@jacebenson/jsn 4.3.7-dev.37 → 4.3.7-dev.39
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/package.json +1 -1
- package/src/commands/actions.js +21 -4
- package/src/commands/flows.js +23 -4
- package/src/flow-create.js +9 -3
- package/src/flow-designer-interactive.js +2 -2
- package/src/helpers.js +15 -0
package/package.json
CHANGED
package/src/commands/actions.js
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import { buildDevCmd } from './_generic.js';
|
|
2
|
-
import { parseDataArg } from '../helpers.js';
|
|
2
|
+
import { formatCommandList, parseDataArg } from '../helpers.js';
|
|
3
3
|
import { resolveRecord, unwrapSysId } from '../resolve-record.js';
|
|
4
4
|
import { declareCapabilities } from '../capabilities.js';
|
|
5
5
|
import { ACTION_TABLE, actionScope } from '../processflow-actions.js';
|
|
6
6
|
import { errUsage } from '../errors.js';
|
|
7
7
|
import { cancelled, pickDesignerRecord, designerScope, guidedActionCreate, guidedActionEdit, guidedActionTestInputs, interactiveDesigner, hasDefinitionData, confirmDesignerMutation } from '../flow-designer-interactive.js';
|
|
8
8
|
|
|
9
|
+
const ACTION_COMMANDS = [
|
|
10
|
+
{ name: 'list', description: 'List actions' },
|
|
11
|
+
{ name: 'show [identifier]', description: 'Show an action by name or sys_id' },
|
|
12
|
+
{ name: 'definition [identifier]', description: 'Read the full JSON definition including executable step_instances' },
|
|
13
|
+
{ name: 'step-types', description: 'Read step schema templates for a target scope' },
|
|
14
|
+
{ name: 'create', description: 'Create an action: guided in a terminal, full JSON definition in scripts' },
|
|
15
|
+
{ name: 'update [identifier]', description: 'Save a full definition through Process Flow (alias: edit)' },
|
|
16
|
+
{ name: 'test [identifier]', description: 'Execute an action and optionally wait for actual outputs' },
|
|
17
|
+
{ name: 'delete [identifier]', description: 'Delete an action parent explicitly' },
|
|
18
|
+
];
|
|
19
|
+
|
|
9
20
|
const scopeOption = y => y.option('scope', { type: 'string', describe: 'Exact transaction scope sys_id; inferred from existing action when omitted' });
|
|
10
21
|
const dataOptions = y => y
|
|
11
22
|
.option('data-file', { type: 'string', describe: 'Full action definition JSON file, not table fields' })
|
|
@@ -131,9 +142,15 @@ export const actionsCmd = wrap => {
|
|
|
131
142
|
}),
|
|
132
143
|
}),
|
|
133
144
|
handler: wrap(async (_argv, app) => {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
145
|
+
const summary = 'Manage Flow Designer actions from the sys_hub_action_type_definition table. Create and update guide terminal users; automation passes full JSON definitions, not table fields.';
|
|
146
|
+
app.ok({
|
|
147
|
+
commands: ACTION_COMMANDS.map(command => command.name),
|
|
148
|
+
_formatted: formatCommandList({
|
|
149
|
+
title: summary,
|
|
150
|
+
commands: ACTION_COMMANDS,
|
|
151
|
+
footer: 'Run "jsn actions <command> --help" for details. In a terminal you can omit the target and pick one.',
|
|
152
|
+
}),
|
|
153
|
+
}, { summary });
|
|
137
154
|
}),
|
|
138
155
|
};
|
|
139
156
|
};
|
package/src/commands/flows.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import { formatRecordForDisplay, getStringField, interactiveList } from '../helpers.js';
|
|
2
|
+
import { formatRecordForDisplay, formatCommandList, getStringField, interactiveList } from '../helpers.js';
|
|
3
3
|
import { discoverFlowContextFields, normalizeFlowContext, summarizeFlowContexts, formatFlowContextSummary, aggregateFlowContextMappings, mergeFlowContextStats, buildFlowContextQuery } from '../flow-context.js';
|
|
4
4
|
import { declareCapabilities } from '../capabilities.js';
|
|
5
5
|
import { inspectFlow } from '../flow-inspection.js';
|
|
@@ -12,6 +12,19 @@ import { cancelled, pickDesignerRecord, guidedFlowCreate, guidedFlowEdit, guided
|
|
|
12
12
|
|
|
13
13
|
const pickFlow = (argv, app, query = '') => pickDesignerRecord(argv, app, argv.action ? 'sys_hub_action_type_definition' : 'sys_hub_flow', argv.action ? 'action' : 'flow', query);
|
|
14
14
|
|
|
15
|
+
const FLOW_COMMANDS = [
|
|
16
|
+
{ name: 'list', description: 'List flows' },
|
|
17
|
+
{ name: 'executions', description: 'Show flow executions from sys_flow_context' },
|
|
18
|
+
{ name: 'show [identifier]', description: 'Show a flow: structure, inputs, steps and conditions' },
|
|
19
|
+
{ name: 'status [identifier]', description: 'Check whether a flow is actually able to run' },
|
|
20
|
+
{ name: 'publish [identifier]', description: 'Publish (activate) a flow, or a custom action with --action' },
|
|
21
|
+
{ name: 'test [identifier]', description: 'Execute a record-triggered flow against one record' },
|
|
22
|
+
{ name: 'create', description: 'Create a draft flow: guided in a terminal, JSON manifest in scripts' },
|
|
23
|
+
{ name: 'update [identifier]', description: 'Update a draft flow (alias: edit)' },
|
|
24
|
+
{ name: 'doctor', description: 'Check whether this instance can publish flows at all' },
|
|
25
|
+
{ name: 'delete [identifier]', description: 'Delete a flow (not implemented: use the Flow Designer UI)' },
|
|
26
|
+
];
|
|
27
|
+
|
|
15
28
|
function flowInspectionAdapter(app) {
|
|
16
29
|
return {
|
|
17
30
|
inspectFlow: app.sdk.inspectFlow.bind(app.sdk),
|
|
@@ -336,9 +349,15 @@ export function flowsCmd(wrap) {
|
|
|
336
349
|
});
|
|
337
350
|
},
|
|
338
351
|
handler: wrap(async (_argv, app) => {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
352
|
+
const summary = 'Manage Flow Designer flows from the sys_hub_flow table. Flow structure comes from the ProcessFlow API, so V1, V2 and subflow definitions all render in full.';
|
|
353
|
+
app.ok({
|
|
354
|
+
commands: FLOW_COMMANDS.map(command => command.name),
|
|
355
|
+
_formatted: formatCommandList({
|
|
356
|
+
title: summary,
|
|
357
|
+
commands: FLOW_COMMANDS,
|
|
358
|
+
footer: 'Run "jsn flows <command> --help" for details. In a terminal you can omit the target and pick one; scripts use explicit identifiers and manifests.',
|
|
359
|
+
}),
|
|
360
|
+
}, { summary });
|
|
342
361
|
}),
|
|
343
362
|
};
|
|
344
363
|
}
|
package/src/flow-create.js
CHANGED
|
@@ -230,14 +230,20 @@ export async function readActionDefinition(sdk, instance, actionTypeId, scope, {
|
|
|
230
230
|
return { definition, schema };
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
function buildTypedInputs(action, schema) {
|
|
233
|
+
export function buildTypedInputs(action, schema) {
|
|
234
234
|
const supplied = action.inputs || {};
|
|
235
|
-
const allowed = new Set(schema.map(field => field
|
|
235
|
+
const allowed = new Set(schema.map(field => field?.name).filter(Boolean));
|
|
236
236
|
for (const key of Object.keys(supplied)) if (!allowed.has(key)) throw new Error(`Unsupported input "${key}" for action ${action.type}`);
|
|
237
237
|
return schema.map(field => {
|
|
238
|
-
|
|
238
|
+
// The instance's own definition is the contract: identity is required,
|
|
239
|
+
// everything else (including an optional `parameter` block) is echoed back
|
|
240
|
+
// untouched. Demanding a key the provider omits breaks real actions.
|
|
241
|
+
if (!field || typeof field !== 'object' || !field.id || !field.name) {
|
|
239
242
|
throw new Error(`Action ${action.type} returned an incomplete input schema; refusing to invent input metadata for "${field?.name || 'unknown'}"`);
|
|
240
243
|
}
|
|
244
|
+
if (field.parameter !== undefined && (typeof field.parameter !== 'object' || field.parameter === null || Array.isArray(field.parameter))) {
|
|
245
|
+
throw new Error(`Action ${action.type} input "${field.name}" has a malformed parameter block; refusing to change it`);
|
|
246
|
+
}
|
|
241
247
|
const suppliedValue = Object.prototype.hasOwnProperty.call(supplied, field.name) ? supplied[field.name] : field.default;
|
|
242
248
|
if ((suppliedValue === undefined || suppliedValue === null) && (field.mandatory === true || field.required === true)) throw new Error(`Missing required input "${field.name}" for action ${action.type}`);
|
|
243
249
|
const value = suppliedValue ?? null;
|
|
@@ -265,8 +265,8 @@ export async function guidedFlowCreate(argv, app) {
|
|
|
265
265
|
const { schema } = await readActionDefinition(app.sdk, app.getEffectiveInstance(), id, manifest.scope, { requireTypes: true });
|
|
266
266
|
const inputs = {};
|
|
267
267
|
for (const field of schema) {
|
|
268
|
-
if (!field.id || !field.
|
|
269
|
-
throw errUsage(`Published action input ${field.name} lacks provider
|
|
268
|
+
if (!field.id || !field.name) {
|
|
269
|
+
throw errUsage(`Published action input ${field.name || 'unknown'} lacks the provider identity needed to bind a value; no flow was allocated`);
|
|
270
270
|
}
|
|
271
271
|
inputs[field.name] = await promptSchemaValue(app, field, field.default, 'Action input: ');
|
|
272
272
|
}
|
package/src/helpers.js
CHANGED
|
@@ -32,6 +32,21 @@ export function canPrompt() {
|
|
|
32
32
|
return isTTY(process.stdout) && isTTY(process.stdin);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Render a parent command's subcommand list for its default handler.
|
|
37
|
+
*
|
|
38
|
+
* Returned through the `_formatted` side channel so a terminal prints the list
|
|
39
|
+
* while `--json`/`--quiet` keep the structured envelope. A parent command that
|
|
40
|
+
* only sets a summary leaves terminal users with no way to discover children.
|
|
41
|
+
*/
|
|
42
|
+
export function formatCommandList({ title, commands, footer }) {
|
|
43
|
+
const width = Math.max(...commands.map(command => command.name.length));
|
|
44
|
+
const lines = [title, '', 'Available subcommands:'];
|
|
45
|
+
for (const command of commands) lines.push(` ${command.name.padEnd(width)} ${command.description}`);
|
|
46
|
+
if (footer) lines.push('', footer);
|
|
47
|
+
return `${lines.join('\n')}\n`;
|
|
48
|
+
}
|
|
49
|
+
|
|
35
50
|
/**
|
|
36
51
|
* Confirm a destructive action before executing.
|
|
37
52
|
*
|