@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,98 @@
1
+ /**
2
+ * Global configuration manager for ExpressoTS CLI
3
+ * Manages user preferences stored in ~/.expressots/config.json
4
+ */
5
+ export interface TemplateConfig {
6
+ repository: string;
7
+ branch: string;
8
+ cacheTTL: number;
9
+ }
10
+ export interface PricingConfig {
11
+ sources: ("api" | "remote" | "local")[];
12
+ cacheTTL: number;
13
+ customFile: string | null;
14
+ }
15
+ export interface GlobalConfig {
16
+ templates: TemplateConfig;
17
+ pricing: PricingConfig;
18
+ offline: boolean;
19
+ }
20
+ export declare class ConfigManager {
21
+ private config;
22
+ private configPath;
23
+ constructor();
24
+ /**
25
+ * Ensure config directory exists
26
+ */
27
+ private ensureConfigDir;
28
+ /**
29
+ * Load configuration from file
30
+ */
31
+ private load;
32
+ /**
33
+ * Merge loaded config with defaults
34
+ */
35
+ private mergeWithDefaults;
36
+ /**
37
+ * Save configuration to file
38
+ */
39
+ save(): void;
40
+ /**
41
+ * Get full configuration
42
+ */
43
+ getConfig(): GlobalConfig;
44
+ /**
45
+ * Get template configuration
46
+ */
47
+ getTemplateConfig(): TemplateConfig;
48
+ /**
49
+ * Get pricing configuration
50
+ */
51
+ getPricingConfig(): PricingConfig;
52
+ /**
53
+ * Set template repository
54
+ */
55
+ setTemplateRepository(repository: string, branch?: string): void;
56
+ /**
57
+ * Reset template repository to default
58
+ */
59
+ resetTemplateRepository(): void;
60
+ /**
61
+ * Set template cache TTL
62
+ */
63
+ setTemplateCacheTTL(ttl: number): void;
64
+ /**
65
+ * Set pricing sources
66
+ */
67
+ setPricingSources(sources: ("api" | "remote" | "local")[]): void;
68
+ /**
69
+ * Set custom pricing file
70
+ */
71
+ setCustomPricingFile(filePath: string | null): void;
72
+ /**
73
+ * Set pricing cache TTL
74
+ */
75
+ setPricingCacheTTL(ttl: number): void;
76
+ /**
77
+ * Set offline mode
78
+ */
79
+ setOfflineMode(offline: boolean): void;
80
+ /**
81
+ * Get offline mode
82
+ */
83
+ isOffline(): boolean;
84
+ /**
85
+ * Reset all configuration to defaults
86
+ */
87
+ reset(): void;
88
+ /**
89
+ * Get config file path
90
+ */
91
+ getConfigPath(): string;
92
+ /**
93
+ * Get config directory path
94
+ */
95
+ getConfigDir(): string;
96
+ }
97
+ export declare function getConfigManager(): ConfigManager;
98
+ export declare function resetConfigManager(): void;
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ /**
3
+ * Global configuration manager for ExpressoTS CLI
4
+ * Manages user preferences stored in ~/.expressots/config.json
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.resetConfigManager = exports.getConfigManager = exports.ConfigManager = void 0;
11
+ const fs_1 = __importDefault(require("fs"));
12
+ const path_1 = __importDefault(require("path"));
13
+ const os_1 = __importDefault(require("os"));
14
+ const cli_ui_1 = require("../utils/cli-ui");
15
+ const CONFIG_DIR = path_1.default.join(os_1.default.homedir(), ".expressots");
16
+ const CONFIG_FILE = path_1.default.join(CONFIG_DIR, "config.json");
17
+ const DEFAULT_CONFIG = {
18
+ templates: {
19
+ repository: "expressots/templates",
20
+ branch: "main",
21
+ cacheTTL: 86400, // 24 hours
22
+ },
23
+ pricing: {
24
+ sources: ["api", "remote", "local"],
25
+ cacheTTL: 21600,
26
+ customFile: null,
27
+ },
28
+ offline: false,
29
+ };
30
+ /**
31
+ * Returns a deep clone of the default config so callers can mutate
32
+ * their copy without poisoning the module-level constant. A previous
33
+ * implementation used `{ ...DEFAULT_CONFIG }` which kept the inner
34
+ * `templates`/`pricing` objects shared, so `setTemplateRepository`
35
+ * mutated the defaults and broke `reset()`.
36
+ */
37
+ function freshDefaults() {
38
+ return {
39
+ templates: { ...DEFAULT_CONFIG.templates },
40
+ pricing: {
41
+ ...DEFAULT_CONFIG.pricing,
42
+ sources: [...DEFAULT_CONFIG.pricing.sources],
43
+ },
44
+ offline: DEFAULT_CONFIG.offline,
45
+ };
46
+ }
47
+ class ConfigManager {
48
+ constructor() {
49
+ this.configPath = CONFIG_FILE;
50
+ this.config = this.load();
51
+ }
52
+ /**
53
+ * Ensure config directory exists
54
+ */
55
+ ensureConfigDir() {
56
+ if (!fs_1.default.existsSync(CONFIG_DIR)) {
57
+ fs_1.default.mkdirSync(CONFIG_DIR, { recursive: true });
58
+ }
59
+ }
60
+ /**
61
+ * Load configuration from file
62
+ */
63
+ load() {
64
+ if (!fs_1.default.existsSync(this.configPath)) {
65
+ return freshDefaults();
66
+ }
67
+ let content;
68
+ try {
69
+ content = fs_1.default.readFileSync(this.configPath, "utf-8");
70
+ }
71
+ catch (err) {
72
+ (0, cli_ui_1.printWarning)(`Could not read ${this.configPath}: ${err.message}. Falling back to defaults.`, "config");
73
+ return freshDefaults();
74
+ }
75
+ try {
76
+ const loaded = JSON.parse(content);
77
+ if (loaded === null ||
78
+ typeof loaded !== "object" ||
79
+ Array.isArray(loaded)) {
80
+ (0, cli_ui_1.printWarning)(`${this.configPath} is not a JSON object. Falling back to defaults.`, "config");
81
+ return freshDefaults();
82
+ }
83
+ return this.mergeWithDefaults(loaded);
84
+ }
85
+ catch (err) {
86
+ (0, cli_ui_1.printWarning)(`${this.configPath} is not valid JSON: ${err.message}. Falling back to defaults.`, "config");
87
+ return freshDefaults();
88
+ }
89
+ }
90
+ /**
91
+ * Merge loaded config with defaults
92
+ */
93
+ mergeWithDefaults(loaded) {
94
+ return {
95
+ templates: {
96
+ ...DEFAULT_CONFIG.templates,
97
+ ...loaded.templates,
98
+ },
99
+ pricing: {
100
+ ...DEFAULT_CONFIG.pricing,
101
+ ...loaded.pricing,
102
+ },
103
+ offline: loaded.offline ?? DEFAULT_CONFIG.offline,
104
+ };
105
+ }
106
+ /**
107
+ * Save configuration to file
108
+ */
109
+ save() {
110
+ this.ensureConfigDir();
111
+ fs_1.default.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2), "utf-8");
112
+ }
113
+ /**
114
+ * Get full configuration
115
+ */
116
+ getConfig() {
117
+ return { ...this.config };
118
+ }
119
+ /**
120
+ * Get template configuration
121
+ */
122
+ getTemplateConfig() {
123
+ return { ...this.config.templates };
124
+ }
125
+ /**
126
+ * Get pricing configuration
127
+ */
128
+ getPricingConfig() {
129
+ return { ...this.config.pricing };
130
+ }
131
+ /**
132
+ * Set template repository
133
+ */
134
+ setTemplateRepository(repository, branch) {
135
+ this.config.templates.repository = repository;
136
+ if (branch) {
137
+ this.config.templates.branch = branch;
138
+ }
139
+ this.save();
140
+ }
141
+ /**
142
+ * Reset template repository to default
143
+ */
144
+ resetTemplateRepository() {
145
+ this.config.templates = { ...DEFAULT_CONFIG.templates };
146
+ this.save();
147
+ }
148
+ /**
149
+ * Set template cache TTL
150
+ */
151
+ setTemplateCacheTTL(ttl) {
152
+ this.config.templates.cacheTTL = ttl;
153
+ this.save();
154
+ }
155
+ /**
156
+ * Set pricing sources
157
+ */
158
+ setPricingSources(sources) {
159
+ this.config.pricing.sources = sources;
160
+ this.save();
161
+ }
162
+ /**
163
+ * Set custom pricing file
164
+ */
165
+ setCustomPricingFile(filePath) {
166
+ this.config.pricing.customFile = filePath;
167
+ this.save();
168
+ }
169
+ /**
170
+ * Set pricing cache TTL
171
+ */
172
+ setPricingCacheTTL(ttl) {
173
+ this.config.pricing.cacheTTL = ttl;
174
+ this.save();
175
+ }
176
+ /**
177
+ * Set offline mode
178
+ */
179
+ setOfflineMode(offline) {
180
+ this.config.offline = offline;
181
+ this.save();
182
+ }
183
+ /**
184
+ * Get offline mode
185
+ */
186
+ isOffline() {
187
+ return this.config.offline;
188
+ }
189
+ /**
190
+ * Reset all configuration to defaults
191
+ */
192
+ reset() {
193
+ this.config = freshDefaults();
194
+ this.save();
195
+ }
196
+ /**
197
+ * Get config file path
198
+ */
199
+ getConfigPath() {
200
+ return this.configPath;
201
+ }
202
+ /**
203
+ * Get config directory path
204
+ */
205
+ getConfigDir() {
206
+ return CONFIG_DIR;
207
+ }
208
+ }
209
+ exports.ConfigManager = ConfigManager;
210
+ // Singleton instance
211
+ let configInstance = null;
212
+ function getConfigManager() {
213
+ if (!configInstance) {
214
+ configInstance = new ConfigManager();
215
+ }
216
+ return configInstance;
217
+ }
218
+ exports.getConfigManager = getConfigManager;
219
+ function resetConfigManager() {
220
+ configInstance = null;
221
+ }
222
+ exports.resetConfigManager = resetConfigManager;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Environment file mapping from bootstrap configuration
3
+ */
4
+ export interface EnvFileMapping {
5
+ [environment: string]: string;
6
+ }
7
+ /**
8
+ * Bootstrap configuration detected from main.ts
9
+ */
10
+ export interface BootstrapConfig {
11
+ /** Whether envFileConfig is used */
12
+ hasEnvFileConfig: boolean;
13
+ /** Whether skipFileLoading is set to true (container-friendly) */
14
+ skipFileLoading: boolean;
15
+ /** Whether ciMode is explicitly set */
16
+ ciMode: boolean | undefined;
17
+ /** Environment file mappings */
18
+ envFiles: EnvFileMapping;
19
+ /** Required environment variables */
20
+ requiredVariables: string[];
21
+ /** Whether autoCreateTemplate is enabled */
22
+ autoCreateTemplate: boolean;
23
+ /** Current environment if specified */
24
+ currentEnvironment: string | undefined;
25
+ /** Detected env files that exist on disk */
26
+ existingEnvFiles: string[];
27
+ /** Detected env files that are missing */
28
+ missingEnvFiles: string[];
29
+ /** Whether the configuration is container-ready */
30
+ isContainerReady: boolean;
31
+ /** Recommendations for container deployment */
32
+ recommendations: string[];
33
+ }
34
+ /**
35
+ * Analyze the bootstrap configuration in main.ts
36
+ * Detects environment file configurations that affect container deployment
37
+ */
38
+ export declare function analyzeBootstrapConfig(): Promise<BootstrapConfig>;
39
+ /**
40
+ * Get the env file for a specific environment
41
+ */
42
+ export declare function getEnvFileForEnvironment(config: BootstrapConfig, environment: string): string;
43
+ /**
44
+ * Check if env files should be copied to the container
45
+ */
46
+ export declare function shouldCopyEnvFiles(config: BootstrapConfig): boolean;
@@ -0,0 +1,187 @@
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.shouldCopyEnvFiles = exports.getEnvFileForEnvironment = exports.analyzeBootstrapConfig = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ /**
10
+ * Analyze the bootstrap configuration in main.ts
11
+ * Detects environment file configurations that affect container deployment
12
+ */
13
+ async function analyzeBootstrapConfig() {
14
+ const cwd = process.cwd();
15
+ const result = {
16
+ hasEnvFileConfig: false,
17
+ skipFileLoading: false,
18
+ ciMode: undefined,
19
+ envFiles: {},
20
+ requiredVariables: [],
21
+ autoCreateTemplate: false,
22
+ currentEnvironment: undefined,
23
+ existingEnvFiles: [],
24
+ missingEnvFiles: [],
25
+ isContainerReady: true,
26
+ recommendations: [],
27
+ };
28
+ // Find main.ts file
29
+ const mainTsPath = findMainFile(cwd);
30
+ if (!mainTsPath) {
31
+ return result;
32
+ }
33
+ const content = fs_1.default.readFileSync(mainTsPath, "utf-8");
34
+ // Check if bootstrap is imported and used
35
+ if (!content.includes("bootstrap")) {
36
+ return result;
37
+ }
38
+ // Parse bootstrap configuration
39
+ parseBootstrapConfig(content, result);
40
+ // Detect existing env files
41
+ detectExistingEnvFiles(cwd, result);
42
+ // Determine if configuration is container-ready
43
+ evaluateContainerReadiness(result);
44
+ return result;
45
+ }
46
+ exports.analyzeBootstrapConfig = analyzeBootstrapConfig;
47
+ /**
48
+ * Find the main.ts file in the project
49
+ */
50
+ function findMainFile(cwd) {
51
+ const possiblePaths = [
52
+ path_1.default.join(cwd, "src", "main.ts"),
53
+ path_1.default.join(cwd, "src", "index.ts"),
54
+ path_1.default.join(cwd, "main.ts"),
55
+ path_1.default.join(cwd, "index.ts"),
56
+ ];
57
+ for (const filePath of possiblePaths) {
58
+ if (fs_1.default.existsSync(filePath)) {
59
+ return filePath;
60
+ }
61
+ }
62
+ return null;
63
+ }
64
+ /**
65
+ * Parse bootstrap configuration from file content
66
+ * Uses regex patterns to extract configuration without full AST parsing
67
+ */
68
+ function parseBootstrapConfig(content, result) {
69
+ // Check for envFileConfig usage
70
+ const envFileConfigMatch = content.match(/envFileConfig\s*[:{]/);
71
+ if (envFileConfigMatch) {
72
+ result.hasEnvFileConfig = true;
73
+ }
74
+ // Check for skipFileLoading: true
75
+ if (/skipFileLoading\s*:\s*true/.test(content)) {
76
+ result.skipFileLoading = true;
77
+ }
78
+ // Check for ciMode
79
+ const ciModeMatch = content.match(/ciMode\s*:\s*(true|false)/);
80
+ if (ciModeMatch) {
81
+ result.ciMode = ciModeMatch[1] === "true";
82
+ }
83
+ // Check for autoCreateTemplate
84
+ if (/autoCreateTemplate\s*:\s*true/.test(content)) {
85
+ result.autoCreateTemplate = true;
86
+ }
87
+ // Extract files mapping
88
+ const filesMatch = content.match(/files\s*:\s*\{([^}]+)\}/s);
89
+ if (filesMatch) {
90
+ const filesContent = filesMatch[1];
91
+ // Match key-value pairs like: development: ".env.dev"
92
+ const envMappings = filesContent.matchAll(/(\w+)\s*:\s*["'`]([^"'`]+)["'`]/g);
93
+ for (const match of envMappings) {
94
+ result.envFiles[match[1]] = match[2];
95
+ }
96
+ }
97
+ // Extract required variables
98
+ const requiredMatch = content.match(/required\s*:\s*\[([^\]]+)\]/s);
99
+ if (requiredMatch) {
100
+ const requiredContent = requiredMatch[1];
101
+ const variables = requiredContent.matchAll(/["'`]([^"'`]+)["'`]/g);
102
+ for (const match of variables) {
103
+ result.requiredVariables.push(match[1]);
104
+ }
105
+ }
106
+ // Extract currentEnvironment
107
+ const envMatch = content.match(/currentEnvironment\s*:\s*["'`]([^"'`]+)["'`]/);
108
+ if (envMatch) {
109
+ result.currentEnvironment = envMatch[1];
110
+ }
111
+ }
112
+ /**
113
+ * Detect which env files exist and which are missing
114
+ */
115
+ function detectExistingEnvFiles(cwd, result) {
116
+ // If no explicit files mapping, use convention
117
+ if (Object.keys(result.envFiles).length === 0 && result.hasEnvFileConfig) {
118
+ // Default convention: .env.{environment}
119
+ const defaultEnvs = ["development", "production", "staging", "test"];
120
+ for (const env of defaultEnvs) {
121
+ result.envFiles[env] = `.env.${env}`;
122
+ }
123
+ }
124
+ // Check each mapped file
125
+ for (const [env, fileName] of Object.entries(result.envFiles)) {
126
+ const filePath = path_1.default.join(cwd, fileName);
127
+ if (fs_1.default.existsSync(filePath)) {
128
+ result.existingEnvFiles.push(fileName);
129
+ }
130
+ else {
131
+ result.missingEnvFiles.push(fileName);
132
+ }
133
+ }
134
+ // Also check for common env files
135
+ const commonEnvFiles = [".env", ".env.local", ".env.example"];
136
+ for (const fileName of commonEnvFiles) {
137
+ const filePath = path_1.default.join(cwd, fileName);
138
+ if (fs_1.default.existsSync(filePath) &&
139
+ !result.existingEnvFiles.includes(fileName)) {
140
+ result.existingEnvFiles.push(fileName);
141
+ }
142
+ }
143
+ }
144
+ /**
145
+ * Evaluate if the bootstrap configuration is container-ready
146
+ */
147
+ function evaluateContainerReadiness(result) {
148
+ result.isContainerReady = true;
149
+ result.recommendations = [];
150
+ // If envFileConfig is used but skipFileLoading is not true
151
+ if (result.hasEnvFileConfig && !result.skipFileLoading && !result.ciMode) {
152
+ // Check if there are missing env files for development
153
+ const devEnvFile = result.envFiles["development"] || ".env.development";
154
+ if (result.missingEnvFiles.includes(devEnvFile)) {
155
+ result.isContainerReady = false;
156
+ result.recommendations.push(`Create ${devEnvFile} or set skipFileLoading: true for containers`);
157
+ }
158
+ // Recommend container-friendly configuration
159
+ if (!result.skipFileLoading) {
160
+ result.recommendations.push("Consider using skipFileLoading: true for Docker deployments");
161
+ result.recommendations.push("Use docker-compose environment variables instead of .env files");
162
+ }
163
+ }
164
+ // If there are required variables, they need to be provided
165
+ if (result.requiredVariables.length > 0) {
166
+ result.recommendations.push(`Ensure these variables are set in docker-compose: ${result.requiredVariables.join(", ")}`);
167
+ }
168
+ }
169
+ /**
170
+ * Get the env file for a specific environment
171
+ */
172
+ function getEnvFileForEnvironment(config, environment) {
173
+ return config.envFiles[environment] || `.env.${environment}`;
174
+ }
175
+ exports.getEnvFileForEnvironment = getEnvFileForEnvironment;
176
+ /**
177
+ * Check if env files should be copied to the container
178
+ */
179
+ function shouldCopyEnvFiles(config) {
180
+ // Don't copy if skipFileLoading is true or ciMode is true
181
+ if (config.skipFileLoading || config.ciMode) {
182
+ return false;
183
+ }
184
+ // Copy if envFileConfig is used and there are existing files
185
+ return config.hasEnvFileConfig && config.existingEnvFiles.length > 0;
186
+ }
187
+ exports.shouldCopyEnvFiles = shouldCopyEnvFiles;
@@ -0,0 +1,20 @@
1
+ import { type BootstrapConfig } from "./bootstrap-analyzer";
2
+ export interface ProjectAnalysis {
3
+ nodeVersion: string;
4
+ packageManager: "npm" | "pnpm" | "yarn" | "bun";
5
+ dependencies: string[];
6
+ devDependencies: string[];
7
+ controllers: string[];
8
+ hasDatabase: boolean;
9
+ hasRedis: boolean;
10
+ hasCors: boolean;
11
+ estimatedMemory: string;
12
+ estimatedCpu: string;
13
+ healthCheckPaths: string[];
14
+ port: number;
15
+ hasLocalDependencies: boolean;
16
+ localDependencyPaths: string[];
17
+ /** Bootstrap configuration analysis */
18
+ bootstrapConfig: BootstrapConfig;
19
+ }
20
+ export declare function analyzeProject(): Promise<ProjectAnalysis>;