@synthigy/sdk 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -3
- package/codegen/codegen.mjs +80 -19
- package/codegen/pull.mjs +7 -1
- package/package.json +9 -1
- package/src/index.d.ts +27 -0
- package/src/index.js +49 -4
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ for await (const ev of w.events) {
|
|
|
66
66
|
IAM / RBAC / row-level security enforced *server-side*. Tokens never have to
|
|
67
67
|
reach the browser. → [AUTH.md](./docs/AUTH.md)
|
|
68
68
|
|
|
69
|
-
- **Typed from your model.** `synthigy-gen` compiles your ERD + `.xsql` files
|
|
69
|
+
- **Typed from your model.** `synthigy-gen` (needs `typescript` in your project) compiles your ERD + `.xsql` files
|
|
70
70
|
into typed methods whose result types follow the selection — a typo'd entity
|
|
71
71
|
or an unselected field is a compile error. → [codegen](./docs/WATCH.md#codegen)
|
|
72
72
|
|
|
@@ -79,8 +79,7 @@ for await (const ev of w.events) {
|
|
|
79
79
|
| [WATCH.md](./docs/WATCH.md) | `watch` / `watchQuery` / `watchSqlTemplate` / `observe`, lifecycle, and codegen |
|
|
80
80
|
| [AUTH.md](./docs/AUTH.md) | OAuth client registration, `actingAs`, BFF / SPA / native patterns |
|
|
81
81
|
| [CHANGELOG.md](./CHANGELOG.md) | Version history |
|
|
82
|
-
| [examples
|
|
83
|
-
| [examples/movies-live.mjs](./examples/movies-live.mjs) | Minimal live-watch demo |
|
|
82
|
+
| [synthigy/examples: movies/js](https://github.com/synthigy/examples/tree/main/movies/js) | End-to-end Datastar BFF against the published package |
|
|
84
83
|
| [src/index.d.ts](./src/index.d.ts) | Full type definitions |
|
|
85
84
|
|
|
86
85
|
## Tests
|
package/codegen/codegen.mjs
CHANGED
|
@@ -10,8 +10,21 @@ import fs from 'node:fs'
|
|
|
10
10
|
import path from 'node:path'
|
|
11
11
|
import { createHash } from 'node:crypto'
|
|
12
12
|
import { execFileSync } from 'node:child_process'
|
|
13
|
-
import
|
|
13
|
+
import { createRequire } from 'node:module'
|
|
14
14
|
import { TS, tsScalar, pascal, camel } from './lib.mjs'
|
|
15
|
+
import { PLATFORM_AUDIENCE } from '../src/index.js'
|
|
16
|
+
|
|
17
|
+
// typescript is an optional peer: the runtime client has no dependencies and
|
|
18
|
+
// must stay that way, but generating .ts files needs the compiler — resolved
|
|
19
|
+
// from the consumer's project, where a TypeScript codebase already has it.
|
|
20
|
+
let ts
|
|
21
|
+
try {
|
|
22
|
+
ts = createRequire(import.meta.url)('typescript')
|
|
23
|
+
} catch {
|
|
24
|
+
console.error('synthigy-gen: `typescript` is required to generate code and was not found.\n' +
|
|
25
|
+
' npm install -D typescript')
|
|
26
|
+
process.exit(1)
|
|
27
|
+
}
|
|
15
28
|
|
|
16
29
|
const here = path.dirname(new URL(import.meta.url).pathname)
|
|
17
30
|
|
|
@@ -44,6 +57,7 @@ Environment:
|
|
|
44
57
|
SYNTHIGY_ENDPOINT server URL (default: http://localhost:7887)
|
|
45
58
|
SYNTHIGY_CLIENT_ID OAuth client ID
|
|
46
59
|
SYNTHIGY_CLIENT_SECRET OAuth client secret
|
|
60
|
+
SYNTHIGY_AUDIENCE client_credentials audience, when the server requires one
|
|
47
61
|
|
|
48
62
|
Examples:
|
|
49
63
|
node codegen.mjs movies.xsql src/generated/ first run auto-pulls schema
|
|
@@ -124,7 +138,7 @@ const toKey = flags.keys === 'camel' ? camel : s => s
|
|
|
124
138
|
|
|
125
139
|
// ── describe ─────────────────────────────────────────────────────────────────
|
|
126
140
|
const ENDPOINT = process.env.SYNTHIGY_ENDPOINT ?? 'http://localhost:7887'
|
|
127
|
-
const { SYNTHIGY_CLIENT_ID, SYNTHIGY_CLIENT_SECRET } = process.env
|
|
141
|
+
const { SYNTHIGY_CLIENT_ID, SYNTHIGY_CLIENT_SECRET, SYNTHIGY_AUDIENCE } = process.env
|
|
128
142
|
|
|
129
143
|
// Auto-pull schema if missing or --pull requested (saved next to .xsql, cached for future runs).
|
|
130
144
|
if (!flags.schemaOverride && (flags.pull || !fs.existsSync(schemaPath))) {
|
|
@@ -144,7 +158,11 @@ async function token() {
|
|
|
144
158
|
method: 'POST',
|
|
145
159
|
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
146
160
|
body: new URLSearchParams({ grant_type: 'client_credentials',
|
|
147
|
-
client_id: SYNTHIGY_CLIENT_ID, client_secret: SYNTHIGY_CLIENT_SECRET
|
|
161
|
+
client_id: SYNTHIGY_CLIENT_ID, client_secret: SYNTHIGY_CLIENT_SECRET,
|
|
162
|
+
// describe is a platform-API call like any other, so it mints for the
|
|
163
|
+
// platform audience. Hand-rolled here rather than going through the
|
|
164
|
+
// client, so the default has to be named explicitly.
|
|
165
|
+
audience: SYNTHIGY_AUDIENCE || PLATFORM_AUDIENCE }),
|
|
148
166
|
})
|
|
149
167
|
if (!r.ok) throw new Error(`token ${r.status}: ${await r.text()}`)
|
|
150
168
|
return (await r.json()).access_token
|
|
@@ -194,7 +212,15 @@ if (cached && cached.sourceHash === sourceHash) {
|
|
|
194
212
|
if (!resp.ok) throw new Error(`describe ${resp.status}: ${await resp.text()}`)
|
|
195
213
|
const body = await resp.json()
|
|
196
214
|
const r0 = (body.results ?? body.result ?? [body.data ?? body])[0] ?? body
|
|
215
|
+
// A describe that fails answers 200 with {ok:false, error} in the result.
|
|
216
|
+
// Reading .operations off that yields "not iterable" and throws the
|
|
217
|
+
// server's diagnostic away — which is the only thing that says WHICH
|
|
218
|
+
// attribute the templates got wrong.
|
|
219
|
+
const err = r0?.error ?? (r0?.ok === false ? { message: 'describe failed' } : null)
|
|
220
|
+
if (err) throw new Error(err.message ?? JSON.stringify(err))
|
|
197
221
|
ir = r0.result ?? r0.data ?? r0
|
|
222
|
+
if (!Array.isArray(ir?.operations))
|
|
223
|
+
throw new Error(`describe returned no operations: ${JSON.stringify(ir).slice(0, 200)}`)
|
|
198
224
|
} catch (e) {
|
|
199
225
|
console.error(cached
|
|
200
226
|
? `sources changed since IR pull and describe failed (${e.message}) — start a backend (SYNTHIGY_ENDPOINT) or revert the .xsql edit`
|
|
@@ -239,7 +265,13 @@ fs.writeFileSync(irPath, JSON.stringify(ir, null, 2) + '\n')
|
|
|
239
265
|
// Identity (namespace / name), @watch, and sql-template @returns results all come
|
|
240
266
|
// from the IR now — the canonical XSQL parser owns them. No XSQL re-parsing here.
|
|
241
267
|
const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf8'))
|
|
242
|
-
|
|
268
|
+
// Installed from npm -> import the package by name; a relative path out of
|
|
269
|
+
// node_modules is correct only for one install layout. Inside this repo the
|
|
270
|
+
// relative path is still what works, since there is no package to resolve.
|
|
271
|
+
const sdkRoot = path.join(here, '..')
|
|
272
|
+
const sdkSrc = sdkRoot.includes(`${path.sep}node_modules${path.sep}`)
|
|
273
|
+
? '@synthigy/sdk'
|
|
274
|
+
: path.relative(outDir, path.join(sdkRoot, 'src')) + '/index.js'
|
|
243
275
|
const ent = (n) => schema.entities[n] ?? {}
|
|
244
276
|
const visited = new Set()
|
|
245
277
|
|
|
@@ -329,7 +361,14 @@ for (const n of allEntities) nsOf(entityPascal(n))
|
|
|
329
361
|
// never emitted from XSQL. Skip LOUDLY, never silently.
|
|
330
362
|
const MUTATE_VERBS = new Set(['sync', 'stack', 'delete'])
|
|
331
363
|
for (const op of ir.operations) {
|
|
332
|
-
if (op.batch)
|
|
364
|
+
if (op.batch) {
|
|
365
|
+
// The Python and PHP generators emit a batch function; this one does not
|
|
366
|
+
// yet. Say so — the author declared an operation and would otherwise get
|
|
367
|
+
// nothing back with no diagnostic.
|
|
368
|
+
console.warn(`skipped @batch ${op.name} — not generated by the JS codegen yet; ` +
|
|
369
|
+
`call the members individually, or exec([op(...), op(...)]) for one round trip`)
|
|
370
|
+
continue
|
|
371
|
+
}
|
|
333
372
|
if (MUTATE_VERBS.has(op.op)) {
|
|
334
373
|
console.warn(`skipped @${op.op} ${op.name} — mutations are generated from the schema; use ${entityPascal(op.entity ?? '<Entity>')}.${op.op}(data)`)
|
|
335
374
|
continue
|
|
@@ -478,20 +517,42 @@ fs.writeFileSync(path.join(outDir, 'ops.ts'), OPS_HDR_COMMENT + formatTs(OPS_
|
|
|
478
517
|
// type-check — never ship broken/stale output silently (the old emit-and-swallow
|
|
479
518
|
// shipped a stale ops.js once). No .js emitted: consumers import the .ts source
|
|
480
519
|
// (Node 23+ type-stripping / a bundler); the type-only `./schema.js` import erases
|
|
481
|
-
// at runtime.
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
path.join(
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
520
|
+
// at runtime.
|
|
521
|
+
// Locate tsc through the SAME resolution that found the `typescript` module
|
|
522
|
+
// above, so a hoisted install — the normal consumer layout — is found. A path
|
|
523
|
+
// built from `here` only exists when typescript is nested under this package.
|
|
524
|
+
const tscBin = (() => {
|
|
525
|
+
try {
|
|
526
|
+
const lib = createRequire(import.meta.url).resolve('typescript')
|
|
527
|
+
const bin = path.join(path.dirname(lib), '..', 'bin', 'tsc')
|
|
528
|
+
if (fs.existsSync(bin)) return bin
|
|
529
|
+
} catch {}
|
|
530
|
+
for (const c of [path.join(here, '..', 'node_modules', '.bin', 'tsc'),
|
|
531
|
+
path.join(process.cwd(), 'node_modules', '.bin', 'tsc')]) {
|
|
532
|
+
if (fs.existsSync(c)) return c
|
|
533
|
+
}
|
|
534
|
+
return null
|
|
535
|
+
})()
|
|
536
|
+
|
|
537
|
+
// `--ignoreConfig` needs TypeScript 6. On 5.x the flag is itself an error, and
|
|
538
|
+
// naming files explicitly already makes tsc skip tsconfig.json, so it is left off.
|
|
539
|
+
const tscMajor = Number.parseInt(ts.version ?? '0', 10) || 0
|
|
540
|
+
if (tscBin) {
|
|
541
|
+
try {
|
|
542
|
+
execFileSync(tscBin, [
|
|
543
|
+
...(tscMajor >= 6 ? ['--ignoreConfig'] : []),
|
|
544
|
+
'--module', 'nodenext', '--moduleResolution', 'nodenext',
|
|
545
|
+
'--target', 'es2022', '--strict', '--skipLibCheck', '--noEmit',
|
|
546
|
+
path.join(outDir, 'ops.ts'),
|
|
547
|
+
path.join(outDir, 'schema.ts'),
|
|
548
|
+
], { stdio: 'pipe' })
|
|
549
|
+
} catch (e) {
|
|
550
|
+
process.stderr.write('codegen: generated TS failed to type-check (not shipped):\n')
|
|
551
|
+
process.stderr.write((e.stdout ?? e.stderr ?? '').toString())
|
|
552
|
+
process.exit(1)
|
|
553
|
+
}
|
|
554
|
+
} else {
|
|
555
|
+
process.stderr.write('codegen: tsc not found — skipping the type-check gate.\n')
|
|
495
556
|
}
|
|
496
557
|
const flagSummary = [flags.keys !== 'snake' && `keys=${flags.keys}`, !flags.writes && 'no-writes'].filter(Boolean).join(' ')
|
|
497
558
|
const opCount = ir.operations.filter(o => !o.batch).length
|
package/codegen/pull.mjs
CHANGED
|
@@ -26,11 +26,17 @@ if (!endpoint) {
|
|
|
26
26
|
process.exit(1)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const { SYNTHIGY_TOKEN, SYNTHIGY_CLIENT_ID, SYNTHIGY_CLIENT_SECRET
|
|
29
|
+
const { SYNTHIGY_TOKEN, SYNTHIGY_CLIENT_ID, SYNTHIGY_CLIENT_SECRET,
|
|
30
|
+
SYNTHIGY_AUDIENCE } = process.env
|
|
30
31
|
const config = { endpoint }
|
|
31
32
|
if (SYNTHIGY_CLIENT_ID && SYNTHIGY_CLIENT_SECRET) {
|
|
32
33
|
config.clientId = SYNTHIGY_CLIENT_ID
|
|
33
34
|
config.clientSecret = SYNTHIGY_CLIENT_SECRET
|
|
35
|
+
// A server can require an explicit client_credentials audience for /data and
|
|
36
|
+
// /schema. Without it the mint still succeeds and the token is then refused,
|
|
37
|
+
// so the symptom is a 401 on schema rather than anything about auth config.
|
|
38
|
+
// A static SYNTHIGY_TOKEN already has its audience baked in.
|
|
39
|
+
if (SYNTHIGY_AUDIENCE) config.audience = SYNTHIGY_AUDIENCE
|
|
34
40
|
} else {
|
|
35
41
|
config.token = SYNTHIGY_TOKEN ?? '' // '' = authless (bare server)
|
|
36
42
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synthigy/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Zero-dependency client for Synthigy's /data endpoint",
|
|
5
5
|
"author": "Robert Geršak",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,6 +50,14 @@
|
|
|
50
50
|
"realtime",
|
|
51
51
|
"xsql"
|
|
52
52
|
],
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"typescript": ">=5"
|
|
55
|
+
},
|
|
56
|
+
"peerDependenciesMeta": {
|
|
57
|
+
"typescript": {
|
|
58
|
+
"optional": true
|
|
59
|
+
}
|
|
60
|
+
},
|
|
53
61
|
"devDependencies": {
|
|
54
62
|
"typescript": "^6.0.3"
|
|
55
63
|
},
|
package/src/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/** The platform API this SDK is a client of; the default audience for every mint. */
|
|
2
|
+
export const PLATFORM_AUDIENCE: "https://synthigy.com"
|
|
3
|
+
|
|
1
4
|
// ============================================================================
|
|
2
5
|
// Selection
|
|
3
6
|
// ============================================================================
|
|
@@ -79,6 +82,13 @@ export interface TreeExecOpts extends ExecOpts {
|
|
|
79
82
|
childrenKey?: string
|
|
80
83
|
}
|
|
81
84
|
|
|
85
|
+
/** What `deploy()` acks with — `dataset` is the xid `destroy()` takes. */
|
|
86
|
+
export interface DeployAck {
|
|
87
|
+
deployed: boolean
|
|
88
|
+
version: string
|
|
89
|
+
dataset: string
|
|
90
|
+
}
|
|
91
|
+
|
|
82
92
|
export type OperationResult<T = unknown> =
|
|
83
93
|
| { ok: true; data: T }
|
|
84
94
|
| { ok: false; error: { message: string; code: string } }
|
|
@@ -608,6 +618,19 @@ export class SynthigyClient {
|
|
|
608
618
|
*/
|
|
609
619
|
deployedModel(opts?: ExecOpts): Promise<Record<string, unknown>>
|
|
610
620
|
|
|
621
|
+
/**
|
|
622
|
+
* Deploy a dataset version from a modeler export — pass the export file's
|
|
623
|
+
* contents verbatim, the server decodes it. Requires `dataset:deploy`.
|
|
624
|
+
* The ack carries the dataset xid `destroy()` takes.
|
|
625
|
+
*/
|
|
626
|
+
deploy(exportContents: string, opts?: ExecOpts): Promise<DeployAck>
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Destroy a dataset — every version, table and row. Requires
|
|
630
|
+
* `dataset:delete`. Idempotent.
|
|
631
|
+
*/
|
|
632
|
+
destroy(datasetXid: string, opts?: ExecOpts): Promise<boolean>
|
|
633
|
+
|
|
611
634
|
/**
|
|
612
635
|
* Fetch the runtime (enhanced) ERD model via `op: "runtime-model"` —
|
|
613
636
|
* the model as the running system actually emits it, with audit
|
|
@@ -1014,6 +1037,8 @@ export const op: {
|
|
|
1014
1037
|
sqlTemplate(template: string, params?: Record<string, unknown> | unknown[], opts?: { cached?: boolean }): Operation
|
|
1015
1038
|
deployedModel(): Operation
|
|
1016
1039
|
runtimeModel(): Operation
|
|
1040
|
+
deploy(exportContents: string): Operation
|
|
1041
|
+
destroy(datasetXid: string): Operation
|
|
1017
1042
|
}
|
|
1018
1043
|
|
|
1019
1044
|
// ============================================================================
|
|
@@ -1087,6 +1112,8 @@ export { _delete as delete }
|
|
|
1087
1112
|
|
|
1088
1113
|
export const schema: SynthigyClient['schema']
|
|
1089
1114
|
export const lint: SynthigyClient['lint']
|
|
1115
|
+
export const deploy: SynthigyClient['deploy']
|
|
1116
|
+
export const destroy: SynthigyClient['destroy']
|
|
1090
1117
|
export const deployedModel: SynthigyClient['deployedModel']
|
|
1091
1118
|
export const runtimeModel: SynthigyClient['runtimeModel']
|
|
1092
1119
|
export const token: SynthigyClient['token']
|
package/src/index.js
CHANGED
|
@@ -733,6 +733,15 @@ const RETRYABLE_CATEGORIES = new Set(['network', 'rate_limit', 'internal'])
|
|
|
733
733
|
* - .requestId— request ID for cross-correlation with server logs
|
|
734
734
|
* - .status — HTTP status code (for transport-level errors)
|
|
735
735
|
*/
|
|
736
|
+
/**
|
|
737
|
+
* The platform API this SDK is a client of. `/data`, `/schema`, `/history`,
|
|
738
|
+
* `/logs` and subscriptions all require a token bound to it. It identifies the
|
|
739
|
+
* API, never a deployment, so it is the same string on localhost and in
|
|
740
|
+
* production — which is exactly why it is a constant here rather than
|
|
741
|
+
* something every caller configures.
|
|
742
|
+
*/
|
|
743
|
+
export const PLATFORM_AUDIENCE = 'https://synthigy.com'
|
|
744
|
+
|
|
736
745
|
export class SynthigyError extends Error {
|
|
737
746
|
constructor(message, code, details, extras) {
|
|
738
747
|
super(message)
|
|
@@ -870,12 +879,16 @@ class SynthigyClient {
|
|
|
870
879
|
// [sub, client_id] isn't torn down between watches. Replaces the
|
|
871
880
|
// earlier "dummy keepalive watch" workaround.
|
|
872
881
|
this._keepAlive = config.keepAlive === true
|
|
873
|
-
//
|
|
874
|
-
//
|
|
875
|
-
//
|
|
882
|
+
// A client_credentials mint naming no audience resolves to the
|
|
883
|
+
// identity-only OIDC audience, which /data rejects. This SDK is the client
|
|
884
|
+
// for the platform API, so PLATFORM_AUDIENCE is what it asks for — there
|
|
885
|
+
// is nothing for a caller to configure, and nowhere to look the value up
|
|
886
|
+
// if there were: the server does not advertise it in discovery. Minting a
|
|
887
|
+
// token for some OTHER API is a per-call argument on token(), not a
|
|
888
|
+
// property of the client. The env var stays only as an escape hatch.
|
|
876
889
|
this._defaultAudience = config.audience
|
|
877
890
|
?? (typeof process !== 'undefined' ? process.env?.SYNTHIGY_AUDIENCE : undefined)
|
|
878
|
-
??
|
|
891
|
+
?? PLATFORM_AUDIENCE
|
|
879
892
|
|
|
880
893
|
if (config.token !== undefined && config.token !== null) {
|
|
881
894
|
// Static token mode — empty string allowed for unauth / dev servers.
|
|
@@ -1863,6 +1876,34 @@ class SynthigyClient {
|
|
|
1863
1876
|
return result.data
|
|
1864
1877
|
}
|
|
1865
1878
|
|
|
1879
|
+
/**
|
|
1880
|
+
* Deploy a dataset version from a modeler export. Pass the export file's
|
|
1881
|
+
* contents verbatim — the server decodes it. Requires `dataset:deploy`.
|
|
1882
|
+
*
|
|
1883
|
+
* @param {string} exportContents - Contents of a `<Dataset>@<version>.json` export
|
|
1884
|
+
* @param {Object} [opts] - Options ({ actingAs })
|
|
1885
|
+
* @returns {Promise<{deployed: boolean, version: string, dataset: string}>}
|
|
1886
|
+
*/
|
|
1887
|
+
async deploy(exportContents, opts) {
|
|
1888
|
+
const [result] = await this.exec([{ op: 'deploy', data: exportContents }], opts)
|
|
1889
|
+
if (!result.ok) throw _errorFromServer(result.error, undefined, result._requestId)
|
|
1890
|
+
return result.data
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
/**
|
|
1894
|
+
* Destroy a dataset: every version, every table, every row. Requires
|
|
1895
|
+
* `dataset:delete`. Idempotent — a dataset that is already gone is not an error.
|
|
1896
|
+
*
|
|
1897
|
+
* @param {string} datasetXid - The dataset xid (`deploy()` returns it)
|
|
1898
|
+
* @param {Object} [opts] - Options ({ actingAs })
|
|
1899
|
+
* @returns {Promise<boolean>}
|
|
1900
|
+
*/
|
|
1901
|
+
async destroy(datasetXid, opts) {
|
|
1902
|
+
const [result] = await this.exec([{ op: 'delete', entity: 'dataset', data: { xid: datasetXid } }], opts)
|
|
1903
|
+
if (!result.ok) throw _errorFromServer(result.error, undefined, result._requestId)
|
|
1904
|
+
return result.data
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1866
1907
|
/**
|
|
1867
1908
|
* Fetch the runtime ERD model — the deployed model augmented with:
|
|
1868
1909
|
* - `xid` / `euuid` identity attrs on every entity
|
|
@@ -2387,6 +2428,8 @@ export const op = {
|
|
|
2387
2428
|
sqlTemplate: (template, params) => ({ op: 'sql-template', template, params: params || [] }),
|
|
2388
2429
|
deployedModel: () => ({ op: 'deployed-model' }),
|
|
2389
2430
|
runtimeModel: () => ({ op: 'runtime-model' }),
|
|
2431
|
+
deploy: (exportContents) => ({ op: 'deploy', data: exportContents }),
|
|
2432
|
+
destroy: (datasetXid) => ({ op: 'delete', entity: 'dataset', data: { xid: datasetXid } }),
|
|
2390
2433
|
}
|
|
2391
2434
|
|
|
2392
2435
|
// ============================================================================
|
|
@@ -2512,6 +2555,8 @@ export const schema = (...a) => _dflt().schema(...a)
|
|
|
2512
2555
|
export const lint = (...a) => _dflt().lint(...a)
|
|
2513
2556
|
export const onboard = (...a) => _dflt().onboard(...a)
|
|
2514
2557
|
export const onboardComplete = (...a) => _dflt().onboardComplete(...a)
|
|
2558
|
+
export const deploy = (...a) => _dflt().deploy(...a)
|
|
2559
|
+
export const destroy = (...a) => _dflt().destroy(...a)
|
|
2515
2560
|
export const deployedModel = (...a) => _dflt().deployedModel(...a)
|
|
2516
2561
|
export const runtimeModel = (...a) => _dflt().runtimeModel(...a)
|
|
2517
2562
|
export const token = (...a) => _dflt().token(...a)
|