@expressots/cli 3.0.0-beta.4 → 4.0.0-preview.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -95
- package/bin/cicd/cli.d.ts +6 -0
- package/bin/cicd/cli.js +126 -0
- package/bin/cicd/form.d.ts +29 -0
- package/bin/cicd/form.js +345 -0
- package/bin/cicd/generators/azure-devops.d.ts +2 -0
- package/bin/cicd/generators/azure-devops.js +370 -0
- package/bin/cicd/generators/bitbucket.d.ts +2 -0
- package/bin/cicd/generators/bitbucket.js +217 -0
- package/bin/cicd/generators/circleci.d.ts +2 -0
- package/bin/cicd/generators/circleci.js +274 -0
- package/bin/cicd/generators/github-actions.d.ts +14 -0
- package/bin/cicd/generators/github-actions.js +426 -0
- package/bin/cicd/generators/gitlab-ci.d.ts +2 -0
- package/bin/cicd/generators/gitlab-ci.js +237 -0
- package/bin/cicd/generators/index.d.ts +6 -0
- package/bin/cicd/generators/index.js +15 -0
- package/bin/cicd/generators/jenkins.d.ts +2 -0
- package/bin/cicd/generators/jenkins.js +248 -0
- package/bin/cicd/generators/template-loader.d.ts +17 -0
- package/bin/cicd/generators/template-loader.js +128 -0
- package/bin/cicd/index.d.ts +1 -0
- package/bin/cicd/index.js +5 -0
- package/bin/cli.d.ts +1 -1
- package/bin/cli.js +18 -3
- package/bin/commands/project.commands.d.ts +19 -6
- package/bin/commands/project.commands.js +390 -61
- package/bin/config/index.d.ts +5 -0
- package/bin/config/index.js +10 -0
- package/bin/config/manager.d.ts +98 -0
- package/bin/config/manager.js +222 -0
- package/bin/containerize/analyzers/bootstrap-analyzer.d.ts +46 -0
- package/bin/containerize/analyzers/bootstrap-analyzer.js +187 -0
- package/bin/containerize/analyzers/project-analyzer.d.ts +20 -0
- package/bin/containerize/analyzers/project-analyzer.js +150 -0
- package/bin/containerize/cli.d.ts +4 -0
- package/bin/containerize/cli.js +113 -0
- package/bin/containerize/form.d.ts +15 -0
- package/bin/containerize/form.js +154 -0
- package/bin/containerize/generators/ci-generator.d.ts +31 -0
- package/bin/containerize/generators/ci-generator.js +936 -0
- package/bin/containerize/generators/docker-compose-generator.d.ts +8 -0
- package/bin/containerize/generators/docker-compose-generator.js +186 -0
- package/bin/containerize/generators/dockerfile-generator.d.ts +8 -0
- package/bin/containerize/generators/dockerfile-generator.js +635 -0
- package/bin/containerize/generators/kubernetes-generator.d.ts +8 -0
- package/bin/containerize/generators/kubernetes-generator.js +133 -0
- package/bin/containerize/generators/template-loader.d.ts +36 -0
- package/bin/containerize/generators/template-loader.js +129 -0
- package/bin/containerize/index.d.ts +4 -0
- package/bin/containerize/index.js +13 -0
- package/bin/containerize/presets/preset-registry.d.ts +20 -0
- package/bin/containerize/presets/preset-registry.js +102 -0
- package/bin/costs/cli.d.ts +5 -0
- package/bin/costs/cli.js +183 -0
- package/bin/costs/form.d.ts +44 -0
- package/bin/costs/form.js +412 -0
- package/bin/costs/index.d.ts +4 -0
- package/bin/costs/index.js +25 -0
- package/bin/costs/pricing-manager.d.ts +84 -0
- package/bin/costs/pricing-manager.js +342 -0
- package/bin/costs/providers/index.d.ts +32 -0
- package/bin/costs/providers/index.js +153 -0
- package/bin/costs/sources/api-source.d.ts +10 -0
- package/bin/costs/sources/api-source.js +32 -0
- package/bin/costs/sources/index.d.ts +6 -0
- package/bin/costs/sources/index.js +15 -0
- package/bin/costs/sources/local-json-source.d.ts +23 -0
- package/bin/costs/sources/local-json-source.js +59 -0
- package/bin/costs/sources/remote-json-source.d.ts +11 -0
- package/bin/costs/sources/remote-json-source.js +53 -0
- package/bin/costs/types.d.ts +53 -0
- package/bin/costs/types.js +5 -0
- package/bin/dev/cli.d.ts +4 -0
- package/bin/dev/cli.js +134 -0
- package/bin/dev/form.d.ts +36 -0
- package/bin/dev/form.js +254 -0
- package/bin/dev/index.d.ts +1 -0
- package/bin/dev/index.js +5 -0
- package/bin/generate/cli.js +29 -2
- package/bin/generate/form.d.ts +5 -1
- package/bin/generate/form.js +3 -3
- package/bin/generate/templates/nonopinionated/config.tpl +12 -0
- package/bin/generate/templates/nonopinionated/event.tpl +10 -0
- package/bin/generate/templates/nonopinionated/guard.tpl +18 -0
- package/bin/generate/templates/nonopinionated/handler.tpl +12 -0
- package/bin/generate/templates/nonopinionated/interceptor.tpl +27 -0
- package/bin/generate/templates/opinionated/config.tpl +47 -0
- package/bin/generate/templates/opinionated/entity.tpl +1 -8
- package/bin/generate/templates/opinionated/event.tpl +15 -0
- package/bin/generate/templates/opinionated/guard.tpl +41 -0
- package/bin/generate/templates/opinionated/handler.tpl +23 -0
- package/bin/generate/templates/opinionated/interceptor.tpl +50 -0
- package/bin/generate/utils/command-utils.d.ts +7 -3
- package/bin/generate/utils/command-utils.js +95 -31
- package/bin/generate/utils/nonopininated-cmd.d.ts +10 -1
- package/bin/generate/utils/nonopininated-cmd.js +100 -1
- package/bin/generate/utils/opinionated-cmd.d.ts +10 -1
- package/bin/generate/utils/opinionated-cmd.js +112 -7
- package/bin/generate/utils/string-utils.d.ts +6 -0
- package/bin/generate/utils/string-utils.js +13 -1
- package/bin/help/form.js +11 -3
- package/bin/migrate/analyzers/platform-detector.d.ts +14 -0
- package/bin/migrate/analyzers/platform-detector.js +116 -0
- package/bin/migrate/cli.d.ts +6 -0
- package/bin/migrate/cli.js +96 -0
- package/bin/migrate/form.d.ts +25 -0
- package/bin/migrate/form.js +347 -0
- package/bin/migrate/generators/compose-to-k8s.d.ts +2 -0
- package/bin/migrate/generators/compose-to-k8s.js +324 -0
- package/bin/migrate/generators/compose-to-railway.d.ts +2 -0
- package/bin/migrate/generators/compose-to-railway.js +138 -0
- package/bin/migrate/generators/compose-to-render.d.ts +2 -0
- package/bin/migrate/generators/compose-to-render.js +148 -0
- package/bin/migrate/generators/generic-migration.d.ts +9 -0
- package/bin/migrate/generators/generic-migration.js +221 -0
- package/bin/migrate/generators/heroku-to-fly.d.ts +2 -0
- package/bin/migrate/generators/heroku-to-fly.js +291 -0
- package/bin/migrate/generators/heroku-to-railway.d.ts +2 -0
- package/bin/migrate/generators/heroku-to-railway.js +283 -0
- package/bin/migrate/generators/heroku-to-render.d.ts +2 -0
- package/bin/migrate/generators/heroku-to-render.js +148 -0
- package/bin/migrate/generators/index.d.ts +7 -0
- package/bin/migrate/generators/index.js +17 -0
- package/bin/migrate/generators/template-loader.d.ts +21 -0
- package/bin/migrate/generators/template-loader.js +59 -0
- package/bin/migrate/index.d.ts +1 -0
- package/bin/migrate/index.js +5 -0
- package/bin/new/cli.js +21 -6
- package/bin/new/form.d.ts +25 -4
- package/bin/new/form.js +285 -70
- package/bin/profile/analyzers/dockerfile-analyzer.d.ts +27 -0
- package/bin/profile/analyzers/dockerfile-analyzer.js +122 -0
- package/bin/profile/analyzers/image-analyzer.d.ts +19 -0
- package/bin/profile/analyzers/image-analyzer.js +85 -0
- package/bin/profile/cli.d.ts +4 -0
- package/bin/profile/cli.js +92 -0
- package/bin/profile/form.d.ts +56 -0
- package/bin/profile/form.js +400 -0
- package/bin/profile/index.d.ts +1 -0
- package/bin/profile/index.js +5 -0
- package/bin/profile/optimizers/index.d.ts +19 -0
- package/bin/profile/optimizers/index.js +137 -0
- package/bin/providers/add/form.d.ts +1 -1
- package/bin/providers/add/form.js +27 -6
- package/bin/providers/create/form.js +2 -1
- package/bin/scripts/form.js +27 -5
- package/bin/studio/cli.d.ts +15 -0
- package/bin/studio/cli.js +166 -0
- package/bin/studio/index.d.ts +5 -0
- package/bin/studio/index.js +9 -0
- package/bin/templates/cache.d.ts +54 -0
- package/bin/templates/cache.js +180 -0
- package/bin/templates/cli.d.ts +8 -0
- package/bin/templates/cli.js +292 -0
- package/bin/templates/fetcher.d.ts +49 -0
- package/bin/templates/fetcher.js +208 -0
- package/bin/templates/index.d.ts +11 -0
- package/bin/templates/index.js +37 -0
- package/bin/templates/manager.d.ts +116 -0
- package/bin/templates/manager.js +323 -0
- package/bin/templates/renderer.d.ts +49 -0
- package/bin/templates/renderer.js +204 -0
- package/bin/templates/types.d.ts +51 -0
- package/bin/templates/types.js +5 -0
- package/bin/utils/add-module-to-container.d.ts +2 -2
- package/bin/utils/add-module-to-container.js +15 -5
- package/bin/utils/cli-ui.d.ts +30 -3
- package/bin/utils/cli-ui.js +95 -13
- package/bin/utils/index.d.ts +4 -0
- package/bin/utils/index.js +4 -0
- package/bin/utils/input-validation.d.ts +50 -0
- package/bin/utils/input-validation.js +143 -0
- package/bin/utils/package-manager-commands.d.ts +24 -0
- package/bin/utils/package-manager-commands.js +50 -0
- package/bin/utils/safe-spawn.d.ts +35 -0
- package/bin/utils/safe-spawn.js +51 -0
- package/bin/utils/update-tsconfig-paths.d.ts +35 -0
- package/bin/utils/update-tsconfig-paths.js +286 -0
- package/package.json +154 -154
|
@@ -0,0 +1,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; } });
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template Manager - orchestrates template fetching, caching, and rendering
|
|
3
|
+
*/
|
|
4
|
+
import type { TemplateCategory, CICDPlatform, CIStrategy, TemplateManifest, RenderOptions, FetchResult } from "./types";
|
|
5
|
+
export interface TemplateManagerConfig {
|
|
6
|
+
repository?: string;
|
|
7
|
+
branch?: string;
|
|
8
|
+
cacheTTL?: number;
|
|
9
|
+
offline?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare class TemplateManager {
|
|
12
|
+
private cache;
|
|
13
|
+
private fetcher;
|
|
14
|
+
private renderer;
|
|
15
|
+
private offline;
|
|
16
|
+
private manifest;
|
|
17
|
+
constructor(config?: TemplateManagerConfig);
|
|
18
|
+
/**
|
|
19
|
+
* Fetch and cache the template manifest
|
|
20
|
+
*/
|
|
21
|
+
getManifest(forceRefresh?: boolean): Promise<TemplateManifest | null>;
|
|
22
|
+
/**
|
|
23
|
+
* Fetch a template by type
|
|
24
|
+
*/
|
|
25
|
+
fetchTemplate(category: TemplateCategory, platform: string, variant?: string): Promise<FetchResult<string>>;
|
|
26
|
+
/**
|
|
27
|
+
* Fetch CI/CD template
|
|
28
|
+
*/
|
|
29
|
+
fetchCICDTemplate(platform: CICDPlatform, strategy?: CIStrategy): Promise<FetchResult<string>>;
|
|
30
|
+
/**
|
|
31
|
+
* Fetch Docker template
|
|
32
|
+
*/
|
|
33
|
+
fetchDockerTemplate(type: string): Promise<FetchResult<string>>;
|
|
34
|
+
/**
|
|
35
|
+
* Fetch Kubernetes template
|
|
36
|
+
*/
|
|
37
|
+
fetchKubernetesTemplate(type: string): Promise<FetchResult<string>>;
|
|
38
|
+
/**
|
|
39
|
+
* Fetch migration template
|
|
40
|
+
*/
|
|
41
|
+
fetchMigrationTemplate(from: string, to: string, file?: string): Promise<FetchResult<string>>;
|
|
42
|
+
/**
|
|
43
|
+
* Render a template with variables
|
|
44
|
+
*/
|
|
45
|
+
render(template: string, options: RenderOptions): string;
|
|
46
|
+
/**
|
|
47
|
+
* Fetch and render template in one step
|
|
48
|
+
*/
|
|
49
|
+
fetchAndRender(category: TemplateCategory, platform: string, variant: string | undefined, renderOptions: RenderOptions): Promise<FetchResult<string>>;
|
|
50
|
+
/**
|
|
51
|
+
* Update all cached templates
|
|
52
|
+
*/
|
|
53
|
+
updateCache(): Promise<{
|
|
54
|
+
updated: number;
|
|
55
|
+
errors: string[];
|
|
56
|
+
}>;
|
|
57
|
+
/**
|
|
58
|
+
* Clear template cache
|
|
59
|
+
*/
|
|
60
|
+
clearCache(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Get cache statistics
|
|
63
|
+
*/
|
|
64
|
+
getCacheStats(): {
|
|
65
|
+
files: number;
|
|
66
|
+
totalSize: number;
|
|
67
|
+
oldestEntry: Date | null;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* List available templates
|
|
71
|
+
*/
|
|
72
|
+
listTemplates(): Promise<{
|
|
73
|
+
cicd: Record<string, string[]>;
|
|
74
|
+
docker: string[];
|
|
75
|
+
kubernetes: string[];
|
|
76
|
+
migrations: string[];
|
|
77
|
+
source: "remote" | "embedded";
|
|
78
|
+
}>;
|
|
79
|
+
/**
|
|
80
|
+
* Get list of embedded templates (fallback when remote unavailable)
|
|
81
|
+
*/
|
|
82
|
+
private getEmbeddedTemplatesList;
|
|
83
|
+
/**
|
|
84
|
+
* Set repository for template fetching
|
|
85
|
+
*/
|
|
86
|
+
setRepository(repository: string, branch?: string): void;
|
|
87
|
+
/**
|
|
88
|
+
* Set offline mode
|
|
89
|
+
*/
|
|
90
|
+
setOfflineMode(offline: boolean): void;
|
|
91
|
+
/**
|
|
92
|
+
* Check if templates are available (cached or remote)
|
|
93
|
+
*/
|
|
94
|
+
checkAvailability(): Promise<{
|
|
95
|
+
online: boolean;
|
|
96
|
+
cached: boolean;
|
|
97
|
+
manifest: boolean;
|
|
98
|
+
}>;
|
|
99
|
+
/**
|
|
100
|
+
* Validate a template
|
|
101
|
+
*/
|
|
102
|
+
validateTemplate(template: string): {
|
|
103
|
+
valid: boolean;
|
|
104
|
+
errors: string[];
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Extract variables from template
|
|
108
|
+
*/
|
|
109
|
+
extractVariables(template: string): string[];
|
|
110
|
+
/**
|
|
111
|
+
* Print template status (for CLI output)
|
|
112
|
+
*/
|
|
113
|
+
printStatus(): Promise<void>;
|
|
114
|
+
}
|
|
115
|
+
export declare function getTemplateManager(config?: TemplateManagerConfig): TemplateManager;
|
|
116
|
+
export declare function resetTemplateManager(): void;
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Template Manager - orchestrates template fetching, caching, and rendering
|
|
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.resetTemplateManager = exports.getTemplateManager = exports.TemplateManager = void 0;
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const cache_1 = require("./cache");
|
|
12
|
+
const fetcher_1 = require("./fetcher");
|
|
13
|
+
const renderer_1 = require("./renderer");
|
|
14
|
+
class TemplateManager {
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.manifest = null;
|
|
17
|
+
this.cache = (0, cache_1.getTemplateCache)({ ttl: config?.cacheTTL });
|
|
18
|
+
this.fetcher = (0, fetcher_1.getGitHubFetcher)({
|
|
19
|
+
repository: config?.repository,
|
|
20
|
+
branch: config?.branch,
|
|
21
|
+
});
|
|
22
|
+
this.renderer = (0, renderer_1.getTemplateRenderer)();
|
|
23
|
+
this.offline = config?.offline ?? false;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Fetch and cache the template manifest
|
|
27
|
+
*/
|
|
28
|
+
async getManifest(forceRefresh = false) {
|
|
29
|
+
// Check memory cache first
|
|
30
|
+
if (this.manifest && !forceRefresh) {
|
|
31
|
+
return this.manifest;
|
|
32
|
+
}
|
|
33
|
+
// Check disk cache
|
|
34
|
+
if (!forceRefresh) {
|
|
35
|
+
const cached = this.cache.get("manifest", "root");
|
|
36
|
+
if (cached) {
|
|
37
|
+
this.manifest = cached;
|
|
38
|
+
return cached;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Fetch from remote (if not offline)
|
|
42
|
+
if (!this.offline) {
|
|
43
|
+
const result = await this.fetcher.fetchManifest();
|
|
44
|
+
if (result.data) {
|
|
45
|
+
this.manifest = result.data;
|
|
46
|
+
this.cache.set("manifest", "root", result.data);
|
|
47
|
+
return result.data;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Fetch a template by type
|
|
54
|
+
*/
|
|
55
|
+
async fetchTemplate(category, platform, variant) {
|
|
56
|
+
const cacheKey = variant ? `${platform}-${variant}` : platform;
|
|
57
|
+
// Check cache first
|
|
58
|
+
const cached = this.cache.get(category, cacheKey);
|
|
59
|
+
if (cached) {
|
|
60
|
+
return { data: cached, source: "cache" };
|
|
61
|
+
}
|
|
62
|
+
// If offline, return null
|
|
63
|
+
if (this.offline) {
|
|
64
|
+
return {
|
|
65
|
+
data: null,
|
|
66
|
+
source: "cache",
|
|
67
|
+
error: "Offline mode - template not in cache",
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// Fetch from remote
|
|
71
|
+
const result = await this.fetcher.fetchByType(category, platform, variant);
|
|
72
|
+
if (result.data) {
|
|
73
|
+
// Cache the template
|
|
74
|
+
this.cache.set(category, cacheKey, result.data);
|
|
75
|
+
return { data: result.data, source: "remote" };
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Fetch CI/CD template
|
|
81
|
+
*/
|
|
82
|
+
async fetchCICDTemplate(platform, strategy = "basic") {
|
|
83
|
+
return this.fetchTemplate("cicd", platform, strategy);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Fetch Docker template
|
|
87
|
+
*/
|
|
88
|
+
async fetchDockerTemplate(type) {
|
|
89
|
+
return this.fetchTemplate("docker", type);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Fetch Kubernetes template
|
|
93
|
+
*/
|
|
94
|
+
async fetchKubernetesTemplate(type) {
|
|
95
|
+
return this.fetchTemplate("kubernetes", type);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Fetch migration template
|
|
99
|
+
*/
|
|
100
|
+
async fetchMigrationTemplate(from, to, file) {
|
|
101
|
+
const migrationPath = `${from}-to-${to}`;
|
|
102
|
+
return this.fetchTemplate("migrations", migrationPath, file);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Render a template with variables
|
|
106
|
+
*/
|
|
107
|
+
render(template, options) {
|
|
108
|
+
return this.renderer.render(template, options);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Fetch and render template in one step
|
|
112
|
+
*/
|
|
113
|
+
async fetchAndRender(category, platform, variant, renderOptions) {
|
|
114
|
+
const fetchResult = await this.fetchTemplate(category, platform, variant);
|
|
115
|
+
if (!fetchResult.data) {
|
|
116
|
+
return fetchResult;
|
|
117
|
+
}
|
|
118
|
+
const rendered = this.render(fetchResult.data, renderOptions);
|
|
119
|
+
return { data: rendered, source: fetchResult.source };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Update all cached templates
|
|
123
|
+
*/
|
|
124
|
+
async updateCache() {
|
|
125
|
+
const errors = [];
|
|
126
|
+
let updated = 0;
|
|
127
|
+
// Fetch fresh manifest
|
|
128
|
+
const manifest = await this.getManifest(true);
|
|
129
|
+
if (!manifest) {
|
|
130
|
+
return { updated: 0, errors: ["Failed to fetch manifest"] };
|
|
131
|
+
}
|
|
132
|
+
// Update CI/CD templates
|
|
133
|
+
if (manifest.templates.cicd) {
|
|
134
|
+
for (const [platform, strategies] of Object.entries(manifest.templates.cicd)) {
|
|
135
|
+
for (const [strategy, info] of Object.entries(strategies)) {
|
|
136
|
+
const result = await this.fetcher.fetchTemplate(info.path);
|
|
137
|
+
if (result.data) {
|
|
138
|
+
this.cache.set("cicd", `${platform}-${strategy}`, result.data);
|
|
139
|
+
updated++;
|
|
140
|
+
}
|
|
141
|
+
else if (result.error) {
|
|
142
|
+
errors.push(`${platform}/${strategy}: ${result.error}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Update Docker templates
|
|
148
|
+
if (manifest.templates.docker) {
|
|
149
|
+
for (const [type, info] of Object.entries(manifest.templates.docker)) {
|
|
150
|
+
const result = await this.fetcher.fetchTemplate(info.path);
|
|
151
|
+
if (result.data) {
|
|
152
|
+
this.cache.set("docker", type, result.data);
|
|
153
|
+
updated++;
|
|
154
|
+
}
|
|
155
|
+
else if (result.error) {
|
|
156
|
+
errors.push(`docker/${type}: ${result.error}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Update Kubernetes templates
|
|
161
|
+
if (manifest.templates.kubernetes) {
|
|
162
|
+
for (const [type, info] of Object.entries(manifest.templates.kubernetes)) {
|
|
163
|
+
const result = await this.fetcher.fetchTemplate(info.path);
|
|
164
|
+
if (result.data) {
|
|
165
|
+
this.cache.set("kubernetes", type, result.data);
|
|
166
|
+
updated++;
|
|
167
|
+
}
|
|
168
|
+
else if (result.error) {
|
|
169
|
+
errors.push(`kubernetes/${type}: ${result.error}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return { updated, errors };
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Clear template cache
|
|
177
|
+
*/
|
|
178
|
+
clearCache() {
|
|
179
|
+
this.cache.clear();
|
|
180
|
+
this.manifest = null;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get cache statistics
|
|
184
|
+
*/
|
|
185
|
+
getCacheStats() {
|
|
186
|
+
return this.cache.getStats();
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* List available templates
|
|
190
|
+
*/
|
|
191
|
+
async listTemplates() {
|
|
192
|
+
const manifest = await this.getManifest();
|
|
193
|
+
// If remote manifest available, use it
|
|
194
|
+
if (manifest) {
|
|
195
|
+
const result = {
|
|
196
|
+
cicd: {},
|
|
197
|
+
docker: [],
|
|
198
|
+
kubernetes: [],
|
|
199
|
+
migrations: [],
|
|
200
|
+
source: "remote",
|
|
201
|
+
};
|
|
202
|
+
// CI/CD templates
|
|
203
|
+
if (manifest.templates.cicd) {
|
|
204
|
+
for (const [platform, strategies] of Object.entries(manifest.templates.cicd)) {
|
|
205
|
+
result.cicd[platform] = Object.keys(strategies);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Docker templates
|
|
209
|
+
if (manifest.templates.docker) {
|
|
210
|
+
result.docker = Object.keys(manifest.templates.docker);
|
|
211
|
+
}
|
|
212
|
+
// Kubernetes templates
|
|
213
|
+
if (manifest.templates.kubernetes) {
|
|
214
|
+
result.kubernetes = Object.keys(manifest.templates.kubernetes);
|
|
215
|
+
}
|
|
216
|
+
// Migration templates
|
|
217
|
+
if (manifest.templates.migrations) {
|
|
218
|
+
for (const [from, targets] of Object.entries(manifest.templates.migrations)) {
|
|
219
|
+
for (const to of Object.keys(targets)) {
|
|
220
|
+
result.migrations.push(`${from} → ${to}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
// Fallback to embedded templates list
|
|
227
|
+
return this.getEmbeddedTemplatesList();
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Get list of embedded templates (fallback when remote unavailable)
|
|
231
|
+
*/
|
|
232
|
+
getEmbeddedTemplatesList() {
|
|
233
|
+
return {
|
|
234
|
+
cicd: {
|
|
235
|
+
github: ["basic", "comprehensive", "security-focused"],
|
|
236
|
+
gitlab: ["basic", "comprehensive", "security-focused"],
|
|
237
|
+
circleci: ["basic", "comprehensive"],
|
|
238
|
+
jenkins: ["basic"],
|
|
239
|
+
bitbucket: ["basic"],
|
|
240
|
+
azure: ["basic"],
|
|
241
|
+
},
|
|
242
|
+
docker: [
|
|
243
|
+
"production",
|
|
244
|
+
"development",
|
|
245
|
+
"compose",
|
|
246
|
+
"compose-development",
|
|
247
|
+
],
|
|
248
|
+
kubernetes: ["deployment", "service", "configmap", "ingress"],
|
|
249
|
+
migrations: [
|
|
250
|
+
"heroku → railway",
|
|
251
|
+
"heroku → render",
|
|
252
|
+
"heroku → fly",
|
|
253
|
+
"compose → kubernetes",
|
|
254
|
+
],
|
|
255
|
+
source: "embedded",
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Set repository for template fetching
|
|
260
|
+
*/
|
|
261
|
+
setRepository(repository, branch) {
|
|
262
|
+
this.fetcher.setRepository(repository, branch);
|
|
263
|
+
// Clear cache when repository changes
|
|
264
|
+
this.clearCache();
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Set offline mode
|
|
268
|
+
*/
|
|
269
|
+
setOfflineMode(offline) {
|
|
270
|
+
this.offline = offline;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Check if templates are available (cached or remote)
|
|
274
|
+
*/
|
|
275
|
+
async checkAvailability() {
|
|
276
|
+
const online = !this.offline && (await this.fetcher.checkConnection());
|
|
277
|
+
const cached = this.cache.getStats().files > 0;
|
|
278
|
+
const manifest = (await this.getManifest()) !== null;
|
|
279
|
+
return { online, cached, manifest };
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Validate a template
|
|
283
|
+
*/
|
|
284
|
+
validateTemplate(template) {
|
|
285
|
+
return this.renderer.validateTemplate(template);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Extract variables from template
|
|
289
|
+
*/
|
|
290
|
+
extractVariables(template) {
|
|
291
|
+
return this.renderer.extractVariables(template);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Print template status (for CLI output)
|
|
295
|
+
*/
|
|
296
|
+
async printStatus() {
|
|
297
|
+
const availability = await this.checkAvailability();
|
|
298
|
+
const stats = this.getCacheStats();
|
|
299
|
+
console.log(chalk_1.default.bold("\nTemplate System Status:\n"));
|
|
300
|
+
console.log(` Online: ${availability.online ? chalk_1.default.green("✓") : chalk_1.default.red("✗")}`);
|
|
301
|
+
console.log(` Cached: ${availability.cached ? chalk_1.default.green("✓") : chalk_1.default.yellow("No templates cached")}`);
|
|
302
|
+
console.log(` Manifest: ${availability.manifest ? chalk_1.default.green("✓") : chalk_1.default.yellow("Not loaded")}`);
|
|
303
|
+
console.log(chalk_1.default.bold("\nCache Statistics:\n"));
|
|
304
|
+
console.log(` Files: ${stats.files}`);
|
|
305
|
+
console.log(` Size: ${(stats.totalSize / 1024).toFixed(2)} KB`);
|
|
306
|
+
console.log(` Oldest: ${stats.oldestEntry?.toLocaleString() || "N/A"}`);
|
|
307
|
+
console.log(` Location: ${this.cache.getCacheDirectory()}`);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
exports.TemplateManager = TemplateManager;
|
|
311
|
+
// Singleton instance
|
|
312
|
+
let managerInstance = null;
|
|
313
|
+
function getTemplateManager(config) {
|
|
314
|
+
if (!managerInstance) {
|
|
315
|
+
managerInstance = new TemplateManager(config);
|
|
316
|
+
}
|
|
317
|
+
return managerInstance;
|
|
318
|
+
}
|
|
319
|
+
exports.getTemplateManager = getTemplateManager;
|
|
320
|
+
function resetTemplateManager() {
|
|
321
|
+
managerInstance = null;
|
|
322
|
+
}
|
|
323
|
+
exports.resetTemplateManager = resetTemplateManager;
|