@shell-shock/core 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +1 -1
  2. package/dist/components/docs.d.cts +5 -5
  3. package/dist/components/index.cjs +1 -1
  4. package/dist/components/index.d.cts +2 -2
  5. package/dist/components/index.d.mts +2 -2
  6. package/dist/components/index.mjs +2 -2
  7. package/dist/components/options-parser-logic.cjs +17 -22
  8. package/dist/components/options-parser-logic.cjs.map +1 -1
  9. package/dist/components/options-parser-logic.d.cts +4 -8
  10. package/dist/components/options-parser-logic.d.cts.map +1 -1
  11. package/dist/components/options-parser-logic.d.mts +4 -8
  12. package/dist/components/options-parser-logic.d.mts.map +1 -1
  13. package/dist/components/options-parser-logic.mjs +18 -23
  14. package/dist/components/options-parser-logic.mjs.map +1 -1
  15. package/dist/components/usage.cjs +1 -1
  16. package/dist/components/usage.cjs.map +1 -1
  17. package/dist/components/usage.d.cts +2 -2
  18. package/dist/components/usage.d.mts +2 -2
  19. package/dist/components/usage.mjs +2 -2
  20. package/dist/components/usage.mjs.map +1 -1
  21. package/dist/helpers/resolve-command.cjs +20 -31
  22. package/dist/helpers/resolve-command.cjs.map +1 -1
  23. package/dist/helpers/resolve-command.mjs +21 -32
  24. package/dist/helpers/resolve-command.mjs.map +1 -1
  25. package/dist/helpers/validations.cjs +20 -20
  26. package/dist/helpers/validations.cjs.map +1 -1
  27. package/dist/helpers/validations.mjs +21 -21
  28. package/dist/helpers/validations.mjs.map +1 -1
  29. package/dist/index.d.cts +2 -2
  30. package/dist/index.d.mts +2 -2
  31. package/dist/plugin-utils/context-helpers.cjs +106 -5
  32. package/dist/plugin-utils/context-helpers.cjs.map +1 -1
  33. package/dist/plugin-utils/context-helpers.d.cts +89 -3
  34. package/dist/plugin-utils/context-helpers.d.cts.map +1 -1
  35. package/dist/plugin-utils/context-helpers.d.mts +89 -3
  36. package/dist/plugin-utils/context-helpers.d.mts.map +1 -1
  37. package/dist/plugin-utils/context-helpers.mjs +100 -4
  38. package/dist/plugin-utils/context-helpers.mjs.map +1 -1
  39. package/dist/plugin-utils/get-command-tree.cjs +1 -1
  40. package/dist/plugin-utils/get-command-tree.cjs.map +1 -1
  41. package/dist/plugin-utils/get-command-tree.mjs +2 -2
  42. package/dist/plugin-utils/get-command-tree.mjs.map +1 -1
  43. package/dist/plugin-utils/index.cjs +7 -2
  44. package/dist/plugin-utils/index.d.cts +2 -2
  45. package/dist/plugin-utils/index.d.mts +2 -2
  46. package/dist/plugin-utils/index.mjs +2 -2
  47. package/dist/plugin.cjs +1 -1
  48. package/dist/plugin.cjs.map +1 -1
  49. package/dist/plugin.d.cts.map +1 -1
  50. package/dist/plugin.d.mts.map +1 -1
  51. package/dist/plugin.mjs +2 -2
  52. package/dist/plugin.mjs.map +1 -1
  53. package/dist/types/command.d.cts +20 -3
  54. package/dist/types/command.d.cts.map +1 -1
  55. package/dist/types/command.d.mts +20 -3
  56. package/dist/types/command.d.mts.map +1 -1
  57. package/dist/types/index.d.cts +2 -2
  58. package/dist/types/index.d.mts +2 -2
  59. package/package.json +6 -6
@@ -1,4 +1,4 @@
1
- import { getAppTitle, getPositionalCommandOptionName, isPositionalCommandOption } from "../plugin-utils/context-helpers.mjs";
1
+ import { getAppTitle, getDynamicPathSegmentName, isCatchAllPathSegment, isDynamicPathSegment, isOptionalCatchAllPathSegment, isPathSegmentGroup } from "../plugin-utils/context-helpers.mjs";
2
2
  import { getDefaultOptions } from "./utilities.mjs";
3
3
  import { toArray } from "@stryke/convert/to-array";
4
4
  import { appendPath } from "@stryke/path/append";
@@ -30,7 +30,7 @@ function resolveCommandOptionDescription(kind, optional, name, title, defaultVal
30
30
  return `A${optional && !defaultValue ? "n optional" : ""} ${kind === ReflectionKind.boolean ? "flag provided via the command-line" : "command-line option"} that allows the user to ${kind === ReflectionKind.boolean ? "set the" : kind === ReflectionKind.array ? "specify custom" : "specify a custom"} ${title?.trim() || titleCase(name)} ${kind === ReflectionKind.boolean ? "indicator" : `${kind === ReflectionKind.number ? "numeric" : "string"} value${kind === ReflectionKind.array ? "s" : ""}`} that will be used in the application.`;
31
31
  }
32
32
  function resolveCommandId(context, file) {
33
- return replacePath(findFilePath(file), context.commandsPath).split("/").filter((p) => Boolean(p) && !isPositionalCommandOption(p)).join("/").replaceAll(/^\/+/g, "").replaceAll(/\/+$/g, "").replaceAll("/", "-");
33
+ return replacePath(findFilePath(file), context.commandsPath).split("/").filter((p) => Boolean(p) && !isDynamicPathSegment(p)).join("/").replaceAll(/^\/+/g, "").replaceAll(/\/+$/g, "").replaceAll("/", "-");
34
34
  }
35
35
  /**
36
36
  * Finds the command name from the given file path.
@@ -41,14 +41,14 @@ function resolveCommandId(context, file) {
41
41
  function resolveCommandName(file) {
42
42
  let path = findFilePath(file);
43
43
  let name = findFolderName(file, { requireExtension: true });
44
- while (isPositionalCommandOption(name)) {
44
+ while (isDynamicPathSegment(name)) {
45
45
  path = resolveParentPath(path);
46
46
  name = findFolderName(path, { requireExtension: true });
47
47
  }
48
48
  return name;
49
49
  }
50
50
  function resolveCommandPath(context, file) {
51
- return replacePath(findFilePath(file), context.commandsPath).replaceAll(/^\/+/g, "").replaceAll(/\/+$/g, "");
51
+ return replacePath(findFilePath(file), context.commandsPath).replaceAll(/^\/+/g, "").replaceAll(/\/+$/g, "").split("/").filter((path) => path && !isPathSegmentGroup(path)).join("/");
52
52
  }
53
53
  function findCommandsRoot(context) {
54
54
  if (isSetString(context.config.entry)) return appendPath(appendPath(stripStars(context.config.entry), context.config.projectRoot), context.workspaceConfig.workspaceRoot);
@@ -91,23 +91,24 @@ function extractCommandOption(command, reflection) {
91
91
  * @param reflection - The type parameter reflection to extract information from.
92
92
  * @returns The extracted command option information.
93
93
  */
94
- function extractCommandPositionalOption(command, segment, reflection) {
95
- if (reflection.type.kind !== ReflectionKind.string && reflection.type.kind !== ReflectionKind.number && !(reflection.type.kind === ReflectionKind.array && (reflection.type.type.kind === ReflectionKind.string || reflection.type.type.kind === ReflectionKind.number))) throw new Error(`Unsupported type for positional option "${segment}" in command "${command.name}". Only string and number types (or string[] and number[]) are supported, received ${stringifyType(reflection.type).trim().replaceAll(" | ", ", or ")}.`);
94
+ function extractCommandDynamicSegment(command, segment, reflection) {
95
+ if (reflection.type.kind !== ReflectionKind.string && !(reflection.type.kind === ReflectionKind.array && reflection.type.type.kind === ReflectionKind.string)) throw new Error(`Unsupported type for dynamic path segment "${segment}" in command "${command.name}". Only string types (or an array of strings) are supported, received ${stringifyType(reflection.type).trim().replaceAll(" | ", ", or ")}.`);
96
96
  const option = {
97
97
  name: segment,
98
- alias: [],
99
98
  title: titleCase(segment),
100
- description: reflection.description || resolveCommandOptionDescription(reflection.type.kind, !!reflection.optional, segment, titleCase(segment), reflection.default),
101
- env: constantCase(segment),
102
- kind: reflection.type.kind,
99
+ description: reflection.description || resolveCommandOptionDescription(ReflectionKind.string, !!reflection.optional, segment, titleCase(segment), reflection.default),
103
100
  optional: reflection.optional,
104
101
  default: reflection.default,
105
- variadic: false
102
+ catchAll: command.path.segments.some((seg) => getDynamicPathSegmentName(segment) === seg && isCatchAllPathSegment(seg))
106
103
  };
107
- if (reflection.type.kind === ReflectionKind.array) if (reflection.type.type.kind === ReflectionKind.string || reflection.type.type.kind === ReflectionKind.number) {
104
+ if (reflection.type.kind === ReflectionKind.array) {
105
+ if (!option.catchAll) throw new Error(`Dynamic path segment "${segment}" in command "${command.name}" is an array type but is not defined as a catch-all segment. To use an array type for a dynamic path segment, it must be defined as a catch-all segment using the "[...segment]" syntax.`);
108
106
  option.variadic = true;
109
- option.kind = reflection.type.type.kind;
110
- } else throw new Error(`Unsupported array type for option "${segment}" in command "${command.name}". Only string[] and number[] are supported.`);
107
+ }
108
+ if (option.catchAll) {
109
+ if (!option.optional && command.path.segments.some((seg) => getDynamicPathSegmentName(segment) === seg && isOptionalCatchAllPathSegment(seg))) throw new Error(`Dynamic path segment "${segment}" in command "${command.name}" is defined as a catch-all segment but is not optional. To define an optional catch-all segment, use the "[[...segment]]" syntax.`);
110
+ else if (option.optional && !command.path.segments.some((seg) => getDynamicPathSegmentName(segment) === seg && isOptionalCatchAllPathSegment(seg))) throw new Error(`Dynamic path segment "${segment}" in command "${command.name}" is defined as an optional segment but is not defined as an optional catch-all segment. To define an optional catch-all segment, use the "[[...segment]]" syntax.`);
111
+ }
111
112
  return option;
112
113
  }
113
114
  /**
@@ -126,7 +127,7 @@ async function reflectCommandTree(context, command, parent) {
126
127
  title,
127
128
  path: {
128
129
  ...command.path,
129
- positional: {}
130
+ dynamics: {}
130
131
  },
131
132
  options: getDefaultOptions(context, command),
132
133
  parent: parent ?? null,
@@ -152,11 +153,11 @@ async function reflectCommandTree(context, command, parent) {
152
153
  const optionsReflection = ReflectionClass.from(firstParam.type);
153
154
  for (const propertyReflection of optionsReflection.getProperties()) tree.options[propertyReflection.getNameAsString()] = extractCommandOption(command, propertyReflection);
154
155
  }
155
- tree.path.positional = tree.path.segments.filter((segment) => isPositionalCommandOption(segment)).reduce((obj, segment, index) => {
156
+ tree.path.dynamics = tree.path.segments.filter((segment) => isDynamicPathSegment(segment)).reduce((obj, segment, index) => {
156
157
  if (type.parameters.length < index + 2 || !type.parameters[index + 1]) return obj;
157
- const paramName = getPositionalCommandOptionName(segment);
158
- obj[paramName] = extractCommandPositionalOption(command, paramName, type.parameters[index + 1]);
159
- obj[paramName].description = obj[paramName].description || `The ${paramName} positional option for the ${command.name} command.`;
158
+ const paramName = getDynamicPathSegmentName(segment);
159
+ obj[paramName] = extractCommandDynamicSegment(command, paramName, type.parameters[index + 1]);
160
+ obj[paramName].description = obj[paramName].description || `The ${paramName} ${obj[paramName].catchAll ? `${obj[paramName].optional ? "optional " : ""}catch-all` : "dynamic "} segment for the ${command.name} command.`;
160
161
  return obj;
161
162
  }, {});
162
163
  }
@@ -180,20 +181,8 @@ async function reflectCommandTree(context, command, parent) {
180
181
  }
181
182
  });
182
183
  });
183
- if (Object.values(tree.path.positional).filter((option) => option.env !== false).length > 0) Object.values(tree.path.positional).filter((option) => option.env !== false).forEach((option) => context.env.types.env.addProperty({
184
- name: constantCase(option.name),
185
- optional: option.optional ? true : void 0,
186
- description: option.description,
187
- visibility: ReflectionVisibility.public,
188
- type: option.variadic ? {
189
- kind: ReflectionKind.array,
190
- type: { kind: ReflectionKind.string }
191
- } : { kind: ReflectionKind.string },
192
- default: option.default,
193
- tags: { domain: "cli" }
194
- }));
195
184
  }
196
- for (const input of context.inputs.filter((input$1) => input$1.path.segments.filter((segment) => !isPositionalCommandOption(segment)).length === command.path.segments.filter((segment) => !isPositionalCommandOption(segment)).length + 1 && input$1.path.segments.slice(0, command.path.segments.length).every((value, index) => value === command.path.segments[index]))) tree.children[input.name] = await reflectCommandTree(context, input, tree);
185
+ for (const input of context.inputs.filter((input$1) => input$1.path.segments.filter((segment) => !isDynamicPathSegment(segment)).length === command.path.segments.filter((segment) => !isDynamicPathSegment(segment)).length + 1 && input$1.path.segments.slice(0, command.path.segments.length).every((value, index) => value === command.path.segments[index]))) tree.children[input.name] = await reflectCommandTree(context, input, tree);
197
186
  return tree;
198
187
  }
199
188
 
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-command.mjs","names":["esbuildPlugin","reflect","ReflectionClass","ReflectionKind","ReflectionVisibility","stringifyType","toArray","appendPath","commonPath","findFilePath","findFolderName","stripStars","replacePath","resolveParentPath","constantCase","titleCase","isSetObject","isSetString","resolveModule","getAppTitle","getPositionalCommandOptionName","isPositionalCommandOption","getDefaultOptions","resolveCommandOptionDescription","kind","optional","name","title","defaultValue","boolean","array","trim","number","resolveCommandId","context","file","commandsPath","split","filter","p","Boolean","join","replaceAll","resolveCommandName","path","requireExtension","resolveCommandPath","resolveCommandParams","map","findCommandsRoot","config","entry","projectRoot","workspaceConfig","workspaceRoot","Array","isArray","length","sourceRoot","extractCommandOption","command","reflection","propertyType","getType","option","getNameAsString","alias","getTags","description","getDescription","getKind","isOptional","getDefaultValue","env","default","variadic","type","string","Error","extractCommandPositionalOption","segment","reflectCommandTree","parent","isVirtual","replace","tree","positional","options","children","input","fs","existsSync","debug","id","resolved","plugins","reflectionLevel","metadata","function","parameters","firstParam","objectLiteral","class","optionsReflection","from","propertyReflection","getProperties","segments","reduce","obj","index","paramName","Object","values","forEach","types","addProperty","undefined","visibility","public","tags","domain","inputs","slice","every","value"],"sources":["../../src/helpers/resolve-command.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 { esbuildPlugin } from \"@powerlines/deepkit/esbuild-plugin\";\nimport type {\n ReflectionProperty,\n TypeParameter\n} from \"@powerlines/deepkit/vendor/type\";\nimport {\n reflect,\n ReflectionClass,\n ReflectionKind,\n ReflectionVisibility,\n stringifyType\n} from \"@powerlines/deepkit/vendor/type\";\nimport { toArray } from \"@stryke/convert/to-array\";\nimport { appendPath } from \"@stryke/path/append\";\nimport { commonPath } from \"@stryke/path/common\";\nimport { findFilePath, findFolderName } from \"@stryke/path/file-path-fns\";\nimport { stripStars } from \"@stryke/path/normalize\";\nimport { replacePath } from \"@stryke/path/replace\";\nimport { resolveParentPath } from \"@stryke/path/resolve-parent-path\";\nimport { constantCase } from \"@stryke/string-format/constant-case\";\nimport { titleCase } from \"@stryke/string-format/title-case\";\nimport { isSetObject } from \"@stryke/type-checks/is-set-object\";\nimport { isSetString } from \"@stryke/type-checks/is-set-string\";\nimport { resolveModule } from \"powerlines/lib/utilities/resolve\";\nimport {\n getAppTitle,\n getPositionalCommandOptionName,\n isPositionalCommandOption\n} from \"../plugin-utils/context-helpers\";\nimport type {\n CommandInput,\n CommandModule,\n CommandOption,\n CommandPositionalOption,\n CommandTree,\n NumberCommandOption,\n StringCommandOption\n} from \"../types/command\";\nimport type { Context } from \"../types/context\";\nimport { getDefaultOptions } from \"./utilities\";\n\n/**\n * Resolves the description for a command option based on its reflection.\n *\n * @param kind - The reflection kind of the command option.\n * @param optional - Whether the command option is optional.\n * @param name - The name of the command option.\n * @param title - The title of the command option, if any.\n * @param defaultValue - The default value of the command option, if any.\n * @returns The resolved description for the command option.\n */\nexport function resolveCommandOptionDescription(\n kind: ReflectionKind,\n optional: boolean,\n name: string,\n title?: string,\n defaultValue?: any\n): string {\n return `A${optional && !defaultValue ? \"n optional\" : \"\"} ${\n kind === ReflectionKind.boolean\n ? \"flag provided via the command-line\"\n : \"command-line option\"\n } that allows the user to ${\n kind === ReflectionKind.boolean\n ? \"set the\"\n : kind === ReflectionKind.array\n ? \"specify custom\"\n : \"specify a custom\"\n } ${title?.trim() || titleCase(name)} ${\n kind === ReflectionKind.boolean\n ? \"indicator\"\n : `${kind === ReflectionKind.number ? \"numeric\" : \"string\"} value${\n kind === ReflectionKind.array ? \"s\" : \"\"\n }`\n } that will be used in the application.`;\n}\n\nexport function resolveCommandId(context: Context, file: string): string {\n return replacePath(findFilePath(file), context.commandsPath)\n .split(\"/\")\n .filter(p => Boolean(p) && !isPositionalCommandOption(p))\n .join(\"/\")\n .replaceAll(/^\\/+/g, \"\")\n .replaceAll(/\\/+$/g, \"\")\n .replaceAll(\"/\", \"-\");\n}\n\n/**\n * Finds the command name from the given file path.\n *\n * @param file - The file path to extract the command name from.\n * @returns The command name.\n */\nexport function resolveCommandName(file: string) {\n let path = findFilePath(file);\n let name = findFolderName(file, {\n requireExtension: true\n });\n\n while (isPositionalCommandOption(name)) {\n path = resolveParentPath(path);\n name = findFolderName(path, {\n requireExtension: true\n });\n }\n\n return name;\n}\n\nexport function resolveCommandPath(context: Context, file: string): string {\n return replacePath(findFilePath(file), context.commandsPath)\n .replaceAll(/^\\/+/g, \"\")\n .replaceAll(/\\/+$/g, \"\");\n}\n\nexport function resolveCommandParams(context: Context, file: string): string[] {\n return replacePath(findFilePath(file), context.commandsPath)\n .split(\"/\")\n .filter(p => Boolean(p) && isPositionalCommandOption(p))\n .map(p => p.replaceAll(/^\\[+/g, \"\").replaceAll(/\\]+$/g, \"\"));\n}\n\nexport function findCommandsRoot(context: Context): string {\n if (isSetString(context.config.entry)) {\n return appendPath(\n appendPath(stripStars(context.config.entry), context.config.projectRoot),\n context.workspaceConfig.workspaceRoot\n );\n } else if (\n isSetObject(context.config.entry) &&\n \"file\" in context.config.entry\n ) {\n return appendPath(\n appendPath(\n stripStars(context.config.entry.file),\n context.config.projectRoot\n ),\n context.workspaceConfig.workspaceRoot\n );\n } else if (\n Array.isArray(context.config.entry) &&\n context.config.entry.length > 0\n ) {\n return commonPath(\n context.config.entry.map(entry =>\n appendPath(\n appendPath(\n stripStars(isSetString(entry) ? entry : entry.file),\n context.config.projectRoot\n ),\n context.workspaceConfig.workspaceRoot\n )\n )\n );\n }\n\n return appendPath(\n context.config.sourceRoot || context.config.projectRoot,\n context.workspaceConfig.workspaceRoot\n );\n}\n\n/**\n * Extracts command parameter information from a type parameter reflection.\n *\n * @param command - The command tree to which the parameter belongs.\n * @param reflection - The type parameter reflection to extract information from.\n * @returns The extracted command option information.\n */\nexport function extractCommandOption(\n command: CommandInput,\n reflection: ReflectionProperty\n): CommandOption {\n const propertyType = reflection.getType();\n\n const option = {\n name: reflection.getNameAsString(),\n alias: reflection.getTags().alias ?? [],\n title:\n reflection.getTags().title?.trim() ||\n titleCase(reflection.getNameAsString()),\n description:\n reflection.getDescription() ||\n resolveCommandOptionDescription(\n reflection.getKind(),\n reflection.isOptional(),\n reflection.getNameAsString(),\n reflection.getTags().title,\n reflection.getDefaultValue()\n ),\n env: constantCase(reflection.getNameAsString()),\n kind: propertyType.kind as\n | ReflectionKind.string\n | ReflectionKind.number\n | ReflectionKind.boolean,\n optional: reflection.isOptional(),\n default: reflection.getDefaultValue(),\n variadic: false\n } as CommandOption;\n if (propertyType.kind === ReflectionKind.array) {\n if (\n propertyType.type.kind === ReflectionKind.string ||\n propertyType.type.kind === ReflectionKind.number\n ) {\n (option as StringCommandOption | NumberCommandOption).variadic = true;\n (option as StringCommandOption | NumberCommandOption).kind =\n propertyType.type.kind;\n } else {\n throw new Error(\n `Unsupported array type for option \"${reflection.getNameAsString()}\" in command \"${\n command.name\n }\". Only string[] and number[] are supported.`\n );\n }\n } else if (\n propertyType.kind !== ReflectionKind.boolean &&\n propertyType.kind !== ReflectionKind.string &&\n propertyType.kind !== ReflectionKind.number\n ) {\n throw new Error(\n `Unsupported type for option \"${reflection.getNameAsString()}\" in command \"${\n command.name\n }\". Only string, number, boolean, string[] and number[] are supported, received ${stringifyType(\n propertyType\n )\n .trim()\n .replaceAll(\" | \", \", or \")}.`\n );\n }\n\n return option;\n}\n\n/**\n * Extracts command parameter information from a type parameter reflection.\n *\n * @param command - The command tree to which the parameter belongs.\n * @param segment - The command path segment corresponding to the parameter.\n * @param reflection - The type parameter reflection to extract information from.\n * @returns The extracted command option information.\n */\nexport function extractCommandPositionalOption(\n command: CommandInput,\n segment: string,\n reflection: TypeParameter\n): CommandPositionalOption {\n if (\n reflection.type.kind !== ReflectionKind.string &&\n reflection.type.kind !== ReflectionKind.number &&\n !(\n reflection.type.kind === ReflectionKind.array &&\n (reflection.type.type.kind === ReflectionKind.string ||\n reflection.type.type.kind === ReflectionKind.number)\n )\n ) {\n throw new Error(\n `Unsupported type for positional option \"${segment}\" in command \"${\n command.name\n }\". Only string and number types (or string[] and number[]) are supported, received ${stringifyType(\n reflection.type\n )\n .trim()\n .replaceAll(\" | \", \", or \")}.`\n );\n }\n\n const option = {\n name: segment,\n alias: [],\n title: titleCase(segment),\n description:\n reflection.description ||\n resolveCommandOptionDescription(\n reflection.type.kind,\n !!reflection.optional,\n segment,\n titleCase(segment),\n reflection.default\n ),\n env: constantCase(segment),\n kind: reflection.type.kind,\n optional: reflection.optional,\n default: reflection.default,\n variadic: false\n } as CommandPositionalOption;\n\n if (reflection.type.kind === ReflectionKind.array) {\n if (\n reflection.type.type.kind === ReflectionKind.string ||\n reflection.type.type.kind === ReflectionKind.number\n ) {\n (option as StringCommandOption | NumberCommandOption).variadic = true;\n (option as StringCommandOption | NumberCommandOption).kind =\n reflection.type.type.kind;\n } else {\n throw new Error(\n `Unsupported array type for option \"${segment}\" in command \"${\n command.name\n }\". Only string[] and number[] are supported.`\n );\n }\n }\n\n return option;\n}\n\n/**\n * Reflects the command tree for a given command input.\n *\n * @param context - The context in which the command is being reflected.\n * @param command - The command input to reflect.\n * @param parent - The parent command tree, if any.\n * @returns The reflected command tree.\n */\nexport async function reflectCommandTree<TContext extends Context = Context>(\n context: TContext,\n command: CommandInput,\n parent?: CommandTree\n): Promise<CommandTree> {\n const title =\n command.title ||\n `${parent?.title ? `${parent.isVirtual ? parent.title.replace(/ Commands$/, \"\") : parent.title} - ` : \"\"}${titleCase(command.name)}${\n command.isVirtual ? \" Commands\" : \"\"\n }`;\n\n const tree = {\n alias: [],\n ...command,\n title,\n path: {\n ...command.path,\n positional: {}\n },\n options: getDefaultOptions(context, command),\n parent: parent ?? null,\n children: {}\n } as CommandTree;\n\n if (!command.isVirtual) {\n if (\n !command.entry.input?.file ||\n !context.fs.existsSync(command.entry.input.file)\n ) {\n throw new Error(\n `${\n !command.entry.input?.file ? \"Missing\" : \"Non-existent\"\n } command entry file for \"${command.name}\"`\n );\n }\n\n context.debug(\n `Adding reflection for user-defined command: ${command.id} (file: ${\n command.entry.input.file\n })`\n );\n\n const resolved = await resolveModule<CommandModule>(\n context,\n command.entry.input,\n {\n plugins: [\n esbuildPlugin(context, {\n reflection: \"default\",\n reflectionLevel: \"verbose\"\n })\n ]\n }\n );\n\n const metadata = resolved.metadata ?? {};\n if (isSetString(metadata.title)) {\n tree.title = metadata.title;\n }\n if (isSetString(metadata.description)) {\n tree.description = metadata.description;\n }\n if (\n isSetString(metadata.alias) ||\n (Array.isArray(metadata.alias) && metadata.alias.length > 0)\n ) {\n tree.alias = toArray(metadata.alias);\n }\n\n const type = reflect(resolved);\n\n // const type = await reflectType<TContext>(context, command.entry.input);\n if (type.kind !== ReflectionKind.function) {\n throw new Error(\n `The command entry file \"${command.entry.input.file}\" does not export a valid function.`\n );\n }\n\n tree.description ??=\n command.description ||\n type.description ||\n `The ${tree.title} executable command-line interface.`;\n\n if (type.parameters.length > 0 && type.parameters[0]) {\n const firstParam = type.parameters[0];\n if (\n firstParam.type.kind === ReflectionKind.objectLiteral ||\n firstParam.type.kind === ReflectionKind.class\n ) {\n const optionsReflection = ReflectionClass.from(firstParam.type);\n for (const propertyReflection of optionsReflection.getProperties()) {\n tree.options[propertyReflection.getNameAsString()] =\n extractCommandOption(command, propertyReflection);\n }\n }\n\n tree.path.positional = tree.path.segments\n .filter(segment => isPositionalCommandOption(segment))\n .reduce(\n (obj, segment, index) => {\n if (\n type.parameters.length < index + 2 ||\n !type.parameters[index + 1]\n ) {\n return obj;\n }\n\n const paramName = getPositionalCommandOptionName(segment);\n obj[paramName] = extractCommandPositionalOption(\n command,\n paramName,\n type.parameters[index + 1]!\n );\n\n obj[paramName].description =\n obj[paramName].description ||\n `The ${paramName} positional option for the ${command.name} command.`;\n\n return obj;\n },\n {} as Record<string, CommandPositionalOption>\n );\n }\n } else {\n tree.description ??= `A collection of available ${\n tree.title || titleCase(tree.name)\n } commands that are included in the ${getAppTitle(\n context\n )} command-line application.`;\n }\n\n if (context.env) {\n if (isSetObject(tree.options)) {\n Object.values(tree.options)\n .filter(option => option.env !== false)\n .forEach(option => {\n context.env.types.env.addProperty({\n name: option.env as string,\n optional: option.optional ? true : undefined,\n description: option.description,\n visibility: ReflectionVisibility.public,\n type:\n option.kind === ReflectionKind.string ||\n option.kind === ReflectionKind.number\n ? option.variadic\n ? { kind: ReflectionKind.array, type: { kind: option.kind } }\n : { kind: option.kind }\n : { kind: ReflectionKind.boolean },\n default: option.default,\n tags: {\n title: option.title,\n alias: option.alias\n .filter(alias => alias.length > 0)\n .map(alias => constantCase(alias)),\n domain: \"cli\"\n }\n });\n });\n }\n\n if (\n Object.values(tree.path.positional).filter(option => option.env !== false)\n .length > 0\n ) {\n Object.values(tree.path.positional)\n .filter(option => option.env !== false)\n .forEach(option =>\n context.env.types.env.addProperty({\n name: constantCase(option.name),\n optional: option.optional ? true : undefined,\n description: option.description,\n visibility: ReflectionVisibility.public,\n type: option.variadic\n ? {\n kind: ReflectionKind.array,\n type: { kind: ReflectionKind.string }\n }\n : { kind: ReflectionKind.string },\n default: option.default,\n tags: {\n domain: \"cli\"\n }\n })\n );\n }\n }\n\n for (const input of context.inputs.filter(\n input =>\n input.path.segments.filter(segment => !isPositionalCommandOption(segment))\n .length ===\n command.path.segments.filter(\n segment => !isPositionalCommandOption(segment)\n ).length +\n 1 &&\n input.path.segments\n .slice(0, command.path.segments.length)\n .every((value, index) => value === command.path.segments[index])\n )) {\n tree.children[input.name] = await reflectCommandTree(context, input, tree);\n }\n\n return tree;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"resolve-command.mjs","names":["esbuildPlugin","reflect","ReflectionClass","ReflectionKind","ReflectionVisibility","stringifyType","toArray","appendPath","commonPath","findFilePath","findFolderName","stripStars","replacePath","resolveParentPath","constantCase","titleCase","isSetObject","isSetString","resolveModule","getAppTitle","getDynamicPathSegmentName","isCatchAllPathSegment","isDynamicPathSegment","isOptionalCatchAllPathSegment","isPathSegmentGroup","getDefaultOptions","resolveCommandOptionDescription","kind","optional","name","title","defaultValue","boolean","array","trim","number","resolveCommandId","context","file","commandsPath","split","filter","p","Boolean","join","replaceAll","resolveCommandName","path","requireExtension","resolveCommandPath","resolveCommandDynamicPathSegments","map","findCommandsRoot","config","entry","projectRoot","workspaceConfig","workspaceRoot","Array","isArray","length","sourceRoot","extractCommandOption","command","reflection","propertyType","getType","option","getNameAsString","alias","getTags","description","getDescription","getKind","isOptional","getDefaultValue","env","default","variadic","type","string","Error","extractCommandDynamicSegment","segment","catchAll","segments","some","seg","reflectCommandTree","parent","isVirtual","replace","tree","dynamics","options","children","input","fs","existsSync","debug","id","resolved","plugins","reflectionLevel","metadata","function","parameters","firstParam","objectLiteral","class","optionsReflection","from","propertyReflection","getProperties","reduce","obj","index","paramName","Object","values","forEach","types","addProperty","undefined","visibility","public","tags","domain","inputs","slice","every","value"],"sources":["../../src/helpers/resolve-command.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 { esbuildPlugin } from \"@powerlines/deepkit/esbuild-plugin\";\nimport type {\n ReflectionProperty,\n TypeParameter\n} from \"@powerlines/deepkit/vendor/type\";\nimport {\n reflect,\n ReflectionClass,\n ReflectionKind,\n ReflectionVisibility,\n stringifyType\n} from \"@powerlines/deepkit/vendor/type\";\nimport { toArray } from \"@stryke/convert/to-array\";\nimport { appendPath } from \"@stryke/path/append\";\nimport { commonPath } from \"@stryke/path/common\";\nimport { findFilePath, findFolderName } from \"@stryke/path/file-path-fns\";\nimport { stripStars } from \"@stryke/path/normalize\";\nimport { replacePath } from \"@stryke/path/replace\";\nimport { resolveParentPath } from \"@stryke/path/resolve-parent-path\";\nimport { constantCase } from \"@stryke/string-format/constant-case\";\nimport { titleCase } from \"@stryke/string-format/title-case\";\nimport { isSetObject } from \"@stryke/type-checks/is-set-object\";\nimport { isSetString } from \"@stryke/type-checks/is-set-string\";\nimport { resolveModule } from \"powerlines/lib/utilities/resolve\";\nimport {\n getAppTitle,\n getDynamicPathSegmentName,\n isCatchAllPathSegment,\n isDynamicPathSegment,\n isOptionalCatchAllPathSegment,\n isPathSegmentGroup\n} from \"../plugin-utils/context-helpers\";\nimport type {\n CommandDynamicSegment,\n CommandInput,\n CommandModule,\n CommandOption,\n CommandTree,\n NumberCommandOption,\n StringCommandOption\n} from \"../types/command\";\nimport type { Context } from \"../types/context\";\nimport { getDefaultOptions } from \"./utilities\";\n\n/**\n * Resolves the description for a command option based on its reflection.\n *\n * @param kind - The reflection kind of the command option.\n * @param optional - Whether the command option is optional.\n * @param name - The name of the command option.\n * @param title - The title of the command option, if any.\n * @param defaultValue - The default value of the command option, if any.\n * @returns The resolved description for the command option.\n */\nexport function resolveCommandOptionDescription(\n kind: ReflectionKind,\n optional: boolean,\n name: string,\n title?: string,\n defaultValue?: any\n): string {\n return `A${optional && !defaultValue ? \"n optional\" : \"\"} ${\n kind === ReflectionKind.boolean\n ? \"flag provided via the command-line\"\n : \"command-line option\"\n } that allows the user to ${\n kind === ReflectionKind.boolean\n ? \"set the\"\n : kind === ReflectionKind.array\n ? \"specify custom\"\n : \"specify a custom\"\n } ${title?.trim() || titleCase(name)} ${\n kind === ReflectionKind.boolean\n ? \"indicator\"\n : `${kind === ReflectionKind.number ? \"numeric\" : \"string\"} value${\n kind === ReflectionKind.array ? \"s\" : \"\"\n }`\n } that will be used in the application.`;\n}\n\nexport function resolveCommandId(context: Context, file: string): string {\n return replacePath(findFilePath(file), context.commandsPath)\n .split(\"/\")\n .filter(p => Boolean(p) && !isDynamicPathSegment(p))\n .join(\"/\")\n .replaceAll(/^\\/+/g, \"\")\n .replaceAll(/\\/+$/g, \"\")\n .replaceAll(\"/\", \"-\");\n}\n\n/**\n * Finds the command name from the given file path.\n *\n * @param file - The file path to extract the command name from.\n * @returns The command name.\n */\nexport function resolveCommandName(file: string) {\n let path = findFilePath(file);\n let name = findFolderName(file, {\n requireExtension: true\n });\n\n while (isDynamicPathSegment(name)) {\n path = resolveParentPath(path);\n name = findFolderName(path, {\n requireExtension: true\n });\n }\n\n return name;\n}\n\nexport function resolveCommandPath(context: Context, file: string): string {\n return replacePath(findFilePath(file), context.commandsPath)\n .replaceAll(/^\\/+/g, \"\")\n .replaceAll(/\\/+$/g, \"\")\n .split(\"/\")\n .filter(path => path && !isPathSegmentGroup(path))\n .join(\"/\");\n}\n\nexport function resolveCommandDynamicPathSegments(\n context: Context,\n file: string\n): string[] {\n return replacePath(findFilePath(file), context.commandsPath)\n .split(\"/\")\n .filter(path => Boolean(path) && isDynamicPathSegment(path))\n .map(path => getDynamicPathSegmentName(path));\n}\n\nexport function findCommandsRoot(context: Context): string {\n if (isSetString(context.config.entry)) {\n return appendPath(\n appendPath(stripStars(context.config.entry), context.config.projectRoot),\n context.workspaceConfig.workspaceRoot\n );\n } else if (\n isSetObject(context.config.entry) &&\n \"file\" in context.config.entry\n ) {\n return appendPath(\n appendPath(\n stripStars(context.config.entry.file),\n context.config.projectRoot\n ),\n context.workspaceConfig.workspaceRoot\n );\n } else if (\n Array.isArray(context.config.entry) &&\n context.config.entry.length > 0\n ) {\n return commonPath(\n context.config.entry.map(entry =>\n appendPath(\n appendPath(\n stripStars(isSetString(entry) ? entry : entry.file),\n context.config.projectRoot\n ),\n context.workspaceConfig.workspaceRoot\n )\n )\n );\n }\n\n return appendPath(\n context.config.sourceRoot || context.config.projectRoot,\n context.workspaceConfig.workspaceRoot\n );\n}\n\n/**\n * Extracts command parameter information from a type parameter reflection.\n *\n * @param command - The command tree to which the parameter belongs.\n * @param reflection - The type parameter reflection to extract information from.\n * @returns The extracted command option information.\n */\nexport function extractCommandOption(\n command: CommandInput,\n reflection: ReflectionProperty\n): CommandOption {\n const propertyType = reflection.getType();\n\n const option = {\n name: reflection.getNameAsString(),\n alias: reflection.getTags().alias ?? [],\n title:\n reflection.getTags().title?.trim() ||\n titleCase(reflection.getNameAsString()),\n description:\n reflection.getDescription() ||\n resolveCommandOptionDescription(\n reflection.getKind(),\n reflection.isOptional(),\n reflection.getNameAsString(),\n reflection.getTags().title,\n reflection.getDefaultValue()\n ),\n env: constantCase(reflection.getNameAsString()),\n kind: propertyType.kind as\n | ReflectionKind.string\n | ReflectionKind.number\n | ReflectionKind.boolean,\n optional: reflection.isOptional(),\n default: reflection.getDefaultValue(),\n variadic: false\n } as CommandOption;\n if (propertyType.kind === ReflectionKind.array) {\n if (\n propertyType.type.kind === ReflectionKind.string ||\n propertyType.type.kind === ReflectionKind.number\n ) {\n (option as StringCommandOption | NumberCommandOption).variadic = true;\n (option as StringCommandOption | NumberCommandOption).kind =\n propertyType.type.kind;\n } else {\n throw new Error(\n `Unsupported array type for option \"${reflection.getNameAsString()}\" in command \"${\n command.name\n }\". Only string[] and number[] are supported.`\n );\n }\n } else if (\n propertyType.kind !== ReflectionKind.boolean &&\n propertyType.kind !== ReflectionKind.string &&\n propertyType.kind !== ReflectionKind.number\n ) {\n throw new Error(\n `Unsupported type for option \"${reflection.getNameAsString()}\" in command \"${\n command.name\n }\". Only string, number, boolean, string[] and number[] are supported, received ${stringifyType(\n propertyType\n )\n .trim()\n .replaceAll(\" | \", \", or \")}.`\n );\n }\n\n return option;\n}\n\n/**\n * Extracts command parameter information from a type parameter reflection.\n *\n * @param command - The command tree to which the parameter belongs.\n * @param segment - The command path segment corresponding to the parameter.\n * @param reflection - The type parameter reflection to extract information from.\n * @returns The extracted command option information.\n */\nexport function extractCommandDynamicSegment(\n command: CommandInput,\n segment: string,\n reflection: TypeParameter\n): CommandDynamicSegment {\n if (\n reflection.type.kind !== ReflectionKind.string &&\n !(\n reflection.type.kind === ReflectionKind.array &&\n reflection.type.type.kind === ReflectionKind.string\n )\n ) {\n throw new Error(\n `Unsupported type for dynamic path segment \"${segment}\" in command \"${\n command.name\n }\". Only string types (or an array of strings) are supported, received ${stringifyType(\n reflection.type\n )\n .trim()\n .replaceAll(\" | \", \", or \")}.`\n );\n }\n\n const option = {\n name: segment,\n title: titleCase(segment),\n description:\n reflection.description ||\n resolveCommandOptionDescription(\n ReflectionKind.string,\n !!reflection.optional,\n segment,\n titleCase(segment),\n reflection.default\n ),\n optional: reflection.optional,\n default: reflection.default,\n catchAll: command.path.segments.some(\n seg =>\n getDynamicPathSegmentName(segment) === seg && isCatchAllPathSegment(seg)\n )\n } as CommandDynamicSegment;\n\n if (reflection.type.kind === ReflectionKind.array) {\n if (!option.catchAll) {\n throw new Error(\n `Dynamic path segment \"${segment}\" in command \"${\n command.name\n }\" is an array type but is not defined as a catch-all segment. To use an array type for a dynamic path segment, it must be defined as a catch-all segment using the \"[...segment]\" syntax.`\n );\n }\n\n option.variadic = true;\n }\n\n if (option.catchAll) {\n if (\n !option.optional &&\n command.path.segments.some(\n seg =>\n getDynamicPathSegmentName(segment) === seg &&\n isOptionalCatchAllPathSegment(seg)\n )\n ) {\n throw new Error(\n `Dynamic path segment \"${segment}\" in command \"${\n command.name\n }\" is defined as a catch-all segment but is not optional. To define an optional catch-all segment, use the \"[[...segment]]\" syntax.`\n );\n } else if (\n option.optional &&\n !command.path.segments.some(\n seg =>\n getDynamicPathSegmentName(segment) === seg &&\n isOptionalCatchAllPathSegment(seg)\n )\n ) {\n throw new Error(\n `Dynamic path segment \"${segment}\" in command \"${\n command.name\n }\" is defined as an optional segment but is not defined as an optional catch-all segment. To define an optional catch-all segment, use the \"[[...segment]]\" syntax.`\n );\n }\n }\n\n return option;\n}\n\n/**\n * Reflects the command tree for a given command input.\n *\n * @param context - The context in which the command is being reflected.\n * @param command - The command input to reflect.\n * @param parent - The parent command tree, if any.\n * @returns The reflected command tree.\n */\nexport async function reflectCommandTree<TContext extends Context = Context>(\n context: TContext,\n command: CommandInput,\n parent?: CommandTree\n): Promise<CommandTree> {\n const title =\n command.title ||\n `${parent?.title ? `${parent.isVirtual ? parent.title.replace(/ Commands$/, \"\") : parent.title} - ` : \"\"}${titleCase(command.name)}${\n command.isVirtual ? \" Commands\" : \"\"\n }`;\n\n const tree = {\n alias: [],\n ...command,\n title,\n path: {\n ...command.path,\n dynamics: {}\n },\n options: getDefaultOptions(context, command),\n parent: parent ?? null,\n children: {}\n } as CommandTree;\n\n if (!command.isVirtual) {\n if (\n !command.entry.input?.file ||\n !context.fs.existsSync(command.entry.input.file)\n ) {\n throw new Error(\n `${\n !command.entry.input?.file ? \"Missing\" : \"Non-existent\"\n } command entry file for \"${command.name}\"`\n );\n }\n\n context.debug(\n `Adding reflection for user-defined command: ${command.id} (file: ${\n command.entry.input.file\n })`\n );\n\n const resolved = await resolveModule<CommandModule>(\n context,\n command.entry.input,\n {\n plugins: [\n esbuildPlugin(context, {\n reflection: \"default\",\n reflectionLevel: \"verbose\"\n })\n ]\n }\n );\n\n const metadata = resolved.metadata ?? {};\n if (isSetString(metadata.title)) {\n tree.title = metadata.title;\n }\n if (isSetString(metadata.description)) {\n tree.description = metadata.description;\n }\n if (\n isSetString(metadata.alias) ||\n (Array.isArray(metadata.alias) && metadata.alias.length > 0)\n ) {\n tree.alias = toArray(metadata.alias);\n }\n\n const type = reflect(resolved);\n\n // const type = await reflectType<TContext>(context, command.entry.input);\n if (type.kind !== ReflectionKind.function) {\n throw new Error(\n `The command entry file \"${command.entry.input.file}\" does not export a valid function.`\n );\n }\n\n tree.description ??=\n command.description ||\n type.description ||\n `The ${tree.title} executable command-line interface.`;\n\n if (type.parameters.length > 0 && type.parameters[0]) {\n const firstParam = type.parameters[0];\n if (\n firstParam.type.kind === ReflectionKind.objectLiteral ||\n firstParam.type.kind === ReflectionKind.class\n ) {\n const optionsReflection = ReflectionClass.from(firstParam.type);\n for (const propertyReflection of optionsReflection.getProperties()) {\n tree.options[propertyReflection.getNameAsString()] =\n extractCommandOption(command, propertyReflection);\n }\n }\n\n tree.path.dynamics = tree.path.segments\n .filter(segment => isDynamicPathSegment(segment))\n .reduce(\n (obj, segment, index) => {\n if (\n type.parameters.length < index + 2 ||\n !type.parameters[index + 1]\n ) {\n return obj;\n }\n\n const paramName = getDynamicPathSegmentName(segment);\n obj[paramName] = extractCommandDynamicSegment(\n command,\n paramName,\n type.parameters[index + 1]!\n );\n\n obj[paramName].description =\n obj[paramName].description ||\n `The ${paramName} ${\n obj[paramName].catchAll\n ? `${obj[paramName].optional ? \"optional \" : \"\"}catch-all`\n : \"dynamic \"\n } segment for the ${command.name} command.`;\n\n return obj;\n },\n {} as Record<string, CommandDynamicSegment>\n );\n }\n } else {\n tree.description ??= `A collection of available ${\n tree.title || titleCase(tree.name)\n } commands that are included in the ${getAppTitle(\n context\n )} command-line application.`;\n }\n\n if (context.env) {\n if (isSetObject(tree.options)) {\n Object.values(tree.options)\n .filter(option => option.env !== false)\n .forEach(option => {\n context.env.types.env.addProperty({\n name: option.env as string,\n optional: option.optional ? true : undefined,\n description: option.description,\n visibility: ReflectionVisibility.public,\n type:\n option.kind === ReflectionKind.string ||\n option.kind === ReflectionKind.number\n ? option.variadic\n ? { kind: ReflectionKind.array, type: { kind: option.kind } }\n : { kind: option.kind }\n : { kind: ReflectionKind.boolean },\n default: option.default,\n tags: {\n title: option.title,\n alias: option.alias\n .filter(alias => alias.length > 0)\n .map(alias => constantCase(alias)),\n domain: \"cli\"\n }\n });\n });\n }\n\n // if (\n // Object.values(tree.path.dynamics).filter(option => option.env !== false)\n // .length > 0\n // ) {\n // Object.values(tree.path.dynamics)\n // .filter(option => option.env !== false)\n // .forEach(option =>\n // context.env.types.env.addProperty({\n // name: constantCase(option.name),\n // optional: option.optional ? true : undefined,\n // description: option.description,\n // visibility: ReflectionVisibility.public,\n // type: option.variadic\n // ? {\n // kind: ReflectionKind.array,\n // type: { kind: ReflectionKind.string }\n // }\n // : { kind: ReflectionKind.string },\n // default: option.default,\n // tags: {\n // domain: \"cli\"\n // }\n // })\n // );\n // }\n }\n\n for (const input of context.inputs.filter(\n input =>\n input.path.segments.filter(segment => !isDynamicPathSegment(segment))\n .length ===\n command.path.segments.filter(segment => !isDynamicPathSegment(segment))\n .length +\n 1 &&\n input.path.segments\n .slice(0, command.path.segments.length)\n .every((value, index) => value === command.path.segments[index])\n )) {\n tree.children[input.name] = await reflectCommandTree(context, input, tree);\n }\n\n return tree;\n}\n"],"mappings":"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"}
@@ -1,35 +1,35 @@
1
1
  const require_plugin_utils_context_helpers = require('../plugin-utils/context-helpers.cjs');
2
2
 
3
3
  //#region src/helpers/validations.ts
4
- function validateCommandPositionalOptions(command) {
4
+ function validateDynamicPathSegments(command) {
5
5
  const failures = [];
6
6
  if (!command.isVirtual && command.path.segments.length > 0) {
7
- const positionalOptionPathNames = /* @__PURE__ */ new Set();
8
- for (const segment of command.path.segments.filter(require_plugin_utils_context_helpers.isPositionalCommandOption) ?? []) {
9
- if (positionalOptionPathNames.has(segment)) failures.push({
10
- code: "DUPLICATE_POSITIONAL_OPTION_PATH_NAME",
11
- details: `Duplicate positional option path name "${require_plugin_utils_context_helpers.getPositionalCommandOptionName(segment)}" found in command.`
7
+ const dynamicPathSegmentNames = /* @__PURE__ */ new Set();
8
+ for (const segment of command.path.segments.filter(require_plugin_utils_context_helpers.isDynamicPathSegment) ?? []) {
9
+ if (dynamicPathSegmentNames.has(segment)) failures.push({
10
+ code: "DUPLICATE_DYNAMIC_PATH_SEGMENT_NAME",
11
+ details: `Duplicate dynamic path segment name "${require_plugin_utils_context_helpers.getDynamicPathSegmentName(segment)}" found in command.`
12
12
  });
13
- positionalOptionPathNames.add(require_plugin_utils_context_helpers.getPositionalCommandOptionName(segment));
13
+ dynamicPathSegmentNames.add(require_plugin_utils_context_helpers.getDynamicPathSegmentName(segment));
14
14
  }
15
- if (command.path.segments.filter(require_plugin_utils_context_helpers.isPositionalCommandOption).length !== Object.keys(command.path.positional ?? {}).length) failures.push({
16
- code: "POSITIONAL_OPTION_PATH_MISMATCH",
17
- details: `Mismatch between positional options path segments and defined path positional options in command (found ${command.path.segments.filter(require_plugin_utils_context_helpers.isPositionalCommandOption).length} positional options in the command folder path "${command.path.segments.join("/")}", but ${Object.keys(command.path.positional ?? {}).length} potential positional option path(s) could be determined from the command's function signature).`
15
+ if (command.path.segments.filter(require_plugin_utils_context_helpers.isDynamicPathSegment).length !== Object.keys(command.path.dynamics ?? {}).length) failures.push({
16
+ code: "DYNAMIC_PATH_SEGMENT_MISMATCH",
17
+ details: `Mismatch between dynamic path segments and defined dynamic path segments in command (found ${command.path.segments.filter(require_plugin_utils_context_helpers.isDynamicPathSegment).length} dynamic path segments in the command folder path "${command.path.segments.join("/")}", but ${Object.keys(command.path.dynamics ?? {}).length} potential dynamic path segment(s) could be determined from the command's function signature).`
18
18
  });
19
- const missing = command.path.segments.filter(require_plugin_utils_context_helpers.isPositionalCommandOption).filter((segment) => Object.prototype.hasOwnProperty.call(command.path.positional ?? {}, require_plugin_utils_context_helpers.getPositionalCommandOptionName(segment)) === false);
19
+ const missing = command.path.segments.filter(require_plugin_utils_context_helpers.isDynamicPathSegment).filter((segment) => Object.prototype.hasOwnProperty.call(command.path.dynamics ?? {}, require_plugin_utils_context_helpers.getDynamicPathSegmentName(segment)) === false);
20
20
  if (missing.length > 0) failures.push({
21
- code: "MISSING_POSITIONAL_OPTION_PATH",
22
- details: `${missing.length} positional option path segment${missing.length > 1 ? "s" : ""} in the command folder path "${command.path.segments.join("/")}" do${missing.length > 1 ? "" : "es"} not have corresponding entr${missing.length > 1 ? "ies" : "y"} in the command's path positional options: \n- ${missing.map((segment) => `"${require_plugin_utils_context_helpers.getPositionalCommandOptionName(segment)}"`).join("\n- ")}`
21
+ code: "MISSING_DYNAMIC_PATH_SEGMENT_DEFINITION",
22
+ details: `${missing.length} dynamic path segment${missing.length > 1 ? "s" : ""} in the command folder path "${command.path.segments.join("/")}" do${missing.length > 1 ? "" : "es"} not have corresponding entr${missing.length > 1 ? "ies" : "y"} in the command's path dynamic segments: \n- ${missing.map((segment) => `"${require_plugin_utils_context_helpers.getDynamicPathSegmentName(segment)}"`).join("\n- ")}`
23
23
  });
24
24
  else {
25
- for (const varName of Object.keys(command.path.positional ?? {})) if (!command.path.segments.filter(require_plugin_utils_context_helpers.isPositionalCommandOption).find((segment) => require_plugin_utils_context_helpers.getPositionalCommandOptionName(segment) === varName)) failures.push({
26
- code: "UNUSED_POSITIONAL_OPTION_PATH",
27
- details: `The positional option path name "${varName}" defined in the command's path positional options is not used in the command folder path "${command.path.segments.join("/")}".`
25
+ for (const varName of Object.keys(command.path.dynamics ?? {})) if (!command.path.segments.filter(require_plugin_utils_context_helpers.isDynamicPathSegment).find((segment) => require_plugin_utils_context_helpers.getDynamicPathSegmentName(segment) === varName)) failures.push({
26
+ code: "UNUSED_DYNAMIC_PATH_SEGMENT",
27
+ details: `The dynamic path segment name "${varName}" defined in the command's path dynamic segments is not used in the command folder path "${command.path.segments.join("/")}".`
28
28
  });
29
29
  command.path.segments.forEach((segment, index) => {
30
- if (require_plugin_utils_context_helpers.isPositionalCommandOption(segment) && command.path.positional[require_plugin_utils_context_helpers.getPositionalCommandOptionName(segment)]?.variadic === true && index + 1 < command.path.segments.length && command.path.segments[index + 1] && command.path.positional[require_plugin_utils_context_helpers.getPositionalCommandOptionName(command.path.segments[index + 1])]?.variadic === true) failures.push({
31
- code: "MULTIPLE_VARIADIC_POSITIONAL_OPTION_PATHS",
32
- details: `The positional option path segment "${require_plugin_utils_context_helpers.getPositionalCommandOptionName(segment)}" in the command at path "${command.path.segments.join("/")}" is marked as variadic, and it is followed by another variadic positional option path segment "${require_plugin_utils_context_helpers.getPositionalCommandOptionName(command.path.segments[index + 1])}". Only one variadic positional option path segment is allowed per command, and it must be the final path segment.`
30
+ if (require_plugin_utils_context_helpers.isDynamicPathSegment(segment) && command.path.dynamics[require_plugin_utils_context_helpers.getDynamicPathSegmentName(segment)]?.catchAll === true && index + 1 < command.path.segments.length && command.path.segments[index + 1] && command.path.dynamics[require_plugin_utils_context_helpers.getDynamicPathSegmentName(command.path.segments[index + 1])]?.catchAll === true) failures.push({
31
+ code: "MULTIPLE_CATCH_ALL_PATH_SEGMENTS",
32
+ details: `The catch-all path segment "${require_plugin_utils_context_helpers.getDynamicPathSegmentName(segment)}" in the command at path "${command.path.segments.join("/")}" is marked as catch-all, and it is followed by another catch-all dynamic path segment "${require_plugin_utils_context_helpers.getDynamicPathSegmentName(command.path.segments[index + 1])}". Only one catch-all path segment is allowed per command, and it must be the final path segment.`
33
33
  });
34
34
  });
35
35
  }
@@ -57,7 +57,7 @@ function validateCommandOptions(command) {
57
57
  }
58
58
  function validateCommand(command) {
59
59
  const results = [];
60
- let failures = validateCommandPositionalOptions(command);
60
+ let failures = validateDynamicPathSegments(command);
61
61
  if (failures.length > 0) results.push(...failures);
62
62
  failures = validateCommandOptions(command);
63
63
  if (failures.length > 0) results.push(...failures);
@@ -1 +1 @@
1
- {"version":3,"file":"validations.cjs","names":["getPositionalCommandOptionName","isPositionalCommandOption","validateCommandPositionalOptions","command","failures","isVirtual","path","segments","length","positionalOptionPathNames","Set","segment","filter","has","push","code","details","add","Object","keys","positional","join","missing","prototype","hasOwnProperty","call","map","varName","find","forEach","index","variadic","validateCommandOptions","optionNames","option","values","options","name","alias","validateCommand","results"],"sources":["../../src/helpers/validations.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 {\n getPositionalCommandOptionName,\n isPositionalCommandOption\n} from \"../plugin-utils/context-helpers\";\nimport type { CommandTree } from \"../types\";\n\nexport interface ValidationFailure {\n code: string;\n details: string;\n}\n\nexport function validateCommandPositionalOptions(\n command: CommandTree\n): ValidationFailure[] {\n const failures: ValidationFailure[] = [];\n if (!command.isVirtual && command.path.segments.length > 0) {\n const positionalOptionPathNames = new Set<string>();\n for (const segment of command.path.segments.filter(\n isPositionalCommandOption\n ) ?? []) {\n if (positionalOptionPathNames.has(segment)) {\n failures.push({\n code: \"DUPLICATE_POSITIONAL_OPTION_PATH_NAME\",\n details: `Duplicate positional option path name \"${getPositionalCommandOptionName(segment)}\" found in command.`\n });\n }\n positionalOptionPathNames.add(getPositionalCommandOptionName(segment));\n }\n\n if (\n command.path.segments.filter(isPositionalCommandOption).length !==\n Object.keys(command.path.positional ?? {}).length\n ) {\n failures.push({\n code: \"POSITIONAL_OPTION_PATH_MISMATCH\",\n details: `Mismatch between positional options path segments and defined path positional options in command (found ${\n command.path.segments.filter(isPositionalCommandOption).length\n } positional options in the command folder path \"${command.path.segments.join(\"/\")}\", but ${\n Object.keys(command.path.positional ?? {}).length\n } potential positional option path(s) could be determined from the command's function signature).`\n });\n }\n\n const missing = command.path.segments\n .filter(isPositionalCommandOption)\n .filter(\n segment =>\n Object.prototype.hasOwnProperty.call(\n command.path.positional ?? {},\n getPositionalCommandOptionName(segment)\n ) === false\n );\n if (missing.length > 0) {\n failures.push({\n code: \"MISSING_POSITIONAL_OPTION_PATH\",\n details: `${missing.length} positional option path segment${missing.length > 1 ? \"s\" : \"\"} in the command folder path \"${command.path.segments.join(\n \"/\"\n )}\" do${missing.length > 1 ? \"\" : \"es\"} not have corresponding entr${\n missing.length > 1 ? \"ies\" : \"y\"\n } in the command's path positional options: \\n- ${missing\n .map(segment => `\"${getPositionalCommandOptionName(segment)}\"`)\n .join(\"\\n- \")}`\n });\n } else {\n for (const varName of Object.keys(command.path.positional ?? {})) {\n if (\n !command.path.segments\n .filter(isPositionalCommandOption)\n .find(\n segment => getPositionalCommandOptionName(segment) === varName\n )\n ) {\n failures.push({\n code: \"UNUSED_POSITIONAL_OPTION_PATH\",\n details: `The positional option path name \"${varName}\" defined in the command's path positional options is not used in the command folder path \"${command.path.segments.join(\n \"/\"\n )}\".`\n });\n }\n }\n\n command.path.segments.forEach((segment, index) => {\n if (\n isPositionalCommandOption(segment) &&\n command.path.positional[getPositionalCommandOptionName(segment)]\n ?.variadic === true &&\n index + 1 < command.path.segments.length &&\n command.path.segments[index + 1] &&\n command.path.positional[\n getPositionalCommandOptionName(command.path.segments[index + 1]!)\n ]?.variadic === true\n ) {\n failures.push({\n code: \"MULTIPLE_VARIADIC_POSITIONAL_OPTION_PATHS\",\n details: `The positional option path segment \"${getPositionalCommandOptionName(\n segment\n )}\" in the command at path \"${command.path.segments.join(\n \"/\"\n )}\" is marked as variadic, and it is followed by another variadic positional option path segment \"${getPositionalCommandOptionName(\n command.path.segments[index + 1]!\n )}\". Only one variadic positional option path segment is allowed per command, and it must be the final path segment.`\n });\n }\n });\n }\n }\n\n return failures;\n}\n\nexport function validateCommandOptions(\n command: CommandTree\n): ValidationFailure[] {\n const failures: ValidationFailure[] = [];\n\n const optionNames = new Set<string>();\n for (const option of Object.values(command.options ?? {})) {\n if (optionNames.has(option.name)) {\n failures.push({\n code: \"DUPLICATE_OPTION_NAME\",\n details: `Duplicate option name \"${option.name}\" found in command.`\n });\n }\n optionNames.add(option.name);\n\n for (const alias of option.alias) {\n if (optionNames.has(alias)) {\n failures.push({\n code: \"DUPLICATE_OPTION_ALIAS\",\n details: `Duplicate option name \"${alias}\" (an alias of \"${\n option.name\n }\") found in command.`\n });\n }\n optionNames.add(alias);\n }\n }\n\n return failures;\n}\n\nexport function validateCommand(command: CommandTree): ValidationFailure[] {\n const results: ValidationFailure[] = [];\n\n let failures = validateCommandPositionalOptions(command);\n if (failures.length > 0) {\n results.push(...failures);\n }\n\n failures = validateCommandOptions(command);\n if (failures.length > 0) {\n results.push(...failures);\n }\n\n return results;\n}\n"],"mappings":";;;AA6BA,SAAgBE,iCACdC,SACqB;CACrB,MAAMC,WAAgC,EAAE;AACxC,KAAI,CAACD,QAAQE,aAAaF,QAAQG,KAAKC,SAASC,SAAS,GAAG;EAC1D,MAAMC,4CAA4B,IAAIC,KAAa;AACnD,OAAK,MAAMC,WAAWR,QAAQG,KAAKC,SAASK,OAC1CX,+DACD,IAAI,EAAE,EAAE;AACP,OAAIQ,0BAA0BI,IAAIF,QAAQ,CACxCP,UAASU,KAAK;IACZC,MAAM;IACNC,SAAS,0CAA0ChB,oEAA+BW,QAAQ,CAAA;IAC3F,CAAC;AAEJF,6BAA0BQ,IAAIjB,oEAA+BW,QAAQ,CAAC;;AAGxE,MACER,QAAQG,KAAKC,SAASK,OAAOX,+DAA0B,CAACO,WACxDU,OAAOC,KAAKhB,QAAQG,KAAKc,cAAc,EAAE,CAAC,CAACZ,OAE3CJ,UAASU,KAAK;GACZC,MAAM;GACNC,SAAS,2GACPb,QAAQG,KAAKC,SAASK,OAAOX,+DAA0B,CAACO,OAAM,kDACbL,QAAQG,KAAKC,SAASc,KAAK,IAAI,CAAA,SAChFH,OAAOC,KAAKhB,QAAQG,KAAKc,cAAc,EAAE,CAAC,CAACZ,OAAM;GAEpD,CAAC;EAGJ,MAAMc,UAAUnB,QAAQG,KAAKC,SAC1BK,OAAOX,+DAA0B,CACjCW,QACCD,YACEO,OAAOK,UAAUC,eAAeC,KAC9BtB,QAAQG,KAAKc,cAAc,EAAE,EAC7BpB,oEAA+BW,QACjC,CAAC,KAAK,MACT;AACH,MAAIW,QAAQd,SAAS,EACnBJ,UAASU,KAAK;GACZC,MAAM;GACNC,SAAS,GAAGM,QAAQd,OAAM,iCAAkCc,QAAQd,SAAS,IAAI,MAAM,GAAE,+BAAgCL,QAAQG,KAAKC,SAASc,KAC7I,IACD,CAAA,MAAOC,QAAQd,SAAS,IAAI,KAAK,KAAI,8BACpCc,QAAQd,SAAS,IAAI,QAAQ,IAAG,iDACgBc,QAC/CI,KAAIf,YAAW,IAAIX,oEAA+BW,QAAQ,CAAA,GAAI,CAC9DU,KAAK,OAAO;GAChB,CAAC;OACG;AACL,QAAK,MAAMM,WAAWT,OAAOC,KAAKhB,QAAQG,KAAKc,cAAc,EAAE,CAAC,CAC9D,KACE,CAACjB,QAAQG,KAAKC,SACXK,OAAOX,+DAA0B,CACjC2B,MACCjB,YAAWX,oEAA+BW,QAAQ,KAAKgB,QACxD,CAEHvB,UAASU,KAAK;IACZC,MAAM;IACNC,SAAS,oCAAoCW,QAAO,6FAA8FxB,QAAQG,KAAKC,SAASc,KACtK,IACD,CAAA;IACF,CAAC;AAINlB,WAAQG,KAAKC,SAASsB,SAASlB,SAASmB,UAAU;AAChD,QACE7B,+DAA0BU,QAAQ,IAClCR,QAAQG,KAAKc,WAAWpB,oEAA+BW,QAAQ,GAC3DoB,aAAa,QACjBD,QAAQ,IAAI3B,QAAQG,KAAKC,SAASC,UAClCL,QAAQG,KAAKC,SAASuB,QAAQ,MAC9B3B,QAAQG,KAAKc,WACXpB,oEAA+BG,QAAQG,KAAKC,SAASuB,QAAQ,GAAI,GAChEC,aAAa,KAEhB3B,UAASU,KAAK;KACZC,MAAM;KACNC,SAAS,uCAAuChB,oEAC9CW,QACD,CAAA,4BAA6BR,QAAQG,KAAKC,SAASc,KAClD,IACD,CAAA,kGAAmGrB,oEAClGG,QAAQG,KAAKC,SAASuB,QAAQ,GAC/B,CAAA;KACF,CAAC;KAEJ;;;AAIN,QAAO1B;;AAGT,SAAgB4B,uBACd7B,SACqB;CACrB,MAAMC,WAAgC,EAAE;CAExC,MAAM6B,8BAAc,IAAIvB,KAAa;AACrC,MAAK,MAAMwB,UAAUhB,OAAOiB,OAAOhC,QAAQiC,WAAW,EAAE,CAAC,EAAE;AACzD,MAAIH,YAAYpB,IAAIqB,OAAOG,KAAK,CAC9BjC,UAASU,KAAK;GACZC,MAAM;GACNC,SAAS,0BAA0BkB,OAAOG,KAAI;GAC/C,CAAC;AAEJJ,cAAYhB,IAAIiB,OAAOG,KAAK;AAE5B,OAAK,MAAMC,SAASJ,OAAOI,OAAO;AAChC,OAAIL,YAAYpB,IAAIyB,MAAM,CACxBlC,UAASU,KAAK;IACZC,MAAM;IACNC,SAAS,0BAA0BsB,MAAK,kBACtCJ,OAAOG,KAAI;IAEd,CAAC;AAEJJ,eAAYhB,IAAIqB,MAAM;;;AAI1B,QAAOlC;;AAGT,SAAgBmC,gBAAgBpC,SAA2C;CACzE,MAAMqC,UAA+B,EAAE;CAEvC,IAAIpC,WAAWF,iCAAiCC,QAAQ;AACxD,KAAIC,SAASI,SAAS,EACpBgC,SAAQ1B,KAAK,GAAGV,SAAS;AAG3BA,YAAW4B,uBAAuB7B,QAAQ;AAC1C,KAAIC,SAASI,SAAS,EACpBgC,SAAQ1B,KAAK,GAAGV,SAAS;AAG3B,QAAOoC"}
1
+ {"version":3,"file":"validations.cjs","names":["getDynamicPathSegmentName","isDynamicPathSegment","validateDynamicPathSegments","command","failures","isVirtual","path","segments","length","dynamicPathSegmentNames","Set","segment","filter","has","push","code","details","add","Object","keys","dynamics","join","missing","prototype","hasOwnProperty","call","map","varName","find","forEach","index","catchAll","validateCommandOptions","optionNames","option","values","options","name","alias","validateCommand","results"],"sources":["../../src/helpers/validations.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 {\n getDynamicPathSegmentName,\n isDynamicPathSegment\n} from \"../plugin-utils/context-helpers\";\nimport type { CommandTree } from \"../types\";\n\nexport interface ValidationFailure {\n code: string;\n details: string;\n}\n\nexport function validateDynamicPathSegments(\n command: CommandTree\n): ValidationFailure[] {\n const failures: ValidationFailure[] = [];\n if (!command.isVirtual && command.path.segments.length > 0) {\n const dynamicPathSegmentNames = new Set<string>();\n for (const segment of command.path.segments.filter(isDynamicPathSegment) ??\n []) {\n if (dynamicPathSegmentNames.has(segment)) {\n failures.push({\n code: \"DUPLICATE_DYNAMIC_PATH_SEGMENT_NAME\",\n details: `Duplicate dynamic path segment name \"${getDynamicPathSegmentName(segment)}\" found in command.`\n });\n }\n dynamicPathSegmentNames.add(getDynamicPathSegmentName(segment));\n }\n\n if (\n command.path.segments.filter(isDynamicPathSegment).length !==\n Object.keys(command.path.dynamics ?? {}).length\n ) {\n failures.push({\n code: \"DYNAMIC_PATH_SEGMENT_MISMATCH\",\n details: `Mismatch between dynamic path segments and defined dynamic path segments in command (found ${\n command.path.segments.filter(isDynamicPathSegment).length\n } dynamic path segments in the command folder path \"${command.path.segments.join(\"/\")}\", but ${\n Object.keys(command.path.dynamics ?? {}).length\n } potential dynamic path segment(s) could be determined from the command's function signature).`\n });\n }\n\n const missing = command.path.segments\n .filter(isDynamicPathSegment)\n .filter(\n segment =>\n Object.prototype.hasOwnProperty.call(\n command.path.dynamics ?? {},\n getDynamicPathSegmentName(segment)\n ) === false\n );\n if (missing.length > 0) {\n failures.push({\n code: \"MISSING_DYNAMIC_PATH_SEGMENT_DEFINITION\",\n details: `${missing.length} dynamic path segment${missing.length > 1 ? \"s\" : \"\"} in the command folder path \"${command.path.segments.join(\n \"/\"\n )}\" do${missing.length > 1 ? \"\" : \"es\"} not have corresponding entr${\n missing.length > 1 ? \"ies\" : \"y\"\n } in the command's path dynamic segments: \\n- ${missing\n .map(segment => `\"${getDynamicPathSegmentName(segment)}\"`)\n .join(\"\\n- \")}`\n });\n } else {\n for (const varName of Object.keys(command.path.dynamics ?? {})) {\n if (\n !command.path.segments\n .filter(isDynamicPathSegment)\n .find(segment => getDynamicPathSegmentName(segment) === varName)\n ) {\n failures.push({\n code: \"UNUSED_DYNAMIC_PATH_SEGMENT\",\n details: `The dynamic path segment name \"${\n varName\n }\" defined in the command's path dynamic segments is not used in the command folder path \"${command.path.segments.join(\n \"/\"\n )}\".`\n });\n }\n }\n\n command.path.segments.forEach((segment, index) => {\n if (\n isDynamicPathSegment(segment) &&\n command.path.dynamics[getDynamicPathSegmentName(segment)]\n ?.catchAll === true &&\n index + 1 < command.path.segments.length &&\n command.path.segments[index + 1] &&\n command.path.dynamics[\n getDynamicPathSegmentName(command.path.segments[index + 1]!)\n ]?.catchAll === true\n ) {\n failures.push({\n code: \"MULTIPLE_CATCH_ALL_PATH_SEGMENTS\",\n details: `The catch-all path segment \"${getDynamicPathSegmentName(\n segment\n )}\" in the command at path \"${command.path.segments.join(\n \"/\"\n )}\" is marked as catch-all, and it is followed by another catch-all dynamic path segment \"${getDynamicPathSegmentName(\n command.path.segments[index + 1]!\n )}\". Only one catch-all path segment is allowed per command, and it must be the final path segment.`\n });\n }\n });\n }\n }\n\n return failures;\n}\n\nexport function validateCommandOptions(\n command: CommandTree\n): ValidationFailure[] {\n const failures: ValidationFailure[] = [];\n\n const optionNames = new Set<string>();\n for (const option of Object.values(command.options ?? {})) {\n if (optionNames.has(option.name)) {\n failures.push({\n code: \"DUPLICATE_OPTION_NAME\",\n details: `Duplicate option name \"${option.name}\" found in command.`\n });\n }\n optionNames.add(option.name);\n\n for (const alias of option.alias) {\n if (optionNames.has(alias)) {\n failures.push({\n code: \"DUPLICATE_OPTION_ALIAS\",\n details: `Duplicate option name \"${alias}\" (an alias of \"${\n option.name\n }\") found in command.`\n });\n }\n optionNames.add(alias);\n }\n }\n\n return failures;\n}\n\nexport function validateCommand(command: CommandTree): ValidationFailure[] {\n const results: ValidationFailure[] = [];\n\n let failures = validateDynamicPathSegments(command);\n if (failures.length > 0) {\n results.push(...failures);\n }\n\n failures = validateCommandOptions(command);\n if (failures.length > 0) {\n results.push(...failures);\n }\n\n return results;\n}\n"],"mappings":"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"}
@@ -1,35 +1,35 @@
1
- import { getPositionalCommandOptionName, isPositionalCommandOption } from "../plugin-utils/context-helpers.mjs";
1
+ import { getDynamicPathSegmentName, isDynamicPathSegment } from "../plugin-utils/context-helpers.mjs";
2
2
 
3
3
  //#region src/helpers/validations.ts
4
- function validateCommandPositionalOptions(command) {
4
+ function validateDynamicPathSegments(command) {
5
5
  const failures = [];
6
6
  if (!command.isVirtual && command.path.segments.length > 0) {
7
- const positionalOptionPathNames = /* @__PURE__ */ new Set();
8
- for (const segment of command.path.segments.filter(isPositionalCommandOption) ?? []) {
9
- if (positionalOptionPathNames.has(segment)) failures.push({
10
- code: "DUPLICATE_POSITIONAL_OPTION_PATH_NAME",
11
- details: `Duplicate positional option path name "${getPositionalCommandOptionName(segment)}" found in command.`
7
+ const dynamicPathSegmentNames = /* @__PURE__ */ new Set();
8
+ for (const segment of command.path.segments.filter(isDynamicPathSegment) ?? []) {
9
+ if (dynamicPathSegmentNames.has(segment)) failures.push({
10
+ code: "DUPLICATE_DYNAMIC_PATH_SEGMENT_NAME",
11
+ details: `Duplicate dynamic path segment name "${getDynamicPathSegmentName(segment)}" found in command.`
12
12
  });
13
- positionalOptionPathNames.add(getPositionalCommandOptionName(segment));
13
+ dynamicPathSegmentNames.add(getDynamicPathSegmentName(segment));
14
14
  }
15
- if (command.path.segments.filter(isPositionalCommandOption).length !== Object.keys(command.path.positional ?? {}).length) failures.push({
16
- code: "POSITIONAL_OPTION_PATH_MISMATCH",
17
- details: `Mismatch between positional options path segments and defined path positional options in command (found ${command.path.segments.filter(isPositionalCommandOption).length} positional options in the command folder path "${command.path.segments.join("/")}", but ${Object.keys(command.path.positional ?? {}).length} potential positional option path(s) could be determined from the command's function signature).`
15
+ if (command.path.segments.filter(isDynamicPathSegment).length !== Object.keys(command.path.dynamics ?? {}).length) failures.push({
16
+ code: "DYNAMIC_PATH_SEGMENT_MISMATCH",
17
+ details: `Mismatch between dynamic path segments and defined dynamic path segments in command (found ${command.path.segments.filter(isDynamicPathSegment).length} dynamic path segments in the command folder path "${command.path.segments.join("/")}", but ${Object.keys(command.path.dynamics ?? {}).length} potential dynamic path segment(s) could be determined from the command's function signature).`
18
18
  });
19
- const missing = command.path.segments.filter(isPositionalCommandOption).filter((segment) => Object.prototype.hasOwnProperty.call(command.path.positional ?? {}, getPositionalCommandOptionName(segment)) === false);
19
+ const missing = command.path.segments.filter(isDynamicPathSegment).filter((segment) => Object.prototype.hasOwnProperty.call(command.path.dynamics ?? {}, getDynamicPathSegmentName(segment)) === false);
20
20
  if (missing.length > 0) failures.push({
21
- code: "MISSING_POSITIONAL_OPTION_PATH",
22
- details: `${missing.length} positional option path segment${missing.length > 1 ? "s" : ""} in the command folder path "${command.path.segments.join("/")}" do${missing.length > 1 ? "" : "es"} not have corresponding entr${missing.length > 1 ? "ies" : "y"} in the command's path positional options: \n- ${missing.map((segment) => `"${getPositionalCommandOptionName(segment)}"`).join("\n- ")}`
21
+ code: "MISSING_DYNAMIC_PATH_SEGMENT_DEFINITION",
22
+ details: `${missing.length} dynamic path segment${missing.length > 1 ? "s" : ""} in the command folder path "${command.path.segments.join("/")}" do${missing.length > 1 ? "" : "es"} not have corresponding entr${missing.length > 1 ? "ies" : "y"} in the command's path dynamic segments: \n- ${missing.map((segment) => `"${getDynamicPathSegmentName(segment)}"`).join("\n- ")}`
23
23
  });
24
24
  else {
25
- for (const varName of Object.keys(command.path.positional ?? {})) if (!command.path.segments.filter(isPositionalCommandOption).find((segment) => getPositionalCommandOptionName(segment) === varName)) failures.push({
26
- code: "UNUSED_POSITIONAL_OPTION_PATH",
27
- details: `The positional option path name "${varName}" defined in the command's path positional options is not used in the command folder path "${command.path.segments.join("/")}".`
25
+ for (const varName of Object.keys(command.path.dynamics ?? {})) if (!command.path.segments.filter(isDynamicPathSegment).find((segment) => getDynamicPathSegmentName(segment) === varName)) failures.push({
26
+ code: "UNUSED_DYNAMIC_PATH_SEGMENT",
27
+ details: `The dynamic path segment name "${varName}" defined in the command's path dynamic segments is not used in the command folder path "${command.path.segments.join("/")}".`
28
28
  });
29
29
  command.path.segments.forEach((segment, index) => {
30
- if (isPositionalCommandOption(segment) && command.path.positional[getPositionalCommandOptionName(segment)]?.variadic === true && index + 1 < command.path.segments.length && command.path.segments[index + 1] && command.path.positional[getPositionalCommandOptionName(command.path.segments[index + 1])]?.variadic === true) failures.push({
31
- code: "MULTIPLE_VARIADIC_POSITIONAL_OPTION_PATHS",
32
- details: `The positional option path segment "${getPositionalCommandOptionName(segment)}" in the command at path "${command.path.segments.join("/")}" is marked as variadic, and it is followed by another variadic positional option path segment "${getPositionalCommandOptionName(command.path.segments[index + 1])}". Only one variadic positional option path segment is allowed per command, and it must be the final path segment.`
30
+ if (isDynamicPathSegment(segment) && command.path.dynamics[getDynamicPathSegmentName(segment)]?.catchAll === true && index + 1 < command.path.segments.length && command.path.segments[index + 1] && command.path.dynamics[getDynamicPathSegmentName(command.path.segments[index + 1])]?.catchAll === true) failures.push({
31
+ code: "MULTIPLE_CATCH_ALL_PATH_SEGMENTS",
32
+ details: `The catch-all path segment "${getDynamicPathSegmentName(segment)}" in the command at path "${command.path.segments.join("/")}" is marked as catch-all, and it is followed by another catch-all dynamic path segment "${getDynamicPathSegmentName(command.path.segments[index + 1])}". Only one catch-all path segment is allowed per command, and it must be the final path segment.`
33
33
  });
34
34
  });
35
35
  }
@@ -57,7 +57,7 @@ function validateCommandOptions(command) {
57
57
  }
58
58
  function validateCommand(command) {
59
59
  const results = [];
60
- let failures = validateCommandPositionalOptions(command);
60
+ let failures = validateDynamicPathSegments(command);
61
61
  if (failures.length > 0) results.push(...failures);
62
62
  failures = validateCommandOptions(command);
63
63
  if (failures.length > 0) results.push(...failures);
@@ -1 +1 @@
1
- {"version":3,"file":"validations.mjs","names":["getPositionalCommandOptionName","isPositionalCommandOption","validateCommandPositionalOptions","command","failures","isVirtual","path","segments","length","positionalOptionPathNames","Set","segment","filter","has","push","code","details","add","Object","keys","positional","join","missing","prototype","hasOwnProperty","call","map","varName","find","forEach","index","variadic","validateCommandOptions","optionNames","option","values","options","name","alias","validateCommand","results"],"sources":["../../src/helpers/validations.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 {\n getPositionalCommandOptionName,\n isPositionalCommandOption\n} from \"../plugin-utils/context-helpers\";\nimport type { CommandTree } from \"../types\";\n\nexport interface ValidationFailure {\n code: string;\n details: string;\n}\n\nexport function validateCommandPositionalOptions(\n command: CommandTree\n): ValidationFailure[] {\n const failures: ValidationFailure[] = [];\n if (!command.isVirtual && command.path.segments.length > 0) {\n const positionalOptionPathNames = new Set<string>();\n for (const segment of command.path.segments.filter(\n isPositionalCommandOption\n ) ?? []) {\n if (positionalOptionPathNames.has(segment)) {\n failures.push({\n code: \"DUPLICATE_POSITIONAL_OPTION_PATH_NAME\",\n details: `Duplicate positional option path name \"${getPositionalCommandOptionName(segment)}\" found in command.`\n });\n }\n positionalOptionPathNames.add(getPositionalCommandOptionName(segment));\n }\n\n if (\n command.path.segments.filter(isPositionalCommandOption).length !==\n Object.keys(command.path.positional ?? {}).length\n ) {\n failures.push({\n code: \"POSITIONAL_OPTION_PATH_MISMATCH\",\n details: `Mismatch between positional options path segments and defined path positional options in command (found ${\n command.path.segments.filter(isPositionalCommandOption).length\n } positional options in the command folder path \"${command.path.segments.join(\"/\")}\", but ${\n Object.keys(command.path.positional ?? {}).length\n } potential positional option path(s) could be determined from the command's function signature).`\n });\n }\n\n const missing = command.path.segments\n .filter(isPositionalCommandOption)\n .filter(\n segment =>\n Object.prototype.hasOwnProperty.call(\n command.path.positional ?? {},\n getPositionalCommandOptionName(segment)\n ) === false\n );\n if (missing.length > 0) {\n failures.push({\n code: \"MISSING_POSITIONAL_OPTION_PATH\",\n details: `${missing.length} positional option path segment${missing.length > 1 ? \"s\" : \"\"} in the command folder path \"${command.path.segments.join(\n \"/\"\n )}\" do${missing.length > 1 ? \"\" : \"es\"} not have corresponding entr${\n missing.length > 1 ? \"ies\" : \"y\"\n } in the command's path positional options: \\n- ${missing\n .map(segment => `\"${getPositionalCommandOptionName(segment)}\"`)\n .join(\"\\n- \")}`\n });\n } else {\n for (const varName of Object.keys(command.path.positional ?? {})) {\n if (\n !command.path.segments\n .filter(isPositionalCommandOption)\n .find(\n segment => getPositionalCommandOptionName(segment) === varName\n )\n ) {\n failures.push({\n code: \"UNUSED_POSITIONAL_OPTION_PATH\",\n details: `The positional option path name \"${varName}\" defined in the command's path positional options is not used in the command folder path \"${command.path.segments.join(\n \"/\"\n )}\".`\n });\n }\n }\n\n command.path.segments.forEach((segment, index) => {\n if (\n isPositionalCommandOption(segment) &&\n command.path.positional[getPositionalCommandOptionName(segment)]\n ?.variadic === true &&\n index + 1 < command.path.segments.length &&\n command.path.segments[index + 1] &&\n command.path.positional[\n getPositionalCommandOptionName(command.path.segments[index + 1]!)\n ]?.variadic === true\n ) {\n failures.push({\n code: \"MULTIPLE_VARIADIC_POSITIONAL_OPTION_PATHS\",\n details: `The positional option path segment \"${getPositionalCommandOptionName(\n segment\n )}\" in the command at path \"${command.path.segments.join(\n \"/\"\n )}\" is marked as variadic, and it is followed by another variadic positional option path segment \"${getPositionalCommandOptionName(\n command.path.segments[index + 1]!\n )}\". Only one variadic positional option path segment is allowed per command, and it must be the final path segment.`\n });\n }\n });\n }\n }\n\n return failures;\n}\n\nexport function validateCommandOptions(\n command: CommandTree\n): ValidationFailure[] {\n const failures: ValidationFailure[] = [];\n\n const optionNames = new Set<string>();\n for (const option of Object.values(command.options ?? {})) {\n if (optionNames.has(option.name)) {\n failures.push({\n code: \"DUPLICATE_OPTION_NAME\",\n details: `Duplicate option name \"${option.name}\" found in command.`\n });\n }\n optionNames.add(option.name);\n\n for (const alias of option.alias) {\n if (optionNames.has(alias)) {\n failures.push({\n code: \"DUPLICATE_OPTION_ALIAS\",\n details: `Duplicate option name \"${alias}\" (an alias of \"${\n option.name\n }\") found in command.`\n });\n }\n optionNames.add(alias);\n }\n }\n\n return failures;\n}\n\nexport function validateCommand(command: CommandTree): ValidationFailure[] {\n const results: ValidationFailure[] = [];\n\n let failures = validateCommandPositionalOptions(command);\n if (failures.length > 0) {\n results.push(...failures);\n }\n\n failures = validateCommandOptions(command);\n if (failures.length > 0) {\n results.push(...failures);\n }\n\n return results;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"validations.mjs","names":["getDynamicPathSegmentName","isDynamicPathSegment","validateDynamicPathSegments","command","failures","isVirtual","path","segments","length","dynamicPathSegmentNames","Set","segment","filter","has","push","code","details","add","Object","keys","dynamics","join","missing","prototype","hasOwnProperty","call","map","varName","find","forEach","index","catchAll","validateCommandOptions","optionNames","option","values","options","name","alias","validateCommand","results"],"sources":["../../src/helpers/validations.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 {\n getDynamicPathSegmentName,\n isDynamicPathSegment\n} from \"../plugin-utils/context-helpers\";\nimport type { CommandTree } from \"../types\";\n\nexport interface ValidationFailure {\n code: string;\n details: string;\n}\n\nexport function validateDynamicPathSegments(\n command: CommandTree\n): ValidationFailure[] {\n const failures: ValidationFailure[] = [];\n if (!command.isVirtual && command.path.segments.length > 0) {\n const dynamicPathSegmentNames = new Set<string>();\n for (const segment of command.path.segments.filter(isDynamicPathSegment) ??\n []) {\n if (dynamicPathSegmentNames.has(segment)) {\n failures.push({\n code: \"DUPLICATE_DYNAMIC_PATH_SEGMENT_NAME\",\n details: `Duplicate dynamic path segment name \"${getDynamicPathSegmentName(segment)}\" found in command.`\n });\n }\n dynamicPathSegmentNames.add(getDynamicPathSegmentName(segment));\n }\n\n if (\n command.path.segments.filter(isDynamicPathSegment).length !==\n Object.keys(command.path.dynamics ?? {}).length\n ) {\n failures.push({\n code: \"DYNAMIC_PATH_SEGMENT_MISMATCH\",\n details: `Mismatch between dynamic path segments and defined dynamic path segments in command (found ${\n command.path.segments.filter(isDynamicPathSegment).length\n } dynamic path segments in the command folder path \"${command.path.segments.join(\"/\")}\", but ${\n Object.keys(command.path.dynamics ?? {}).length\n } potential dynamic path segment(s) could be determined from the command's function signature).`\n });\n }\n\n const missing = command.path.segments\n .filter(isDynamicPathSegment)\n .filter(\n segment =>\n Object.prototype.hasOwnProperty.call(\n command.path.dynamics ?? {},\n getDynamicPathSegmentName(segment)\n ) === false\n );\n if (missing.length > 0) {\n failures.push({\n code: \"MISSING_DYNAMIC_PATH_SEGMENT_DEFINITION\",\n details: `${missing.length} dynamic path segment${missing.length > 1 ? \"s\" : \"\"} in the command folder path \"${command.path.segments.join(\n \"/\"\n )}\" do${missing.length > 1 ? \"\" : \"es\"} not have corresponding entr${\n missing.length > 1 ? \"ies\" : \"y\"\n } in the command's path dynamic segments: \\n- ${missing\n .map(segment => `\"${getDynamicPathSegmentName(segment)}\"`)\n .join(\"\\n- \")}`\n });\n } else {\n for (const varName of Object.keys(command.path.dynamics ?? {})) {\n if (\n !command.path.segments\n .filter(isDynamicPathSegment)\n .find(segment => getDynamicPathSegmentName(segment) === varName)\n ) {\n failures.push({\n code: \"UNUSED_DYNAMIC_PATH_SEGMENT\",\n details: `The dynamic path segment name \"${\n varName\n }\" defined in the command's path dynamic segments is not used in the command folder path \"${command.path.segments.join(\n \"/\"\n )}\".`\n });\n }\n }\n\n command.path.segments.forEach((segment, index) => {\n if (\n isDynamicPathSegment(segment) &&\n command.path.dynamics[getDynamicPathSegmentName(segment)]\n ?.catchAll === true &&\n index + 1 < command.path.segments.length &&\n command.path.segments[index + 1] &&\n command.path.dynamics[\n getDynamicPathSegmentName(command.path.segments[index + 1]!)\n ]?.catchAll === true\n ) {\n failures.push({\n code: \"MULTIPLE_CATCH_ALL_PATH_SEGMENTS\",\n details: `The catch-all path segment \"${getDynamicPathSegmentName(\n segment\n )}\" in the command at path \"${command.path.segments.join(\n \"/\"\n )}\" is marked as catch-all, and it is followed by another catch-all dynamic path segment \"${getDynamicPathSegmentName(\n command.path.segments[index + 1]!\n )}\". Only one catch-all path segment is allowed per command, and it must be the final path segment.`\n });\n }\n });\n }\n }\n\n return failures;\n}\n\nexport function validateCommandOptions(\n command: CommandTree\n): ValidationFailure[] {\n const failures: ValidationFailure[] = [];\n\n const optionNames = new Set<string>();\n for (const option of Object.values(command.options ?? {})) {\n if (optionNames.has(option.name)) {\n failures.push({\n code: \"DUPLICATE_OPTION_NAME\",\n details: `Duplicate option name \"${option.name}\" found in command.`\n });\n }\n optionNames.add(option.name);\n\n for (const alias of option.alias) {\n if (optionNames.has(alias)) {\n failures.push({\n code: \"DUPLICATE_OPTION_ALIAS\",\n details: `Duplicate option name \"${alias}\" (an alias of \"${\n option.name\n }\") found in command.`\n });\n }\n optionNames.add(alias);\n }\n }\n\n return failures;\n}\n\nexport function validateCommand(command: CommandTree): ValidationFailure[] {\n const results: ValidationFailure[] = [];\n\n let failures = validateDynamicPathSegments(command);\n if (failures.length > 0) {\n results.push(...failures);\n }\n\n failures = validateCommandOptions(command);\n if (failures.length > 0) {\n results.push(...failures);\n }\n\n return results;\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { BaseCommandOption, BooleanCommandOption, CommandBase, CommandInput, CommandModule, CommandOption, CommandPath, CommandPositionalOption, CommandTree, CommandTreePath, Metadata, NumberCommandOption, SerializedCommandTree, StringCommandOption } from "./types/command.cjs";
1
+ import { BaseCommandOption, BooleanCommandOption, CommandBase, CommandDynamicSegment, CommandInput, CommandModule, CommandOption, CommandPath, CommandTree, CommandTreePath, Metadata, NumberCommandOption, SerializedCommandTree, StringCommandOption } from "./types/command.cjs";
2
2
  import { Context, UnresolvedContext } from "./types/context.cjs";
3
3
  import { BaseConfig, Options, OutputConfig, ResolvedConfig, UserConfig } from "./types/config.cjs";
4
4
  import { ShellShockAPI, createShellShock } from "./api.cjs";
@@ -6,4 +6,4 @@ import { defineConfig } from "./config.cjs";
6
6
  import { BaseCommandOptions } from "./types/options.cjs";
7
7
  import "./types/index.cjs";
8
8
  import plugin from "./plugin.cjs";
9
- export { BaseCommandOption, BaseCommandOptions, BaseConfig, BooleanCommandOption, CommandBase, CommandInput, CommandModule, CommandOption, CommandPath, CommandPositionalOption, CommandTree, CommandTreePath, Context, Metadata, NumberCommandOption, Options, OutputConfig, ResolvedConfig, SerializedCommandTree, ShellShockAPI, ShellShockAPI as default, StringCommandOption, UnresolvedContext, UserConfig, createShellShock, defineConfig, plugin, plugin as shellShock };
9
+ export { BaseCommandOption, BaseCommandOptions, BaseConfig, BooleanCommandOption, CommandBase, CommandDynamicSegment, CommandInput, CommandModule, CommandOption, CommandPath, CommandTree, CommandTreePath, Context, Metadata, NumberCommandOption, Options, OutputConfig, ResolvedConfig, SerializedCommandTree, ShellShockAPI, ShellShockAPI as default, StringCommandOption, UnresolvedContext, UserConfig, createShellShock, defineConfig, plugin, plugin as shellShock };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { BaseCommandOption, BooleanCommandOption, CommandBase, CommandInput, CommandModule, CommandOption, CommandPath, CommandPositionalOption, CommandTree, CommandTreePath, Metadata, NumberCommandOption, SerializedCommandTree, StringCommandOption } from "./types/command.mjs";
1
+ import { BaseCommandOption, BooleanCommandOption, CommandBase, CommandDynamicSegment, CommandInput, CommandModule, CommandOption, CommandPath, CommandTree, CommandTreePath, Metadata, NumberCommandOption, SerializedCommandTree, StringCommandOption } from "./types/command.mjs";
2
2
  import { Context, UnresolvedContext } from "./types/context.mjs";
3
3
  import { BaseConfig, Options, OutputConfig, ResolvedConfig, UserConfig } from "./types/config.mjs";
4
4
  import { ShellShockAPI, createShellShock } from "./api.mjs";
@@ -6,4 +6,4 @@ import { defineConfig } from "./config.mjs";
6
6
  import { BaseCommandOptions } from "./types/options.mjs";
7
7
  import "./types/index.mjs";
8
8
  import plugin from "./plugin.mjs";
9
- export { BaseCommandOption, BaseCommandOptions, BaseConfig, BooleanCommandOption, CommandBase, CommandInput, CommandModule, CommandOption, CommandPath, CommandPositionalOption, CommandTree, CommandTreePath, Context, Metadata, NumberCommandOption, Options, OutputConfig, ResolvedConfig, SerializedCommandTree, ShellShockAPI, ShellShockAPI as default, StringCommandOption, UnresolvedContext, UserConfig, createShellShock, defineConfig, plugin, plugin as shellShock };
9
+ export { BaseCommandOption, BaseCommandOptions, BaseConfig, BooleanCommandOption, CommandBase, CommandDynamicSegment, CommandInput, CommandModule, CommandOption, CommandPath, CommandTree, CommandTreePath, Context, Metadata, NumberCommandOption, Options, OutputConfig, ResolvedConfig, SerializedCommandTree, ShellShockAPI, ShellShockAPI as default, StringCommandOption, UnresolvedContext, UserConfig, createShellShock, defineConfig, plugin, plugin as shellShock };