@deepseek-ai/dsh-cmdline 0.0.1-rc.1 → 0.0.1-rc.3
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.i18n.yaml +2 -2
- package/README.md +5 -6
- package/README.zh.md +5 -6
- package/lib/index.js +46 -35
- package/lib/types/index.d.ts +16 -35
- package/package.json +4 -4
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/boot/cmdline/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 33125014539e801dbd2952a3b4513cafc80bdcee
|
|
6
|
+
README.zh.md: 7ef49a1027d3c17817c9171e1166ed6feecd8559
|
package/README.md
CHANGED
|
@@ -15,15 +15,16 @@ An embedding host with no command line provides an empty list; that is the hones
|
|
|
15
15
|
|
|
16
16
|
## Ordinary providers and injected config
|
|
17
17
|
|
|
18
|
-
Any app plugin may inject `cmdlineArgs`, parse it, and publish an ordinary app-owned service. `parseCmdline(ctx, program
|
|
18
|
+
Any app plugin may inject `cmdlineArgs`, parse it, and publish an ordinary app-owned service. `parseCmdline(ctx, program)` is only a commander adapter; the program's own action owns validation and the published service:
|
|
19
19
|
|
|
20
20
|
```ts ignore
|
|
21
21
|
export const name = 'web-startup'
|
|
22
22
|
export const inject = ['cmdlineArgs']
|
|
23
23
|
|
|
24
24
|
export function apply(ctx: Context): void {
|
|
25
|
-
const
|
|
26
|
-
|
|
25
|
+
const program = webCommand()
|
|
26
|
+
program.action(() => ctx.provide('webStartup', webValuesFrom(program)))
|
|
27
|
+
parseCmdline(ctx, program)
|
|
27
28
|
}
|
|
28
29
|
```
|
|
29
30
|
|
|
@@ -45,14 +46,12 @@ Every row configured from those values uses ordinary service injection and direc
|
|
|
45
46
|
port: !!js ctx.webStartup.port ?? 3080
|
|
46
47
|
```
|
|
47
48
|
|
|
48
|
-
`parseCmdline` parses the immutable arguments
|
|
49
|
+
`parseCmdline` refuses at load a program in which no command declares an action, routes every command's exit and output through the launcher (commander copies those settings into subcommands only at registration), and parses the immutable arguments; commander runs the invoked command's synchronous action on success. An action rejects an invalid invocation with `program.error(...)` — before publishing, since statements ahead of the rejection have already run. On `--help`, `--version`, a parse error, or that rejection, the helper writes commander's text and requests exit; the provider publishes nothing, so dependent rows never activate.
|
|
49
50
|
|
|
50
51
|
### How injection orders config
|
|
51
52
|
|
|
52
53
|
Loader defers a row's `!!js` interpolation until that row's declared injections are active, then evaluates against the row's plugin context. The example above can therefore read `ctx.webStartup` directly: Cordis has already populated that injected service before Loader asks for `webserver`'s config. Include trees preserve nested expression nodes until each target row reaches this point. Provider replacement and live patch reload repeat interpolation against the current injected services, so a launch flag cannot be silently reset.
|
|
53
54
|
|
|
54
|
-
`enableRow(ctx, id)` turns on a row a bundle ships disabled because only some invocations want it (`dsh web --dev` and its client-plugin reload chain). The activation is an in-memory override: it does not rewrite the row's configured `disabled` value and survives config reapplication for that mounted entry. Loader applies the enabled row's ordinary injection ordering.
|
|
55
|
-
|
|
56
55
|
### Shared immutable arguments
|
|
57
56
|
|
|
58
57
|
`get()` does not consume or mutate argv. Multiple plugins can parse the same snapshot and independently provide services. The launcher does not inspect the composition for a command-line owner; a profile with no reader simply ignores its app arguments.
|
package/README.zh.md
CHANGED
|
@@ -15,15 +15,16 @@ dsh 启动器交给它所引导应用的那条命令行。启动器只解析属
|
|
|
15
15
|
|
|
16
16
|
## 普通提供方与注入配置
|
|
17
17
|
|
|
18
|
-
任何应用插件都可以注入 `cmdlineArgs`、解析它,再发布一个普通的应用自有服务。`parseCmdline(ctx, program
|
|
18
|
+
任何应用插件都可以注入 `cmdlineArgs`、解析它,再发布一个普通的应用自有服务。`parseCmdline(ctx, program)` 只适配 commander;校验与发布的服务都归 program 自己的 action 持有:
|
|
19
19
|
|
|
20
20
|
```ts ignore
|
|
21
21
|
export const name = 'web-startup'
|
|
22
22
|
export const inject = ['cmdlineArgs']
|
|
23
23
|
|
|
24
24
|
export function apply(ctx: Context): void {
|
|
25
|
-
const
|
|
26
|
-
|
|
25
|
+
const program = webCommand()
|
|
26
|
+
program.action(() => ctx.provide('webStartup', webValuesFrom(program)))
|
|
27
|
+
parseCmdline(ctx, program)
|
|
27
28
|
}
|
|
28
29
|
```
|
|
29
30
|
|
|
@@ -45,14 +46,12 @@ export function apply(ctx: Context): void {
|
|
|
45
46
|
port: !!js ctx.webStartup.port ?? 3080
|
|
46
47
|
```
|
|
47
48
|
|
|
48
|
-
`parseCmdline`
|
|
49
|
+
`parseCmdline` 在加载时拒绝整棵命令树中没有任何命令声明 action 的 program,把每个命令的退出与输出都接到启动器上(commander 只在注册时把这些设置复制进子命令),再解析不可变参数;解析成功时 commander 运行被调用命令的同步 action。action 用 `program.error(...)` 拒绝无效调用——必须先拒绝后发布,因为写在拒绝之前的语句已经执行。遇到 `--help`、`--version`、解析错误或这种拒绝时,该适配器输出 commander 文本并请求退出;提供方什么也不发布,因此依赖行不会激活。
|
|
49
50
|
|
|
50
51
|
### 注入如何排列配置求值
|
|
51
52
|
|
|
52
53
|
Loader 会把一行的 `!!js` 插值推迟到该行声明的注入全部激活之后,再基于该行的插件上下文求值。所以上例可以直接读取 `ctx.webStartup`:Loader 索取 `webserver` 的配置之前,Cordis 已经填入了这个注入服务。Include 树会保留嵌套表达式节点,直到各个目标行到达这一时点。提供方替换与活动 patch 重载都会针对当前注入服务重新插值,因此启动 flag 不会被悄悄重置。
|
|
53
54
|
|
|
54
|
-
`enableRow(ctx, id)` 打开某个组合包以禁用状态交付、只有部分调用才需要的行(`dsh web --dev` 及其客户端插件重载链路)。该激活是内存中的覆盖:它不会改写行所配置的 `disabled` 值,并会在已挂载条目的配置重新应用后继续生效。Loader 会对启用后的行应用普通的注入顺序。
|
|
55
|
-
|
|
56
55
|
### 共享不可变参数
|
|
57
56
|
|
|
58
57
|
`get()` 不会消费或修改 argv。多个插件可以解析同一份快照,并分别提供服务。启动器不会检查组合中的命令行所有者;没有读取方的 profile 只会忽略自己的应用参数。
|
package/lib/index.js
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* text, and its parse errors instead of the launcher knowing them.
|
|
10
10
|
*
|
|
11
11
|
* Any app plugin can inject `cmdlineArgs` and call {@link parseCmdline}. A
|
|
12
|
-
* provider may publish the parsed values as its own service
|
|
12
|
+
* provider may publish the parsed values as its own service from its program's
|
|
13
|
+
* commander action, and ordinary rows
|
|
13
14
|
* can inject that service and read it from lazily resolved config —
|
|
14
15
|
* `port: !!js ctx.webStartup.port ?? 3080` — so a flag beats the value written
|
|
15
16
|
* beside it. No row has launcher-level command-line status.
|
|
@@ -34,55 +35,65 @@ const internals = {
|
|
|
34
35
|
};
|
|
35
36
|
/**
|
|
36
37
|
* Parse the launcher's immutable argument snapshot with an app's commander
|
|
37
|
-
* program.
|
|
38
|
-
*
|
|
38
|
+
* program. Commander runs the program's own synchronous action handler on a
|
|
39
|
+
* successful parse; app code there publishes its service and rejects an
|
|
40
|
+
* invalid invocation with `program.error(...)`. This helper has no Loader-row
|
|
41
|
+
* or service ownership semantics.
|
|
39
42
|
*
|
|
40
|
-
* Help, version, and rejected arguments
|
|
41
|
-
*
|
|
42
|
-
* `
|
|
43
|
+
* Help, version, and rejected arguments — from the grammar or from an action
|
|
44
|
+
* — are terminal for the process: commander writes the text and the helper
|
|
45
|
+
* requests `ctx.appExit`. The action never runs on help, version, or a
|
|
46
|
+
* grammar rejection; an action must reject before it publishes, because
|
|
47
|
+
* statements before its `program.error(...)` have already run.
|
|
43
48
|
* @param ctx - plugin context carrying `cmdlineArgs` and `appExit`.
|
|
44
|
-
* @param program - the app's commander program, with its flags
|
|
45
|
-
*
|
|
46
|
-
* @
|
|
47
|
-
*
|
|
49
|
+
* @param program - the app's commander program, with its flags, description,
|
|
50
|
+
* actions, and any subcommands already declared.
|
|
51
|
+
* @throws when the launcher did not provide the command line and exit request,
|
|
52
|
+
* or when no command in the program declares an action.
|
|
48
53
|
*/
|
|
49
|
-
function parseCmdline(ctx, program
|
|
54
|
+
function parseCmdline(ctx, program) {
|
|
50
55
|
const args = ctx.get("cmdlineArgs");
|
|
51
56
|
const exit = ctx.get("appExit");
|
|
52
57
|
if (args === void 0 || exit === void 0) throw new Error(`${program.name()}: the launcher must provide ctx.cmdlineArgs and ctx.appExit before the tree mounts`);
|
|
53
|
-
program.
|
|
54
|
-
|
|
55
|
-
writeErr: (text) => void internals.stderr.write(text)
|
|
56
|
-
});
|
|
58
|
+
if (!hasAction(program)) throw new Error(`${program.name()}: no command in the program declares an action; parseCmdline runs the invoked command's action on a successful parse, and app code there publishes its service`);
|
|
59
|
+
configureExitAndOutput(program);
|
|
57
60
|
try {
|
|
58
61
|
program.parse(args.get(), { from: "user" });
|
|
59
|
-
return plan(program, ctx);
|
|
60
62
|
} catch (error) {
|
|
61
63
|
if (!isCommanderError(error)) throw error;
|
|
62
64
|
exit(error.exitCode);
|
|
63
|
-
return;
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
67
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
68
|
+
* Whether any command in the tree declares an action handler.
|
|
69
|
+
*
|
|
70
|
+
* The `Command` type cannot express the action precondition, so the handler is
|
|
71
|
+
* read structurally (as {@link isCommanderError} reads commander's control-flow
|
|
72
|
+
* errors): without this guard, a program that forgot its action would parse
|
|
73
|
+
* successfully, publish nothing, and surface only as dependent rows pending on
|
|
74
|
+
* the absent service.
|
|
75
|
+
* @param command - the command whose tree is inspected.
|
|
76
|
+
* @returns true when the command or any registered subcommand has an action.
|
|
77
|
+
*/
|
|
78
|
+
function hasAction(command) {
|
|
79
|
+
if (typeof command._actionHandler === "function") return true;
|
|
80
|
+
return command.commands.some(hasAction);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Route every command's exit and output through the launcher adapter.
|
|
69
84
|
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* @param ctx - plugin context whose Loader tree carries the row.
|
|
76
|
-
* @param id - the row id.
|
|
77
|
-
* @returns nothing once the row has started or is waiting for its dependencies.
|
|
78
|
-
* @throws when the Loader or named row is absent.
|
|
85
|
+
* Commander copies `exitOverride` and output configuration into a subcommand
|
|
86
|
+
* only at registration, so a root-only override would let an
|
|
87
|
+
* already-registered subcommand's rejection write to the process streams and
|
|
88
|
+
* call `process.exit` directly, bypassing `ctx.appExit`.
|
|
89
|
+
* @param command - the root of the command tree to configure.
|
|
79
90
|
*/
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
91
|
+
function configureExitAndOutput(command) {
|
|
92
|
+
command.exitOverride().configureOutput({
|
|
93
|
+
writeOut: (text) => void internals.stdout.write(text),
|
|
94
|
+
writeErr: (text) => void internals.stderr.write(text)
|
|
95
|
+
});
|
|
96
|
+
for (const child of command.commands) configureExitAndOutput(child);
|
|
86
97
|
}
|
|
87
98
|
/**
|
|
88
99
|
* Whether a thrown value is commander's own control-flow error (help, version,
|
|
@@ -101,4 +112,4 @@ function isCommanderError(error) {
|
|
|
101
112
|
return typeof candidate.code === "string" && candidate.code.startsWith("commander.") && typeof candidate.exitCode === "number";
|
|
102
113
|
}
|
|
103
114
|
//#endregion
|
|
104
|
-
export {
|
|
115
|
+
export { internals, parseCmdline, provideCmdline };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* text, and its parse errors instead of the launcher knowing them.
|
|
9
9
|
*
|
|
10
10
|
* Any app plugin can inject `cmdlineArgs` and call {@link parseCmdline}. A
|
|
11
|
-
* provider may publish the parsed values as its own service
|
|
11
|
+
* provider may publish the parsed values as its own service from its program's
|
|
12
|
+
* commander action, and ordinary rows
|
|
12
13
|
* can inject that service and read it from lazily resolved config —
|
|
13
14
|
* `port: !!js ctx.webStartup.port ?? 3080` — so a flag beats the value written
|
|
14
15
|
* beside it. No row has launcher-level command-line status.
|
|
@@ -68,43 +69,23 @@ export declare const internals: {
|
|
|
68
69
|
write(chunk: string): unknown;
|
|
69
70
|
};
|
|
70
71
|
};
|
|
71
|
-
/**
|
|
72
|
-
* Resolve parsed arguments into an app-owned value. Call
|
|
73
|
-
* `program.error(...)` to reject the invocation with a usage message instead
|
|
74
|
-
* of throwing.
|
|
75
|
-
* @param program - the parsed commander program.
|
|
76
|
-
* @param ctx - the plugin context that received the command line.
|
|
77
|
-
* @returns the value an ordinary provider plugin may publish.
|
|
78
|
-
*/
|
|
79
|
-
export type CmdlinePlan<T = unknown> = (program: Command, ctx: Context) => T;
|
|
80
72
|
/**
|
|
81
73
|
* Parse the launcher's immutable argument snapshot with an app's commander
|
|
82
|
-
* program.
|
|
83
|
-
*
|
|
74
|
+
* program. Commander runs the program's own synchronous action handler on a
|
|
75
|
+
* successful parse; app code there publishes its service and rejects an
|
|
76
|
+
* invalid invocation with `program.error(...)`. This helper has no Loader-row
|
|
77
|
+
* or service ownership semantics.
|
|
84
78
|
*
|
|
85
|
-
* Help, version, and rejected arguments
|
|
86
|
-
*
|
|
87
|
-
* `
|
|
79
|
+
* Help, version, and rejected arguments — from the grammar or from an action
|
|
80
|
+
* — are terminal for the process: commander writes the text and the helper
|
|
81
|
+
* requests `ctx.appExit`. The action never runs on help, version, or a
|
|
82
|
+
* grammar rejection; an action must reject before it publishes, because
|
|
83
|
+
* statements before its `program.error(...)` have already run.
|
|
88
84
|
* @param ctx - plugin context carrying `cmdlineArgs` and `appExit`.
|
|
89
|
-
* @param program - the app's commander program, with its flags
|
|
90
|
-
*
|
|
91
|
-
* @
|
|
92
|
-
*
|
|
93
|
-
*/
|
|
94
|
-
export declare function parseCmdline<T>(ctx: Context, program: Command, plan?: CmdlinePlan<T>): T | undefined;
|
|
95
|
-
/**
|
|
96
|
-
* Turn on a row this composition ships disabled, because this invocation asked
|
|
97
|
-
* for it (`dsh web --dev` and its client-plugin reload chain).
|
|
98
|
-
*
|
|
99
|
-
* A row cannot be inserted from inside a mounting plugin — the Loader returns a
|
|
100
|
-
* prefixed id it then fails to resolve — so a conditional row ships disabled
|
|
101
|
-
* and a row mounted beside it enables it after startup resolves the invocation.
|
|
102
|
-
* The Loader keeps that activation in memory, separate from serialized options,
|
|
103
|
-
* so reapplying the composition cannot restore the invocation's row to disabled.
|
|
104
|
-
* @param ctx - plugin context whose Loader tree carries the row.
|
|
105
|
-
* @param id - the row id.
|
|
106
|
-
* @returns nothing once the row has started or is waiting for its dependencies.
|
|
107
|
-
* @throws when the Loader or named row is absent.
|
|
85
|
+
* @param program - the app's commander program, with its flags, description,
|
|
86
|
+
* actions, and any subcommands already declared.
|
|
87
|
+
* @throws when the launcher did not provide the command line and exit request,
|
|
88
|
+
* or when no command in the program declares an action.
|
|
108
89
|
*/
|
|
109
|
-
export declare function
|
|
90
|
+
export declare function parseCmdline(ctx: Context, program: Command): void;
|
|
110
91
|
//# sourceMappingURL=index.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-cmdline",
|
|
3
3
|
"description": "Immutable command-line handoff from a dsh launcher to any app plugin that injects cmdlineArgs",
|
|
4
|
-
"version": "0.0.1-rc.
|
|
4
|
+
"version": "0.0.1-rc.3",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "restricted"
|
|
7
7
|
},
|
|
@@ -32,15 +32,15 @@
|
|
|
32
32
|
],
|
|
33
33
|
"license": "BSD-3-Clause",
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@deepseek-ai/
|
|
35
|
+
"@deepseek-ai/cordis-plugin-loader": "^1.0.1-rc.1",
|
|
36
36
|
"@deepseek-ai/cordis": "^4.0.1-rc.1",
|
|
37
|
-
"@deepseek-ai/
|
|
37
|
+
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.3"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"commander": "^15.0.0",
|
|
41
41
|
"@deepseek-ai/cordis-plugin-include": "^1.0.5-rc.1",
|
|
42
42
|
"@deepseek-ai/cordis-plugin-loader": "^1.0.1-rc.1",
|
|
43
|
-
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.
|
|
43
|
+
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.3",
|
|
44
44
|
"@deepseek-ai/cordis": "^4.0.1-rc.1"
|
|
45
45
|
}
|
|
46
46
|
}
|