@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.
Files changed (180) hide show
  1. package/README.md +41 -95
  2. package/bin/cicd/cli.d.ts +6 -0
  3. package/bin/cicd/cli.js +126 -0
  4. package/bin/cicd/form.d.ts +29 -0
  5. package/bin/cicd/form.js +345 -0
  6. package/bin/cicd/generators/azure-devops.d.ts +2 -0
  7. package/bin/cicd/generators/azure-devops.js +370 -0
  8. package/bin/cicd/generators/bitbucket.d.ts +2 -0
  9. package/bin/cicd/generators/bitbucket.js +217 -0
  10. package/bin/cicd/generators/circleci.d.ts +2 -0
  11. package/bin/cicd/generators/circleci.js +274 -0
  12. package/bin/cicd/generators/github-actions.d.ts +14 -0
  13. package/bin/cicd/generators/github-actions.js +426 -0
  14. package/bin/cicd/generators/gitlab-ci.d.ts +2 -0
  15. package/bin/cicd/generators/gitlab-ci.js +237 -0
  16. package/bin/cicd/generators/index.d.ts +6 -0
  17. package/bin/cicd/generators/index.js +15 -0
  18. package/bin/cicd/generators/jenkins.d.ts +2 -0
  19. package/bin/cicd/generators/jenkins.js +248 -0
  20. package/bin/cicd/generators/template-loader.d.ts +17 -0
  21. package/bin/cicd/generators/template-loader.js +128 -0
  22. package/bin/cicd/index.d.ts +1 -0
  23. package/bin/cicd/index.js +5 -0
  24. package/bin/cli.d.ts +1 -1
  25. package/bin/cli.js +18 -3
  26. package/bin/commands/project.commands.d.ts +19 -6
  27. package/bin/commands/project.commands.js +390 -61
  28. package/bin/config/index.d.ts +5 -0
  29. package/bin/config/index.js +10 -0
  30. package/bin/config/manager.d.ts +98 -0
  31. package/bin/config/manager.js +222 -0
  32. package/bin/containerize/analyzers/bootstrap-analyzer.d.ts +46 -0
  33. package/bin/containerize/analyzers/bootstrap-analyzer.js +187 -0
  34. package/bin/containerize/analyzers/project-analyzer.d.ts +20 -0
  35. package/bin/containerize/analyzers/project-analyzer.js +150 -0
  36. package/bin/containerize/cli.d.ts +4 -0
  37. package/bin/containerize/cli.js +113 -0
  38. package/bin/containerize/form.d.ts +15 -0
  39. package/bin/containerize/form.js +154 -0
  40. package/bin/containerize/generators/ci-generator.d.ts +31 -0
  41. package/bin/containerize/generators/ci-generator.js +936 -0
  42. package/bin/containerize/generators/docker-compose-generator.d.ts +8 -0
  43. package/bin/containerize/generators/docker-compose-generator.js +186 -0
  44. package/bin/containerize/generators/dockerfile-generator.d.ts +8 -0
  45. package/bin/containerize/generators/dockerfile-generator.js +635 -0
  46. package/bin/containerize/generators/kubernetes-generator.d.ts +8 -0
  47. package/bin/containerize/generators/kubernetes-generator.js +133 -0
  48. package/bin/containerize/generators/template-loader.d.ts +36 -0
  49. package/bin/containerize/generators/template-loader.js +129 -0
  50. package/bin/containerize/index.d.ts +4 -0
  51. package/bin/containerize/index.js +13 -0
  52. package/bin/containerize/presets/preset-registry.d.ts +20 -0
  53. package/bin/containerize/presets/preset-registry.js +102 -0
  54. package/bin/costs/cli.d.ts +5 -0
  55. package/bin/costs/cli.js +183 -0
  56. package/bin/costs/form.d.ts +44 -0
  57. package/bin/costs/form.js +412 -0
  58. package/bin/costs/index.d.ts +4 -0
  59. package/bin/costs/index.js +25 -0
  60. package/bin/costs/pricing-manager.d.ts +84 -0
  61. package/bin/costs/pricing-manager.js +342 -0
  62. package/bin/costs/providers/index.d.ts +32 -0
  63. package/bin/costs/providers/index.js +153 -0
  64. package/bin/costs/sources/api-source.d.ts +10 -0
  65. package/bin/costs/sources/api-source.js +32 -0
  66. package/bin/costs/sources/index.d.ts +6 -0
  67. package/bin/costs/sources/index.js +15 -0
  68. package/bin/costs/sources/local-json-source.d.ts +23 -0
  69. package/bin/costs/sources/local-json-source.js +59 -0
  70. package/bin/costs/sources/remote-json-source.d.ts +11 -0
  71. package/bin/costs/sources/remote-json-source.js +53 -0
  72. package/bin/costs/types.d.ts +53 -0
  73. package/bin/costs/types.js +5 -0
  74. package/bin/dev/cli.d.ts +4 -0
  75. package/bin/dev/cli.js +134 -0
  76. package/bin/dev/form.d.ts +36 -0
  77. package/bin/dev/form.js +254 -0
  78. package/bin/dev/index.d.ts +1 -0
  79. package/bin/dev/index.js +5 -0
  80. package/bin/generate/cli.js +29 -2
  81. package/bin/generate/form.d.ts +5 -1
  82. package/bin/generate/form.js +3 -3
  83. package/bin/generate/templates/nonopinionated/config.tpl +12 -0
  84. package/bin/generate/templates/nonopinionated/event.tpl +10 -0
  85. package/bin/generate/templates/nonopinionated/guard.tpl +18 -0
  86. package/bin/generate/templates/nonopinionated/handler.tpl +12 -0
  87. package/bin/generate/templates/nonopinionated/interceptor.tpl +27 -0
  88. package/bin/generate/templates/opinionated/config.tpl +47 -0
  89. package/bin/generate/templates/opinionated/entity.tpl +1 -8
  90. package/bin/generate/templates/opinionated/event.tpl +15 -0
  91. package/bin/generate/templates/opinionated/guard.tpl +41 -0
  92. package/bin/generate/templates/opinionated/handler.tpl +23 -0
  93. package/bin/generate/templates/opinionated/interceptor.tpl +50 -0
  94. package/bin/generate/utils/command-utils.d.ts +7 -3
  95. package/bin/generate/utils/command-utils.js +95 -31
  96. package/bin/generate/utils/nonopininated-cmd.d.ts +10 -1
  97. package/bin/generate/utils/nonopininated-cmd.js +100 -1
  98. package/bin/generate/utils/opinionated-cmd.d.ts +10 -1
  99. package/bin/generate/utils/opinionated-cmd.js +112 -7
  100. package/bin/generate/utils/string-utils.d.ts +6 -0
  101. package/bin/generate/utils/string-utils.js +13 -1
  102. package/bin/help/form.js +11 -3
  103. package/bin/migrate/analyzers/platform-detector.d.ts +14 -0
  104. package/bin/migrate/analyzers/platform-detector.js +116 -0
  105. package/bin/migrate/cli.d.ts +6 -0
  106. package/bin/migrate/cli.js +96 -0
  107. package/bin/migrate/form.d.ts +25 -0
  108. package/bin/migrate/form.js +347 -0
  109. package/bin/migrate/generators/compose-to-k8s.d.ts +2 -0
  110. package/bin/migrate/generators/compose-to-k8s.js +324 -0
  111. package/bin/migrate/generators/compose-to-railway.d.ts +2 -0
  112. package/bin/migrate/generators/compose-to-railway.js +138 -0
  113. package/bin/migrate/generators/compose-to-render.d.ts +2 -0
  114. package/bin/migrate/generators/compose-to-render.js +148 -0
  115. package/bin/migrate/generators/generic-migration.d.ts +9 -0
  116. package/bin/migrate/generators/generic-migration.js +221 -0
  117. package/bin/migrate/generators/heroku-to-fly.d.ts +2 -0
  118. package/bin/migrate/generators/heroku-to-fly.js +291 -0
  119. package/bin/migrate/generators/heroku-to-railway.d.ts +2 -0
  120. package/bin/migrate/generators/heroku-to-railway.js +283 -0
  121. package/bin/migrate/generators/heroku-to-render.d.ts +2 -0
  122. package/bin/migrate/generators/heroku-to-render.js +148 -0
  123. package/bin/migrate/generators/index.d.ts +7 -0
  124. package/bin/migrate/generators/index.js +17 -0
  125. package/bin/migrate/generators/template-loader.d.ts +21 -0
  126. package/bin/migrate/generators/template-loader.js +59 -0
  127. package/bin/migrate/index.d.ts +1 -0
  128. package/bin/migrate/index.js +5 -0
  129. package/bin/new/cli.js +21 -6
  130. package/bin/new/form.d.ts +25 -4
  131. package/bin/new/form.js +285 -70
  132. package/bin/profile/analyzers/dockerfile-analyzer.d.ts +27 -0
  133. package/bin/profile/analyzers/dockerfile-analyzer.js +122 -0
  134. package/bin/profile/analyzers/image-analyzer.d.ts +19 -0
  135. package/bin/profile/analyzers/image-analyzer.js +85 -0
  136. package/bin/profile/cli.d.ts +4 -0
  137. package/bin/profile/cli.js +92 -0
  138. package/bin/profile/form.d.ts +56 -0
  139. package/bin/profile/form.js +400 -0
  140. package/bin/profile/index.d.ts +1 -0
  141. package/bin/profile/index.js +5 -0
  142. package/bin/profile/optimizers/index.d.ts +19 -0
  143. package/bin/profile/optimizers/index.js +137 -0
  144. package/bin/providers/add/form.d.ts +1 -1
  145. package/bin/providers/add/form.js +27 -6
  146. package/bin/providers/create/form.js +2 -1
  147. package/bin/scripts/form.js +27 -5
  148. package/bin/studio/cli.d.ts +15 -0
  149. package/bin/studio/cli.js +166 -0
  150. package/bin/studio/index.d.ts +5 -0
  151. package/bin/studio/index.js +9 -0
  152. package/bin/templates/cache.d.ts +54 -0
  153. package/bin/templates/cache.js +180 -0
  154. package/bin/templates/cli.d.ts +8 -0
  155. package/bin/templates/cli.js +292 -0
  156. package/bin/templates/fetcher.d.ts +49 -0
  157. package/bin/templates/fetcher.js +208 -0
  158. package/bin/templates/index.d.ts +11 -0
  159. package/bin/templates/index.js +37 -0
  160. package/bin/templates/manager.d.ts +116 -0
  161. package/bin/templates/manager.js +323 -0
  162. package/bin/templates/renderer.d.ts +49 -0
  163. package/bin/templates/renderer.js +204 -0
  164. package/bin/templates/types.d.ts +51 -0
  165. package/bin/templates/types.js +5 -0
  166. package/bin/utils/add-module-to-container.d.ts +2 -2
  167. package/bin/utils/add-module-to-container.js +15 -5
  168. package/bin/utils/cli-ui.d.ts +30 -3
  169. package/bin/utils/cli-ui.js +95 -13
  170. package/bin/utils/index.d.ts +4 -0
  171. package/bin/utils/index.js +4 -0
  172. package/bin/utils/input-validation.d.ts +50 -0
  173. package/bin/utils/input-validation.js +143 -0
  174. package/bin/utils/package-manager-commands.d.ts +24 -0
  175. package/bin/utils/package-manager-commands.js +50 -0
  176. package/bin/utils/safe-spawn.d.ts +35 -0
  177. package/bin/utils/safe-spawn.js +51 -0
  178. package/bin/utils/update-tsconfig-paths.d.ts +35 -0
  179. package/bin/utils/update-tsconfig-paths.js +286 -0
  180. package/package.json +154 -154
@@ -0,0 +1,237 @@
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.generateGitLabCI = 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 generateGitLabCI(outputDir, options) {
12
+ // Try remote template, fall back to embedded
13
+ const result = await (0, template_loader_1.loadCICDTemplate)("gitlab", options.strategy, options, generateGitLabContentEmbedded);
14
+ (0, template_loader_1.logTemplateSource)("GitLab CI", result.source);
15
+ const filePath = path_1.default.join(outputDir, ".gitlab-ci.yml");
16
+ fs_1.default.writeFileSync(filePath, result.content, "utf-8");
17
+ console.log(chalk_1.default.green(` ✓ Created .gitlab-ci.yml`));
18
+ }
19
+ exports.generateGitLabCI = generateGitLabCI;
20
+ /**
21
+ * Embedded template generator (fallback when remote templates unavailable)
22
+ */
23
+ function generateGitLabContentEmbedded(options) {
24
+ const { nodeVersion, packageManager, strategy, includeSecurity, includeE2E, includeCoverage, deployTarget, branch, } = options;
25
+ const installCmd = packageManager === "pnpm"
26
+ ? "pnpm install"
27
+ : packageManager === "yarn"
28
+ ? "yarn install"
29
+ : "npm ci";
30
+ const testCmd = packageManager === "pnpm"
31
+ ? "pnpm test"
32
+ : packageManager === "yarn"
33
+ ? "yarn test"
34
+ : "npm test";
35
+ const buildCmd = packageManager === "pnpm"
36
+ ? "pnpm build"
37
+ : packageManager === "yarn"
38
+ ? "yarn build"
39
+ : "npm run build";
40
+ const lintCmd = packageManager === "pnpm"
41
+ ? "pnpm lint"
42
+ : packageManager === "yarn"
43
+ ? "yarn lint"
44
+ : "npm run lint";
45
+ let content = `# GitLab CI/CD Pipeline
46
+ # Generated by ExpressoTS CLI
47
+ # Strategy: ${strategy}
48
+
49
+ image: node:${nodeVersion}-alpine
50
+
51
+ stages:
52
+ - lint
53
+ - test${includeSecurity && (strategy === "comprehensive" || strategy === "security-focused") ? "\n - security" : ""}${includeE2E ? "\n - e2e" : ""}
54
+ - build
55
+ - docker${deployTarget !== "none" ? "\n - deploy" : ""}
56
+
57
+ variables:
58
+ npm_config_cache: "$CI_PROJECT_DIR/.npm"
59
+ DOCKER_IMAGE: $CI_REGISTRY_IMAGE
60
+
61
+ cache:
62
+ key: \${CI_COMMIT_REF_SLUG}
63
+ paths:
64
+ - .npm/
65
+ - node_modules/
66
+
67
+ # Lint Stage
68
+ lint:
69
+ stage: lint
70
+ script:
71
+ - ${installCmd}
72
+ - ${lintCmd}
73
+ only:
74
+ - ${branch}
75
+ - merge_requests
76
+
77
+ # Test Stage
78
+ test:
79
+ stage: test
80
+ script:
81
+ - ${installCmd}
82
+ - ${testCmd}${includeCoverage ? ` --coverage` : ""}
83
+ ${includeCoverage
84
+ ? `coverage: '/All files[^|]*\\|[^|]*\\s+([\\d\\.]+)/'
85
+ artifacts:
86
+ reports:
87
+ coverage_report:
88
+ coverage_format: cobertura
89
+ path: coverage/cobertura-coverage.xml`
90
+ : ""}
91
+ only:
92
+ - ${branch}
93
+ - merge_requests
94
+
95
+ `;
96
+ // Security scanning
97
+ if (includeSecurity &&
98
+ (strategy === "comprehensive" || strategy === "security-focused")) {
99
+ content += `# Security Stage
100
+ security:
101
+ stage: security
102
+ image:
103
+ name: aquasec/trivy:latest
104
+ entrypoint: [""]
105
+ script:
106
+ - trivy fs --exit-code 0 --severity HIGH,CRITICAL --format json -o trivy-report.json .
107
+ artifacts:
108
+ reports:
109
+ container_scanning: trivy-report.json
110
+ expire_in: 1 week
111
+ only:
112
+ - ${branch}
113
+
114
+ `;
115
+ if (strategy === "security-focused") {
116
+ content += `dependency_scanning:
117
+ stage: security
118
+ image: node:${nodeVersion}
119
+ script:
120
+ - npm audit --audit-level=high
121
+ allow_failure: true
122
+ only:
123
+ - ${branch}
124
+
125
+ `;
126
+ }
127
+ }
128
+ // E2E tests
129
+ if (includeE2E) {
130
+ content += `# E2E Tests
131
+ e2e:
132
+ stage: e2e
133
+ services:
134
+ - postgres:15-alpine
135
+ variables:
136
+ DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/test"
137
+ script:
138
+ - ${installCmd}
139
+ - ${buildCmd}
140
+ - npm start &
141
+ - sleep 10
142
+ - npm run test:e2e
143
+ only:
144
+ - ${branch}
145
+
146
+ `;
147
+ }
148
+ // Build stage
149
+ content += `# Build Stage
150
+ build:
151
+ stage: build
152
+ script:
153
+ - ${installCmd}
154
+ - ${buildCmd}
155
+ artifacts:
156
+ paths:
157
+ - dist/
158
+ expire_in: 1 week
159
+ only:
160
+ - ${branch}
161
+
162
+ # Docker Build Stage
163
+ docker:
164
+ stage: docker
165
+ image: docker:24
166
+ services:
167
+ - docker:24-dind
168
+ variables:
169
+ DOCKER_TLS_CERTDIR: "/certs"
170
+ before_script:
171
+ - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
172
+ script:
173
+ - docker build -t $DOCKER_IMAGE:$CI_COMMIT_SHA -t $DOCKER_IMAGE:latest .
174
+ - docker push $DOCKER_IMAGE:$CI_COMMIT_SHA
175
+ - docker push $DOCKER_IMAGE:latest
176
+ only:
177
+ - ${branch}
178
+
179
+ `;
180
+ // Deploy stage
181
+ if (deployTarget !== "none") {
182
+ content += generateGitLabDeployJob(deployTarget, branch);
183
+ }
184
+ return content;
185
+ }
186
+ function generateGitLabDeployJob(target, branch) {
187
+ switch (target) {
188
+ case "kubernetes":
189
+ return `# Deploy to Kubernetes
190
+ deploy:
191
+ stage: deploy
192
+ image: bitnami/kubectl:latest
193
+ script:
194
+ - kubectl config set-cluster k8s --server="$KUBE_URL"
195
+ - kubectl config set-credentials gitlab --token="$KUBE_TOKEN"
196
+ - kubectl config set-context default --cluster=k8s --user=gitlab
197
+ - kubectl config use-context default
198
+ - kubectl set image deployment/expressots-app app=$DOCKER_IMAGE:$CI_COMMIT_SHA
199
+ - kubectl rollout status deployment/expressots-app
200
+ environment:
201
+ name: production
202
+ url: https://your-app.com
203
+ only:
204
+ - ${branch}
205
+ when: manual
206
+
207
+ `;
208
+ case "railway":
209
+ return `# Deploy to Railway
210
+ deploy:
211
+ stage: deploy
212
+ image: node:20-alpine
213
+ script:
214
+ - npm install -g @railway/cli
215
+ - railway up
216
+ environment:
217
+ name: production
218
+ only:
219
+ - ${branch}
220
+ when: manual
221
+
222
+ `;
223
+ default:
224
+ return `# Deploy Stage
225
+ deploy:
226
+ stage: deploy
227
+ script:
228
+ - echo "Deploy to ${target}"
229
+ environment:
230
+ name: production
231
+ only:
232
+ - ${branch}
233
+ when: manual
234
+
235
+ `;
236
+ }
237
+ }
@@ -0,0 +1,6 @@
1
+ export { generateGitHubActions } from "./github-actions";
2
+ export { generateGitLabCI } from "./gitlab-ci";
3
+ export { generateCircleCI } from "./circleci";
4
+ export { generateJenkinsfile } from "./jenkins";
5
+ export { generateBitbucketPipelines } from "./bitbucket";
6
+ export { generateAzureDevOps } from "./azure-devops";
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateAzureDevOps = exports.generateBitbucketPipelines = exports.generateJenkinsfile = exports.generateCircleCI = exports.generateGitLabCI = exports.generateGitHubActions = void 0;
4
+ var github_actions_1 = require("./github-actions");
5
+ Object.defineProperty(exports, "generateGitHubActions", { enumerable: true, get: function () { return github_actions_1.generateGitHubActions; } });
6
+ var gitlab_ci_1 = require("./gitlab-ci");
7
+ Object.defineProperty(exports, "generateGitLabCI", { enumerable: true, get: function () { return gitlab_ci_1.generateGitLabCI; } });
8
+ var circleci_1 = require("./circleci");
9
+ Object.defineProperty(exports, "generateCircleCI", { enumerable: true, get: function () { return circleci_1.generateCircleCI; } });
10
+ var jenkins_1 = require("./jenkins");
11
+ Object.defineProperty(exports, "generateJenkinsfile", { enumerable: true, get: function () { return jenkins_1.generateJenkinsfile; } });
12
+ var bitbucket_1 = require("./bitbucket");
13
+ Object.defineProperty(exports, "generateBitbucketPipelines", { enumerable: true, get: function () { return bitbucket_1.generateBitbucketPipelines; } });
14
+ var azure_devops_1 = require("./azure-devops");
15
+ Object.defineProperty(exports, "generateAzureDevOps", { enumerable: true, get: function () { return azure_devops_1.generateAzureDevOps; } });
@@ -0,0 +1,2 @@
1
+ import type { GeneratorOptions } from "./github-actions";
2
+ export declare function generateJenkinsfile(outputDir: string, options: GeneratorOptions): Promise<void>;
@@ -0,0 +1,248 @@
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.generateJenkinsfile = 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 generateJenkinsfile(outputDir, options) {
12
+ // Try remote template, fall back to embedded
13
+ const result = await (0, template_loader_1.loadCICDTemplate)("jenkins", options.strategy, options, generateJenkinsContentEmbedded);
14
+ (0, template_loader_1.logTemplateSource)("Jenkins", result.source);
15
+ const filePath = path_1.default.join(outputDir, "Jenkinsfile");
16
+ fs_1.default.writeFileSync(filePath, result.content, "utf-8");
17
+ console.log(chalk_1.default.green(` ✓ Created Jenkinsfile`));
18
+ }
19
+ exports.generateJenkinsfile = generateJenkinsfile;
20
+ /**
21
+ * Embedded template generator (fallback when remote templates unavailable)
22
+ */
23
+ function generateJenkinsContentEmbedded(options) {
24
+ const { projectName, nodeVersion, packageManager, strategy, includeSecurity, includeE2E, includeCoverage, deployTarget, branch, } = options;
25
+ const installCmd = packageManager === "pnpm"
26
+ ? "pnpm install"
27
+ : packageManager === "yarn"
28
+ ? "yarn install"
29
+ : "npm ci";
30
+ const testCmd = packageManager === "pnpm"
31
+ ? "pnpm test"
32
+ : packageManager === "yarn"
33
+ ? "yarn test"
34
+ : "npm test";
35
+ const buildCmd = packageManager === "pnpm"
36
+ ? "pnpm build"
37
+ : packageManager === "yarn"
38
+ ? "yarn build"
39
+ : "npm run build";
40
+ const lintCmd = packageManager === "pnpm"
41
+ ? "pnpm lint"
42
+ : packageManager === "yarn"
43
+ ? "yarn lint"
44
+ : "npm run lint";
45
+ let content = `// Jenkinsfile
46
+ // Generated by ExpressoTS CLI
47
+ // Strategy: ${strategy}
48
+
49
+ pipeline {
50
+ agent any
51
+
52
+ environment {
53
+ NODE_VERSION = '${nodeVersion}'
54
+ DOCKER_IMAGE = '${projectName}'
55
+ DOCKER_TAG = "\${BUILD_NUMBER}"
56
+ }
57
+
58
+ tools {
59
+ nodejs "node-\${NODE_VERSION}"
60
+ }
61
+
62
+ options {
63
+ buildDiscarder(logRotator(numToKeepStr: '10'))
64
+ timeout(time: 30, unit: 'MINUTES')
65
+ disableConcurrentBuilds()
66
+ }
67
+
68
+ stages {
69
+ stage('Checkout') {
70
+ steps {
71
+ checkout scm
72
+ }
73
+ }
74
+
75
+ stage('Install Dependencies') {
76
+ steps {
77
+ sh '${installCmd}'
78
+ }
79
+ }
80
+
81
+ stage('Lint') {
82
+ steps {
83
+ sh '${lintCmd}'
84
+ }
85
+ }
86
+
87
+ stage('Test') {
88
+ steps {
89
+ sh '${testCmd}${includeCoverage ? " --coverage" : ""}'
90
+ }
91
+ `;
92
+ if (includeCoverage) {
93
+ content += ` post {
94
+ always {
95
+ publishHTML(target: [
96
+ allowMissing: false,
97
+ alwaysLinkToLastBuild: true,
98
+ keepAll: true,
99
+ reportDir: 'coverage/lcov-report',
100
+ reportFiles: 'index.html',
101
+ reportName: 'Coverage Report'
102
+ ])
103
+ }
104
+ }
105
+ `;
106
+ }
107
+ content += ` }
108
+ `;
109
+ // Security stage
110
+ if (includeSecurity &&
111
+ (strategy === "comprehensive" || strategy === "security-focused")) {
112
+ content += `
113
+ stage('Security Scan') {
114
+ steps {
115
+ script {
116
+ // Run npm audit
117
+ sh 'npm audit --audit-level=high || true'
118
+
119
+ // Run Trivy if available
120
+ sh '''
121
+ if command -v trivy &> /dev/null; then
122
+ trivy fs --exit-code 0 --severity HIGH,CRITICAL .
123
+ else
124
+ echo "Trivy not installed, skipping filesystem scan"
125
+ fi
126
+ '''
127
+ }
128
+ }
129
+ }
130
+ `;
131
+ }
132
+ // E2E tests
133
+ if (includeE2E) {
134
+ content += `
135
+ stage('E2E Tests') {
136
+ steps {
137
+ script {
138
+ sh '${buildCmd}'
139
+ sh '''
140
+ npm start &
141
+ sleep 10
142
+ npm run test:e2e
143
+ '''
144
+ }
145
+ }
146
+ }
147
+ `;
148
+ }
149
+ // Build stage
150
+ content += `
151
+ stage('Build') {
152
+ steps {
153
+ sh '${buildCmd}'
154
+ }
155
+ }
156
+
157
+ stage('Docker Build') {
158
+ when {
159
+ branch '${branch}'
160
+ }
161
+ steps {
162
+ script {
163
+ docker.build("\${DOCKER_IMAGE}:\${DOCKER_TAG}")
164
+ docker.build("\${DOCKER_IMAGE}:latest")
165
+ }
166
+ }
167
+ }
168
+
169
+ stage('Docker Push') {
170
+ when {
171
+ branch '${branch}'
172
+ }
173
+ steps {
174
+ script {
175
+ docker.withRegistry('https://registry.hub.docker.com', 'docker-hub-credentials') {
176
+ docker.image("\${DOCKER_IMAGE}:\${DOCKER_TAG}").push()
177
+ docker.image("\${DOCKER_IMAGE}:latest").push()
178
+ }
179
+ }
180
+ }
181
+ }
182
+ `;
183
+ // Deploy stage
184
+ if (deployTarget !== "none") {
185
+ content += generateJenkinsDeployStage(deployTarget, branch);
186
+ }
187
+ content += ` }
188
+
189
+ post {
190
+ always {
191
+ cleanWs()
192
+ }
193
+ success {
194
+ echo 'Pipeline completed successfully!'
195
+ }
196
+ failure {
197
+ echo 'Pipeline failed!'
198
+ }
199
+ }
200
+ }
201
+ `;
202
+ return content;
203
+ }
204
+ function generateJenkinsDeployStage(target, branch) {
205
+ switch (target) {
206
+ case "kubernetes":
207
+ return `
208
+ stage('Deploy to Kubernetes') {
209
+ when {
210
+ branch '${branch}'
211
+ }
212
+ steps {
213
+ withKubeConfig([credentialsId: 'kubeconfig']) {
214
+ sh '''
215
+ kubectl set image deployment/expressots-app \\
216
+ app=\${DOCKER_IMAGE}:\${DOCKER_TAG}
217
+ kubectl rollout status deployment/expressots-app
218
+ '''
219
+ }
220
+ }
221
+ }
222
+ `;
223
+ case "railway":
224
+ return `
225
+ stage('Deploy to Railway') {
226
+ when {
227
+ branch '${branch}'
228
+ }
229
+ steps {
230
+ withCredentials([string(credentialsId: 'railway-token', variable: 'RAILWAY_TOKEN')]) {
231
+ sh 'npx @railway/cli up'
232
+ }
233
+ }
234
+ }
235
+ `;
236
+ default:
237
+ return `
238
+ stage('Deploy') {
239
+ when {
240
+ branch '${branch}'
241
+ }
242
+ steps {
243
+ echo 'Deploying to ${target}...'
244
+ }
245
+ }
246
+ `;
247
+ }
248
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Template loader for CI/CD generators
3
+ * Handles remote template fetching with fallback to embedded templates
4
+ */
5
+ import type { GeneratorOptions } from "./github-actions";
6
+ export interface TemplateResult {
7
+ content: string;
8
+ source: "remote" | "embedded";
9
+ }
10
+ /**
11
+ * Load CI/CD template with fallback
12
+ */
13
+ export declare function loadCICDTemplate(platform: string, strategy: string, options: GeneratorOptions, embeddedGenerator: (options: GeneratorOptions) => string): Promise<TemplateResult>;
14
+ /**
15
+ * Log template source for debugging
16
+ */
17
+ export declare function logTemplateSource(platform: string, source: "remote" | "embedded"): void;
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ /**
3
+ * Template loader for CI/CD generators
4
+ * Handles remote template fetching with fallback to embedded templates
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.logTemplateSource = exports.loadCICDTemplate = void 0;
8
+ const templates_1 = require("../../templates");
9
+ /**
10
+ * Load CI/CD template with fallback
11
+ */
12
+ async function loadCICDTemplate(platform, strategy, options, embeddedGenerator) {
13
+ const manager = (0, templates_1.getTemplateManager)();
14
+ try {
15
+ // Try to fetch from remote template repository
16
+ const result = await manager.fetchCICDTemplate(platform, strategy);
17
+ if (result.data) {
18
+ // Template found, render with variables
19
+ const renderOptions = {
20
+ variables: {
21
+ projectName: options.projectName,
22
+ nodeVersion: options.nodeVersion,
23
+ packageManager: options.packageManager,
24
+ strategy: options.strategy,
25
+ includeSecurity: options.includeSecurity,
26
+ includeE2E: options.includeE2E,
27
+ includeCoverage: options.includeCoverage,
28
+ dockerRegistry: options.dockerRegistry || "ghcr.io",
29
+ deployTarget: options.deployTarget,
30
+ branch: options.branch,
31
+ port: options.port,
32
+ // Computed variables
33
+ installCmd: getInstallCommand(options.packageManager),
34
+ testCmd: getTestCommand(options.packageManager),
35
+ buildCmd: getBuildCommand(options.packageManager),
36
+ lintCmd: getLintCommand(options.packageManager),
37
+ },
38
+ conditionals: {
39
+ includeSecurity: options.includeSecurity,
40
+ includeE2E: options.includeE2E,
41
+ includeCoverage: options.includeCoverage,
42
+ isComprehensive: options.strategy === "comprehensive",
43
+ isSecurityFocused: options.strategy === "security-focused",
44
+ hasDeployTarget: options.deployTarget !== "none",
45
+ deployKubernetes: options.deployTarget === "kubernetes",
46
+ deployRailway: options.deployTarget === "railway",
47
+ deployRender: options.deployTarget === "render",
48
+ deployFly: options.deployTarget === "fly",
49
+ deployECS: options.deployTarget === "ecs",
50
+ deployCloudRun: options.deployTarget === "cloudrun",
51
+ },
52
+ };
53
+ const rendered = manager.render(result.data, renderOptions);
54
+ return { content: rendered, source: "remote" };
55
+ }
56
+ }
57
+ catch {
58
+ // Remote fetch failed, fall back to embedded
59
+ }
60
+ // Fall back to embedded template generator
61
+ return {
62
+ content: embeddedGenerator(options),
63
+ source: "embedded",
64
+ };
65
+ }
66
+ exports.loadCICDTemplate = loadCICDTemplate;
67
+ /**
68
+ * Get install command for package manager
69
+ */
70
+ function getInstallCommand(packageManager) {
71
+ switch (packageManager) {
72
+ case "pnpm":
73
+ return "pnpm install";
74
+ case "yarn":
75
+ return "yarn install";
76
+ default:
77
+ return "npm ci";
78
+ }
79
+ }
80
+ /**
81
+ * Get test command for package manager
82
+ */
83
+ function getTestCommand(packageManager) {
84
+ switch (packageManager) {
85
+ case "pnpm":
86
+ return "pnpm test";
87
+ case "yarn":
88
+ return "yarn test";
89
+ default:
90
+ return "npm test";
91
+ }
92
+ }
93
+ /**
94
+ * Get build command for package manager
95
+ */
96
+ function getBuildCommand(packageManager) {
97
+ switch (packageManager) {
98
+ case "pnpm":
99
+ return "pnpm build";
100
+ case "yarn":
101
+ return "yarn build";
102
+ default:
103
+ return "npm run build";
104
+ }
105
+ }
106
+ /**
107
+ * Get lint command for package manager
108
+ */
109
+ function getLintCommand(packageManager) {
110
+ switch (packageManager) {
111
+ case "pnpm":
112
+ return "pnpm lint";
113
+ case "yarn":
114
+ return "yarn lint";
115
+ default:
116
+ return "npm run lint";
117
+ }
118
+ }
119
+ /**
120
+ * Log template source for debugging
121
+ */
122
+ function logTemplateSource(platform, source) {
123
+ if (process.env.EXPRESSOTS_DEBUG) {
124
+ const sourceLabel = source === "remote" ? "remote template" : "embedded template";
125
+ console.log(` [DEBUG] ${platform}: Using ${sourceLabel}`);
126
+ }
127
+ }
128
+ exports.logTemplateSource = logTemplateSource;
@@ -0,0 +1 @@
1
+ export { cicdCommand } from "./cli";
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cicdCommand = void 0;
4
+ var cli_1 = require("./cli");
5
+ Object.defineProperty(exports, "cicdCommand", { enumerable: true, get: function () { return cli_1.cicdCommand; } });
package/bin/cli.d.ts CHANGED
@@ -3,4 +3,4 @@
3
3
  * The current version of the ExpressoTS Bundle.
4
4
  * core, adapters, and cli.
5
5
  */
6
- export declare const BUNDLE_VERSION = "3.0.0";
6
+ export declare const BUNDLE_VERSION = "4.0.0-preview.2";