genbox 1.0.41 → 1.0.43
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 +46 -0
- package/dist/commands/init.js +27 -16
- package/dist/commands/scan.js +7 -1
- package/dist/profile-resolver.js +4 -0
- package/package.json +1 -1
package/dist/commands/create.js
CHANGED
|
@@ -51,6 +51,20 @@ const ssh_config_1 = require("../ssh-config");
|
|
|
51
51
|
const schema_v4_1 = require("../schema-v4");
|
|
52
52
|
const child_process_1 = require("child_process");
|
|
53
53
|
const random_name_1 = require("../random-name");
|
|
54
|
+
// Credits consumed per hour for each size (matches API billing.config.ts)
|
|
55
|
+
const CREDITS_PER_HOUR = {
|
|
56
|
+
cx22: 1,
|
|
57
|
+
cx32: 2,
|
|
58
|
+
cx42: 4,
|
|
59
|
+
cx52: 8,
|
|
60
|
+
small: 1,
|
|
61
|
+
medium: 2,
|
|
62
|
+
large: 4,
|
|
63
|
+
xl: 8,
|
|
64
|
+
};
|
|
65
|
+
function getCreditsPerHour(size) {
|
|
66
|
+
return CREDITS_PER_HOUR[size.toLowerCase()] || 2; // Default to medium
|
|
67
|
+
}
|
|
54
68
|
/**
|
|
55
69
|
* Spawn a background process to poll for IP and add SSH config
|
|
56
70
|
* This runs detached so the main process can exit immediately
|
|
@@ -296,11 +310,41 @@ exports.createCommand = new commander_1.Command('create')
|
|
|
296
310
|
if (!selectedProfile && !options.yes && !options.dryRun) {
|
|
297
311
|
await profileResolver.askSaveProfile(config, resolved);
|
|
298
312
|
}
|
|
313
|
+
// Calculate credits that will be consumed
|
|
314
|
+
const creditsPerHour = getCreditsPerHour(resolved.size);
|
|
315
|
+
// Fetch user's current credit balance
|
|
316
|
+
let userCredits = 0;
|
|
317
|
+
let addonCredits = 0;
|
|
318
|
+
try {
|
|
319
|
+
const user = await (0, api_1.fetchApi)('/users/me');
|
|
320
|
+
userCredits = user.credits || 0;
|
|
321
|
+
addonCredits = user.addonCredits || 0;
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
// Continue without balance info if fetch fails
|
|
325
|
+
}
|
|
326
|
+
const totalCredits = userCredits + addonCredits;
|
|
327
|
+
const estimatedHours = totalCredits > 0 ? Math.floor(totalCredits / creditsPerHour) : 0;
|
|
328
|
+
// Display billing info
|
|
329
|
+
console.log(chalk_1.default.blue('=== Billing ==='));
|
|
330
|
+
console.log(` Credits to start: ${chalk_1.default.yellow(creditsPerHour)} (${creditsPerHour} credit${creditsPerHour > 1 ? 's' : ''}/hr for ${resolved.size})`);
|
|
331
|
+
if (totalCredits > 0) {
|
|
332
|
+
console.log(` Your balance: ${chalk_1.default.green(totalCredits)} credits${addonCredits > 0 ? chalk_1.default.dim(` (${userCredits} regular + ${addonCredits} addon)`) : ''}`);
|
|
333
|
+
console.log(` After creation: ${chalk_1.default.cyan(totalCredits - creditsPerHour)} credits`);
|
|
334
|
+
console.log(` Estimated runtime: ${chalk_1.default.cyan('~' + estimatedHours + ' hours')}`);
|
|
335
|
+
}
|
|
336
|
+
console.log('');
|
|
299
337
|
// Dry run mode
|
|
300
338
|
if (options.dryRun) {
|
|
301
339
|
console.log(chalk_1.default.yellow('\nDry run mode - no genbox created'));
|
|
302
340
|
return;
|
|
303
341
|
}
|
|
342
|
+
// Check if user has enough credits
|
|
343
|
+
if (totalCredits < creditsPerHour) {
|
|
344
|
+
console.log(chalk_1.default.red(`Insufficient credits. Need ${creditsPerHour}, have ${totalCredits}.`));
|
|
345
|
+
console.log(chalk_1.default.dim('Run `genbox balance` to check your balance or purchase more credits.'));
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
304
348
|
// Confirm creation
|
|
305
349
|
if (!options.yes) {
|
|
306
350
|
const confirm = await prompts.confirm({
|
|
@@ -771,6 +815,8 @@ function buildPayload(resolved, config, publicKey, privateKey, configLoader) {
|
|
|
771
815
|
framework: a.framework,
|
|
772
816
|
runner: a.runner,
|
|
773
817
|
docker: a.docker,
|
|
818
|
+
healthcheck: a.healthcheck,
|
|
819
|
+
dependsOn: a.dependsOn,
|
|
774
820
|
commands: a.commands,
|
|
775
821
|
})),
|
|
776
822
|
infrastructure: resolved.infrastructure.map(i => ({
|
package/dist/commands/init.js
CHANGED
|
@@ -583,8 +583,15 @@ exports.initCommand = new commander_1.Command('init')
|
|
|
583
583
|
console.log(` ... and ${scan.apps.length - 5} more`);
|
|
584
584
|
}
|
|
585
585
|
}
|
|
586
|
-
|
|
587
|
-
|
|
586
|
+
// Show Docker app count (apps with runner: 'docker')
|
|
587
|
+
const dockerApps = scan.apps.filter(a => a.runner === 'docker');
|
|
588
|
+
if (dockerApps.length > 0) {
|
|
589
|
+
console.log(` ${chalk_1.default.dim('Docker:')} ${dockerApps.length} app(s) with docker runner`);
|
|
590
|
+
}
|
|
591
|
+
// Show infrastructure services from docker-compose (databases, caches, etc.)
|
|
592
|
+
if (scan.compose && scan.compose.databases.length + scan.compose.caches.length + scan.compose.queues.length > 0) {
|
|
593
|
+
const infraCount = scan.compose.databases.length + scan.compose.caches.length + scan.compose.queues.length;
|
|
594
|
+
console.log(` ${chalk_1.default.dim('Infra:')} ${infraCount} infrastructure service(s)`);
|
|
588
595
|
}
|
|
589
596
|
if (scan.git) {
|
|
590
597
|
console.log(` ${chalk_1.default.dim('Git:')} ${scan.git.remote} (${scan.git.type})`);
|
|
@@ -1886,24 +1893,28 @@ function convertDetectedToScan(detected) {
|
|
|
1886
1893
|
lockfile: r.lockfile,
|
|
1887
1894
|
}));
|
|
1888
1895
|
// Convert infrastructure to compose analysis
|
|
1896
|
+
// Note: docker_services is deprecated - apps with runner: 'docker' are now tracked per-app
|
|
1889
1897
|
let compose = null;
|
|
1890
1898
|
const hasInfra = detected.infrastructure && detected.infrastructure.length > 0;
|
|
1891
|
-
|
|
1892
|
-
|
|
1899
|
+
// Get docker apps from apps with runner: 'docker' (new approach)
|
|
1900
|
+
const dockerApps = Object.entries(detected.apps || {})
|
|
1901
|
+
.filter(([, app]) => app.runner === 'docker')
|
|
1902
|
+
.map(([name, app]) => ({
|
|
1903
|
+
name,
|
|
1904
|
+
image: app.docker?.service || name,
|
|
1905
|
+
build: app.docker?.build_context ? {
|
|
1906
|
+
context: app.docker.build_context,
|
|
1907
|
+
dockerfile: app.docker.dockerfile,
|
|
1908
|
+
} : undefined,
|
|
1909
|
+
ports: app.port ? [{ host: app.port, container: app.port }] : [],
|
|
1910
|
+
environment: {},
|
|
1911
|
+
dependsOn: app.depends_on || [],
|
|
1912
|
+
volumes: [],
|
|
1913
|
+
}));
|
|
1914
|
+
if (hasInfra || dockerApps.length > 0) {
|
|
1893
1915
|
compose = {
|
|
1894
1916
|
files: ['docker-compose.yml'],
|
|
1895
|
-
applications:
|
|
1896
|
-
name: svc.name,
|
|
1897
|
-
image: svc.image,
|
|
1898
|
-
build: svc.build_context ? {
|
|
1899
|
-
context: svc.build_context,
|
|
1900
|
-
dockerfile: svc.dockerfile,
|
|
1901
|
-
} : undefined,
|
|
1902
|
-
ports: svc.port ? [{ host: svc.port, container: svc.port }] : [],
|
|
1903
|
-
environment: {},
|
|
1904
|
-
dependsOn: svc.depends_on || [],
|
|
1905
|
-
volumes: [],
|
|
1906
|
-
})),
|
|
1917
|
+
applications: dockerApps,
|
|
1907
1918
|
databases: (detected.infrastructure || [])
|
|
1908
1919
|
.filter(i => i.type === 'database')
|
|
1909
1920
|
.map(i => ({
|
package/dist/commands/scan.js
CHANGED
|
@@ -514,11 +514,17 @@ async function editAppConfig(name, app, rootDir) {
|
|
|
514
514
|
build_context: dockerContext,
|
|
515
515
|
dockerfile: dockerfile || app.docker?.dockerfile,
|
|
516
516
|
};
|
|
517
|
-
// Auto-set
|
|
517
|
+
// Auto-set values from docker-compose
|
|
518
518
|
if (composeInfo?.port) {
|
|
519
519
|
result.port = composeInfo.port;
|
|
520
520
|
result.port_source = 'docker-compose.yml';
|
|
521
521
|
}
|
|
522
|
+
if (composeInfo?.healthcheck) {
|
|
523
|
+
result.healthcheck = composeInfo.healthcheck;
|
|
524
|
+
}
|
|
525
|
+
if (composeInfo?.dependsOn?.length) {
|
|
526
|
+
result.depends_on = composeInfo.dependsOn;
|
|
527
|
+
}
|
|
522
528
|
}
|
|
523
529
|
// Edit port (only if not a library and not already set by docker-compose)
|
|
524
530
|
if (newRunner !== 'none' && result.type !== 'library') {
|
package/dist/profile-resolver.js
CHANGED
|
@@ -242,6 +242,8 @@ class ProfileResolver {
|
|
|
242
242
|
const v4Config = appConfig;
|
|
243
243
|
const runner = v4Config.runner;
|
|
244
244
|
const docker = v4Config.docker;
|
|
245
|
+
const healthcheck = v4Config.healthcheck;
|
|
246
|
+
const dependsOn = v4Config.depends_on;
|
|
245
247
|
return {
|
|
246
248
|
name: appName,
|
|
247
249
|
path: appConfig.path,
|
|
@@ -253,6 +255,8 @@ class ProfileResolver {
|
|
|
253
255
|
env: appConfig.env,
|
|
254
256
|
runner,
|
|
255
257
|
docker,
|
|
258
|
+
healthcheck,
|
|
259
|
+
dependsOn,
|
|
256
260
|
dependencies,
|
|
257
261
|
};
|
|
258
262
|
}
|