@reliverse/rempts 1.7.2 โ†’ 1.7.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.md CHANGED
@@ -18,7 +18,7 @@
18
18
  - ๐Ÿšจ Crash-safe (Ctrl+C, SIGINT, errors)
19
19
  - ๐Ÿช„ Minimal API surface, max expressiveness
20
20
  - ๐Ÿงช Scriptable for testing, stable for production
21
- - ๐Ÿ†• Automatic commands creation (via `dler init --cmd my-cool-cmd`)
21
+ - ๐Ÿ†• Automatic commands creation (via `dler rempts init --cmd my-cool-cmd`)
22
22
  - ๐Ÿž๏ธ No more hacking together `inquirer`, `citty`, `commander`, `chalk`
23
23
 
24
24
  ## Installation
@@ -145,6 +145,8 @@ await main();
145
145
 
146
146
  #### Launcher Usage Example
147
147
 
148
+ **Important**: Ensure your commands don't have `await main();`, `await runMain();`, or something like that โ€” to prevent any unexpected behavior. Only main command should have it.
149
+
148
150
  ```ts
149
151
  import { relinka } from "@reliverse/relinka";
150
152
 
@@ -220,7 +222,7 @@ export default defineCommand({
220
222
  **Hint**:
221
223
 
222
224
  - Install `bun add -D @reliverse/dler`
223
- - Use `dler init --cmd cmd1 cmd2` to init commands for rempts launcher's automatically
225
+ - Use `dler rempts init --cmd cmd1 cmd2` to init commands for rempts launcher's automatically
224
226
 
225
227
  ### Advanced Minimal API
226
228
 
@@ -287,7 +289,7 @@ await runMain(defineCommand({}));
287
289
 
288
290
  ```bash
289
291
  bun add -D @reliverse/dler # or: bun i -g @reliverse/dler
290
- bun dler init --cmd my-cmd-1 # or: dler init my-cmd-1 my-cmd-2 --main src/mod.ts
292
+ bun dler rempts init --cmd my-cmd-1 # or: dler rempts init my-cmd-1 my-cmd-2 --main src/mod.ts
291
293
  # * `--main` is optional, default is `./src/mod.ts`
292
294
  # * you can specify multiple commands at once
293
295
  ```
@@ -53,6 +53,7 @@ type CommandContext<ARGS> = {
53
53
  raw: string[];
54
54
  };
55
55
  type CommandRun<ARGS> = (ctx: CommandContext<ARGS>) => void | Promise<void>;
56
+ type CommandHook<ARGS> = (ctx: CommandContext<ARGS>) => void | Promise<void>;
56
57
  type DefineCommandOptions<A extends ArgDefinitions = EmptyArgs> = {
57
58
  meta?: CommandMeta;
58
59
  args?: A;
@@ -66,21 +67,21 @@ type DefineCommandOptions<A extends ArgDefinitions = EmptyArgs> = {
66
67
  */
67
68
  subCommands?: CommandsMap;
68
69
  /**
69
- * Called before the command runs
70
+ * Called before the command runs. Receives `{ args, raw }` (parsed args and raw argv).
70
71
  */
71
- onCmdStart?: () => void | Promise<void>;
72
+ onCmdStart?: CommandHook<InferArgTypes<A>>;
72
73
  /**
73
- * Called after the command finishes
74
+ * Called after the command finishes. Receives `{ args, raw }` (parsed args and raw argv).
74
75
  */
75
- onCmdEnd?: () => void | Promise<void>;
76
+ onCmdEnd?: CommandHook<InferArgTypes<A>>;
76
77
  /**
77
78
  * @deprecated Use onCmdStart instead
78
79
  */
79
- setup?: () => void | Promise<void>;
80
+ setup?: CommandHook<InferArgTypes<A>>;
80
81
  /**
81
82
  * @deprecated Use onCmdEnd instead
82
83
  */
83
- cleanup?: () => void | Promise<void>;
84
+ cleanup?: CommandHook<InferArgTypes<A>>;
84
85
  /**
85
86
  * Called once per CLI process, before any command/run() is executed
86
87
  */
@@ -103,21 +104,21 @@ export type Command<A extends ArgDefinitions = EmptyArgs> = {
103
104
  */
104
105
  subCommands?: CommandsMap;
105
106
  /**
106
- * Called before the command runs
107
+ * Called before the command runs. Receives `{ args, raw }` (parsed args and raw argv).
107
108
  */
108
- onCmdStart?: () => void | Promise<void>;
109
+ onCmdStart?: CommandHook<InferArgTypes<A>>;
109
110
  /**
110
- * Called after the command finishes
111
+ * Called after the command finishes. Receives `{ args, raw }` (parsed args and raw argv).
111
112
  */
112
- onCmdEnd?: () => void | Promise<void>;
113
+ onCmdEnd?: CommandHook<InferArgTypes<A>>;
113
114
  /**
114
115
  * @deprecated Use onCmdStart instead
115
116
  */
116
- setup?: () => void | Promise<void>;
117
+ setup?: CommandHook<InferArgTypes<A>>;
117
118
  /**
118
119
  * @deprecated Use onCmdEnd instead
119
120
  */
120
- cleanup?: () => void | Promise<void>;
121
+ cleanup?: CommandHook<InferArgTypes<A>>;
121
122
  /**
122
123
  * Called once per CLI process, before any command/run() is executed
123
124
  */
@@ -167,7 +167,7 @@ export async function showUsage(command, parserOptions = {}, displayNotFoundMess
167
167
  );
168
168
  }
169
169
  if (subCommandNames.length > 0) {
170
- relinka("log", "Available commands (run with `help` to see more):");
170
+ relinka("info", "Available commands (run with `help` to see more):");
171
171
  subCommandDefs.forEach(({ name, def }) => {
172
172
  const desc = def?.meta?.description ?? "";
173
173
  relinka("log", `\u2022 ${name}${desc ? ` | ${desc}` : ""}`);
@@ -217,14 +217,14 @@ export async function showUsage(command, parserOptions = {}, displayNotFoundMess
217
217
  );
218
218
  }
219
219
  if (subCommandNames.length > 0) {
220
- relinka("log", "Available commands (run with `help` to see more):");
220
+ relinka("info", "Available commands (run with `help` to see more):");
221
221
  subCommandDefs.forEach(({ name, def }) => {
222
222
  const desc = def?.meta?.description ?? "";
223
223
  relinka("log", `\u2022 ${name}${desc ? ` | ${desc}` : ""}`);
224
224
  });
225
225
  }
226
226
  }
227
- relinka("log", "Available options:");
227
+ relinka("info", "Available options:");
228
228
  relinka("log", "\u2022 -h, --help | Show help");
229
229
  relinka("log", "\u2022 -v, --version | Show version");
230
230
  relinka("log", "\u2022 --debug | Enable debug mode");
@@ -334,14 +334,17 @@ This can cause recursion or unexpected behavior.`
334
334
  if (fileBasedEnabled && rawArgv.length > 0 && !isFlag(rawArgv[0])) {
335
335
  const [subName, ...subCmdArgv] = rawArgv;
336
336
  try {
337
+ const ctx = getParsedContext(command, rawArgv, parserOptions);
337
338
  if (typeof command.onCmdStart === "function")
338
- await command.onCmdStart();
339
+ await command.onCmdStart(ctx);
339
340
  await runFileBasedSubCmd(
340
341
  subName,
341
342
  subCmdArgv,
342
343
  parserOptions.fileBasedCmds,
343
344
  parserOptions,
344
- command.onCmdEnd
345
+ command.onCmdEnd ? async (_subCtx) => {
346
+ await command.onCmdEnd?.(ctx);
347
+ } : void 0
345
348
  );
346
349
  if (autoExit) process.exit(0);
347
350
  return;
@@ -371,13 +374,16 @@ This can cause recursion or unexpected behavior.`
371
374
  }
372
375
  if (subSpec) {
373
376
  try {
377
+ const ctx = getParsedContext(command, rawArgv, parserOptions);
374
378
  if (typeof command.onCmdStart === "function")
375
- await command.onCmdStart();
379
+ await command.onCmdStart(ctx);
376
380
  await runSubCommand(
377
381
  subSpec,
378
382
  subCmdArgv,
379
383
  parserOptions,
380
- command.onCmdEnd
384
+ command.onCmdEnd ? async (_subCtx) => {
385
+ await command.onCmdEnd?.(ctx);
386
+ } : void 0
381
387
  );
382
388
  if (autoExit) process.exit(0);
383
389
  return;
@@ -474,20 +480,32 @@ Info for this CLI's developer: No valid command directory found, expected: ${exp
474
480
  );
475
481
  }
476
482
  try {
477
- await runCommandWithArgs(subCommand, argv, parserOptions);
483
+ const subCtx = await runCommandWithArgs(
484
+ subCommand,
485
+ argv,
486
+ parserOptions,
487
+ true
488
+ );
489
+ if (typeof parentFinish === "function" && subCtx)
490
+ await parentFinish(subCtx);
478
491
  } finally {
479
- if (typeof parentFinish === "function") await parentFinish();
480
492
  }
481
493
  }
482
494
  async function runSubCommand(spec, argv, parserOptions, parentFinish) {
483
495
  const subCommand = await loadSubCommand(spec);
484
496
  try {
485
- await runCommandWithArgs(subCommand, argv, parserOptions);
497
+ const subCtx = await runCommandWithArgs(
498
+ subCommand,
499
+ argv,
500
+ parserOptions,
501
+ true
502
+ );
503
+ if (typeof parentFinish === "function" && subCtx)
504
+ await parentFinish(subCtx);
486
505
  } finally {
487
- if (typeof parentFinish === "function") await parentFinish();
488
506
  }
489
507
  }
490
- async function runCommandWithArgs(command, argv, parserOptions) {
508
+ async function runCommandWithArgs(command, argv, parserOptions, returnCtx) {
491
509
  const autoExit = parserOptions.autoExit !== false;
492
510
  const booleanKeys = Object.keys(command.args || {}).filter(
493
511
  (k) => command.args[k].type === "boolean"
@@ -593,6 +611,8 @@ ${String(err)}`);
593
611
  if (autoExit) process.exit(1);
594
612
  else throw err;
595
613
  }
614
+ if (returnCtx) return ctx;
615
+ return void 0;
596
616
  }
597
617
  function castArgValue(def, rawVal, argName) {
598
618
  if (rawVal == null) {
@@ -708,3 +728,47 @@ export async function runCmd(command, argv = [], parserOptions = {}) {
708
728
  throw new Error("Command has no run() handler.");
709
729
  }
710
730
  }
731
+ function getParsedContext(command, argv, parserOptions) {
732
+ const booleanKeys = Object.keys(command.args || {}).filter(
733
+ (k) => command.args[k].type === "boolean"
734
+ );
735
+ const defaultMap = {};
736
+ for (const [argKey, def] of Object.entries(command.args || {})) {
737
+ if (def.default !== void 0) {
738
+ if (def.type === "array" && typeof def.default === "string") {
739
+ defaultMap[argKey] = [def.default];
740
+ } else {
741
+ defaultMap[argKey] = def.default;
742
+ }
743
+ }
744
+ }
745
+ const mergedParserOptions = {
746
+ ...parserOptions,
747
+ boolean: [...parserOptions.boolean || [], ...booleanKeys],
748
+ defaults: { ...defaultMap, ...parserOptions.defaults || {} }
749
+ };
750
+ const parsed = reliArgParser(argv, mergedParserOptions);
751
+ const finalArgs = {};
752
+ const positionalKeys = Object.keys(command.args || {}).filter(
753
+ (k) => command.args[k].type === "positional"
754
+ );
755
+ const leftoverPositionals = [...parsed._ || []];
756
+ for (let i = 0; i < positionalKeys.length; i++) {
757
+ const key = positionalKeys[i];
758
+ const def = command.args?.[key];
759
+ const val = leftoverPositionals[i];
760
+ finalArgs[key] = val != null ? castArgValue(def, val, key) : def.default;
761
+ }
762
+ const otherKeys = Object.keys(command.args || {}).filter(
763
+ (k) => command.args[k].type !== "positional"
764
+ );
765
+ for (const key of otherKeys) {
766
+ const def = command.args?.[key];
767
+ let rawVal = parsed[key];
768
+ if (def.type === "array" && rawVal !== void 0 && !Array.isArray(rawVal)) {
769
+ rawVal = [rawVal];
770
+ }
771
+ finalArgs[key] = castArgValue(def, rawVal, key);
772
+ }
773
+ return { args: finalArgs, raw: argv };
774
+ }
package/package.json CHANGED
@@ -28,7 +28,7 @@
28
28
  "license": "MIT",
29
29
  "name": "@reliverse/rempts",
30
30
  "type": "module",
31
- "version": "1.7.2",
31
+ "version": "1.7.3",
32
32
  "author": "reliverse",
33
33
  "bugs": {
34
34
  "email": "blefnk@gmail.com",