@ductape/cli 0.3.20 → 0.3.21
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.
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type ComponentActionKind = 'graph' | 'vector';
|
|
2
|
+
export type ComponentActionVerb = 'create' | 'update' | 'get' | 'list' | 'delete' | 'execute';
|
|
3
|
+
export declare function runComponentActions(kind: ComponentActionKind, verb: ComponentActionVerb, opts: {
|
|
4
|
+
resource?: string;
|
|
5
|
+
action?: string;
|
|
6
|
+
file?: string;
|
|
7
|
+
json?: boolean;
|
|
8
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { readJsonBody } from '../lib/read-body.js';
|
|
2
|
+
import { getSdkProxy, requireSession } from '../lib/proxy/context.js';
|
|
3
|
+
import { printJson } from '../lib/output.js';
|
|
4
|
+
export async function runComponentActions(kind, verb, opts) {
|
|
5
|
+
const session = requireSession();
|
|
6
|
+
const body = readJsonBody(opts.file) ?? {};
|
|
7
|
+
const resourceKey = kind === 'graph' ? 'graph' : 'vector';
|
|
8
|
+
const resource = opts.resource ?? String(body[resourceKey] ?? body[`${resourceKey}Tag`] ?? '');
|
|
9
|
+
const action = opts.action ?? String(body.actionTag ?? body.action ?? '');
|
|
10
|
+
const base = { product: session.project.product_tag, ...body };
|
|
11
|
+
let method;
|
|
12
|
+
let params;
|
|
13
|
+
if (verb === 'create') {
|
|
14
|
+
if (!opts.file)
|
|
15
|
+
throw new Error(`${kind} actions create requires --action-file <file.json>`);
|
|
16
|
+
method = kind === 'graph' ? 'action.create' : 'actions.create';
|
|
17
|
+
params = [base];
|
|
18
|
+
}
|
|
19
|
+
else if (verb === 'update') {
|
|
20
|
+
if (!opts.file)
|
|
21
|
+
throw new Error(`${kind} actions update requires --action-file <file.json>`);
|
|
22
|
+
method = kind === 'graph' ? 'action.update' : 'actions.update';
|
|
23
|
+
params = [base];
|
|
24
|
+
}
|
|
25
|
+
else if (verb === 'list') {
|
|
26
|
+
if (!resource)
|
|
27
|
+
throw new Error(`${kind} actions list requires --${kind} <tag>`);
|
|
28
|
+
method = kind === 'graph' ? 'action.fetchAll' : 'actions.fetchAll';
|
|
29
|
+
params = [{ product: session.project.product_tag, [resourceKey]: resource }];
|
|
30
|
+
}
|
|
31
|
+
else if (verb === 'get' || verb === 'delete') {
|
|
32
|
+
if (!resource || !action)
|
|
33
|
+
throw new Error(`${kind} actions ${verb} requires <action> --${kind} <tag>`);
|
|
34
|
+
method = kind === 'graph' ? `action.${verb === 'get' ? 'fetch' : 'delete'}` : `actions.${verb === 'get' ? 'fetch' : 'delete'}`;
|
|
35
|
+
params = [{ product: session.project.product_tag, [resourceKey]: resource, actionTag: action }];
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
if (!opts.file)
|
|
39
|
+
throw new Error(`${kind} actions execute requires --action-file <file.json>`);
|
|
40
|
+
method = kind === 'graph' ? 'action.execute' : 'actions.execute';
|
|
41
|
+
params = [{ product: session.project.product_tag, env: session.project.env_slug, ...body }];
|
|
42
|
+
}
|
|
43
|
+
const result = await getSdkProxy(session).execute(kind, method, params);
|
|
44
|
+
printJson(result, Boolean(opts.json));
|
|
45
|
+
}
|
package/dist/commands/db.d.ts
CHANGED
|
@@ -4,11 +4,10 @@ export declare function runDb(method: string, opts: {
|
|
|
4
4
|
}): Promise<void>;
|
|
5
5
|
/**
|
|
6
6
|
* Database Actions — reusable, parameterized query/mutation definitions saved against a
|
|
7
|
-
* database component (databases.action.* in the SDK).
|
|
8
|
-
* (uses the access-key-backed sdk-proxy, same as
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* of these, not a raw {table, where} shape.
|
|
7
|
+
* database component (databases.action.* in the SDK). Definition management is
|
|
8
|
+
* administrative metadata (uses the access-key-backed sdk-proxy, same as
|
|
9
|
+
* `resources <type> create`). Runtime execution uses databases.execute with an `action`
|
|
10
|
+
* tag. Direct query/insert/update/delete calls keep their raw {table, where, ...} shape.
|
|
12
11
|
*
|
|
13
12
|
* Tag format is always "product_tag:database_tag:action_tag" — always pass it fully
|
|
14
13
|
* qualified here (the SDK's 2-part fallback only works inside a single long-lived process
|
package/dist/commands/db.js
CHANGED
|
@@ -47,14 +47,13 @@ export async function runDb(method, opts) {
|
|
|
47
47
|
}
|
|
48
48
|
printJson(result, Boolean(opts.json));
|
|
49
49
|
}
|
|
50
|
-
const DB_ACTION_VERBS = ['create', 'update', 'get', 'list', 'delete'];
|
|
50
|
+
const DB_ACTION_VERBS = ['create', 'update', 'get', 'list', 'delete', 'execute', 'dispatch'];
|
|
51
51
|
/**
|
|
52
52
|
* Database Actions — reusable, parameterized query/mutation definitions saved against a
|
|
53
|
-
* database component (databases.action.* in the SDK).
|
|
54
|
-
* (uses the access-key-backed sdk-proxy, same as
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* of these, not a raw {table, where} shape.
|
|
53
|
+
* database component (databases.action.* in the SDK). Definition management is
|
|
54
|
+
* administrative metadata (uses the access-key-backed sdk-proxy, same as
|
|
55
|
+
* `resources <type> create`). Runtime execution uses databases.execute with an `action`
|
|
56
|
+
* tag. Direct query/insert/update/delete calls keep their raw {table, where, ...} shape.
|
|
58
57
|
*
|
|
59
58
|
* Tag format is always "product_tag:database_tag:action_tag" — always pass it fully
|
|
60
59
|
* qualified here (the SDK's 2-part fallback only works inside a single long-lived process
|
|
@@ -109,6 +108,22 @@ export async function runDbActions(verb, opts, extraArgs) {
|
|
|
109
108
|
method = 'action.delete';
|
|
110
109
|
params = [tag];
|
|
111
110
|
break;
|
|
111
|
+
case 'dispatch': {
|
|
112
|
+
const body = readJsonBody(opts.file);
|
|
113
|
+
if (!body || Object.keys(body).length === 0)
|
|
114
|
+
throw new Error('dispatch requires --action-file <file.json>');
|
|
115
|
+
method = 'action.dispatch';
|
|
116
|
+
params = [body];
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
case 'execute': {
|
|
120
|
+
const body = readJsonBody(opts.file);
|
|
121
|
+
if (!body || Object.keys(body).length === 0)
|
|
122
|
+
throw new Error('execute requires --action-file <file.json>');
|
|
123
|
+
method = 'execute';
|
|
124
|
+
params = [body];
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
112
127
|
}
|
|
113
128
|
const result = await proxy.execute('databases', method, params);
|
|
114
129
|
printJson(result, Boolean(opts.json));
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ import { runStart, runStop, runStatus } from './commands/platform.js';
|
|
|
16
16
|
import { runResourceCrud, runResourcesList, runEventTopicCrud, runNotificationMessageCrud } from './commands/resources.js';
|
|
17
17
|
import { runCloud, runCloudPreflight } from './commands/cloud.js';
|
|
18
18
|
import { runDb, runDbActions, runDbContext } from './commands/db.js';
|
|
19
|
+
import { runComponentActions } from './commands/component-actions.js';
|
|
19
20
|
import { runDbMigrate, runDbMigrateStatus, runDbMigrateRollback } from './commands/db-migrate.js';
|
|
20
21
|
import { runFeaturesSync } from './commands/features-sync.js';
|
|
21
22
|
import { runDbSchemaGenerate, runDbSchemaPush } from './commands/db-schema.js';
|
|
@@ -807,23 +808,23 @@ dbMigrate
|
|
|
807
808
|
.action(wrap((opts) => runDbMigrateRollback({ env: opts.env, db: opts.db, n: Number(opts.n) })));
|
|
808
809
|
const dbActions = db
|
|
809
810
|
.command('actions')
|
|
810
|
-
.description('Reusable database action definitions (saved parameterized queries).
|
|
811
|
-
'
|
|
812
|
-
'
|
|
813
|
-
'
|
|
811
|
+
.description('Reusable database action definitions (saved parameterized queries). Execute them with ' +
|
|
812
|
+
'database.execute({ database, action, input }) in Features, databases.execute({ product, ' +
|
|
813
|
+
'env, database, action, input }) in the SDK, or `db actions execute` in the CLI. Direct ' +
|
|
814
|
+
'query/insert/update/delete calls keep their raw table/where/data shape.');
|
|
814
815
|
dbActions
|
|
815
816
|
.command('create')
|
|
816
817
|
.description('Create a database action from a file: { tag: "product:database:action", name, tableName, operation, template }')
|
|
817
|
-
.requiredOption('-
|
|
818
|
+
.requiredOption('--action-file <path>', 'JSON file with the action definition')
|
|
818
819
|
.option('--json', 'JSON output')
|
|
819
|
-
.action(wrap((opts) => runDbActions('create', { file: opts.
|
|
820
|
+
.action(wrap((opts) => runDbActions('create', { file: opts.actionFile, json: opts.json }, [])));
|
|
820
821
|
dbActions
|
|
821
822
|
.command('update')
|
|
822
823
|
.description('Update an existing database action')
|
|
823
824
|
.requiredOption('-t, --tag <tag>', 'Action tag ("product:database:action")')
|
|
824
|
-
.requiredOption('-
|
|
825
|
+
.requiredOption('--action-file <path>', 'JSON file with the fields to change')
|
|
825
826
|
.option('--json', 'JSON output')
|
|
826
|
-
.action(wrap((opts) => runDbActions('update', { tag: opts.tag, file: opts.
|
|
827
|
+
.action(wrap((opts) => runDbActions('update', { tag: opts.tag, file: opts.actionFile, json: opts.json }, [])));
|
|
827
828
|
dbActions
|
|
828
829
|
.command('get')
|
|
829
830
|
.description('Fetch one database action')
|
|
@@ -842,6 +843,18 @@ dbActions
|
|
|
842
843
|
.argument('<tag>', 'Action tag ("product:database:action")')
|
|
843
844
|
.option('--json', 'JSON output')
|
|
844
845
|
.action(wrap((tag, opts) => runDbActions('delete', { tag, json: opts.json }, [])));
|
|
846
|
+
dbActions
|
|
847
|
+
.command('dispatch')
|
|
848
|
+
.description('Dispatch a database action immediately or on a schedule')
|
|
849
|
+
.requiredOption('--action-file <path>', 'JSON body: { product, env, database, action, input, schedule? }')
|
|
850
|
+
.option('--json', 'JSON output')
|
|
851
|
+
.action(wrap((opts) => runDbActions('dispatch', { file: opts.actionFile, json: opts.json }, [])));
|
|
852
|
+
dbActions
|
|
853
|
+
.command('execute')
|
|
854
|
+
.description('Execute a saved database action synchronously')
|
|
855
|
+
.requiredOption('--action-file <path>', 'JSON body: { product, env, database, action, input }')
|
|
856
|
+
.option('--json', 'JSON output')
|
|
857
|
+
.action(wrap((opts) => runDbActions('execute', { file: opts.actionFile, json: opts.json }, [])));
|
|
845
858
|
const dbSchema = db.command('schema').description('Schema management for ductape/database/schema.json');
|
|
846
859
|
dbSchema
|
|
847
860
|
.command('generate')
|
|
@@ -873,11 +886,56 @@ features
|
|
|
873
886
|
.argument('[filter]', 'Optional substring passed through to the project\'s features:sync script')
|
|
874
887
|
.action(wrap((filter) => runFeaturesSync({ filter })));
|
|
875
888
|
const graph = program.command('graph').description('Graph runtime (graph-proxy)');
|
|
889
|
+
const graphActions = graph.command('actions').description('Reusable graph actions');
|
|
890
|
+
for (const verb of ['create', 'update', 'get', 'list', 'delete', 'execute']) {
|
|
891
|
+
const command = graphActions.command(verb);
|
|
892
|
+
if (verb === 'get' || verb === 'delete')
|
|
893
|
+
command.argument('<action>');
|
|
894
|
+
if (verb !== 'create' && verb !== 'update' && verb !== 'execute')
|
|
895
|
+
command.requiredOption('--graph <tag>');
|
|
896
|
+
if (verb === 'create' || verb === 'update' || verb === 'execute')
|
|
897
|
+
command.requiredOption('--action-file <path>');
|
|
898
|
+
command.option('--json').action(wrap((actionOrOpts, maybeOpts) => {
|
|
899
|
+
const hasArgument = verb === 'get' || verb === 'delete';
|
|
900
|
+
const opts = hasArgument ? maybeOpts : actionOrOpts;
|
|
901
|
+
return runComponentActions('graph', verb, {
|
|
902
|
+
action: hasArgument ? actionOrOpts : undefined,
|
|
903
|
+
resource: opts.graph,
|
|
904
|
+
file: opts.actionFile,
|
|
905
|
+
json: opts.json,
|
|
906
|
+
});
|
|
907
|
+
}));
|
|
908
|
+
}
|
|
876
909
|
graph
|
|
877
|
-
.argument('
|
|
910
|
+
.argument('[verb]', 'connect | query | createAction | validateAction | updateAction | …')
|
|
878
911
|
.option('-f, --file <path>')
|
|
879
912
|
.option('--json', 'JSON output')
|
|
880
|
-
.action(wrap((verb, opts) =>
|
|
913
|
+
.action(wrap((verb, opts) => {
|
|
914
|
+
if (!verb)
|
|
915
|
+
throw new Error('Specify a graph verb or use `graph actions --help`');
|
|
916
|
+
return runGraph(verb, { file: opts.file, json: opts.json });
|
|
917
|
+
}));
|
|
918
|
+
const vector = program.command('vector').description('Vector runtime and reusable actions');
|
|
919
|
+
const vectorActions = vector.command('actions').description('Reusable vector actions');
|
|
920
|
+
for (const verb of ['create', 'update', 'get', 'list', 'delete', 'execute']) {
|
|
921
|
+
const command = vectorActions.command(verb);
|
|
922
|
+
if (verb === 'get' || verb === 'delete')
|
|
923
|
+
command.argument('<action>');
|
|
924
|
+
if (verb !== 'create' && verb !== 'update' && verb !== 'execute')
|
|
925
|
+
command.requiredOption('--vector <tag>');
|
|
926
|
+
if (verb === 'create' || verb === 'update' || verb === 'execute')
|
|
927
|
+
command.requiredOption('--action-file <path>');
|
|
928
|
+
command.option('--json').action(wrap((actionOrOpts, maybeOpts) => {
|
|
929
|
+
const hasArgument = verb === 'get' || verb === 'delete';
|
|
930
|
+
const opts = hasArgument ? maybeOpts : actionOrOpts;
|
|
931
|
+
return runComponentActions('vector', verb, {
|
|
932
|
+
action: hasArgument ? actionOrOpts : undefined,
|
|
933
|
+
resource: opts.vector,
|
|
934
|
+
file: opts.actionFile,
|
|
935
|
+
json: opts.json,
|
|
936
|
+
});
|
|
937
|
+
}));
|
|
938
|
+
}
|
|
881
939
|
program
|
|
882
940
|
.command('secrets <verb>')
|
|
883
941
|
.description('Workspace secrets CRUD')
|
package/package.json
CHANGED