@nwire/please 0.7.1 → 0.8.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 +53 -13
- package/dist/__tests__/define-command.test.d.ts +9 -0
- package/dist/__tests__/define-command.test.d.ts.map +1 -0
- package/dist/__tests__/define-command.test.js +93 -0
- package/dist/__tests__/define-command.test.js.map +1 -0
- package/dist/__tests__/run-please.test.d.ts +8 -0
- package/dist/__tests__/run-please.test.d.ts.map +1 -0
- package/dist/__tests__/run-please.test.js +118 -0
- package/dist/__tests__/run-please.test.js.map +1 -0
- package/dist/define-command.d.ts +74 -0
- package/dist/define-command.d.ts.map +1 -0
- package/dist/define-command.js +36 -0
- package/dist/define-command.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/please.d.ts +9 -0
- package/dist/please.d.ts.map +1 -1
- package/dist/please.js +118 -4
- package/dist/please.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,38 +1,78 @@
|
|
|
1
1
|
# @nwire/please
|
|
2
2
|
|
|
3
|
-
> Operator CLI — dispatch any registered action or query from the command line.
|
|
3
|
+
> Operator CLI — dispatch any registered action or query (and operator-script commands) from the command line.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
`runPlease({ apps, commands, argv })` boots every registered app, looks
|
|
6
|
+
up the named target in the supplied `commands` first (operator scripts
|
|
7
|
+
take precedence) then in each app's action/query surface, seeds an
|
|
8
|
+
envelope, dispatches, prints the result. Same handlers as HTTP/queue —
|
|
9
|
+
operator parity guaranteed.
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
pnpm add @nwire/please
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
## Quick
|
|
15
|
+
## Quick example
|
|
16
16
|
|
|
17
17
|
```ts
|
|
18
18
|
#!/usr/bin/env node
|
|
19
|
-
import { runPlease } from "@nwire/please";
|
|
19
|
+
import { runPlease, defineCommand } from "@nwire/please";
|
|
20
|
+
import { z } from "zod";
|
|
20
21
|
import { apps } from "../app/apps";
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
const backfillUsers = defineCommand("backfill-users", {
|
|
24
|
+
describe: "Re-hydrate users from the external source",
|
|
25
|
+
args: z.object({ since: z.string().optional() }),
|
|
26
|
+
handler: async ({ args, ctx }) => {
|
|
27
|
+
const repo = ctx.resolve<UserRepo>("UserRepo");
|
|
28
|
+
return { updated: await repo.backfill(args) };
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const code = await runPlease({
|
|
33
|
+
apps,
|
|
34
|
+
commands: [backfillUsers],
|
|
35
|
+
argv: process.argv.slice(2),
|
|
36
|
+
});
|
|
37
|
+
process.exit(code);
|
|
23
38
|
```
|
|
24
39
|
|
|
25
40
|
```bash
|
|
41
|
+
please backfill-users --since 2026-01-01 # operator script (takes precedence)
|
|
26
42
|
please submissions.flag-for-review --submissionId xyz --confidence 0.4
|
|
27
43
|
please lessons.start-attempt --lessonId hebrew-1 --studentId avi
|
|
28
44
|
please submissions.by-student --studentId avi --status under-review
|
|
29
45
|
please --help
|
|
30
46
|
```
|
|
31
47
|
|
|
32
|
-
##
|
|
48
|
+
## Surface
|
|
49
|
+
|
|
50
|
+
| Export | Role |
|
|
51
|
+
| ------------------------------------------ | ----------------------------------------------------------- |
|
|
52
|
+
| `runPlease({ apps, commands?, argv, … })` | Boot apps, dispatch one target, return exit code (0 / 1). |
|
|
53
|
+
| `defineCommand(name, meta)` | Operator-script primitive. `{ describe?, args?, handler }`. |
|
|
54
|
+
| `CommandDefinition` / `CommandContext` / `CommandHandler` / `CommandMeta` / `CommandArgsSchema` | Types for command authors and consumers. |
|
|
55
|
+
|
|
56
|
+
### Resolution order
|
|
57
|
+
|
|
58
|
+
`runPlease` resolves `argv[0]` in this order:
|
|
59
|
+
|
|
60
|
+
1. `commands[]` — operator scripts shadow domain names on purpose.
|
|
61
|
+
2. Any app's action surface.
|
|
62
|
+
3. Any app's query surface (projection-backed reads).
|
|
63
|
+
|
|
64
|
+
Args parsers are duck-typed — any object with `.parse(input) → output`
|
|
65
|
+
works, so a `z.object({...})` schema is the obvious choice.
|
|
66
|
+
|
|
67
|
+
`defineCommand` captures `$source` so Studio's Commands page can
|
|
68
|
+
render IDE-link chips.
|
|
69
|
+
|
|
70
|
+
## Related
|
|
33
71
|
|
|
34
|
-
- `
|
|
72
|
+
- `@nwire/forge` — supplies the `App` / `AppDefinition` / `HandlerContext` types `runPlease` and `defineCommand` build on.
|
|
73
|
+
- `@nwire/cli` — `nwire please <name>` delegates to this package.
|
|
74
|
+
- `@nwire/scan` — emits `.nwire/commands.json` so Studio + AI surfaces see every operator script.
|
|
35
75
|
|
|
36
|
-
##
|
|
76
|
+
## Status
|
|
37
77
|
|
|
38
|
-
|
|
78
|
+
v0.x — `runPlease` argv contract + `defineCommand` shape are locked. Scaffolders (`make:module`, `make:action`) land on top in a follow-up.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineCommand` — operator-script primitive.
|
|
3
|
+
*
|
|
4
|
+
* Verifies the primitive shape, source capture, optional args, and that
|
|
5
|
+
* commands plumb through `runPlease` to invoke the handler with an injected
|
|
6
|
+
* resolver + app instance.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=define-command.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-command.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/define-command.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineCommand` — operator-script primitive.
|
|
3
|
+
*
|
|
4
|
+
* Verifies the primitive shape, source capture, optional args, and that
|
|
5
|
+
* commands plumb through `runPlease` to invoke the handler with an injected
|
|
6
|
+
* resolver + app instance.
|
|
7
|
+
*/
|
|
8
|
+
import { describe, it, expect } from "vitest";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { defineModule, createApp } from "@nwire/forge";
|
|
11
|
+
import { defineCommand, runPlease } from "../please.js";
|
|
12
|
+
describe("defineCommand", () => {
|
|
13
|
+
it("returns a $kind=command definition with source location", () => {
|
|
14
|
+
const cmd = defineCommand("seed-students", {
|
|
15
|
+
describe: "Seed Dina's starter classroom roster.",
|
|
16
|
+
args: z.object({ count: z.number().int().positive() }),
|
|
17
|
+
handler: async ({ args }) => ({ created: args.count }),
|
|
18
|
+
});
|
|
19
|
+
expect(cmd.$kind).toBe("command");
|
|
20
|
+
expect(cmd.name).toBe("seed-students");
|
|
21
|
+
expect(cmd.describe).toContain("Dina");
|
|
22
|
+
expect(cmd.args).toBeDefined();
|
|
23
|
+
// captureSourceLocation populates $source from the call site. The
|
|
24
|
+
// helper skips nwire-internal frames (including this test file, which
|
|
25
|
+
// lives under packages/nwire-please), so $source resolves to the next
|
|
26
|
+
// user-code frame the V8 stack exposes — what matters is that it ran.
|
|
27
|
+
expect(cmd.$source).toBeDefined();
|
|
28
|
+
expect(typeof cmd.$source?.line).toBe("number");
|
|
29
|
+
});
|
|
30
|
+
it("accepts a command with no args schema (optional field)", () => {
|
|
31
|
+
const cmd = defineCommand("ping", {
|
|
32
|
+
describe: "Smoke-test that the wire is up.",
|
|
33
|
+
handler: async () => ({ ok: true }),
|
|
34
|
+
});
|
|
35
|
+
expect(cmd.args).toBeUndefined();
|
|
36
|
+
expect(cmd.describe).toBe("Smoke-test that the wire is up.");
|
|
37
|
+
});
|
|
38
|
+
it("invokes the handler via runPlease with parsed args + ctx.resolve", async () => {
|
|
39
|
+
let captured = null;
|
|
40
|
+
const emptyModule = defineModule("ops", {});
|
|
41
|
+
const app = createApp({ modules: [emptyModule], appName: "ops-app" });
|
|
42
|
+
app.container.register("Reporter", () => ({ report: () => "reported" }));
|
|
43
|
+
const cmd = defineCommand("backfill-users", {
|
|
44
|
+
describe: "Re-hydrate users.",
|
|
45
|
+
args: z.object({ since: z.string().optional() }),
|
|
46
|
+
handler: async ({ args, ctx }) => {
|
|
47
|
+
captured = {
|
|
48
|
+
args,
|
|
49
|
+
resolved: ctx.resolve("Reporter").report(),
|
|
50
|
+
appKind: ctx.app.$nwireApp,
|
|
51
|
+
};
|
|
52
|
+
return { ok: true };
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
const stdout = [];
|
|
56
|
+
const stderr = [];
|
|
57
|
+
const code = await runPlease({
|
|
58
|
+
apps: [],
|
|
59
|
+
appInstances: [app],
|
|
60
|
+
argv: ["backfill-users", "--since", "2026-01-01"],
|
|
61
|
+
commands: [cmd],
|
|
62
|
+
stdout: (l) => stdout.push(l),
|
|
63
|
+
stderr: (l) => stderr.push(l),
|
|
64
|
+
});
|
|
65
|
+
expect(code).toBe(0);
|
|
66
|
+
expect(stderr).toEqual([]);
|
|
67
|
+
expect(captured).not.toBeNull();
|
|
68
|
+
expect(captured.args).toEqual({ since: "2026-01-01" });
|
|
69
|
+
expect(captured.resolved).toBe("reported");
|
|
70
|
+
expect(captured.appKind).toBe(true);
|
|
71
|
+
expect(stdout.join("\n")).toContain('"ok": true');
|
|
72
|
+
});
|
|
73
|
+
it("surfaces zod validation errors with a non-zero exit code", async () => {
|
|
74
|
+
const emptyModule = defineModule("ops", {});
|
|
75
|
+
const app = createApp({ modules: [emptyModule], appName: "ops-app" });
|
|
76
|
+
const cmd = defineCommand("require-id", {
|
|
77
|
+
args: z.object({ id: z.string() }),
|
|
78
|
+
handler: async () => "never",
|
|
79
|
+
});
|
|
80
|
+
const stderr = [];
|
|
81
|
+
const code = await runPlease({
|
|
82
|
+
apps: [],
|
|
83
|
+
appInstances: [app],
|
|
84
|
+
argv: ["require-id"],
|
|
85
|
+
commands: [cmd],
|
|
86
|
+
stdout: () => { },
|
|
87
|
+
stderr: (l) => stderr.push(l),
|
|
88
|
+
});
|
|
89
|
+
expect(code).toBe(1);
|
|
90
|
+
expect(stderr.join("\n")).toMatch(/invalid args for "require-id"/);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
//# sourceMappingURL=define-command.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-command.test.js","sourceRoot":"","sources":["../../src/__tests__/define-command.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-please.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/run-please.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `runPlease` — operator CLI dispatcher.
|
|
3
|
+
*
|
|
4
|
+
* Covers command-vs-action precedence so domain-action surface stays clean
|
|
5
|
+
* and operator scripts run via the same `please <name>` UX.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, expect } from "vitest";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import { defineAction, defineModule, createApp } from "@nwire/forge";
|
|
10
|
+
import { defineCommand, runPlease } from "../please.js";
|
|
11
|
+
describe("runPlease command dispatch", () => {
|
|
12
|
+
it("dispatches a registered command by name (precedence over actions)", async () => {
|
|
13
|
+
let actionRan = false;
|
|
14
|
+
let commandRan = false;
|
|
15
|
+
// Domain action sharing the same name as the operator command.
|
|
16
|
+
const ping = defineAction({
|
|
17
|
+
name: "ping",
|
|
18
|
+
description: "Domain ping action — should NOT run when shadowed.",
|
|
19
|
+
schema: z.object({}),
|
|
20
|
+
handler: async () => {
|
|
21
|
+
actionRan = true;
|
|
22
|
+
return undefined;
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
const opsModule = defineModule("ops", { actions: [ping] });
|
|
26
|
+
const app = createApp({ modules: [opsModule], appName: "ops-app" });
|
|
27
|
+
const pingCommand = defineCommand("ping", {
|
|
28
|
+
describe: "Operator ping — shadows the domain action.",
|
|
29
|
+
handler: async () => {
|
|
30
|
+
commandRan = true;
|
|
31
|
+
return { from: "command" };
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
const stdout = [];
|
|
35
|
+
const code = await runPlease({
|
|
36
|
+
apps: [],
|
|
37
|
+
appInstances: [app],
|
|
38
|
+
argv: ["ping"],
|
|
39
|
+
commands: [pingCommand],
|
|
40
|
+
stdout: (l) => stdout.push(l),
|
|
41
|
+
stderr: () => { },
|
|
42
|
+
});
|
|
43
|
+
expect(code).toBe(0);
|
|
44
|
+
expect(commandRan).toBe(true);
|
|
45
|
+
expect(actionRan).toBe(false);
|
|
46
|
+
expect(stdout.join("\n")).toContain('"from": "command"');
|
|
47
|
+
});
|
|
48
|
+
it("falls back to the action surface when no command matches the name", async () => {
|
|
49
|
+
let actionInput = null;
|
|
50
|
+
const flagSubmission = defineAction({
|
|
51
|
+
name: "submissions.flag",
|
|
52
|
+
description: "Flag Avi's submission for review.",
|
|
53
|
+
schema: z.object({ submissionId: z.string() }),
|
|
54
|
+
handler: async (input) => {
|
|
55
|
+
actionInput = input;
|
|
56
|
+
return undefined;
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
const submissionsModule = defineModule("submissions", { actions: [flagSubmission] });
|
|
60
|
+
const app = createApp({ modules: [submissionsModule], appName: "ops-app" });
|
|
61
|
+
const backfill = defineCommand("backfill-users", {
|
|
62
|
+
handler: async () => "noop",
|
|
63
|
+
});
|
|
64
|
+
const stdout = [];
|
|
65
|
+
const stderr = [];
|
|
66
|
+
const code = await runPlease({
|
|
67
|
+
apps: [],
|
|
68
|
+
appInstances: [app],
|
|
69
|
+
argv: ["submissions.flag", "--submissionId", "sub-1"],
|
|
70
|
+
commands: [backfill],
|
|
71
|
+
stdout: (l) => stdout.push(l),
|
|
72
|
+
stderr: (l) => stderr.push(l),
|
|
73
|
+
});
|
|
74
|
+
expect(code).toBe(0);
|
|
75
|
+
expect(stderr).toEqual([]);
|
|
76
|
+
expect(actionInput).toEqual({ submissionId: "sub-1" });
|
|
77
|
+
expect(stdout.join("\n")).toContain("OK");
|
|
78
|
+
});
|
|
79
|
+
it("reports unknown name when neither a command nor an action matches", async () => {
|
|
80
|
+
const emptyModule = defineModule("ops", {});
|
|
81
|
+
const app = createApp({ modules: [emptyModule], appName: "ops-app" });
|
|
82
|
+
const stderr = [];
|
|
83
|
+
const code = await runPlease({
|
|
84
|
+
apps: [],
|
|
85
|
+
appInstances: [app],
|
|
86
|
+
argv: ["nope"],
|
|
87
|
+
commands: [],
|
|
88
|
+
stdout: () => { },
|
|
89
|
+
stderr: (l) => stderr.push(l),
|
|
90
|
+
});
|
|
91
|
+
expect(code).toBe(1);
|
|
92
|
+
expect(stderr.join("\n")).toMatch(/unknown command, action, or query: "nope"/);
|
|
93
|
+
});
|
|
94
|
+
it("lists commands in --help output alongside actions", async () => {
|
|
95
|
+
const emptyModule = defineModule("ops", {});
|
|
96
|
+
const app = createApp({ modules: [emptyModule], appName: "ops-app" });
|
|
97
|
+
const stdout = [];
|
|
98
|
+
const code = await runPlease({
|
|
99
|
+
apps: [],
|
|
100
|
+
appInstances: [app],
|
|
101
|
+
argv: ["--help"],
|
|
102
|
+
commands: [
|
|
103
|
+
defineCommand("seed-classroom", {
|
|
104
|
+
describe: "Seed Dina's starter classroom.",
|
|
105
|
+
handler: async () => undefined,
|
|
106
|
+
}),
|
|
107
|
+
],
|
|
108
|
+
stdout: (l) => stdout.push(l),
|
|
109
|
+
stderr: () => { },
|
|
110
|
+
});
|
|
111
|
+
expect(code).toBe(0);
|
|
112
|
+
const out = stdout.join("\n");
|
|
113
|
+
expect(out).toContain("# Commands (operator scripts)");
|
|
114
|
+
expect(out).toContain("seed-classroom");
|
|
115
|
+
expect(out).toContain("Seed Dina's starter classroom.");
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
//# sourceMappingURL=run-please.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-please.test.js","sourceRoot":"","sources":["../../src/__tests__/run-please.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineCommand` — operator-script primitive.
|
|
3
|
+
*
|
|
4
|
+
* Peer to `defineAction` / `defineQuery`, but lives at the *operator* layer:
|
|
5
|
+
* one-off scripts the team runs from the CLI (backfills, replays, seed loaders,
|
|
6
|
+
* data fixers). They don't belong on the domain action surface — they're not
|
|
7
|
+
* intent the system processes through its event-sourced spine, they're
|
|
8
|
+
* imperative jobs the operator triggers by hand.
|
|
9
|
+
*
|
|
10
|
+
* export const backfillUsers = defineCommand("backfill-users", {
|
|
11
|
+
* describe: "Re-hydrate users from external source",
|
|
12
|
+
* args: z.object({ since: z.string().optional() }),
|
|
13
|
+
* handler: async ({ args, ctx }) => {
|
|
14
|
+
* const repo = ctx.resolve("UserRepo")
|
|
15
|
+
* return { updated: await repo.backfill(args) }
|
|
16
|
+
* },
|
|
17
|
+
* })
|
|
18
|
+
*
|
|
19
|
+
* Wire commands by listing them on `runPlease({ apps, commands, argv })`.
|
|
20
|
+
* `runPlease` looks up the named arg in the commands array FIRST, then falls
|
|
21
|
+
* back to the action/query surface. This keeps the action graph clean and
|
|
22
|
+
* pushes ops scripts to the layer they belong on.
|
|
23
|
+
*/
|
|
24
|
+
import type * as forge from "@nwire/forge";
|
|
25
|
+
import type { SourceLocation } from "@nwire/messages";
|
|
26
|
+
/**
|
|
27
|
+
* Minimal zod-like schema contract — anything with `.parse(input) → output`.
|
|
28
|
+
* Lets `defineCommand` accept a real `z.object({...})` schema, a plain `{}`
|
|
29
|
+
* marker (treated as "no args"), or any other parser-shaped object without
|
|
30
|
+
* coupling `@nwire/please` to zod's runtime.
|
|
31
|
+
*/
|
|
32
|
+
export interface CommandArgsSchema<TOut = any> {
|
|
33
|
+
parse(input: unknown): TOut;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Context passed to a command's handler. Intentionally minimal — mirrors the
|
|
37
|
+
* `ctx.resolve` shape from forge's `HandlerContext` plus the booted `App`
|
|
38
|
+
* instance so operator scripts can `app.runtime.dispatch(...)` an action,
|
|
39
|
+
* `app.runtime.query(...)` a projection, or pull any DI'd dependency by name.
|
|
40
|
+
*/
|
|
41
|
+
export interface CommandContext {
|
|
42
|
+
/** Look up a dependency by name (container.resolve shortcut). */
|
|
43
|
+
resolve<T = unknown>(name: string): T;
|
|
44
|
+
/** The booted app the command was dispatched against. */
|
|
45
|
+
readonly app: forge.App;
|
|
46
|
+
}
|
|
47
|
+
export interface CommandHandlerArgs<TArgs> {
|
|
48
|
+
readonly args: TArgs;
|
|
49
|
+
readonly ctx: CommandContext;
|
|
50
|
+
}
|
|
51
|
+
export type CommandHandler<TArgs> = (args: CommandHandlerArgs<TArgs>) => Promise<unknown> | unknown;
|
|
52
|
+
export interface CommandMeta<TSchema extends CommandArgsSchema | undefined> {
|
|
53
|
+
/** Short, human-readable summary printed by `please --help`. */
|
|
54
|
+
readonly describe?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Args parser. Pass a zod schema (`z.object({...})`) for typed/validated
|
|
57
|
+
* input, or a plain object marker (`{}`) when the command takes no args.
|
|
58
|
+
* Anything with a `.parse(input) → output` method is accepted.
|
|
59
|
+
*/
|
|
60
|
+
readonly args?: TSchema;
|
|
61
|
+
/** Handler executed when the operator runs `please <name>`. */
|
|
62
|
+
readonly handler: CommandHandler<TSchema extends CommandArgsSchema<infer T> ? T : Record<string, unknown>>;
|
|
63
|
+
}
|
|
64
|
+
export interface CommandDefinition<TSchema extends CommandArgsSchema | undefined = CommandArgsSchema | undefined> {
|
|
65
|
+
readonly $kind: "command";
|
|
66
|
+
readonly name: string;
|
|
67
|
+
readonly describe?: string;
|
|
68
|
+
readonly args?: TSchema;
|
|
69
|
+
readonly handler: CommandHandler<TSchema extends CommandArgsSchema<infer T> ? T : Record<string, unknown>>;
|
|
70
|
+
/** Where the command was declared. Studio/Hooks page uses this for IDE links. */
|
|
71
|
+
readonly $source?: SourceLocation;
|
|
72
|
+
}
|
|
73
|
+
export declare function defineCommand<TSchema extends CommandArgsSchema | undefined = undefined>(name: string, meta: CommandMeta<TSchema>): CommandDefinition<TSchema>;
|
|
74
|
+
//# sourceMappingURL=define-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-command.d.ts","sourceRoot":"","sources":["../src/define-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD;;;;;GAKG;AAEH,MAAM,WAAW,iBAAiB,CAAC,IAAI,GAAG,GAAG;IAC3C,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC;IACtC,yDAAyD;IACzD,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB,CAAC,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;CAC9B;AAED,MAAM,MAAM,cAAc,CAAC,KAAK,IAAI,CAElC,IAAI,EAAE,kBAAkB,CAAC,KAAK,CAAC,KAC5B,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAEhC,MAAM,WAAW,WAAW,CAAC,OAAO,SAAS,iBAAiB,GAAG,SAAS;IACxE,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,cAAc,CAC9B,OAAO,SAAS,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CACzE,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB,CAChC,OAAO,SAAS,iBAAiB,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS;IAE7E,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,cAAc,CAC9B,OAAO,SAAS,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CACzE,CAAC;IACF,iFAAiF;IACjF,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;CACnC;AAED,wBAAgB,aAAa,CAAC,OAAO,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACrF,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,GACzB,iBAAiB,CAAC,OAAO,CAAC,CAU5B"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineCommand` — operator-script primitive.
|
|
3
|
+
*
|
|
4
|
+
* Peer to `defineAction` / `defineQuery`, but lives at the *operator* layer:
|
|
5
|
+
* one-off scripts the team runs from the CLI (backfills, replays, seed loaders,
|
|
6
|
+
* data fixers). They don't belong on the domain action surface — they're not
|
|
7
|
+
* intent the system processes through its event-sourced spine, they're
|
|
8
|
+
* imperative jobs the operator triggers by hand.
|
|
9
|
+
*
|
|
10
|
+
* export const backfillUsers = defineCommand("backfill-users", {
|
|
11
|
+
* describe: "Re-hydrate users from external source",
|
|
12
|
+
* args: z.object({ since: z.string().optional() }),
|
|
13
|
+
* handler: async ({ args, ctx }) => {
|
|
14
|
+
* const repo = ctx.resolve("UserRepo")
|
|
15
|
+
* return { updated: await repo.backfill(args) }
|
|
16
|
+
* },
|
|
17
|
+
* })
|
|
18
|
+
*
|
|
19
|
+
* Wire commands by listing them on `runPlease({ apps, commands, argv })`.
|
|
20
|
+
* `runPlease` looks up the named arg in the commands array FIRST, then falls
|
|
21
|
+
* back to the action/query surface. This keeps the action graph clean and
|
|
22
|
+
* pushes ops scripts to the layer they belong on.
|
|
23
|
+
*/
|
|
24
|
+
import { captureSourceLocation } from "@nwire/messages";
|
|
25
|
+
export function defineCommand(name, meta) {
|
|
26
|
+
const $source = captureSourceLocation();
|
|
27
|
+
return {
|
|
28
|
+
$kind: "command",
|
|
29
|
+
name,
|
|
30
|
+
describe: meta.describe,
|
|
31
|
+
args: meta.args,
|
|
32
|
+
handler: meta.handler,
|
|
33
|
+
$source,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=define-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-command.js","sourceRoot":"","sources":["../src/define-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAiExD,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,IAA0B;IAE1B,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAC;IACxC,OAAO;QACL,KAAK,EAAE,SAAS;QAChB,IAAI;QACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,OAAO;KACR,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nwire/please` — barrel entry. Mirrors the surface of `./please.ts` so
|
|
3
|
+
* consumers can import from `@nwire/please` regardless of which entry the
|
|
4
|
+
* bundler / package.json resolves.
|
|
5
|
+
*/
|
|
6
|
+
export * from "./please.js";
|
|
7
|
+
export * from "./define-command.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nwire/please` — barrel entry. Mirrors the surface of `./please.ts` so
|
|
3
|
+
* consumers can import from `@nwire/please` regardless of which entry the
|
|
4
|
+
* bundler / package.json resolves.
|
|
5
|
+
*/
|
|
6
|
+
export * from "./please.js";
|
|
7
|
+
export * from "./define-command.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC"}
|
package/dist/please.d.ts
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* follow-up phase — the CLI runner is the primitive, scaffolders compose on top.
|
|
18
18
|
*/
|
|
19
19
|
import * as forge from "@nwire/forge";
|
|
20
|
+
import type { CommandDefinition } from "./define-command.js";
|
|
20
21
|
export interface RunPleaseOptions {
|
|
21
22
|
/** Apps to expose. The CLI dispatches against any action/query in any of these. */
|
|
22
23
|
readonly apps: readonly forge.AppDefinition[];
|
|
@@ -30,10 +31,18 @@ export interface RunPleaseOptions {
|
|
|
30
31
|
readonly stderr?: (line: string) => void;
|
|
31
32
|
/** Hook for store/logger overrides at instantiation time. */
|
|
32
33
|
readonly createOverrides?: (appDef: forge.AppDefinition) => Omit<forge.CreateAppOptions, "modules">;
|
|
34
|
+
/**
|
|
35
|
+
* Operator-script commands (`defineCommand`). Dispatched by name with
|
|
36
|
+
* precedence over actions/queries — so a backfill script can shadow a
|
|
37
|
+
* domain action name on purpose, and ops scripts never leak into the
|
|
38
|
+
* action surface.
|
|
39
|
+
*/
|
|
40
|
+
readonly commands?: readonly CommandDefinition[];
|
|
33
41
|
}
|
|
34
42
|
/**
|
|
35
43
|
* Boot every registered app, run the dispatched action/query against the
|
|
36
44
|
* matching app, return the exit code (0 on success, 1 on error).
|
|
37
45
|
*/
|
|
38
46
|
export declare function runPlease(options: RunPleaseOptions): Promise<number>;
|
|
47
|
+
export { defineCommand, type CommandArgsSchema, type CommandContext, type CommandDefinition, type CommandHandler, type CommandHandlerArgs, type CommandMeta, } from "./define-command.js";
|
|
39
48
|
//# sourceMappingURL=please.d.ts.map
|
package/dist/please.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"please.d.ts","sourceRoot":"","sources":["../src/please.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"please.d.ts","sourceRoot":"","sources":["../src/please.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,WAAW,gBAAgB;IAC/B,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,SAAS,KAAK,CAAC,aAAa,EAAE,CAAC;IAC9C,qEAAqE;IACrE,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,KAAK,CAAC,GAAG,EAAE,CAAC;IAC7C,qDAAqD;IACrD,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,qDAAqD;IACrD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,uDAAuD;IACvD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,6DAA6D;IAC7D,QAAQ,CAAC,eAAe,CAAC,EAAE,CACzB,MAAM,EAAE,KAAK,CAAC,aAAa,KACxB,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;IAC7C;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAClD;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2C1E;AA8ID,OAAO,EACL,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,WAAW,GACjB,MAAM,kBAAkB,CAAC"}
|
package/dist/please.js
CHANGED
|
@@ -31,18 +31,121 @@ export async function runPlease(options) {
|
|
|
31
31
|
const argv = options.argv;
|
|
32
32
|
const stdout = options.stdout;
|
|
33
33
|
const stderr = options.stderr;
|
|
34
|
+
const commands = options.commands ?? [];
|
|
34
35
|
if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h") {
|
|
35
|
-
printAllHelp(instances, options.stdout ?? ((l) => console.log(l)));
|
|
36
|
+
printAllHelp(instances, commands, options.stdout ?? ((l) => console.log(l)));
|
|
36
37
|
return 0;
|
|
37
38
|
}
|
|
38
39
|
const targetName = argv[0];
|
|
40
|
+
// Commands take precedence: operator scripts shadow the action surface so a
|
|
41
|
+
// backfill named "submissions.flag" never collides with the domain action of
|
|
42
|
+
// the same name. The first registered command wins on duplicates.
|
|
43
|
+
const command = commands.find((c) => c.name === targetName);
|
|
44
|
+
if (command) {
|
|
45
|
+
return runCommand(command, instances, argv.slice(1), {
|
|
46
|
+
stdout: stdout ?? ((l) => console.log(l)),
|
|
47
|
+
stderr: stderr ?? ((l) => console.error(l)),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
39
50
|
const owner = instances.find((a) => actionOrQueryNames(a).includes(targetName));
|
|
40
51
|
if (!owner) {
|
|
41
|
-
(options.stderr ?? ((l) => console.error(l)))(`unknown action or query: "${targetName}". Run with --help.`);
|
|
52
|
+
(options.stderr ?? ((l) => console.error(l)))(`unknown command, action, or query: "${targetName}". Run with --help.`);
|
|
42
53
|
return 1;
|
|
43
54
|
}
|
|
44
55
|
return forge.runCli(owner, argv, { stdout, stderr });
|
|
45
56
|
}
|
|
57
|
+
async function runCommand(command, instances, rest, io) {
|
|
58
|
+
const app = instances[0];
|
|
59
|
+
if (!app) {
|
|
60
|
+
io.stderr(`cannot run command "${command.name}": no app is registered with runPlease`);
|
|
61
|
+
return 1;
|
|
62
|
+
}
|
|
63
|
+
const parsed = parseFlagsToObject(rest);
|
|
64
|
+
let args = parsed;
|
|
65
|
+
if (command.args && typeof command.args.parse === "function") {
|
|
66
|
+
try {
|
|
67
|
+
args = command.args.parse(parsed);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
io.stderr(`invalid args for "${command.name}": ${err.message}`);
|
|
71
|
+
return 1;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const ctx = {
|
|
75
|
+
app,
|
|
76
|
+
resolve(name) {
|
|
77
|
+
return app.container.resolve(name);
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
try {
|
|
81
|
+
const result = await command.handler({ args: args, ctx });
|
|
82
|
+
if (result === undefined) {
|
|
83
|
+
io.stdout("OK");
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
io.stdout(JSON.stringify(result, null, 2));
|
|
87
|
+
}
|
|
88
|
+
return 0;
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
io.stderr(`error running command "${command.name}": ${err.message}`);
|
|
92
|
+
return 1;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Minimal flag parser shared with the action CLI surface. Mirrors the
|
|
97
|
+
* `--field value` / `--field=value` / repeated-flag / boolean-toggle behavior
|
|
98
|
+
* `forge.runCli` exposes, so command authors get the same operator UX.
|
|
99
|
+
*/
|
|
100
|
+
function parseFlagsToObject(argv) {
|
|
101
|
+
const out = {};
|
|
102
|
+
for (let i = 0; i < argv.length; i++) {
|
|
103
|
+
const arg = argv[i];
|
|
104
|
+
if (!arg.startsWith("--"))
|
|
105
|
+
continue;
|
|
106
|
+
const eq = arg.indexOf("=");
|
|
107
|
+
let key;
|
|
108
|
+
let value;
|
|
109
|
+
if (eq >= 0) {
|
|
110
|
+
key = arg.slice(2, eq);
|
|
111
|
+
value = arg.slice(eq + 1);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
key = arg.slice(2);
|
|
115
|
+
const next = argv[i + 1];
|
|
116
|
+
if (next !== undefined && !next.startsWith("--")) {
|
|
117
|
+
value = next;
|
|
118
|
+
i++;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
value = true;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const coerced = typeof value === "string" ? coerceFlag(value) : value;
|
|
125
|
+
if (key in out) {
|
|
126
|
+
const existing = out[key];
|
|
127
|
+
if (Array.isArray(existing))
|
|
128
|
+
existing.push(coerced);
|
|
129
|
+
else
|
|
130
|
+
out[key] = [existing, coerced];
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
out[key] = coerced;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
function coerceFlag(value) {
|
|
139
|
+
if (value === "true")
|
|
140
|
+
return true;
|
|
141
|
+
if (value === "false")
|
|
142
|
+
return false;
|
|
143
|
+
if (/^-?\d+$/.test(value))
|
|
144
|
+
return Number(value);
|
|
145
|
+
if (/^-?\d+\.\d+$/.test(value))
|
|
146
|
+
return Number(value);
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
46
149
|
function actionOrQueryNames(app) {
|
|
47
150
|
const actions = [];
|
|
48
151
|
for (const module of app.modules) {
|
|
@@ -53,9 +156,16 @@ function actionOrQueryNames(app) {
|
|
|
53
156
|
}
|
|
54
157
|
return actions;
|
|
55
158
|
}
|
|
56
|
-
function printAllHelp(instances, out) {
|
|
159
|
+
function printAllHelp(instances, commands, out) {
|
|
57
160
|
out("please — Nwire operator CLI\n");
|
|
58
|
-
out("Usage: please <action-or-query
|
|
161
|
+
out("Usage: please <command-or-action-or-query> [--field value ...] [--tenant <id>]\n");
|
|
162
|
+
if (commands.length > 0) {
|
|
163
|
+
out("# Commands (operator scripts)");
|
|
164
|
+
for (const c of commands) {
|
|
165
|
+
out(` ${c.name}${c.describe ? " — " + c.describe.slice(0, 70) : ""}`);
|
|
166
|
+
}
|
|
167
|
+
out("");
|
|
168
|
+
}
|
|
59
169
|
for (const app of instances) {
|
|
60
170
|
out(`# App: ${describeApp(app)}`);
|
|
61
171
|
for (const module of app.modules) {
|
|
@@ -74,4 +184,8 @@ function describeApp(app) {
|
|
|
74
184
|
// `App` carries its AppDefinition reference. Today: show module count.
|
|
75
185
|
return `${app.modules.length} module${app.modules.length === 1 ? "" : "s"}`;
|
|
76
186
|
}
|
|
187
|
+
// Surface the operator-script primitive alongside `runPlease`. Consumers
|
|
188
|
+
// import them from the same package entry: `import { defineCommand, runPlease }
|
|
189
|
+
// from '@nwire/please'`.
|
|
190
|
+
export { defineCommand, } from "./define-command.js";
|
|
77
191
|
//# sourceMappingURL=please.js.map
|
package/dist/please.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"please.js","sourceRoot":"","sources":["../src/please.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"please.js","sourceRoot":"","sources":["../src/please.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nwire/please",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Nwire — operator CLI. runPlease dispatches actions/queries by name across all registered apps; --tenant for tenant scoping; --help lists everything. Scaffolding (make:module / make:action) lands on top.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ace",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"access": "public"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@nwire/forge": "0.
|
|
31
|
+
"@nwire/forge": "0.8.0",
|
|
32
|
+
"@nwire/messages": "0.8.0"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
34
35
|
"@types/node": "^22.19.9",
|