@shell-shock/core 0.17.5 → 0.17.6

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 (73) hide show
  1. package/dist/components/command-validation-logic.cjs +214 -152
  2. package/dist/components/command-validation-logic.mjs +213 -152
  3. package/dist/components/command-validation-logic.mjs.map +1 -1
  4. package/dist/components/docs.cjs +113 -9
  5. package/dist/components/docs.mjs +109 -9
  6. package/dist/components/docs.mjs.map +1 -1
  7. package/dist/components/exec-builtin.cjs +36 -1
  8. package/dist/components/exec-builtin.d.cts.map +1 -1
  9. package/dist/components/exec-builtin.d.mts.map +1 -1
  10. package/dist/components/exec-builtin.mjs +35 -1
  11. package/dist/components/exec-builtin.mjs.map +1 -1
  12. package/dist/components/helpers.cjs +51 -2
  13. package/dist/components/helpers.mjs +50 -2
  14. package/dist/components/helpers.mjs.map +1 -1
  15. package/dist/components/index.cjs +17 -1
  16. package/dist/components/index.mjs +9 -9
  17. package/dist/components/options-parser-logic.cjs +411 -174
  18. package/dist/components/options-parser-logic.d.cts.map +1 -1
  19. package/dist/components/options-parser-logic.d.mts.map +1 -1
  20. package/dist/components/options-parser-logic.mjs +405 -174
  21. package/dist/components/options-parser-logic.mjs.map +1 -1
  22. package/dist/components/state-builtin.cjs +61 -5
  23. package/dist/components/state-builtin.mjs +60 -5
  24. package/dist/components/state-builtin.mjs.map +1 -1
  25. package/dist/components/usage.cjs +46 -3
  26. package/dist/components/usage.mjs +45 -3
  27. package/dist/components/usage.mjs.map +1 -1
  28. package/dist/components/utils-builtin.cjs +68 -3
  29. package/dist/components/utils-builtin.mjs +67 -3
  30. package/dist/components/utils-builtin.mjs.map +1 -1
  31. package/dist/helpers/automd.cjs +28 -13
  32. package/dist/helpers/automd.mjs +28 -13
  33. package/dist/helpers/automd.mjs.map +1 -1
  34. package/dist/index.cjs +11 -0
  35. package/dist/index.d.cts +2 -2
  36. package/dist/index.d.mts +2 -2
  37. package/dist/index.mjs +2 -2
  38. package/dist/plugin-utils/compute-bin.cjs +50 -0
  39. package/dist/plugin-utils/compute-bin.d.cts +13 -0
  40. package/dist/plugin-utils/compute-bin.d.cts.map +1 -0
  41. package/dist/plugin-utils/compute-bin.d.mts +13 -0
  42. package/dist/plugin-utils/compute-bin.d.mts.map +1 -0
  43. package/dist/plugin-utils/compute-bin.mjs +50 -0
  44. package/dist/plugin-utils/compute-bin.mjs.map +1 -0
  45. package/dist/plugin-utils/get-command-tree.cjs +50 -0
  46. package/dist/plugin-utils/get-command-tree.d.cts +15 -1
  47. package/dist/plugin-utils/get-command-tree.d.cts.map +1 -1
  48. package/dist/plugin-utils/get-command-tree.d.mts +15 -1
  49. package/dist/plugin-utils/get-command-tree.d.mts.map +1 -1
  50. package/dist/plugin-utils/get-command-tree.mjs +49 -1
  51. package/dist/plugin-utils/get-command-tree.mjs.map +1 -1
  52. package/dist/plugin-utils/index.cjs +4 -0
  53. package/dist/plugin-utils/index.d.cts +3 -2
  54. package/dist/plugin-utils/index.d.mts +3 -2
  55. package/dist/plugin-utils/index.mjs +3 -2
  56. package/dist/plugin.cjs +170 -52
  57. package/dist/plugin.mjs +170 -52
  58. package/dist/plugin.mjs.map +1 -1
  59. package/dist/resolver/deepkit.cjs +1 -1
  60. package/dist/resolver/deepkit.mjs +1 -1
  61. package/dist/resolver/deepkit.mjs.map +1 -1
  62. package/dist/types/command.cjs +120 -10
  63. package/dist/types/command.d.cts +95 -8
  64. package/dist/types/command.d.cts.map +1 -1
  65. package/dist/types/command.d.mts +95 -8
  66. package/dist/types/command.d.mts.map +1 -1
  67. package/dist/types/command.mjs +109 -10
  68. package/dist/types/command.mjs.map +1 -1
  69. package/dist/types/index.cjs +12 -1
  70. package/dist/types/index.d.cts +2 -2
  71. package/dist/types/index.d.mts +2 -2
  72. package/dist/types/index.mjs +2 -2
  73. package/package.json +10 -10
package/dist/plugin.mjs CHANGED
@@ -35,17 +35,21 @@ import { defu } from "defu";
35
35
  import { resolveInputs } from "powerlines/utils";
36
36
 
37
37
  //#region src/plugin.tsx
38
+ function __assignType(fn, args) {
39
+ fn.__type = args;
40
+ return fn;
41
+ }
38
42
  const MAX_DEPTH = 50;
39
43
  /**
40
44
  * The core Powerlines plugin to build Shell Shock projects.
41
45
  */
42
- const plugin = (options = {}) => {
46
+ const plugin = __assignType((options = {}) => {
43
47
  return [
44
- tsdown(),
45
- automd(),
48
+ (tsdown.Ω = [["Context", "\"w!"]], tsdown()),
49
+ (automd.Ω = [["Context", "\"w!"]], automd()),
46
50
  {
47
51
  name: "shell-shock:config",
48
- async config() {
52
+ config: __assignType(async function config() {
49
53
  this.debug("Resolving the Shell Shock configuration.");
50
54
  await updatePackageJsonBinary(this);
51
55
  return defu({ output: { path: joinPaths(this.config.root, "dist") } }, options, {
@@ -71,7 +75,7 @@ const plugin = (options = {}) => {
71
75
  unbundle: false
72
76
  }
73
77
  });
74
- },
78
+ }, ["config", "P\"/!"]),
75
79
  configResolved: {
76
80
  order: "pre",
77
81
  async handler() {
@@ -100,19 +104,23 @@ const plugin = (options = {}) => {
100
104
  alias: [],
101
105
  isVirtual: false
102
106
  }));
103
- this.options = this.options.map((option) => ({
107
+ this.options = this.options.map(__assignType((option) => ({
104
108
  ...option,
105
109
  name: camelCase(option.name),
106
110
  alias: option.alias ?? [],
107
111
  optional: option.optional ?? false
108
- }));
112
+ }), [
113
+ "option",
114
+ "",
115
+ "P\"2!\"/\""
116
+ ]));
109
117
  }
110
118
  }
111
119
  },
112
- ...nodejs(defu(options ?? {}, { env: {
120
+ ...(nodejs.Ω = [["Context", "\"w!"]], nodejs(defu(options ?? {}, { env: {
113
121
  types: "@shell-shock/core/types/env#ShellShockEnv",
114
122
  validate: false
115
- } })),
123
+ } }))),
116
124
  {
117
125
  name: "shell-shock:inputs",
118
126
  async configResolved() {
@@ -122,17 +130,34 @@ const plugin = (options = {}) => {
122
130
  this.debug(`Resolved commands root path: ${this.commandsPath}`);
123
131
  const inputs = await resolveInputs(this, this.config.input);
124
132
  this.debug(`Found ${inputs.length} entry points specified in the configuration options.`);
125
- this.inputs = inputs.reduce((ret, entry) => {
133
+ this.inputs = inputs.reduce(__assignType((ret, entry) => {
126
134
  if (entry.file !== this.commandsPath && !isParentPath(entry.file, this.commandsPath)) throw new Error(`Command entry point "${entry.file}" is not located within the commands root "${this.commandsPath}". Please ensure that all command entry points are located within the current project.`);
127
135
  const id = resolveCommandId(this, entry.file);
128
- if (!ret.some((existing) => existing.id === id)) {
136
+ if (!ret.some(__assignType((existing) => existing.id === id, [
137
+ "existing",
138
+ "",
139
+ "P\"2!\"/\""
140
+ ]))) {
129
141
  const name = resolveCommandName(entry.file);
130
142
  let segments = resolveCommandPath(this, entry.file).split("/").filter(Boolean);
131
- segments = segments.map((segment, index) => {
132
- const found = segments.findIndex((existing) => existing === segment);
133
- if (found !== -1 && found !== index) segment += `_${segments.filter((segment) => isDynamicPathSegment(segment) && getDynamicPathSegmentName(segment).replace(/_\d+$/, "") === segment).length}`;
143
+ segments = segments.map(__assignType((segment, index) => {
144
+ const found = segments.findIndex(__assignType((existing) => existing === segment, [
145
+ "existing",
146
+ "",
147
+ "P\"2!\"/\""
148
+ ]));
149
+ if (found !== -1 && found !== index) segment += `_${segments.filter(__assignType((segment) => isDynamicPathSegment(segment) && getDynamicPathSegmentName(segment).replace(/_\d+$/, "") === segment, [
150
+ "segment",
151
+ "",
152
+ "P\"2!\"/\""
153
+ ])).length}`;
134
154
  return segment;
135
- });
155
+ }, [
156
+ "segment",
157
+ "index",
158
+ "",
159
+ "P\"2!\"2\"\"/#"
160
+ ]));
136
161
  ret.push({
137
162
  id,
138
163
  path: segments.join("/"),
@@ -154,17 +179,26 @@ const plugin = (options = {}) => {
154
179
  });
155
180
  }
156
181
  return ret;
157
- }, this.inputs);
158
- this.debug(`Shell Shock will process ${this.inputs.length} command entry files: \n${this.inputs.map((command) => ` - ${command.id}: ${replacePath(command.entry.file, this.commandsPath)}`).join("\n")}`);
182
+ }, [
183
+ "ret",
184
+ "entry",
185
+ "",
186
+ "P\"2!\"2\"\"/#"
187
+ ]), this.inputs);
188
+ this.debug(`Shell Shock will process ${this.inputs.length} command entry files: \n${this.inputs.map(__assignType((command) => ` - ${command.id}: ${replacePath(command.entry.file, this.commandsPath)}`, [
189
+ "command",
190
+ "",
191
+ "P\"2!\"/\""
192
+ ])).join("\n")}`);
159
193
  },
160
- async prepare() {
194
+ prepare: __assignType(async function prepare() {
161
195
  this.debug("Rendering base built-in modules for the Shell Shock application.");
162
196
  return render(this, [
163
197
  createComponent(StateBuiltin, {}),
164
198
  createComponent(UtilsBuiltin, {}),
165
199
  createComponent(ExecBuiltin, {})
166
200
  ]);
167
- }
201
+ }, ["prepare", "P\"/!"])
168
202
  },
169
203
  {
170
204
  name: "shell-shock:virtual-inputs",
@@ -174,22 +208,43 @@ const plugin = (options = {}) => {
174
208
  if (this.inputs.length === 0) this.warn("No commands were found in the project. Please ensure at least one command exists.");
175
209
  else {
176
210
  this.debug("Finding and adding virtual command inputs for each command previously found.");
177
- this.inputs = this.inputs.reduce((ret, command) => {
211
+ this.inputs = this.inputs.reduce(__assignType((ret, command) => {
178
212
  let depth = 0;
179
213
  let parentPath = resolveParentPath(findFilePath(command.entry.file));
180
214
  if (isParentPath(parentPath, this.commandsPath)) while (parentPath !== this.commandsPath) {
181
215
  if (depth++ > MAX_DEPTH) throw new Error(`Unable to process virtual commands for ${command.name} \n\nPlease ensure ${command.entry.file} is a valid command entry file and does not have an invalid path.`);
182
- if (!ret.some((existing) => findFilePath(existing.entry.file) === parentPath)) {
216
+ if (!ret.some(__assignType((existing) => findFilePath(existing.entry.file) === parentPath, [
217
+ "existing",
218
+ "",
219
+ "P\"2!\"/\""
220
+ ]))) {
183
221
  const file = joinPaths(parentPath, "command.ts");
184
222
  const id = resolveCommandId(this, file);
185
- if (!ret.some((existing) => existing.id === id)) {
223
+ if (!ret.some(__assignType((existing) => existing.id === id, [
224
+ "existing",
225
+ "",
226
+ "P\"2!\"/\""
227
+ ]))) {
186
228
  const name = resolveCommandName(file);
187
229
  let segments = resolveCommandPath(this, file).split("/").filter(Boolean);
188
- segments = segments.map((segment, index) => {
189
- const found = segments.findIndex((existing) => existing === segment);
190
- if (found !== -1 && found !== index) segment += `_${segments.filter((segment) => isDynamicPathSegment(segment) && getDynamicPathSegmentName(segment).replace(/_\d+$/, "") === segment).length}`;
230
+ segments = segments.map(__assignType((segment, index) => {
231
+ const found = segments.findIndex(__assignType((existing) => existing === segment, [
232
+ "existing",
233
+ "",
234
+ "P\"2!\"/\""
235
+ ]));
236
+ if (found !== -1 && found !== index) segment += `_${segments.filter(__assignType((segment) => isDynamicPathSegment(segment) && getDynamicPathSegmentName(segment).replace(/_\d+$/, "") === segment, [
237
+ "segment",
238
+ "",
239
+ "P\"2!\"/\""
240
+ ])).length}`;
191
241
  return segment;
192
- });
242
+ }, [
243
+ "segment",
244
+ "index",
245
+ "",
246
+ "P\"2!\"2\"\"/#"
247
+ ]));
193
248
  ret.push({
194
249
  id,
195
250
  path: segments.join("/"),
@@ -206,8 +261,22 @@ const plugin = (options = {}) => {
206
261
  parentPath = resolveParentPath(parentPath);
207
262
  }
208
263
  return ret;
209
- }, this.inputs).sort((a, b) => a.segments.length - b.segments.length);
210
- this.debug(`Final command input list: \n${this.inputs.map((command) => ` - ${command.id}${command.isVirtual ? " (virtual)" : ""}: ${command.source === "file" ? replacePath(command.entry.file, this.commandsPath) : `added by ${command.source}`}`).join("\n")}`);
264
+ }, [
265
+ "ret",
266
+ "command",
267
+ "",
268
+ "P\"2!\"2\"\"/#"
269
+ ]), this.inputs).sort(__assignType((a, b) => a.segments.length - b.segments.length, [
270
+ "a",
271
+ "b",
272
+ "",
273
+ "P\"2!\"2\"\"/#"
274
+ ]));
275
+ this.debug(`Final command input list: \n${this.inputs.map(__assignType((command) => ` - ${command.id}${command.isVirtual ? " (virtual)" : ""}: ${command.source === "file" ? replacePath(command.entry.file, this.commandsPath) : `added by ${command.source}`}`, [
276
+ "command",
277
+ "",
278
+ "P\"2!\"/\""
279
+ ])).join("\n")}`);
211
280
  }
212
281
  }
213
282
  }
@@ -223,30 +292,54 @@ const plugin = (options = {}) => {
223
292
  this.debug(`Skipping command resolution as the meta checksum has not changed.`);
224
293
  await readCommandsPersistence(this);
225
294
  } else {
226
- for (const input of this.inputs.filter((input) => input.segments.filter((segment) => !isDynamicPathSegment(segment) && !isPathSegmentGroup(segment)).length === 1)) this.commands[input.name] = await resolve({
295
+ for (const input of this.inputs.filter(__assignType((input) => input.segments.filter(__assignType((segment) => !isDynamicPathSegment(segment) && !isPathSegmentGroup(segment), [
296
+ "segment",
297
+ "",
298
+ "P\"2!\"/\""
299
+ ])).length === 1, [
300
+ "input",
301
+ "",
302
+ "P\"2!\"/\""
303
+ ]))) this.commands[input.name] = await resolve({
227
304
  context: this,
228
305
  command: input
229
306
  });
230
307
  this.debug("Post-processing commands to ensure proper reflection.");
231
- await traverseCommands(this, (command) => {
232
- command.options = Object.fromEntries(Object.entries(command.options).map(([name, option]) => [camelCase(name), {
308
+ await traverseCommands(this, __assignType((command) => {
309
+ command.options = Object.fromEntries(Object.entries(command.options).map(__assignType(([name, option]) => [camelCase(name), {
233
310
  ...option,
234
311
  name: camelCase(name),
235
312
  alias: option.alias ?? [],
236
313
  optional: option.optional ?? false
237
- }]));
238
- });
314
+ }], [
315
+ "param0",
316
+ "",
317
+ "P\"2!\"/\""
318
+ ])));
319
+ }, [
320
+ "command",
321
+ "",
322
+ "P\"2!\"/\""
323
+ ]));
239
324
  await writeCommandsPersistence(this);
240
325
  }
241
326
  this.debug("Validating the CLI applications command tree.");
242
327
  let isValid = true;
243
- await traverseCommands(this, (command) => {
328
+ await traverseCommands(this, __assignType((command) => {
244
329
  const failures = validateCommand(command);
245
330
  if (failures.length > 0) {
246
- this.error(`Found ${failures.length} issue${failures.length > 1 ? "s" : ""} with the ${command.title} command: \n${failures.map((failure) => ` - ${failure.code}: ${failure.details}`).join("\n")}\n`);
331
+ this.error(`Found ${failures.length} issue${failures.length > 1 ? "s" : ""} with the ${command.title} command: \n${failures.map(__assignType((failure) => ` - ${failure.code}: ${failure.details}`, [
332
+ "failure",
333
+ "",
334
+ "P\"2!\"/\""
335
+ ])).join("\n")}\n`);
247
336
  isValid = false;
248
337
  }
249
- });
338
+ }, [
339
+ "command",
340
+ "",
341
+ "P\"2!\"/\""
342
+ ]));
250
343
  if (!isValid) throw new Error(`One or more commands in the command tree are invalid. Please review the errors above and correct them before proceeding.`);
251
344
  this.info(`\nCreating an application with the following command tree: \n${formatCommandTree(this)}\n`);
252
345
  }
@@ -256,8 +349,8 @@ const plugin = (options = {}) => {
256
349
  name: "shell-shock:chmod+x",
257
350
  configResolved() {
258
351
  this.config.tsdown.hooks ??= {};
259
- this.config.tsdown.hooks["build:done"] = async (_) => {
260
- await Promise.all(Object.values(this.config.bin).map(async (bin) => {
352
+ this.config.tsdown.hooks["build:done"] = __assignType(async (_) => {
353
+ await Promise.all(Object.values(this.config.bin).map(__assignType(async (bin) => {
261
354
  const path = appendPath(bin, joinPaths(this.workspaceConfig.workspaceRoot, this.config.root));
262
355
  if (this.fs.existsSync(path)) {
263
356
  this.debug(`Adding hashbang to binary executable output file: ${path}`);
@@ -266,40 +359,65 @@ const plugin = (options = {}) => {
266
359
  this.debug(`Adding executable permissions (chmod+x) to binary executable output file: ${path}`);
267
360
  await chmodX(path);
268
361
  } else this.warn(`Expected binary output file not found at path: ${path}. Skipping adding hashbang and executable permissions (chmod+x).`);
269
- }));
270
- };
362
+ }, [
363
+ "bin",
364
+ "",
365
+ "P\"2!\"/\""
366
+ ])));
367
+ }, [
368
+ "chunks",
369
+ "_",
370
+ "",
371
+ "PP!P!F4!MK2\"\"/#"
372
+ ]);
271
373
  }
272
374
  },
273
375
  {
274
376
  name: "shell-shock:docs",
275
- configResolved() {
377
+ configResolved: __assignType(function configResolved() {
276
378
  this.config.automd ??= {};
277
379
  this.config.automd.generators = {
278
380
  ...this.config.automd.generators ?? {},
279
381
  commands: commands(this)
280
382
  };
281
- },
383
+ }, ["configResolved", "P\"/!"]),
282
384
  async docs() {
283
385
  this.debug("Rendering entrypoint modules for the Shell Shock `script` preset.");
284
- const commands = this.inputs.map((input) => getCommandTree(this, input.segments)).filter(Boolean);
386
+ const commands = this.inputs.map(__assignType((input) => getCommandTree(this, input.segments), [
387
+ "input",
388
+ "",
389
+ "P\"2!\"/\""
390
+ ])).filter(Boolean);
285
391
  return render(this, createComponent(For, {
286
392
  get each() {
287
393
  return Object.values(commands);
288
394
  },
289
395
  doubleHardline: true,
290
- children: (child) => createComponent(Show, {
291
- get when() {
292
- return !child.isVirtual;
293
- },
294
- get children() {
295
- return createComponent(CommandDocsFile, { command: child });
296
- }
297
- })
396
+ get children() {
397
+ return __assignType((child) => createComponent(Show, {
398
+ get when() {
399
+ return !child.isVirtual;
400
+ },
401
+ get children() {
402
+ return createComponent(CommandDocsFile, { command: child });
403
+ }
404
+ }), [
405
+ "child",
406
+ "",
407
+ "P\"2!\"/\""
408
+ ]);
409
+ }
298
410
  }));
299
411
  }
300
412
  }
301
413
  ];
302
- };
414
+ }, [
415
+ "Options",
416
+ "options",
417
+ () => ({}),
418
+ "",
419
+ "P\"w!2\">#!F/$"
420
+ ]);
303
421
 
304
422
  //#endregion
305
423
  export { plugin as default, plugin };
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.mjs","names":[],"sources":["../src/plugin.tsx"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Shell Shock\n\n This code was released as part of the Shell Shock project. Shell Shock\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/shell-shock.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/shell-shock\n Documentation: https://docs.stormsoftware.com/projects/shell-shock\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { For, Show } from \"@alloy-js/core/components\";\nimport { render } from \"@powerlines/plugin-alloy/render\";\nimport automd from \"@powerlines/plugin-automd\";\nimport nodejs from \"@powerlines/plugin-nodejs\";\nimport tsdown from \"@powerlines/plugin-tsdown\";\nimport { toArray } from \"@stryke/convert/to-array\";\nimport { chmodX } from \"@stryke/fs/chmod-x\";\nimport { appendPath } from \"@stryke/path/append\";\nimport { findFilePath } from \"@stryke/path/file-path-fns\";\nimport { isParentPath } from \"@stryke/path/is-parent-path\";\nimport { joinPaths } from \"@stryke/path/join-paths\";\nimport { replacePath } from \"@stryke/path/replace\";\nimport { resolveParentPath } from \"@stryke/path/resolve-parent-path\";\nimport { camelCase } from \"@stryke/string-format/camel-case\";\nimport { constantCase } from \"@stryke/string-format/constant-case\";\nimport { kebabCase } from \"@stryke/string-format/kebab-case\";\nimport { isObject } from \"@stryke/type-checks/is-object\";\nimport { isSetString } from \"@stryke/type-checks/is-set-string\";\nimport { defu } from \"defu\";\nimport type { Plugin } from \"powerlines\";\nimport { resolveInputs } from \"powerlines/utils\";\nimport type { BuildContext, RolldownChunk, TsdownHooks } from \"tsdown\";\nimport { CommandDocsFile } from \"./components/docs\";\nimport { ExecBuiltin } from \"./components/exec-builtin\";\nimport { StateBuiltin } from \"./components/state-builtin\";\nimport { UtilsBuiltin } from \"./components/utils-builtin\";\nimport { commands } from \"./helpers/automd\";\nimport {\n findCommandsRoot,\n resolveCommandId,\n resolveCommandName,\n resolveCommandPath\n} from \"./helpers/paths\";\nimport {\n getCommandsPersistencePath,\n readCommandsPersistence,\n writeCommandsPersistence\n} from \"./helpers/persistence\";\nimport {\n formatBinaryPath,\n updatePackageJsonBinary\n} from \"./helpers/update-package-json\";\nimport { formatCommandTree, getGlobalOptions } from \"./helpers/utilities\";\nimport { validateCommand } from \"./helpers/validations\";\nimport {\n getAppDescription,\n getAppName,\n getAppTitle,\n getDynamicPathSegmentName,\n isDynamicPathSegment,\n isPathSegmentGroup\n} from \"./plugin-utils/context-helpers\";\nimport { getCommandTree } from \"./plugin-utils/get-command-tree\";\nimport { traverseCommands } from \"./plugin-utils/traverse-command-tree\";\nimport { resolve } from \"./resolver/resolve\";\nimport type { CommandOption, CommandTree } from \"./types/command\";\nimport type { Options } from \"./types/config\";\nimport type { Context } from \"./types/context\";\n\nconst MAX_DEPTH = 50;\n\n/**\n * The core Powerlines plugin to build Shell Shock projects.\n */\nexport const plugin = <TContext extends Context = Context>(\n options: Options = {}\n): Plugin<TContext>[] => {\n return [\n tsdown<TContext>(),\n automd<TContext>(),\n {\n name: \"shell-shock:config\",\n async config() {\n this.debug(\"Resolving the Shell Shock configuration.\");\n\n await updatePackageJsonBinary(this);\n\n const result = defu(\n {\n output: {\n path: joinPaths(this.config.root, \"dist\")\n }\n },\n options,\n {\n name: getAppName(this),\n title: getAppTitle(this),\n description: getAppDescription(this),\n platform: \"node\",\n projectType: \"application\",\n framework: \"shell-shock\",\n isCaseSensitive: false,\n output: {\n format: \"esm\",\n dts: false\n },\n input:\n !this.config.input ||\n (Array.isArray(this.config.input) &&\n this.config.input.length === 0) ||\n (isObject(this.config.input) &&\n Object.keys(this.config.input).length === 0)\n ? [\n joinPaths(this.config.root, \"src/**/command.ts\"),\n joinPaths(this.config.root, \"src/**/command.tsx\")\n ]\n : undefined,\n resolve: {\n external: [\"@powerlines/deepkit\"],\n skipNodeModulesBundle: true\n },\n tsdown: {\n dts: false,\n nodeProtocol: true,\n unbundle: false\n }\n }\n );\n\n return result;\n },\n configResolved: {\n order: \"pre\",\n async handler() {\n this.debug(\"Shell Shock configuration has been resolved.\");\n\n this.config.appSpecificEnvPrefix = isSetString(\n this.config.autoAssignEnv\n )\n ? this.config.autoAssignEnv\n : constantCase(getAppName(this));\n if (\n !this.config.env.prefix ||\n !Array.isArray(this.config.env.prefix)\n ) {\n this.config.env.prefix = toArray(this.config.env.prefix);\n }\n\n if (\n !this.config.env.prefix.includes(this.config.appSpecificEnvPrefix)\n ) {\n this.config.env.prefix.push(this.config.appSpecificEnvPrefix);\n }\n\n this.config.bin = (isSetString(this.packageJson.bin)\n ? { [kebabCase(this.config.name)]: this.packageJson.bin }\n : this.packageJson.bin) ?? {\n [kebabCase(this.config.name)]: formatBinaryPath(\n this.config.output.format\n )\n };\n\n if (isSetString(this.config.reference)) {\n if (this.config.reference.includes(\"{command}\")) {\n this.config.reference = {\n app: this.config.reference\n .substring(0, this.config.reference.indexOf(\"{command}\"))\n .replace(/\\/?$/, \"/\"),\n commands: this.config.reference\n };\n } else if (this.config.reference.includes(\"{commands}\")) {\n this.config.reference = {\n app: this.config.reference\n .substring(0, this.config.reference.indexOf(\"{commands}\"))\n .replace(/\\/?$/, \"/\"),\n commands: this.config.reference\n };\n } else {\n this.config.reference = {\n app: this.config.reference\n };\n }\n }\n\n this.inputs ??= [];\n this.options = Object.values(\n getGlobalOptions(this, {\n id: null,\n name: this.config.name,\n path: null,\n segments: [],\n title: this.config.title,\n description: this.config.description,\n alias: [],\n isVirtual: false\n })\n );\n\n this.options = this.options.map(\n option =>\n ({\n ...option,\n name: camelCase(option.name),\n alias: option.alias ?? [],\n optional: option.optional ?? false\n }) as CommandOption\n );\n }\n }\n },\n ...nodejs<TContext>(\n defu(options ?? {}, {\n env: {\n types: \"@shell-shock/core/types/env#ShellShockEnv\",\n validate: false\n }\n })\n ),\n {\n name: \"shell-shock:inputs\",\n async configResolved() {\n this.debug(\"Finding command entry point files.\");\n\n this.debug(\n `Checking for commands using input: ${JSON.stringify(this.config.input)}`\n );\n\n this.commandsPath = await findCommandsRoot(this);\n this.debug(`Resolved commands root path: ${this.commandsPath}`);\n\n const inputs = await resolveInputs(this, this.config.input);\n\n this.debug(\n `Found ${\n inputs.length\n } entry points specified in the configuration options.`\n );\n\n this.inputs = inputs.reduce((ret, entry) => {\n if (\n entry.file !== this.commandsPath &&\n !isParentPath(entry.file, this.commandsPath)\n ) {\n throw new Error(\n `Command entry point \"${\n entry.file\n }\" is not located within the commands root \"${\n this.commandsPath\n }\". Please ensure that all command entry points are located within the current project.`\n );\n }\n\n const id = resolveCommandId(this, entry.file);\n if (!ret.some(existing => existing.id === id)) {\n const name = resolveCommandName(entry.file);\n let segments = resolveCommandPath(this, entry.file)\n .split(\"/\")\n .filter(Boolean);\n\n // Ensure unique segment names by appending an index suffix to duplicates\n segments = segments.map((segment, index) => {\n const found = segments.findIndex(\n existing => existing === segment\n );\n if (found !== -1 && found !== index) {\n segment += `_${\n segments.filter(\n segment =>\n isDynamicPathSegment(segment) &&\n getDynamicPathSegmentName(segment).replace(\n /_\\d+$/,\n \"\"\n ) === segment\n ).length\n }`;\n }\n\n return segment;\n });\n\n ret.push({\n id,\n path: segments.join(\"/\"),\n segments,\n name,\n alias: [],\n tags: [],\n isVirtual: false,\n source: \"file\",\n entry: {\n ...entry,\n file: entry.file,\n input: {\n file: entry.file,\n name: entry.name\n },\n output: name\n }\n });\n }\n\n return ret;\n }, this.inputs);\n\n this.debug(\n `Shell Shock will process ${\n this.inputs.length\n } command entry files: \\n${this.inputs\n .map(\n command =>\n ` - ${command.id}: ${replacePath(\n command.entry.file,\n this.commandsPath\n )}`\n )\n .join(\"\\n\")}`\n );\n },\n async prepare() {\n this.debug(\n \"Rendering base built-in modules for the Shell Shock application.\"\n );\n\n return render(\n this,\n <>\n <StateBuiltin />\n <UtilsBuiltin />\n <ExecBuiltin />\n </>\n );\n }\n },\n {\n name: \"shell-shock:virtual-inputs\",\n configResolved: {\n order: \"post\",\n async handler() {\n if (this.inputs.length === 0) {\n this.warn(\n \"No commands were found in the project. Please ensure at least one command exists.\"\n );\n } else {\n this.debug(\n \"Finding and adding virtual command inputs for each command previously found.\"\n );\n\n this.inputs = this.inputs\n .reduce((ret, command) => {\n let depth = 0;\n\n let parentPath = resolveParentPath(\n findFilePath(command.entry.file)\n );\n if (isParentPath(parentPath, this.commandsPath)) {\n while (parentPath !== this.commandsPath) {\n if (depth++ > MAX_DEPTH) {\n throw new Error(\n `Unable to process virtual commands for ${\n command.name\n } \\n\\nPlease ensure ${\n command.entry.file\n } is a valid command entry file and does not have an invalid path.`\n );\n }\n\n if (\n !ret.some(\n existing =>\n findFilePath(existing.entry.file) === parentPath\n )\n ) {\n const file = joinPaths(parentPath, \"command.ts\");\n const id = resolveCommandId(this, file);\n if (!ret.some(existing => existing.id === id)) {\n const name = resolveCommandName(file);\n\n let segments = resolveCommandPath(this, file)\n .split(\"/\")\n .filter(Boolean);\n\n // Ensure unique segment names by appending an index suffix to duplicates\n segments = segments.map((segment, index) => {\n const found = segments.findIndex(\n existing => existing === segment\n );\n if (found !== -1 && found !== index) {\n segment += `_${\n segments.filter(\n segment =>\n isDynamicPathSegment(segment) &&\n getDynamicPathSegmentName(segment).replace(\n /_\\d+$/,\n \"\"\n ) === segment\n ).length\n }`;\n }\n\n return segment;\n });\n\n ret.push({\n id,\n path: segments.join(\"/\"),\n segments,\n name,\n alias: [],\n tags: [],\n isVirtual: true,\n entry: {\n file\n },\n source: \"file\"\n });\n }\n }\n\n parentPath = resolveParentPath(parentPath);\n }\n }\n\n return ret;\n }, this.inputs)\n .sort((a, b) => a.segments.length - b.segments.length);\n\n this.debug(\n `Final command input list: \\n${this.inputs\n .map(\n command =>\n ` - ${command.id}${command.isVirtual ? \" (virtual)\" : \"\"}: ${\n command.source === \"file\"\n ? replacePath(command.entry.file, this.commandsPath)\n : `added by ${command.source}`\n }`\n )\n .join(\"\\n\")}`\n );\n }\n }\n }\n },\n {\n name: \"shell-shock:resolve-commands\",\n prepare: {\n order: \"post\",\n async handler() {\n this.debug(\"Initializing the CLI application's command tree.\");\n\n this.commands = {};\n if (\n this.config.command !== \"prepare\" &&\n this.config.skipCache !== true &&\n this.persistedMeta?.checksum === this.meta.checksum &&\n this.fs.existsSync(getCommandsPersistencePath(this))\n ) {\n this.debug(\n `Skipping command resolution as the meta checksum has not changed.`\n );\n\n await readCommandsPersistence(this);\n } else {\n for (const input of this.inputs.filter(\n input =>\n input.segments.filter(\n segment =>\n !isDynamicPathSegment(segment) &&\n !isPathSegmentGroup(segment)\n ).length === 1\n )) {\n this.commands[input.name] = await resolve({\n context: this,\n command: input\n });\n }\n\n this.debug(\"Post-processing commands to ensure proper reflection.\");\n\n await traverseCommands(this, command => {\n command.options = Object.fromEntries(\n Object.entries(command.options).map(([name, option]) => [\n camelCase(name),\n {\n ...option,\n name: camelCase(name),\n alias: option.alias ?? [],\n optional: option.optional ?? false\n } as CommandOption\n ])\n );\n });\n\n await writeCommandsPersistence(this);\n }\n\n this.debug(\"Validating the CLI applications command tree.\");\n\n let isValid = true;\n await traverseCommands(this, command => {\n const failures = validateCommand(command);\n if (failures.length > 0) {\n this.error(\n `Found ${failures.length} issue${failures.length > 1 ? \"s\" : \"\"} with the ${\n command.title\n } command: \\n${failures\n .map(failure => ` - ${failure.code}: ${failure.details}`)\n .join(\"\\n\")}\\n`\n );\n isValid = false;\n }\n });\n if (!isValid) {\n throw new Error(\n `One or more commands in the command tree are invalid. Please review the errors above and correct them before proceeding.`\n );\n }\n\n this.info(\n `\\nCreating an application with the following command tree: \\n${formatCommandTree(\n this\n )}\\n`\n );\n }\n }\n },\n {\n name: \"shell-shock:chmod+x\",\n configResolved() {\n this.config.tsdown.hooks ??= {} as TsdownHooks;\n (this.config.tsdown.hooks as TsdownHooks)[\"build:done\"] = async (\n _: BuildContext & {\n chunks: RolldownChunk[];\n }\n ) => {\n await Promise.all(\n Object.values(this.config.bin).map(async bin => {\n const path = appendPath(\n bin,\n joinPaths(this.workspaceConfig.workspaceRoot, this.config.root)\n );\n if (this.fs.existsSync(path)) {\n this.debug(\n `Adding hashbang to binary executable output file: ${path}`\n );\n\n const content = await this.fs.read(path);\n if (content && !content.startsWith(\"#!\")) {\n await this.fs.write(\n path,\n `#!/usr/bin/env ${\n this.config.mode === \"development\"\n ? \"-S NODE_OPTIONS=--enable-source-maps\"\n : \"\"\n } node\\n\\n${content}`\n );\n }\n\n this.debug(\n `Adding executable permissions (chmod+x) to binary executable output file: ${\n path\n }`\n );\n\n await chmodX(path);\n } else {\n this.warn(\n `Expected binary output file not found at path: ${\n path\n }. Skipping adding hashbang and executable permissions (chmod+x).`\n );\n }\n })\n );\n };\n }\n },\n {\n name: \"shell-shock:docs\",\n configResolved() {\n this.config.automd ??= {};\n this.config.automd.generators = {\n ...(this.config.automd.generators ?? {}),\n commands: commands(this)\n };\n },\n async docs() {\n this.debug(\n \"Rendering entrypoint modules for the Shell Shock `script` preset.\"\n );\n\n const commands = this.inputs\n .map(input => getCommandTree(this, input.segments))\n .filter(Boolean) as CommandTree[];\n\n return render(\n this,\n <For each={Object.values(commands)} doubleHardline>\n {child => (\n <Show when={!child.isVirtual}>\n <CommandDocsFile command={child} />\n </Show>\n )}\n </For>\n );\n }\n }\n ];\n};\n\nexport default plugin;\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.mjs","names":[],"sources":["../src/plugin.tsx"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Shell Shock\n\n This code was released as part of the Shell Shock project. Shell Shock\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/shell-shock.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/shell-shock\n Documentation: https://docs.stormsoftware.com/projects/shell-shock\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { For, Show } from \"@alloy-js/core/components\";\nimport { render } from \"@powerlines/plugin-alloy/render\";\nimport automd from \"@powerlines/plugin-automd\";\nimport nodejs from \"@powerlines/plugin-nodejs\";\nimport tsdown from \"@powerlines/plugin-tsdown\";\nimport { toArray } from \"@stryke/convert/to-array\";\nimport { chmodX } from \"@stryke/fs/chmod-x\";\nimport { appendPath } from \"@stryke/path/append\";\nimport { findFilePath } from \"@stryke/path/file-path-fns\";\nimport { isParentPath } from \"@stryke/path/is-parent-path\";\nimport { joinPaths } from \"@stryke/path/join-paths\";\nimport { replacePath } from \"@stryke/path/replace\";\nimport { resolveParentPath } from \"@stryke/path/resolve-parent-path\";\nimport { camelCase } from \"@stryke/string-format/camel-case\";\nimport { constantCase } from \"@stryke/string-format/constant-case\";\nimport { kebabCase } from \"@stryke/string-format/kebab-case\";\nimport { isObject } from \"@stryke/type-checks/is-object\";\nimport { isSetString } from \"@stryke/type-checks/is-set-string\";\nimport { defu } from \"defu\";\nimport type { Plugin } from \"powerlines\";\nimport { resolveInputs } from \"powerlines/utils\";\nimport type { BuildContext, RolldownChunk, TsdownHooks } from \"tsdown\";\nimport { CommandDocsFile } from \"./components/docs\";\nimport { ExecBuiltin } from \"./components/exec-builtin\";\nimport { StateBuiltin } from \"./components/state-builtin\";\nimport { UtilsBuiltin } from \"./components/utils-builtin\";\nimport { commands } from \"./helpers/automd\";\nimport {\n findCommandsRoot,\n resolveCommandId,\n resolveCommandName,\n resolveCommandPath\n} from \"./helpers/paths\";\nimport {\n getCommandsPersistencePath,\n readCommandsPersistence,\n writeCommandsPersistence\n} from \"./helpers/persistence\";\nimport {\n formatBinaryPath,\n updatePackageJsonBinary\n} from \"./helpers/update-package-json\";\nimport { formatCommandTree, getGlobalOptions } from \"./helpers/utilities\";\nimport { validateCommand } from \"./helpers/validations\";\nimport {\n getAppDescription,\n getAppName,\n getAppTitle,\n getDynamicPathSegmentName,\n isDynamicPathSegment,\n isPathSegmentGroup\n} from \"./plugin-utils/context-helpers\";\nimport { getCommandTree } from \"./plugin-utils/get-command-tree\";\nimport { traverseCommands } from \"./plugin-utils/traverse-command-tree\";\nimport { resolve } from \"./resolver/resolve\";\nimport type { CommandOption, CommandTree } from \"./types/command\";\nimport type { Options } from \"./types/config\";\nimport type { Context } from \"./types/context\";\n\nconst MAX_DEPTH = 50;\n\n/**\n * The core Powerlines plugin to build Shell Shock projects.\n */\nexport const plugin = <TContext extends Context = Context>(\n options: Options = {}\n): Plugin<TContext>[] => {\n return [\n tsdown<TContext>(),\n automd<TContext>(),\n {\n name: \"shell-shock:config\",\n async config() {\n this.debug(\"Resolving the Shell Shock configuration.\");\n\n await updatePackageJsonBinary(this);\n\n const result = defu(\n {\n output: {\n path: joinPaths(this.config.root, \"dist\")\n }\n },\n options,\n {\n name: getAppName(this),\n title: getAppTitle(this),\n description: getAppDescription(this),\n platform: \"node\",\n projectType: \"application\",\n framework: \"shell-shock\",\n isCaseSensitive: false,\n output: {\n format: \"esm\",\n dts: false\n },\n input:\n !this.config.input ||\n (Array.isArray(this.config.input) &&\n this.config.input.length === 0) ||\n (isObject(this.config.input) &&\n Object.keys(this.config.input).length === 0)\n ? [\n joinPaths(this.config.root, \"src/**/command.ts\"),\n joinPaths(this.config.root, \"src/**/command.tsx\")\n ]\n : undefined,\n resolve: {\n external: [\"@powerlines/deepkit\"],\n skipNodeModulesBundle: true\n },\n tsdown: {\n dts: false,\n nodeProtocol: true,\n unbundle: false\n }\n }\n );\n\n return result;\n },\n configResolved: {\n order: \"pre\",\n async handler() {\n this.debug(\"Shell Shock configuration has been resolved.\");\n\n this.config.appSpecificEnvPrefix = isSetString(\n this.config.autoAssignEnv\n )\n ? this.config.autoAssignEnv\n : constantCase(getAppName(this));\n if (\n !this.config.env.prefix ||\n !Array.isArray(this.config.env.prefix)\n ) {\n this.config.env.prefix = toArray(this.config.env.prefix);\n }\n\n if (\n !this.config.env.prefix.includes(this.config.appSpecificEnvPrefix)\n ) {\n this.config.env.prefix.push(this.config.appSpecificEnvPrefix);\n }\n\n this.config.bin = (isSetString(this.packageJson.bin)\n ? { [kebabCase(this.config.name)]: this.packageJson.bin }\n : this.packageJson.bin) ?? {\n [kebabCase(this.config.name)]: formatBinaryPath(\n this.config.output.format\n )\n };\n\n if (isSetString(this.config.reference)) {\n if (this.config.reference.includes(\"{command}\")) {\n this.config.reference = {\n app: this.config.reference\n .substring(0, this.config.reference.indexOf(\"{command}\"))\n .replace(/\\/?$/, \"/\"),\n commands: this.config.reference\n };\n } else if (this.config.reference.includes(\"{commands}\")) {\n this.config.reference = {\n app: this.config.reference\n .substring(0, this.config.reference.indexOf(\"{commands}\"))\n .replace(/\\/?$/, \"/\"),\n commands: this.config.reference\n };\n } else {\n this.config.reference = {\n app: this.config.reference\n };\n }\n }\n\n this.inputs ??= [];\n this.options = Object.values(\n getGlobalOptions(this, {\n id: null,\n name: this.config.name,\n path: null,\n segments: [],\n title: this.config.title,\n description: this.config.description,\n alias: [],\n isVirtual: false\n })\n );\n\n this.options = this.options.map(\n option =>\n ({\n ...option,\n name: camelCase(option.name),\n alias: option.alias ?? [],\n optional: option.optional ?? false\n }) as CommandOption\n );\n }\n }\n },\n ...nodejs<TContext>(\n defu(options ?? {}, {\n env: {\n types: \"@shell-shock/core/types/env#ShellShockEnv\",\n validate: false\n }\n })\n ),\n {\n name: \"shell-shock:inputs\",\n async configResolved() {\n this.debug(\"Finding command entry point files.\");\n\n this.debug(\n `Checking for commands using input: ${JSON.stringify(this.config.input)}`\n );\n\n this.commandsPath = await findCommandsRoot(this);\n this.debug(`Resolved commands root path: ${this.commandsPath}`);\n\n const inputs = await resolveInputs(this, this.config.input);\n\n this.debug(\n `Found ${\n inputs.length\n } entry points specified in the configuration options.`\n );\n\n this.inputs = inputs.reduce((ret, entry) => {\n if (\n entry.file !== this.commandsPath &&\n !isParentPath(entry.file, this.commandsPath)\n ) {\n throw new Error(\n `Command entry point \"${\n entry.file\n }\" is not located within the commands root \"${\n this.commandsPath\n }\". Please ensure that all command entry points are located within the current project.`\n );\n }\n\n const id = resolveCommandId(this, entry.file);\n if (!ret.some(existing => existing.id === id)) {\n const name = resolveCommandName(entry.file);\n let segments = resolveCommandPath(this, entry.file)\n .split(\"/\")\n .filter(Boolean);\n\n // Ensure unique segment names by appending an index suffix to duplicates\n segments = segments.map((segment, index) => {\n const found = segments.findIndex(\n existing => existing === segment\n );\n if (found !== -1 && found !== index) {\n segment += `_${\n segments.filter(\n segment =>\n isDynamicPathSegment(segment) &&\n getDynamicPathSegmentName(segment).replace(\n /_\\d+$/,\n \"\"\n ) === segment\n ).length\n }`;\n }\n\n return segment;\n });\n\n ret.push({\n id,\n path: segments.join(\"/\"),\n segments,\n name,\n alias: [],\n tags: [],\n isVirtual: false,\n source: \"file\",\n entry: {\n ...entry,\n file: entry.file,\n input: {\n file: entry.file,\n name: entry.name\n },\n output: name\n }\n });\n }\n\n return ret;\n }, this.inputs);\n\n this.debug(\n `Shell Shock will process ${\n this.inputs.length\n } command entry files: \\n${this.inputs\n .map(\n command =>\n ` - ${command.id}: ${replacePath(\n command.entry.file,\n this.commandsPath\n )}`\n )\n .join(\"\\n\")}`\n );\n },\n async prepare() {\n this.debug(\n \"Rendering base built-in modules for the Shell Shock application.\"\n );\n\n return render(\n this,\n <>\n <StateBuiltin />\n <UtilsBuiltin />\n <ExecBuiltin />\n </>\n );\n }\n },\n {\n name: \"shell-shock:virtual-inputs\",\n configResolved: {\n order: \"post\",\n async handler() {\n if (this.inputs.length === 0) {\n this.warn(\n \"No commands were found in the project. Please ensure at least one command exists.\"\n );\n } else {\n this.debug(\n \"Finding and adding virtual command inputs for each command previously found.\"\n );\n\n this.inputs = this.inputs\n .reduce((ret, command) => {\n let depth = 0;\n\n let parentPath = resolveParentPath(\n findFilePath(command.entry.file)\n );\n if (isParentPath(parentPath, this.commandsPath)) {\n while (parentPath !== this.commandsPath) {\n if (depth++ > MAX_DEPTH) {\n throw new Error(\n `Unable to process virtual commands for ${\n command.name\n } \\n\\nPlease ensure ${\n command.entry.file\n } is a valid command entry file and does not have an invalid path.`\n );\n }\n\n if (\n !ret.some(\n existing =>\n findFilePath(existing.entry.file) === parentPath\n )\n ) {\n const file = joinPaths(parentPath, \"command.ts\");\n const id = resolveCommandId(this, file);\n if (!ret.some(existing => existing.id === id)) {\n const name = resolveCommandName(file);\n\n let segments = resolveCommandPath(this, file)\n .split(\"/\")\n .filter(Boolean);\n\n // Ensure unique segment names by appending an index suffix to duplicates\n segments = segments.map((segment, index) => {\n const found = segments.findIndex(\n existing => existing === segment\n );\n if (found !== -1 && found !== index) {\n segment += `_${\n segments.filter(\n segment =>\n isDynamicPathSegment(segment) &&\n getDynamicPathSegmentName(segment).replace(\n /_\\d+$/,\n \"\"\n ) === segment\n ).length\n }`;\n }\n\n return segment;\n });\n\n ret.push({\n id,\n path: segments.join(\"/\"),\n segments,\n name,\n alias: [],\n tags: [],\n isVirtual: true,\n entry: {\n file\n },\n source: \"file\"\n });\n }\n }\n\n parentPath = resolveParentPath(parentPath);\n }\n }\n\n return ret;\n }, this.inputs)\n .sort((a, b) => a.segments.length - b.segments.length);\n\n this.debug(\n `Final command input list: \\n${this.inputs\n .map(\n command =>\n ` - ${command.id}${command.isVirtual ? \" (virtual)\" : \"\"}: ${\n command.source === \"file\"\n ? replacePath(command.entry.file, this.commandsPath)\n : `added by ${command.source}`\n }`\n )\n .join(\"\\n\")}`\n );\n }\n }\n }\n },\n {\n name: \"shell-shock:resolve-commands\",\n prepare: {\n order: \"post\",\n async handler() {\n this.debug(\"Initializing the CLI application's command tree.\");\n\n this.commands = {};\n if (\n this.config.command !== \"prepare\" &&\n this.config.skipCache !== true &&\n this.persistedMeta?.checksum === this.meta.checksum &&\n this.fs.existsSync(getCommandsPersistencePath(this))\n ) {\n this.debug(\n `Skipping command resolution as the meta checksum has not changed.`\n );\n\n await readCommandsPersistence(this);\n } else {\n for (const input of this.inputs.filter(\n input =>\n input.segments.filter(\n segment =>\n !isDynamicPathSegment(segment) &&\n !isPathSegmentGroup(segment)\n ).length === 1\n )) {\n this.commands[input.name] = await resolve({\n context: this,\n command: input\n });\n }\n\n this.debug(\"Post-processing commands to ensure proper reflection.\");\n\n await traverseCommands(this, command => {\n command.options = Object.fromEntries(\n Object.entries(command.options).map(([name, option]) => [\n camelCase(name),\n {\n ...option,\n name: camelCase(name),\n alias: option.alias ?? [],\n optional: option.optional ?? false\n } as CommandOption\n ])\n );\n });\n\n await writeCommandsPersistence(this);\n }\n\n this.debug(\"Validating the CLI applications command tree.\");\n\n let isValid = true;\n await traverseCommands(this, command => {\n const failures = validateCommand(command);\n if (failures.length > 0) {\n this.error(\n `Found ${failures.length} issue${failures.length > 1 ? \"s\" : \"\"} with the ${\n command.title\n } command: \\n${failures\n .map(failure => ` - ${failure.code}: ${failure.details}`)\n .join(\"\\n\")}\\n`\n );\n isValid = false;\n }\n });\n if (!isValid) {\n throw new Error(\n `One or more commands in the command tree are invalid. Please review the errors above and correct them before proceeding.`\n );\n }\n\n this.info(\n `\\nCreating an application with the following command tree: \\n${formatCommandTree(\n this\n )}\\n`\n );\n }\n }\n },\n {\n name: \"shell-shock:chmod+x\",\n configResolved() {\n this.config.tsdown.hooks ??= {} as TsdownHooks;\n (this.config.tsdown.hooks as TsdownHooks)[\"build:done\"] = async (\n _: BuildContext & {\n chunks: RolldownChunk[];\n }\n ) => {\n await Promise.all(\n Object.values(this.config.bin).map(async bin => {\n const path = appendPath(\n bin,\n joinPaths(this.workspaceConfig.workspaceRoot, this.config.root)\n );\n if (this.fs.existsSync(path)) {\n this.debug(\n `Adding hashbang to binary executable output file: ${path}`\n );\n\n const content = await this.fs.read(path);\n if (content && !content.startsWith(\"#!\")) {\n await this.fs.write(\n path,\n `#!/usr/bin/env ${\n this.config.mode === \"development\"\n ? \"-S NODE_OPTIONS=--enable-source-maps\"\n : \"\"\n } node\\n\\n${content}`\n );\n }\n\n this.debug(\n `Adding executable permissions (chmod+x) to binary executable output file: ${\n path\n }`\n );\n\n await chmodX(path);\n } else {\n this.warn(\n `Expected binary output file not found at path: ${\n path\n }. Skipping adding hashbang and executable permissions (chmod+x).`\n );\n }\n })\n );\n };\n }\n },\n {\n name: \"shell-shock:docs\",\n configResolved() {\n this.config.automd ??= {};\n this.config.automd.generators = {\n ...(this.config.automd.generators ?? {}),\n commands: commands(this)\n };\n },\n async docs() {\n this.debug(\n \"Rendering entrypoint modules for the Shell Shock `script` preset.\"\n );\n\n const commands = this.inputs\n .map(input => getCommandTree(this, input.segments))\n .filter(Boolean) as CommandTree[];\n\n return render(\n this,\n <For each={Object.values(commands)} doubleHardline>\n {child => (\n <Show when={!child.isVirtual}>\n <CommandDocsFile command={child} />\n </Show>\n )}\n </For>\n );\n }\n }\n ];\n};\n\nexport default plugin;\n"],"mappings":"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"}
@@ -73,7 +73,7 @@ function resolveCommandArgument(ctx, index, reflection) {
73
73
  title: reflection.getTitle() || reflection.parameter.tags?.title,
74
74
  description: reflection.parameter.description,
75
75
  optional: reflection.isOptional(),
76
- default: reflection.getDefaultValue()
76
+ default: reflection.getDefaultValue() || reflection.parameter.default
77
77
  };
78
78
  if (type.kind === _powerlines_deepkit_vendor_type.ReflectionKind.array) if (type.type.kind === _powerlines_deepkit_vendor_type.ReflectionKind.string || type.type.kind === _powerlines_deepkit_vendor_type.ReflectionKind.number) {
79
79
  argument.variadic = true;
@@ -72,7 +72,7 @@ function resolveCommandArgument(ctx, index, reflection) {
72
72
  title: reflection.getTitle() || reflection.parameter.tags?.title,
73
73
  description: reflection.parameter.description,
74
74
  optional: reflection.isOptional(),
75
- default: reflection.getDefaultValue()
75
+ default: reflection.getDefaultValue() || reflection.parameter.default
76
76
  };
77
77
  if (type.kind === ReflectionKind.array) if (type.type.kind === ReflectionKind.string || type.type.kind === ReflectionKind.number) {
78
78
  argument.variadic = true;
@@ -1 +1 @@
1
- {"version":3,"file":"deepkit.mjs","names":[],"sources":["../../src/resolver/deepkit.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Shell Shock\n\n This code was released as part of the Shell Shock project. Shell Shock\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/shell-shock.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/shell-shock\n Documentation: https://docs.stormsoftware.com/projects/shell-shock\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport type {\n ReflectionParameter,\n ReflectionProperty,\n Type,\n TypeArray\n} from \"@powerlines/deepkit/vendor/type\";\nimport {\n reflect,\n ReflectionClass,\n ReflectionFunction,\n ReflectionKind,\n stringifyType\n} from \"@powerlines/deepkit/vendor/type\";\nimport { isBigInt } from \"@stryke/type-checks/is-bigint\";\nimport { isNumber } from \"@stryke/type-checks/is-number\";\nimport { isRegExp } from \"@stryke/type-checks/is-regexp\";\nimport { isSetObject } from \"@stryke/type-checks/is-set-object\";\nimport type {\n CommandArgument,\n CommandOption,\n CommandParameterKind,\n Context,\n NumberCommandParameter,\n StringCommandParameter\n} from \"../types\";\nimport { CommandParameterKinds } from \"../types\";\nimport { mergeCommandParameter } from \"./helpers\";\nimport type { ResolverContext } from \"./types\";\n\nfunction extractCommandParameterKind(\n type: Type | ReflectionKind\n): CommandParameterKind {\n const isKind = !(isSetObject(type) && \"kind\" in type);\n const kind = !isKind ? type.kind : type;\n if (kind === ReflectionKind.string) {\n return CommandParameterKinds.string;\n } else if (\n kind === ReflectionKind.number ||\n kind === ReflectionKind.bigint ||\n (!isKind &&\n type.kind === ReflectionKind.literal &&\n (isNumber(type.literal) || isBigInt(type.literal)))\n ) {\n return CommandParameterKinds.number;\n } else if (kind === ReflectionKind.boolean) {\n return CommandParameterKinds.boolean;\n } else {\n return CommandParameterKinds.string;\n }\n}\n\nfunction resolveCommandOption(\n ctx: ResolverContext,\n reflection: ReflectionProperty\n): CommandOption {\n const type = reflection.getType();\n const existing = (ctx.output.options[reflection.getNameAsString()] ??\n {}) as Partial<CommandOption>;\n\n const option = {\n name: reflection.getNameAsString(),\n alias: reflection.getTags().alias ?? [],\n title: reflection.getTags().title?.trim(),\n description: reflection.getDescription(),\n kind: extractCommandParameterKind(type),\n optional: reflection.isOptional(),\n default: reflection.getDefaultValue(),\n variadic: reflection.isArray()\n };\n\n if (option.variadic) {\n option.kind = extractCommandParameterKind((type as TypeArray).type.kind);\n } else if (type.kind === ReflectionKind.union) {\n option.kind = type.types.every(\n t =>\n t.kind === ReflectionKind.number ||\n (t.kind === ReflectionKind.literal &&\n (isNumber(t.literal) || isBigInt(t.literal)))\n )\n ? CommandParameterKinds.number\n : CommandParameterKinds.string;\n\n (option as StringCommandParameter | NumberCommandParameter).choices =\n type.types\n .map(t =>\n t.kind === ReflectionKind.literal\n ? isNumber(t.literal)\n ? t.literal\n : isBigInt(t.literal)\n ? Number(t.literal)\n : isRegExp(t.literal)\n ? t.literal.source\n : String(t.literal)\n : null\n )\n .filter(Boolean) as string[] | number[];\n } else if (type.kind === ReflectionKind.literal) {\n (option as StringCommandParameter | NumberCommandParameter).choices = [\n isNumber(type.literal)\n ? type.literal\n : isBigInt(type.literal)\n ? Number(type.literal)\n : isRegExp(type.literal)\n ? type.literal.source\n : String(type.literal)\n ].filter(Boolean) as string[] | number[];\n } else if (\n !existing.kind &&\n type.kind !== ReflectionKind.boolean &&\n type.kind !== ReflectionKind.string &&\n type.kind !== ReflectionKind.number\n ) {\n throw new Error(\n `Unsupported type for option \"${reflection.getNameAsString()}\" in command \"${\n ctx.input.command.name\n }\". Only string, number, boolean, string[], number[], or literal[] are supported, received ${stringifyType(\n type\n )\n .trim()\n .replaceAll(\" | \", \", or \")}.`\n );\n }\n\n return mergeCommandParameter(existing, option) as CommandOption;\n}\n\nfunction resolveCommandArgument(\n ctx: ResolverContext,\n index: number,\n reflection: ReflectionParameter\n): CommandArgument {\n const type = reflection.getType();\n const existing = (\n ctx.output.args.length > index ? ctx.output.args[index] : {}\n ) as Partial<CommandArgument>;\n\n const argument = {\n name: reflection.getName() || reflection.parameter.name,\n alias: reflection.getAlias(),\n kind: extractCommandParameterKind(type.kind),\n title: reflection.getTitle() || reflection.parameter.tags?.title,\n description: reflection.parameter.description,\n optional: reflection.isOptional(),\n default: reflection.getDefaultValue()\n };\n\n if (type.kind === ReflectionKind.array) {\n if (\n type.type.kind === ReflectionKind.string ||\n type.type.kind === ReflectionKind.number\n ) {\n (argument as StringCommandParameter | NumberCommandParameter).variadic =\n true;\n (argument as StringCommandParameter | NumberCommandParameter).kind =\n extractCommandParameterKind(type.type.kind) as \"string\" | \"number\";\n } else {\n throw new Error(\n `Unsupported array type for positional argument \"${argument.name}\" in command \"${\n ctx.input.command.name\n }\". Only string[], number[], or literal[] are supported, received ${stringifyType(\n type\n )\n .trim()\n .replaceAll(\" | \", \", or \")}.`\n );\n }\n } else if (type.kind === ReflectionKind.union) {\n argument.kind = type.types.every(\n t =>\n t.kind === ReflectionKind.number ||\n (t.kind === ReflectionKind.literal &&\n (isNumber(t.literal) || isBigInt(t.literal)))\n )\n ? CommandParameterKinds.number\n : CommandParameterKinds.string;\n\n (argument as StringCommandParameter | NumberCommandParameter).choices =\n type.types\n .map(t =>\n t.kind === ReflectionKind.literal\n ? isNumber(t.literal)\n ? t.literal\n : isBigInt(t.literal)\n ? Number(t.literal)\n : isRegExp(t.literal)\n ? t.literal.source\n : String(t.literal)\n : null\n )\n .filter(Boolean) as string[] | number[];\n } else if (type.kind === ReflectionKind.literal) {\n (argument as StringCommandParameter | NumberCommandParameter).choices = [\n isNumber(type.literal)\n ? type.literal\n : isBigInt(type.literal)\n ? Number(type.literal)\n : isRegExp(type.literal)\n ? type.literal.source\n : String(type.literal)\n ].filter(Boolean) as string[] | number[];\n } else if (\n !ctx.output.args?.length &&\n type.kind !== ReflectionKind.boolean &&\n type.kind !== ReflectionKind.string &&\n type.kind !== ReflectionKind.number\n ) {\n throw new Error(\n `Unsupported type for positional argument \"${argument.name}\" in command \"${\n ctx.input.command.name\n }\". Only string, number, boolean, string[], number[], or literal[] are supported, received ${stringifyType(\n type\n )\n .trim()\n .replaceAll(\" | \", \", or \")}.`\n );\n }\n\n return mergeCommandParameter(existing, argument, {\n name: `arg${index}`\n }) as CommandArgument;\n}\n\nexport function resolveFromBytecode<TContext extends Context = Context>(\n ctx: ResolverContext<TContext>\n) {\n const { input, module } = ctx;\n\n const type = reflect(module);\n if (type.kind !== ReflectionKind.function) {\n throw new Error(\n `The command entry file \"${\n input.command.entry.input?.file || input.command.path\n }\" does not export a valid function.`\n );\n }\n\n const reflection = new ReflectionFunction(type);\n\n ctx.output.description ??= (ctx.input.command.description ||\n reflection.getDescription() ||\n type.description)!;\n\n const parameters = reflection.getParameters();\n if (parameters.length > 0) {\n const hasOptions =\n parameters[0] &&\n (parameters[0].type.kind === ReflectionKind.objectLiteral ||\n parameters[0].type.kind === ReflectionKind.class);\n if (hasOptions) {\n const optionsReflection = ReflectionClass.from(parameters[0]?.type);\n for (const propertyReflection of optionsReflection.getProperties()) {\n ctx.output.options[propertyReflection.getNameAsString()] =\n resolveCommandOption(ctx, propertyReflection);\n }\n }\n\n ctx.output.args = (hasOptions ? parameters.slice(1) : parameters).map(\n (arg, index) => resolveCommandArgument(ctx, index, arg)\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"deepkit.mjs","names":[],"sources":["../../src/resolver/deepkit.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Shell Shock\n\n This code was released as part of the Shell Shock project. Shell Shock\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/shell-shock.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/shell-shock\n Documentation: https://docs.stormsoftware.com/projects/shell-shock\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport type {\n ReflectionParameter,\n ReflectionProperty,\n Type,\n TypeArray\n} from \"@powerlines/deepkit/vendor/type\";\nimport {\n reflect,\n ReflectionClass,\n ReflectionFunction,\n ReflectionKind,\n stringifyType\n} from \"@powerlines/deepkit/vendor/type\";\nimport { isBigInt } from \"@stryke/type-checks/is-bigint\";\nimport { isNumber } from \"@stryke/type-checks/is-number\";\nimport { isRegExp } from \"@stryke/type-checks/is-regexp\";\nimport { isSetObject } from \"@stryke/type-checks/is-set-object\";\nimport type {\n CommandArgument,\n CommandOption,\n CommandParameterKind,\n Context,\n NumberCommandParameter,\n StringCommandParameter\n} from \"../types\";\nimport { CommandParameterKinds } from \"../types\";\nimport { mergeCommandParameter } from \"./helpers\";\nimport type { ResolverContext } from \"./types\";\n\nfunction extractCommandParameterKind(\n type: Type | ReflectionKind\n): CommandParameterKind {\n const isKind = !(isSetObject(type) && \"kind\" in type);\n const kind = !isKind ? type.kind : type;\n if (kind === ReflectionKind.string) {\n return CommandParameterKinds.string;\n } else if (\n kind === ReflectionKind.number ||\n kind === ReflectionKind.bigint ||\n (!isKind &&\n type.kind === ReflectionKind.literal &&\n (isNumber(type.literal) || isBigInt(type.literal)))\n ) {\n return CommandParameterKinds.number;\n } else if (kind === ReflectionKind.boolean) {\n return CommandParameterKinds.boolean;\n } else {\n return CommandParameterKinds.string;\n }\n}\n\nfunction resolveCommandOption(\n ctx: ResolverContext,\n reflection: ReflectionProperty\n): CommandOption {\n const type = reflection.getType();\n const existing = (ctx.output.options[reflection.getNameAsString()] ??\n {}) as Partial<CommandOption>;\n\n const option = {\n name: reflection.getNameAsString(),\n alias: reflection.getTags().alias ?? [],\n title: reflection.getTags().title?.trim(),\n description: reflection.getDescription(),\n kind: extractCommandParameterKind(type),\n optional: reflection.isOptional(),\n default: reflection.getDefaultValue(),\n variadic: reflection.isArray()\n };\n\n if (option.variadic) {\n option.kind = extractCommandParameterKind((type as TypeArray).type.kind);\n } else if (type.kind === ReflectionKind.union) {\n option.kind = type.types.every(\n t =>\n t.kind === ReflectionKind.number ||\n (t.kind === ReflectionKind.literal &&\n (isNumber(t.literal) || isBigInt(t.literal)))\n )\n ? CommandParameterKinds.number\n : CommandParameterKinds.string;\n\n (option as StringCommandParameter | NumberCommandParameter).choices =\n type.types\n .map(t =>\n t.kind === ReflectionKind.literal\n ? isNumber(t.literal)\n ? t.literal\n : isBigInt(t.literal)\n ? Number(t.literal)\n : isRegExp(t.literal)\n ? t.literal.source\n : String(t.literal)\n : null\n )\n .filter(Boolean) as string[] | number[];\n } else if (type.kind === ReflectionKind.literal) {\n (option as StringCommandParameter | NumberCommandParameter).choices = [\n isNumber(type.literal)\n ? type.literal\n : isBigInt(type.literal)\n ? Number(type.literal)\n : isRegExp(type.literal)\n ? type.literal.source\n : String(type.literal)\n ].filter(Boolean) as string[] | number[];\n } else if (\n !existing.kind &&\n type.kind !== ReflectionKind.boolean &&\n type.kind !== ReflectionKind.string &&\n type.kind !== ReflectionKind.number\n ) {\n throw new Error(\n `Unsupported type for option \"${reflection.getNameAsString()}\" in command \"${\n ctx.input.command.name\n }\". Only string, number, boolean, string[], number[], or literal[] are supported, received ${stringifyType(\n type\n )\n .trim()\n .replaceAll(\" | \", \", or \")}.`\n );\n }\n\n return mergeCommandParameter(existing, option) as CommandOption;\n}\n\nfunction resolveCommandArgument(\n ctx: ResolverContext,\n index: number,\n reflection: ReflectionParameter\n): CommandArgument {\n const type = reflection.getType();\n const existing = (\n ctx.output.args.length > index ? ctx.output.args[index] : {}\n ) as Partial<CommandArgument>;\n\n const argument = {\n name: reflection.getName() || reflection.parameter.name,\n alias: reflection.getAlias(),\n kind: extractCommandParameterKind(type.kind),\n title: reflection.getTitle() || reflection.parameter.tags?.title,\n description: reflection.parameter.description,\n optional: reflection.isOptional(),\n default: reflection.getDefaultValue() || reflection.parameter.default\n };\n\n if (type.kind === ReflectionKind.array) {\n if (\n type.type.kind === ReflectionKind.string ||\n type.type.kind === ReflectionKind.number\n ) {\n (argument as StringCommandParameter | NumberCommandParameter).variadic =\n true;\n (argument as StringCommandParameter | NumberCommandParameter).kind =\n extractCommandParameterKind(type.type.kind) as \"string\" | \"number\";\n } else {\n throw new Error(\n `Unsupported array type for positional argument \"${argument.name}\" in command \"${\n ctx.input.command.name\n }\". Only string[], number[], or literal[] are supported, received ${stringifyType(\n type\n )\n .trim()\n .replaceAll(\" | \", \", or \")}.`\n );\n }\n } else if (type.kind === ReflectionKind.union) {\n argument.kind = type.types.every(\n t =>\n t.kind === ReflectionKind.number ||\n (t.kind === ReflectionKind.literal &&\n (isNumber(t.literal) || isBigInt(t.literal)))\n )\n ? CommandParameterKinds.number\n : CommandParameterKinds.string;\n\n (argument as StringCommandParameter | NumberCommandParameter).choices =\n type.types\n .map(t =>\n t.kind === ReflectionKind.literal\n ? isNumber(t.literal)\n ? t.literal\n : isBigInt(t.literal)\n ? Number(t.literal)\n : isRegExp(t.literal)\n ? t.literal.source\n : String(t.literal)\n : null\n )\n .filter(Boolean) as string[] | number[];\n } else if (type.kind === ReflectionKind.literal) {\n (argument as StringCommandParameter | NumberCommandParameter).choices = [\n isNumber(type.literal)\n ? type.literal\n : isBigInt(type.literal)\n ? Number(type.literal)\n : isRegExp(type.literal)\n ? type.literal.source\n : String(type.literal)\n ].filter(Boolean) as string[] | number[];\n } else if (\n !ctx.output.args?.length &&\n type.kind !== ReflectionKind.boolean &&\n type.kind !== ReflectionKind.string &&\n type.kind !== ReflectionKind.number\n ) {\n throw new Error(\n `Unsupported type for positional argument \"${argument.name}\" in command \"${\n ctx.input.command.name\n }\". Only string, number, boolean, string[], number[], or literal[] are supported, received ${stringifyType(\n type\n )\n .trim()\n .replaceAll(\" | \", \", or \")}.`\n );\n }\n\n return mergeCommandParameter(existing, argument, {\n name: `arg${index}`\n }) as CommandArgument;\n}\n\nexport function resolveFromBytecode<TContext extends Context = Context>(\n ctx: ResolverContext<TContext>\n) {\n const { input, module } = ctx;\n\n const type = reflect(module);\n if (type.kind !== ReflectionKind.function) {\n throw new Error(\n `The command entry file \"${\n input.command.entry.input?.file || input.command.path\n }\" does not export a valid function.`\n );\n }\n\n const reflection = new ReflectionFunction(type);\n\n ctx.output.description ??= (ctx.input.command.description ||\n reflection.getDescription() ||\n type.description)!;\n\n const parameters = reflection.getParameters();\n if (parameters.length > 0) {\n const hasOptions =\n parameters[0] &&\n (parameters[0].type.kind === ReflectionKind.objectLiteral ||\n parameters[0].type.kind === ReflectionKind.class);\n if (hasOptions) {\n const optionsReflection = ReflectionClass.from(parameters[0]?.type);\n for (const propertyReflection of optionsReflection.getProperties()) {\n ctx.output.options[propertyReflection.getNameAsString()] =\n resolveCommandOption(ctx, propertyReflection);\n }\n }\n\n ctx.output.args = (hasOptions ? parameters.slice(1) : parameters).map(\n (arg, index) => resolveCommandArgument(ctx, index, arg)\n );\n }\n}\n"],"mappings":"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"}