@expressots/cli 3.0.0 → 4.0.0-preview.3
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.
- package/README.md +41 -95
- package/bin/cicd/cli.d.ts +6 -0
- package/bin/cicd/cli.js +128 -0
- package/bin/cicd/form.d.ts +29 -0
- package/bin/cicd/form.js +346 -0
- package/bin/cicd/generators/azure-devops.d.ts +2 -0
- package/bin/cicd/generators/azure-devops.js +370 -0
- package/bin/cicd/generators/bitbucket.d.ts +2 -0
- package/bin/cicd/generators/bitbucket.js +217 -0
- package/bin/cicd/generators/circleci.d.ts +2 -0
- package/bin/cicd/generators/circleci.js +274 -0
- package/bin/cicd/generators/github-actions.d.ts +14 -0
- package/bin/cicd/generators/github-actions.js +426 -0
- package/bin/cicd/generators/gitlab-ci.d.ts +2 -0
- package/bin/cicd/generators/gitlab-ci.js +237 -0
- package/bin/cicd/generators/index.d.ts +6 -0
- package/bin/cicd/generators/index.js +15 -0
- package/bin/cicd/generators/jenkins.d.ts +2 -0
- package/bin/cicd/generators/jenkins.js +248 -0
- package/bin/cicd/generators/template-loader.d.ts +17 -0
- package/bin/cicd/generators/template-loader.js +128 -0
- package/bin/cicd/index.d.ts +1 -0
- package/bin/cicd/index.js +5 -0
- package/bin/cli.d.ts +1 -5
- package/bin/cli.js +72 -7
- package/bin/commands/project.commands.d.ts +19 -6
- package/bin/commands/project.commands.js +602 -66
- package/bin/config/index.d.ts +5 -0
- package/bin/config/index.js +10 -0
- package/bin/config/manager.d.ts +98 -0
- package/bin/config/manager.js +222 -0
- package/bin/containerize/analyzers/bootstrap-analyzer.d.ts +46 -0
- package/bin/containerize/analyzers/bootstrap-analyzer.js +187 -0
- package/bin/containerize/analyzers/project-analyzer.d.ts +20 -0
- package/bin/containerize/analyzers/project-analyzer.js +150 -0
- package/bin/containerize/cli.d.ts +4 -0
- package/bin/containerize/cli.js +113 -0
- package/bin/containerize/form.d.ts +15 -0
- package/bin/containerize/form.js +152 -0
- package/bin/containerize/generators/ci-generator.d.ts +31 -0
- package/bin/containerize/generators/ci-generator.js +940 -0
- package/bin/containerize/generators/docker-compose-generator.d.ts +8 -0
- package/bin/containerize/generators/docker-compose-generator.js +187 -0
- package/bin/containerize/generators/dockerfile-generator.d.ts +8 -0
- package/bin/containerize/generators/dockerfile-generator.js +657 -0
- package/bin/containerize/generators/kubernetes-generator.d.ts +8 -0
- package/bin/containerize/generators/kubernetes-generator.js +134 -0
- package/bin/containerize/generators/template-loader.d.ts +36 -0
- package/bin/containerize/generators/template-loader.js +129 -0
- package/bin/containerize/index.d.ts +4 -0
- package/bin/containerize/index.js +13 -0
- package/bin/containerize/presets/preset-registry.d.ts +20 -0
- package/bin/containerize/presets/preset-registry.js +102 -0
- package/bin/costs/cli.d.ts +5 -0
- package/bin/costs/cli.js +185 -0
- package/bin/costs/form.d.ts +44 -0
- package/bin/costs/form.js +412 -0
- package/bin/costs/index.d.ts +4 -0
- package/bin/costs/index.js +25 -0
- package/bin/costs/pricing-manager.d.ts +84 -0
- package/bin/costs/pricing-manager.js +342 -0
- package/bin/costs/providers/index.d.ts +32 -0
- package/bin/costs/providers/index.js +153 -0
- package/bin/costs/sources/api-source.d.ts +10 -0
- package/bin/costs/sources/api-source.js +32 -0
- package/bin/costs/sources/index.d.ts +6 -0
- package/bin/costs/sources/index.js +15 -0
- package/bin/costs/sources/local-json-source.d.ts +23 -0
- package/bin/costs/sources/local-json-source.js +59 -0
- package/bin/costs/sources/remote-json-source.d.ts +11 -0
- package/bin/costs/sources/remote-json-source.js +53 -0
- package/bin/costs/types.d.ts +53 -0
- package/bin/costs/types.js +5 -0
- package/bin/dev/cli.d.ts +4 -0
- package/bin/dev/cli.js +136 -0
- package/bin/dev/form.d.ts +36 -0
- package/bin/dev/form.js +254 -0
- package/bin/dev/index.d.ts +1 -0
- package/bin/dev/index.js +5 -0
- package/bin/generate/cli.d.ts +1 -1
- package/bin/generate/cli.js +29 -2
- package/bin/generate/form.d.ts +5 -1
- package/bin/generate/form.js +3 -3
- package/bin/generate/templates/nonopinionated/config.tpl +12 -0
- package/bin/generate/templates/nonopinionated/event.tpl +10 -0
- package/bin/generate/templates/nonopinionated/guard.tpl +18 -0
- package/bin/generate/templates/nonopinionated/handler.tpl +12 -0
- package/bin/generate/templates/nonopinionated/interceptor.tpl +27 -0
- package/bin/generate/templates/opinionated/config.tpl +47 -0
- package/bin/generate/templates/opinionated/entity.tpl +1 -8
- package/bin/generate/templates/opinionated/event.tpl +15 -0
- package/bin/generate/templates/opinionated/guard.tpl +41 -0
- package/bin/generate/templates/opinionated/handler.tpl +23 -0
- package/bin/generate/templates/opinionated/interceptor.tpl +50 -0
- package/bin/generate/utils/command-utils.d.ts +20 -5
- package/bin/generate/utils/command-utils.js +145 -48
- package/bin/generate/utils/nonopininated-cmd.d.ts +10 -1
- package/bin/generate/utils/nonopininated-cmd.js +100 -1
- package/bin/generate/utils/opinionated-cmd.d.ts +10 -1
- package/bin/generate/utils/opinionated-cmd.js +128 -16
- package/bin/generate/utils/string-utils.d.ts +6 -0
- package/bin/generate/utils/string-utils.js +13 -1
- package/bin/help/cli.d.ts +1 -1
- package/bin/help/command-help-registry.d.ts +23 -0
- package/bin/help/command-help-registry.js +303 -0
- package/bin/help/command-help.d.ts +36 -0
- package/bin/help/command-help.js +56 -0
- package/bin/help/form.js +127 -22
- package/bin/help/main-help.d.ts +8 -0
- package/bin/help/main-help.js +126 -0
- package/bin/help/render.d.ts +32 -0
- package/bin/help/render.js +46 -0
- package/bin/info/cli.d.ts +1 -1
- package/bin/info/form.d.ts +1 -1
- package/bin/info/form.js +11 -11
- package/bin/migrate/analyzers/platform-detector.d.ts +14 -0
- package/bin/migrate/analyzers/platform-detector.js +116 -0
- package/bin/migrate/cli.d.ts +6 -0
- package/bin/migrate/cli.js +98 -0
- package/bin/migrate/form.d.ts +25 -0
- package/bin/migrate/form.js +348 -0
- package/bin/migrate/generators/compose-to-k8s.d.ts +2 -0
- package/bin/migrate/generators/compose-to-k8s.js +324 -0
- package/bin/migrate/generators/compose-to-railway.d.ts +2 -0
- package/bin/migrate/generators/compose-to-railway.js +138 -0
- package/bin/migrate/generators/compose-to-render.d.ts +2 -0
- package/bin/migrate/generators/compose-to-render.js +148 -0
- package/bin/migrate/generators/generic-migration.d.ts +9 -0
- package/bin/migrate/generators/generic-migration.js +221 -0
- package/bin/migrate/generators/heroku-to-fly.d.ts +2 -0
- package/bin/migrate/generators/heroku-to-fly.js +291 -0
- package/bin/migrate/generators/heroku-to-railway.d.ts +2 -0
- package/bin/migrate/generators/heroku-to-railway.js +283 -0
- package/bin/migrate/generators/heroku-to-render.d.ts +2 -0
- package/bin/migrate/generators/heroku-to-render.js +148 -0
- package/bin/migrate/generators/index.d.ts +7 -0
- package/bin/migrate/generators/index.js +17 -0
- package/bin/migrate/generators/template-loader.d.ts +21 -0
- package/bin/migrate/generators/template-loader.js +59 -0
- package/bin/migrate/index.d.ts +1 -0
- package/bin/migrate/index.js +5 -0
- package/bin/new/cli.d.ts +5 -1
- package/bin/new/cli.js +77 -14
- package/bin/new/form.d.ts +27 -4
- package/bin/new/form.js +605 -75
- package/bin/profile/analyzers/dockerfile-analyzer.d.ts +27 -0
- package/bin/profile/analyzers/dockerfile-analyzer.js +122 -0
- package/bin/profile/analyzers/image-analyzer.d.ts +19 -0
- package/bin/profile/analyzers/image-analyzer.js +85 -0
- package/bin/profile/cli.d.ts +4 -0
- package/bin/profile/cli.js +94 -0
- package/bin/profile/form.d.ts +56 -0
- package/bin/profile/form.js +401 -0
- package/bin/profile/index.d.ts +1 -0
- package/bin/profile/index.js +5 -0
- package/bin/profile/optimizers/index.d.ts +19 -0
- package/bin/profile/optimizers/index.js +137 -0
- package/bin/providers/add/form.d.ts +1 -1
- package/bin/providers/add/form.js +27 -6
- package/bin/providers/create/form.js +53 -3
- package/bin/scripts/form.js +27 -5
- package/bin/studio/cli.d.ts +15 -0
- package/bin/studio/cli.js +172 -0
- package/bin/studio/index.d.ts +5 -0
- package/bin/studio/index.js +9 -0
- package/bin/templates/cache.d.ts +54 -0
- package/bin/templates/cache.js +180 -0
- package/bin/templates/cli.d.ts +8 -0
- package/bin/templates/cli.js +294 -0
- package/bin/templates/fetcher.d.ts +49 -0
- package/bin/templates/fetcher.js +208 -0
- package/bin/templates/index.d.ts +11 -0
- package/bin/templates/index.js +37 -0
- package/bin/templates/manager.d.ts +116 -0
- package/bin/templates/manager.js +323 -0
- package/bin/templates/renderer.d.ts +49 -0
- package/bin/templates/renderer.js +204 -0
- package/bin/templates/types.d.ts +51 -0
- package/bin/templates/types.js +5 -0
- package/bin/utils/add-module-to-container.d.ts +14 -3
- package/bin/utils/add-module-to-container.js +327 -98
- package/bin/utils/cli-ui.d.ts +49 -3
- package/bin/utils/cli-ui.js +133 -13
- package/bin/utils/index.d.ts +4 -0
- package/bin/utils/index.js +4 -0
- package/bin/utils/input-validation.d.ts +50 -0
- package/bin/utils/input-validation.js +143 -0
- package/bin/utils/package-manager-commands.d.ts +24 -0
- package/bin/utils/package-manager-commands.js +50 -0
- package/bin/utils/safe-spawn.d.ts +35 -0
- package/bin/utils/safe-spawn.js +51 -0
- package/bin/utils/update-tsconfig-paths.d.ts +35 -0
- package/bin/utils/update-tsconfig-paths.js +326 -0
- package/package.json +165 -156
package/bin/utils/cli-ui.js
CHANGED
|
@@ -3,30 +3,150 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.printGenerateSuccess = exports.printGenerateError = exports.printWarning = exports.printSuccess = exports.printError = void 0;
|
|
6
|
+
exports.printHeader = exports.printKeyValue = exports.printDivider = exports.printBullet = exports.printSection = exports.printGenerateSuccess = exports.printGenerateError = exports.printDebug = exports.printInfo = exports.printWarning = exports.printSuccess = exports.printError = void 0;
|
|
7
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
8
|
const process_1 = require("process");
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Format timestamp for display (matches core logger format)
|
|
11
|
+
*/
|
|
12
|
+
function formatTimestamp() {
|
|
13
|
+
const date = new Date();
|
|
14
|
+
const options = {
|
|
15
|
+
year: "numeric",
|
|
16
|
+
month: "2-digit",
|
|
17
|
+
day: "2-digit",
|
|
18
|
+
hour: "2-digit",
|
|
19
|
+
minute: "2-digit",
|
|
20
|
+
second: "2-digit",
|
|
21
|
+
};
|
|
22
|
+
return date.toLocaleString(undefined, options).replace(",", "");
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Color a string based on log level
|
|
26
|
+
*/
|
|
27
|
+
function colorByLevel(level, text) {
|
|
28
|
+
switch (level) {
|
|
29
|
+
case "INFO":
|
|
30
|
+
return chalk_1.default.green(text);
|
|
31
|
+
case "WARN":
|
|
32
|
+
return chalk_1.default.yellow(text);
|
|
33
|
+
case "ERROR":
|
|
34
|
+
return chalk_1.default.red(text);
|
|
35
|
+
case "DEBUG":
|
|
36
|
+
return chalk_1.default.blue(text);
|
|
37
|
+
default:
|
|
38
|
+
return chalk_1.default.white(text);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Core log function matching ExpressoTS core logger format
|
|
43
|
+
* Format: [ExpressoTS] timestamp LEVEL [context] message
|
|
44
|
+
*/
|
|
45
|
+
function log(level, context, message, icon) {
|
|
46
|
+
const timestamp = formatTimestamp();
|
|
47
|
+
const levelStr = colorByLevel(level, level.padEnd(5, " "));
|
|
48
|
+
const contextStr = chalk_1.default.green(`[${context}]`);
|
|
49
|
+
const messageStr = colorByLevel(level, message);
|
|
50
|
+
const iconStr = icon ? ` ${icon}` : "";
|
|
51
|
+
const output = `${chalk_1.default.green("[ExpressoTS]")} ${timestamp} ${levelStr} ${contextStr} ${messageStr}${iconStr}\n`;
|
|
52
|
+
if (level === "ERROR") {
|
|
53
|
+
process.stderr.write(output);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
process_1.stdout.write(output);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Print error message (matches core logger ERROR format)
|
|
61
|
+
*/
|
|
62
|
+
function printError(message, context) {
|
|
63
|
+
log("ERROR", context, message, "❌");
|
|
11
64
|
}
|
|
12
65
|
exports.printError = printError;
|
|
13
|
-
|
|
14
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Print success message (matches core logger INFO format)
|
|
68
|
+
*/
|
|
69
|
+
function printSuccess(message, context) {
|
|
70
|
+
log("INFO", context, message, "✔️");
|
|
15
71
|
}
|
|
16
72
|
exports.printSuccess = printSuccess;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
process_1.stdout.write(chalk_1.default.yellow(`${message}:`, chalk_1.default.bold(chalk_1.default.white(`[${component}] ⚠️\n`))));
|
|
73
|
+
/**
|
|
74
|
+
* Print warning message (matches core logger WARN format)
|
|
75
|
+
*/
|
|
76
|
+
function printWarning(message, context) {
|
|
77
|
+
log("WARN", context || "cli", message, "⚠️");
|
|
23
78
|
}
|
|
24
79
|
exports.printWarning = printWarning;
|
|
80
|
+
/**
|
|
81
|
+
* Print info message (matches core logger INFO format)
|
|
82
|
+
*/
|
|
83
|
+
function printInfo(message, context) {
|
|
84
|
+
log("INFO", context, message);
|
|
85
|
+
}
|
|
86
|
+
exports.printInfo = printInfo;
|
|
87
|
+
/**
|
|
88
|
+
* Print debug message (matches core logger DEBUG format)
|
|
89
|
+
*/
|
|
90
|
+
function printDebug(message, context) {
|
|
91
|
+
log("DEBUG", context, message);
|
|
92
|
+
}
|
|
93
|
+
exports.printDebug = printDebug;
|
|
94
|
+
/**
|
|
95
|
+
* Print generate error (simplified format for scaffolding)
|
|
96
|
+
*/
|
|
25
97
|
async function printGenerateError(schematic, file) {
|
|
26
|
-
|
|
98
|
+
log("ERROR", schematic, `${file.split(".")[0]} not created!`, "❌");
|
|
27
99
|
}
|
|
28
100
|
exports.printGenerateError = printGenerateError;
|
|
101
|
+
/**
|
|
102
|
+
* Print generate success (simplified format for scaffolding)
|
|
103
|
+
*/
|
|
29
104
|
async function printGenerateSuccess(schematic, file) {
|
|
30
|
-
|
|
105
|
+
log("INFO", schematic, `${file.split(".")[0]} created!`, "✔️");
|
|
31
106
|
}
|
|
32
107
|
exports.printGenerateSuccess = printGenerateSuccess;
|
|
108
|
+
/**
|
|
109
|
+
* Print a section title. Intended for interactive/listing output (e.g.
|
|
110
|
+
* `templates list`, `costs compare`) where the structured logger format
|
|
111
|
+
* (`[ExpressoTS] timestamp LEVEL`) would be noisy. Leading newline keeps
|
|
112
|
+
* sections visually separated.
|
|
113
|
+
*/
|
|
114
|
+
function printSection(title) {
|
|
115
|
+
process_1.stdout.write(`\n${chalk_1.default.bold.cyan(title)}\n`);
|
|
116
|
+
}
|
|
117
|
+
exports.printSection = printSection;
|
|
118
|
+
/**
|
|
119
|
+
* Print an indented bullet point under a section.
|
|
120
|
+
*/
|
|
121
|
+
function printBullet(text) {
|
|
122
|
+
process_1.stdout.write(` ${chalk_1.default.gray("-")} ${text}\n`);
|
|
123
|
+
}
|
|
124
|
+
exports.printBullet = printBullet;
|
|
125
|
+
/**
|
|
126
|
+
* Print a dim horizontal divider sized to the terminal width (capped).
|
|
127
|
+
*/
|
|
128
|
+
function printDivider() {
|
|
129
|
+
const cols = typeof process.stdout.columns === "number" && process.stdout.columns > 0
|
|
130
|
+
? process.stdout.columns
|
|
131
|
+
: 80;
|
|
132
|
+
const width = Math.min(Math.max(cols, 20), 80);
|
|
133
|
+
process_1.stdout.write(`${chalk_1.default.dim("\u2500".repeat(width))}\n`);
|
|
134
|
+
}
|
|
135
|
+
exports.printDivider = printDivider;
|
|
136
|
+
/**
|
|
137
|
+
* Print an aligned key/value pair (e.g. `Source: remote`).
|
|
138
|
+
*/
|
|
139
|
+
function printKeyValue(key, value, padding = 12) {
|
|
140
|
+
process_1.stdout.write(` ${chalk_1.default.bold(`${key}:`.padEnd(padding))} ${value}\n`);
|
|
141
|
+
}
|
|
142
|
+
exports.printKeyValue = printKeyValue;
|
|
143
|
+
/**
|
|
144
|
+
* Print the ExpressoTS CLI header
|
|
145
|
+
*/
|
|
146
|
+
function printHeader(version) {
|
|
147
|
+
const title = version
|
|
148
|
+
? `🐎 ExpressoTS CLI v${version}`
|
|
149
|
+
: "🐎 ExpressoTS CLI";
|
|
150
|
+
process_1.stdout.write(`\n${chalk_1.default.bold.green(title)}\n\n`);
|
|
151
|
+
}
|
|
152
|
+
exports.printHeader = printHeader;
|
package/bin/utils/index.d.ts
CHANGED
package/bin/utils/index.js
CHANGED
|
@@ -15,3 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./compiler"), exports);
|
|
18
|
+
__exportStar(require("./input-validation"), exports);
|
|
19
|
+
__exportStar(require("./package-manager-commands"), exports);
|
|
20
|
+
__exportStar(require("./safe-spawn"), exports);
|
|
21
|
+
__exportStar(require("./update-tsconfig-paths"), exports);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input validation utilities used across the CLI to defend against
|
|
3
|
+
* command injection and path traversal when user-supplied values flow
|
|
4
|
+
* into child_process spawn/exec calls or filesystem writes.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Guard against shell metacharacters in any value that will be
|
|
8
|
+
* interpolated into a shell-evaluated command line.
|
|
9
|
+
*/
|
|
10
|
+
export declare function containsShellMetachars(value: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Validate an npm package name (with optional scope).
|
|
13
|
+
*/
|
|
14
|
+
export declare function isValidPackageName(name: unknown): name is string;
|
|
15
|
+
/**
|
|
16
|
+
* Validate a version specifier passed to a package manager. Accepts
|
|
17
|
+
* `latest`, `next`, exact versions and common range syntaxes
|
|
18
|
+
* (`>=1.2.3 <2.0.0`, `*`, `1.x`). Returns false for the boolean
|
|
19
|
+
* fallback yargs sometimes assigns when the flag is absent.
|
|
20
|
+
*
|
|
21
|
+
* Versions are forwarded via argv (`shell: false`), so we whitelist
|
|
22
|
+
* the characters npm itself accepts in semver ranges and reject the
|
|
23
|
+
* rest. We do NOT layer the broader `containsShellMetachars` check
|
|
24
|
+
* here because legitimate ranges include `<`, `>`, `|`, and `*`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function isValidVersion(version: unknown): version is string;
|
|
27
|
+
/**
|
|
28
|
+
* Validate an npm/yarn/pnpm script name.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isValidScriptName(name: unknown): name is string;
|
|
31
|
+
export declare function isValidPackageManager(pm: unknown): pm is "npm" | "yarn" | "pnpm" | "bun";
|
|
32
|
+
/**
|
|
33
|
+
* Resolve `target` against `base` and verify the result is contained
|
|
34
|
+
* within `base`. Returns the resolved absolute path on success, or
|
|
35
|
+
* `null` when the resolved path escapes the base directory (path
|
|
36
|
+
* traversal attempt).
|
|
37
|
+
*/
|
|
38
|
+
export declare function safeResolveWithin(base: string, target: string): string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Throws a generic `Error` if the value is not a safe package name.
|
|
41
|
+
*/
|
|
42
|
+
export declare function assertValidPackageName(name: unknown): asserts name is string;
|
|
43
|
+
/**
|
|
44
|
+
* Throws a generic `Error` if the value is not a safe version range.
|
|
45
|
+
*/
|
|
46
|
+
export declare function assertValidVersion(version: unknown): asserts version is string;
|
|
47
|
+
/**
|
|
48
|
+
* Throws a generic `Error` if the value is not a safe script name.
|
|
49
|
+
*/
|
|
50
|
+
export declare function assertValidScriptName(name: unknown): asserts name is string;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Input validation utilities used across the CLI to defend against
|
|
4
|
+
* command injection and path traversal when user-supplied values flow
|
|
5
|
+
* into child_process spawn/exec calls or filesystem writes.
|
|
6
|
+
*/
|
|
7
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.assertValidScriptName = exports.assertValidVersion = exports.assertValidPackageName = exports.safeResolveWithin = exports.isValidPackageManager = exports.isValidScriptName = exports.isValidVersion = exports.isValidPackageName = exports.containsShellMetachars = void 0;
|
|
12
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
13
|
+
/**
|
|
14
|
+
* Characters that have shell-special meaning across POSIX shells and
|
|
15
|
+
* Windows cmd. If any appear in a value that will be interpolated into
|
|
16
|
+
* a shell-evaluated command (`shell: true` or `execSync(string)`), the
|
|
17
|
+
* value must be rejected.
|
|
18
|
+
*/
|
|
19
|
+
const SHELL_METACHARACTERS = /[;&|`$()<>\n\r\\"'*?{}[\]!#~]/;
|
|
20
|
+
/**
|
|
21
|
+
* Conservative regex for npm package names. Allows scoped packages,
|
|
22
|
+
* dotted segments and dashes, mirroring https://docs.npmjs.com/cli/v10/configuring-npm/package-json#name
|
|
23
|
+
* but stricter than npm itself to remove ambiguity (no leading dots,
|
|
24
|
+
* no uppercase to keep it portable across registries).
|
|
25
|
+
*/
|
|
26
|
+
const PACKAGE_NAME_RE = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
|
|
27
|
+
/**
|
|
28
|
+
* Semver-ish range validator. Accepts the common syntactic shapes
|
|
29
|
+
* (e.g. 1.2.3, ^1.2, ~1, 1.x, latest, next, >=1.2.3 <2.0.0) without
|
|
30
|
+
* pulling in the full semver parser for this guard.
|
|
31
|
+
*/
|
|
32
|
+
const VERSION_RE = /^[A-Za-z0-9.\-+~^>=<* |]+$/;
|
|
33
|
+
/**
|
|
34
|
+
* Script name validator for npm/yarn/pnpm `run` targets. Matches what
|
|
35
|
+
* those package managers actually accept (alphanumerics plus
|
|
36
|
+
* `:_-./`), explicitly rejecting whitespace and shell metacharacters.
|
|
37
|
+
*/
|
|
38
|
+
const SCRIPT_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9:_./-]*$/;
|
|
39
|
+
/**
|
|
40
|
+
* Guard against shell metacharacters in any value that will be
|
|
41
|
+
* interpolated into a shell-evaluated command line.
|
|
42
|
+
*/
|
|
43
|
+
function containsShellMetachars(value) {
|
|
44
|
+
return SHELL_METACHARACTERS.test(value);
|
|
45
|
+
}
|
|
46
|
+
exports.containsShellMetachars = containsShellMetachars;
|
|
47
|
+
/**
|
|
48
|
+
* Validate an npm package name (with optional scope).
|
|
49
|
+
*/
|
|
50
|
+
function isValidPackageName(name) {
|
|
51
|
+
if (typeof name !== "string" || name.length === 0 || name.length > 214) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
if (containsShellMetachars(name))
|
|
55
|
+
return false;
|
|
56
|
+
return PACKAGE_NAME_RE.test(name);
|
|
57
|
+
}
|
|
58
|
+
exports.isValidPackageName = isValidPackageName;
|
|
59
|
+
/**
|
|
60
|
+
* Validate a version specifier passed to a package manager. Accepts
|
|
61
|
+
* `latest`, `next`, exact versions and common range syntaxes
|
|
62
|
+
* (`>=1.2.3 <2.0.0`, `*`, `1.x`). Returns false for the boolean
|
|
63
|
+
* fallback yargs sometimes assigns when the flag is absent.
|
|
64
|
+
*
|
|
65
|
+
* Versions are forwarded via argv (`shell: false`), so we whitelist
|
|
66
|
+
* the characters npm itself accepts in semver ranges and reject the
|
|
67
|
+
* rest. We do NOT layer the broader `containsShellMetachars` check
|
|
68
|
+
* here because legitimate ranges include `<`, `>`, `|`, and `*`.
|
|
69
|
+
*/
|
|
70
|
+
function isValidVersion(version) {
|
|
71
|
+
if (typeof version !== "string" || version.length === 0)
|
|
72
|
+
return false;
|
|
73
|
+
if (version.length > 64)
|
|
74
|
+
return false;
|
|
75
|
+
return VERSION_RE.test(version);
|
|
76
|
+
}
|
|
77
|
+
exports.isValidVersion = isValidVersion;
|
|
78
|
+
/**
|
|
79
|
+
* Validate an npm/yarn/pnpm script name.
|
|
80
|
+
*/
|
|
81
|
+
function isValidScriptName(name) {
|
|
82
|
+
if (typeof name !== "string" || name.length === 0 || name.length > 214) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
if (containsShellMetachars(name))
|
|
86
|
+
return false;
|
|
87
|
+
return SCRIPT_NAME_RE.test(name);
|
|
88
|
+
}
|
|
89
|
+
exports.isValidScriptName = isValidScriptName;
|
|
90
|
+
/**
|
|
91
|
+
* Validate a package manager identifier.
|
|
92
|
+
*/
|
|
93
|
+
const ALLOWED_PACKAGE_MANAGERS = new Set(["npm", "yarn", "pnpm", "bun"]);
|
|
94
|
+
function isValidPackageManager(pm) {
|
|
95
|
+
return typeof pm === "string" && ALLOWED_PACKAGE_MANAGERS.has(pm);
|
|
96
|
+
}
|
|
97
|
+
exports.isValidPackageManager = isValidPackageManager;
|
|
98
|
+
/**
|
|
99
|
+
* Resolve `target` against `base` and verify the result is contained
|
|
100
|
+
* within `base`. Returns the resolved absolute path on success, or
|
|
101
|
+
* `null` when the resolved path escapes the base directory (path
|
|
102
|
+
* traversal attempt).
|
|
103
|
+
*/
|
|
104
|
+
function safeResolveWithin(base, target) {
|
|
105
|
+
const absoluteBase = node_path_1.default.resolve(base);
|
|
106
|
+
const absoluteTarget = node_path_1.default.resolve(absoluteBase, target);
|
|
107
|
+
const baseWithSep = absoluteBase.endsWith(node_path_1.default.sep)
|
|
108
|
+
? absoluteBase
|
|
109
|
+
: absoluteBase + node_path_1.default.sep;
|
|
110
|
+
if (absoluteTarget !== absoluteBase &&
|
|
111
|
+
!absoluteTarget.startsWith(baseWithSep)) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
return absoluteTarget;
|
|
115
|
+
}
|
|
116
|
+
exports.safeResolveWithin = safeResolveWithin;
|
|
117
|
+
/**
|
|
118
|
+
* Throws a generic `Error` if the value is not a safe package name.
|
|
119
|
+
*/
|
|
120
|
+
function assertValidPackageName(name) {
|
|
121
|
+
if (!isValidPackageName(name)) {
|
|
122
|
+
throw new Error(`Invalid package name: ${JSON.stringify(name)}. Names must match npm package name rules and contain no shell metacharacters.`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.assertValidPackageName = assertValidPackageName;
|
|
126
|
+
/**
|
|
127
|
+
* Throws a generic `Error` if the value is not a safe version range.
|
|
128
|
+
*/
|
|
129
|
+
function assertValidVersion(version) {
|
|
130
|
+
if (!isValidVersion(version)) {
|
|
131
|
+
throw new Error(`Invalid version specifier: ${JSON.stringify(version)}.`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
exports.assertValidVersion = assertValidVersion;
|
|
135
|
+
/**
|
|
136
|
+
* Throws a generic `Error` if the value is not a safe script name.
|
|
137
|
+
*/
|
|
138
|
+
function assertValidScriptName(name) {
|
|
139
|
+
if (!isValidScriptName(name)) {
|
|
140
|
+
throw new Error(`Invalid script name: ${JSON.stringify(name)}. Script names must match ^[a-zA-Z0-9][a-zA-Z0-9:_./-]*$.`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.assertValidScriptName = assertValidScriptName;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared package-manager command helpers for code generators
|
|
3
|
+
* (Dockerfiles, CI/CD pipelines). These centralize the mapping
|
|
4
|
+
* between an analyzer-detected package manager and the literal
|
|
5
|
+
* shell strings emitted into generated files.
|
|
6
|
+
*
|
|
7
|
+
* Two flavors exist:
|
|
8
|
+
* - `RUN`/`CMD`-style strings used INSIDE Dockerfiles.
|
|
9
|
+
* - Plain shell invocations used in CI scripts and informational
|
|
10
|
+
* comments (no `RUN ` prefix).
|
|
11
|
+
*/
|
|
12
|
+
export type SupportedPackageManager = "npm" | "yarn" | "pnpm" | "bun";
|
|
13
|
+
/**
|
|
14
|
+
* Shell invocation that installs project dependencies, suitable for
|
|
15
|
+
* a CI step (no `RUN ` prefix). Uses the strict, lockfile-respecting
|
|
16
|
+
* variant for each package manager because CI runs should be
|
|
17
|
+
* reproducible.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getCiInstallCommand(packageManager: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Shell invocation that runs an npm-style script (e.g. `lint`,
|
|
22
|
+
* `test`, `build`). Used in CI scripts and informational comments.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getRunScriptCommand(packageManager: string, scriptName: string): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared package-manager command helpers for code generators
|
|
4
|
+
* (Dockerfiles, CI/CD pipelines). These centralize the mapping
|
|
5
|
+
* between an analyzer-detected package manager and the literal
|
|
6
|
+
* shell strings emitted into generated files.
|
|
7
|
+
*
|
|
8
|
+
* Two flavors exist:
|
|
9
|
+
* - `RUN`/`CMD`-style strings used INSIDE Dockerfiles.
|
|
10
|
+
* - Plain shell invocations used in CI scripts and informational
|
|
11
|
+
* comments (no `RUN ` prefix).
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.getRunScriptCommand = exports.getCiInstallCommand = void 0;
|
|
15
|
+
/**
|
|
16
|
+
* Shell invocation that installs project dependencies, suitable for
|
|
17
|
+
* a CI step (no `RUN ` prefix). Uses the strict, lockfile-respecting
|
|
18
|
+
* variant for each package manager because CI runs should be
|
|
19
|
+
* reproducible.
|
|
20
|
+
*/
|
|
21
|
+
function getCiInstallCommand(packageManager) {
|
|
22
|
+
switch (packageManager) {
|
|
23
|
+
case "pnpm":
|
|
24
|
+
return "pnpm install --frozen-lockfile";
|
|
25
|
+
case "yarn":
|
|
26
|
+
return "yarn install --frozen-lockfile";
|
|
27
|
+
case "bun":
|
|
28
|
+
return "bun install --frozen-lockfile";
|
|
29
|
+
default:
|
|
30
|
+
return "npm ci";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.getCiInstallCommand = getCiInstallCommand;
|
|
34
|
+
/**
|
|
35
|
+
* Shell invocation that runs an npm-style script (e.g. `lint`,
|
|
36
|
+
* `test`, `build`). Used in CI scripts and informational comments.
|
|
37
|
+
*/
|
|
38
|
+
function getRunScriptCommand(packageManager, scriptName) {
|
|
39
|
+
switch (packageManager) {
|
|
40
|
+
case "pnpm":
|
|
41
|
+
return `pnpm run ${scriptName}`;
|
|
42
|
+
case "yarn":
|
|
43
|
+
return `yarn ${scriptName}`;
|
|
44
|
+
case "bun":
|
|
45
|
+
return `bun run ${scriptName}`;
|
|
46
|
+
default:
|
|
47
|
+
return `npm run ${scriptName}`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.getRunScriptCommand = getRunScriptCommand;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform wrappers around `child_process.spawn` / `spawnSync` for
|
|
3
|
+
* launching package-manager binaries (npm, yarn, pnpm, npx, tsx, tsc,
|
|
4
|
+
* docker, etc.) reliably on every supported platform.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists
|
|
7
|
+
* ---------------
|
|
8
|
+
* Starting with Node.js 18.20.2 / 20.12.2 / 21.7.3 (and every v22+), the
|
|
9
|
+
* runtime refuses to spawn `.bat` / `.cmd` files unless `shell: true` is
|
|
10
|
+
* passed (see CVE-2024-27980). On Windows, `npm`, `yarn`, `pnpm`, `npx`,
|
|
11
|
+
* `tsx`, `tsc`, and the `node_modules/.bin/*` shims are all `.cmd` files,
|
|
12
|
+
* so a direct `spawn("npm", [...], { shell: false })` call now fails with
|
|
13
|
+
* `EINVAL` ("Package manager not found"). At the same time, just flipping
|
|
14
|
+
* `shell: true` reintroduces the original CVE: arguments containing shell
|
|
15
|
+
* metacharacters (`|`, `>`, `<`, `^`, `&`, `(`, `)`, ...) get interpreted
|
|
16
|
+
* by `cmd.exe` instead of being passed verbatim, which is a real concern
|
|
17
|
+
* for inputs like a semver range (`>=1.0.0 <2.0.0`) or a user-supplied
|
|
18
|
+
* `--src` flag.
|
|
19
|
+
*
|
|
20
|
+
* `cross-spawn` solves both problems:
|
|
21
|
+
* - On Windows it parses the command, resolves `.cmd` shims via PATHEXT,
|
|
22
|
+
* and invokes `cmd.exe /d /s /c "command args"` with `shell: false` and
|
|
23
|
+
* `windowsVerbatimArguments: true`. Each argv entry is passed through a
|
|
24
|
+
* cmd.exe-aware escaper, so metacharacters stay literal.
|
|
25
|
+
* - On Unix it falls through to plain `spawn` with `shell: false`.
|
|
26
|
+
*
|
|
27
|
+
* The helpers here are thin wrappers that default `windowsHide: true` so
|
|
28
|
+
* the Windows console doesn't flash, and re-export the same options shape
|
|
29
|
+
* as `child_process` for drop-in usage.
|
|
30
|
+
*/
|
|
31
|
+
/// <reference types="node" />
|
|
32
|
+
/// <reference types="node" />
|
|
33
|
+
import type { ChildProcess, SpawnOptions, SpawnSyncOptions, SpawnSyncReturns } from "node:child_process";
|
|
34
|
+
export declare function safeSpawn(command: string, args?: ReadonlyArray<string>, options?: SpawnOptions): ChildProcess;
|
|
35
|
+
export declare function safeSpawnSync(command: string, args?: ReadonlyArray<string>, options?: SpawnSyncOptions): SpawnSyncReturns<Buffer>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cross-platform wrappers around `child_process.spawn` / `spawnSync` for
|
|
4
|
+
* launching package-manager binaries (npm, yarn, pnpm, npx, tsx, tsc,
|
|
5
|
+
* docker, etc.) reliably on every supported platform.
|
|
6
|
+
*
|
|
7
|
+
* Why this exists
|
|
8
|
+
* ---------------
|
|
9
|
+
* Starting with Node.js 18.20.2 / 20.12.2 / 21.7.3 (and every v22+), the
|
|
10
|
+
* runtime refuses to spawn `.bat` / `.cmd` files unless `shell: true` is
|
|
11
|
+
* passed (see CVE-2024-27980). On Windows, `npm`, `yarn`, `pnpm`, `npx`,
|
|
12
|
+
* `tsx`, `tsc`, and the `node_modules/.bin/*` shims are all `.cmd` files,
|
|
13
|
+
* so a direct `spawn("npm", [...], { shell: false })` call now fails with
|
|
14
|
+
* `EINVAL` ("Package manager not found"). At the same time, just flipping
|
|
15
|
+
* `shell: true` reintroduces the original CVE: arguments containing shell
|
|
16
|
+
* metacharacters (`|`, `>`, `<`, `^`, `&`, `(`, `)`, ...) get interpreted
|
|
17
|
+
* by `cmd.exe` instead of being passed verbatim, which is a real concern
|
|
18
|
+
* for inputs like a semver range (`>=1.0.0 <2.0.0`) or a user-supplied
|
|
19
|
+
* `--src` flag.
|
|
20
|
+
*
|
|
21
|
+
* `cross-spawn` solves both problems:
|
|
22
|
+
* - On Windows it parses the command, resolves `.cmd` shims via PATHEXT,
|
|
23
|
+
* and invokes `cmd.exe /d /s /c "command args"` with `shell: false` and
|
|
24
|
+
* `windowsVerbatimArguments: true`. Each argv entry is passed through a
|
|
25
|
+
* cmd.exe-aware escaper, so metacharacters stay literal.
|
|
26
|
+
* - On Unix it falls through to plain `spawn` with `shell: false`.
|
|
27
|
+
*
|
|
28
|
+
* The helpers here are thin wrappers that default `windowsHide: true` so
|
|
29
|
+
* the Windows console doesn't flash, and re-export the same options shape
|
|
30
|
+
* as `child_process` for drop-in usage.
|
|
31
|
+
*/
|
|
32
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
33
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
34
|
+
};
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.safeSpawnSync = exports.safeSpawn = void 0;
|
|
37
|
+
const cross_spawn_1 = __importDefault(require("cross-spawn"));
|
|
38
|
+
function safeSpawn(command, args = [], options = {}) {
|
|
39
|
+
return (0, cross_spawn_1.default)(command, args, {
|
|
40
|
+
windowsHide: true,
|
|
41
|
+
...options,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
exports.safeSpawn = safeSpawn;
|
|
45
|
+
function safeSpawnSync(command, args = [], options = {}) {
|
|
46
|
+
return cross_spawn_1.default.sync(command, args, {
|
|
47
|
+
windowsHide: true,
|
|
48
|
+
...options,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
exports.safeSpawnSync = safeSpawnSync;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate path alias from folder name
|
|
3
|
+
* Handles both default mappings and custom folder names
|
|
4
|
+
*
|
|
5
|
+
* @param folderName - The folder name (e.g., "useCases", "my-custom-folder")
|
|
6
|
+
* @returns The path alias (e.g., "@useCases", "@myCustomFolder")
|
|
7
|
+
*/
|
|
8
|
+
export declare function generatePathAlias(folderName: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Update tsconfig.json paths to include missing aliases for opinionated scaffolding
|
|
11
|
+
* Handles both default folders and custom scaffoldSchematics overrides
|
|
12
|
+
*
|
|
13
|
+
* @param folderName - The folder name where the schematic is being created
|
|
14
|
+
* @param sourceRoot - The source root directory (default: "src")
|
|
15
|
+
*/
|
|
16
|
+
export declare function updateTsconfigPaths(folderName: string, sourceRoot?: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Get the path alias for a given folder name
|
|
19
|
+
* Used by other utilities to determine the correct import path
|
|
20
|
+
*
|
|
21
|
+
* @param folderName - The folder name
|
|
22
|
+
* @returns The path alias (e.g., "@useCases")
|
|
23
|
+
*/
|
|
24
|
+
export declare function getPathAliasForFolder(folderName: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Check if tsconfig already has all required path aliases for opinionated mode
|
|
27
|
+
* This can be used to validate project setup
|
|
28
|
+
*
|
|
29
|
+
* @param requiredFolders - List of folder names that need path aliases
|
|
30
|
+
* @returns Object with missing aliases and whether all are present
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateTsconfigPaths(requiredFolders: string[]): {
|
|
33
|
+
valid: boolean;
|
|
34
|
+
missingAliases: string[];
|
|
35
|
+
};
|