@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,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Remote JSON pricing source - fetches from GitHub-hosted pricing file
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.createRemoteJSONPricingSource = exports.RemoteJSONPricingSource = void 0;
|
|
10
|
+
const https_1 = __importDefault(require("https"));
|
|
11
|
+
const DEFAULT_URL = "https://raw.githubusercontent.com/expressots/pricing/main/pricing.json";
|
|
12
|
+
const FETCH_TIMEOUT = 10000;
|
|
13
|
+
class RemoteJSONPricingSource {
|
|
14
|
+
constructor(url) {
|
|
15
|
+
this.name = "remote";
|
|
16
|
+
this.url = url || DEFAULT_URL;
|
|
17
|
+
}
|
|
18
|
+
async fetch() {
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
const request = https_1.default.get(this.url, { timeout: FETCH_TIMEOUT }, (response) => {
|
|
21
|
+
if (response.statusCode !== 200) {
|
|
22
|
+
resolve(null);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
let data = "";
|
|
26
|
+
response.on("data", (chunk) => {
|
|
27
|
+
data += chunk;
|
|
28
|
+
});
|
|
29
|
+
response.on("end", () => {
|
|
30
|
+
try {
|
|
31
|
+
const pricing = JSON.parse(data);
|
|
32
|
+
resolve(pricing);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
resolve(null);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
request.on("error", () => {
|
|
40
|
+
resolve(null);
|
|
41
|
+
});
|
|
42
|
+
request.on("timeout", () => {
|
|
43
|
+
request.destroy();
|
|
44
|
+
resolve(null);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.RemoteJSONPricingSource = RemoteJSONPricingSource;
|
|
50
|
+
function createRemoteJSONPricingSource(url) {
|
|
51
|
+
return new RemoteJSONPricingSource(url);
|
|
52
|
+
}
|
|
53
|
+
exports.createRemoteJSONPricingSource = createRemoteJSONPricingSource;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pricing types and interfaces
|
|
3
|
+
*/
|
|
4
|
+
export type CloudProvider = "aws" | "gcp" | "azure" | "railway" | "render" | "fly" | "digitalocean" | "heroku";
|
|
5
|
+
export type PricingModel = "per-hour" | "per-month" | "usage";
|
|
6
|
+
export interface ProviderPricing {
|
|
7
|
+
serviceName: string;
|
|
8
|
+
model: PricingModel;
|
|
9
|
+
basePrice: number;
|
|
10
|
+
cpuPerHour: number;
|
|
11
|
+
memoryPerGbHour: number;
|
|
12
|
+
storagePerGb: number;
|
|
13
|
+
bandwidthPerGb: number;
|
|
14
|
+
freeBandwidth: number;
|
|
15
|
+
freeCredits?: number;
|
|
16
|
+
notes?: string;
|
|
17
|
+
source?: string;
|
|
18
|
+
lastVerified?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface PricingData {
|
|
21
|
+
version: string;
|
|
22
|
+
updated: string;
|
|
23
|
+
providers: Record<CloudProvider, ProviderPricing>;
|
|
24
|
+
}
|
|
25
|
+
export interface PricingSource {
|
|
26
|
+
name: string;
|
|
27
|
+
fetch(): Promise<PricingData | null>;
|
|
28
|
+
}
|
|
29
|
+
export interface ResourceEstimate {
|
|
30
|
+
instances: number;
|
|
31
|
+
cpu: number;
|
|
32
|
+
memory: number;
|
|
33
|
+
storage: number;
|
|
34
|
+
bandwidth: number;
|
|
35
|
+
hours: number;
|
|
36
|
+
}
|
|
37
|
+
export interface CostEstimate {
|
|
38
|
+
provider: CloudProvider;
|
|
39
|
+
monthlyCost: number;
|
|
40
|
+
breakdown: {
|
|
41
|
+
compute: number;
|
|
42
|
+
storage: number;
|
|
43
|
+
bandwidth: number;
|
|
44
|
+
base: number;
|
|
45
|
+
};
|
|
46
|
+
currency: string;
|
|
47
|
+
notes?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface PricingCacheEntry {
|
|
50
|
+
data: PricingData;
|
|
51
|
+
timestamp: number;
|
|
52
|
+
source: string;
|
|
53
|
+
}
|
package/bin/dev/cli.d.ts
ADDED
package/bin/dev/cli.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.devContainerCommand = void 0;
|
|
4
|
+
const form_1 = require("./form");
|
|
5
|
+
const devContainerCommand = () => {
|
|
6
|
+
return {
|
|
7
|
+
command: "container-dev [action]",
|
|
8
|
+
describe: "Develop inside Docker containers with hot reload.",
|
|
9
|
+
aliases: ["cdev", "docker-dev"],
|
|
10
|
+
builder: (yargs) => {
|
|
11
|
+
yargs.positional("action", {
|
|
12
|
+
choices: [
|
|
13
|
+
"start",
|
|
14
|
+
"stop",
|
|
15
|
+
"attach",
|
|
16
|
+
"shell",
|
|
17
|
+
"status",
|
|
18
|
+
"logs",
|
|
19
|
+
],
|
|
20
|
+
describe: "Action to perform",
|
|
21
|
+
type: "string",
|
|
22
|
+
default: "start",
|
|
23
|
+
});
|
|
24
|
+
yargs.option("container", {
|
|
25
|
+
describe: "Run development in Docker container",
|
|
26
|
+
type: "boolean",
|
|
27
|
+
alias: "c",
|
|
28
|
+
default: false,
|
|
29
|
+
});
|
|
30
|
+
yargs.option("service", {
|
|
31
|
+
describe: "Docker Compose service name",
|
|
32
|
+
type: "string",
|
|
33
|
+
alias: "s",
|
|
34
|
+
default: "app",
|
|
35
|
+
});
|
|
36
|
+
yargs.option("compose-file", {
|
|
37
|
+
describe: "Path to docker-compose file",
|
|
38
|
+
type: "string",
|
|
39
|
+
alias: "f",
|
|
40
|
+
default: "docker-compose.development.yml",
|
|
41
|
+
});
|
|
42
|
+
yargs.option("build", {
|
|
43
|
+
describe: "Rebuild container before starting",
|
|
44
|
+
type: "boolean",
|
|
45
|
+
alias: "b",
|
|
46
|
+
default: false,
|
|
47
|
+
});
|
|
48
|
+
yargs.option("detach", {
|
|
49
|
+
describe: "Run in background",
|
|
50
|
+
type: "boolean",
|
|
51
|
+
alias: "d",
|
|
52
|
+
default: false,
|
|
53
|
+
});
|
|
54
|
+
yargs.option("port", {
|
|
55
|
+
describe: "Override application port",
|
|
56
|
+
type: "number",
|
|
57
|
+
alias: "p",
|
|
58
|
+
});
|
|
59
|
+
yargs.option("debug-port", {
|
|
60
|
+
describe: "Debug port for Node.js inspector",
|
|
61
|
+
type: "number",
|
|
62
|
+
default: 9229,
|
|
63
|
+
});
|
|
64
|
+
yargs.option("watch", {
|
|
65
|
+
describe: "Enable file watching for hot reload",
|
|
66
|
+
type: "boolean",
|
|
67
|
+
alias: "w",
|
|
68
|
+
default: true,
|
|
69
|
+
});
|
|
70
|
+
yargs.option("follow", {
|
|
71
|
+
describe: "Follow logs (for logs action)",
|
|
72
|
+
type: "boolean",
|
|
73
|
+
default: true,
|
|
74
|
+
});
|
|
75
|
+
yargs.option("tail", {
|
|
76
|
+
describe: "Number of log lines to show",
|
|
77
|
+
type: "number",
|
|
78
|
+
default: 100,
|
|
79
|
+
});
|
|
80
|
+
return yargs;
|
|
81
|
+
},
|
|
82
|
+
handler: async (argv) => {
|
|
83
|
+
const { action, container, service, composeFile, build, detach, port, debugPort, watch, follow, tail, } = argv;
|
|
84
|
+
const options = {
|
|
85
|
+
container,
|
|
86
|
+
service,
|
|
87
|
+
composeFile,
|
|
88
|
+
build,
|
|
89
|
+
detach,
|
|
90
|
+
port,
|
|
91
|
+
debugPort,
|
|
92
|
+
watch,
|
|
93
|
+
follow,
|
|
94
|
+
tail,
|
|
95
|
+
};
|
|
96
|
+
// If --container flag is set without action, start container dev
|
|
97
|
+
if (container && action === "start") {
|
|
98
|
+
await (0, form_1.startDevContainer)(options);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
switch (action) {
|
|
102
|
+
case "start":
|
|
103
|
+
if (container) {
|
|
104
|
+
await (0, form_1.startDevContainer)(options);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// Regular dev command (non-container) - delegate to existing
|
|
108
|
+
console.log("Starting local development...");
|
|
109
|
+
console.log("Use --container flag to develop inside Docker.");
|
|
110
|
+
console.log("Or run: npm run dev");
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
case "stop":
|
|
114
|
+
await (0, form_1.stopDevContainer)(options);
|
|
115
|
+
break;
|
|
116
|
+
case "attach":
|
|
117
|
+
await (0, form_1.attachToContainer)(options);
|
|
118
|
+
break;
|
|
119
|
+
case "shell":
|
|
120
|
+
await (0, form_1.openShell)(options);
|
|
121
|
+
break;
|
|
122
|
+
case "status":
|
|
123
|
+
await (0, form_1.showStatus)(options);
|
|
124
|
+
break;
|
|
125
|
+
case "logs":
|
|
126
|
+
await (0, form_1.showLogs)(options);
|
|
127
|
+
break;
|
|
128
|
+
default:
|
|
129
|
+
console.log(`Unknown action: ${action}`);
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
exports.devContainerCommand = devContainerCommand;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface DevOptions {
|
|
2
|
+
container: boolean;
|
|
3
|
+
service: string;
|
|
4
|
+
composeFile: string;
|
|
5
|
+
build: boolean;
|
|
6
|
+
detach: boolean;
|
|
7
|
+
port?: number;
|
|
8
|
+
debugPort: number;
|
|
9
|
+
watch: boolean;
|
|
10
|
+
follow: boolean;
|
|
11
|
+
tail: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Start development container with hot reload
|
|
15
|
+
*/
|
|
16
|
+
export declare function startDevContainer(options: DevOptions): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Stop development containers
|
|
19
|
+
*/
|
|
20
|
+
export declare function stopDevContainer(options: DevOptions): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Attach to running container
|
|
23
|
+
*/
|
|
24
|
+
export declare function attachToContainer(options: DevOptions): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Open shell in container
|
|
27
|
+
*/
|
|
28
|
+
export declare function openShell(options: DevOptions): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Show status of development containers
|
|
31
|
+
*/
|
|
32
|
+
export declare function showStatus(options: DevOptions): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Show container logs
|
|
35
|
+
*/
|
|
36
|
+
export declare function showLogs(options: DevOptions): Promise<void>;
|
package/bin/dev/form.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
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.showLogs = exports.showStatus = exports.openShell = exports.attachToContainer = exports.stopDevContainer = exports.startDevContainer = 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 child_process_1 = require("child_process");
|
|
11
|
+
/**
|
|
12
|
+
* Start development container with hot reload
|
|
13
|
+
*/
|
|
14
|
+
async function startDevContainer(options) {
|
|
15
|
+
console.log(chalk_1.default.cyan("\n🐳 ExpressoTS Container Development\n"));
|
|
16
|
+
const cwd = process.cwd();
|
|
17
|
+
const composeFile = path_1.default.join(cwd, options.composeFile);
|
|
18
|
+
// Check if docker-compose file exists
|
|
19
|
+
if (!fs_1.default.existsSync(composeFile)) {
|
|
20
|
+
console.log(chalk_1.default.yellow(`⚠️ ${options.composeFile} not found.`));
|
|
21
|
+
console.log(chalk_1.default.gray("Generating development Docker configuration..."));
|
|
22
|
+
// Try to generate if containerize is available
|
|
23
|
+
console.log(chalk_1.default.gray("\nRun the following to generate development config:"));
|
|
24
|
+
console.log(chalk_1.default.white(` expressots containerize docker --env development`));
|
|
25
|
+
console.log();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// Check if Docker is running
|
|
29
|
+
if (!isDockerRunning()) {
|
|
30
|
+
console.log(chalk_1.default.red("Error: Docker is not running."));
|
|
31
|
+
console.log(chalk_1.default.gray("Please start Docker Desktop or Docker daemon."));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
console.log(chalk_1.default.yellow(`📄 Using ${options.composeFile}`));
|
|
35
|
+
// Build arguments
|
|
36
|
+
const args = ["-f", composeFile];
|
|
37
|
+
if (options.build) {
|
|
38
|
+
console.log(chalk_1.default.yellow("🔨 Building containers..."));
|
|
39
|
+
runDockerCompose([...args, "build"], { cwd });
|
|
40
|
+
}
|
|
41
|
+
// Start containers
|
|
42
|
+
console.log(chalk_1.default.yellow("🚀 Starting development containers..."));
|
|
43
|
+
const upArgs = [...args, "up"];
|
|
44
|
+
if (options.detach) {
|
|
45
|
+
upArgs.push("-d");
|
|
46
|
+
}
|
|
47
|
+
// Set environment variables
|
|
48
|
+
const env = {
|
|
49
|
+
...process.env,
|
|
50
|
+
};
|
|
51
|
+
if (options.port) {
|
|
52
|
+
env.PORT = String(options.port);
|
|
53
|
+
}
|
|
54
|
+
env.DEBUG_PORT = String(options.debugPort);
|
|
55
|
+
if (options.detach) {
|
|
56
|
+
runDockerCompose(upArgs, { cwd, env });
|
|
57
|
+
console.log(chalk_1.default.green("\n✅ Development containers started in background.\n"));
|
|
58
|
+
printDevInfo(options);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
console.log(chalk_1.default.green("\n✅ Starting development environment...\n"));
|
|
62
|
+
printDevInfo(options);
|
|
63
|
+
console.log(chalk_1.default.gray("Press Ctrl+C to stop\n"));
|
|
64
|
+
// Run in foreground
|
|
65
|
+
spawnDockerCompose(upArgs, { cwd, env, stdio: "inherit" });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.startDevContainer = startDevContainer;
|
|
69
|
+
/**
|
|
70
|
+
* Stop development containers
|
|
71
|
+
*/
|
|
72
|
+
async function stopDevContainer(options) {
|
|
73
|
+
console.log(chalk_1.default.cyan("\n🛑 Stopping development containers...\n"));
|
|
74
|
+
const cwd = process.cwd();
|
|
75
|
+
const composeFile = path_1.default.join(cwd, options.composeFile);
|
|
76
|
+
if (!fs_1.default.existsSync(composeFile)) {
|
|
77
|
+
// Try default compose file
|
|
78
|
+
const defaultCompose = path_1.default.join(cwd, "docker-compose.yml");
|
|
79
|
+
if (fs_1.default.existsSync(defaultCompose)) {
|
|
80
|
+
runDockerCompose(["-f", defaultCompose, "down"], { cwd });
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.log(chalk_1.default.yellow("No docker-compose file found."));
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
runDockerCompose(["-f", composeFile, "down"], { cwd });
|
|
88
|
+
console.log(chalk_1.default.green("✅ Development containers stopped."));
|
|
89
|
+
}
|
|
90
|
+
exports.stopDevContainer = stopDevContainer;
|
|
91
|
+
/**
|
|
92
|
+
* Attach to running container
|
|
93
|
+
*/
|
|
94
|
+
async function attachToContainer(options) {
|
|
95
|
+
console.log(chalk_1.default.cyan(`\n🔗 Attaching to ${options.service}...\n`));
|
|
96
|
+
const cwd = process.cwd();
|
|
97
|
+
const composeFile = path_1.default.join(cwd, options.composeFile);
|
|
98
|
+
if (!fs_1.default.existsSync(composeFile)) {
|
|
99
|
+
console.log(chalk_1.default.red(`Error: ${options.composeFile} not found.`));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
spawnDockerCompose(["-f", composeFile, "attach", options.service], {
|
|
103
|
+
cwd,
|
|
104
|
+
stdio: "inherit",
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
exports.attachToContainer = attachToContainer;
|
|
108
|
+
/**
|
|
109
|
+
* Open shell in container
|
|
110
|
+
*/
|
|
111
|
+
async function openShell(options) {
|
|
112
|
+
console.log(chalk_1.default.cyan(`\n🐚 Opening shell in ${options.service}...\n`));
|
|
113
|
+
const cwd = process.cwd();
|
|
114
|
+
const composeFile = path_1.default.join(cwd, options.composeFile);
|
|
115
|
+
if (!fs_1.default.existsSync(composeFile)) {
|
|
116
|
+
console.log(chalk_1.default.red(`Error: ${options.composeFile} not found.`));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// Try sh first (Alpine), fall back to bash
|
|
120
|
+
spawnDockerCompose(["-f", composeFile, "exec", options.service, "sh"], {
|
|
121
|
+
cwd,
|
|
122
|
+
stdio: "inherit",
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
exports.openShell = openShell;
|
|
126
|
+
/**
|
|
127
|
+
* Show status of development containers
|
|
128
|
+
*/
|
|
129
|
+
async function showStatus(options) {
|
|
130
|
+
console.log(chalk_1.default.cyan("\n📊 Development Container Status\n"));
|
|
131
|
+
const cwd = process.cwd();
|
|
132
|
+
const composeFile = path_1.default.join(cwd, options.composeFile);
|
|
133
|
+
if (!fs_1.default.existsSync(composeFile)) {
|
|
134
|
+
// Try default compose
|
|
135
|
+
const defaultCompose = path_1.default.join(cwd, "docker-compose.yml");
|
|
136
|
+
if (fs_1.default.existsSync(defaultCompose)) {
|
|
137
|
+
runDockerCompose(["-f", defaultCompose, "ps"], { cwd });
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
console.log(chalk_1.default.yellow("No docker-compose file found."));
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
runDockerCompose(["-f", composeFile, "ps"], { cwd });
|
|
145
|
+
// Show resource usage
|
|
146
|
+
console.log(chalk_1.default.bold("\nResource Usage:"));
|
|
147
|
+
try {
|
|
148
|
+
// Use double quotes for cross-platform compatibility (Windows + Unix)
|
|
149
|
+
const output = (0, child_process_1.execSync)('docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"', {
|
|
150
|
+
encoding: "utf-8",
|
|
151
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
152
|
+
});
|
|
153
|
+
console.log(output);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
console.log(chalk_1.default.gray(" Unable to get resource stats"));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
exports.showStatus = showStatus;
|
|
160
|
+
/**
|
|
161
|
+
* Show container logs
|
|
162
|
+
*/
|
|
163
|
+
async function showLogs(options) {
|
|
164
|
+
console.log(chalk_1.default.cyan(`\n📜 Logs for ${options.service}\n`));
|
|
165
|
+
const cwd = process.cwd();
|
|
166
|
+
const composeFile = path_1.default.join(cwd, options.composeFile);
|
|
167
|
+
if (!fs_1.default.existsSync(composeFile)) {
|
|
168
|
+
console.log(chalk_1.default.red(`Error: ${options.composeFile} not found.`));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const args = ["-f", composeFile, "logs"];
|
|
172
|
+
if (options.follow) {
|
|
173
|
+
args.push("-f");
|
|
174
|
+
}
|
|
175
|
+
args.push("--tail", String(options.tail));
|
|
176
|
+
args.push(options.service);
|
|
177
|
+
spawnDockerCompose(args, { cwd, stdio: "inherit" });
|
|
178
|
+
}
|
|
179
|
+
exports.showLogs = showLogs;
|
|
180
|
+
/**
|
|
181
|
+
* Check if Docker is running
|
|
182
|
+
*/
|
|
183
|
+
function isDockerRunning() {
|
|
184
|
+
try {
|
|
185
|
+
(0, child_process_1.execSync)("docker info", { stdio: ["pipe", "pipe", "pipe"] });
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Run docker-compose command synchronously
|
|
194
|
+
*/
|
|
195
|
+
function runDockerCompose(args, options) {
|
|
196
|
+
try {
|
|
197
|
+
// Try docker compose (v2) first
|
|
198
|
+
(0, child_process_1.execSync)(`docker compose ${args.join(" ")}`, {
|
|
199
|
+
cwd: options.cwd,
|
|
200
|
+
env: options.env || process.env,
|
|
201
|
+
stdio: "inherit",
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
// Fall back to docker-compose (v1)
|
|
206
|
+
try {
|
|
207
|
+
(0, child_process_1.execSync)(`docker-compose ${args.join(" ")}`, {
|
|
208
|
+
cwd: options.cwd,
|
|
209
|
+
env: options.env || process.env,
|
|
210
|
+
stdio: "inherit",
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
console.log(chalk_1.default.red("Error running docker-compose"));
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Spawn docker-compose command (for interactive/streaming)
|
|
221
|
+
*/
|
|
222
|
+
function spawnDockerCompose(args, options) {
|
|
223
|
+
// Try docker compose (v2) first
|
|
224
|
+
const proc = (0, child_process_1.spawn)("docker", ["compose", ...args], {
|
|
225
|
+
...options,
|
|
226
|
+
shell: true,
|
|
227
|
+
});
|
|
228
|
+
proc.on("error", () => {
|
|
229
|
+
// Fall back to docker-compose (v1)
|
|
230
|
+
(0, child_process_1.spawn)("docker-compose", args, {
|
|
231
|
+
...options,
|
|
232
|
+
shell: true,
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Print development info
|
|
238
|
+
*/
|
|
239
|
+
function printDevInfo(options) {
|
|
240
|
+
console.log(chalk_1.default.bold("Development Environment:"));
|
|
241
|
+
console.log(` 🌐 App: http://localhost:${options.port || 3000}`);
|
|
242
|
+
console.log(` 🔍 Debug: localhost:${options.debugPort}`);
|
|
243
|
+
console.log(` 📁 Service: ${options.service}`);
|
|
244
|
+
console.log();
|
|
245
|
+
console.log(chalk_1.default.bold("Available Commands:"));
|
|
246
|
+
console.log(` ${chalk_1.default.gray("expressots container-dev status")} Show container status`);
|
|
247
|
+
console.log(` ${chalk_1.default.gray("expressots container-dev logs")} View logs`);
|
|
248
|
+
console.log(` ${chalk_1.default.gray("expressots container-dev shell")} Open shell in container`);
|
|
249
|
+
console.log(` ${chalk_1.default.gray("expressots container-dev stop")} Stop containers`);
|
|
250
|
+
console.log();
|
|
251
|
+
if (options.watch) {
|
|
252
|
+
console.log(chalk_1.default.green("🔄 Hot reload is enabled - edit files to see changes"));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { devContainerCommand } from "./cli";
|
package/bin/dev/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.devContainerCommand = void 0;
|
|
4
|
+
var cli_1 = require("./cli");
|
|
5
|
+
Object.defineProperty(exports, "devContainerCommand", { enumerable: true, get: function () { return cli_1.devContainerCommand; } });
|
package/bin/generate/cli.js
CHANGED
|
@@ -20,6 +20,17 @@ const coerceSchematicAliases = (arg) => {
|
|
|
20
20
|
return "module";
|
|
21
21
|
case "mi":
|
|
22
22
|
return "middleware";
|
|
23
|
+
// NEW v4.0 schematics
|
|
24
|
+
case "i":
|
|
25
|
+
return "interceptor";
|
|
26
|
+
case "ev":
|
|
27
|
+
return "event";
|
|
28
|
+
case "h":
|
|
29
|
+
return "handler";
|
|
30
|
+
case "gu":
|
|
31
|
+
return "guard";
|
|
32
|
+
case "cfg":
|
|
33
|
+
return "config";
|
|
23
34
|
default:
|
|
24
35
|
return arg;
|
|
25
36
|
}
|
|
@@ -40,6 +51,12 @@ const generateProject = () => {
|
|
|
40
51
|
"entity",
|
|
41
52
|
"module",
|
|
42
53
|
"middleware",
|
|
54
|
+
// NEW v4.0 schematics
|
|
55
|
+
"interceptor",
|
|
56
|
+
"event",
|
|
57
|
+
"handler",
|
|
58
|
+
"guard",
|
|
59
|
+
"config",
|
|
43
60
|
],
|
|
44
61
|
describe: "The schematic to generate",
|
|
45
62
|
type: "string",
|
|
@@ -56,10 +73,20 @@ const generateProject = () => {
|
|
|
56
73
|
type: "string",
|
|
57
74
|
alias: "m",
|
|
58
75
|
});
|
|
76
|
+
// NEW: Options for v4.0 schematics
|
|
77
|
+
yargs.option("event", {
|
|
78
|
+
describe: "Event class name for handler generation",
|
|
79
|
+
type: "string",
|
|
80
|
+
});
|
|
81
|
+
yargs.option("priority", {
|
|
82
|
+
describe: "Priority for interceptors/handlers (lower = earlier execution)",
|
|
83
|
+
type: "number",
|
|
84
|
+
default: 10,
|
|
85
|
+
});
|
|
59
86
|
return yargs;
|
|
60
87
|
},
|
|
61
|
-
handler: async ({ schematic, path, method }) => {
|
|
62
|
-
await (0, form_1.createTemplate)({ schematic, path, method });
|
|
88
|
+
handler: async ({ schematic, path, method, event, priority }) => {
|
|
89
|
+
await (0, form_1.createTemplate)({ schematic, path, method, event, priority });
|
|
63
90
|
},
|
|
64
91
|
};
|
|
65
92
|
};
|
package/bin/generate/form.d.ts
CHANGED
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
* @param schematic
|
|
4
4
|
* @param path
|
|
5
5
|
* @param method
|
|
6
|
+
* @param event - Event class name (for handler generation)
|
|
7
|
+
* @param priority - Priority for interceptors/handlers
|
|
6
8
|
*/
|
|
7
9
|
type CreateTemplateProps = {
|
|
8
10
|
schematic: string;
|
|
9
11
|
path: string;
|
|
10
12
|
method: string;
|
|
13
|
+
event?: string;
|
|
14
|
+
priority?: number;
|
|
11
15
|
};
|
|
12
16
|
/**
|
|
13
17
|
* Create a template based on the schematic
|
|
@@ -16,5 +20,5 @@ type CreateTemplateProps = {
|
|
|
16
20
|
* @param method - the http method
|
|
17
21
|
* @returns the file created
|
|
18
22
|
*/
|
|
19
|
-
export declare const createTemplate: ({ schematic, path: target, method, }: CreateTemplateProps) => Promise<string>;
|
|
23
|
+
export declare const createTemplate: ({ schematic, path: target, method, event, priority, }: CreateTemplateProps) => Promise<string>;
|
|
20
24
|
export {};
|
package/bin/generate/form.js
CHANGED
|
@@ -15,15 +15,15 @@ const opinionated_cmd_1 = require("./utils/opinionated-cmd");
|
|
|
15
15
|
* @param method - the http method
|
|
16
16
|
* @returns the file created
|
|
17
17
|
*/
|
|
18
|
-
const createTemplate = async ({ schematic, path: target, method, }) => {
|
|
18
|
+
const createTemplate = async ({ schematic, path: target, method, event, priority = 10, }) => {
|
|
19
19
|
const config = await compiler_1.default.loadConfig();
|
|
20
20
|
const pathStyle = (0, command_utils_1.checkPathStyle)(target);
|
|
21
21
|
let returnFile = "";
|
|
22
22
|
if (config.opinionated) {
|
|
23
|
-
returnFile = await (0, opinionated_cmd_1.opinionatedProcess)(schematic, target, method, config, pathStyle);
|
|
23
|
+
returnFile = await (0, opinionated_cmd_1.opinionatedProcess)(schematic, target, method, config, pathStyle, { event, priority });
|
|
24
24
|
}
|
|
25
25
|
else {
|
|
26
|
-
returnFile = await (0, nonopininated_cmd_1.nonOpinionatedProcess)(schematic, target, method, config);
|
|
26
|
+
returnFile = await (0, nonopininated_cmd_1.nonOpinionatedProcess)(schematic, target, method, config, { event, priority });
|
|
27
27
|
}
|
|
28
28
|
return returnFile;
|
|
29
29
|
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig, Env, loadEnvSync } from "@expressots/core";
|
|
2
|
+
|
|
3
|
+
loadEnvSync({ files: { development: ".env.local", production: ".env.prod" } });
|
|
4
|
+
|
|
5
|
+
export const {{moduleName}}Config = defineConfig({
|
|
6
|
+
enabled: Env.boolean("{{envPrefix}}_ENABLED", { default: true }),
|
|
7
|
+
// Add more config options as needed
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const config = {{moduleName}}Config.values;
|
|
11
|
+
export type {{className}}Config = typeof config;
|
|
12
|
+
|