genbox 1.0.47 → 1.0.48
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/dist/commands/create.js +3 -8
- package/dist/commands/db-sync.js +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/migrate.js +18 -215
- package/dist/commands/profiles.js +5 -11
- package/dist/commands/push.js +19 -24
- package/dist/commands/rebuild.js +3 -8
- package/dist/commands/validate.js +13 -13
- package/dist/config-explainer.js +1 -1
- package/dist/config-loader.js +74 -150
- package/dist/profile-resolver.js +15 -23
- package/dist/schema-v4.js +35 -35
- package/dist/strict-mode.js +57 -126
- package/package.json +1 -1
- package/dist/migration.js +0 -335
- package/dist/schema-v3.js +0 -48
package/dist/strict-mode.js
CHANGED
|
@@ -7,22 +7,16 @@
|
|
|
7
7
|
* - All ports must be explicit or use $detect markers
|
|
8
8
|
* - All connections must be declared in connects_to
|
|
9
9
|
* - No implicit defaults are applied
|
|
10
|
-
*
|
|
11
|
-
* This ensures reproducible, predictable behavior across
|
|
12
|
-
* different environments and team members.
|
|
13
10
|
*/
|
|
14
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.DEFAULT_STRICT_CONFIG = void 0;
|
|
16
12
|
exports.validateStrictMode = validateStrictMode;
|
|
17
13
|
exports.getStrictModeSettings = getStrictModeSettings;
|
|
18
14
|
exports.isStrictModeEnabled = isStrictModeEnabled;
|
|
19
15
|
exports.formatStrictViolations = formatStrictViolations;
|
|
20
|
-
exports.
|
|
21
|
-
const
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
// ============================================
|
|
25
|
-
exports.DEFAULT_STRICT_CONFIG = {
|
|
16
|
+
exports.enforceStrictMode = enforceStrictMode;
|
|
17
|
+
const schema_v4_1 = require("./schema-v4");
|
|
18
|
+
// Default strict mode settings
|
|
19
|
+
const DEFAULT_STRICT_CONFIG = {
|
|
26
20
|
enabled: true,
|
|
27
21
|
allow_detect: true,
|
|
28
22
|
warnings_as_errors: false,
|
|
@@ -34,7 +28,7 @@ exports.DEFAULT_STRICT_CONFIG = {
|
|
|
34
28
|
* Validate a configuration against strict mode rules
|
|
35
29
|
*/
|
|
36
30
|
function validateStrictMode(config, strictConfig = {}) {
|
|
37
|
-
const settings = { ...
|
|
31
|
+
const settings = { ...DEFAULT_STRICT_CONFIG, ...strictConfig };
|
|
38
32
|
const violations = [];
|
|
39
33
|
let explicitValues = 0;
|
|
40
34
|
let detectMarkers = 0;
|
|
@@ -53,7 +47,7 @@ function validateStrictMode(config, strictConfig = {}) {
|
|
|
53
47
|
});
|
|
54
48
|
inferredValues++;
|
|
55
49
|
}
|
|
56
|
-
else if ((0,
|
|
50
|
+
else if ((0, schema_v4_1.isDetectMarker)(appConfig.type)) {
|
|
57
51
|
if (!settings.allow_detect) {
|
|
58
52
|
violations.push({
|
|
59
53
|
path: `${appPath}.type`,
|
|
@@ -67,7 +61,7 @@ function validateStrictMode(config, strictConfig = {}) {
|
|
|
67
61
|
}
|
|
68
62
|
else {
|
|
69
63
|
explicitValues++;
|
|
70
|
-
// Check for naming-based inference
|
|
64
|
+
// Check for naming-based inference
|
|
71
65
|
if (isTypeInferredFromName(appName, appConfig.type)) {
|
|
72
66
|
violations.push({
|
|
73
67
|
path: `${appPath}.type`,
|
|
@@ -90,7 +84,7 @@ function validateStrictMode(config, strictConfig = {}) {
|
|
|
90
84
|
});
|
|
91
85
|
inferredValues++;
|
|
92
86
|
}
|
|
93
|
-
else if ((0,
|
|
87
|
+
else if ((0, schema_v4_1.isDetectMarker)(appConfig.port)) {
|
|
94
88
|
if (!settings.allow_detect) {
|
|
95
89
|
violations.push({
|
|
96
90
|
path: `${appPath}.port`,
|
|
@@ -106,10 +100,9 @@ function validateStrictMode(config, strictConfig = {}) {
|
|
|
106
100
|
explicitValues++;
|
|
107
101
|
}
|
|
108
102
|
}
|
|
109
|
-
// Check connections
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
for (const [connName, connConfig] of Object.entries(v4App.connects_to)) {
|
|
103
|
+
// Check connections
|
|
104
|
+
if (appConfig.connects_to) {
|
|
105
|
+
for (const [connName, connConfig] of Object.entries(appConfig.connects_to)) {
|
|
113
106
|
if (!connConfig || typeof connConfig !== 'object') {
|
|
114
107
|
violations.push({
|
|
115
108
|
path: `${appPath}.connects_to.${connName}`,
|
|
@@ -122,24 +115,10 @@ function validateStrictMode(config, strictConfig = {}) {
|
|
|
122
115
|
explicitValues++;
|
|
123
116
|
}
|
|
124
117
|
}
|
|
125
|
-
// Check for legacy requires (v3 style)
|
|
126
|
-
const v3App = appConfig;
|
|
127
|
-
if (v3App.requires) {
|
|
128
|
-
for (const [depName, requirement] of Object.entries(v3App.requires)) {
|
|
129
|
-
violations.push({
|
|
130
|
-
path: `${appPath}.requires.${depName}`,
|
|
131
|
-
type: 'undeclared_connection',
|
|
132
|
-
message: `Legacy "requires" syntax used`,
|
|
133
|
-
suggestion: `Use "connects_to: { ${depName}: { mode: local } }" instead`,
|
|
134
|
-
severity: settings.enabled ? 'error' : 'warning',
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
118
|
}
|
|
139
|
-
// Check provides
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
for (const [infraName, infraConfig] of Object.entries(v4Config.provides)) {
|
|
119
|
+
// Check provides
|
|
120
|
+
if (config.provides) {
|
|
121
|
+
for (const [infraName, infraConfig] of Object.entries(config.provides)) {
|
|
143
122
|
if (!infraConfig.type || !infraConfig.image || !infraConfig.port) {
|
|
144
123
|
violations.push({
|
|
145
124
|
path: `provides.${infraName}`,
|
|
@@ -150,17 +129,15 @@ function validateStrictMode(config, strictConfig = {}) {
|
|
|
150
129
|
});
|
|
151
130
|
}
|
|
152
131
|
else {
|
|
153
|
-
explicitValues += 3;
|
|
132
|
+
explicitValues += 3;
|
|
154
133
|
}
|
|
155
134
|
}
|
|
156
135
|
}
|
|
157
136
|
// Calculate summary
|
|
158
137
|
const errors = violations.filter(v => v.severity === 'error').length;
|
|
159
138
|
const warnings = violations.filter(v => v.severity === 'warning').length;
|
|
160
|
-
// In strict mode with warnings_as_errors, warnings become errors
|
|
161
|
-
const finalErrors = settings.warnings_as_errors ? errors + warnings : errors;
|
|
162
139
|
return {
|
|
163
|
-
valid:
|
|
140
|
+
valid: settings.warnings_as_errors ? violations.length === 0 : errors === 0,
|
|
164
141
|
violations,
|
|
165
142
|
summary: {
|
|
166
143
|
errors,
|
|
@@ -175,114 +152,68 @@ function validateStrictMode(config, strictConfig = {}) {
|
|
|
175
152
|
* Check if a type appears to be inferred from the app name
|
|
176
153
|
*/
|
|
177
154
|
function isTypeInferredFromName(appName, type) {
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return /gateway|proxy|router/.test(nameLower);
|
|
190
|
-
}
|
|
191
|
-
return false;
|
|
155
|
+
const name = appName.toLowerCase();
|
|
156
|
+
const patterns = {
|
|
157
|
+
frontend: ['web', 'ui', 'client', 'app', 'dashboard', 'admin'],
|
|
158
|
+
backend: ['api', 'server', 'service', 'backend'],
|
|
159
|
+
worker: ['worker', 'job', 'queue', 'processor'],
|
|
160
|
+
gateway: ['gateway', 'proxy', 'router'],
|
|
161
|
+
};
|
|
162
|
+
const typePatterns = patterns[type];
|
|
163
|
+
if (!typePatterns)
|
|
164
|
+
return false;
|
|
165
|
+
return typePatterns.some(pattern => name.includes(pattern));
|
|
192
166
|
}
|
|
193
|
-
// ============================================
|
|
194
|
-
// Strict Mode Helpers
|
|
195
|
-
// ============================================
|
|
196
167
|
/**
|
|
197
168
|
* Get strict mode settings from config
|
|
198
169
|
*/
|
|
199
170
|
function getStrictModeSettings(config) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
// v3 configs default to lenient mode
|
|
205
|
-
if (config.version !== 4) {
|
|
206
|
-
return {
|
|
207
|
-
enabled: false,
|
|
208
|
-
allow_detect: true,
|
|
209
|
-
warnings_as_errors: false,
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
return exports.DEFAULT_STRICT_CONFIG;
|
|
171
|
+
return {
|
|
172
|
+
...DEFAULT_STRICT_CONFIG,
|
|
173
|
+
...config.strict,
|
|
174
|
+
};
|
|
213
175
|
}
|
|
214
176
|
/**
|
|
215
177
|
* Check if strict mode is enabled
|
|
216
178
|
*/
|
|
217
179
|
function isStrictModeEnabled(config) {
|
|
218
|
-
return
|
|
180
|
+
return config.strict?.enabled ?? true;
|
|
219
181
|
}
|
|
220
182
|
/**
|
|
221
|
-
* Format
|
|
183
|
+
* Format violations for display
|
|
222
184
|
*/
|
|
223
185
|
function formatStrictViolations(result) {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
lines.push('✓ Strict mode validation passed');
|
|
186
|
+
if (result.violations.length === 0) {
|
|
187
|
+
return '✓ No strict mode violations';
|
|
227
188
|
}
|
|
228
|
-
|
|
229
|
-
|
|
189
|
+
const lines = [];
|
|
190
|
+
const errors = result.violations.filter(v => v.severity === 'error');
|
|
191
|
+
const warnings = result.violations.filter(v => v.severity === 'warning');
|
|
192
|
+
if (errors.length > 0) {
|
|
193
|
+
lines.push(`\n❌ ${errors.length} error(s):\n`);
|
|
194
|
+
for (const v of errors) {
|
|
195
|
+
lines.push(` • ${v.path}: ${v.message}`);
|
|
196
|
+
lines.push(` → ${v.suggestion}`);
|
|
197
|
+
}
|
|
230
198
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
lines.push(` Errors: ${result.summary.errors}`);
|
|
237
|
-
lines.push(` Warnings: ${result.summary.warnings}`);
|
|
238
|
-
if (result.violations.length > 0) {
|
|
239
|
-
lines.push('');
|
|
240
|
-
lines.push('Violations:');
|
|
241
|
-
for (const violation of result.violations) {
|
|
242
|
-
const icon = violation.severity === 'error' ? '✗' : '⚠';
|
|
243
|
-
lines.push(` ${icon} ${violation.path}`);
|
|
244
|
-
lines.push(` ${violation.message}`);
|
|
245
|
-
lines.push(` → ${violation.suggestion}`);
|
|
199
|
+
if (warnings.length > 0) {
|
|
200
|
+
lines.push(`\n⚠️ ${warnings.length} warning(s):\n`);
|
|
201
|
+
for (const v of warnings) {
|
|
202
|
+
lines.push(` • ${v.path}: ${v.message}`);
|
|
203
|
+
lines.push(` → ${v.suggestion}`);
|
|
246
204
|
}
|
|
247
205
|
}
|
|
248
206
|
return lines.join('\n');
|
|
249
207
|
}
|
|
250
208
|
/**
|
|
251
|
-
*
|
|
209
|
+
* Check a config and throw if invalid in strict mode
|
|
252
210
|
*/
|
|
253
|
-
function
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
action: 'add',
|
|
261
|
-
value: '$detect',
|
|
262
|
-
description: `Add $detect marker to auto-detect type`,
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
if (violation.type === 'missing_port') {
|
|
266
|
-
fixes.push({
|
|
267
|
-
path: violation.path,
|
|
268
|
-
action: 'add',
|
|
269
|
-
value: '$detect',
|
|
270
|
-
description: `Add $detect marker to auto-detect port`,
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
if (violation.type === 'undeclared_connection' && violation.path.includes('requires')) {
|
|
274
|
-
// Convert requires to connects_to
|
|
275
|
-
const match = violation.path.match(/apps\.(\w+)\.requires\.(\w+)/);
|
|
276
|
-
if (match) {
|
|
277
|
-
const [, appName, depName] = match;
|
|
278
|
-
fixes.push({
|
|
279
|
-
path: `apps.${appName}.connects_to.${depName}`,
|
|
280
|
-
action: 'add',
|
|
281
|
-
value: { mode: 'local', required: true },
|
|
282
|
-
description: `Convert requires.${depName} to connects_to`,
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
}
|
|
211
|
+
function enforceStrictMode(config, options = {}) {
|
|
212
|
+
const settings = getStrictModeSettings(config);
|
|
213
|
+
if (!settings.enabled)
|
|
214
|
+
return;
|
|
215
|
+
const result = validateStrictMode(config, settings);
|
|
216
|
+
if (!result.valid || (options.throwOnWarnings && result.summary.warnings > 0)) {
|
|
217
|
+
throw new Error(`Strict mode validation failed:\n${formatStrictViolations(result)}`);
|
|
286
218
|
}
|
|
287
|
-
return fixes;
|
|
288
219
|
}
|
package/package.json
CHANGED
package/dist/migration.js
DELETED
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Configuration Migration Utilities
|
|
4
|
-
*
|
|
5
|
-
* Handles migration from v3 to v4 schema:
|
|
6
|
-
* - Converts `requires` to `connects_to`
|
|
7
|
-
* - Converts `infrastructure` to `provides`
|
|
8
|
-
* - Adds explicit types where inferred
|
|
9
|
-
* - Shows deprecation warnings
|
|
10
|
-
*/
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.checkDeprecations = checkDeprecations;
|
|
13
|
-
exports.migrateV3ToV4 = migrateV3ToV4;
|
|
14
|
-
exports.needsMigration = needsMigration;
|
|
15
|
-
exports.getMigrationSummary = getMigrationSummary;
|
|
16
|
-
const schema_v4_1 = require("./schema-v4");
|
|
17
|
-
/**
|
|
18
|
-
* Check a v3 config for deprecated patterns
|
|
19
|
-
*/
|
|
20
|
-
function checkDeprecations(config) {
|
|
21
|
-
const warnings = [];
|
|
22
|
-
// Check version (v3 version is '3.0' string, v4 is number 4)
|
|
23
|
-
if (config.version !== 4) {
|
|
24
|
-
warnings.push({
|
|
25
|
-
path: 'version',
|
|
26
|
-
message: `Config version ${config.version} is deprecated`,
|
|
27
|
-
suggestion: 'Run "genbox migrate" to upgrade to version 4',
|
|
28
|
-
severity: 'warning',
|
|
29
|
-
autoMigrate: true,
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
// Check for requires in apps
|
|
33
|
-
for (const [appName, appConfig] of Object.entries(config.apps || {})) {
|
|
34
|
-
if (appConfig.requires) {
|
|
35
|
-
warnings.push({
|
|
36
|
-
path: `apps.${appName}.requires`,
|
|
37
|
-
message: '"requires" is deprecated in v4',
|
|
38
|
-
suggestion: 'Use "connects_to" with explicit connection modes',
|
|
39
|
-
severity: 'warning',
|
|
40
|
-
autoMigrate: true,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
// Check for infrastructure (should be provides)
|
|
45
|
-
if (config.infrastructure) {
|
|
46
|
-
warnings.push({
|
|
47
|
-
path: 'infrastructure',
|
|
48
|
-
message: '"infrastructure" is renamed to "provides" in v4',
|
|
49
|
-
suggestion: 'Rename to "provides" for clarity',
|
|
50
|
-
severity: 'warning',
|
|
51
|
-
autoMigrate: true,
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
// Check for profile connect_to
|
|
55
|
-
for (const [profileName, profile] of Object.entries(config.profiles || {})) {
|
|
56
|
-
if (profile.connect_to && typeof profile.connect_to === 'string') {
|
|
57
|
-
warnings.push({
|
|
58
|
-
path: `profiles.${profileName}.connect_to`,
|
|
59
|
-
message: 'Single string "connect_to" is deprecated in v4',
|
|
60
|
-
suggestion: 'Use "default_connection" or per-app "connections" overrides',
|
|
61
|
-
severity: 'warning',
|
|
62
|
-
autoMigrate: true,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
// Check for implicit app types (inferred from names)
|
|
67
|
-
for (const [appName, appConfig] of Object.entries(config.apps || {})) {
|
|
68
|
-
if (!appConfig.type) {
|
|
69
|
-
warnings.push({
|
|
70
|
-
path: `apps.${appName}.type`,
|
|
71
|
-
message: `App "${appName}" has no explicit type`,
|
|
72
|
-
suggestion: 'Add explicit "type: frontend|backend|worker|gateway"',
|
|
73
|
-
severity: 'warning',
|
|
74
|
-
autoMigrate: false,
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return warnings;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Migrate a v3 config to v4
|
|
82
|
-
*/
|
|
83
|
-
function migrateV3ToV4(v3Config) {
|
|
84
|
-
const changes = [];
|
|
85
|
-
const warnings = [];
|
|
86
|
-
// Start with base v4 structure
|
|
87
|
-
const v4Config = {
|
|
88
|
-
version: 4,
|
|
89
|
-
project: {
|
|
90
|
-
name: v3Config.project.name,
|
|
91
|
-
description: v3Config.project.description,
|
|
92
|
-
structure: v3Config.project.structure,
|
|
93
|
-
},
|
|
94
|
-
apps: {},
|
|
95
|
-
};
|
|
96
|
-
changes.push({
|
|
97
|
-
type: 'modify',
|
|
98
|
-
path: 'version',
|
|
99
|
-
description: 'Upgraded version from 3 to 4',
|
|
100
|
-
before: v3Config.version,
|
|
101
|
-
after: 4,
|
|
102
|
-
});
|
|
103
|
-
// Migrate infrastructure to provides
|
|
104
|
-
if (v3Config.infrastructure) {
|
|
105
|
-
v4Config.provides = {};
|
|
106
|
-
for (const [name, infra] of Object.entries(v3Config.infrastructure)) {
|
|
107
|
-
v4Config.provides[name] = migrateInfrastructure(name, infra);
|
|
108
|
-
}
|
|
109
|
-
changes.push({
|
|
110
|
-
type: 'rename',
|
|
111
|
-
path: 'infrastructure',
|
|
112
|
-
description: 'Renamed "infrastructure" to "provides"',
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
// Migrate apps
|
|
116
|
-
for (const [appName, appConfig] of Object.entries(v3Config.apps || {})) {
|
|
117
|
-
const migratedApp = migrateApp(appName, appConfig, v3Config, changes, warnings);
|
|
118
|
-
v4Config.apps[appName] = migratedApp;
|
|
119
|
-
}
|
|
120
|
-
// Migrate profiles
|
|
121
|
-
if (v3Config.profiles) {
|
|
122
|
-
v4Config.profiles = {};
|
|
123
|
-
for (const [profileName, profile] of Object.entries(v3Config.profiles)) {
|
|
124
|
-
v4Config.profiles[profileName] = migrateProfile(profileName, profile, changes);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// Copy over other sections
|
|
128
|
-
if (v3Config.environments) {
|
|
129
|
-
v4Config.environments = {};
|
|
130
|
-
for (const [envName, envConfig] of Object.entries(v3Config.environments)) {
|
|
131
|
-
v4Config.environments[envName] = {
|
|
132
|
-
description: envConfig.description,
|
|
133
|
-
urls: extractUrls(envConfig),
|
|
134
|
-
env: {},
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
if (v3Config.repos) {
|
|
139
|
-
v4Config.repos = {};
|
|
140
|
-
for (const [repoName, repoConfig] of Object.entries(v3Config.repos)) {
|
|
141
|
-
v4Config.repos[repoName] = {
|
|
142
|
-
url: repoConfig.url,
|
|
143
|
-
path: repoConfig.path,
|
|
144
|
-
branch: repoConfig.branch,
|
|
145
|
-
auth: repoConfig.auth,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
if (v3Config.defaults) {
|
|
150
|
-
v4Config.defaults = {
|
|
151
|
-
size: v3Config.defaults.size,
|
|
152
|
-
database: v3Config.defaults.database,
|
|
153
|
-
branch: v3Config.defaults.branch,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
if (v3Config.hooks) {
|
|
157
|
-
v4Config.hooks = v3Config.hooks;
|
|
158
|
-
}
|
|
159
|
-
if (v3Config.scripts) {
|
|
160
|
-
v4Config.scripts = v3Config.scripts.map(script => ({
|
|
161
|
-
name: script.name,
|
|
162
|
-
path: script.path,
|
|
163
|
-
stage: script.stage,
|
|
164
|
-
run_as: script.runAs,
|
|
165
|
-
depends_on: script.dependsOn,
|
|
166
|
-
}));
|
|
167
|
-
}
|
|
168
|
-
// Add strict mode (default for v4)
|
|
169
|
-
v4Config.strict = {
|
|
170
|
-
enabled: true,
|
|
171
|
-
allow_detect: true,
|
|
172
|
-
warnings_as_errors: false,
|
|
173
|
-
};
|
|
174
|
-
changes.push({
|
|
175
|
-
type: 'add',
|
|
176
|
-
path: 'strict',
|
|
177
|
-
description: 'Added strict mode configuration (default for v4)',
|
|
178
|
-
after: v4Config.strict,
|
|
179
|
-
});
|
|
180
|
-
return { config: v4Config, changes, warnings };
|
|
181
|
-
}
|
|
182
|
-
function migrateInfrastructure(name, infra) {
|
|
183
|
-
return {
|
|
184
|
-
type: infra.type,
|
|
185
|
-
image: infra.image,
|
|
186
|
-
port: infra.port,
|
|
187
|
-
data_dir: infra.data_dir,
|
|
188
|
-
description: `Migrated from infrastructure.${name}`,
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
function migrateApp(appName, appConfig, v3Config, changes, warnings) {
|
|
192
|
-
const v4App = {
|
|
193
|
-
path: appConfig.path,
|
|
194
|
-
type: appConfig.type || '$detect',
|
|
195
|
-
};
|
|
196
|
-
// Migrate framework
|
|
197
|
-
if (appConfig.framework) {
|
|
198
|
-
v4App.framework = appConfig.framework;
|
|
199
|
-
}
|
|
200
|
-
// Migrate port
|
|
201
|
-
if (appConfig.port) {
|
|
202
|
-
v4App.port = appConfig.port;
|
|
203
|
-
}
|
|
204
|
-
// Migrate requires to connects_to
|
|
205
|
-
if (appConfig.requires) {
|
|
206
|
-
v4App.connects_to = {};
|
|
207
|
-
for (const [depName, requirement] of Object.entries(appConfig.requires)) {
|
|
208
|
-
v4App.connects_to[depName] = {
|
|
209
|
-
mode: 'local', // Default to local
|
|
210
|
-
required: requirement === 'required',
|
|
211
|
-
description: `Migrated from requires.${depName}`,
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
changes.push({
|
|
215
|
-
type: 'rename',
|
|
216
|
-
path: `apps.${appName}.requires`,
|
|
217
|
-
description: `Converted "requires" to "connects_to" for app "${appName}"`,
|
|
218
|
-
before: appConfig.requires,
|
|
219
|
-
after: v4App.connects_to,
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
// Also handle dependencies if present
|
|
223
|
-
if (appConfig.dependencies) {
|
|
224
|
-
if (!v4App.connects_to)
|
|
225
|
-
v4App.connects_to = {};
|
|
226
|
-
for (const [depName, depConfig] of Object.entries(appConfig.dependencies)) {
|
|
227
|
-
if (!v4App.connects_to[depName]) {
|
|
228
|
-
v4App.connects_to[depName] = {
|
|
229
|
-
mode: depConfig.mode,
|
|
230
|
-
required: true,
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
// Migrate commands
|
|
236
|
-
if (appConfig.commands) {
|
|
237
|
-
v4App.commands = appConfig.commands;
|
|
238
|
-
}
|
|
239
|
-
// Copy other fields
|
|
240
|
-
if (appConfig.repo)
|
|
241
|
-
v4App.repo = appConfig.repo;
|
|
242
|
-
if (appConfig.description)
|
|
243
|
-
v4App.description = appConfig.description;
|
|
244
|
-
if (appConfig.env)
|
|
245
|
-
v4App.env = appConfig.env;
|
|
246
|
-
if (appConfig.compose_file) {
|
|
247
|
-
v4App.runner = 'docker';
|
|
248
|
-
v4App.docker = { file: appConfig.compose_file };
|
|
249
|
-
}
|
|
250
|
-
// Warn about missing explicit type
|
|
251
|
-
if (!appConfig.type) {
|
|
252
|
-
warnings.push(`App "${appName}" has no explicit type. Using $detect marker. ` +
|
|
253
|
-
`Run "genbox scan" then "genbox resolve" to determine the type.`);
|
|
254
|
-
}
|
|
255
|
-
return v4App;
|
|
256
|
-
}
|
|
257
|
-
function migrateProfile(profileName, profile, changes) {
|
|
258
|
-
const v4Profile = {
|
|
259
|
-
description: profile.description,
|
|
260
|
-
extends: profile.extends,
|
|
261
|
-
size: profile.size,
|
|
262
|
-
apps: profile.apps,
|
|
263
|
-
database: profile.database,
|
|
264
|
-
env: profile.env,
|
|
265
|
-
branch: profile.branch,
|
|
266
|
-
};
|
|
267
|
-
// Convert connect_to to default_connection
|
|
268
|
-
if (profile.connect_to && typeof profile.connect_to === 'string') {
|
|
269
|
-
v4Profile.default_connection = profile.connect_to;
|
|
270
|
-
changes.push({
|
|
271
|
-
type: 'rename',
|
|
272
|
-
path: `profiles.${profileName}.connect_to`,
|
|
273
|
-
description: `Converted string "connect_to" to "default_connection" in profile "${profileName}"`,
|
|
274
|
-
before: profile.connect_to,
|
|
275
|
-
after: v4Profile.default_connection,
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
return v4Profile;
|
|
279
|
-
}
|
|
280
|
-
function extractUrls(envConfig) {
|
|
281
|
-
const urls = {};
|
|
282
|
-
if (envConfig.api?.url) {
|
|
283
|
-
urls['api'] = envConfig.api.url;
|
|
284
|
-
}
|
|
285
|
-
if (envConfig.api?.gateway) {
|
|
286
|
-
urls['gateway'] = envConfig.api.gateway;
|
|
287
|
-
}
|
|
288
|
-
if (envConfig.mongodb?.url) {
|
|
289
|
-
urls['mongodb'] = envConfig.mongodb.url;
|
|
290
|
-
}
|
|
291
|
-
if (envConfig.redis?.url) {
|
|
292
|
-
urls['redis'] = envConfig.redis.url;
|
|
293
|
-
}
|
|
294
|
-
if (envConfig.rabbitmq?.url) {
|
|
295
|
-
urls['rabbitmq'] = envConfig.rabbitmq.url;
|
|
296
|
-
}
|
|
297
|
-
return urls;
|
|
298
|
-
}
|
|
299
|
-
// ============================================
|
|
300
|
-
// Migration Detection
|
|
301
|
-
// ============================================
|
|
302
|
-
/**
|
|
303
|
-
* Check if a config needs migration
|
|
304
|
-
*/
|
|
305
|
-
function needsMigration(config) {
|
|
306
|
-
const version = (0, schema_v4_1.getConfigVersion)(config);
|
|
307
|
-
return version === 3 || version === 'unknown';
|
|
308
|
-
}
|
|
309
|
-
/**
|
|
310
|
-
* Get migration summary
|
|
311
|
-
*/
|
|
312
|
-
function getMigrationSummary(v3Config) {
|
|
313
|
-
const deprecations = checkDeprecations(v3Config);
|
|
314
|
-
const estimatedChanges = [];
|
|
315
|
-
if (v3Config.infrastructure) {
|
|
316
|
-
estimatedChanges.push('Rename "infrastructure" to "provides"');
|
|
317
|
-
}
|
|
318
|
-
for (const appName of Object.keys(v3Config.apps || {})) {
|
|
319
|
-
const app = v3Config.apps[appName];
|
|
320
|
-
if (app.requires) {
|
|
321
|
-
estimatedChanges.push(`Convert "${appName}.requires" to "connects_to"`);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
for (const profileName of Object.keys(v3Config.profiles || {})) {
|
|
325
|
-
const profile = v3Config.profiles[profileName];
|
|
326
|
-
if (profile.connect_to && typeof profile.connect_to === 'string') {
|
|
327
|
-
estimatedChanges.push(`Convert "${profileName}.connect_to" to "default_connection"`);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
return {
|
|
331
|
-
fieldsToMigrate: estimatedChanges.length,
|
|
332
|
-
deprecatedPatterns: deprecations.length,
|
|
333
|
-
estimatedChanges,
|
|
334
|
-
};
|
|
335
|
-
}
|
package/dist/schema-v3.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Genbox Configuration Schema v3
|
|
4
|
-
*
|
|
5
|
-
* Supports:
|
|
6
|
-
* - Multi-level configs (workspace/project/user)
|
|
7
|
-
* - Flexible app selection (profiles, CLI, interactive)
|
|
8
|
-
* - External environment connections
|
|
9
|
-
* - Database modes (none/local/copy/remote)
|
|
10
|
-
* - Dependency resolution
|
|
11
|
-
*/
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.DETECTABLE_APP_FIELDS = exports.DETECT_MARKER = void 0;
|
|
14
|
-
exports.isDetectMarker = isDetectMarker;
|
|
15
|
-
// ============================================
|
|
16
|
-
// $detect Marker Support
|
|
17
|
-
// ============================================
|
|
18
|
-
/**
|
|
19
|
-
* Special marker indicating a value should be auto-detected.
|
|
20
|
-
* Used in genbox.yaml to opt-in to detection for specific fields.
|
|
21
|
-
*
|
|
22
|
-
* Example:
|
|
23
|
-
* apps:
|
|
24
|
-
* web:
|
|
25
|
-
* path: ./web
|
|
26
|
-
* type: $detect # Auto-detect from dependencies
|
|
27
|
-
* port: $detect # Auto-detect from scripts
|
|
28
|
-
* framework: $detect # Auto-detect from dependencies
|
|
29
|
-
*/
|
|
30
|
-
exports.DETECT_MARKER = '$detect';
|
|
31
|
-
/**
|
|
32
|
-
* List of fields that support $detect markers in AppConfig
|
|
33
|
-
*/
|
|
34
|
-
exports.DETECTABLE_APP_FIELDS = [
|
|
35
|
-
'type',
|
|
36
|
-
'framework',
|
|
37
|
-
'port',
|
|
38
|
-
'commands.install',
|
|
39
|
-
'commands.dev',
|
|
40
|
-
'commands.build',
|
|
41
|
-
'commands.start',
|
|
42
|
-
];
|
|
43
|
-
/**
|
|
44
|
-
* Check if a value is a $detect marker
|
|
45
|
-
*/
|
|
46
|
-
function isDetectMarker(value) {
|
|
47
|
-
return value === exports.DETECT_MARKER;
|
|
48
|
-
}
|