@wentools/zli 0.2.0-beta.2dc33a43

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.
Files changed (167) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +226 -0
  3. package/esm/_dnt.shims.d.ts +6 -0
  4. package/esm/_dnt.shims.d.ts.map +1 -0
  5. package/esm/_dnt.shims.js +61 -0
  6. package/esm/arg.d.ts +9 -0
  7. package/esm/arg.d.ts.map +1 -0
  8. package/esm/arg.js +4 -0
  9. package/esm/create_command.d.ts +28 -0
  10. package/esm/create_command.d.ts.map +1 -0
  11. package/esm/create_command.js +17 -0
  12. package/esm/create_command_directory.d.ts +35 -0
  13. package/esm/create_command_directory.d.ts.map +1 -0
  14. package/esm/create_command_directory.js +31 -0
  15. package/esm/create_flag_arg.d.ts +23 -0
  16. package/esm/create_flag_arg.d.ts.map +1 -0
  17. package/esm/create_flag_arg.js +14 -0
  18. package/esm/create_positional_arg.d.ts +24 -0
  19. package/esm/create_positional_arg.d.ts.map +1 -0
  20. package/esm/create_positional_arg.js +15 -0
  21. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/err/err.d.ts +38 -0
  22. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/err/err.d.ts.map +1 -0
  23. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/err/err.js +38 -0
  24. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/err/index.d.ts +2 -0
  25. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/err/index.d.ts.map +1 -0
  26. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/err/index.js +1 -0
  27. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/index.d.ts +156 -0
  28. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/index.d.ts.map +1 -0
  29. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/index.js +65 -0
  30. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/is_result/index.d.ts +2 -0
  31. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/is_result/index.d.ts.map +1 -0
  32. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/is_result/index.js +1 -0
  33. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/is_result/is_result.d.ts +11 -0
  34. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/is_result/is_result.d.ts.map +1 -0
  35. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/is_result/is_result.js +14 -0
  36. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/propagate_err/index.d.ts +2 -0
  37. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/propagate_err/index.d.ts.map +1 -0
  38. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/propagate_err/index.js +1 -0
  39. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/propagate_err/propagate_err.d.ts +28 -0
  40. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/propagate_err/propagate_err.d.ts.map +1 -0
  41. package/esm/deps/jsr.io/@wentools/result/0.1.0/src/propagate_err/propagate_err.js +30 -0
  42. package/esm/detect_arg_conflicts/detect_arg_conflicts.d.ts +19 -0
  43. package/esm/detect_arg_conflicts/detect_arg_conflicts.d.ts.map +1 -0
  44. package/esm/detect_arg_conflicts/detect_arg_conflicts.js +54 -0
  45. package/esm/detect_arg_conflicts/mod.d.ts +3 -0
  46. package/esm/detect_arg_conflicts/mod.d.ts.map +1 -0
  47. package/esm/detect_arg_conflicts/mod.js +1 -0
  48. package/esm/generate_help_text/generate_help_text.d.ts +13 -0
  49. package/esm/generate_help_text/generate_help_text.d.ts.map +1 -0
  50. package/esm/generate_help_text/generate_help_text.js +54 -0
  51. package/esm/generate_help_text/mod.d.ts +2 -0
  52. package/esm/generate_help_text/mod.d.ts.map +1 -0
  53. package/esm/generate_help_text/mod.js +1 -0
  54. package/esm/infer_args_type.d.ts +29 -0
  55. package/esm/infer_args_type.d.ts.map +1 -0
  56. package/esm/infer_args_type.js +6 -0
  57. package/esm/is_boolean_schema/is_boolean_schema.d.ts +12 -0
  58. package/esm/is_boolean_schema/is_boolean_schema.d.ts.map +1 -0
  59. package/esm/is_boolean_schema/is_boolean_schema.js +21 -0
  60. package/esm/is_boolean_schema/mod.d.ts +2 -0
  61. package/esm/is_boolean_schema/mod.d.ts.map +1 -0
  62. package/esm/is_boolean_schema/mod.js +1 -0
  63. package/esm/mod.d.ts +8 -0
  64. package/esm/mod.d.ts.map +1 -0
  65. package/esm/mod.js +1 -0
  66. package/esm/package.json +3 -0
  67. package/esm/parse_args/mod.d.ts +3 -0
  68. package/esm/parse_args/mod.d.ts.map +1 -0
  69. package/esm/parse_args/mod.js +1 -0
  70. package/esm/parse_args/parse_args.d.ts +24 -0
  71. package/esm/parse_args/parse_args.d.ts.map +1 -0
  72. package/esm/parse_args/parse_args.js +89 -0
  73. package/esm/run.d.ts +19 -0
  74. package/esm/run.d.ts.map +1 -0
  75. package/esm/run.js +152 -0
  76. package/esm/validate_args/mod.d.ts +3 -0
  77. package/esm/validate_args/mod.d.ts.map +1 -0
  78. package/esm/validate_args/mod.js +1 -0
  79. package/esm/validate_args/validate_args.d.ts +20 -0
  80. package/esm/validate_args/validate_args.d.ts.map +1 -0
  81. package/esm/validate_args/validate_args.js +23 -0
  82. package/esm/zli.d.ts +118 -0
  83. package/esm/zli.d.ts.map +1 -0
  84. package/esm/zli.js +124 -0
  85. package/package.json +39 -0
  86. package/script/_dnt.shims.d.ts +6 -0
  87. package/script/_dnt.shims.d.ts.map +1 -0
  88. package/script/_dnt.shims.js +65 -0
  89. package/script/arg.d.ts +9 -0
  90. package/script/arg.d.ts.map +1 -0
  91. package/script/arg.js +5 -0
  92. package/script/create_command.d.ts +28 -0
  93. package/script/create_command.d.ts.map +1 -0
  94. package/script/create_command.js +20 -0
  95. package/script/create_command_directory.d.ts +35 -0
  96. package/script/create_command_directory.d.ts.map +1 -0
  97. package/script/create_command_directory.js +34 -0
  98. package/script/create_flag_arg.d.ts +23 -0
  99. package/script/create_flag_arg.d.ts.map +1 -0
  100. package/script/create_flag_arg.js +17 -0
  101. package/script/create_positional_arg.d.ts +24 -0
  102. package/script/create_positional_arg.d.ts.map +1 -0
  103. package/script/create_positional_arg.js +18 -0
  104. package/script/deps/jsr.io/@wentools/result/0.1.0/src/err/err.d.ts +38 -0
  105. package/script/deps/jsr.io/@wentools/result/0.1.0/src/err/err.d.ts.map +1 -0
  106. package/script/deps/jsr.io/@wentools/result/0.1.0/src/err/err.js +41 -0
  107. package/script/deps/jsr.io/@wentools/result/0.1.0/src/err/index.d.ts +2 -0
  108. package/script/deps/jsr.io/@wentools/result/0.1.0/src/err/index.d.ts.map +1 -0
  109. package/script/deps/jsr.io/@wentools/result/0.1.0/src/err/index.js +5 -0
  110. package/script/deps/jsr.io/@wentools/result/0.1.0/src/index.d.ts +156 -0
  111. package/script/deps/jsr.io/@wentools/result/0.1.0/src/index.d.ts.map +1 -0
  112. package/script/deps/jsr.io/@wentools/result/0.1.0/src/index.js +77 -0
  113. package/script/deps/jsr.io/@wentools/result/0.1.0/src/is_result/index.d.ts +2 -0
  114. package/script/deps/jsr.io/@wentools/result/0.1.0/src/is_result/index.d.ts.map +1 -0
  115. package/script/deps/jsr.io/@wentools/result/0.1.0/src/is_result/index.js +5 -0
  116. package/script/deps/jsr.io/@wentools/result/0.1.0/src/is_result/is_result.d.ts +11 -0
  117. package/script/deps/jsr.io/@wentools/result/0.1.0/src/is_result/is_result.d.ts.map +1 -0
  118. package/script/deps/jsr.io/@wentools/result/0.1.0/src/is_result/is_result.js +17 -0
  119. package/script/deps/jsr.io/@wentools/result/0.1.0/src/propagate_err/index.d.ts +2 -0
  120. package/script/deps/jsr.io/@wentools/result/0.1.0/src/propagate_err/index.d.ts.map +1 -0
  121. package/script/deps/jsr.io/@wentools/result/0.1.0/src/propagate_err/index.js +5 -0
  122. package/script/deps/jsr.io/@wentools/result/0.1.0/src/propagate_err/propagate_err.d.ts +28 -0
  123. package/script/deps/jsr.io/@wentools/result/0.1.0/src/propagate_err/propagate_err.d.ts.map +1 -0
  124. package/script/deps/jsr.io/@wentools/result/0.1.0/src/propagate_err/propagate_err.js +33 -0
  125. package/script/detect_arg_conflicts/detect_arg_conflicts.d.ts +19 -0
  126. package/script/detect_arg_conflicts/detect_arg_conflicts.d.ts.map +1 -0
  127. package/script/detect_arg_conflicts/detect_arg_conflicts.js +57 -0
  128. package/script/detect_arg_conflicts/mod.d.ts +3 -0
  129. package/script/detect_arg_conflicts/mod.d.ts.map +1 -0
  130. package/script/detect_arg_conflicts/mod.js +5 -0
  131. package/script/generate_help_text/generate_help_text.d.ts +13 -0
  132. package/script/generate_help_text/generate_help_text.d.ts.map +1 -0
  133. package/script/generate_help_text/generate_help_text.js +57 -0
  134. package/script/generate_help_text/mod.d.ts +2 -0
  135. package/script/generate_help_text/mod.d.ts.map +1 -0
  136. package/script/generate_help_text/mod.js +5 -0
  137. package/script/infer_args_type.d.ts +29 -0
  138. package/script/infer_args_type.d.ts.map +1 -0
  139. package/script/infer_args_type.js +7 -0
  140. package/script/is_boolean_schema/is_boolean_schema.d.ts +12 -0
  141. package/script/is_boolean_schema/is_boolean_schema.d.ts.map +1 -0
  142. package/script/is_boolean_schema/is_boolean_schema.js +24 -0
  143. package/script/is_boolean_schema/mod.d.ts +2 -0
  144. package/script/is_boolean_schema/mod.d.ts.map +1 -0
  145. package/script/is_boolean_schema/mod.js +5 -0
  146. package/script/mod.d.ts +8 -0
  147. package/script/mod.d.ts.map +1 -0
  148. package/script/mod.js +5 -0
  149. package/script/package.json +3 -0
  150. package/script/parse_args/mod.d.ts +3 -0
  151. package/script/parse_args/mod.d.ts.map +1 -0
  152. package/script/parse_args/mod.js +5 -0
  153. package/script/parse_args/parse_args.d.ts +24 -0
  154. package/script/parse_args/parse_args.d.ts.map +1 -0
  155. package/script/parse_args/parse_args.js +92 -0
  156. package/script/run.d.ts +19 -0
  157. package/script/run.d.ts.map +1 -0
  158. package/script/run.js +189 -0
  159. package/script/validate_args/mod.d.ts +3 -0
  160. package/script/validate_args/mod.d.ts.map +1 -0
  161. package/script/validate_args/mod.js +5 -0
  162. package/script/validate_args/validate_args.d.ts +20 -0
  163. package/script/validate_args/validate_args.d.ts.map +1 -0
  164. package/script/validate_args/validate_args.js +26 -0
  165. package/script/zli.d.ts +118 -0
  166. package/script/zli.d.ts.map +1 -0
  167. package/script/zli.js +127 -0
@@ -0,0 +1 @@
1
+ export { parseArgs } from './parse_args.js';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Parse command-line arguments
3
+ *
4
+ * Takes process.argv and arg definitions, returns parsed raw values (pre-validation).
5
+ *
6
+ * Parsing rules:
7
+ * 1. Positional args fill by position (left to right)
8
+ * 2. Named flags (--name or -short) can fill any arg
9
+ * 3. Explicit (named) overrides implicit (positional)
10
+ *
11
+ * @example
12
+ * const args = [
13
+ * createPositionalArg('email', z.string(), { short: 'e' }),
14
+ * createFlagArg('verbose', z.boolean(), { short: 'v' })
15
+ * ]
16
+ * const rawValues = parseArgs(process.argv.slice(2), args)
17
+ * // rawValues = { email: 'user@example.com', verbose: true }
18
+ */
19
+ import type { Arg } from '../arg.js';
20
+ type RawValues = Record<string, unknown>;
21
+ declare const parseArgs: (argv: string[], args: readonly Arg[]) => RawValues;
22
+ export { parseArgs };
23
+ export type { RawValues };
24
+ //# sourceMappingURL=parse_args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse_args.d.ts","sourceRoot":"","sources":["../../src/parse_args/parse_args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAGpC,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAExC,QAAA,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,EAAE,MAAM,SAAS,GAAG,EAAE,KAAG,SA4EzD,CAAA;AAED,OAAO,EAAE,SAAS,EAAE,CAAA;AACpB,YAAY,EAAE,SAAS,EAAE,CAAA"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Parse command-line arguments
3
+ *
4
+ * Takes process.argv and arg definitions, returns parsed raw values (pre-validation).
5
+ *
6
+ * Parsing rules:
7
+ * 1. Positional args fill by position (left to right)
8
+ * 2. Named flags (--name or -short) can fill any arg
9
+ * 3. Explicit (named) overrides implicit (positional)
10
+ *
11
+ * @example
12
+ * const args = [
13
+ * createPositionalArg('email', z.string(), { short: 'e' }),
14
+ * createFlagArg('verbose', z.boolean(), { short: 'v' })
15
+ * ]
16
+ * const rawValues = parseArgs(process.argv.slice(2), args)
17
+ * // rawValues = { email: 'user@example.com', verbose: true }
18
+ */
19
+ import { isBooleanSchema } from '../is_boolean_schema/mod.js';
20
+ const parseArgs = (argv, args) => {
21
+ const rawValues = {};
22
+ const positionalArgs = args.filter((arg) => arg.type === 'positional');
23
+ const allArgs = args;
24
+ // Build lookup maps for quick access
25
+ const argByLongName = new Map();
26
+ const argByShortName = new Map();
27
+ for (const arg of allArgs) {
28
+ argByLongName.set(arg.name, arg);
29
+ if (arg.short) {
30
+ argByShortName.set(arg.short, arg);
31
+ }
32
+ }
33
+ let positionalIndex = 0;
34
+ for (let i = 0; i < argv.length; i++) {
35
+ const current = argv[i];
36
+ if (current === undefined)
37
+ continue;
38
+ // Long flag: --name or --name=value
39
+ if (current.startsWith('--')) {
40
+ const [flagName, ...valueParts] = current.slice(2).split('=');
41
+ if (flagName === undefined)
42
+ continue;
43
+ const arg = argByLongName.get(flagName);
44
+ if (!arg) {
45
+ // Unknown flag - skip for now (could error later)
46
+ continue;
47
+ }
48
+ if (isBooleanSchema(arg.schema)) {
49
+ rawValues[arg.name] = true;
50
+ }
51
+ else if (valueParts.length > 0) {
52
+ // --name=value format
53
+ rawValues[arg.name] = valueParts.join('=');
54
+ }
55
+ else {
56
+ // --name value format
57
+ i++;
58
+ rawValues[arg.name] = argv[i];
59
+ }
60
+ continue;
61
+ }
62
+ // Short flag: -v or -v value
63
+ if (current.startsWith('-') && current.length > 1) {
64
+ const shortName = current.slice(1);
65
+ const arg = argByShortName.get(shortName);
66
+ if (!arg) {
67
+ // Unknown flag - skip for now
68
+ continue;
69
+ }
70
+ if (isBooleanSchema(arg.schema)) {
71
+ rawValues[arg.name] = true;
72
+ }
73
+ else {
74
+ // -n value format
75
+ i++;
76
+ rawValues[arg.name] = argv[i];
77
+ }
78
+ continue;
79
+ }
80
+ // Positional value
81
+ const positionalArg = positionalArgs[positionalIndex];
82
+ if (positionalArg !== undefined) {
83
+ rawValues[positionalArg.name] = current;
84
+ positionalIndex++;
85
+ }
86
+ }
87
+ return rawValues;
88
+ };
89
+ export { parseArgs };
package/esm/run.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ import type { Command } from './create_command.js';
2
+ type CommandEntry = Command | CommandDirectory;
3
+ type CommandDirectory = {
4
+ name: string;
5
+ description?: string;
6
+ commands: Record<string, CommandEntry>;
7
+ };
8
+ type CliInput = Command | CommandDirectory;
9
+ /**
10
+ * Create a run function with explicit argv (for testing)
11
+ */
12
+ declare const createRun: (argv: string[]) => (input: CliInput) => Promise<void>;
13
+ /**
14
+ * Run a CLI command using Deno.args
15
+ */
16
+ declare const run: (input: CliInput) => Promise<void>;
17
+ export { run, createRun };
18
+ export type { CommandDirectory, CommandEntry, CliInput };
19
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAQlD,KAAK,YAAY,GAAG,OAAO,GAAG,gBAAgB,CAAA;AAG9C,KAAK,gBAAgB,GAAG;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CACtC,CAAA;AAED,KAAK,QAAQ,GAAG,OAAO,GAAG,gBAAgB,CAAA;AAO1C;;GAEG;AACH,QAAA,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,aACE,QAAQ,KAAG,OAAO,CAAC,IAAI,CA+IzD,CAAA;AAED;;GAEG;AACH,QAAA,MAAM,GAAG,GAAU,OAAO,QAAQ,KAAG,OAAO,CAAC,IAAI,CAGhD,CAAA;AAED,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAA;AACzB,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAA"}
package/esm/run.js ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Run a command or multi-command CLI
3
+ *
4
+ * This is the main entry point that:
5
+ * 1. Detects if help is requested
6
+ * 2. Parses arguments
7
+ * 3. Validates against schemas
8
+ * 4. Executes handler
9
+ */
10
+ import * as dntShim from "./_dnt.shims.js";
11
+ import { parseArgs } from './parse_args/mod.js';
12
+ import { validateArgs } from './validate_args/mod.js';
13
+ import { detectArgConflicts } from './detect_arg_conflicts/mod.js';
14
+ import { generateHelpText } from './generate_help_text/mod.js';
15
+ import { isResult } from './deps/jsr.io/@wentools/result/0.1.0/src/index.js';
16
+ // Type guard - check if entry is a directory
17
+ const isCommandDirectory = (input) => {
18
+ return 'commands' in input;
19
+ };
20
+ /**
21
+ * Create a run function with explicit argv (for testing)
22
+ */
23
+ const createRun = (argv) => {
24
+ const runWithArgs = async (input) => {
25
+ if (isCommandDirectory(input)) {
26
+ await runCommandDirectory(input, argv, []);
27
+ }
28
+ else {
29
+ // Single command mode
30
+ const command = input;
31
+ // Check for help
32
+ if (argv[0] === '--help' || argv[0] === '-h') {
33
+ console.log(generateHelpText(command));
34
+ return;
35
+ }
36
+ await runSingleCommand(command, argv);
37
+ }
38
+ };
39
+ const runCommandDirectory = async (dir, args, commandPath) => {
40
+ // Build full path
41
+ const fullPath = [...commandPath, dir.name];
42
+ // Help handling
43
+ if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
44
+ showCommandDirectoryHelp(dir, fullPath);
45
+ return;
46
+ }
47
+ // Lookup subcommand
48
+ const subcommandName = args[0];
49
+ if (subcommandName === undefined) {
50
+ showCommandDirectoryHelp(dir, fullPath);
51
+ return;
52
+ }
53
+ const entry = dir.commands[subcommandName];
54
+ if (!entry) {
55
+ console.error(`❌ Unknown command: ${[...fullPath, subcommandName].join(' ')}`);
56
+ console.error(`\nAvailable commands: ${Object.keys(dir.commands).join(', ')}`);
57
+ dntShim.Deno.exit(1);
58
+ }
59
+ // Recurse or execute
60
+ if (isCommandDirectory(entry)) {
61
+ // Nested directory - recurse!
62
+ await runCommandDirectory(entry, args.slice(1), fullPath);
63
+ }
64
+ else {
65
+ // Leaf command - execute
66
+ const cmdPath = [...fullPath, subcommandName].join(' ');
67
+ // Check for command-specific help
68
+ if (args[1] === '--help' || args[1] === '-h') {
69
+ console.log(generateHelpText(entry, cmdPath));
70
+ return;
71
+ }
72
+ await runSingleCommand(entry, args.slice(1));
73
+ }
74
+ };
75
+ const showCommandDirectoryHelp = (dir, commandPath) => {
76
+ const pathStr = commandPath.join(' ');
77
+ console.log(`${dir.description || dir.name}\n`);
78
+ console.log('Commands:');
79
+ // Group and display commands
80
+ const entries = Object.entries(dir.commands);
81
+ const maxNameLength = Math.max(...entries.map(([name]) => name.length));
82
+ for (const [name, entry] of entries) {
83
+ const padding = ' '.repeat(maxNameLength - name.length + 2);
84
+ const indicator = isCommandDirectory(entry) ? '→ ' : ' ';
85
+ const desc = entry.description || '';
86
+ console.log(` ${name}${padding}${indicator}${desc}`);
87
+ }
88
+ console.log(`\nUse '${pathStr} <command> --help' for command-specific help`);
89
+ };
90
+ const runSingleCommand = async (command, args) => {
91
+ // Check for conflicts
92
+ const conflicts = detectArgConflicts(command.args);
93
+ if (conflicts.length > 0) {
94
+ console.error('❌ Argument configuration error:');
95
+ for (const conflict of conflicts) {
96
+ if (conflict.type === 'duplicate_name') {
97
+ console.error(` Duplicate argument name: ${conflict.name}`);
98
+ }
99
+ else {
100
+ console.error(` Duplicate short flag: -${conflict.name} used by ${conflict.conflictingArgs.join(', ')}`);
101
+ }
102
+ }
103
+ dntShim.Deno.exit(1);
104
+ }
105
+ // Parse arguments
106
+ const rawValues = parseArgs(args, command.args);
107
+ // Validate arguments
108
+ const validatedResult = validateArgs(rawValues, command.args);
109
+ if (validatedResult.isErr()) {
110
+ const { argName, zodError } = validatedResult.error;
111
+ console.error(`❌ Validation error for argument '${argName}':`);
112
+ zodError.issues.forEach((issue) => {
113
+ console.error(` ${issue.path.join('.')}: ${issue.message}`);
114
+ });
115
+ dntShim.Deno.exit(1);
116
+ }
117
+ // Safe: isErr() checked above, Deno.exit() terminates
118
+ const validatedValues = validatedResult._unsafeUnwrap();
119
+ // Execute handler
120
+ try {
121
+ const result = await command.handler(validatedValues);
122
+ // Check if handler returned a Result type
123
+ if (isResult(result)) {
124
+ if (result.isErr()) {
125
+ const error = result.error;
126
+ console.error('❌ Command failed:');
127
+ if (error && typeof error === 'object') {
128
+ console.error(JSON.stringify(error, null, 2));
129
+ }
130
+ else {
131
+ console.error(String(error));
132
+ }
133
+ dntShim.Deno.exit(1);
134
+ }
135
+ // ok() - just return, script ends normally
136
+ }
137
+ }
138
+ catch (error) {
139
+ console.error('❌ Command execution failed:', error);
140
+ dntShim.Deno.exit(1);
141
+ }
142
+ };
143
+ return runWithArgs;
144
+ };
145
+ /**
146
+ * Run a CLI command using Deno.args
147
+ */
148
+ const run = async (input) => {
149
+ const runWithArgs = createRun(dntShim.Deno.args);
150
+ await runWithArgs(input);
151
+ };
152
+ export { run, createRun };
@@ -0,0 +1,3 @@
1
+ export { validateArgs } from './validate_args.js';
2
+ export type { ValidationError, ValidatedValues } from './validate_args.js';
3
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/validate_args/mod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1 @@
1
+ export { validateArgs } from './validate_args.js';
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Validate parsed argument values against Zod schemas
3
+ *
4
+ * Takes raw parsed values and arg definitions, validates each value,
5
+ * returns validated & typed values or validation errors.
6
+ */
7
+ import type { Arg } from '../arg.js';
8
+ import type { RawValues } from '../parse_args/mod.js';
9
+ import { type Result } from '../deps/jsr.io/@wentools/result/0.1.0/src/index.js';
10
+ import type { ZodError } from 'zod';
11
+ type ValidationError = {
12
+ type: 'validation_error';
13
+ argName: string;
14
+ zodError: ZodError;
15
+ };
16
+ type ValidatedValues = Record<string, unknown>;
17
+ declare const validateArgs: (rawValues: RawValues, args: readonly Arg[]) => Result<ValidatedValues, ValidationError>;
18
+ export { validateArgs };
19
+ export type { ValidationError, ValidatedValues };
20
+ //# sourceMappingURL=validate_args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate_args.d.ts","sourceRoot":"","sources":["../../src/validate_args/validate_args.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,oDAAoD,CAAA;AACzF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAA;AAEnC,KAAK,eAAe,GAAG;IACtB,IAAI,EAAE,kBAAkB,CAAA;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,QAAQ,CAAA;CAClB,CAAA;AAED,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAE9C,QAAA,MAAM,YAAY,GACjB,WAAW,SAAS,EACpB,MAAM,SAAS,GAAG,EAAE,KAClB,MAAM,CAAC,eAAe,EAAE,eAAe,CAkBzC,CAAA;AAED,OAAO,EAAE,YAAY,EAAE,CAAA;AACvB,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,CAAA"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Validate parsed argument values against Zod schemas
3
+ *
4
+ * Takes raw parsed values and arg definitions, validates each value,
5
+ * returns validated & typed values or validation errors.
6
+ */
7
+ import { err, ok } from '../deps/jsr.io/@wentools/result/0.1.0/src/index.js';
8
+ const validateArgs = (rawValues, args) => {
9
+ const validated = {};
10
+ for (const arg of args) {
11
+ const rawValue = rawValues[arg.name];
12
+ const result = arg.schema.safeParse(rawValue);
13
+ if (!result.success) {
14
+ return err('validation_error', `Validation failed for argument: ${arg.name}`, {
15
+ argName: arg.name,
16
+ zodError: result.error,
17
+ });
18
+ }
19
+ validated[arg.name] = result.data;
20
+ }
21
+ return ok(validated);
22
+ };
23
+ export { validateArgs };
package/esm/zli.d.ts ADDED
@@ -0,0 +1,118 @@
1
+ /**
2
+ * ZLI - Lightweight CLI builder with Zod validation
3
+ *
4
+ * A minimal, type-safe CLI argument parser built on Zod.
5
+ * Zero dependencies beyond Zod (already in project).
6
+ *
7
+ * ## Goals
8
+ *
9
+ * - Type-safe arguments inferred from Zod schemas
10
+ * - Flexible parsing: positional args by order OR by --name
11
+ * - Short flags: --verbose or -v
12
+ * - Copy-paste friendly: easy to expand from simple to multi-command scripts
13
+ * - Auto-generated help text
14
+ * - Pretty validation error messages
15
+ * - Conflict detection (duplicate names/shorts)
16
+ *
17
+ * ## API
18
+ *
19
+ * - `zli.p(name, schema, options?)` - Create positional argument
20
+ * - `zli.f(name, schema, options?)` - Create flag argument
21
+ * - `zli.c(args, handler, options?)` - Create command
22
+ * - `zli.d(name, options)` - Create command directory
23
+ * - `zli.run(command | multiCommand)` - Execute CLI
24
+ *
25
+ * ## Usage - Simple Single Command
26
+ *
27
+ * ```typescript
28
+ * import { zli } from '@wentools/zli'
29
+ * import { z } from 'zod'
30
+ *
31
+ * const command = zli.c(
32
+ * [
33
+ * zli.p('email', z.string().email(), {
34
+ * description: 'User email address',
35
+ * short: 'e'
36
+ * }),
37
+ * zli.f('verbose', z.boolean(), {
38
+ * description: 'Verbose output',
39
+ * short: 'v'
40
+ * })
41
+ * ],
42
+ * (args) => {
43
+ * console.log(args.email) // typed as string
44
+ * console.log(args.verbose) // typed as boolean | undefined
45
+ * },
46
+ * { description: 'Check user permissions' }
47
+ * )
48
+ *
49
+ * zli.run(command)
50
+ * ```
51
+ *
52
+ * **Invocation:**
53
+ * ```bash
54
+ * # Positional
55
+ * pnpm exec tsx --env-file=.env script.ts user@example.com
56
+ *
57
+ * # Named
58
+ * pnpm exec tsx --env-file=.env script.ts --email user@example.com
59
+ *
60
+ * # Short flag
61
+ * pnpm exec tsx --env-file=.env script.ts -e user@example.com
62
+ *
63
+ * # With flags
64
+ * pnpm exec tsx --env-file=.env script.ts user@example.com --verbose
65
+ * pnpm exec tsx --env-file=.env script.ts user@example.com -v
66
+ *
67
+ * # Help
68
+ * pnpm exec tsx --env-file=.env script.ts --help
69
+ * ```
70
+ *
71
+ * ## Usage - Multi-Command Script
72
+ *
73
+ * ```typescript
74
+ * import { zli } from '@wentools/zli'
75
+ * import { z } from 'zod'
76
+ *
77
+ * const checkPermissions = zli.c(
78
+ * [
79
+ * zli.p('email', z.string().email(), { description: 'User email' }),
80
+ * zli.f('verbose', z.boolean(), { description: 'Verbose output', short: 'v' })
81
+ * ],
82
+ * (args) => {
83
+ * console.log(`Checking permissions for ${args.email}`)
84
+ * },
85
+ * { description: 'Check user permissions' }
86
+ * )
87
+ *
88
+ * const promote = zli.c(
89
+ * [
90
+ * zli.p('email', z.string().email(), { description: 'User email' })
91
+ * ],
92
+ * async (args) => {
93
+ * console.log(`Promoting ${args.email} to admin`)
94
+ * },
95
+ * { description: 'Promote user to admin' }
96
+ * )
97
+ *
98
+ * zli.run({
99
+ * name: 'user',
100
+ * description: 'User management commands',
101
+ * commands: {
102
+ * 'check-permissions': checkPermissions,
103
+ * 'promote': promote
104
+ * }
105
+ * })
106
+ * ```
107
+ */
108
+ declare const zli: {
109
+ p: <TSchema extends import("zod").ZodType>(name: string, schema: TSchema, options?: import("./create_positional_arg.js").PositionalArgOptions) => import("./create_positional_arg.js").PositionalArg<TSchema>;
110
+ f: <TSchema extends import("zod").ZodType>(name: string, schema: TSchema, options?: import("./create_flag_arg.js").FlagArgOptions) => import("./create_flag_arg.js").FlagArg<TSchema>;
111
+ c: <const TArgs extends readonly import("./arg.js").Arg[]>(args: TArgs, handler: import("./create_command.js").CommandHandler<import("./infer_args_type.js").InferArgsType<TArgs>>, options?: import("./create_command.js").CommandOptions) => import("./create_command.js").Command<TArgs>;
112
+ d: <const TCommands extends Record<string, import("./run.js").CommandEntry>>(name: string, options: import("./create_command_directory.js").CommandDirectoryOptions & {
113
+ commands: TCommands;
114
+ }) => import("./create_command_directory.js").CommandDirectory;
115
+ run: (input: import("./run.js").CliInput) => Promise<void>;
116
+ };
117
+ export { zli };
118
+ //# sourceMappingURL=zli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zli.d.ts","sourceRoot":"","sources":["../src/zli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0GG;AAaH,QAAA,MAAM,GAAG;;;;;;;;CAMR,CAAA;AAED,OAAO,EAAE,GAAG,EAAE,CAAA"}
package/esm/zli.js ADDED
@@ -0,0 +1,124 @@
1
+ /**
2
+ * ZLI - Lightweight CLI builder with Zod validation
3
+ *
4
+ * A minimal, type-safe CLI argument parser built on Zod.
5
+ * Zero dependencies beyond Zod (already in project).
6
+ *
7
+ * ## Goals
8
+ *
9
+ * - Type-safe arguments inferred from Zod schemas
10
+ * - Flexible parsing: positional args by order OR by --name
11
+ * - Short flags: --verbose or -v
12
+ * - Copy-paste friendly: easy to expand from simple to multi-command scripts
13
+ * - Auto-generated help text
14
+ * - Pretty validation error messages
15
+ * - Conflict detection (duplicate names/shorts)
16
+ *
17
+ * ## API
18
+ *
19
+ * - `zli.p(name, schema, options?)` - Create positional argument
20
+ * - `zli.f(name, schema, options?)` - Create flag argument
21
+ * - `zli.c(args, handler, options?)` - Create command
22
+ * - `zli.d(name, options)` - Create command directory
23
+ * - `zli.run(command | multiCommand)` - Execute CLI
24
+ *
25
+ * ## Usage - Simple Single Command
26
+ *
27
+ * ```typescript
28
+ * import { zli } from '@wentools/zli'
29
+ * import { z } from 'zod'
30
+ *
31
+ * const command = zli.c(
32
+ * [
33
+ * zli.p('email', z.string().email(), {
34
+ * description: 'User email address',
35
+ * short: 'e'
36
+ * }),
37
+ * zli.f('verbose', z.boolean(), {
38
+ * description: 'Verbose output',
39
+ * short: 'v'
40
+ * })
41
+ * ],
42
+ * (args) => {
43
+ * console.log(args.email) // typed as string
44
+ * console.log(args.verbose) // typed as boolean | undefined
45
+ * },
46
+ * { description: 'Check user permissions' }
47
+ * )
48
+ *
49
+ * zli.run(command)
50
+ * ```
51
+ *
52
+ * **Invocation:**
53
+ * ```bash
54
+ * # Positional
55
+ * pnpm exec tsx --env-file=.env script.ts user@example.com
56
+ *
57
+ * # Named
58
+ * pnpm exec tsx --env-file=.env script.ts --email user@example.com
59
+ *
60
+ * # Short flag
61
+ * pnpm exec tsx --env-file=.env script.ts -e user@example.com
62
+ *
63
+ * # With flags
64
+ * pnpm exec tsx --env-file=.env script.ts user@example.com --verbose
65
+ * pnpm exec tsx --env-file=.env script.ts user@example.com -v
66
+ *
67
+ * # Help
68
+ * pnpm exec tsx --env-file=.env script.ts --help
69
+ * ```
70
+ *
71
+ * ## Usage - Multi-Command Script
72
+ *
73
+ * ```typescript
74
+ * import { zli } from '@wentools/zli'
75
+ * import { z } from 'zod'
76
+ *
77
+ * const checkPermissions = zli.c(
78
+ * [
79
+ * zli.p('email', z.string().email(), { description: 'User email' }),
80
+ * zli.f('verbose', z.boolean(), { description: 'Verbose output', short: 'v' })
81
+ * ],
82
+ * (args) => {
83
+ * console.log(`Checking permissions for ${args.email}`)
84
+ * },
85
+ * { description: 'Check user permissions' }
86
+ * )
87
+ *
88
+ * const promote = zli.c(
89
+ * [
90
+ * zli.p('email', z.string().email(), { description: 'User email' })
91
+ * ],
92
+ * async (args) => {
93
+ * console.log(`Promoting ${args.email} to admin`)
94
+ * },
95
+ * { description: 'Promote user to admin' }
96
+ * )
97
+ *
98
+ * zli.run({
99
+ * name: 'user',
100
+ * description: 'User management commands',
101
+ * commands: {
102
+ * 'check-permissions': checkPermissions,
103
+ * 'promote': promote
104
+ * }
105
+ * })
106
+ * ```
107
+ */
108
+ import { createPositionalArg } from './create_positional_arg.js';
109
+ import { createFlagArg } from './create_flag_arg.js';
110
+ import { createCommand } from './create_command.js';
111
+ import { createCommandDirectory } from './create_command_directory.js';
112
+ import { run } from './run.js';
113
+ const p = createPositionalArg;
114
+ const f = createFlagArg;
115
+ const c = createCommand;
116
+ const d = createCommandDirectory;
117
+ const zli = {
118
+ p,
119
+ f,
120
+ c,
121
+ d,
122
+ run,
123
+ };
124
+ export { zli };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@wentools/zli",
3
+ "version": "0.2.0-beta.2dc33a43",
4
+ "description": "Lightweight CLI builder with Zod validation and type-safe argument parsing",
5
+ "keywords": [
6
+ "cli",
7
+ "command-line",
8
+ "zod",
9
+ "typescript",
10
+ "type-safe",
11
+ "argument-parser"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://gitlab.com/wentools/zli"
16
+ },
17
+ "license": "MIT",
18
+ "main": "./script/mod.js",
19
+ "module": "./esm/mod.js",
20
+ "exports": {
21
+ ".": {
22
+ "import": "./esm/mod.js",
23
+ "require": "./script/mod.js"
24
+ }
25
+ },
26
+ "scripts": {},
27
+ "dependencies": {
28
+ "neverthrow": "^8.2.0",
29
+ "zod": "^4.1.0",
30
+ "@deno/shim-deno": "~0.18.0"
31
+ },
32
+ "peerDependencies": {
33
+ "zod": "^4.1.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^20.9.0"
37
+ },
38
+ "_generatedBy": "dnt@dev"
39
+ }
@@ -0,0 +1,6 @@
1
+ import { Deno } from "@deno/shim-deno";
2
+ export { Deno } from "@deno/shim-deno";
3
+ export declare const dntGlobalThis: Omit<typeof globalThis, "Deno"> & {
4
+ Deno: typeof Deno;
5
+ };
6
+ //# sourceMappingURL=_dnt.shims.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_dnt.shims.d.ts","sourceRoot":"","sources":["../src/_dnt.shims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAKvC,eAAO,MAAM,aAAa;;CAA2C,CAAC"}