@expressots/cli 3.0.0-beta.4 ā 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,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateKubernetesConfigs = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const template_loader_1 = require("./template-loader");
|
|
11
|
+
async function generateKubernetesConfigs(options, analysis) {
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
const k8sDir = path_1.default.join(cwd, "k8s");
|
|
14
|
+
if (!fs_1.default.existsSync(k8sDir)) {
|
|
15
|
+
fs_1.default.mkdirSync(k8sDir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
console.log(chalk_1.default.yellow(`š Generating Kubernetes configurations...`));
|
|
18
|
+
const vars = {
|
|
19
|
+
port: analysis?.port || 3000,
|
|
20
|
+
memory: analysis?.estimatedMemory || "256Mi",
|
|
21
|
+
cpu: analysis?.estimatedCpu || "250m",
|
|
22
|
+
replicas: 3,
|
|
23
|
+
appName: "expressots-app",
|
|
24
|
+
namespace: "default",
|
|
25
|
+
healthCheckPath: analysis?.healthCheckPaths?.[0] || "/health",
|
|
26
|
+
};
|
|
27
|
+
// Generate deployment
|
|
28
|
+
const deploymentResult = await (0, template_loader_1.loadKubernetesTemplate)("deployment", vars, () => generateDeployment(options, analysis));
|
|
29
|
+
(0, template_loader_1.logTemplateSource)("k8s/deployment", deploymentResult.source);
|
|
30
|
+
fs_1.default.writeFileSync(path_1.default.join(k8sDir, "deployment.yaml"), deploymentResult.content, "utf-8");
|
|
31
|
+
console.log(chalk_1.default.green(` ā Created k8s/deployment.yaml`));
|
|
32
|
+
// Generate service
|
|
33
|
+
const serviceResult = await (0, template_loader_1.loadKubernetesTemplate)("service", vars, () => generateService(options, analysis));
|
|
34
|
+
(0, template_loader_1.logTemplateSource)("k8s/service", serviceResult.source);
|
|
35
|
+
fs_1.default.writeFileSync(path_1.default.join(k8sDir, "service.yaml"), serviceResult.content, "utf-8");
|
|
36
|
+
console.log(chalk_1.default.green(` ā Created k8s/service.yaml`));
|
|
37
|
+
// Generate config map
|
|
38
|
+
const configMapResult = await (0, template_loader_1.loadKubernetesTemplate)("configmap", vars, () => generateConfigMap(options, analysis));
|
|
39
|
+
(0, template_loader_1.logTemplateSource)("k8s/configmap", configMapResult.source);
|
|
40
|
+
fs_1.default.writeFileSync(path_1.default.join(k8sDir, "configmap.yaml"), configMapResult.content, "utf-8");
|
|
41
|
+
console.log(chalk_1.default.green(` ā Created k8s/configmap.yaml`));
|
|
42
|
+
}
|
|
43
|
+
exports.generateKubernetesConfigs = generateKubernetesConfigs;
|
|
44
|
+
function generateDeployment(options, analysis) {
|
|
45
|
+
const port = analysis?.port || 3000;
|
|
46
|
+
const memory = analysis?.estimatedMemory || "256Mi";
|
|
47
|
+
const cpu = analysis?.estimatedCpu || "250m";
|
|
48
|
+
return `# Kubernetes Deployment
|
|
49
|
+
# Generated by ExpressoTS CLI
|
|
50
|
+
|
|
51
|
+
apiVersion: apps/v1
|
|
52
|
+
kind: Deployment
|
|
53
|
+
metadata:
|
|
54
|
+
name: expressots-app
|
|
55
|
+
labels:
|
|
56
|
+
app: expressots-app
|
|
57
|
+
spec:
|
|
58
|
+
replicas: 3
|
|
59
|
+
selector:
|
|
60
|
+
matchLabels:
|
|
61
|
+
app: expressots-app
|
|
62
|
+
template:
|
|
63
|
+
metadata:
|
|
64
|
+
labels:
|
|
65
|
+
app: expressots-app
|
|
66
|
+
spec:
|
|
67
|
+
containers:
|
|
68
|
+
- name: app
|
|
69
|
+
image: your-registry/expressots-app:latest
|
|
70
|
+
ports:
|
|
71
|
+
- containerPort: ${port}
|
|
72
|
+
name: http
|
|
73
|
+
env:
|
|
74
|
+
- name: NODE_ENV
|
|
75
|
+
value: "production"
|
|
76
|
+
- name: PORT
|
|
77
|
+
value: "${port}"
|
|
78
|
+
envFrom:
|
|
79
|
+
- configMapRef:
|
|
80
|
+
name: app-config
|
|
81
|
+
resources:
|
|
82
|
+
requests:
|
|
83
|
+
memory: "${memory}"
|
|
84
|
+
cpu: "${cpu}"
|
|
85
|
+
limits:
|
|
86
|
+
memory: "${memory === "256Mi" ? "512Mi" : memory}"
|
|
87
|
+
cpu: "${cpu === "250m" ? "500m" : cpu}"
|
|
88
|
+
livenessProbe:
|
|
89
|
+
httpGet:
|
|
90
|
+
path: /health
|
|
91
|
+
port: ${port}
|
|
92
|
+
initialDelaySeconds: 30
|
|
93
|
+
periodSeconds: 10
|
|
94
|
+
readinessProbe:
|
|
95
|
+
httpGet:
|
|
96
|
+
path: /health
|
|
97
|
+
port: ${port}
|
|
98
|
+
initialDelaySeconds: 5
|
|
99
|
+
periodSeconds: 5
|
|
100
|
+
`;
|
|
101
|
+
}
|
|
102
|
+
function generateService(options, analysis) {
|
|
103
|
+
const port = analysis?.port || 3000;
|
|
104
|
+
return `# Kubernetes Service
|
|
105
|
+
# Generated by ExpressoTS CLI
|
|
106
|
+
|
|
107
|
+
apiVersion: v1
|
|
108
|
+
kind: Service
|
|
109
|
+
metadata:
|
|
110
|
+
name: expressots-app
|
|
111
|
+
spec:
|
|
112
|
+
type: LoadBalancer
|
|
113
|
+
selector:
|
|
114
|
+
app: expressots-app
|
|
115
|
+
ports:
|
|
116
|
+
- protocol: TCP
|
|
117
|
+
port: 80
|
|
118
|
+
targetPort: ${port}
|
|
119
|
+
`;
|
|
120
|
+
}
|
|
121
|
+
function generateConfigMap(options, analysis) {
|
|
122
|
+
return `# Kubernetes ConfigMap
|
|
123
|
+
# Generated by ExpressoTS CLI
|
|
124
|
+
|
|
125
|
+
apiVersion: v1
|
|
126
|
+
kind: ConfigMap
|
|
127
|
+
metadata:
|
|
128
|
+
name: app-config
|
|
129
|
+
data:
|
|
130
|
+
NODE_ENV: "production"
|
|
131
|
+
# Add your configuration here
|
|
132
|
+
`;
|
|
133
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template loader for containerize generators
|
|
3
|
+
* Handles remote template fetching with fallback to embedded templates
|
|
4
|
+
*/
|
|
5
|
+
import type { ProjectAnalysis } from "../analyzers/project-analyzer";
|
|
6
|
+
export interface DockerTemplateVars {
|
|
7
|
+
nodeVersion: string;
|
|
8
|
+
packageManager: string;
|
|
9
|
+
entryPoint: string;
|
|
10
|
+
port: number;
|
|
11
|
+
hasLocalDeps: boolean;
|
|
12
|
+
healthCheckEndpoint: string;
|
|
13
|
+
projectName: string;
|
|
14
|
+
installCommand: string;
|
|
15
|
+
buildCommand: string;
|
|
16
|
+
}
|
|
17
|
+
export interface TemplateResult {
|
|
18
|
+
content: string;
|
|
19
|
+
source: "remote" | "embedded";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Load Docker template with fallback
|
|
23
|
+
*/
|
|
24
|
+
export declare function loadDockerTemplate(templateType: string, variables: DockerTemplateVars, embeddedGenerator: () => string): Promise<TemplateResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Load Kubernetes template with fallback
|
|
27
|
+
*/
|
|
28
|
+
export declare function loadKubernetesTemplate(templateType: string, variables: Record<string, unknown>, embeddedGenerator: () => string): Promise<TemplateResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Build Docker template variables from analysis
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildDockerVars(analysis: ProjectAnalysis | undefined, entryPoint: string, packageManager?: string): DockerTemplateVars;
|
|
33
|
+
/**
|
|
34
|
+
* Log template source for debugging
|
|
35
|
+
*/
|
|
36
|
+
export declare function logTemplateSource(templateName: string, source: "remote" | "embedded"): void;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Template loader for containerize generators
|
|
4
|
+
* Handles remote template fetching with fallback to embedded templates
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.logTemplateSource = exports.buildDockerVars = exports.loadKubernetesTemplate = exports.loadDockerTemplate = void 0;
|
|
8
|
+
const templates_1 = require("../../templates");
|
|
9
|
+
/**
|
|
10
|
+
* Load Docker template with fallback
|
|
11
|
+
*/
|
|
12
|
+
async function loadDockerTemplate(templateType, variables, embeddedGenerator) {
|
|
13
|
+
const manager = (0, templates_1.getTemplateManager)();
|
|
14
|
+
try {
|
|
15
|
+
// Try to fetch from remote template repository
|
|
16
|
+
const result = await manager.fetchDockerTemplate(templateType);
|
|
17
|
+
if (result.data) {
|
|
18
|
+
// Template found, render with variables
|
|
19
|
+
const renderOptions = {
|
|
20
|
+
variables: {
|
|
21
|
+
...variables,
|
|
22
|
+
},
|
|
23
|
+
conditionals: {
|
|
24
|
+
hasLocalDeps: variables.hasLocalDeps,
|
|
25
|
+
useNpmCi: !variables.hasLocalDeps,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
const rendered = manager.render(result.data, renderOptions);
|
|
29
|
+
return { content: rendered, source: "remote" };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Remote fetch failed, fall back to embedded
|
|
34
|
+
}
|
|
35
|
+
// Fall back to embedded template generator
|
|
36
|
+
return {
|
|
37
|
+
content: embeddedGenerator(),
|
|
38
|
+
source: "embedded",
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
exports.loadDockerTemplate = loadDockerTemplate;
|
|
42
|
+
/**
|
|
43
|
+
* Load Kubernetes template with fallback
|
|
44
|
+
*/
|
|
45
|
+
async function loadKubernetesTemplate(templateType, variables, embeddedGenerator) {
|
|
46
|
+
const manager = (0, templates_1.getTemplateManager)();
|
|
47
|
+
try {
|
|
48
|
+
// Try to fetch from remote template repository
|
|
49
|
+
const result = await manager.fetchKubernetesTemplate(templateType);
|
|
50
|
+
if (result.data) {
|
|
51
|
+
// Template found, render with variables
|
|
52
|
+
const renderOptions = {
|
|
53
|
+
variables: variables,
|
|
54
|
+
};
|
|
55
|
+
const rendered = manager.render(result.data, renderOptions);
|
|
56
|
+
return { content: rendered, source: "remote" };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Remote fetch failed, fall back to embedded
|
|
61
|
+
}
|
|
62
|
+
// Fall back to embedded template generator
|
|
63
|
+
return {
|
|
64
|
+
content: embeddedGenerator(),
|
|
65
|
+
source: "embedded",
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
exports.loadKubernetesTemplate = loadKubernetesTemplate;
|
|
69
|
+
/**
|
|
70
|
+
* Build Docker template variables from analysis
|
|
71
|
+
*/
|
|
72
|
+
function buildDockerVars(analysis, entryPoint, packageManager = "npm") {
|
|
73
|
+
return {
|
|
74
|
+
nodeVersion: analysis?.nodeVersion || "20",
|
|
75
|
+
packageManager,
|
|
76
|
+
entryPoint,
|
|
77
|
+
port: analysis?.port || 3000,
|
|
78
|
+
hasLocalDeps: analysis?.hasLocalDependencies || false,
|
|
79
|
+
healthCheckEndpoint: analysis?.healthCheckPaths?.[0] || "/health",
|
|
80
|
+
projectName: "expressots-app",
|
|
81
|
+
installCommand: getInstallCommand(packageManager, analysis?.hasLocalDependencies),
|
|
82
|
+
buildCommand: getBuildCommand(packageManager),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
exports.buildDockerVars = buildDockerVars;
|
|
86
|
+
/**
|
|
87
|
+
* Get install command for package manager
|
|
88
|
+
*/
|
|
89
|
+
function getInstallCommand(packageManager, hasLocalDeps) {
|
|
90
|
+
if (hasLocalDeps) {
|
|
91
|
+
// Use npm install when local deps exist (npm ci doesn't work well with local deps)
|
|
92
|
+
return packageManager === "pnpm"
|
|
93
|
+
? "pnpm install"
|
|
94
|
+
: packageManager === "yarn"
|
|
95
|
+
? "yarn install"
|
|
96
|
+
: "npm install";
|
|
97
|
+
}
|
|
98
|
+
switch (packageManager) {
|
|
99
|
+
case "pnpm":
|
|
100
|
+
return "pnpm install --frozen-lockfile";
|
|
101
|
+
case "yarn":
|
|
102
|
+
return "yarn install --frozen-lockfile";
|
|
103
|
+
default:
|
|
104
|
+
return "npm ci";
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get build command for package manager
|
|
109
|
+
*/
|
|
110
|
+
function getBuildCommand(packageManager) {
|
|
111
|
+
switch (packageManager) {
|
|
112
|
+
case "pnpm":
|
|
113
|
+
return "pnpm build";
|
|
114
|
+
case "yarn":
|
|
115
|
+
return "yarn build";
|
|
116
|
+
default:
|
|
117
|
+
return "npm run build";
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Log template source for debugging
|
|
122
|
+
*/
|
|
123
|
+
function logTemplateSource(templateName, source) {
|
|
124
|
+
if (process.env.EXPRESSOTS_DEBUG) {
|
|
125
|
+
const sourceLabel = source === "remote" ? "remote template" : "embedded template";
|
|
126
|
+
console.log(` [DEBUG] ${templateName}: Using ${sourceLabel}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.logTemplateSource = logTemplateSource;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { containerize } from "./cli";
|
|
2
|
+
export { containerizeProject } from "./form";
|
|
3
|
+
export { analyzeBootstrapConfig, shouldCopyEnvFiles, getEnvFileForEnvironment, type BootstrapConfig, type EnvFileMapping, } from "./analyzers/bootstrap-analyzer";
|
|
4
|
+
export { analyzeProject, type ProjectAnalysis, } from "./analyzers/project-analyzer";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.analyzeProject = exports.getEnvFileForEnvironment = exports.shouldCopyEnvFiles = exports.analyzeBootstrapConfig = exports.containerizeProject = exports.containerize = void 0;
|
|
4
|
+
var cli_1 = require("./cli");
|
|
5
|
+
Object.defineProperty(exports, "containerize", { enumerable: true, get: function () { return cli_1.containerize; } });
|
|
6
|
+
var form_1 = require("./form");
|
|
7
|
+
Object.defineProperty(exports, "containerizeProject", { enumerable: true, get: function () { return form_1.containerizeProject; } });
|
|
8
|
+
var bootstrap_analyzer_1 = require("./analyzers/bootstrap-analyzer");
|
|
9
|
+
Object.defineProperty(exports, "analyzeBootstrapConfig", { enumerable: true, get: function () { return bootstrap_analyzer_1.analyzeBootstrapConfig; } });
|
|
10
|
+
Object.defineProperty(exports, "shouldCopyEnvFiles", { enumerable: true, get: function () { return bootstrap_analyzer_1.shouldCopyEnvFiles; } });
|
|
11
|
+
Object.defineProperty(exports, "getEnvFileForEnvironment", { enumerable: true, get: function () { return bootstrap_analyzer_1.getEnvFileForEnvironment; } });
|
|
12
|
+
var project_analyzer_1 = require("./analyzers/project-analyzer");
|
|
13
|
+
Object.defineProperty(exports, "analyzeProject", { enumerable: true, get: function () { return project_analyzer_1.analyzeProject; } });
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface PresetConfig {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
baseImage?: string;
|
|
5
|
+
multiStage?: boolean;
|
|
6
|
+
security?: {
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
nonRootUser?: boolean;
|
|
9
|
+
};
|
|
10
|
+
healthCheck?: {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
interval?: string;
|
|
13
|
+
};
|
|
14
|
+
optimization?: {
|
|
15
|
+
layerCaching?: boolean;
|
|
16
|
+
minimalDependencies?: boolean;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export declare function getPresetConfig(presetName: string): PresetConfig;
|
|
20
|
+
export declare function listPresets(): PresetConfig[];
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listPresets = exports.getPresetConfig = void 0;
|
|
4
|
+
const presets = {
|
|
5
|
+
standard: {
|
|
6
|
+
name: "Standard",
|
|
7
|
+
description: "Balanced configuration for most applications",
|
|
8
|
+
multiStage: true,
|
|
9
|
+
security: {
|
|
10
|
+
enabled: false,
|
|
11
|
+
},
|
|
12
|
+
healthCheck: {
|
|
13
|
+
enabled: false,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
minimal: {
|
|
17
|
+
name: "Minimal",
|
|
18
|
+
description: "Smallest possible image size (<100MB)",
|
|
19
|
+
baseImage: "node:22-alpine",
|
|
20
|
+
multiStage: true,
|
|
21
|
+
security: {
|
|
22
|
+
enabled: false,
|
|
23
|
+
},
|
|
24
|
+
healthCheck: {
|
|
25
|
+
enabled: false,
|
|
26
|
+
},
|
|
27
|
+
optimization: {
|
|
28
|
+
layerCaching: true,
|
|
29
|
+
minimalDependencies: true,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
secure: {
|
|
33
|
+
name: "Secure",
|
|
34
|
+
description: "Security-hardened configuration",
|
|
35
|
+
baseImage: "node:22-alpine",
|
|
36
|
+
multiStage: true,
|
|
37
|
+
security: {
|
|
38
|
+
enabled: true,
|
|
39
|
+
nonRootUser: true,
|
|
40
|
+
},
|
|
41
|
+
healthCheck: {
|
|
42
|
+
enabled: true,
|
|
43
|
+
interval: "30s",
|
|
44
|
+
},
|
|
45
|
+
optimization: {
|
|
46
|
+
layerCaching: true,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
"fast-startup": {
|
|
50
|
+
name: "Fast Startup",
|
|
51
|
+
description: "Optimized for quick cold starts",
|
|
52
|
+
baseImage: "node:22-alpine",
|
|
53
|
+
multiStage: true,
|
|
54
|
+
security: {
|
|
55
|
+
enabled: false,
|
|
56
|
+
},
|
|
57
|
+
healthCheck: {
|
|
58
|
+
enabled: true,
|
|
59
|
+
},
|
|
60
|
+
optimization: {
|
|
61
|
+
layerCaching: true,
|
|
62
|
+
minimalDependencies: true,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
dev: {
|
|
66
|
+
name: "Development",
|
|
67
|
+
description: "Development environment with hot reload",
|
|
68
|
+
baseImage: "node:22",
|
|
69
|
+
multiStage: false,
|
|
70
|
+
security: {
|
|
71
|
+
enabled: false,
|
|
72
|
+
},
|
|
73
|
+
healthCheck: {
|
|
74
|
+
enabled: false,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
"multi-arch": {
|
|
78
|
+
name: "Multi-Architecture",
|
|
79
|
+
description: "Supports both ARM64 and x86_64",
|
|
80
|
+
baseImage: "node:22-alpine",
|
|
81
|
+
multiStage: true,
|
|
82
|
+
security: {
|
|
83
|
+
enabled: true,
|
|
84
|
+
},
|
|
85
|
+
healthCheck: {
|
|
86
|
+
enabled: true,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
function getPresetConfig(presetName) {
|
|
91
|
+
const preset = presets[presetName];
|
|
92
|
+
if (!preset) {
|
|
93
|
+
console.warn(`Warning: Preset "${presetName}" not found. Using "standard" preset.`);
|
|
94
|
+
return presets.standard;
|
|
95
|
+
}
|
|
96
|
+
return preset;
|
|
97
|
+
}
|
|
98
|
+
exports.getPresetConfig = getPresetConfig;
|
|
99
|
+
function listPresets() {
|
|
100
|
+
return Object.values(presets);
|
|
101
|
+
}
|
|
102
|
+
exports.listPresets = listPresets;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { CommandModule } from "yargs";
|
|
2
|
+
type CommandModuleArgs = {};
|
|
3
|
+
export type CloudProvider = "aws" | "gcp" | "azure" | "railway" | "render" | "fly" | "digitalocean" | "heroku";
|
|
4
|
+
declare const costsCommand: () => CommandModule<CommandModuleArgs, any>;
|
|
5
|
+
export { costsCommand };
|
package/bin/costs/cli.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.costsCommand = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const form_1 = require("./form");
|
|
9
|
+
const pricing_manager_1 = require("./pricing-manager");
|
|
10
|
+
const costsCommand = () => {
|
|
11
|
+
return {
|
|
12
|
+
command: "costs <action>",
|
|
13
|
+
describe: "Estimate and compare cloud deployment costs.",
|
|
14
|
+
aliases: ["cost", "pricing"],
|
|
15
|
+
builder: (yargs) => {
|
|
16
|
+
yargs.positional("action", {
|
|
17
|
+
choices: [
|
|
18
|
+
"estimate",
|
|
19
|
+
"compare",
|
|
20
|
+
"optimize",
|
|
21
|
+
"pricing",
|
|
22
|
+
"update",
|
|
23
|
+
"info",
|
|
24
|
+
],
|
|
25
|
+
describe: "Action to perform",
|
|
26
|
+
type: "string",
|
|
27
|
+
demandOption: true,
|
|
28
|
+
});
|
|
29
|
+
yargs.option("provider", {
|
|
30
|
+
choices: [
|
|
31
|
+
"aws",
|
|
32
|
+
"gcp",
|
|
33
|
+
"azure",
|
|
34
|
+
"railway",
|
|
35
|
+
"render",
|
|
36
|
+
"fly",
|
|
37
|
+
"digitalocean",
|
|
38
|
+
"heroku",
|
|
39
|
+
],
|
|
40
|
+
describe: "Cloud provider",
|
|
41
|
+
type: "string",
|
|
42
|
+
alias: "p",
|
|
43
|
+
});
|
|
44
|
+
yargs.option("service", {
|
|
45
|
+
choices: [
|
|
46
|
+
"ecs",
|
|
47
|
+
"eks",
|
|
48
|
+
"lambda",
|
|
49
|
+
"cloudrun",
|
|
50
|
+
"gke",
|
|
51
|
+
"aci",
|
|
52
|
+
"aks",
|
|
53
|
+
"web-service",
|
|
54
|
+
],
|
|
55
|
+
describe: "Specific service type",
|
|
56
|
+
type: "string",
|
|
57
|
+
alias: "s",
|
|
58
|
+
});
|
|
59
|
+
yargs.option("instances", {
|
|
60
|
+
describe: "Number of instances/replicas",
|
|
61
|
+
type: "number",
|
|
62
|
+
alias: "i",
|
|
63
|
+
default: 1,
|
|
64
|
+
});
|
|
65
|
+
yargs.option("cpu", {
|
|
66
|
+
describe: "CPU cores/vCPUs per instance",
|
|
67
|
+
type: "number",
|
|
68
|
+
alias: "c",
|
|
69
|
+
default: 1,
|
|
70
|
+
});
|
|
71
|
+
yargs.option("memory", {
|
|
72
|
+
describe: "Memory in GB per instance",
|
|
73
|
+
type: "number",
|
|
74
|
+
alias: "m",
|
|
75
|
+
default: 1,
|
|
76
|
+
});
|
|
77
|
+
yargs.option("storage", {
|
|
78
|
+
describe: "Storage in GB",
|
|
79
|
+
type: "number",
|
|
80
|
+
default: 10,
|
|
81
|
+
});
|
|
82
|
+
yargs.option("bandwidth", {
|
|
83
|
+
describe: "Expected bandwidth in GB/month",
|
|
84
|
+
type: "number",
|
|
85
|
+
default: 100,
|
|
86
|
+
});
|
|
87
|
+
yargs.option("region", {
|
|
88
|
+
describe: "Cloud region",
|
|
89
|
+
type: "string",
|
|
90
|
+
alias: "r",
|
|
91
|
+
default: "us-east-1",
|
|
92
|
+
});
|
|
93
|
+
yargs.option("hours", {
|
|
94
|
+
describe: "Expected running hours per month",
|
|
95
|
+
type: "number",
|
|
96
|
+
default: 720, // 24 * 30
|
|
97
|
+
});
|
|
98
|
+
yargs.option("format", {
|
|
99
|
+
choices: ["text", "json", "markdown"],
|
|
100
|
+
describe: "Output format",
|
|
101
|
+
type: "string",
|
|
102
|
+
default: "text",
|
|
103
|
+
});
|
|
104
|
+
yargs.option("output", {
|
|
105
|
+
describe: "Output file",
|
|
106
|
+
type: "string",
|
|
107
|
+
alias: "o",
|
|
108
|
+
});
|
|
109
|
+
return yargs;
|
|
110
|
+
},
|
|
111
|
+
handler: async (argv) => {
|
|
112
|
+
const { action, provider, service, instances, cpu, memory, storage, bandwidth, region, hours, format, output, } = argv;
|
|
113
|
+
const options = {
|
|
114
|
+
provider: provider,
|
|
115
|
+
service,
|
|
116
|
+
instances,
|
|
117
|
+
cpu,
|
|
118
|
+
memory,
|
|
119
|
+
storage,
|
|
120
|
+
bandwidth,
|
|
121
|
+
region,
|
|
122
|
+
hours,
|
|
123
|
+
format: format,
|
|
124
|
+
output,
|
|
125
|
+
};
|
|
126
|
+
switch (action) {
|
|
127
|
+
case "estimate":
|
|
128
|
+
await (0, form_1.estimateCosts)(options);
|
|
129
|
+
break;
|
|
130
|
+
case "compare":
|
|
131
|
+
await (0, form_1.compareCosts)(options);
|
|
132
|
+
break;
|
|
133
|
+
case "optimize":
|
|
134
|
+
await (0, form_1.optimizeCosts)(options);
|
|
135
|
+
break;
|
|
136
|
+
case "pricing":
|
|
137
|
+
await (0, form_1.showPricing)(options);
|
|
138
|
+
break;
|
|
139
|
+
case "update":
|
|
140
|
+
await updatePricingData();
|
|
141
|
+
break;
|
|
142
|
+
case "info":
|
|
143
|
+
await showPricingInfo();
|
|
144
|
+
break;
|
|
145
|
+
default:
|
|
146
|
+
console.log(`Unknown action: ${action}`);
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
exports.costsCommand = costsCommand;
|
|
152
|
+
/**
|
|
153
|
+
* Update pricing data from remote sources
|
|
154
|
+
*/
|
|
155
|
+
async function updatePricingData() {
|
|
156
|
+
console.log(chalk_1.default.cyan("\nš Updating Pricing Data...\n"));
|
|
157
|
+
const manager = (0, pricing_manager_1.getPricingManager)();
|
|
158
|
+
manager.clearCache();
|
|
159
|
+
const success = await manager.updateCache();
|
|
160
|
+
if (success) {
|
|
161
|
+
const source = manager.getLastSource();
|
|
162
|
+
console.log(chalk_1.default.green(`ā Pricing data updated`));
|
|
163
|
+
console.log(chalk_1.default.gray(` Source: ${source}`));
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
console.log(chalk_1.default.red("ā Failed to update pricing data"));
|
|
167
|
+
console.log(chalk_1.default.gray(" Check your network connection and try again."));
|
|
168
|
+
}
|
|
169
|
+
console.log();
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Show pricing system info
|
|
173
|
+
*/
|
|
174
|
+
async function showPricingInfo() {
|
|
175
|
+
const manager = (0, pricing_manager_1.getPricingManager)();
|
|
176
|
+
await manager.printStatus();
|
|
177
|
+
const providers = await manager.getAvailableProviders();
|
|
178
|
+
if (providers.length > 0) {
|
|
179
|
+
console.log(chalk_1.default.bold("\nAvailable Providers:"));
|
|
180
|
+
console.log(` ${providers.join(", ")}`);
|
|
181
|
+
}
|
|
182
|
+
console.log();
|
|
183
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { CloudProvider } from "./cli";
|
|
2
|
+
export interface CostOptions {
|
|
3
|
+
provider?: CloudProvider;
|
|
4
|
+
service?: string;
|
|
5
|
+
instances: number;
|
|
6
|
+
cpu: number;
|
|
7
|
+
memory: number;
|
|
8
|
+
storage: number;
|
|
9
|
+
bandwidth: number;
|
|
10
|
+
region: string;
|
|
11
|
+
hours: number;
|
|
12
|
+
format: "text" | "json" | "markdown";
|
|
13
|
+
output?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface CostEstimate {
|
|
16
|
+
provider: string;
|
|
17
|
+
service: string;
|
|
18
|
+
monthlyCost: number;
|
|
19
|
+
breakdown: CostBreakdown;
|
|
20
|
+
currency: string;
|
|
21
|
+
}
|
|
22
|
+
export interface CostBreakdown {
|
|
23
|
+
compute: number;
|
|
24
|
+
memory?: number;
|
|
25
|
+
storage: number;
|
|
26
|
+
bandwidth: number;
|
|
27
|
+
other: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Estimate costs for a specific provider
|
|
31
|
+
*/
|
|
32
|
+
export declare function estimateCosts(options: CostOptions): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Compare costs across all providers
|
|
35
|
+
*/
|
|
36
|
+
export declare function compareCosts(options: CostOptions): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Suggest cost optimizations
|
|
39
|
+
*/
|
|
40
|
+
export declare function optimizeCosts(options: CostOptions): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Show pricing information for a provider
|
|
43
|
+
*/
|
|
44
|
+
export declare function showPricing(options: CostOptions): Promise<void>;
|