@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
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface DockerfileAnalysis {
|
|
2
|
+
baseImage?: string;
|
|
3
|
+
nodeVersion?: string;
|
|
4
|
+
layers: number;
|
|
5
|
+
hasMultiStage: boolean;
|
|
6
|
+
hasHealthCheck: boolean;
|
|
7
|
+
hasNonRootUser: boolean;
|
|
8
|
+
hasDockerignore: boolean;
|
|
9
|
+
hasNpmInstallWithoutCi: boolean;
|
|
10
|
+
hasCurlOrWgetWithoutCleanup: boolean;
|
|
11
|
+
instructions: DockerInstruction[];
|
|
12
|
+
stages: string[];
|
|
13
|
+
}
|
|
14
|
+
export interface DockerInstruction {
|
|
15
|
+
line: number;
|
|
16
|
+
instruction: string;
|
|
17
|
+
arguments: string;
|
|
18
|
+
raw: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Analyze a Dockerfile for issues and metrics
|
|
22
|
+
*/
|
|
23
|
+
export declare function analyzeDockerfile(dockerfilePath: string): Promise<DockerfileAnalysis>;
|
|
24
|
+
/**
|
|
25
|
+
* Parse a specific Dockerfile instruction
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseInstruction(line: string): DockerInstruction | null;
|
|
@@ -0,0 +1,122 @@
|
|
|
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.parseInstruction = exports.analyzeDockerfile = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
/**
|
|
10
|
+
* Analyze a Dockerfile for issues and metrics
|
|
11
|
+
*/
|
|
12
|
+
async function analyzeDockerfile(dockerfilePath) {
|
|
13
|
+
const content = fs_1.default.readFileSync(dockerfilePath, "utf-8");
|
|
14
|
+
const lines = content.split("\n");
|
|
15
|
+
const instructions = [];
|
|
16
|
+
const stages = [];
|
|
17
|
+
let hasMultiStage = false;
|
|
18
|
+
let hasHealthCheck = false;
|
|
19
|
+
let hasNonRootUser = false;
|
|
20
|
+
let hasNpmInstallWithoutCi = false;
|
|
21
|
+
let hasCurlOrWgetWithoutCleanup = false;
|
|
22
|
+
let baseImage;
|
|
23
|
+
let nodeVersion;
|
|
24
|
+
let runLayerCount = 0;
|
|
25
|
+
// Parse Dockerfile
|
|
26
|
+
let currentLine = 0;
|
|
27
|
+
for (const line of lines) {
|
|
28
|
+
currentLine++;
|
|
29
|
+
const trimmed = line.trim();
|
|
30
|
+
// Skip comments and empty lines
|
|
31
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
// Parse instruction
|
|
35
|
+
const match = trimmed.match(/^(\w+)\s*(.*)/);
|
|
36
|
+
if (!match)
|
|
37
|
+
continue;
|
|
38
|
+
const instruction = match[1].toUpperCase();
|
|
39
|
+
const args = match[2];
|
|
40
|
+
instructions.push({
|
|
41
|
+
line: currentLine,
|
|
42
|
+
instruction,
|
|
43
|
+
arguments: args,
|
|
44
|
+
raw: trimmed,
|
|
45
|
+
});
|
|
46
|
+
// Analyze instruction
|
|
47
|
+
switch (instruction) {
|
|
48
|
+
case "FROM":
|
|
49
|
+
if (stages.length > 0) {
|
|
50
|
+
hasMultiStage = true;
|
|
51
|
+
}
|
|
52
|
+
stages.push(args);
|
|
53
|
+
// Extract base image info
|
|
54
|
+
if (!baseImage) {
|
|
55
|
+
baseImage = args.split(/\s+/)[0];
|
|
56
|
+
// Try to extract Node version
|
|
57
|
+
const nodeMatch = baseImage.match(/node:(\d+)/);
|
|
58
|
+
if (nodeMatch) {
|
|
59
|
+
nodeVersion = nodeMatch[1];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case "HEALTHCHECK":
|
|
64
|
+
hasHealthCheck = true;
|
|
65
|
+
break;
|
|
66
|
+
case "USER":
|
|
67
|
+
// Check if non-root user
|
|
68
|
+
if (args && args !== "root" && args !== "0") {
|
|
69
|
+
hasNonRootUser = true;
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
case "RUN":
|
|
73
|
+
runLayerCount++;
|
|
74
|
+
// Check for npm install vs npm ci
|
|
75
|
+
if (args.includes("npm install") && !args.includes("npm ci")) {
|
|
76
|
+
hasNpmInstallWithoutCi = true;
|
|
77
|
+
}
|
|
78
|
+
// Check for curl/wget without cleanup
|
|
79
|
+
if ((args.includes("curl") || args.includes("wget")) &&
|
|
80
|
+
!args.includes("rm ")) {
|
|
81
|
+
hasCurlOrWgetWithoutCleanup = true;
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Check for .dockerignore
|
|
87
|
+
const dockerignorePath = path_1.default.join(path_1.default.dirname(dockerfilePath), ".dockerignore");
|
|
88
|
+
const hasDockerignore = fs_1.default.existsSync(dockerignorePath);
|
|
89
|
+
return {
|
|
90
|
+
baseImage,
|
|
91
|
+
nodeVersion,
|
|
92
|
+
layers: runLayerCount,
|
|
93
|
+
hasMultiStage,
|
|
94
|
+
hasHealthCheck,
|
|
95
|
+
hasNonRootUser,
|
|
96
|
+
hasDockerignore,
|
|
97
|
+
hasNpmInstallWithoutCi,
|
|
98
|
+
hasCurlOrWgetWithoutCleanup,
|
|
99
|
+
instructions,
|
|
100
|
+
stages,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
exports.analyzeDockerfile = analyzeDockerfile;
|
|
104
|
+
/**
|
|
105
|
+
* Parse a specific Dockerfile instruction
|
|
106
|
+
*/
|
|
107
|
+
function parseInstruction(line) {
|
|
108
|
+
const trimmed = line.trim();
|
|
109
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const match = trimmed.match(/^(\w+)\s*(.*)/);
|
|
113
|
+
if (!match)
|
|
114
|
+
return null;
|
|
115
|
+
return {
|
|
116
|
+
line: 0,
|
|
117
|
+
instruction: match[1].toUpperCase(),
|
|
118
|
+
arguments: match[2],
|
|
119
|
+
raw: trimmed,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
exports.parseInstruction = parseInstruction;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ImageAnalysis {
|
|
2
|
+
size: string;
|
|
3
|
+
layers: number;
|
|
4
|
+
created: string;
|
|
5
|
+
os: string;
|
|
6
|
+
architecture: string;
|
|
7
|
+
vulnerabilities: Vulnerability[];
|
|
8
|
+
}
|
|
9
|
+
export interface Vulnerability {
|
|
10
|
+
id: string;
|
|
11
|
+
severity: "low" | "medium" | "high" | "critical";
|
|
12
|
+
description: string;
|
|
13
|
+
package?: string;
|
|
14
|
+
fixedVersion?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Analyze a Docker image for size, layers, and vulnerabilities
|
|
18
|
+
*/
|
|
19
|
+
export declare function analyzeImage(imageName: string): Promise<ImageAnalysis>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.analyzeImage = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
/**
|
|
6
|
+
* Analyze a Docker image for size, layers, and vulnerabilities
|
|
7
|
+
*/
|
|
8
|
+
async function analyzeImage(imageName) {
|
|
9
|
+
// Get image inspect data
|
|
10
|
+
let size = "Unknown";
|
|
11
|
+
let layers = 0;
|
|
12
|
+
let created = "Unknown";
|
|
13
|
+
let os = "Unknown";
|
|
14
|
+
let architecture = "Unknown";
|
|
15
|
+
try {
|
|
16
|
+
// Use double quotes for cross-platform compatibility (Windows + Unix)
|
|
17
|
+
const inspectOutput = (0, child_process_1.execSync)(`docker inspect ${imageName} --format "{{.Size}} {{.Created}} {{.Os}} {{.Architecture}}"`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
18
|
+
const parts = inspectOutput.split(" ");
|
|
19
|
+
const sizeBytes = parseInt(parts[0], 10);
|
|
20
|
+
size = formatBytes(sizeBytes);
|
|
21
|
+
created = parts[1] || "Unknown";
|
|
22
|
+
os = parts[2] || "linux";
|
|
23
|
+
architecture = parts[3] || "amd64";
|
|
24
|
+
// Get layer count - cross-platform (count lines in Node.js instead of wc -l)
|
|
25
|
+
const historyOutput = (0, child_process_1.execSync)(`docker history ${imageName} --format "{{.ID}}"`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
26
|
+
layers = historyOutput.split("\n").filter((line) => line.trim()).length;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
// Docker command failed, image might not exist or Docker not running
|
|
30
|
+
throw new Error(`Failed to inspect image: ${imageName}`);
|
|
31
|
+
}
|
|
32
|
+
// Try to scan for vulnerabilities using Trivy if available
|
|
33
|
+
const vulnerabilities = [];
|
|
34
|
+
try {
|
|
35
|
+
// Check if Trivy is available
|
|
36
|
+
(0, child_process_1.execSync)("trivy --version", { stdio: ["pipe", "pipe", "pipe"] });
|
|
37
|
+
// Run Trivy scan
|
|
38
|
+
const trivyOutput = (0, child_process_1.execSync)(`trivy image --format json --severity HIGH,CRITICAL ${imageName}`, {
|
|
39
|
+
encoding: "utf-8",
|
|
40
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
41
|
+
maxBuffer: 50 * 1024 * 1024,
|
|
42
|
+
});
|
|
43
|
+
const trivyResult = JSON.parse(trivyOutput);
|
|
44
|
+
if (trivyResult.Results) {
|
|
45
|
+
for (const result of trivyResult.Results) {
|
|
46
|
+
if (result.Vulnerabilities) {
|
|
47
|
+
for (const vuln of result.Vulnerabilities) {
|
|
48
|
+
vulnerabilities.push({
|
|
49
|
+
id: vuln.VulnerabilityID,
|
|
50
|
+
severity: vuln.Severity?.toLowerCase() || "unknown",
|
|
51
|
+
description: vuln.Title ||
|
|
52
|
+
vuln.Description ||
|
|
53
|
+
"No description",
|
|
54
|
+
package: vuln.PkgName,
|
|
55
|
+
fixedVersion: vuln.FixedVersion,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Trivy not available or scan failed, skip vulnerability scanning
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
size,
|
|
67
|
+
layers,
|
|
68
|
+
created,
|
|
69
|
+
os,
|
|
70
|
+
architecture,
|
|
71
|
+
vulnerabilities,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
exports.analyzeImage = analyzeImage;
|
|
75
|
+
/**
|
|
76
|
+
* Format bytes to human readable string
|
|
77
|
+
*/
|
|
78
|
+
function formatBytes(bytes) {
|
|
79
|
+
if (bytes === 0)
|
|
80
|
+
return "0 B";
|
|
81
|
+
const k = 1024;
|
|
82
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
83
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
84
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
|
85
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.profileCommand = void 0;
|
|
4
|
+
const form_1 = require("./form");
|
|
5
|
+
const cli_ui_1 = require("../utils/cli-ui");
|
|
6
|
+
const profileCommand = () => {
|
|
7
|
+
return {
|
|
8
|
+
command: "profile <action> [target]",
|
|
9
|
+
describe: "Analyze and optimize container configurations.",
|
|
10
|
+
aliases: ["prof", "analyze"],
|
|
11
|
+
builder: (yargs) => {
|
|
12
|
+
yargs.positional("action", {
|
|
13
|
+
choices: ["container", "image", "optimize", "report"],
|
|
14
|
+
describe: "Action to perform",
|
|
15
|
+
type: "string",
|
|
16
|
+
demandOption: true,
|
|
17
|
+
});
|
|
18
|
+
yargs.positional("target", {
|
|
19
|
+
describe: "Target to analyze (Dockerfile path or image name)",
|
|
20
|
+
type: "string",
|
|
21
|
+
});
|
|
22
|
+
yargs.option("dockerfile", {
|
|
23
|
+
describe: "Path to Dockerfile",
|
|
24
|
+
type: "string",
|
|
25
|
+
alias: "f",
|
|
26
|
+
default: "Dockerfile",
|
|
27
|
+
});
|
|
28
|
+
yargs.option("format", {
|
|
29
|
+
choices: ["text", "json", "html"],
|
|
30
|
+
describe: "Output format",
|
|
31
|
+
type: "string",
|
|
32
|
+
default: "text",
|
|
33
|
+
});
|
|
34
|
+
yargs.option("severity", {
|
|
35
|
+
choices: ["low", "medium", "high", "critical"],
|
|
36
|
+
describe: "Minimum severity to report",
|
|
37
|
+
type: "string",
|
|
38
|
+
default: "low",
|
|
39
|
+
});
|
|
40
|
+
yargs.option("auto-fix", {
|
|
41
|
+
describe: "Automatically apply safe optimizations",
|
|
42
|
+
type: "boolean",
|
|
43
|
+
default: false,
|
|
44
|
+
});
|
|
45
|
+
yargs.option("output", {
|
|
46
|
+
describe: "Output file for report",
|
|
47
|
+
type: "string",
|
|
48
|
+
alias: "o",
|
|
49
|
+
});
|
|
50
|
+
yargs.option("include-security", {
|
|
51
|
+
describe: "Include security vulnerability scanning",
|
|
52
|
+
type: "boolean",
|
|
53
|
+
default: true,
|
|
54
|
+
});
|
|
55
|
+
yargs.option("include-size", {
|
|
56
|
+
describe: "Include size analysis",
|
|
57
|
+
type: "boolean",
|
|
58
|
+
default: true,
|
|
59
|
+
});
|
|
60
|
+
return yargs;
|
|
61
|
+
},
|
|
62
|
+
handler: async (argv) => {
|
|
63
|
+
const { action, target, dockerfile, format, severity, autoFix, output, includeSecurity, includeSize, } = argv;
|
|
64
|
+
const options = {
|
|
65
|
+
target: target,
|
|
66
|
+
dockerfile,
|
|
67
|
+
format: format,
|
|
68
|
+
severity: severity,
|
|
69
|
+
autoFix,
|
|
70
|
+
output,
|
|
71
|
+
includeSecurity,
|
|
72
|
+
includeSize,
|
|
73
|
+
};
|
|
74
|
+
switch (action) {
|
|
75
|
+
case "container":
|
|
76
|
+
await (0, form_1.profileContainer)(options);
|
|
77
|
+
break;
|
|
78
|
+
case "image":
|
|
79
|
+
await (0, form_1.profileImage)(options);
|
|
80
|
+
break;
|
|
81
|
+
case "optimize":
|
|
82
|
+
await (0, form_1.optimizeContainer)(options);
|
|
83
|
+
break;
|
|
84
|
+
case "report":
|
|
85
|
+
await (0, form_1.showProfileReport)(options);
|
|
86
|
+
break;
|
|
87
|
+
default:
|
|
88
|
+
(0, cli_ui_1.printError)(`Unknown action: ${action}`, "profile");
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
exports.profileCommand = profileCommand;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export interface ProfileOptions {
|
|
2
|
+
target?: string;
|
|
3
|
+
dockerfile: string;
|
|
4
|
+
format: "text" | "json" | "html";
|
|
5
|
+
severity: "low" | "medium" | "high" | "critical";
|
|
6
|
+
autoFix: boolean;
|
|
7
|
+
output?: string;
|
|
8
|
+
includeSecurity: boolean;
|
|
9
|
+
includeSize: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface ProfileResult {
|
|
12
|
+
score: number;
|
|
13
|
+
issues: Issue[];
|
|
14
|
+
recommendations: Recommendation[];
|
|
15
|
+
metrics: Metrics;
|
|
16
|
+
}
|
|
17
|
+
export interface Issue {
|
|
18
|
+
id: string;
|
|
19
|
+
severity: "low" | "medium" | "high" | "critical";
|
|
20
|
+
category: "security" | "size" | "performance" | "best-practice";
|
|
21
|
+
message: string;
|
|
22
|
+
line?: number;
|
|
23
|
+
fix?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface Recommendation {
|
|
26
|
+
priority: "low" | "medium" | "high";
|
|
27
|
+
category: string;
|
|
28
|
+
title: string;
|
|
29
|
+
description: string;
|
|
30
|
+
impact: string;
|
|
31
|
+
}
|
|
32
|
+
export interface Metrics {
|
|
33
|
+
estimatedSize?: string;
|
|
34
|
+
layers?: number;
|
|
35
|
+
baseImage?: string;
|
|
36
|
+
nodeVersion?: string;
|
|
37
|
+
hasMultiStage?: boolean;
|
|
38
|
+
hasHealthCheck?: boolean;
|
|
39
|
+
hasNonRootUser?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Profile a Dockerfile for issues and recommendations
|
|
43
|
+
*/
|
|
44
|
+
export declare function profileContainer(options: ProfileOptions): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Profile a built Docker image
|
|
47
|
+
*/
|
|
48
|
+
export declare function profileImage(options: ProfileOptions): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Generate and optionally apply optimizations
|
|
51
|
+
*/
|
|
52
|
+
export declare function optimizeContainer(options: ProfileOptions): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Show a comprehensive profile report
|
|
55
|
+
*/
|
|
56
|
+
export declare function showProfileReport(options: ProfileOptions): Promise<void>;
|