@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.
Files changed (194) hide show
  1. package/README.md +41 -95
  2. package/bin/cicd/cli.d.ts +6 -0
  3. package/bin/cicd/cli.js +128 -0
  4. package/bin/cicd/form.d.ts +29 -0
  5. package/bin/cicd/form.js +346 -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 -5
  25. package/bin/cli.js +72 -7
  26. package/bin/commands/project.commands.d.ts +19 -6
  27. package/bin/commands/project.commands.js +602 -66
  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 +152 -0
  40. package/bin/containerize/generators/ci-generator.d.ts +31 -0
  41. package/bin/containerize/generators/ci-generator.js +940 -0
  42. package/bin/containerize/generators/docker-compose-generator.d.ts +8 -0
  43. package/bin/containerize/generators/docker-compose-generator.js +187 -0
  44. package/bin/containerize/generators/dockerfile-generator.d.ts +8 -0
  45. package/bin/containerize/generators/dockerfile-generator.js +657 -0
  46. package/bin/containerize/generators/kubernetes-generator.d.ts +8 -0
  47. package/bin/containerize/generators/kubernetes-generator.js +134 -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 +185 -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 +136 -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.d.ts +1 -1
  81. package/bin/generate/cli.js +29 -2
  82. package/bin/generate/form.d.ts +5 -1
  83. package/bin/generate/form.js +3 -3
  84. package/bin/generate/templates/nonopinionated/config.tpl +12 -0
  85. package/bin/generate/templates/nonopinionated/event.tpl +10 -0
  86. package/bin/generate/templates/nonopinionated/guard.tpl +18 -0
  87. package/bin/generate/templates/nonopinionated/handler.tpl +12 -0
  88. package/bin/generate/templates/nonopinionated/interceptor.tpl +27 -0
  89. package/bin/generate/templates/opinionated/config.tpl +47 -0
  90. package/bin/generate/templates/opinionated/entity.tpl +1 -8
  91. package/bin/generate/templates/opinionated/event.tpl +15 -0
  92. package/bin/generate/templates/opinionated/guard.tpl +41 -0
  93. package/bin/generate/templates/opinionated/handler.tpl +23 -0
  94. package/bin/generate/templates/opinionated/interceptor.tpl +50 -0
  95. package/bin/generate/utils/command-utils.d.ts +20 -5
  96. package/bin/generate/utils/command-utils.js +145 -48
  97. package/bin/generate/utils/nonopininated-cmd.d.ts +10 -1
  98. package/bin/generate/utils/nonopininated-cmd.js +100 -1
  99. package/bin/generate/utils/opinionated-cmd.d.ts +10 -1
  100. package/bin/generate/utils/opinionated-cmd.js +128 -16
  101. package/bin/generate/utils/string-utils.d.ts +6 -0
  102. package/bin/generate/utils/string-utils.js +13 -1
  103. package/bin/help/cli.d.ts +1 -1
  104. package/bin/help/command-help-registry.d.ts +23 -0
  105. package/bin/help/command-help-registry.js +303 -0
  106. package/bin/help/command-help.d.ts +36 -0
  107. package/bin/help/command-help.js +56 -0
  108. package/bin/help/form.js +127 -22
  109. package/bin/help/main-help.d.ts +8 -0
  110. package/bin/help/main-help.js +126 -0
  111. package/bin/help/render.d.ts +32 -0
  112. package/bin/help/render.js +46 -0
  113. package/bin/info/cli.d.ts +1 -1
  114. package/bin/info/form.d.ts +1 -1
  115. package/bin/info/form.js +11 -11
  116. package/bin/migrate/analyzers/platform-detector.d.ts +14 -0
  117. package/bin/migrate/analyzers/platform-detector.js +116 -0
  118. package/bin/migrate/cli.d.ts +6 -0
  119. package/bin/migrate/cli.js +98 -0
  120. package/bin/migrate/form.d.ts +25 -0
  121. package/bin/migrate/form.js +348 -0
  122. package/bin/migrate/generators/compose-to-k8s.d.ts +2 -0
  123. package/bin/migrate/generators/compose-to-k8s.js +324 -0
  124. package/bin/migrate/generators/compose-to-railway.d.ts +2 -0
  125. package/bin/migrate/generators/compose-to-railway.js +138 -0
  126. package/bin/migrate/generators/compose-to-render.d.ts +2 -0
  127. package/bin/migrate/generators/compose-to-render.js +148 -0
  128. package/bin/migrate/generators/generic-migration.d.ts +9 -0
  129. package/bin/migrate/generators/generic-migration.js +221 -0
  130. package/bin/migrate/generators/heroku-to-fly.d.ts +2 -0
  131. package/bin/migrate/generators/heroku-to-fly.js +291 -0
  132. package/bin/migrate/generators/heroku-to-railway.d.ts +2 -0
  133. package/bin/migrate/generators/heroku-to-railway.js +283 -0
  134. package/bin/migrate/generators/heroku-to-render.d.ts +2 -0
  135. package/bin/migrate/generators/heroku-to-render.js +148 -0
  136. package/bin/migrate/generators/index.d.ts +7 -0
  137. package/bin/migrate/generators/index.js +17 -0
  138. package/bin/migrate/generators/template-loader.d.ts +21 -0
  139. package/bin/migrate/generators/template-loader.js +59 -0
  140. package/bin/migrate/index.d.ts +1 -0
  141. package/bin/migrate/index.js +5 -0
  142. package/bin/new/cli.d.ts +5 -1
  143. package/bin/new/cli.js +77 -14
  144. package/bin/new/form.d.ts +27 -4
  145. package/bin/new/form.js +605 -75
  146. package/bin/profile/analyzers/dockerfile-analyzer.d.ts +27 -0
  147. package/bin/profile/analyzers/dockerfile-analyzer.js +122 -0
  148. package/bin/profile/analyzers/image-analyzer.d.ts +19 -0
  149. package/bin/profile/analyzers/image-analyzer.js +85 -0
  150. package/bin/profile/cli.d.ts +4 -0
  151. package/bin/profile/cli.js +94 -0
  152. package/bin/profile/form.d.ts +56 -0
  153. package/bin/profile/form.js +401 -0
  154. package/bin/profile/index.d.ts +1 -0
  155. package/bin/profile/index.js +5 -0
  156. package/bin/profile/optimizers/index.d.ts +19 -0
  157. package/bin/profile/optimizers/index.js +137 -0
  158. package/bin/providers/add/form.d.ts +1 -1
  159. package/bin/providers/add/form.js +27 -6
  160. package/bin/providers/create/form.js +53 -3
  161. package/bin/scripts/form.js +27 -5
  162. package/bin/studio/cli.d.ts +15 -0
  163. package/bin/studio/cli.js +172 -0
  164. package/bin/studio/index.d.ts +5 -0
  165. package/bin/studio/index.js +9 -0
  166. package/bin/templates/cache.d.ts +54 -0
  167. package/bin/templates/cache.js +180 -0
  168. package/bin/templates/cli.d.ts +8 -0
  169. package/bin/templates/cli.js +294 -0
  170. package/bin/templates/fetcher.d.ts +49 -0
  171. package/bin/templates/fetcher.js +208 -0
  172. package/bin/templates/index.d.ts +11 -0
  173. package/bin/templates/index.js +37 -0
  174. package/bin/templates/manager.d.ts +116 -0
  175. package/bin/templates/manager.js +323 -0
  176. package/bin/templates/renderer.d.ts +49 -0
  177. package/bin/templates/renderer.js +204 -0
  178. package/bin/templates/types.d.ts +51 -0
  179. package/bin/templates/types.js +5 -0
  180. package/bin/utils/add-module-to-container.d.ts +14 -3
  181. package/bin/utils/add-module-to-container.js +327 -98
  182. package/bin/utils/cli-ui.d.ts +49 -3
  183. package/bin/utils/cli-ui.js +133 -13
  184. package/bin/utils/index.d.ts +4 -0
  185. package/bin/utils/index.js +4 -0
  186. package/bin/utils/input-validation.d.ts +50 -0
  187. package/bin/utils/input-validation.js +143 -0
  188. package/bin/utils/package-manager-commands.d.ts +24 -0
  189. package/bin/utils/package-manager-commands.js +50 -0
  190. package/bin/utils/safe-spawn.d.ts +35 -0
  191. package/bin/utils/safe-spawn.js +51 -0
  192. package/bin/utils/update-tsconfig-paths.d.ts +35 -0
  193. package/bin/utils/update-tsconfig-paths.js +326 -0
  194. package/package.json +165 -156
@@ -0,0 +1,294 @@
1
+ "use strict";
2
+ /**
3
+ * Templates CLI command
4
+ * Manage template sources, cache, and configuration
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.templatesCommand = void 0;
11
+ const chalk_1 = __importDefault(require("chalk"));
12
+ const manager_1 = require("./manager");
13
+ const config_1 = require("../config");
14
+ const cli_ui_1 = require("../utils/cli-ui");
15
+ const templatesCommand = () => {
16
+ return {
17
+ command: "templates <action> [args...]",
18
+ describe: "Manage CLI templates for CI/CD, Docker, and Kubernetes.",
19
+ aliases: ["tpl"],
20
+ builder: (yargs) => {
21
+ yargs.positional("action", {
22
+ choices: [
23
+ "list",
24
+ "update",
25
+ "clear",
26
+ "info",
27
+ "repo",
28
+ "status",
29
+ ],
30
+ describe: "Action to perform",
31
+ type: "string",
32
+ demandOption: true,
33
+ });
34
+ yargs.positional("args", {
35
+ describe: "Additional arguments for the action",
36
+ type: "string",
37
+ array: true,
38
+ });
39
+ yargs.option("category", {
40
+ alias: "c",
41
+ type: "string",
42
+ describe: "Filter by category (cicd, docker, kubernetes, migrations)",
43
+ });
44
+ yargs.option("platform", {
45
+ alias: "p",
46
+ type: "string",
47
+ describe: "Filter by platform (github, gitlab, etc.)",
48
+ });
49
+ yargs.example("$0 templates list", "List all available templates");
50
+ yargs.example("$0 templates update", "Update template cache from remote");
51
+ yargs.example("$0 templates clear", "Clear local template cache");
52
+ yargs.example("$0 templates info cicd github", "Show template info");
53
+ yargs.example("$0 templates repo set https://github.com/myorg/templates", "Set custom repository");
54
+ yargs.example("$0 templates repo reset", "Reset to default repository");
55
+ yargs.example("$0 templates status", "Show template system status");
56
+ return yargs;
57
+ },
58
+ handler: async (argv) => {
59
+ const action = argv.action;
60
+ const args = argv.args || [];
61
+ switch (action) {
62
+ case "list":
63
+ await listTemplates(argv.category, argv.platform);
64
+ break;
65
+ case "update":
66
+ await updateTemplates();
67
+ break;
68
+ case "clear":
69
+ await clearCache();
70
+ break;
71
+ case "info":
72
+ await showTemplateInfo(args[0], args[1]);
73
+ break;
74
+ case "repo":
75
+ await manageRepository(args);
76
+ break;
77
+ case "status":
78
+ await showStatus();
79
+ break;
80
+ default:
81
+ (0, cli_ui_1.printError)(`Unknown action: ${action}`, "templates");
82
+ console.log(chalk_1.default.gray("Run 'expressots templates --help' for usage."));
83
+ process.exit(1);
84
+ }
85
+ },
86
+ };
87
+ };
88
+ exports.templatesCommand = templatesCommand;
89
+ /**
90
+ * List available templates
91
+ */
92
+ async function listTemplates(category, platform) {
93
+ (0, cli_ui_1.printSection)("📋 Available Templates");
94
+ const manager = (0, manager_1.getTemplateManager)();
95
+ const templates = await manager.listTemplates();
96
+ // Show template source
97
+ const sourceLabel = templates.source === "remote"
98
+ ? chalk_1.default.green("(from remote repository)")
99
+ : chalk_1.default.yellow("(embedded fallback)");
100
+ console.log(chalk_1.default.gray(` Source: ${sourceLabel}\n`));
101
+ if (Object.keys(templates.cicd).length === 0 &&
102
+ templates.docker.length === 0 &&
103
+ templates.kubernetes.length === 0) {
104
+ console.log(chalk_1.default.yellow("No templates available. Run 'expressots templates update' to fetch templates."));
105
+ return;
106
+ }
107
+ // CI/CD Templates
108
+ if (!category || category === "cicd") {
109
+ console.log(chalk_1.default.bold("CI/CD Pipelines:"));
110
+ if (Object.keys(templates.cicd).length === 0) {
111
+ console.log(chalk_1.default.gray(" No CI/CD templates available"));
112
+ }
113
+ else {
114
+ for (const [plat, strategies] of Object.entries(templates.cicd)) {
115
+ if (!platform || platform === plat) {
116
+ console.log(` ${chalk_1.default.yellow(plat)}: ${strategies.join(", ")}`);
117
+ }
118
+ }
119
+ }
120
+ console.log();
121
+ }
122
+ // Docker Templates
123
+ if (!category || category === "docker") {
124
+ console.log(chalk_1.default.bold("Docker:"));
125
+ if (templates.docker.length === 0) {
126
+ console.log(chalk_1.default.gray(" No Docker templates available"));
127
+ }
128
+ else {
129
+ for (const tpl of templates.docker) {
130
+ console.log(` ${chalk_1.default.cyan(tpl)}`);
131
+ }
132
+ }
133
+ console.log();
134
+ }
135
+ // Kubernetes Templates
136
+ if (!category || category === "kubernetes") {
137
+ console.log(chalk_1.default.bold("Kubernetes:"));
138
+ if (templates.kubernetes.length === 0) {
139
+ console.log(chalk_1.default.gray(" No Kubernetes templates available"));
140
+ }
141
+ else {
142
+ for (const tpl of templates.kubernetes) {
143
+ console.log(` ${chalk_1.default.green(tpl)}`);
144
+ }
145
+ }
146
+ console.log();
147
+ }
148
+ // Migration Templates
149
+ if (!category || category === "migrations") {
150
+ console.log(chalk_1.default.bold("Migrations:"));
151
+ if (templates.migrations.length === 0) {
152
+ console.log(chalk_1.default.gray(" No migration templates available"));
153
+ }
154
+ else {
155
+ for (const tpl of templates.migrations) {
156
+ console.log(` ${chalk_1.default.magenta(tpl)}`);
157
+ }
158
+ }
159
+ console.log();
160
+ }
161
+ }
162
+ /**
163
+ * Update template cache
164
+ */
165
+ async function updateTemplates() {
166
+ (0, cli_ui_1.printSection)("🔄 Updating Templates...");
167
+ const manager = (0, manager_1.getTemplateManager)();
168
+ const result = await manager.updateCache();
169
+ if (result.updated > 0) {
170
+ console.log(chalk_1.default.green(`✓ Updated ${result.updated} templates`));
171
+ }
172
+ if (result.errors.length > 0) {
173
+ console.log(chalk_1.default.yellow(`\n⚠️ ${result.errors.length} errors occurred:`));
174
+ for (const error of result.errors) {
175
+ console.log(chalk_1.default.gray(` - ${error}`));
176
+ }
177
+ }
178
+ if (result.updated === 0 && result.errors.length === 0) {
179
+ console.log(chalk_1.default.yellow("No templates were updated. Check your network connection."));
180
+ }
181
+ console.log();
182
+ }
183
+ /**
184
+ * Clear template cache
185
+ */
186
+ async function clearCache() {
187
+ (0, cli_ui_1.printSection)("🗑️ Clearing Template Cache...");
188
+ const manager = (0, manager_1.getTemplateManager)();
189
+ const stats = manager.getCacheStats();
190
+ manager.clearCache();
191
+ console.log(chalk_1.default.green(`✓ Cleared ${stats.files} cached templates`));
192
+ console.log(chalk_1.default.gray(` Freed ${(stats.totalSize / 1024).toFixed(2)} KB`));
193
+ console.log();
194
+ }
195
+ /**
196
+ * Show template info
197
+ */
198
+ async function showTemplateInfo(category, platform) {
199
+ if (!category) {
200
+ console.log(chalk_1.default.red("Please specify a category and platform."));
201
+ console.log(chalk_1.default.gray("Example: expressots templates info cicd github"));
202
+ return;
203
+ }
204
+ console.log(chalk_1.default.cyan(`\n📄 Template Info: ${category}${platform ? `/${platform}` : ""}\n`));
205
+ const manager = (0, manager_1.getTemplateManager)();
206
+ const manifest = await manager.getManifest();
207
+ if (!manifest) {
208
+ console.log(chalk_1.default.yellow("No manifest available. Run 'expressots templates update' first."));
209
+ return;
210
+ }
211
+ const categoryTemplates = manifest.templates[category];
212
+ if (!categoryTemplates) {
213
+ console.log(chalk_1.default.red(`Category '${category}' not found.`));
214
+ return;
215
+ }
216
+ if (platform) {
217
+ const platformTemplates = categoryTemplates[platform];
218
+ if (!platformTemplates) {
219
+ console.log(chalk_1.default.red(`Platform '${platform}' not found in category '${category}'.`));
220
+ return;
221
+ }
222
+ console.log(chalk_1.default.bold(`${category}/${platform}:`));
223
+ for (const [variant, info] of Object.entries(platformTemplates)) {
224
+ console.log(` ${chalk_1.default.yellow(variant)}:`);
225
+ console.log(` Path: ${info.path}`);
226
+ console.log(` Version: ${info.version}`);
227
+ }
228
+ }
229
+ else {
230
+ console.log(chalk_1.default.bold(`${category}:`));
231
+ for (const [key, value] of Object.entries(categoryTemplates)) {
232
+ console.log(` ${chalk_1.default.yellow(key)}`);
233
+ }
234
+ }
235
+ console.log();
236
+ }
237
+ /**
238
+ * Manage template repository
239
+ */
240
+ async function manageRepository(args) {
241
+ const configManager = (0, config_1.getConfigManager)();
242
+ const subAction = args[0];
243
+ if (!subAction) {
244
+ const config = configManager.getTemplateConfig();
245
+ (0, cli_ui_1.printSection)("📦 Template Repository Configuration");
246
+ console.log(` Repository: ${chalk_1.default.yellow(config.repository)}`);
247
+ console.log(` Branch: ${chalk_1.default.cyan(config.branch)}`);
248
+ console.log(` Cache TTL: ${config.cacheTTL} seconds`);
249
+ console.log();
250
+ console.log(chalk_1.default.gray("Use 'expressots templates repo set <url>' to change."));
251
+ console.log(chalk_1.default.gray("Use 'expressots templates repo reset' to restore defaults."));
252
+ return;
253
+ }
254
+ switch (subAction) {
255
+ case "set": {
256
+ const repository = args[1];
257
+ const branch = args[2];
258
+ if (!repository) {
259
+ console.log(chalk_1.default.red("Please specify a repository URL."));
260
+ console.log(chalk_1.default.gray("Example: expressots templates repo set https://github.com/myorg/templates"));
261
+ return;
262
+ }
263
+ configManager.setTemplateRepository(repository, branch);
264
+ // Clear cache when repository changes
265
+ const manager = (0, manager_1.getTemplateManager)();
266
+ manager.clearCache();
267
+ manager.setRepository(repository, branch);
268
+ console.log(chalk_1.default.green(`\n✓ Template repository set to: ${repository}`));
269
+ if (branch) {
270
+ console.log(chalk_1.default.green(` Branch: ${branch}`));
271
+ }
272
+ console.log(chalk_1.default.gray("\nRun 'expressots templates update' to fetch templates from the new repository."));
273
+ break;
274
+ }
275
+ case "reset": {
276
+ configManager.resetTemplateRepository();
277
+ const manager = (0, manager_1.getTemplateManager)();
278
+ manager.clearCache();
279
+ manager.setRepository("expressots/templates", "main");
280
+ console.log(chalk_1.default.green("\n✓ Template repository reset to default (expressots/templates)"));
281
+ break;
282
+ }
283
+ default:
284
+ console.log(chalk_1.default.red(`Unknown repository action: ${subAction}`));
285
+ console.log(chalk_1.default.gray("Use 'set' or 'reset'."));
286
+ }
287
+ }
288
+ /**
289
+ * Show template system status
290
+ */
291
+ async function showStatus() {
292
+ const manager = (0, manager_1.getTemplateManager)();
293
+ await manager.printStatus();
294
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Template fetcher - fetches templates from GitHub repository
3
+ */
4
+ import type { TemplateManifest, FetchResult } from "./types";
5
+ export interface FetcherConfig {
6
+ repository: string;
7
+ branch: string;
8
+ timeout: number;
9
+ }
10
+ export declare class GitHubFetcher {
11
+ private config;
12
+ private retryCount;
13
+ private retryDelay;
14
+ constructor(config?: Partial<FetcherConfig>);
15
+ /**
16
+ * Build raw GitHub URL for a file
17
+ */
18
+ private buildUrl;
19
+ /**
20
+ * Fetch content from URL with retry logic
21
+ */
22
+ private fetchWithRetry;
23
+ /**
24
+ * Fetch template manifest
25
+ */
26
+ fetchManifest(): Promise<FetchResult<TemplateManifest>>;
27
+ /**
28
+ * Fetch template content by path
29
+ */
30
+ fetchTemplate(templatePath: string): Promise<FetchResult<string>>;
31
+ /**
32
+ * Fetch template by category, platform, and variant
33
+ */
34
+ fetchByType(category: string, platform: string, variant?: string): Promise<FetchResult<string>>;
35
+ /**
36
+ * Check if repository is accessible
37
+ */
38
+ checkConnection(): Promise<boolean>;
39
+ /**
40
+ * Update repository configuration
41
+ */
42
+ setRepository(repository: string, branch?: string): void;
43
+ /**
44
+ * Get current configuration
45
+ */
46
+ getConfig(): FetcherConfig;
47
+ }
48
+ export declare function getGitHubFetcher(config?: Partial<FetcherConfig>): GitHubFetcher;
49
+ export declare function resetFetcher(): void;
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ /**
3
+ * Template fetcher - fetches templates from GitHub repository
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.resetFetcher = exports.getGitHubFetcher = exports.GitHubFetcher = void 0;
10
+ const https_1 = __importDefault(require("https"));
11
+ const DEFAULT_REPO = "expressots/templates";
12
+ const DEFAULT_BRANCH = "main";
13
+ const GITHUB_RAW_BASE = "https://raw.githubusercontent.com";
14
+ const FETCH_TIMEOUT = 5000; // 5 seconds for faster fallback
15
+ class GitHubFetcher {
16
+ constructor(config) {
17
+ this.retryCount = 1; // Single retry for faster fallback
18
+ this.retryDelay = 500;
19
+ this.config = {
20
+ repository: config?.repository || DEFAULT_REPO,
21
+ branch: config?.branch || DEFAULT_BRANCH,
22
+ timeout: config?.timeout || FETCH_TIMEOUT,
23
+ };
24
+ }
25
+ /**
26
+ * Build raw GitHub URL for a file
27
+ */
28
+ buildUrl(filePath) {
29
+ return `${GITHUB_RAW_BASE}/${this.config.repository}/${this.config.branch}/${filePath}`;
30
+ }
31
+ /**
32
+ * Fetch content from URL with retry logic
33
+ */
34
+ async fetchWithRetry(url, attempt = 1) {
35
+ return new Promise((resolve, reject) => {
36
+ const request = https_1.default.get(url, { timeout: this.config.timeout }, (response) => {
37
+ // Handle redirects
38
+ if (response.statusCode === 301 ||
39
+ response.statusCode === 302) {
40
+ const redirectUrl = response.headers.location;
41
+ if (redirectUrl) {
42
+ this.fetchWithRetry(redirectUrl, attempt)
43
+ .then(resolve)
44
+ .catch(reject);
45
+ return;
46
+ }
47
+ }
48
+ if (response.statusCode === 404) {
49
+ reject(new Error(`Template not found: ${url}`));
50
+ return;
51
+ }
52
+ if (response.statusCode === 403) {
53
+ // Rate limited
54
+ if (attempt < this.retryCount) {
55
+ setTimeout(() => {
56
+ this.fetchWithRetry(url, attempt + 1)
57
+ .then(resolve)
58
+ .catch(reject);
59
+ }, this.retryDelay * Math.pow(2, attempt - 1));
60
+ return;
61
+ }
62
+ reject(new Error("GitHub API rate limit exceeded"));
63
+ return;
64
+ }
65
+ if (response.statusCode !== 200) {
66
+ reject(new Error(`HTTP ${response.statusCode}: Failed to fetch ${url}`));
67
+ return;
68
+ }
69
+ let data = "";
70
+ response.on("data", (chunk) => {
71
+ data += chunk;
72
+ });
73
+ response.on("end", () => {
74
+ resolve(data);
75
+ });
76
+ });
77
+ request.on("error", (error) => {
78
+ if (attempt < this.retryCount) {
79
+ setTimeout(() => {
80
+ this.fetchWithRetry(url, attempt + 1)
81
+ .then(resolve)
82
+ .catch(reject);
83
+ }, this.retryDelay * Math.pow(2, attempt - 1));
84
+ }
85
+ else {
86
+ reject(error);
87
+ }
88
+ });
89
+ request.on("timeout", () => {
90
+ request.destroy();
91
+ if (attempt < this.retryCount) {
92
+ setTimeout(() => {
93
+ this.fetchWithRetry(url, attempt + 1)
94
+ .then(resolve)
95
+ .catch(reject);
96
+ }, this.retryDelay * Math.pow(2, attempt - 1));
97
+ }
98
+ else {
99
+ reject(new Error(`Timeout fetching ${url}`));
100
+ }
101
+ });
102
+ });
103
+ }
104
+ /**
105
+ * Fetch template manifest
106
+ */
107
+ async fetchManifest() {
108
+ try {
109
+ const url = this.buildUrl("manifest.json");
110
+ const content = await this.fetchWithRetry(url);
111
+ const manifest = JSON.parse(content);
112
+ return { data: manifest, source: "remote" };
113
+ }
114
+ catch (error) {
115
+ return {
116
+ data: null,
117
+ source: "remote",
118
+ error: error instanceof Error ? error.message : "Unknown error",
119
+ };
120
+ }
121
+ }
122
+ /**
123
+ * Fetch template content by path
124
+ */
125
+ async fetchTemplate(templatePath) {
126
+ try {
127
+ const url = this.buildUrl(templatePath);
128
+ const content = await this.fetchWithRetry(url);
129
+ return { data: content, source: "remote" };
130
+ }
131
+ catch (error) {
132
+ return {
133
+ data: null,
134
+ source: "remote",
135
+ error: error instanceof Error ? error.message : "Unknown error",
136
+ };
137
+ }
138
+ }
139
+ /**
140
+ * Fetch template by category, platform, and variant
141
+ */
142
+ async fetchByType(category, platform, variant) {
143
+ // Build the path based on category
144
+ let templatePath;
145
+ switch (category) {
146
+ case "cicd":
147
+ templatePath = `cicd/${platform}/${variant || "basic"}.yml`;
148
+ break;
149
+ case "docker":
150
+ templatePath = `docker/${platform}.tpl`;
151
+ break;
152
+ case "kubernetes":
153
+ templatePath = `kubernetes/${platform}.yml.tpl`;
154
+ break;
155
+ case "migrations":
156
+ templatePath = `migrations/${platform}/${variant || "checklist"}.md.tpl`;
157
+ break;
158
+ default:
159
+ return {
160
+ data: null,
161
+ source: "remote",
162
+ error: `Unknown template category: ${category}`,
163
+ };
164
+ }
165
+ return this.fetchTemplate(templatePath);
166
+ }
167
+ /**
168
+ * Check if repository is accessible
169
+ */
170
+ async checkConnection() {
171
+ try {
172
+ const result = await this.fetchManifest();
173
+ return result.data !== null;
174
+ }
175
+ catch {
176
+ return false;
177
+ }
178
+ }
179
+ /**
180
+ * Update repository configuration
181
+ */
182
+ setRepository(repository, branch) {
183
+ this.config.repository = repository;
184
+ if (branch) {
185
+ this.config.branch = branch;
186
+ }
187
+ }
188
+ /**
189
+ * Get current configuration
190
+ */
191
+ getConfig() {
192
+ return { ...this.config };
193
+ }
194
+ }
195
+ exports.GitHubFetcher = GitHubFetcher;
196
+ // Singleton instance
197
+ let fetcherInstance = null;
198
+ function getGitHubFetcher(config) {
199
+ if (!fetcherInstance) {
200
+ fetcherInstance = new GitHubFetcher(config);
201
+ }
202
+ return fetcherInstance;
203
+ }
204
+ exports.getGitHubFetcher = getGitHubFetcher;
205
+ function resetFetcher() {
206
+ fetcherInstance = null;
207
+ }
208
+ exports.resetFetcher = resetFetcher;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Template system exports
3
+ */
4
+ export * from "./types";
5
+ export { TemplateCache, getTemplateCache } from "./cache";
6
+ export { GitHubFetcher, getGitHubFetcher, resetFetcher } from "./fetcher";
7
+ export { TemplateRenderer, getTemplateRenderer } from "./renderer";
8
+ export { TemplateManager, getTemplateManager, resetTemplateManager, } from "./manager";
9
+ export { templatesCommand } from "./cli";
10
+ export type { TemplateManagerConfig } from "./manager";
11
+ export type { FetcherConfig } from "./fetcher";
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ /**
3
+ * Template system exports
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
17
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.templatesCommand = exports.resetTemplateManager = exports.getTemplateManager = exports.TemplateManager = exports.getTemplateRenderer = exports.TemplateRenderer = exports.resetFetcher = exports.getGitHubFetcher = exports.GitHubFetcher = exports.getTemplateCache = exports.TemplateCache = void 0;
21
+ __exportStar(require("./types"), exports);
22
+ var cache_1 = require("./cache");
23
+ Object.defineProperty(exports, "TemplateCache", { enumerable: true, get: function () { return cache_1.TemplateCache; } });
24
+ Object.defineProperty(exports, "getTemplateCache", { enumerable: true, get: function () { return cache_1.getTemplateCache; } });
25
+ var fetcher_1 = require("./fetcher");
26
+ Object.defineProperty(exports, "GitHubFetcher", { enumerable: true, get: function () { return fetcher_1.GitHubFetcher; } });
27
+ Object.defineProperty(exports, "getGitHubFetcher", { enumerable: true, get: function () { return fetcher_1.getGitHubFetcher; } });
28
+ Object.defineProperty(exports, "resetFetcher", { enumerable: true, get: function () { return fetcher_1.resetFetcher; } });
29
+ var renderer_1 = require("./renderer");
30
+ Object.defineProperty(exports, "TemplateRenderer", { enumerable: true, get: function () { return renderer_1.TemplateRenderer; } });
31
+ Object.defineProperty(exports, "getTemplateRenderer", { enumerable: true, get: function () { return renderer_1.getTemplateRenderer; } });
32
+ var manager_1 = require("./manager");
33
+ Object.defineProperty(exports, "TemplateManager", { enumerable: true, get: function () { return manager_1.TemplateManager; } });
34
+ Object.defineProperty(exports, "getTemplateManager", { enumerable: true, get: function () { return manager_1.getTemplateManager; } });
35
+ Object.defineProperty(exports, "resetTemplateManager", { enumerable: true, get: function () { return manager_1.resetTemplateManager; } });
36
+ var cli_1 = require("./cli");
37
+ Object.defineProperty(exports, "templatesCommand", { enumerable: true, get: function () { return cli_1.templatesCommand; } });