@shell-shock/core 0.1.1 → 0.2.1

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 (62) hide show
  1. package/README.md +221 -0
  2. package/dist/_virtual/rolldown_runtime.cjs +29 -1
  3. package/dist/api.cjs +45 -1
  4. package/dist/api.d.cts +7 -0
  5. package/dist/api.d.mts +7 -0
  6. package/dist/api.mjs +44 -1
  7. package/dist/components/index.cjs +7 -0
  8. package/dist/components/index.d.cts +2 -0
  9. package/dist/components/index.d.mts +2 -0
  10. package/dist/components/index.mjs +3 -0
  11. package/dist/components/utils-builtin.cjs +453 -0
  12. package/dist/components/utils-builtin.d.cts +27 -0
  13. package/dist/components/utils-builtin.d.mts +27 -0
  14. package/dist/components/utils-builtin.mjs +447 -0
  15. package/dist/config.cjs +17 -1
  16. package/dist/config.mjs +16 -1
  17. package/dist/helpers/persistence.cjs +49 -0
  18. package/dist/helpers/persistence.mjs +46 -0
  19. package/dist/helpers/resolve-command.cjs +92 -1
  20. package/dist/helpers/resolve-command.mjs +88 -1
  21. package/dist/helpers/update-package-json.cjs +28 -1
  22. package/dist/helpers/update-package-json.mjs +27 -1
  23. package/dist/helpers/utilities.cjs +41 -0
  24. package/dist/helpers/utilities.mjs +38 -0
  25. package/dist/index.cjs +24 -1
  26. package/dist/index.d.cts +16 -2
  27. package/dist/index.d.mts +15 -2
  28. package/dist/index.mjs +19 -1
  29. package/dist/plugin-utils/get-command-tree.cjs +22 -0
  30. package/dist/plugin-utils/get-command-tree.d.cts +15 -0
  31. package/dist/plugin-utils/get-command-tree.d.mts +15 -0
  32. package/dist/plugin-utils/get-command-tree.mjs +21 -0
  33. package/dist/plugin-utils/index.cjs +3 -0
  34. package/dist/plugin-utils/index.d.cts +2 -0
  35. package/dist/plugin-utils/index.d.mts +2 -0
  36. package/dist/plugin-utils/index.mjs +3 -0
  37. package/dist/powerlines.cjs +172 -2
  38. package/dist/powerlines.d.cts +2 -2
  39. package/dist/powerlines.d.mts +2 -2
  40. package/dist/powerlines.mjs +168 -2
  41. package/dist/types/command.d.cts +63 -0
  42. package/dist/types/command.d.mts +63 -0
  43. package/dist/types/command.mjs +1 -0
  44. package/dist/types/config.d.cts +9 -26
  45. package/dist/types/config.d.mts +9 -26
  46. package/dist/types/config.mjs +1 -1
  47. package/dist/types/context.cjs +0 -0
  48. package/dist/types/context.d.cts +26 -0
  49. package/dist/types/context.d.mts +26 -0
  50. package/dist/types/context.mjs +1 -0
  51. package/dist/types/index.d.cts +4 -2
  52. package/dist/types/index.d.mts +4 -2
  53. package/dist/types/index.mjs +1 -1
  54. package/dist/types/options.cjs +0 -0
  55. package/dist/types/options.d.cts +7 -0
  56. package/dist/types/options.d.mts +7 -0
  57. package/dist/types/options.mjs +1 -0
  58. package/package.json +76 -13
  59. package/dist/types/build.d.cts +0 -66
  60. package/dist/types/build.d.mts +0 -66
  61. package/dist/types/build.mjs +0 -1
  62. /package/dist/types/{build.cjs → command.cjs} +0 -0
@@ -0,0 +1,447 @@
1
+ import defu$1 from "defu";
2
+ import { createComponent, createIntrinsic, mergeProps } from "@alloy-js/core/jsx-runtime";
3
+ import { Show, code, splitProps } from "@alloy-js/core";
4
+ import { FunctionDeclaration, InterfaceDeclaration, InterfaceMember, VarDeclaration } from "@alloy-js/typescript";
5
+ import { BuiltinFile } from "@powerlines/plugin-alloy/typescript/components/builtin-file";
6
+ import { TSDoc, TSDocLink, TSDocParam, TSDocReturns } from "@powerlines/plugin-alloy/typescript/components/tsdoc";
7
+
8
+ //#region src/components/utils-builtin.tsx
9
+ /**
10
+ * Generates utilities for detecting terminal color support.
11
+ */
12
+ function EnvSupportUtilities() {
13
+ return [
14
+ createComponent(VarDeclaration, {
15
+ "export": true,
16
+ "const": true,
17
+ name: "isTTY",
18
+ doc: "Detect if stdout.TTY is available",
19
+ initializer: code`Boolean(process.stdout && process.stdout.isTTY);`
20
+ }),
21
+ createIntrinsic("hbr", {}),
22
+ createIntrinsic("hbr", {}),
23
+ createComponent(VarDeclaration, {
24
+ "export": true,
25
+ "const": true,
26
+ name: "isMinimal",
27
+ doc: "Detect if the current environment is minimal (CI, non-TTY, etc.)",
28
+ initializer: code` env.MINIMAL || isCI || isTest || !isTTY; `
29
+ }),
30
+ createIntrinsic("hbr", {}),
31
+ createIntrinsic("hbr", {}),
32
+ createComponent(VarDeclaration, {
33
+ "export": true,
34
+ "const": true,
35
+ name: "isInteractive",
36
+ doc: "Detect if the current environment is interactive",
37
+ initializer: code` !isMinimal && process.stdin?.isTTY && env.TERM !== "dumb"; `
38
+ })
39
+ ];
40
+ }
41
+ /**
42
+ * Generates utilities for detecting terminal color support.
43
+ */
44
+ function ColorSupportUtilities() {
45
+ return [
46
+ createComponent(InterfaceDeclaration, {
47
+ "export": true,
48
+ name: "GetColorSupportLevelOptions",
49
+ doc: "Options for the getColorSupportLevel function",
50
+ get children() {
51
+ return createComponent(InterfaceMember, {
52
+ name: "ignoreFlags",
53
+ type: "boolean",
54
+ doc: "Indicates if the function should skip checking command-line flags for color support"
55
+ });
56
+ }
57
+ }),
58
+ createIntrinsic("hbr", {}),
59
+ createIntrinsic("hbr", {}),
60
+ createComponent(TSDoc, {
61
+ heading: "Checks if a specific flag is present in the command line arguments.",
62
+ get children() {
63
+ return [
64
+ createComponent(TSDocLink, { children: "https://github.com/sindresorhus/has-flag/blob/main/index.js" }),
65
+ createComponent(TSDocParam, {
66
+ name: "flag",
67
+ children: "The flag to check for, e.g., \"color\", \"no-color\"."
68
+ }),
69
+ createComponent(TSDocParam, {
70
+ name: "argv",
71
+ children: "The command line arguments to check against. Defaults to global Deno args or process args."
72
+ }),
73
+ createComponent(TSDocReturns, { children: "True if the flag is present, false otherwise." })
74
+ ];
75
+ }
76
+ }),
77
+ createComponent(FunctionDeclaration, {
78
+ "export": true,
79
+ name: "getColorSupportLevel",
80
+ parameters: [{
81
+ name: "stream",
82
+ type: "NodeJS.WriteStream & { fd: 1 | 2; }"
83
+ }, {
84
+ name: "options",
85
+ type: "GetColorSupportLevelOptions",
86
+ default: "{}"
87
+ }],
88
+ children: code`const { ignoreFlags = false } = options;
89
+
90
+ let forceColor: number | undefined;
91
+ if (env.FORCE_COLOR !== undefined) {
92
+ forceColor = !env.FORCE_COLOR
93
+ ? 0
94
+ : typeof env.FORCE_COLOR === "boolean"
95
+ ? 1
96
+ : typeof env.FORCE_COLOR === "number" &&
97
+ [0, 1, 2, 3].includes(Math.min(env.FORCE_COLOR as number, 3))
98
+ ? Math.min(env.FORCE_COLOR as number, 3)
99
+ : undefined;
100
+ }
101
+
102
+ if (ignoreFlags !== true && forceColor === undefined) {
103
+ forceColor = hasFlag("no-color") ||
104
+ hasFlag("no-colors") ||
105
+ hasFlag("color=false") ||
106
+ hasFlag("color=never")
107
+ ? 0
108
+ : hasFlag("color") ||
109
+ hasFlag("colors") ||
110
+ hasFlag("color=true") ||
111
+ hasFlag("color=always")
112
+ ? 1
113
+ : 0;
114
+ }
115
+
116
+ if (forceColor === 0) {
117
+ return 0;
118
+ }
119
+
120
+ if (ignoreFlags !== true) {
121
+ if (hasFlag("color=16m") ||
122
+ hasFlag("color=full") ||
123
+ hasFlag("color=truecolor")) {
124
+ return 3;
125
+ }
126
+
127
+ if (hasFlag("color=256")) {
128
+ return 2;
129
+ }
130
+ }
131
+
132
+ const level = Boolean(env.TF_BUILD) || Boolean(env.AGENT_NAME)
133
+ ? 1
134
+ : stream &&
135
+ !(isTTY || (stream && stream.isTTY)) &&
136
+ forceColor === undefined
137
+ ? 0
138
+ : env.TERM === "dumb"
139
+ ? forceColor || 0
140
+ : isWindows
141
+ ? Number(os.release().split(".")[0]) >= 10 &&
142
+ Number(os.release().split(".")[2]) >= 10_586
143
+ ? Number(os.release().split(".")[2]) >= 14_931
144
+ ? 3
145
+ : 2
146
+ : 1
147
+ : isCI
148
+ ? Boolean(env.GITHUB_ACTIONS) ||
149
+ Boolean(env.GITEA_ACTIONS) ||
150
+ Boolean(env.CIRCLECI)
151
+ ? 3
152
+ : Boolean(env.TRAVIS) ||
153
+ Boolean(env.APPVEYOR) ||
154
+ Boolean(env.GITLAB_CI) ||
155
+ Boolean(env.BUILDKITE) ||
156
+ Boolean(env.DRONE) ||
157
+ env.CI_NAME === "codeship"
158
+ ? 1
159
+ : forceColor || 0
160
+ : Boolean(env.TEAMCITY_VERSION)
161
+ ? /^(?:9\.0*[1-9]\d*\.|\d{2,}\.)/.test(String(env.TEAMCITY_VERSION) || "")
162
+ ? 1
163
+ : 0
164
+ : String(env.COLORTERM) === "truecolor" ||
165
+ env.TERM === "xterm-kitty"
166
+ ? 3
167
+ : Boolean(env.TERM_PROGRAM)
168
+ ? env.TERM_PROGRAM === "iTerm.app"
169
+ ? Number.parseInt(
170
+ (env.TERM_PROGRAM_VERSION || "").split(".")[0] as string,
171
+ 10
172
+ ) >= 3
173
+ ? 3
174
+ : 2
175
+ : env.TERM_PROGRAM === "Apple_Terminal"
176
+ ? 2
177
+ : 0
178
+ : /-256(?:color)?$/i.test(env.TERM || "")
179
+ ? 2
180
+ : /^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(
181
+ env.TERM || ""
182
+ )
183
+ ? 1
184
+ : Boolean(env.COLORTERM);
185
+
186
+ return typeof level === "boolean" || level === 0
187
+ ? false
188
+ : {
189
+ level,
190
+ hasBasic: true,
191
+ has256: level >= 2,
192
+ has16m: level >= 3,
193
+ };
194
+
195
+ `
196
+ }),
197
+ createIntrinsic("hbr", {}),
198
+ createIntrinsic("hbr", {}),
199
+ createComponent(VarDeclaration, {
200
+ "export": true,
201
+ "const": true,
202
+ name: "colorSupportLevels",
203
+ doc: "Detect the terminal color support level in the current environment",
204
+ initializer: code` {
205
+ stdout: getColorSupportLevel(process.stdout),
206
+ stderr: getColorSupportLevel(process.stderr),
207
+ }; `
208
+ }),
209
+ createIntrinsic("hbr", {}),
210
+ createIntrinsic("hbr", {}),
211
+ createComponent(VarDeclaration, {
212
+ "export": true,
213
+ "const": true,
214
+ name: "isColorSupported",
215
+ doc: "Detect if terminal color is supported in the current environment",
216
+ initializer: code` Boolean(colorSupportLevels.stdout); `
217
+ }),
218
+ createIntrinsic("hbr", {}),
219
+ createIntrinsic("hbr", {}),
220
+ createComponent(VarDeclaration, {
221
+ "export": true,
222
+ "const": true,
223
+ name: "isUnicodeSupported",
224
+ doc: "Detect if Unicode characters are supported in the current environment",
225
+ initializer: code` !isWindows
226
+ ? env.TERM !== "linux"
227
+ : Boolean(env.WT_SESSION) ||
228
+ Boolean(env.TERMINUS_SUBLIME) ||
229
+ env.ConEmuTask === "{cmd::Cmder}" ||
230
+ env.TERM_PROGRAM === "Terminus-Sublime" ||
231
+ env.TERM_PROGRAM === "vscode" ||
232
+ env.TERM === "xterm-256color" ||
233
+ env.TERM === "alacritty" ||
234
+ env.TERM === "rxvt-unicode" ||
235
+ env.TERM === "rxvt-unicode-256color" ||
236
+ env.TERMINAL_EMULATOR === "JetBrains-JediTerm"; `
237
+ })
238
+ ];
239
+ }
240
+ /**
241
+ * Generates utilities for detecting terminal color support.
242
+ */
243
+ function HyperlinkSupportUtilities() {
244
+ return [
245
+ createComponent(FunctionDeclaration, {
246
+ name: "parseVersion",
247
+ parameters: [{
248
+ name: "version",
249
+ type: "string",
250
+ default: "\"\""
251
+ }],
252
+ children: code`if (/^\d{3,4}$/.test(version)) {
253
+ const match = /(\d{1,2})(\d{2})/.exec(version) ?? [];
254
+
255
+ return {
256
+ major: 0,
257
+ minor: Number.parseInt(match[1]!, 10),
258
+ patch: Number.parseInt(match[2]!, 10)
259
+ };
260
+ }
261
+
262
+ const versionParts = (version ?? "")
263
+ .split(".")
264
+ .map(n => Number.parseInt(n, 10));
265
+
266
+ return {
267
+ major: versionParts[0],
268
+ minor: versionParts[1],
269
+ patch: versionParts[2]
270
+ }; `
271
+ }),
272
+ createComponent(TSDoc, {
273
+ heading: "Check if the current environment/terminal supports hyperlinks in the terminal.",
274
+ get children() {
275
+ return createComponent(TSDocReturns, { children: "True if the current environment/terminal supports hyperlinks." });
276
+ }
277
+ }),
278
+ createComponent(FunctionDeclaration, {
279
+ "export": true,
280
+ name: "isHyperlinkSupported",
281
+ returnType: "boolean",
282
+ children: code`if (Boolean(env.FORCE_HYPERLINK)) {
283
+ return true;
284
+ }
285
+
286
+ if (Boolean(env.NETLIFY)) {
287
+ return true;
288
+ } else if (isColorSupported || isTTY) {
289
+ return false;
290
+ } else if (Boolean(env.WT_SESSION)) {
291
+ return true;
292
+ } else if (isWindows || isMinimal || Boolean(env.TEAMCITY_VERSION)) {
293
+ return false;
294
+ } else if (Boolean(env.TERM_PROGRAM)) {
295
+ const version = parseVersion(env.TERM_PROGRAM_VERSION);
296
+
297
+ switch (String(env.TERM_PROGRAM)) {
298
+ case "iTerm.app": {
299
+ if (version.major === 3) {
300
+ return version.minor !== undefined && version.minor >= 1;
301
+ }
302
+
303
+ return version.major !== undefined && version.major > 3;
304
+ }
305
+ case "WezTerm": {
306
+ return version.major !== undefined && version.major >= 20_200_620;
307
+ }
308
+
309
+ case "vscode": {
310
+ if (Boolean(env.CURSOR_TRACE_ID)) {
311
+ return true;
312
+ }
313
+
314
+ return (
315
+ version.minor !== undefined &&
316
+ version.major !== undefined &&
317
+ (version.major > 1 || (version.major === 1 && version.minor >= 72))
318
+ );
319
+ }
320
+
321
+ case "ghostty": {
322
+ return true;
323
+ }
324
+ }
325
+ }
326
+
327
+ if (Boolean(env.VTE_VERSION)) {
328
+ if (env.VTE_VERSION === "0.50.0") {
329
+ return false;
330
+ }
331
+
332
+ const version = parseVersion(env.VTE_VERSION);
333
+ return (
334
+ (version.major !== undefined && version.major > 0) ||
335
+ (version.minor !== undefined && version.minor >= 50)
336
+ );
337
+ }
338
+
339
+ if (String(env.TERM) === "alacritty") {
340
+ return true;
341
+ }
342
+
343
+ return false; `
344
+ })
345
+ ];
346
+ }
347
+ /**
348
+ * Generates utilities for detecting terminal color support.
349
+ */
350
+ function ArgsUtilities() {
351
+ return [createComponent(TSDoc, {
352
+ heading: "Checks if a specific flag is present in the command line arguments.",
353
+ get children() {
354
+ return [
355
+ createComponent(TSDocLink, { children: "https://github.com/sindresorhus/has-flag/blob/main/index.js" }),
356
+ createComponent(TSDocParam, {
357
+ name: "flag",
358
+ children: "The flag (or an array of flags/aliases) to check for, e.g., \"color\", \"no-color\"."
359
+ }),
360
+ createComponent(TSDocParam, {
361
+ name: "argv",
362
+ children: "The command line arguments to check against. Defaults to global Deno args or process args."
363
+ }),
364
+ createComponent(TSDocReturns, { children: "True if the flag is present, false otherwise." })
365
+ ];
366
+ }
367
+ }), createComponent(FunctionDeclaration, {
368
+ "export": true,
369
+ name: "hasFlag",
370
+ parameters: [{
371
+ name: "flag",
372
+ type: "string | string[]"
373
+ }, {
374
+ name: "argv",
375
+ type: "string[]",
376
+ optional: true,
377
+ default: "globalThis.Deno ? globalThis.Deno.args : process.argv"
378
+ }],
379
+ get children() {
380
+ return [
381
+ createComponent(VarDeclaration, {
382
+ "const": true,
383
+ name: "position",
384
+ type: "number",
385
+ initializer: code`(Array.isArray(flag) ? flag : [flag]).reduce((ret, f) => {
386
+ const pos = argv.findIndex(arg => (f.startsWith("-") ? "" : (f.length === 1 ? "-" : "--") + f)?.toLowerCase() === arg?.toLowerCase() || arg?.toLowerCase().startsWith((f.length === 1 ? "-" : "--") + f + "=")?.toLowerCase());
387
+ return pos !== -1 ? pos : ret;
388
+ }, -1);`
389
+ }),
390
+ createIntrinsic("hbr", {}),
391
+ code`return position !== -1 && argv.indexOf("--") === -1 || position < argv.indexOf("--");`
392
+ ];
393
+ }
394
+ })];
395
+ }
396
+ /**
397
+ * A built-in utilities module for Shell Shock.
398
+ */
399
+ function UtilsBuiltin(props) {
400
+ const [{ children }, rest] = splitProps(props, ["children"]);
401
+ return createComponent(BuiltinFile, mergeProps({
402
+ id: "utils",
403
+ description: "A collection of helper utilities that ease command-line application development."
404
+ }, rest, {
405
+ get imports() {
406
+ return defu$1(rest.imports ?? {}, {
407
+ "node:os": ["os"],
408
+ "node:process": ["process"]
409
+ });
410
+ },
411
+ get builtinImports() {
412
+ return defu$1(rest.builtinImports ?? {}, { env: [
413
+ "env",
414
+ "isCI",
415
+ "isTest",
416
+ "isWindows"
417
+ ] });
418
+ },
419
+ get children() {
420
+ return [
421
+ createIntrinsic("hbr", {}),
422
+ createIntrinsic("hbr", {}),
423
+ createComponent(ArgsUtilities, {}),
424
+ createIntrinsic("hbr", {}),
425
+ createIntrinsic("hbr", {}),
426
+ createComponent(EnvSupportUtilities, {}),
427
+ createIntrinsic("hbr", {}),
428
+ createIntrinsic("hbr", {}),
429
+ createComponent(HyperlinkSupportUtilities, {}),
430
+ createIntrinsic("hbr", {}),
431
+ createIntrinsic("hbr", {}),
432
+ createComponent(ColorSupportUtilities, {}),
433
+ createIntrinsic("hbr", {}),
434
+ createIntrinsic("hbr", {}),
435
+ createComponent(Show, {
436
+ get when() {
437
+ return Boolean(children);
438
+ },
439
+ children
440
+ })
441
+ ];
442
+ }
443
+ }));
444
+ }
445
+
446
+ //#endregion
447
+ export { ArgsUtilities, ColorSupportUtilities, EnvSupportUtilities, HyperlinkSupportUtilities, UtilsBuiltin };
package/dist/config.cjs CHANGED
@@ -1 +1,17 @@
1
- function e(e){return e}exports.defineConfig=e;
1
+
2
+ //#region src/config.ts
3
+ /**
4
+ * A utility function to define a Shell Shock user configuration.
5
+ *
6
+ * @remarks
7
+ * This function is used to create a user configuration object for Shell Shock projects. It ensures that the configuration adheres to the expected structure.
8
+ *
9
+ * @param config - A partial user configuration object.
10
+ * @returns A complete user configuration object.
11
+ */
12
+ function defineConfig(config) {
13
+ return config;
14
+ }
15
+
16
+ //#endregion
17
+ exports.defineConfig = defineConfig;
package/dist/config.mjs CHANGED
@@ -1 +1,16 @@
1
- function e(e){return e}export{e as defineConfig};
1
+ //#region src/config.ts
2
+ /**
3
+ * A utility function to define a Shell Shock user configuration.
4
+ *
5
+ * @remarks
6
+ * This function is used to create a user configuration object for Shell Shock projects. It ensures that the configuration adheres to the expected structure.
7
+ *
8
+ * @param config - A partial user configuration object.
9
+ * @returns A complete user configuration object.
10
+ */
11
+ function defineConfig(config) {
12
+ return config;
13
+ }
14
+
15
+ //#endregion
16
+ export { defineConfig };
@@ -0,0 +1,49 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ let __stryke_path_join_paths = require("@stryke/path/join-paths");
3
+
4
+ //#region src/helpers/persistence.ts
5
+ function getCommandsPersistencePath(context) {
6
+ return (0, __stryke_path_join_paths.joinPaths)(context.dataPath, `commands.json`);
7
+ }
8
+ function serializedCommandTree(commands) {
9
+ const serialize = (node, parent = null) => {
10
+ const serializedNode = {
11
+ ...node,
12
+ parent,
13
+ children: {}
14
+ };
15
+ for (const [key, child] of Object.entries(node.children || {})) serializedNode.children[key] = serialize(child, node.id);
16
+ return serializedNode;
17
+ };
18
+ const result = {};
19
+ for (const [key, child] of Object.entries(commands)) result[key] = serialize(child, null);
20
+ return result;
21
+ }
22
+ function deserializeCommandTree(serializedCommands) {
23
+ const deserialize = (node, parent = null) => {
24
+ const deserializedNode = {
25
+ ...node,
26
+ parent,
27
+ children: {}
28
+ };
29
+ for (const [key, child] of Object.entries(node.children || {})) deserializedNode.children[key] = deserialize(child, deserializedNode);
30
+ return deserializedNode;
31
+ };
32
+ const result = {};
33
+ for (const [key, child] of Object.entries(serializedCommands)) result[key] = deserialize(child, null);
34
+ return result;
35
+ }
36
+ async function readCommandsPersistence(context) {
37
+ const reflections = await context.fs.read(getCommandsPersistencePath(context));
38
+ if (!reflections || !reflections.length) throw new Error(`CLI Command reflection file ${getCommandsPersistencePath(context)} is empty`);
39
+ context.commands = deserializeCommandTree(JSON.parse(reflections));
40
+ }
41
+ async function writeCommandsPersistence(context) {
42
+ const filePath = getCommandsPersistencePath(context);
43
+ await context.fs.write(filePath, JSON.stringify(serializedCommandTree(context.commands), null, context.config.mode === "development" ? 2 : 0));
44
+ }
45
+
46
+ //#endregion
47
+ exports.getCommandsPersistencePath = getCommandsPersistencePath;
48
+ exports.readCommandsPersistence = readCommandsPersistence;
49
+ exports.writeCommandsPersistence = writeCommandsPersistence;
@@ -0,0 +1,46 @@
1
+ import { joinPaths } from "@stryke/path/join-paths";
2
+
3
+ //#region src/helpers/persistence.ts
4
+ function getCommandsPersistencePath(context) {
5
+ return joinPaths(context.dataPath, `commands.json`);
6
+ }
7
+ function serializedCommandTree(commands) {
8
+ const serialize = (node, parent = null) => {
9
+ const serializedNode = {
10
+ ...node,
11
+ parent,
12
+ children: {}
13
+ };
14
+ for (const [key, child] of Object.entries(node.children || {})) serializedNode.children[key] = serialize(child, node.id);
15
+ return serializedNode;
16
+ };
17
+ const result = {};
18
+ for (const [key, child] of Object.entries(commands)) result[key] = serialize(child, null);
19
+ return result;
20
+ }
21
+ function deserializeCommandTree(serializedCommands) {
22
+ const deserialize = (node, parent = null) => {
23
+ const deserializedNode = {
24
+ ...node,
25
+ parent,
26
+ children: {}
27
+ };
28
+ for (const [key, child] of Object.entries(node.children || {})) deserializedNode.children[key] = deserialize(child, deserializedNode);
29
+ return deserializedNode;
30
+ };
31
+ const result = {};
32
+ for (const [key, child] of Object.entries(serializedCommands)) result[key] = deserialize(child, null);
33
+ return result;
34
+ }
35
+ async function readCommandsPersistence(context) {
36
+ const reflections = await context.fs.read(getCommandsPersistencePath(context));
37
+ if (!reflections || !reflections.length) throw new Error(`CLI Command reflection file ${getCommandsPersistencePath(context)} is empty`);
38
+ context.commands = deserializeCommandTree(JSON.parse(reflections));
39
+ }
40
+ async function writeCommandsPersistence(context) {
41
+ const filePath = getCommandsPersistencePath(context);
42
+ await context.fs.write(filePath, JSON.stringify(serializedCommandTree(context.commands), null, context.config.mode === "development" ? 2 : 0));
43
+ }
44
+
45
+ //#endregion
46
+ export { getCommandsPersistencePath, readCommandsPersistence, writeCommandsPersistence };
@@ -1 +1,92 @@
1
- const e=require(`../_virtual/rolldown_runtime.cjs`);let t=require(`@stryke/path/append`),n=require(`@stryke/path/file-path-fns`),r=require(`@stryke/type-checks/is-set-object`),i=require(`@stryke/path/common`),a=require(`@stryke/path/normalize`),o=require(`@stryke/path/replace`),s=require(`@stryke/type-checks/is-set-string`);function c(e,t){return(0,o.replacePath)((0,n.findFilePath)(t),e.commandsRoot).replaceAll(/^\/+/g,``).replaceAll(/\/+$/g,``)}function l(e){return(0,s.isSetString)(e.config.entry)?(0,t.appendPath)((0,t.appendPath)((0,a.stripStars)(e.config.entry),e.config.projectRoot),e.workspaceConfig.workspaceRoot):(0,r.isSetObject)(e.config.entry)&&`file`in e.config.entry?(0,t.appendPath)((0,t.appendPath)((0,a.stripStars)(e.config.entry.file),e.config.projectRoot),e.workspaceConfig.workspaceRoot):Array.isArray(e.config.entry)&&e.config.entry.length>0?(0,i.commonPath)(e.config.entry.map(n=>(0,t.appendPath)((0,t.appendPath)((0,a.stripStars)((0,s.isSetString)(n)?n:n.file),e.config.projectRoot),e.workspaceConfig.workspaceRoot))):(0,t.appendPath)(e.config.sourceRoot||e.config.projectRoot,e.workspaceConfig.workspaceRoot)}exports.findCommandsRoot=l,exports.resolveCommandPath=c;
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ let __stryke_helpers_get_unique = require("@stryke/helpers/get-unique");
3
+ let __stryke_path_append = require("@stryke/path/append");
4
+ let __stryke_path_file_path_fns = require("@stryke/path/file-path-fns");
5
+ let __stryke_path_replace = require("@stryke/path/replace");
6
+ let __stryke_path_resolve_parent_path = require("@stryke/path/resolve-parent-path");
7
+ let __stryke_string_format_title_case = require("@stryke/string-format/title-case");
8
+ let __stryke_type_checks_is_function = require("@stryke/type-checks/is-function");
9
+ let __stryke_type_checks_is_set_object = require("@stryke/type-checks/is-set-object");
10
+ let __powerlines_deepkit_reflect_type = require("@powerlines/deepkit/reflect-type");
11
+ let __powerlines_deepkit_vendor_type = require("@powerlines/deepkit/vendor/type");
12
+ let __stryke_path_common = require("@stryke/path/common");
13
+ let __stryke_path_normalize = require("@stryke/path/normalize");
14
+ let __stryke_type_checks_is_set_string = require("@stryke/type-checks/is-set-string");
15
+
16
+ //#region src/helpers/resolve-command.ts
17
+ function resolveCommandPath(context, file) {
18
+ return (0, __stryke_path_replace.replacePath)((0, __stryke_path_file_path_fns.findFilePath)(file), context.commandsPath).replaceAll(/^\/+/g, "").replaceAll(/\/+$/g, "");
19
+ }
20
+ function findCommandsRoot(context) {
21
+ if ((0, __stryke_type_checks_is_set_string.isSetString)(context.config.entry)) return (0, __stryke_path_append.appendPath)((0, __stryke_path_append.appendPath)((0, __stryke_path_normalize.stripStars)(context.config.entry), context.config.projectRoot), context.workspaceConfig.workspaceRoot);
22
+ else if ((0, __stryke_type_checks_is_set_object.isSetObject)(context.config.entry) && "file" in context.config.entry) return (0, __stryke_path_append.appendPath)((0, __stryke_path_append.appendPath)((0, __stryke_path_normalize.stripStars)(context.config.entry.file), context.config.projectRoot), context.workspaceConfig.workspaceRoot);
23
+ else if (Array.isArray(context.config.entry) && context.config.entry.length > 0) return (0, __stryke_path_common.commonPath)(context.config.entry.map((entry) => (0, __stryke_path_append.appendPath)((0, __stryke_path_append.appendPath)((0, __stryke_path_normalize.stripStars)((0, __stryke_type_checks_is_set_string.isSetString)(entry) ? entry : entry.file), context.config.projectRoot), context.workspaceConfig.workspaceRoot)));
24
+ return (0, __stryke_path_append.appendPath)(context.config.sourceRoot || context.config.projectRoot, context.workspaceConfig.workspaceRoot);
25
+ }
26
+ /**
27
+ * Finds the command name from the given file path.
28
+ *
29
+ * @param file - The file path to extract the command name from.
30
+ * @returns The command name.
31
+ */
32
+ function findCommandName(file) {
33
+ let name = (0, __stryke_path_file_path_fns.findFolderName)(file);
34
+ let count = 1;
35
+ while (name.startsWith("[") && name.endsWith("]")) name = (0, __stryke_path_file_path_fns.findFolderName)((0, __stryke_path_resolve_parent_path.resolveParentPath)(file, count++));
36
+ return name;
37
+ }
38
+ async function reflectCommandTree(context, command, parent) {
39
+ const title = command.title || `${parent?.title ? `${parent.title} - ` : ""}${(0, __stryke_string_format_title_case.titleCase)(command.name)}`;
40
+ const commandTree = {
41
+ ...command,
42
+ title,
43
+ description: command.description || `The ${title} ${parent ? "sub-" : ""}command.`,
44
+ options: {},
45
+ params: [],
46
+ parent: parent ?? null,
47
+ children: {}
48
+ };
49
+ if (context.config.defaultOptions === false) commandTree.options = {};
50
+ else if (Array.isArray(context.config.defaultOptions)) commandTree.options = Object.fromEntries((0, __stryke_helpers_get_unique.getUniqueBy)(context.config.defaultOptions, (item) => item.name).map((option) => [option.name, option]));
51
+ else if ((0, __stryke_type_checks_is_function.isFunction)(context.config.defaultOptions)) commandTree.options = Object.fromEntries((0, __stryke_helpers_get_unique.getUniqueBy)(context.config.defaultOptions(context, command), (item) => item.name).map((option) => [option.name, option]));
52
+ if (command.isVirtual) context.trace(`Adding reflection for virtual command: ${command.id}`);
53
+ else {
54
+ if (!command.entry.input?.file || !context.fs.existsSync(command.entry.input.file)) throw new Error(`${!command.entry.input?.file ? "Missing" : "Non-existent"} command entry file for "${command.name}"`);
55
+ context.trace(`Adding reflection for user-defined command: ${command.id} (file: ${command.entry.input.file})`);
56
+ const type = await (0, __powerlines_deepkit_reflect_type.reflectType)(context, command.entry.input);
57
+ if (type.kind !== __powerlines_deepkit_vendor_type.ReflectionKind.function) throw new Error(`The command entry file "${command.entry.input.file}" does not export a valid function.`);
58
+ if (type.parameters.length > 0 && type.parameters[0]) {
59
+ const firstParam = type.parameters[0];
60
+ if (firstParam.type.kind === __powerlines_deepkit_vendor_type.ReflectionKind.objectLiteral || firstParam.type.kind === __powerlines_deepkit_vendor_type.ReflectionKind.class) {
61
+ const optionsReflection = __powerlines_deepkit_vendor_type.ReflectionClass.from(firstParam.type);
62
+ for (const propertyReflection of optionsReflection.getProperties()) {
63
+ const propertyType = propertyReflection.getType();
64
+ commandTree.options[propertyReflection.getNameAsString()] = {
65
+ name: propertyReflection.getNameAsString(),
66
+ alias: propertyReflection.getTags().alias ?? [],
67
+ title: propertyReflection.getTags().title || (0, __stryke_string_format_title_case.titleCase)(propertyReflection.getNameAsString()),
68
+ description: propertyReflection.getDescription(),
69
+ kind: propertyType.kind,
70
+ optional: propertyReflection.isOptional(),
71
+ default: propertyReflection.getDefaultValue(),
72
+ variadic: false
73
+ };
74
+ commandTree.options[propertyReflection.getNameAsString()].description ??= `The ${commandTree.options[propertyReflection.getNameAsString()].title} option.`;
75
+ if (propertyType.kind === __powerlines_deepkit_vendor_type.ReflectionKind.array) if (propertyType.type.kind === __powerlines_deepkit_vendor_type.ReflectionKind.string || propertyType.type.kind === __powerlines_deepkit_vendor_type.ReflectionKind.number) {
76
+ commandTree.options[propertyReflection.getNameAsString()].variadic = true;
77
+ commandTree.options[propertyReflection.getNameAsString()].kind = propertyType.type.kind;
78
+ } else throw new Error(`Unsupported array type for option "${propertyReflection.getNameAsString()}" in command "${command.name}". Only string[] and number[] are supported.`);
79
+ else if (propertyType.kind !== __powerlines_deepkit_vendor_type.ReflectionKind.boolean && propertyType.kind !== __powerlines_deepkit_vendor_type.ReflectionKind.string && propertyType.kind !== __powerlines_deepkit_vendor_type.ReflectionKind.number) throw new Error(`Unsupported type for option "${propertyReflection.getNameAsString()}" in command "${command.name}". Only string, number, boolean, string[] and number[] are supported, received ${(0, __powerlines_deepkit_vendor_type.stringifyType)(propertyType).trim().replaceAll(" | ", ", or ")}.`);
80
+ }
81
+ }
82
+ }
83
+ }
84
+ for (const input of context.inputs.filter((input$1) => input$1.path.length === command.path.length + 1 && input$1.path.slice(0, command.path.length).every((value, index) => value === command.path[index]))) commandTree.children[input.name] = await reflectCommandTree(context, input, commandTree);
85
+ return commandTree;
86
+ }
87
+
88
+ //#endregion
89
+ exports.findCommandName = findCommandName;
90
+ exports.findCommandsRoot = findCommandsRoot;
91
+ exports.reflectCommandTree = reflectCommandTree;
92
+ exports.resolveCommandPath = resolveCommandPath;