@silkweave/cli 3.0.0 → 3.1.0
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 -2
- package/build/index.d.mts.map +1 -1
- package/build/index.mjs +9 -11
- package/build/index.mjs.map +1 -1
- package/package.json +2 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @silkweave/cli
|
|
2
2
|
|
|
3
|
-
CLI adapter for [Silkweave](https://github.com/silkweave/silkweave) - turn your actions into a complete command-line application with help text, option parsing, and
|
|
3
|
+
CLI adapter for [Silkweave](https://github.com/silkweave/silkweave) - turn your actions into a complete command-line application with help text, option parsing, and plain `console` output.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -63,7 +63,7 @@ $ mytool deploy production --dry-run
|
|
|
63
63
|
|
|
64
64
|
## Streaming Actions
|
|
65
65
|
|
|
66
|
-
Actions defined with a `chunk` schema and an `async function*` `run` (see [`@silkweave/core`](https://www.npmjs.com/package/@silkweave/core)) stream output as **NDJSON on stdout** - one JSON-encoded chunk per line
|
|
66
|
+
Actions defined with a `chunk` schema and an `async function*` `run` (see [`@silkweave/core`](https://www.npmjs.com/package/@silkweave/core)) stream output as **NDJSON on stdout** - one JSON-encoded chunk per line, so the output is pipe-friendly.
|
|
67
67
|
|
|
68
68
|
```bash
|
|
69
69
|
$ mytool generate-messages --topic weather --count 3
|
package/build/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/adapter/cli.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/adapter/cli.ts"],"mappings":";;;cA6Fa,GAAA,EAAK,cAAA"}
|
package/build/index.mjs
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { SilkweaveError, isStreamingAction, unwrap } from "@silkweave/core";
|
|
3
|
-
import { createCLILogger } from "@silkweave/logger";
|
|
1
|
+
import { SilkweaveError, createConsoleLogger, isStreamingAction, unwrap } from "@silkweave/core";
|
|
4
2
|
import { camelCase, kebabCase } from "change-case";
|
|
5
3
|
import { Command } from "commander";
|
|
6
4
|
import { once } from "events";
|
|
7
5
|
import z from "zod/v4";
|
|
8
6
|
//#region src/adapter/cli.ts
|
|
9
7
|
function handleCLIError(error) {
|
|
10
|
-
if (error instanceof SilkweaveError)
|
|
8
|
+
if (error instanceof SilkweaveError) console.error(`[${error.code}] ${error.message}`);
|
|
11
9
|
else if (error instanceof z.ZodError) {
|
|
12
|
-
|
|
13
|
-
for (const issue of error.issues)
|
|
14
|
-
} else if (error instanceof Error)
|
|
15
|
-
else if (typeof error === "string")
|
|
16
|
-
else
|
|
10
|
+
console.error("Validation Error");
|
|
11
|
+
for (const issue of error.issues) console.error(`${issue.path}: ${issue.message}`);
|
|
12
|
+
} else if (error instanceof Error) console.error(error.message);
|
|
13
|
+
else if (typeof error === "string") console.error(error);
|
|
14
|
+
else console.error(JSON.stringify(error));
|
|
17
15
|
process.exitCode = 1;
|
|
18
16
|
}
|
|
19
17
|
function parseCLIInput(action, args) {
|
|
@@ -59,7 +57,7 @@ function registerCommand(program, action, options, context) {
|
|
|
59
57
|
addCliOption(command, key, type, defaultValue, action.args?.includes(key) ?? false);
|
|
60
58
|
}
|
|
61
59
|
command.action((...args) => {
|
|
62
|
-
const logger =
|
|
60
|
+
const logger = createConsoleLogger();
|
|
63
61
|
const input = parseCLIInput(action, args);
|
|
64
62
|
const actionContext = context.fork({
|
|
65
63
|
logger,
|
|
@@ -69,7 +67,7 @@ function registerCommand(program, action, options, context) {
|
|
|
69
67
|
runStreamingCommand(action, input, actionContext).catch(handleCLIError);
|
|
70
68
|
return;
|
|
71
69
|
}
|
|
72
|
-
|
|
70
|
+
console.info(`${options.name} - ${action.name}`);
|
|
73
71
|
const runFn = action.run;
|
|
74
72
|
runFn(input, actionContext).then((result) => {
|
|
75
73
|
logger.info(JSON.stringify(result, null, 2));
|
package/build/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/adapter/cli.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/adapter/cli.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { Action, ActionRun, ActionStreamRun, AdapterFactory, createConsoleLogger, isStreamingAction, SilkweaveContext, SilkweaveError, SilkweaveOptions, unwrap } from '@silkweave/core'\nimport { camelCase, kebabCase } from 'change-case'\nimport { Command } from 'commander'\nimport { once } from 'events'\nimport z from 'zod/v4'\n\nfunction handleCLIError(error: unknown) {\n if (error instanceof SilkweaveError) {\n console.error(`[${error.code}] ${error.message}`)\n } else if (error instanceof z.ZodError) {\n console.error('Validation Error')\n for (const issue of error.issues) {\n console.error(`${issue.path}: ${issue.message}`)\n }\n } else if (error instanceof Error) {\n console.error(error.message)\n } else if (typeof error === 'string') {\n console.error(error)\n } else {\n console.error(JSON.stringify(error))\n }\n process.exitCode = 1\n}\n\nfunction parseCLIInput(action: Action, args: any[]) {\n const tmpArgs = args.slice(0, -1)\n const rawInput = tmpArgs.pop()\n action.args?.forEach((k, index) => { rawInput[k] = args[index] })\n const { error, data } = action.input.safeParse(rawInput)\n if (error || !data) {\n handleCLIError(error)\n process.exit()\n }\n\n return data\n}\n\nfunction addCliOption(command: Command, key: string, type: z.ZodType, defaultValue: any, isArgument: boolean) {\n const description = type.description\n if (isArgument) {\n command.argument(`[${camelCase(key)}]`, description, defaultValue)\n return\n }\n const flag = kebabCase(key)\n if (type instanceof z.ZodBoolean) {\n command.option(`--${flag}`, description, defaultValue)\n command.option(`--no-${flag}`)\n } else if (type instanceof z.ZodNumber) {\n command.option(`--${flag} <number>`, description, defaultValue)\n } else if (type instanceof z.ZodString || type instanceof z.ZodEnum) {\n command.option(`--${flag} <string>`, description, defaultValue)\n } else if (type instanceof z.ZodObject || type instanceof z.ZodRecord || type instanceof z.ZodArray) {\n command.option(`--${flag} <json>`, description ?? '', JSON.parse, defaultValue)\n } else {\n throw new Error(`Invalid zod type: ${type.def.type}`)\n }\n}\n\nasync function runStreamingCommand(action: Action, input: object, context: SilkweaveContext) {\n const streamRun = action.run as ActionStreamRun<object, unknown>\n const iter = streamRun(input, context)\n for await (const chunk of iter) {\n const line = JSON.stringify(chunk) + '\\n'\n if (!process.stdout.write(line)) {\n await once(process.stdout, 'drain')\n }\n }\n}\n\nfunction registerCommand(program: Command, action: Action, options: SilkweaveOptions, context: SilkweaveContext) {\n const command = program.command(kebabCase(action.name)).description(action.description)\n const shape = action.input.shape\n for (const key of Object.keys(shape)) {\n const [type, { defaultValue }] = unwrap(shape[key])\n addCliOption(command, key, type, defaultValue, action.args?.includes(key) ?? false)\n }\n command.action((...args) => {\n const logger = createConsoleLogger()\n const input = parseCLIInput(action, args)\n const actionContext = context.fork({ logger, command })\n if (isStreamingAction(action)) {\n runStreamingCommand(action, input, actionContext).catch(handleCLIError)\n return\n }\n console.info(`${options.name} - ${action.name}`)\n const runFn = action.run as ActionRun<object, object>\n runFn(input, actionContext).then((result) => {\n logger.info(JSON.stringify(result, null, 2))\n }).catch(handleCLIError)\n })\n}\n\nexport const cli: AdapterFactory = () => {\n return (options, baseContext) => {\n const context = baseContext.fork({ adapter: 'cli' })\n const program = new Command()\n .name(options.name)\n .description(options.description)\n .version(options.version)\n\n return {\n context,\n start: async (actions) => {\n for (const action of actions) {\n registerCommand(program, action, options, context)\n }\n program.parse()\n },\n stop: async () => { }\n }\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@silkweave/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Silkweave CLI Adapter",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://www.silkweave.dev",
|
|
@@ -26,12 +26,10 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@clack/prompts": "^1.0.1",
|
|
30
29
|
"change-case": "^5.4.4",
|
|
31
30
|
"commander": "^13.1.0",
|
|
32
31
|
"zod": "^3.25.0",
|
|
33
|
-
"@silkweave/
|
|
34
|
-
"@silkweave/core": "3.0.0"
|
|
32
|
+
"@silkweave/core": "3.1.0"
|
|
35
33
|
},
|
|
36
34
|
"devDependencies": {
|
|
37
35
|
"@eslint/js": "^10.0.1",
|