@shell-shock/core 0.2.0 → 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 (50) 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.mjs +44 -1
  5. package/dist/components/index.cjs +7 -0
  6. package/dist/components/index.d.cts +2 -0
  7. package/dist/components/index.d.mts +2 -0
  8. package/dist/components/index.mjs +3 -0
  9. package/dist/components/utils-builtin.cjs +453 -0
  10. package/dist/components/utils-builtin.d.cts +27 -0
  11. package/dist/components/utils-builtin.d.mts +27 -0
  12. package/dist/components/utils-builtin.mjs +447 -0
  13. package/dist/config.cjs +17 -1
  14. package/dist/config.mjs +16 -1
  15. package/dist/helpers/persistence.cjs +49 -1
  16. package/dist/helpers/persistence.mjs +46 -1
  17. package/dist/helpers/resolve-command.cjs +92 -1
  18. package/dist/helpers/resolve-command.mjs +88 -1
  19. package/dist/helpers/update-package-json.cjs +28 -1
  20. package/dist/helpers/update-package-json.mjs +27 -1
  21. package/dist/helpers/utilities.cjs +41 -1
  22. package/dist/helpers/utilities.mjs +38 -1
  23. package/dist/index.cjs +24 -1
  24. package/dist/index.d.cts +2 -2
  25. package/dist/index.d.mts +1 -2
  26. package/dist/index.mjs +19 -1
  27. package/dist/plugin-utils/get-command-tree.cjs +22 -0
  28. package/dist/plugin-utils/get-command-tree.d.cts +15 -0
  29. package/dist/plugin-utils/get-command-tree.d.mts +15 -0
  30. package/dist/plugin-utils/get-command-tree.mjs +21 -0
  31. package/dist/plugin-utils/index.cjs +3 -0
  32. package/dist/plugin-utils/index.d.cts +2 -0
  33. package/dist/plugin-utils/index.d.mts +2 -0
  34. package/dist/plugin-utils/index.mjs +3 -0
  35. package/dist/powerlines.cjs +172 -3
  36. package/dist/powerlines.mjs +168 -3
  37. package/dist/types/command.mjs +1 -1
  38. package/dist/types/config.d.cts +4 -19
  39. package/dist/types/config.d.mts +4 -19
  40. package/dist/types/config.mjs +1 -1
  41. package/dist/types/context.d.cts +2 -1
  42. package/dist/types/context.d.mts +2 -1
  43. package/dist/types/context.mjs +1 -1
  44. package/dist/types/index.mjs +1 -1
  45. package/dist/types/options.mjs +1 -1
  46. package/package.json +75 -15
  47. package/dist/helpers/get-default-options.cjs +0 -1
  48. package/dist/helpers/get-default-options.d.cts +0 -15
  49. package/dist/helpers/get-default-options.d.mts +0 -15
  50. package/dist/helpers/get-default-options.mjs +0 -1
@@ -1,3 +1,172 @@
1
- Object.defineProperty(exports,`__esModule`,{value:!0});const e=require(`./_virtual/rolldown_runtime.cjs`),t=require(`./helpers/get-default-options.cjs`),n=require(`./helpers/persistence.cjs`),r=require(`./helpers/resolve-command.cjs`),i=require(`./helpers/update-package-json.cjs`),a=require(`./helpers/utilities.cjs`);let o=require(`@stryke/fs/chmod-x`),s=require(`@stryke/path/append`),c=require(`@stryke/path/file-path-fns`),l=require(`@stryke/path/is-parent-path`),u=require(`@stryke/path/join-paths`),d=require(`@stryke/path/replace`),f=require(`@stryke/path/resolve-parent-path`),p=require(`@stryke/string-format/title-case`),m=require(`@stryke/type-checks/is-set-object`),h=require(`defu`),g=require(`node:fs`);const _=50,v=(e={})=>[{name:`shell-shock:config`,async config(){return this.trace(`Resolving the Shell Shock configuration.`),(0,h.defu)(e,{entry:!this.config.entry||Array.isArray(this.config.entry)&&this.config.entry.length===0?[(0,u.joinPaths)(this.config.sourceRoot,`**/*`)]:void 0,build:{target:`node22`,platform:`node`},interactive:!0,type:`application`,framework:`shell-shock`})},configResolved:{order:`pre`,async handler(){this.trace(`Shell Shock configuration has been resolved.`),await i.updatePackageJsonBinary(this),this.config.name=a.getAppName(this),this.config.title=a.getAppTitle(this),this.config.description=a.getAppDescription(this),this.options=t.getDefaultOptions(this,{id:null,name:this.config.name,title:this.config.title,description:this.config.description,path:[],isVirtual:!1}),this.inputs??=[]}}},{name:`shell-shock:inputs`,async configResolved(){this.trace(`Finding command entry points.`),this.commandsPath=r.findCommandsRoot(this),this.inputs=this.entry.filter(e=>(0,c.findFileName)(e.file,{withExtension:!1})===`command`).reduce((e,t)=>{let n=(0,s.appendPath)((0,s.appendPath)(t.file,this.config.projectRoot),this.workspaceConfig.workspaceRoot);if(!(0,l.isParentPath)(n,this.commandsPath))throw Error(`Command entry point "${n}" is not located within the commands root "${this.commandsPath}". Please ensure that all command entry points are located within the current project.`);let i=r.resolveCommandPath(this,n),a=i.replaceAll(`/`,`-`);if(!e.some(e=>e.id===a)){let o=r.findCommandName(n);e.push({id:a,path:i.split(`/`).filter(Boolean),name:o,title:(0,p.titleCase)(o),isVirtual:!1,entry:{...t,file:n,input:{file:t.file,name:t.name},output:o}})}return e},this.inputs)}},{name:`shell-shock:virtual-inputs`,configResolved:{order:`post`,async handler(){this.inputs.length===0?this.warn(`No commands were found in the project. Please ensure at least one command exists.`):(this.info(`Shell Shock will create an application with the following commands: \n${this.inputs.filter(e=>!e.isVirtual).map(e=>` - ${e.id}: ${(0,d.replacePath)(e.entry.file,this.commandsPath)}${e.isVirtual?` (virtual)`:``}`).join(`
2
- `)}`),this.trace(`Finding and adding virtual command inputs for each command previously found.`),this.inputs=this.inputs.reduce((e,t)=>{let n=0,i=(0,f.resolveParentPath)((0,c.findFilePath)(t.entry.file));for(;i!==this.commandsPath;){if(n++>50)throw Error(`Maximum command virtual parent depth of 50 exceeded while processing command: ${t.name}`);if(!e.some(e=>(0,c.findFilePath)(e.entry.file)===i)){let t=(0,u.joinPaths)(i,`command.ts`),n=r.resolveCommandPath(this,t),a=n.replaceAll(`/`,`-`);if(!e.some(e=>e.id===a)){let i=r.findCommandName(t);e.push({id:a,path:n.split(`/`).filter(Boolean),name:i,title:(0,p.titleCase)(i),isVirtual:!0,entry:{file:t,input:{file:t}}})}}i=(0,f.resolveParentPath)(i)}return e},this.inputs).sort((e,t)=>e.path.length-t.path.length),this.trace(`Final command input list: \n${this.inputs.map(e=>` - ${e.id}: ${(0,d.replacePath)(e.entry.file,this.commandsPath)}${e.isVirtual?` (virtual)`:``}`).join(`
3
- `)}`))}}},{name:`shell-shock:reflect-commands`,async prepare(){if(this.entry=[],this.commands={},this.config.command!==`prepare`&&this.persistedMeta?.checksum===this.meta.checksum&&this.fs.existsSync(n.getCommandsPersistencePath(this)))this.debug(`Skipping reflection initialization as the meta checksum has not changed.`),await n.readCommandsPersistence(this);else{for(let e of this.inputs.filter(e=>e.path.length===1))this.commands[e.name]=await r.reflectCommandTree(this,e);await n.writeCommandsPersistence(this)}}},{name:`shell-shock:chmod+x`,async buildEnd(){if(!(0,m.isSetObject)(this.packageJson.bin)){this.warn(`No binaries were found in package.json. Please ensure the binaries are correctly configured.`);return}this.debug(`Adding executable permissions to binaries.`);for(let e of Object.values(this.packageJson.bin))(0,g.existsSync)((0,s.appendPath)(e,this.config.output.buildPath))&&await(0,o.chmodX)((0,s.appendPath)(e,this.config.output.buildPath))}}];var y=v;exports.default=y,exports.shellShock=v;
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
3
+ const require_persistence = require('./helpers/persistence.cjs');
4
+ const require_resolve_command = require('./helpers/resolve-command.cjs');
5
+ const require_update_package_json = require('./helpers/update-package-json.cjs');
6
+ const require_utilities = require('./helpers/utilities.cjs');
7
+ let __powerlines_plugin_tsdown = require("@powerlines/plugin-tsdown");
8
+ __powerlines_plugin_tsdown = require_rolldown_runtime.__toESM(__powerlines_plugin_tsdown);
9
+ let __stryke_fs_chmod_x = require("@stryke/fs/chmod-x");
10
+ let __stryke_helpers_get_unique = require("@stryke/helpers/get-unique");
11
+ let __stryke_path_append = require("@stryke/path/append");
12
+ let __stryke_path_file_path_fns = require("@stryke/path/file-path-fns");
13
+ let __stryke_path_is_parent_path = require("@stryke/path/is-parent-path");
14
+ let __stryke_path_join_paths = require("@stryke/path/join-paths");
15
+ let __stryke_path_replace = require("@stryke/path/replace");
16
+ let __stryke_path_resolve_parent_path = require("@stryke/path/resolve-parent-path");
17
+ let __stryke_string_format_title_case = require("@stryke/string-format/title-case");
18
+ let __stryke_type_checks_is_function = require("@stryke/type-checks/is-function");
19
+ let __stryke_type_checks_is_set_object = require("@stryke/type-checks/is-set-object");
20
+ let defu = require("defu");
21
+
22
+ //#region src/powerlines.ts
23
+ const MAX_DEPTH = 50;
24
+ /**
25
+ * The core Powerlines plugin to build Shell Shock projects.
26
+ */
27
+ const shellShock = (options = {}) => {
28
+ return [
29
+ (0, __powerlines_plugin_tsdown.default)(),
30
+ {
31
+ name: "shell-shock:config",
32
+ async config() {
33
+ this.trace("Resolving the Shell Shock configuration.");
34
+ return (0, defu.defu)(options, {
35
+ entry: !this.config.entry || Array.isArray(this.config.entry) && this.config.entry.length === 0 ? [(0, __stryke_path_join_paths.joinPaths)(this.config.sourceRoot, "**/*")] : void 0,
36
+ build: {
37
+ target: "node22",
38
+ platform: "node"
39
+ },
40
+ type: "application",
41
+ framework: "shell-shock"
42
+ });
43
+ },
44
+ configResolved: {
45
+ order: "pre",
46
+ async handler() {
47
+ this.trace("Shell Shock configuration has been resolved.");
48
+ await require_update_package_json.updatePackageJsonBinary(this);
49
+ this.config.name = require_utilities.getAppName(this);
50
+ this.config.title = require_utilities.getAppTitle(this);
51
+ this.config.description = require_utilities.getAppDescription(this);
52
+ if (this.config.defaultOptions === false) this.options = [];
53
+ else if (Array.isArray(this.config.defaultOptions)) this.options = (0, __stryke_helpers_get_unique.getUniqueBy)(this.config.defaultOptions, (item) => item.name);
54
+ else if ((0, __stryke_type_checks_is_function.isFunction)(this.config.defaultOptions)) this.options = (0, __stryke_helpers_get_unique.getUniqueBy)(this.config.defaultOptions(this, {
55
+ id: null,
56
+ name: this.config.name,
57
+ title: this.config.title,
58
+ description: this.config.description,
59
+ path: [],
60
+ isVirtual: false
61
+ }), (item) => item.name);
62
+ this.inputs ??= [];
63
+ }
64
+ }
65
+ },
66
+ {
67
+ name: "shell-shock:inputs",
68
+ async configResolved() {
69
+ this.trace("Finding command entry points.");
70
+ this.commandsPath = require_resolve_command.findCommandsRoot(this);
71
+ this.inputs = this.entry.filter((entry) => (0, __stryke_path_file_path_fns.findFileName)(entry.file, { withExtension: false }) === "command").reduce((ret, entry) => {
72
+ const file = (0, __stryke_path_append.appendPath)((0, __stryke_path_append.appendPath)(entry.file, this.config.projectRoot), this.workspaceConfig.workspaceRoot);
73
+ if (!(0, __stryke_path_is_parent_path.isParentPath)(file, this.commandsPath)) throw new Error(`Command entry point "${file}" is not located within the commands root "${this.commandsPath}". Please ensure that all command entry points are located within the current project.`);
74
+ const path = require_resolve_command.resolveCommandPath(this, file);
75
+ const id = path.replaceAll("/", "-");
76
+ if (!ret.some((existing) => existing.id === id)) {
77
+ const name = require_resolve_command.findCommandName(file);
78
+ ret.push({
79
+ id,
80
+ path: path.split("/").filter(Boolean),
81
+ name,
82
+ title: (0, __stryke_string_format_title_case.titleCase)(name),
83
+ isVirtual: false,
84
+ entry: {
85
+ ...entry,
86
+ file,
87
+ input: {
88
+ file: entry.file,
89
+ name: entry.name
90
+ },
91
+ output: name
92
+ }
93
+ });
94
+ }
95
+ return ret;
96
+ }, this.inputs);
97
+ }
98
+ },
99
+ {
100
+ name: "shell-shock:virtual-inputs",
101
+ configResolved: {
102
+ order: "post",
103
+ async handler() {
104
+ if (this.inputs.length === 0) this.warn("No commands were found in the project. Please ensure at least one command exists.");
105
+ else {
106
+ this.info(`Shell Shock will create an application with the following commands: \n${this.inputs.filter((cmd) => !cmd.isVirtual).map((command) => ` - ${command.id}: ${(0, __stryke_path_replace.replacePath)(command.entry.file, this.commandsPath)}${command.isVirtual ? " (virtual)" : ""}`).join("\n")}`);
107
+ this.trace("Finding and adding virtual command inputs for each command previously found.");
108
+ this.inputs = this.inputs.reduce((ret, command) => {
109
+ let depth = 0;
110
+ let parentPath = (0, __stryke_path_resolve_parent_path.resolveParentPath)((0, __stryke_path_file_path_fns.findFilePath)(command.entry.file));
111
+ while (parentPath !== this.commandsPath) {
112
+ if (depth++ > MAX_DEPTH) throw new Error(`Maximum command virtual parent depth of ${MAX_DEPTH} exceeded while processing command: ${command.name}`);
113
+ if (!ret.some((existing) => (0, __stryke_path_file_path_fns.findFilePath)(existing.entry.file) === parentPath)) {
114
+ const file = (0, __stryke_path_join_paths.joinPaths)(parentPath, "command.ts");
115
+ const path = require_resolve_command.resolveCommandPath(this, file);
116
+ const id = path.replaceAll("/", "-");
117
+ if (!ret.some((existing) => existing.id === id)) {
118
+ const name = require_resolve_command.findCommandName(file);
119
+ ret.push({
120
+ id,
121
+ path: path.split("/").filter(Boolean),
122
+ name,
123
+ title: (0, __stryke_string_format_title_case.titleCase)(name),
124
+ isVirtual: true,
125
+ entry: {
126
+ file,
127
+ input: { file }
128
+ }
129
+ });
130
+ }
131
+ }
132
+ parentPath = (0, __stryke_path_resolve_parent_path.resolveParentPath)(parentPath);
133
+ }
134
+ return ret;
135
+ }, this.inputs).sort((a, b) => a.path.length - b.path.length);
136
+ this.trace(`Final command input list: \n${this.inputs.map((command) => ` - ${command.id}: ${(0, __stryke_path_replace.replacePath)(command.entry.file, this.commandsPath)}${command.isVirtual ? " (virtual)" : ""}`).join("\n")}`);
137
+ }
138
+ }
139
+ }
140
+ },
141
+ {
142
+ name: "shell-shock:reflect-commands",
143
+ async prepare() {
144
+ this.entry = [];
145
+ this.commands = {};
146
+ if (this.config.command !== "prepare" && this.config.skipCache !== true && this.persistedMeta?.checksum === this.meta.checksum && this.fs.existsSync(require_persistence.getCommandsPersistencePath(this))) {
147
+ this.debug(`Skipping reflection initialization as the meta checksum has not changed.`);
148
+ await require_persistence.readCommandsPersistence(this);
149
+ } else {
150
+ for (const input of this.inputs.filter((input$1) => input$1.path.length === 1)) this.commands[input.name] = await require_resolve_command.reflectCommandTree(this, input);
151
+ await require_persistence.writeCommandsPersistence(this);
152
+ }
153
+ }
154
+ },
155
+ {
156
+ name: "shell-shock:chmod+x",
157
+ async buildEnd() {
158
+ if (!(0, __stryke_type_checks_is_set_object.isSetObject)(this.packageJson.bin)) {
159
+ this.warn("No binaries were found in package.json. Please ensure the binaries are correctly configured.");
160
+ return;
161
+ }
162
+ this.debug("Adding executable permissions to binaries.");
163
+ for (const executablePath of Object.values(this.packageJson.bin)) if (this.fs.existsSync((0, __stryke_path_append.appendPath)(executablePath, this.config.output.buildPath))) await (0, __stryke_fs_chmod_x.chmodX)((0, __stryke_path_append.appendPath)(executablePath, this.config.output.buildPath));
164
+ }
165
+ }
166
+ ];
167
+ };
168
+ var powerlines_default = shellShock;
169
+
170
+ //#endregion
171
+ exports.default = powerlines_default;
172
+ exports.shellShock = shellShock;
@@ -1,3 +1,168 @@
1
- import{getDefaultOptions as e}from"./helpers/get-default-options.mjs";import{getCommandsPersistencePath as t,readCommandsPersistence as n,writeCommandsPersistence as r}from"./helpers/persistence.mjs";import{findCommandName as i,findCommandsRoot as a,reflectCommandTree as o,resolveCommandPath as s}from"./helpers/resolve-command.mjs";import{updatePackageJsonBinary as c}from"./helpers/update-package-json.mjs";import{getAppDescription as l,getAppName as u,getAppTitle as d}from"./helpers/utilities.mjs";import{chmodX as f}from"@stryke/fs/chmod-x";import{appendPath as p}from"@stryke/path/append";import{findFileName as m,findFilePath as h}from"@stryke/path/file-path-fns";import{isParentPath as g}from"@stryke/path/is-parent-path";import{joinPaths as _}from"@stryke/path/join-paths";import{replacePath as v}from"@stryke/path/replace";import{resolveParentPath as y}from"@stryke/path/resolve-parent-path";import{titleCase as b}from"@stryke/string-format/title-case";import{isSetObject as x}from"@stryke/type-checks/is-set-object";import{defu as S}from"defu";import{existsSync as C}from"node:fs";const w=(w={})=>[{name:`shell-shock:config`,async config(){return this.trace(`Resolving the Shell Shock configuration.`),S(w,{entry:!this.config.entry||Array.isArray(this.config.entry)&&this.config.entry.length===0?[_(this.config.sourceRoot,`**/*`)]:void 0,build:{target:`node22`,platform:`node`},interactive:!0,type:`application`,framework:`shell-shock`})},configResolved:{order:`pre`,async handler(){this.trace(`Shell Shock configuration has been resolved.`),await c(this),this.config.name=u(this),this.config.title=d(this),this.config.description=l(this),this.options=e(this,{id:null,name:this.config.name,title:this.config.title,description:this.config.description,path:[],isVirtual:!1}),this.inputs??=[]}}},{name:`shell-shock:inputs`,async configResolved(){this.trace(`Finding command entry points.`),this.commandsPath=a(this),this.inputs=this.entry.filter(e=>m(e.file,{withExtension:!1})===`command`).reduce((e,t)=>{let n=p(p(t.file,this.config.projectRoot),this.workspaceConfig.workspaceRoot);if(!g(n,this.commandsPath))throw Error(`Command entry point "${n}" is not located within the commands root "${this.commandsPath}". Please ensure that all command entry points are located within the current project.`);let r=s(this,n),a=r.replaceAll(`/`,`-`);if(!e.some(e=>e.id===a)){let o=i(n);e.push({id:a,path:r.split(`/`).filter(Boolean),name:o,title:b(o),isVirtual:!1,entry:{...t,file:n,input:{file:t.file,name:t.name},output:o}})}return e},this.inputs)}},{name:`shell-shock:virtual-inputs`,configResolved:{order:`post`,async handler(){this.inputs.length===0?this.warn(`No commands were found in the project. Please ensure at least one command exists.`):(this.info(`Shell Shock will create an application with the following commands: \n${this.inputs.filter(e=>!e.isVirtual).map(e=>` - ${e.id}: ${v(e.entry.file,this.commandsPath)}${e.isVirtual?` (virtual)`:``}`).join(`
2
- `)}`),this.trace(`Finding and adding virtual command inputs for each command previously found.`),this.inputs=this.inputs.reduce((e,t)=>{let n=0,r=y(h(t.entry.file));for(;r!==this.commandsPath;){if(n++>50)throw Error(`Maximum command virtual parent depth of 50 exceeded while processing command: ${t.name}`);if(!e.some(e=>h(e.entry.file)===r)){let t=_(r,`command.ts`),n=s(this,t),a=n.replaceAll(`/`,`-`);if(!e.some(e=>e.id===a)){let r=i(t);e.push({id:a,path:n.split(`/`).filter(Boolean),name:r,title:b(r),isVirtual:!0,entry:{file:t,input:{file:t}}})}}r=y(r)}return e},this.inputs).sort((e,t)=>e.path.length-t.path.length),this.trace(`Final command input list: \n${this.inputs.map(e=>` - ${e.id}: ${v(e.entry.file,this.commandsPath)}${e.isVirtual?` (virtual)`:``}`).join(`
3
- `)}`))}}},{name:`shell-shock:reflect-commands`,async prepare(){if(this.entry=[],this.commands={},this.config.command!==`prepare`&&this.persistedMeta?.checksum===this.meta.checksum&&this.fs.existsSync(t(this)))this.debug(`Skipping reflection initialization as the meta checksum has not changed.`),await n(this);else{for(let e of this.inputs.filter(e=>e.path.length===1))this.commands[e.name]=await o(this,e);await r(this)}}},{name:`shell-shock:chmod+x`,async buildEnd(){if(!x(this.packageJson.bin)){this.warn(`No binaries were found in package.json. Please ensure the binaries are correctly configured.`);return}this.debug(`Adding executable permissions to binaries.`);for(let e of Object.values(this.packageJson.bin))C(p(e,this.config.output.buildPath))&&await f(p(e,this.config.output.buildPath))}}];var T=w;export{T as default,w as shellShock};
1
+ import { getCommandsPersistencePath, readCommandsPersistence, writeCommandsPersistence } from "./helpers/persistence.mjs";
2
+ import { findCommandName, findCommandsRoot, reflectCommandTree, resolveCommandPath } from "./helpers/resolve-command.mjs";
3
+ import { updatePackageJsonBinary } from "./helpers/update-package-json.mjs";
4
+ import { getAppDescription, getAppName, getAppTitle } from "./helpers/utilities.mjs";
5
+ import tsdown from "@powerlines/plugin-tsdown";
6
+ import { chmodX } from "@stryke/fs/chmod-x";
7
+ import { getUniqueBy } from "@stryke/helpers/get-unique";
8
+ import { appendPath } from "@stryke/path/append";
9
+ import { findFileName, findFilePath } from "@stryke/path/file-path-fns";
10
+ import { isParentPath } from "@stryke/path/is-parent-path";
11
+ import { joinPaths } from "@stryke/path/join-paths";
12
+ import { replacePath } from "@stryke/path/replace";
13
+ import { resolveParentPath } from "@stryke/path/resolve-parent-path";
14
+ import { titleCase } from "@stryke/string-format/title-case";
15
+ import { isFunction } from "@stryke/type-checks/is-function";
16
+ import { isSetObject } from "@stryke/type-checks/is-set-object";
17
+ import { defu } from "defu";
18
+
19
+ //#region src/powerlines.ts
20
+ const MAX_DEPTH = 50;
21
+ /**
22
+ * The core Powerlines plugin to build Shell Shock projects.
23
+ */
24
+ const shellShock = (options = {}) => {
25
+ return [
26
+ tsdown(),
27
+ {
28
+ name: "shell-shock:config",
29
+ async config() {
30
+ this.trace("Resolving the Shell Shock configuration.");
31
+ return defu(options, {
32
+ entry: !this.config.entry || Array.isArray(this.config.entry) && this.config.entry.length === 0 ? [joinPaths(this.config.sourceRoot, "**/*")] : void 0,
33
+ build: {
34
+ target: "node22",
35
+ platform: "node"
36
+ },
37
+ type: "application",
38
+ framework: "shell-shock"
39
+ });
40
+ },
41
+ configResolved: {
42
+ order: "pre",
43
+ async handler() {
44
+ this.trace("Shell Shock configuration has been resolved.");
45
+ await updatePackageJsonBinary(this);
46
+ this.config.name = getAppName(this);
47
+ this.config.title = getAppTitle(this);
48
+ this.config.description = getAppDescription(this);
49
+ if (this.config.defaultOptions === false) this.options = [];
50
+ else if (Array.isArray(this.config.defaultOptions)) this.options = getUniqueBy(this.config.defaultOptions, (item) => item.name);
51
+ else if (isFunction(this.config.defaultOptions)) this.options = getUniqueBy(this.config.defaultOptions(this, {
52
+ id: null,
53
+ name: this.config.name,
54
+ title: this.config.title,
55
+ description: this.config.description,
56
+ path: [],
57
+ isVirtual: false
58
+ }), (item) => item.name);
59
+ this.inputs ??= [];
60
+ }
61
+ }
62
+ },
63
+ {
64
+ name: "shell-shock:inputs",
65
+ async configResolved() {
66
+ this.trace("Finding command entry points.");
67
+ this.commandsPath = findCommandsRoot(this);
68
+ this.inputs = this.entry.filter((entry) => findFileName(entry.file, { withExtension: false }) === "command").reduce((ret, entry) => {
69
+ const file = appendPath(appendPath(entry.file, this.config.projectRoot), this.workspaceConfig.workspaceRoot);
70
+ if (!isParentPath(file, this.commandsPath)) throw new Error(`Command entry point "${file}" is not located within the commands root "${this.commandsPath}". Please ensure that all command entry points are located within the current project.`);
71
+ const path = resolveCommandPath(this, file);
72
+ const id = path.replaceAll("/", "-");
73
+ if (!ret.some((existing) => existing.id === id)) {
74
+ const name = findCommandName(file);
75
+ ret.push({
76
+ id,
77
+ path: path.split("/").filter(Boolean),
78
+ name,
79
+ title: titleCase(name),
80
+ isVirtual: false,
81
+ entry: {
82
+ ...entry,
83
+ file,
84
+ input: {
85
+ file: entry.file,
86
+ name: entry.name
87
+ },
88
+ output: name
89
+ }
90
+ });
91
+ }
92
+ return ret;
93
+ }, this.inputs);
94
+ }
95
+ },
96
+ {
97
+ name: "shell-shock:virtual-inputs",
98
+ configResolved: {
99
+ order: "post",
100
+ async handler() {
101
+ if (this.inputs.length === 0) this.warn("No commands were found in the project. Please ensure at least one command exists.");
102
+ else {
103
+ this.info(`Shell Shock will create an application with the following commands: \n${this.inputs.filter((cmd) => !cmd.isVirtual).map((command) => ` - ${command.id}: ${replacePath(command.entry.file, this.commandsPath)}${command.isVirtual ? " (virtual)" : ""}`).join("\n")}`);
104
+ this.trace("Finding and adding virtual command inputs for each command previously found.");
105
+ this.inputs = this.inputs.reduce((ret, command) => {
106
+ let depth = 0;
107
+ let parentPath = resolveParentPath(findFilePath(command.entry.file));
108
+ while (parentPath !== this.commandsPath) {
109
+ if (depth++ > MAX_DEPTH) throw new Error(`Maximum command virtual parent depth of ${MAX_DEPTH} exceeded while processing command: ${command.name}`);
110
+ if (!ret.some((existing) => findFilePath(existing.entry.file) === parentPath)) {
111
+ const file = joinPaths(parentPath, "command.ts");
112
+ const path = resolveCommandPath(this, file);
113
+ const id = path.replaceAll("/", "-");
114
+ if (!ret.some((existing) => existing.id === id)) {
115
+ const name = findCommandName(file);
116
+ ret.push({
117
+ id,
118
+ path: path.split("/").filter(Boolean),
119
+ name,
120
+ title: titleCase(name),
121
+ isVirtual: true,
122
+ entry: {
123
+ file,
124
+ input: { file }
125
+ }
126
+ });
127
+ }
128
+ }
129
+ parentPath = resolveParentPath(parentPath);
130
+ }
131
+ return ret;
132
+ }, this.inputs).sort((a, b) => a.path.length - b.path.length);
133
+ this.trace(`Final command input list: \n${this.inputs.map((command) => ` - ${command.id}: ${replacePath(command.entry.file, this.commandsPath)}${command.isVirtual ? " (virtual)" : ""}`).join("\n")}`);
134
+ }
135
+ }
136
+ }
137
+ },
138
+ {
139
+ name: "shell-shock:reflect-commands",
140
+ async prepare() {
141
+ this.entry = [];
142
+ this.commands = {};
143
+ if (this.config.command !== "prepare" && this.config.skipCache !== true && this.persistedMeta?.checksum === this.meta.checksum && this.fs.existsSync(getCommandsPersistencePath(this))) {
144
+ this.debug(`Skipping reflection initialization as the meta checksum has not changed.`);
145
+ await readCommandsPersistence(this);
146
+ } else {
147
+ for (const input of this.inputs.filter((input$1) => input$1.path.length === 1)) this.commands[input.name] = await reflectCommandTree(this, input);
148
+ await writeCommandsPersistence(this);
149
+ }
150
+ }
151
+ },
152
+ {
153
+ name: "shell-shock:chmod+x",
154
+ async buildEnd() {
155
+ if (!isSetObject(this.packageJson.bin)) {
156
+ this.warn("No binaries were found in package.json. Please ensure the binaries are correctly configured.");
157
+ return;
158
+ }
159
+ this.debug("Adding executable permissions to binaries.");
160
+ for (const executablePath of Object.values(this.packageJson.bin)) if (this.fs.existsSync(appendPath(executablePath, this.config.output.buildPath))) await chmodX(appendPath(executablePath, this.config.output.buildPath));
161
+ }
162
+ }
163
+ ];
164
+ };
165
+ var powerlines_default = shellShock;
166
+
167
+ //#endregion
168
+ export { powerlines_default as default, shellShock };
@@ -1 +1 @@
1
- export{};
1
+ export { };
@@ -1,29 +1,14 @@
1
1
  import { CommandBase, CommandOption } from "./command.cjs";
2
2
  import { Context } from "./context.cjs";
3
+ import { NodeJsPluginOptions, NodeJsPluginResolvedConfig, NodeJsPluginUserConfig } from "@powerlines/plugin-nodejs/types/plugin";
3
4
  import { TsdownPluginResolvedConfig, TsdownPluginUserConfig } from "@powerlines/plugin-tsdown";
4
5
 
5
6
  //#region src/types/config.d.ts
6
- interface Options {
7
- /**
8
- * The default interactive mode to apply to commands.
9
- *
10
- * @remarks
11
- * The following modes are available:
12
- * - `true`: Enable interactivity when a TTY is detected and no explicit interactive flag is set (default).
13
- * - `false`: Disable interactivity unless an explicit interactive flag is set.
14
- * - `"never"`: Always disable interactivity, regardless of TTY presence or flags.
15
- *
16
- * @defaultValue `true`
17
- */
18
- interactive?: boolean | "never";
7
+ interface Options extends NodeJsPluginOptions {
19
8
  /**
20
9
  * A set of default command options to apply to each command.
21
10
  *
22
11
  * @remarks
23
- * By default, Shell Shock adds the following set of default arguments to each command:
24
- * - `--help` (`-h`, `-?`): Show help information.
25
- * - `--version` (`-v`): Show the version of the application.
26
- *
27
12
  * To disable the addition of these default options, set this property to `false`, or provide a custom set of options/a function that returns them.
28
13
  */
29
14
  defaultOptions?: CommandOption[] | ((context: Context, input: CommandBase) => CommandOption[]) | false;
@@ -32,8 +17,8 @@ interface Options {
32
17
  */
33
18
  bin?: string | string[];
34
19
  }
35
- type UserConfig = Partial<Omit<TsdownPluginUserConfig, "type" | "framework" | "singleBuild" | "environments">> & Options;
36
- type ResolvedConfig = TsdownPluginResolvedConfig & Required<Omit<Options, "bin"> & {
20
+ type UserConfig = Partial<Omit<TsdownPluginUserConfig, "type" | "framework" | "singleBuild" | "environments">> & Partial<NodeJsPluginUserConfig> & Omit<Options, "env">;
21
+ type ResolvedConfig = TsdownPluginResolvedConfig & NodeJsPluginResolvedConfig & Required<Omit<Options, "bin" | "env"> & {
37
22
  bin: string[];
38
23
  }>;
39
24
  //#endregion
@@ -1,29 +1,14 @@
1
1
  import { CommandBase, CommandOption } from "./command.mjs";
2
2
  import { Context } from "./context.mjs";
3
3
  import { TsdownPluginResolvedConfig, TsdownPluginUserConfig } from "@powerlines/plugin-tsdown";
4
+ import { NodeJsPluginOptions, NodeJsPluginResolvedConfig, NodeJsPluginUserConfig } from "@powerlines/plugin-nodejs/types/plugin";
4
5
 
5
6
  //#region src/types/config.d.ts
6
- interface Options {
7
- /**
8
- * The default interactive mode to apply to commands.
9
- *
10
- * @remarks
11
- * The following modes are available:
12
- * - `true`: Enable interactivity when a TTY is detected and no explicit interactive flag is set (default).
13
- * - `false`: Disable interactivity unless an explicit interactive flag is set.
14
- * - `"never"`: Always disable interactivity, regardless of TTY presence or flags.
15
- *
16
- * @defaultValue `true`
17
- */
18
- interactive?: boolean | "never";
7
+ interface Options extends NodeJsPluginOptions {
19
8
  /**
20
9
  * A set of default command options to apply to each command.
21
10
  *
22
11
  * @remarks
23
- * By default, Shell Shock adds the following set of default arguments to each command:
24
- * - `--help` (`-h`, `-?`): Show help information.
25
- * - `--version` (`-v`): Show the version of the application.
26
- *
27
12
  * To disable the addition of these default options, set this property to `false`, or provide a custom set of options/a function that returns them.
28
13
  */
29
14
  defaultOptions?: CommandOption[] | ((context: Context, input: CommandBase) => CommandOption[]) | false;
@@ -32,8 +17,8 @@ interface Options {
32
17
  */
33
18
  bin?: string | string[];
34
19
  }
35
- type UserConfig = Partial<Omit<TsdownPluginUserConfig, "type" | "framework" | "singleBuild" | "environments">> & Options;
36
- type ResolvedConfig = TsdownPluginResolvedConfig & Required<Omit<Options, "bin"> & {
20
+ type UserConfig = Partial<Omit<TsdownPluginUserConfig, "type" | "framework" | "singleBuild" | "environments">> & Partial<NodeJsPluginUserConfig> & Omit<Options, "env">;
21
+ type ResolvedConfig = TsdownPluginResolvedConfig & NodeJsPluginResolvedConfig & Required<Omit<Options, "bin" | "env"> & {
37
22
  bin: string[];
38
23
  }>;
39
24
  //#endregion
@@ -1 +1 @@
1
- export{};
1
+ export { };
@@ -1,9 +1,10 @@
1
1
  import { CommandInput, CommandOption, CommandTree } from "./command.cjs";
2
2
  import { ResolvedConfig } from "./config.cjs";
3
3
  import { TsdownPluginContext } from "@powerlines/plugin-tsdown";
4
+ import { EnvPluginContext } from "@powerlines/plugin-env/types/plugin";
4
5
 
5
6
  //#region src/types/context.d.ts
6
- type Context<TResolvedConfig extends ResolvedConfig = ResolvedConfig> = TsdownPluginContext<TResolvedConfig> & {
7
+ type Context<TResolvedConfig extends ResolvedConfig = ResolvedConfig> = TsdownPluginContext<TResolvedConfig> & EnvPluginContext<TResolvedConfig> & {
7
8
  /**
8
9
  * The root path where commands are located.
9
10
  */
@@ -1,9 +1,10 @@
1
1
  import { CommandInput, CommandOption, CommandTree } from "./command.mjs";
2
2
  import { ResolvedConfig } from "./config.mjs";
3
3
  import { TsdownPluginContext } from "@powerlines/plugin-tsdown";
4
+ import { EnvPluginContext } from "@powerlines/plugin-env/types/plugin";
4
5
 
5
6
  //#region src/types/context.d.ts
6
- type Context<TResolvedConfig extends ResolvedConfig = ResolvedConfig> = TsdownPluginContext<TResolvedConfig> & {
7
+ type Context<TResolvedConfig extends ResolvedConfig = ResolvedConfig> = TsdownPluginContext<TResolvedConfig> & EnvPluginContext<TResolvedConfig> & {
7
8
  /**
8
9
  * The root path where commands are located.
9
10
  */
@@ -1 +1 @@
1
- export{};
1
+ export { };
@@ -1 +1 @@
1
- export{};
1
+ export { };
@@ -1 +1 @@
1
- export{};
1
+ export { };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shell-shock/core",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "description": "A package containing the core Shell Shock functionality used to build and manage a command-line application.",
6
6
  "repository": {
@@ -131,26 +131,86 @@
131
131
  "types": "./dist/types/*.d.mts",
132
132
  "default": "./dist/types/*.mjs"
133
133
  }
134
+ },
135
+ "./plugin-utils": {
136
+ "import": {
137
+ "types": "./dist/plugin-utils/index.d.mts",
138
+ "default": "./dist/plugin-utils/index.mjs"
139
+ },
140
+ "require": {
141
+ "types": "./dist/plugin-utils/index.d.cts",
142
+ "default": "./dist/plugin-utils/index.cjs"
143
+ },
144
+ "default": {
145
+ "types": "./dist/plugin-utils/index.d.mts",
146
+ "default": "./dist/plugin-utils/index.mjs"
147
+ }
148
+ },
149
+ "./plugin-utils/*": {
150
+ "import": {
151
+ "types": "./dist/plugin-utils/*.d.mts",
152
+ "default": "./dist/plugin-utils/*.mjs"
153
+ },
154
+ "require": {
155
+ "types": "./dist/plugin-utils/*.d.cts",
156
+ "default": "./dist/plugin-utils/*.cjs"
157
+ },
158
+ "default": {
159
+ "types": "./dist/plugin-utils/*.d.mts",
160
+ "default": "./dist/plugin-utils/*.mjs"
161
+ }
162
+ },
163
+ "./components": {
164
+ "import": {
165
+ "types": "./dist/components/index.d.mts",
166
+ "default": "./dist/components/index.mjs"
167
+ },
168
+ "require": {
169
+ "types": "./dist/components/index.d.cts",
170
+ "default": "./dist/components/index.cjs"
171
+ },
172
+ "default": {
173
+ "types": "./dist/components/index.d.mts",
174
+ "default": "./dist/components/index.mjs"
175
+ }
176
+ },
177
+ "./components/*": {
178
+ "import": {
179
+ "types": "./dist/components/*.d.mts",
180
+ "default": "./dist/components/*.mjs"
181
+ },
182
+ "require": {
183
+ "types": "./dist/components/*.d.cts",
184
+ "default": "./dist/components/*.cjs"
185
+ },
186
+ "default": {
187
+ "types": "./dist/components/*.d.mts",
188
+ "default": "./dist/components/*.mjs"
189
+ }
134
190
  }
135
191
  },
136
192
  "files": ["dist/**/*"],
137
193
  "keywords": ["shell-shock", "powerlines", "storm-software"],
138
194
  "dependencies": {
139
- "@powerlines/deepkit": "^0.5.10",
140
- "@powerlines/plugin-plugin": "^0.12.47",
141
- "@powerlines/plugin-tsdown": "^0.1.47",
142
- "@stryke/convert": "^0.6.29",
143
- "@stryke/helpers": "^0.9.31",
144
- "@stryke/json": "^0.9.32",
145
- "@stryke/path": "^0.24.0",
146
- "@stryke/string-format": "^0.12.29",
147
- "@stryke/type-checks": "^0.5.14",
195
+ "@alloy-js/core": "^0.22.0",
196
+ "@alloy-js/typescript": "^0.22.0",
197
+ "@powerlines/deepkit": "^0.5.56",
198
+ "@powerlines/plugin-alloy": "^0.18.24",
199
+ "@powerlines/plugin-plugin": "^0.12.92",
200
+ "@powerlines/plugin-tsdown": "^0.1.93",
201
+ "@stryke/convert": "^0.6.30",
202
+ "@stryke/fs": "^0.33.27",
203
+ "@stryke/helpers": "^0.9.32",
204
+ "@stryke/json": "^0.9.33",
205
+ "@stryke/path": "^0.24.1",
206
+ "@stryke/string-format": "^0.12.30",
207
+ "@stryke/type-checks": "^0.5.15",
148
208
  "defu": "^6.1.4",
149
- "powerlines": "^0.36.0",
150
- "@stryke/capnp": "^0.12.51",
151
- "@stryke/fs": "^0.33.26"
209
+ "powerlines": "^0.37.14",
210
+ "@powerlines/plugin-env": "^0.15.27",
211
+ "@powerlines/plugin-nodejs": "^0.1.22"
152
212
  },
153
- "devDependencies": { "@types/node": "^24.10.4", "typescript": "^5.9.3" },
213
+ "devDependencies": { "@types/node": "^22.19.3", "typescript": "^5.9.3" },
154
214
  "publishConfig": { "access": "public" },
155
- "gitHead": "e7794a7d008c5d32b5a999b62421281d370166cd"
215
+ "gitHead": "5a8ce9d8f2cefeec8df5147bf80b5c3af71c6c16"
156
216
  }
@@ -1 +0,0 @@
1
- const e=require(`../_virtual/rolldown_runtime.cjs`);let t=require(`@powerlines/deepkit/vendor/type`),n=require(`@stryke/type-checks/is-function`);function r(e,r){return e.config.defaultOptions===!1?[]:Array.isArray(e.config.defaultOptions)?e.config.defaultOptions:(0,n.isFunction)(e.config.defaultOptions)?e.config.defaultOptions(e,r):[{name:`help`,title:`Help`,description:`Show help information.`,alias:[`h`,`?`],kind:t.ReflectionKind.boolean,optional:!0,default:!1,skipAddingNegative:!0},{name:`version`,title:`Version`,description:`Show the version of the application.`,alias:[`v`],kind:t.ReflectionKind.boolean,optional:!0,default:!1,skipAddingNegative:!0}]}exports.getDefaultOptions=r;
@@ -1,15 +0,0 @@
1
- import { CommandBase, CommandOption } from "../types/command.cjs";
2
- import { Context } from "../types/context.cjs";
3
-
4
- //#region src/helpers/get-default-options.d.ts
5
-
6
- /**
7
- * Get the default command options.
8
- *
9
- * @param context - The build context.
10
- * @param command - The command input.
11
- * @returns The default command options.
12
- */
13
- declare function getDefaultOptions(context: Context, command: CommandBase): CommandOption[];
14
- //#endregion
15
- export { getDefaultOptions };
@@ -1,15 +0,0 @@
1
- import { CommandBase, CommandOption } from "../types/command.mjs";
2
- import { Context } from "../types/context.mjs";
3
-
4
- //#region src/helpers/get-default-options.d.ts
5
-
6
- /**
7
- * Get the default command options.
8
- *
9
- * @param context - The build context.
10
- * @param command - The command input.
11
- * @returns The default command options.
12
- */
13
- declare function getDefaultOptions(context: Context, command: CommandBase): CommandOption[];
14
- //#endregion
15
- export { getDefaultOptions };
@@ -1 +0,0 @@
1
- import{ReflectionKind as e}from"@powerlines/deepkit/vendor/type";import{isFunction as t}from"@stryke/type-checks/is-function";function n(n,r){return n.config.defaultOptions===!1?[]:Array.isArray(n.config.defaultOptions)?n.config.defaultOptions:t(n.config.defaultOptions)?n.config.defaultOptions(n,r):[{name:`help`,title:`Help`,description:`Show help information.`,alias:[`h`,`?`],kind:e.boolean,optional:!0,default:!1,skipAddingNegative:!0},{name:`version`,title:`Version`,description:`Show the version of the application.`,alias:[`v`],kind:e.boolean,optional:!0,default:!1,skipAddingNegative:!0}]}export{n as getDefaultOptions};