feat(cli): support --dependencies for script actions
- action add/update: new --dependencies <json> option - parseDependencies accepts JSON, name@version shorthand, or bare names - update is incremental; --dependencies replaces the whole array - docs: deployment/systemd.md + skill SKILL/action-types/development document the npm-deps feature and the service-PATH requirement (spawn npm ENOENT without nvm bin dir on PATH)
This commit is contained in:
Vendored
+54
-2
@@ -349,6 +349,7 @@ function actionCommand() {
|
||||
.option('--code <js>', 'Script JS code (script)')
|
||||
.option('--code-file <path>', 'Read script code from a file (script)')
|
||||
.option('--timeout <ms>', 'Script timeout ms (script, default 60000)')
|
||||
.option('--dependencies <json>', 'npm packages JSON array for script, e.g. \'[{"name":"axios","version":"1.6.0"}]\' (script)')
|
||||
.option('--to <email>', 'Recipient (sendEmail)')
|
||||
.option('--subject <s>', 'Subject (sendEmail)')
|
||||
.option('--body <html>', 'HTML body (sendEmail)')
|
||||
@@ -410,6 +411,8 @@ function actionCommand() {
|
||||
.option('--config <json>', 'Full replacement config JSON')
|
||||
.option('--code <js>', 'Script JS code (script)')
|
||||
.option('--code-file <path>', 'Read script code from a file (script)')
|
||||
.option('--timeout <ms>', 'Script timeout ms (script)')
|
||||
.option('--dependencies <json>', 'npm packages JSON array for script, e.g. \'[{"name":"axios","version":"1.6.0"}]\' (script; replaces existing deps)')
|
||||
.option('--name <n>', 'New node display name')
|
||||
.option('--base-id <id>', 'Base id (overrides default)')
|
||||
.action((0, ctx_1.run)(async (ctx, args, o) => {
|
||||
@@ -425,8 +428,17 @@ function actionCommand() {
|
||||
let config = node.config || {};
|
||||
if (opts.config)
|
||||
config = JSON.parse(opts.config);
|
||||
else if (opts.code !== undefined || opts['code-file'] !== undefined) {
|
||||
config = { ...config, code: opts['code-file'] ? readFile(opts['code-file']) : opts.code };
|
||||
else {
|
||||
// Granular update: merge only the flags the user actually passed.
|
||||
config = { ...config };
|
||||
if (opts.code !== undefined || opts['code-file'] !== undefined) {
|
||||
config.code = opts['code-file'] ? readFile(opts['code-file']) : opts.code;
|
||||
}
|
||||
if (opts.timeout !== undefined)
|
||||
config.timeout = Number(opts.timeout);
|
||||
if (opts.dependencies !== undefined) {
|
||||
config.dependencies = parseDependencies(opts.dependencies);
|
||||
}
|
||||
}
|
||||
nodes[idx] = { ...node, config, name: opts.name ?? node.name };
|
||||
const updated = await ctx.client.replaceNodes(baseId, workflowId, {
|
||||
@@ -463,6 +475,44 @@ function readFile(p) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
return require('node:fs').readFileSync(p, 'utf8');
|
||||
}
|
||||
/**
|
||||
* Parse `--dependencies` into the ScriptDependency[] shape the backend expects.
|
||||
* Accepts:
|
||||
* - full JSON: '[{"name":"axios","version":"1.6.0"}]'
|
||||
* - name list: 'axios,lodash' (version defaults to 'latest')
|
||||
* - name@ver: 'axios@1.6.0,lodash@4.17.21'
|
||||
* - empty '[]' or '' to clear deps
|
||||
*/
|
||||
function parseDependencies(raw) {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed || trimmed === '[]')
|
||||
return [];
|
||||
// JSON form
|
||||
if (trimmed[0] === '[') {
|
||||
const parsed = JSON.parse(trimmed);
|
||||
if (!Array.isArray(parsed))
|
||||
throw new Error('--dependencies JSON must be an array');
|
||||
return parsed.map((d) => {
|
||||
if (typeof d === 'string')
|
||||
return { name: d };
|
||||
if (d && typeof d === 'object' && typeof d.name === 'string') {
|
||||
return { name: d.name, ...(d.version ? { version: String(d.version) } : {}) };
|
||||
}
|
||||
throw new Error('--dependencies entries must be strings or {name,version?} objects');
|
||||
});
|
||||
}
|
||||
// Comma list form: axios@1.6.0,lodash
|
||||
return trimmed
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean)
|
||||
.map((spec) => {
|
||||
const at = spec.lastIndexOf('@');
|
||||
if (at > 0)
|
||||
return { name: spec.slice(0, at), version: spec.slice(at + 1) };
|
||||
return { name: spec };
|
||||
});
|
||||
}
|
||||
/** Build action config from granular flags. */
|
||||
function buildActionConfig(opts) {
|
||||
const type = opts.type;
|
||||
@@ -479,6 +529,8 @@ function buildActionConfig(opts) {
|
||||
config.code = opts.code;
|
||||
if (opts.timeout)
|
||||
config.timeout = Number(opts.timeout);
|
||||
if (opts.dependencies)
|
||||
config.dependencies = parseDependencies(opts.dependencies);
|
||||
break;
|
||||
}
|
||||
case 'sendEmail': {
|
||||
|
||||
Reference in New Issue
Block a user