@expressots/cli 3.0.0 → 4.0.0-preview.2
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 +126 -0
- package/bin/cicd/form.d.ts +29 -0
- package/bin/cicd/form.js +345 -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 -1
- package/bin/cli.js +18 -3
- package/bin/commands/project.commands.d.ts +19 -6
- package/bin/commands/project.commands.js +390 -61
- 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 +154 -0
- package/bin/containerize/generators/ci-generator.d.ts +31 -0
- package/bin/containerize/generators/ci-generator.js +936 -0
- package/bin/containerize/generators/docker-compose-generator.d.ts +8 -0
- package/bin/containerize/generators/docker-compose-generator.js +186 -0
- package/bin/containerize/generators/dockerfile-generator.d.ts +8 -0
- package/bin/containerize/generators/dockerfile-generator.js +635 -0
- package/bin/containerize/generators/kubernetes-generator.d.ts +8 -0
- package/bin/containerize/generators/kubernetes-generator.js +133 -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 +183 -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 +134 -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.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 +7 -3
- package/bin/generate/utils/command-utils.js +95 -31
- 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 +112 -7
- package/bin/generate/utils/string-utils.d.ts +6 -0
- package/bin/generate/utils/string-utils.js +13 -1
- package/bin/help/form.js +11 -3
- 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 +96 -0
- package/bin/migrate/form.d.ts +25 -0
- package/bin/migrate/form.js +347 -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.js +21 -6
- package/bin/new/form.d.ts +25 -4
- package/bin/new/form.js +285 -70
- 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 +92 -0
- package/bin/profile/form.d.ts +56 -0
- package/bin/profile/form.js +400 -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 +2 -1
- package/bin/scripts/form.js +27 -5
- package/bin/studio/cli.d.ts +15 -0
- package/bin/studio/cli.js +166 -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 +292 -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 +2 -2
- package/bin/utils/add-module-to-container.js +15 -5
- package/bin/utils/cli-ui.d.ts +30 -3
- package/bin/utils/cli-ui.js +95 -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 +286 -0
- package/package.json +154 -154
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template renderer - processes templates with variable substitution
|
|
3
|
+
* Uses Mustache-like syntax: {{variable}}, {{#condition}}...{{/condition}}
|
|
4
|
+
*/
|
|
5
|
+
import type { RenderOptions } from "./types";
|
|
6
|
+
export declare class TemplateRenderer {
|
|
7
|
+
/**
|
|
8
|
+
* Render template with variable substitution
|
|
9
|
+
*/
|
|
10
|
+
render(template: string, options: RenderOptions): string;
|
|
11
|
+
/**
|
|
12
|
+
* Process conditional blocks {{#condition}}...{{/condition}}
|
|
13
|
+
*/
|
|
14
|
+
private processConditionals;
|
|
15
|
+
/**
|
|
16
|
+
* Process negative conditional blocks {{^condition}}...{{/condition}}
|
|
17
|
+
*/
|
|
18
|
+
private processNegativeConditionals;
|
|
19
|
+
/**
|
|
20
|
+
* Process loop blocks for arrays
|
|
21
|
+
*/
|
|
22
|
+
private processLoops;
|
|
23
|
+
/**
|
|
24
|
+
* Process simple variable substitution {{variable}}
|
|
25
|
+
*/
|
|
26
|
+
private processVariables;
|
|
27
|
+
/**
|
|
28
|
+
* Get nested value from object using dot notation. Falls back to a
|
|
29
|
+
* flat-key lookup so callers can provide either
|
|
30
|
+
* `{ app: { version: "1.0.0" } }` or `{ "app.version": "1.0.0" }`.
|
|
31
|
+
*/
|
|
32
|
+
private getNestedValue;
|
|
33
|
+
/**
|
|
34
|
+
* Check if value is truthy for conditional evaluation
|
|
35
|
+
*/
|
|
36
|
+
private isTruthy;
|
|
37
|
+
/**
|
|
38
|
+
* Validate template syntax
|
|
39
|
+
*/
|
|
40
|
+
validateTemplate(template: string): {
|
|
41
|
+
valid: boolean;
|
|
42
|
+
errors: string[];
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Extract variable names from template
|
|
46
|
+
*/
|
|
47
|
+
extractVariables(template: string): string[];
|
|
48
|
+
}
|
|
49
|
+
export declare function getTemplateRenderer(): TemplateRenderer;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Template renderer - processes templates with variable substitution
|
|
4
|
+
* Uses Mustache-like syntax: {{variable}}, {{#condition}}...{{/condition}}
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.getTemplateRenderer = exports.TemplateRenderer = void 0;
|
|
8
|
+
class TemplateRenderer {
|
|
9
|
+
/**
|
|
10
|
+
* Render template with variable substitution
|
|
11
|
+
*/
|
|
12
|
+
render(template, options) {
|
|
13
|
+
let result = template;
|
|
14
|
+
// Process conditionals first: {{#condition}}content{{/condition}}
|
|
15
|
+
result = this.processConditionals(result, options);
|
|
16
|
+
// Process negative conditionals: {{^condition}}content{{/condition}}
|
|
17
|
+
result = this.processNegativeConditionals(result, options);
|
|
18
|
+
// Process loops: {{#items}}{{.}}{{/items}}
|
|
19
|
+
result = this.processLoops(result, options);
|
|
20
|
+
// Process simple variable substitution: {{variable}}
|
|
21
|
+
result = this.processVariables(result, options);
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Process conditional blocks {{#condition}}...{{/condition}}
|
|
26
|
+
*/
|
|
27
|
+
processConditionals(template, options) {
|
|
28
|
+
const pattern = /\{\{#(\w+)\}\}([\s\S]*?)\{\{\/\1\}\}/g;
|
|
29
|
+
return template.replace(pattern, (match, condition, content) => {
|
|
30
|
+
const value = options.conditionals?.[condition] ??
|
|
31
|
+
options.variables[condition];
|
|
32
|
+
// Check if value is truthy
|
|
33
|
+
if (this.isTruthy(value)) {
|
|
34
|
+
// Recursively process the content
|
|
35
|
+
return this.render(content, options);
|
|
36
|
+
}
|
|
37
|
+
return "";
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Process negative conditional blocks {{^condition}}...{{/condition}}
|
|
42
|
+
*/
|
|
43
|
+
processNegativeConditionals(template, options) {
|
|
44
|
+
const pattern = /\{\{\^(\w+)\}\}([\s\S]*?)\{\{\/\1\}\}/g;
|
|
45
|
+
return template.replace(pattern, (match, condition, content) => {
|
|
46
|
+
const value = options.conditionals?.[condition] ??
|
|
47
|
+
options.variables[condition];
|
|
48
|
+
// Check if value is falsy
|
|
49
|
+
if (!this.isTruthy(value)) {
|
|
50
|
+
return this.render(content, options);
|
|
51
|
+
}
|
|
52
|
+
return "";
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Process loop blocks for arrays
|
|
57
|
+
*/
|
|
58
|
+
processLoops(template, options) {
|
|
59
|
+
const pattern = /\{\{#each\s+(\w+)\}\}([\s\S]*?)\{\{\/each\}\}/g;
|
|
60
|
+
return template.replace(pattern, (match, arrayName, content) => {
|
|
61
|
+
const array = options.variables[arrayName];
|
|
62
|
+
if (!Array.isArray(array)) {
|
|
63
|
+
return "";
|
|
64
|
+
}
|
|
65
|
+
return array
|
|
66
|
+
.map((item, index) => {
|
|
67
|
+
// Create new options with item context
|
|
68
|
+
const itemOptions = {
|
|
69
|
+
...options,
|
|
70
|
+
variables: {
|
|
71
|
+
...options.variables,
|
|
72
|
+
".": String(item),
|
|
73
|
+
"@index": index,
|
|
74
|
+
"@first": index === 0,
|
|
75
|
+
"@last": index === array.length - 1,
|
|
76
|
+
...(typeof item === "object" ? item : {}),
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
return this.render(content, itemOptions);
|
|
80
|
+
})
|
|
81
|
+
.join("");
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Process simple variable substitution {{variable}}
|
|
86
|
+
*/
|
|
87
|
+
processVariables(template, options) {
|
|
88
|
+
// Match {{variable}} but not {{#variable}} or {{/variable}} or {{^variable}}
|
|
89
|
+
const pattern = /\{\{([^#/^}][^}]*?)\}\}/g;
|
|
90
|
+
return template.replace(pattern, (match, variable) => {
|
|
91
|
+
const trimmedVar = variable.trim();
|
|
92
|
+
// Handle dot notation for nested variables
|
|
93
|
+
const value = this.getNestedValue(options.variables, trimmedVar);
|
|
94
|
+
if (value === undefined || value === null) {
|
|
95
|
+
// Keep the placeholder if variable not found (for debugging)
|
|
96
|
+
return "";
|
|
97
|
+
}
|
|
98
|
+
return String(value);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get nested value from object using dot notation. Falls back to a
|
|
103
|
+
* flat-key lookup so callers can provide either
|
|
104
|
+
* `{ app: { version: "1.0.0" } }` or `{ "app.version": "1.0.0" }`.
|
|
105
|
+
*/
|
|
106
|
+
getNestedValue(obj, path) {
|
|
107
|
+
if (Object.prototype.hasOwnProperty.call(obj, path)) {
|
|
108
|
+
return obj[path];
|
|
109
|
+
}
|
|
110
|
+
const parts = path.split(".");
|
|
111
|
+
let current = obj;
|
|
112
|
+
for (const part of parts) {
|
|
113
|
+
if (current === null || current === undefined) {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
if (typeof current !== "object") {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
current = current[part];
|
|
120
|
+
}
|
|
121
|
+
return current;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Check if value is truthy for conditional evaluation
|
|
125
|
+
*/
|
|
126
|
+
isTruthy(value) {
|
|
127
|
+
if (value === undefined || value === null)
|
|
128
|
+
return false;
|
|
129
|
+
if (typeof value === "boolean")
|
|
130
|
+
return value;
|
|
131
|
+
if (typeof value === "number")
|
|
132
|
+
return value !== 0;
|
|
133
|
+
if (typeof value === "string")
|
|
134
|
+
return value.length > 0;
|
|
135
|
+
if (Array.isArray(value))
|
|
136
|
+
return value.length > 0;
|
|
137
|
+
if (typeof value === "object")
|
|
138
|
+
return Object.keys(value).length > 0;
|
|
139
|
+
return Boolean(value);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Validate template syntax
|
|
143
|
+
*/
|
|
144
|
+
validateTemplate(template) {
|
|
145
|
+
const errors = [];
|
|
146
|
+
// Check for unclosed conditionals
|
|
147
|
+
const openConditionals = template.match(/\{\{#(\w+)\}\}/g) || [];
|
|
148
|
+
const closeConditionals = template.match(/\{\{\/(\w+)\}\}/g) || [];
|
|
149
|
+
for (const open of openConditionals) {
|
|
150
|
+
const name = open.match(/\{\{#(\w+)\}\}/)?.[1];
|
|
151
|
+
if (name) {
|
|
152
|
+
const closePattern = new RegExp(`\\{\\{\\/${name}\\}\\}`);
|
|
153
|
+
if (!closePattern.test(template)) {
|
|
154
|
+
errors.push(`Unclosed conditional block: {{#${name}}}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Check for orphaned closing tags
|
|
159
|
+
for (const close of closeConditionals) {
|
|
160
|
+
const name = close.match(/\{\{\/(\w+)\}\}/)?.[1];
|
|
161
|
+
if (name) {
|
|
162
|
+
const openPattern = new RegExp(`\\{\\{[#\\^]${name}\\}\\}`);
|
|
163
|
+
if (!openPattern.test(template)) {
|
|
164
|
+
errors.push(`Orphaned closing tag: {{/${name}}}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
valid: errors.length === 0,
|
|
170
|
+
errors,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Extract variable names from template
|
|
175
|
+
*/
|
|
176
|
+
extractVariables(template) {
|
|
177
|
+
const variables = new Set();
|
|
178
|
+
// Match simple variables
|
|
179
|
+
const simplePattern = /\{\{([^#/^}][^}]*?)\}\}/g;
|
|
180
|
+
let match;
|
|
181
|
+
while ((match = simplePattern.exec(template)) !== null) {
|
|
182
|
+
const variable = match[1].trim();
|
|
183
|
+
if (!variable.startsWith(".") && !variable.startsWith("@")) {
|
|
184
|
+
variables.add(variable.split(".")[0]); // Get root variable
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Match conditional variables
|
|
188
|
+
const conditionalPattern = /\{\{[#^](\w+)\}\}/g;
|
|
189
|
+
while ((match = conditionalPattern.exec(template)) !== null) {
|
|
190
|
+
variables.add(match[1]);
|
|
191
|
+
}
|
|
192
|
+
return Array.from(variables);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
exports.TemplateRenderer = TemplateRenderer;
|
|
196
|
+
// Singleton instance
|
|
197
|
+
let rendererInstance = null;
|
|
198
|
+
function getTemplateRenderer() {
|
|
199
|
+
if (!rendererInstance) {
|
|
200
|
+
rendererInstance = new TemplateRenderer();
|
|
201
|
+
}
|
|
202
|
+
return rendererInstance;
|
|
203
|
+
}
|
|
204
|
+
exports.getTemplateRenderer = getTemplateRenderer;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template types and interfaces
|
|
3
|
+
*/
|
|
4
|
+
export type TemplateCategory = "cicd" | "docker" | "kubernetes" | "migrations";
|
|
5
|
+
export type CICDPlatform = "github" | "gitlab" | "circleci" | "jenkins" | "bitbucket" | "azure";
|
|
6
|
+
export type CIStrategy = "basic" | "comprehensive" | "security-focused";
|
|
7
|
+
export type DockerTemplate = "production" | "development" | "compose" | "compose-development";
|
|
8
|
+
export type KubernetesTemplate = "deployment" | "service" | "configmap" | "ingress" | "secrets" | "kustomization";
|
|
9
|
+
export interface TemplateInfo {
|
|
10
|
+
path: string;
|
|
11
|
+
version: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
variables?: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface TemplateManifest {
|
|
16
|
+
version: string;
|
|
17
|
+
updated: string;
|
|
18
|
+
templates: {
|
|
19
|
+
cicd?: Record<CICDPlatform, Record<CIStrategy, TemplateInfo>>;
|
|
20
|
+
docker?: Record<DockerTemplate, TemplateInfo>;
|
|
21
|
+
kubernetes?: Record<KubernetesTemplate, TemplateInfo>;
|
|
22
|
+
migrations?: Record<string, Record<string, TemplateInfo>>;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export interface TemplateVariable {
|
|
26
|
+
name: string;
|
|
27
|
+
value: string | number | boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface RenderOptions {
|
|
30
|
+
variables: Record<string, string | number | boolean | undefined>;
|
|
31
|
+
conditionals?: Record<string, boolean>;
|
|
32
|
+
}
|
|
33
|
+
export interface CacheEntry<T> {
|
|
34
|
+
data: T;
|
|
35
|
+
timestamp: number;
|
|
36
|
+
ttl: number;
|
|
37
|
+
}
|
|
38
|
+
export interface CacheConfig {
|
|
39
|
+
directory: string;
|
|
40
|
+
ttl: number;
|
|
41
|
+
}
|
|
42
|
+
export interface TemplateConfig {
|
|
43
|
+
repository: string;
|
|
44
|
+
branch: string;
|
|
45
|
+
cacheTTL: number;
|
|
46
|
+
}
|
|
47
|
+
export interface FetchResult<T> {
|
|
48
|
+
data: T | null;
|
|
49
|
+
source: "cache" | "remote" | "fallback";
|
|
50
|
+
error?: string;
|
|
51
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
declare function addModuleToContainer(name: string, modulePath?: string, path?: string): Promise<void>;
|
|
2
|
-
declare function addModuleToContainerNestedPath(name: string, path?: string): Promise<void>;
|
|
1
|
+
declare function addModuleToContainer(name: string, modulePath?: string, path?: string, folderName?: string): Promise<void>;
|
|
2
|
+
declare function addModuleToContainerNestedPath(name: string, path?: string, folderName?: string): Promise<void>;
|
|
3
3
|
export { addModuleToContainer, addModuleToContainerNestedPath };
|
|
@@ -9,6 +9,7 @@ const glob_1 = require("glob");
|
|
|
9
9
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
10
10
|
const cli_ui_1 = require("./cli-ui");
|
|
11
11
|
const compiler_1 = __importDefault(require("./compiler"));
|
|
12
|
+
const update_tsconfig_paths_1 = require("./update-tsconfig-paths");
|
|
12
13
|
const APP_CONTAINER = "app.ts";
|
|
13
14
|
async function validateAppContainer() {
|
|
14
15
|
const { sourceRoot } = await compiler_1.default.loadConfig();
|
|
@@ -56,14 +57,18 @@ async function validateAppContainer() {
|
|
|
56
57
|
notImports,
|
|
57
58
|
};
|
|
58
59
|
}
|
|
59
|
-
async function addModuleToContainer(name, modulePath, path) {
|
|
60
|
-
console.log("To chamando esse cara");
|
|
60
|
+
async function addModuleToContainer(name, modulePath, path, folderName) {
|
|
61
61
|
const containerData = await validateAppContainer();
|
|
62
62
|
const moduleName = (name[0].toUpperCase() + name.slice(1)).trimStart();
|
|
63
63
|
const { opinionated } = await compiler_1.default.loadConfig();
|
|
64
64
|
let usecaseDir;
|
|
65
65
|
if (opinionated) {
|
|
66
|
-
|
|
66
|
+
// Use dynamic path alias based on the actual folder
|
|
67
|
+
// Default to @useCases for backward compatibility
|
|
68
|
+
const pathAlias = folderName
|
|
69
|
+
? (0, update_tsconfig_paths_1.getPathAliasForFolder)(folderName)
|
|
70
|
+
: "@useCases";
|
|
71
|
+
usecaseDir = `${pathAlias}/`;
|
|
67
72
|
}
|
|
68
73
|
else {
|
|
69
74
|
usecaseDir = `./`;
|
|
@@ -99,13 +104,18 @@ async function addModuleToContainer(name, modulePath, path) {
|
|
|
99
104
|
await node_fs_1.default.promises.writeFile(containerData.path, newFileContent, "utf8");
|
|
100
105
|
}
|
|
101
106
|
exports.addModuleToContainer = addModuleToContainer;
|
|
102
|
-
async function addModuleToContainerNestedPath(name, path) {
|
|
107
|
+
async function addModuleToContainerNestedPath(name, path, folderName) {
|
|
103
108
|
const containerData = await validateAppContainer();
|
|
104
109
|
const moduleName = (name[0].toUpperCase() + name.slice(1)).trimStart();
|
|
105
110
|
const { opinionated } = await compiler_1.default.loadConfig();
|
|
106
111
|
let usecaseDir;
|
|
107
112
|
if (opinionated) {
|
|
108
|
-
|
|
113
|
+
// Use dynamic path alias based on the actual folder
|
|
114
|
+
// Default to @useCases for backward compatibility
|
|
115
|
+
const pathAlias = folderName
|
|
116
|
+
? (0, update_tsconfig_paths_1.getPathAliasForFolder)(folderName)
|
|
117
|
+
: "@useCases";
|
|
118
|
+
usecaseDir = `${pathAlias}/`;
|
|
109
119
|
}
|
|
110
120
|
else {
|
|
111
121
|
usecaseDir = `./`;
|
package/bin/utils/cli-ui.d.ts
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Print error message (matches core logger ERROR format)
|
|
3
|
+
*/
|
|
4
|
+
export declare function printError(message: string, context: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* Print success message (matches core logger INFO format)
|
|
7
|
+
*/
|
|
8
|
+
export declare function printSuccess(message: string, context: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* Print warning message (matches core logger WARN format)
|
|
11
|
+
*/
|
|
12
|
+
export declare function printWarning(message: string, context?: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Print info message (matches core logger INFO format)
|
|
15
|
+
*/
|
|
16
|
+
export declare function printInfo(message: string, context: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Print debug message (matches core logger DEBUG format)
|
|
19
|
+
*/
|
|
20
|
+
export declare function printDebug(message: string, context: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Print generate error (simplified format for scaffolding)
|
|
23
|
+
*/
|
|
4
24
|
export declare function printGenerateError(schematic: string, file: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Print generate success (simplified format for scaffolding)
|
|
27
|
+
*/
|
|
5
28
|
export declare function printGenerateSuccess(schematic: string, file: string): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Print the ExpressoTS CLI header
|
|
31
|
+
*/
|
|
32
|
+
export declare function printHeader(): void;
|
package/bin/utils/cli-ui.js
CHANGED
|
@@ -3,30 +3,112 @@ 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.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 the ExpressoTS CLI header
|
|
110
|
+
*/
|
|
111
|
+
function printHeader() {
|
|
112
|
+
process_1.stdout.write(`\n${chalk_1.default.bold.green("🐎 ExpressoTS CLI")}\n\n`);
|
|
113
|
+
}
|
|
114
|
+
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;
|