@@ -253,16 +253,16 @@ defineCommand({
253253 { name: " files" , variadic: true },
254254 ],
255255 async run(ctx ) {
256- ctx .arguments .platform ; // "android"
257- ctx .arguments .template ; // "blank", or absent
258- ctx .arguments .files ; // string[], possibly empty
256+ ctx .params .platform ; // "android"
257+ ctx .params .template ; // "blank", or absent
258+ ctx .params .files ; // string[], possibly empty
259259 },
260260});
261261```
262262
263263A spec accepts:
264264
265- - ` name ` — the key the value appears under on ` ctx.arguments ` , and the name
265+ - ` name ` — the key the value appears under on ` ctx.params ` , and the name
266266 messages use.
267267- ` required ` — defaults to false. A required argument may not follow an
268268 optional one; positional matching would never be able to satisfy it.
@@ -288,11 +288,11 @@ and lets a mandatory parameter claim whichever argument happens to satisfy it
288288so ` ns command b a ` could satisfy ` [a, b] ` . Nothing in the CLI depends on that
289289behaviour, and positional is what the declaration reads like.
290290
291- The practical consequence: ` ctx.arguments .template ` is ` args[1] ` whether or not
291+ The practical consequence: ` ctx.params .template ` is ` args[1] ` whether or not
292292` args[1] ` looks like a template. An argument that could be several things is a
293293job for ` validate ` or for ` canExecute ` , not for the matcher.
294294
295- ` ctx.arguments ` is always present, even with ` arguments: "none" ` or ` "any" ` —
295+ ` ctx.params ` is always present, even with ` arguments: "none" ` or ` "any" ` —
296296it is simply ` {} ` when no specs are declared. An optional non-variadic argument
297297the command line did not reach is absent from it; a variadic one is always
298298there, as an array.
@@ -334,8 +334,10 @@ The run context
334334
335335- ` ctx.args ` — ` string[] ` , the positional arguments left after the command name
336336 (including any subcommand segments) has been consumed.
337- - ` ctx.arguments ` — the same arguments keyed by the names the ` arguments ` specs
338- declare, ` {} ` when there are none.
337+ - ` ctx.params ` — the same arguments keyed by the names the ` arguments ` specs
338+ declare, ` {} ` when there are none. It is spelled ` params ` because
339+ ` arguments ` is a reserved binding name in strict mode, so a destructuring
340+ ` const { args, arguments } = ctx ` would not even parse.
339341- ` ctx.options ` — the current value of each declared option, read at the moment
340342 the command executes.
341343- ` ctx.injector ` — the injector this command was registered against; see
@@ -458,7 +460,7 @@ export default defineCommand({
458460 name: " create" ,
459461 arguments: [{ name: " appName" , required: true }],
460462 async run(ctx ) {
461- const projectDir = await createProject (ctx .arguments .appName as string );
463+ const projectDir = await createProject (ctx .params .appName as string );
462464 return { projectDir };
463465 },
464466 postRun(ctx , { projectDir }) {
@@ -648,6 +650,71 @@ after the first `await` — and needs to know nothing else. The spread keeps the
648650This replaces the class-inheritance pattern the legacy commands use, where a
649651per-platform command subclasses a shared base to override one field.
650652
653+ Running a command in process
654+ ----------------------------
655+
656+ ` runCommand ` dispatches a registered command from inside the process that is
657+ already running:
658+
659+ ``` ts
660+ import { runCommand } from " ../common/services/command-definition-adapter" ;
661+
662+ await runCommand (" open|ios" );
663+ await runCommand (" install" , [" lodash" ]);
664+ ```
665+
666+ The command gets what a typed command line gives it, in the same order: its
667+ declared options are primed into the parser — so ` ctx.options ` holds this
668+ command's values and its declared defaults rather than the outer command
669+ line's — then the ` arguments ` policy, then ` canExecute ` , then ` run ` ,
670+ ` postRun ` , and the command's hooks.
671+
672+ Two things differ, both because the caller is a process that has to keep
673+ running afterwards:
674+
675+ - ** A failure throws instead of exiting.** A failed command line ends in
676+ ` process.exit ` . ` runCommand ` reports the failure the same way — the same
677+ message formatting, the same ` ns … --help ` suggestion — and then throws, so
678+ the caller decides what happens next.
679+ - ** Analytics do not fire.** An in-process dispatch is not a new invocation of
680+ the CLI, and the consent check can prompt on a terminal the caller has put
681+ into raw mode. Hooks do fire: a project's ` before-open-ios ` hook is part of
682+ what ` open|ios ` means, however the command was reached.
683+
684+ The options service is put back the way it was found. Merging a command's
685+ declarations into it rewrites the values the host process is still running on
686+ — ` open|ios ` declares ` watch: false ` , which would otherwise leave an ` ns start `
687+ out of watch mode for the rest of its life.
688+
689+ Which injector it dispatches through follows the rule ` registerCommand ` does:
690+ the injector of the current injection context, and the CLI's own outside one.
691+ ` runCommand ` is a thin call onto ` CommandsService.executeCommandInProcess ` ,
692+ where the pipeline itself lives.
693+
694+ ### Key shortcuts
695+
696+ The interactive keys ` ns start ` and ` ns run ` offer are the CLI's own caller. A
697+ shortcut is a table entry with a ` when ` deciding whether the key is live, and
698+ an ` action ` that runs it:
699+
700+ ``` ts
701+ {
702+ key : " I" ,
703+ description : " Open project in Xcode" ,
704+ when : onPlatform (" iOS" ),
705+ action : () => runCommand (" open|ios" ),
706+ }
707+ ```
708+
709+ The context an action receives carries state and nothing else — the platform
710+ being watched, whether this is ` ns start ` or an ` ns run ` child it spawned, and
711+ the injector. Capabilities are resolved from that injector rather than handed
712+ over as context methods:
713+
714+ ``` ts
715+ action : (ctx ) => ctx .injector .get <IStartService >(" startService" ).runIOS (),
716+ ```
717+
651718Relationship to ` ICommand `
652719--------------------------
653720
0 commit comments