@geekmidas/cli 1.5.0 → 1.6.0
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/CHANGELOG.md +17 -0
- package/dist/{HostingerProvider-B9N-TKbp.mjs → HostingerProvider-402UdK89.mjs} +34 -1
- package/dist/HostingerProvider-402UdK89.mjs.map +1 -0
- package/dist/{HostingerProvider-DUV9-Tzg.cjs → HostingerProvider-BiXdHjiq.cjs} +34 -1
- package/dist/HostingerProvider-BiXdHjiq.cjs.map +1 -0
- package/dist/{Route53Provider-C8mS0zY6.mjs → Route53Provider-DbBo7Uz5.mjs} +53 -1
- package/dist/Route53Provider-DbBo7Uz5.mjs.map +1 -0
- package/dist/{Route53Provider-Bs7Arms9.cjs → Route53Provider-kfJ77LmL.cjs} +53 -1
- package/dist/Route53Provider-kfJ77LmL.cjs.map +1 -0
- package/dist/backup-provisioner-B5e-F6zX.cjs +164 -0
- package/dist/backup-provisioner-B5e-F6zX.cjs.map +1 -0
- package/dist/backup-provisioner-BIArpmTr.mjs +163 -0
- package/dist/backup-provisioner-BIArpmTr.mjs.map +1 -0
- package/dist/{config-ZQM1vBoz.cjs → config-6JHOwLCx.cjs} +30 -2
- package/dist/{config-ZQM1vBoz.cjs.map → config-6JHOwLCx.cjs.map} +1 -1
- package/dist/{config-DfCJ29PQ.mjs → config-DxASSNjr.mjs} +25 -3
- package/dist/{config-DfCJ29PQ.mjs.map → config-DxASSNjr.mjs.map} +1 -1
- package/dist/config.cjs +3 -2
- package/dist/config.d.cts +14 -2
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +15 -3
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +3 -3
- package/dist/{dokploy-api-z0833e7r.mjs → dokploy-api-2ldYoN3i.mjs} +131 -1
- package/dist/dokploy-api-2ldYoN3i.mjs.map +1 -0
- package/dist/dokploy-api-C93pveuy.mjs +3 -0
- package/dist/dokploy-api-CbDh4o93.cjs +3 -0
- package/dist/{dokploy-api-CQvhV6Hd.cjs → dokploy-api-DLgvEQlr.cjs} +131 -1
- package/dist/dokploy-api-DLgvEQlr.cjs.map +1 -0
- package/dist/{index-C0SpUT9Y.d.mts → index-C-KxSGGK.d.mts} +133 -31
- package/dist/index-C-KxSGGK.d.mts.map +1 -0
- package/dist/{index-B58qjyBd.d.cts → index-Cyk2rTyj.d.cts} +132 -30
- package/dist/index-Cyk2rTyj.d.cts.map +1 -0
- package/dist/index.cjs +662 -152
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +626 -116
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-BcSjLfWq.mjs → openapi-BYlyAbH3.mjs} +6 -5
- package/dist/openapi-BYlyAbH3.mjs.map +1 -0
- package/dist/{openapi-D6Hcfov0.cjs → openapi-CnvwSRDU.cjs} +6 -5
- package/dist/openapi-CnvwSRDU.cjs.map +1 -0
- package/dist/openapi.cjs +3 -3
- package/dist/openapi.d.cts +1 -0
- package/dist/openapi.d.cts.map +1 -1
- package/dist/openapi.d.mts +2 -1
- package/dist/openapi.d.mts.map +1 -1
- package/dist/openapi.mjs +3 -3
- package/dist/{types-B9UZ7fOG.d.mts → types-CZg5iUgD.d.mts} +1 -1
- package/dist/{types-B9UZ7fOG.d.mts.map → types-CZg5iUgD.d.mts.map} +1 -1
- package/dist/workspace/index.cjs +1 -1
- package/dist/workspace/index.d.cts +1 -1
- package/dist/workspace/index.d.mts +2 -2
- package/dist/workspace/index.mjs +1 -1
- package/dist/{workspace-BW2iU37P.mjs → workspace-9IQIjwkQ.mjs} +20 -4
- package/dist/workspace-9IQIjwkQ.mjs.map +1 -0
- package/dist/{workspace-2Do2YcGZ.cjs → workspace-D2ocAlpl.cjs} +20 -4
- package/dist/workspace-D2ocAlpl.cjs.map +1 -0
- package/examples/cron-example.ts +6 -6
- package/examples/function-example.ts +1 -1
- package/package.json +6 -3
- package/src/config.ts +44 -0
- package/src/deploy/__tests__/backup-provisioner.spec.ts +428 -0
- package/src/deploy/__tests__/createDnsProvider.spec.ts +23 -0
- package/src/deploy/__tests__/env-resolver.spec.ts +1 -1
- package/src/deploy/__tests__/undeploy.spec.ts +758 -0
- package/src/deploy/backup-provisioner.ts +316 -0
- package/src/deploy/dns/DnsProvider.ts +39 -1
- package/src/deploy/dns/HostingerProvider.ts +74 -0
- package/src/deploy/dns/Route53Provider.ts +81 -0
- package/src/deploy/dns/index.ts +25 -0
- package/src/deploy/dokploy-api.ts +237 -0
- package/src/deploy/index.ts +71 -13
- package/src/deploy/state.ts +171 -0
- package/src/deploy/undeploy.ts +407 -0
- package/src/dev/__tests__/index.spec.ts +490 -0
- package/src/dev/index.ts +313 -18
- package/src/generators/FunctionGenerator.ts +1 -1
- package/src/generators/Generator.ts +4 -1
- package/src/init/__tests__/generators.spec.ts +167 -18
- package/src/init/__tests__/init.spec.ts +66 -3
- package/src/init/generators/auth.ts +6 -5
- package/src/init/generators/config.ts +49 -7
- package/src/init/generators/docker.ts +8 -8
- package/src/init/generators/index.ts +1 -0
- package/src/init/generators/models.ts +3 -5
- package/src/init/generators/package.ts +4 -0
- package/src/init/generators/test.ts +133 -0
- package/src/init/generators/ui.ts +13 -12
- package/src/init/generators/web.ts +9 -8
- package/src/init/index.ts +2 -0
- package/src/init/templates/api.ts +6 -6
- package/src/init/templates/minimal.ts +2 -2
- package/src/init/templates/worker.ts +2 -2
- package/src/init/versions.ts +3 -3
- package/src/openapi.ts +6 -2
- package/src/test/__tests__/__fixtures__/workspace.ts +104 -0
- package/src/test/__tests__/api.spec.ts +199 -0
- package/src/test/__tests__/auth.spec.ts +162 -0
- package/src/test/__tests__/index.spec.ts +323 -0
- package/src/test/__tests__/web.spec.ts +210 -0
- package/src/test/index.ts +165 -14
- package/src/workspace/__tests__/index.spec.ts +3 -0
- package/src/workspace/index.ts +4 -2
- package/src/workspace/schema.ts +26 -0
- package/src/workspace/types.ts +14 -37
- package/dist/HostingerProvider-B9N-TKbp.mjs.map +0 -1
- package/dist/HostingerProvider-DUV9-Tzg.cjs.map +0 -1
- package/dist/Route53Provider-Bs7Arms9.cjs.map +0 -1
- package/dist/Route53Provider-C8mS0zY6.mjs.map +0 -1
- package/dist/dokploy-api-CQvhV6Hd.cjs.map +0 -1
- package/dist/dokploy-api-CWc02yyg.cjs +0 -3
- package/dist/dokploy-api-DSJYNx88.mjs +0 -3
- package/dist/dokploy-api-z0833e7r.mjs.map +0 -1
- package/dist/index-B58qjyBd.d.cts.map +0 -1
- package/dist/index-C0SpUT9Y.d.mts.map +0 -1
- package/dist/openapi-BcSjLfWq.mjs.map +0 -1
- package/dist/openapi-D6Hcfov0.cjs.map +0 -1
- package/dist/workspace-2Do2YcGZ.cjs.map +0 -1
- package/dist/workspace-BW2iU37P.mjs.map +0 -1
|
@@ -13,11 +13,16 @@ import {
|
|
|
13
13
|
findAvailablePort,
|
|
14
14
|
generateAllDependencyEnvVars,
|
|
15
15
|
isPortAvailable,
|
|
16
|
+
loadPortState,
|
|
16
17
|
loadSecretsForApp,
|
|
17
18
|
normalizeHooksConfig,
|
|
18
19
|
normalizeProductionConfig,
|
|
19
20
|
normalizeStudioConfig,
|
|
20
21
|
normalizeTelescopeConfig,
|
|
22
|
+
parseComposePortMappings,
|
|
23
|
+
replacePortInUrl,
|
|
24
|
+
rewriteUrlsWithPorts,
|
|
25
|
+
savePortState,
|
|
21
26
|
validateFrontendApp,
|
|
22
27
|
validateFrontendApps,
|
|
23
28
|
} from '../index';
|
|
@@ -582,7 +587,9 @@ describe('Workspace Dev Server', () => {
|
|
|
582
587
|
const env = generateAllDependencyEnvVars(workspace);
|
|
583
588
|
expect(env).toEqual({
|
|
584
589
|
API_URL: 'http://localhost:3000',
|
|
590
|
+
NEXT_PUBLIC_API_URL: 'http://localhost:3000',
|
|
585
591
|
AUTH_URL: 'http://localhost:3001',
|
|
592
|
+
NEXT_PUBLIC_AUTH_URL: 'http://localhost:3001',
|
|
586
593
|
});
|
|
587
594
|
});
|
|
588
595
|
|
|
@@ -611,6 +618,7 @@ describe('Workspace Dev Server', () => {
|
|
|
611
618
|
const env = generateAllDependencyEnvVars(workspace);
|
|
612
619
|
expect(env).toEqual({
|
|
613
620
|
'USER-SERVICE_URL': 'http://localhost:3001',
|
|
621
|
+
'NEXT_PUBLIC_USER-SERVICE_URL': 'http://localhost:3001',
|
|
614
622
|
});
|
|
615
623
|
});
|
|
616
624
|
|
|
@@ -633,6 +641,7 @@ describe('Workspace Dev Server', () => {
|
|
|
633
641
|
const env = generateAllDependencyEnvVars(workspace, 'http://127.0.0.1');
|
|
634
642
|
expect(env).toEqual({
|
|
635
643
|
API_URL: 'http://127.0.0.1:3000',
|
|
644
|
+
NEXT_PUBLIC_API_URL: 'http://127.0.0.1:3000',
|
|
636
645
|
});
|
|
637
646
|
});
|
|
638
647
|
|
|
@@ -673,8 +682,11 @@ describe('Workspace Dev Server', () => {
|
|
|
673
682
|
const env = generateAllDependencyEnvVars(workspace);
|
|
674
683
|
expect(env).toEqual({
|
|
675
684
|
AUTH_URL: 'http://localhost:3001',
|
|
685
|
+
NEXT_PUBLIC_AUTH_URL: 'http://localhost:3001',
|
|
676
686
|
API_URL: 'http://localhost:3000',
|
|
687
|
+
NEXT_PUBLIC_API_URL: 'http://localhost:3000',
|
|
677
688
|
PAYMENTS_URL: 'http://localhost:3002',
|
|
689
|
+
NEXT_PUBLIC_PAYMENTS_URL: 'http://localhost:3002',
|
|
678
690
|
});
|
|
679
691
|
});
|
|
680
692
|
});
|
|
@@ -1188,3 +1200,481 @@ describe('loadSecretsForApp', () => {
|
|
|
1188
1200
|
});
|
|
1189
1201
|
});
|
|
1190
1202
|
});
|
|
1203
|
+
|
|
1204
|
+
describe('replacePortInUrl', () => {
|
|
1205
|
+
it('should replace port in a postgresql URL', () => {
|
|
1206
|
+
const url = 'postgresql://app:pass@localhost:5432/mydb';
|
|
1207
|
+
expect(replacePortInUrl(url, 5432, 5433)).toBe(
|
|
1208
|
+
'postgresql://app:pass@localhost:5433/mydb',
|
|
1209
|
+
);
|
|
1210
|
+
});
|
|
1211
|
+
|
|
1212
|
+
it('should replace port in a redis URL', () => {
|
|
1213
|
+
const url = 'redis://:pass@localhost:6379';
|
|
1214
|
+
expect(replacePortInUrl(url, 6379, 6380)).toBe(
|
|
1215
|
+
'redis://:pass@localhost:6380',
|
|
1216
|
+
);
|
|
1217
|
+
});
|
|
1218
|
+
|
|
1219
|
+
it('should replace port with Docker hostname', () => {
|
|
1220
|
+
const url = 'postgresql://app:pass@postgres:5432/mydb';
|
|
1221
|
+
expect(replacePortInUrl(url, 5432, 5433)).toBe(
|
|
1222
|
+
'postgresql://app:pass@postgres:5433/mydb',
|
|
1223
|
+
);
|
|
1224
|
+
});
|
|
1225
|
+
|
|
1226
|
+
it('should return url unchanged when ports are equal', () => {
|
|
1227
|
+
const url = 'postgresql://app:pass@localhost:5432/mydb';
|
|
1228
|
+
expect(replacePortInUrl(url, 5432, 5432)).toBe(url);
|
|
1229
|
+
});
|
|
1230
|
+
|
|
1231
|
+
it('should not replace port that appears in path or password', () => {
|
|
1232
|
+
const url = 'postgresql://app:pass5432@localhost:5432/db5432';
|
|
1233
|
+
const result = replacePortInUrl(url, 5432, 5433);
|
|
1234
|
+
// Only the :5432 before / should be replaced
|
|
1235
|
+
expect(result).toBe('postgresql://app:pass5432@localhost:5433/db5432');
|
|
1236
|
+
});
|
|
1237
|
+
});
|
|
1238
|
+
|
|
1239
|
+
describe('rewriteUrlsWithPorts', () => {
|
|
1240
|
+
const pgMapping = {
|
|
1241
|
+
service: 'postgres',
|
|
1242
|
+
envVar: 'POSTGRES_HOST_PORT',
|
|
1243
|
+
defaultPort: 5432,
|
|
1244
|
+
containerPort: 5432,
|
|
1245
|
+
};
|
|
1246
|
+
const redisMapping = {
|
|
1247
|
+
service: 'redis',
|
|
1248
|
+
envVar: 'REDIS_HOST_PORT',
|
|
1249
|
+
defaultPort: 6379,
|
|
1250
|
+
containerPort: 6379,
|
|
1251
|
+
};
|
|
1252
|
+
const rmqMapping = {
|
|
1253
|
+
service: 'rabbitmq',
|
|
1254
|
+
envVar: 'RABBITMQ_HOST_PORT',
|
|
1255
|
+
defaultPort: 5672,
|
|
1256
|
+
containerPort: 5672,
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1259
|
+
it('should rewrite DATABASE_URL with resolved postgres port', () => {
|
|
1260
|
+
const secrets = {
|
|
1261
|
+
DATABASE_URL: 'postgresql://app:pass@postgres:5432/mydb',
|
|
1262
|
+
POSTGRES_PORT: '5432',
|
|
1263
|
+
SOME_OTHER: 'value',
|
|
1264
|
+
};
|
|
1265
|
+
const result = rewriteUrlsWithPorts(secrets, {
|
|
1266
|
+
dockerEnv: { POSTGRES_HOST_PORT: '5433' },
|
|
1267
|
+
ports: { POSTGRES_HOST_PORT: 5433 },
|
|
1268
|
+
mappings: [pgMapping],
|
|
1269
|
+
});
|
|
1270
|
+
expect(result.DATABASE_URL).toBe(
|
|
1271
|
+
'postgresql://app:pass@postgres:5433/mydb',
|
|
1272
|
+
);
|
|
1273
|
+
expect(result.POSTGRES_PORT).toBe('5433');
|
|
1274
|
+
expect(result.SOME_OTHER).toBe('value');
|
|
1275
|
+
});
|
|
1276
|
+
|
|
1277
|
+
it('should rewrite fullstack APP_DATABASE_URL', () => {
|
|
1278
|
+
const secrets = {
|
|
1279
|
+
API_DATABASE_URL: 'postgresql://api:pass@localhost:5432/mydb',
|
|
1280
|
+
AUTH_DATABASE_URL: 'postgresql://auth:pass@localhost:5432/mydb',
|
|
1281
|
+
};
|
|
1282
|
+
const result = rewriteUrlsWithPorts(secrets, {
|
|
1283
|
+
dockerEnv: { POSTGRES_HOST_PORT: '5433' },
|
|
1284
|
+
ports: { POSTGRES_HOST_PORT: 5433 },
|
|
1285
|
+
mappings: [pgMapping],
|
|
1286
|
+
});
|
|
1287
|
+
expect(result.API_DATABASE_URL).toBe(
|
|
1288
|
+
'postgresql://api:pass@localhost:5433/mydb',
|
|
1289
|
+
);
|
|
1290
|
+
expect(result.AUTH_DATABASE_URL).toBe(
|
|
1291
|
+
'postgresql://auth:pass@localhost:5433/mydb',
|
|
1292
|
+
);
|
|
1293
|
+
});
|
|
1294
|
+
|
|
1295
|
+
it('should rewrite REDIS_URL and REDIS_PORT', () => {
|
|
1296
|
+
const secrets = {
|
|
1297
|
+
REDIS_URL: 'redis://:pass@redis:6379',
|
|
1298
|
+
REDIS_PORT: '6379',
|
|
1299
|
+
};
|
|
1300
|
+
const result = rewriteUrlsWithPorts(secrets, {
|
|
1301
|
+
dockerEnv: { REDIS_HOST_PORT: '6380' },
|
|
1302
|
+
ports: { REDIS_HOST_PORT: 6380 },
|
|
1303
|
+
mappings: [redisMapping],
|
|
1304
|
+
});
|
|
1305
|
+
expect(result.REDIS_URL).toBe('redis://:pass@redis:6380');
|
|
1306
|
+
expect(result.REDIS_PORT).toBe('6380');
|
|
1307
|
+
});
|
|
1308
|
+
|
|
1309
|
+
it('should rewrite RABBITMQ_URL and RABBITMQ_PORT', () => {
|
|
1310
|
+
const secrets = {
|
|
1311
|
+
RABBITMQ_URL: 'amqp://app:pass@rabbitmq:5672/%2F',
|
|
1312
|
+
RABBITMQ_PORT: '5672',
|
|
1313
|
+
};
|
|
1314
|
+
const result = rewriteUrlsWithPorts(secrets, {
|
|
1315
|
+
dockerEnv: { RABBITMQ_HOST_PORT: '5673' },
|
|
1316
|
+
ports: { RABBITMQ_HOST_PORT: 5673 },
|
|
1317
|
+
mappings: [rmqMapping],
|
|
1318
|
+
});
|
|
1319
|
+
expect(result.RABBITMQ_URL).toBe('amqp://app:pass@rabbitmq:5673/%2F');
|
|
1320
|
+
expect(result.RABBITMQ_PORT).toBe('5673');
|
|
1321
|
+
});
|
|
1322
|
+
|
|
1323
|
+
it('should handle multiple services at once', () => {
|
|
1324
|
+
const secrets = {
|
|
1325
|
+
DATABASE_URL: 'postgresql://app:pass@postgres:5432/mydb',
|
|
1326
|
+
POSTGRES_PORT: '5432',
|
|
1327
|
+
REDIS_URL: 'redis://:pass@redis:6379',
|
|
1328
|
+
REDIS_PORT: '6379',
|
|
1329
|
+
};
|
|
1330
|
+
const result = rewriteUrlsWithPorts(secrets, {
|
|
1331
|
+
dockerEnv: {
|
|
1332
|
+
POSTGRES_HOST_PORT: '5433',
|
|
1333
|
+
REDIS_HOST_PORT: '6380',
|
|
1334
|
+
},
|
|
1335
|
+
ports: { POSTGRES_HOST_PORT: 5433, REDIS_HOST_PORT: 6380 },
|
|
1336
|
+
mappings: [pgMapping, redisMapping],
|
|
1337
|
+
});
|
|
1338
|
+
expect(result.DATABASE_URL).toContain(':5433/');
|
|
1339
|
+
expect(result.POSTGRES_PORT).toBe('5433');
|
|
1340
|
+
expect(result.REDIS_URL).toContain(':6380');
|
|
1341
|
+
expect(result.REDIS_PORT).toBe('6380');
|
|
1342
|
+
});
|
|
1343
|
+
|
|
1344
|
+
it('should not modify secrets when ports are defaults', () => {
|
|
1345
|
+
const secrets = {
|
|
1346
|
+
DATABASE_URL: 'postgresql://app:pass@postgres:5432/mydb',
|
|
1347
|
+
POSTGRES_PORT: '5432',
|
|
1348
|
+
};
|
|
1349
|
+
const result = rewriteUrlsWithPorts(secrets, {
|
|
1350
|
+
dockerEnv: { POSTGRES_HOST_PORT: '5432' },
|
|
1351
|
+
ports: { POSTGRES_HOST_PORT: 5432 },
|
|
1352
|
+
mappings: [pgMapping],
|
|
1353
|
+
});
|
|
1354
|
+
expect(result.DATABASE_URL).toBe(secrets.DATABASE_URL);
|
|
1355
|
+
expect(result.POSTGRES_PORT).toBe('5432');
|
|
1356
|
+
});
|
|
1357
|
+
|
|
1358
|
+
it('should return empty for no mappings', () => {
|
|
1359
|
+
const result = rewriteUrlsWithPorts(
|
|
1360
|
+
{},
|
|
1361
|
+
{ dockerEnv: {}, ports: {}, mappings: [] },
|
|
1362
|
+
);
|
|
1363
|
+
expect(result).toEqual({});
|
|
1364
|
+
});
|
|
1365
|
+
});
|
|
1366
|
+
|
|
1367
|
+
describe('port state persistence', () => {
|
|
1368
|
+
let testDir: string;
|
|
1369
|
+
|
|
1370
|
+
beforeEach(() => {
|
|
1371
|
+
testDir = join(tmpdir(), `gkm-port-state-test-${Date.now()}`);
|
|
1372
|
+
mkdirSync(testDir, { recursive: true });
|
|
1373
|
+
});
|
|
1374
|
+
|
|
1375
|
+
afterEach(() => {
|
|
1376
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
1377
|
+
});
|
|
1378
|
+
|
|
1379
|
+
it('should return empty object when no state file exists', async () => {
|
|
1380
|
+
const state = await loadPortState(testDir);
|
|
1381
|
+
expect(state).toEqual({});
|
|
1382
|
+
});
|
|
1383
|
+
|
|
1384
|
+
it('should save and load port state', async () => {
|
|
1385
|
+
const ports = { POSTGRES_HOST_PORT: 5433, REDIS_HOST_PORT: 6380 };
|
|
1386
|
+
await savePortState(testDir, ports);
|
|
1387
|
+
const loaded = await loadPortState(testDir);
|
|
1388
|
+
expect(loaded).toEqual(ports);
|
|
1389
|
+
});
|
|
1390
|
+
|
|
1391
|
+
it('should create .gkm directory if missing', async () => {
|
|
1392
|
+
const ports = { POSTGRES_HOST_PORT: 5433 };
|
|
1393
|
+
await savePortState(testDir, ports);
|
|
1394
|
+
expect(existsSync(join(testDir, '.gkm'))).toBe(true);
|
|
1395
|
+
expect(existsSync(join(testDir, '.gkm', 'ports.json'))).toBe(true);
|
|
1396
|
+
});
|
|
1397
|
+
|
|
1398
|
+
it('should overwrite existing state', async () => {
|
|
1399
|
+
await savePortState(testDir, { POSTGRES_HOST_PORT: 5433 });
|
|
1400
|
+
await savePortState(testDir, {
|
|
1401
|
+
POSTGRES_HOST_PORT: 5434,
|
|
1402
|
+
REDIS_HOST_PORT: 6380,
|
|
1403
|
+
});
|
|
1404
|
+
const loaded = await loadPortState(testDir);
|
|
1405
|
+
expect(loaded).toEqual({
|
|
1406
|
+
POSTGRES_HOST_PORT: 5434,
|
|
1407
|
+
REDIS_HOST_PORT: 6380,
|
|
1408
|
+
});
|
|
1409
|
+
});
|
|
1410
|
+
});
|
|
1411
|
+
|
|
1412
|
+
describe('parseComposePortMappings', () => {
|
|
1413
|
+
let testDir: string;
|
|
1414
|
+
|
|
1415
|
+
beforeEach(() => {
|
|
1416
|
+
testDir = join(tmpdir(), `gkm-compose-parse-test-${Date.now()}`);
|
|
1417
|
+
mkdirSync(testDir, { recursive: true });
|
|
1418
|
+
});
|
|
1419
|
+
|
|
1420
|
+
afterEach(() => {
|
|
1421
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
1422
|
+
});
|
|
1423
|
+
|
|
1424
|
+
it('should parse standard api template ports', () => {
|
|
1425
|
+
const composePath = join(testDir, 'docker-compose.yml');
|
|
1426
|
+
writeFileSync(
|
|
1427
|
+
composePath,
|
|
1428
|
+
`
|
|
1429
|
+
services:
|
|
1430
|
+
postgres:
|
|
1431
|
+
image: postgres:17
|
|
1432
|
+
ports:
|
|
1433
|
+
- '\${POSTGRES_HOST_PORT:-5432}:5432'
|
|
1434
|
+
redis:
|
|
1435
|
+
image: redis:7
|
|
1436
|
+
ports:
|
|
1437
|
+
- '\${REDIS_HOST_PORT:-6379}:6379'
|
|
1438
|
+
mailpit:
|
|
1439
|
+
image: axllent/mailpit
|
|
1440
|
+
ports:
|
|
1441
|
+
- '\${MAILPIT_SMTP_PORT:-1025}:1025'
|
|
1442
|
+
- '\${MAILPIT_UI_PORT:-8025}:8025'
|
|
1443
|
+
`,
|
|
1444
|
+
);
|
|
1445
|
+
|
|
1446
|
+
const mappings = parseComposePortMappings(composePath);
|
|
1447
|
+
expect(mappings).toEqual([
|
|
1448
|
+
{
|
|
1449
|
+
service: 'postgres',
|
|
1450
|
+
envVar: 'POSTGRES_HOST_PORT',
|
|
1451
|
+
defaultPort: 5432,
|
|
1452
|
+
containerPort: 5432,
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
service: 'redis',
|
|
1456
|
+
envVar: 'REDIS_HOST_PORT',
|
|
1457
|
+
defaultPort: 6379,
|
|
1458
|
+
containerPort: 6379,
|
|
1459
|
+
},
|
|
1460
|
+
{
|
|
1461
|
+
service: 'mailpit',
|
|
1462
|
+
envVar: 'MAILPIT_SMTP_PORT',
|
|
1463
|
+
defaultPort: 1025,
|
|
1464
|
+
containerPort: 1025,
|
|
1465
|
+
},
|
|
1466
|
+
{
|
|
1467
|
+
service: 'mailpit',
|
|
1468
|
+
envVar: 'MAILPIT_UI_PORT',
|
|
1469
|
+
defaultPort: 8025,
|
|
1470
|
+
containerPort: 8025,
|
|
1471
|
+
},
|
|
1472
|
+
]);
|
|
1473
|
+
});
|
|
1474
|
+
|
|
1475
|
+
it('should parse worker template with rabbitmq', () => {
|
|
1476
|
+
const composePath = join(testDir, 'docker-compose.yml');
|
|
1477
|
+
writeFileSync(
|
|
1478
|
+
composePath,
|
|
1479
|
+
`
|
|
1480
|
+
services:
|
|
1481
|
+
postgres:
|
|
1482
|
+
image: postgres:17
|
|
1483
|
+
ports:
|
|
1484
|
+
- '\${POSTGRES_HOST_PORT:-5432}:5432'
|
|
1485
|
+
rabbitmq:
|
|
1486
|
+
image: rabbitmq:3-management
|
|
1487
|
+
ports:
|
|
1488
|
+
- '\${RABBITMQ_HOST_PORT:-5672}:5672'
|
|
1489
|
+
- '\${RABBITMQ_MGMT_PORT:-15672}:15672'
|
|
1490
|
+
`,
|
|
1491
|
+
);
|
|
1492
|
+
|
|
1493
|
+
const mappings = parseComposePortMappings(composePath);
|
|
1494
|
+
expect(mappings).toEqual([
|
|
1495
|
+
{
|
|
1496
|
+
service: 'postgres',
|
|
1497
|
+
envVar: 'POSTGRES_HOST_PORT',
|
|
1498
|
+
defaultPort: 5432,
|
|
1499
|
+
containerPort: 5432,
|
|
1500
|
+
},
|
|
1501
|
+
{
|
|
1502
|
+
service: 'rabbitmq',
|
|
1503
|
+
envVar: 'RABBITMQ_HOST_PORT',
|
|
1504
|
+
defaultPort: 5672,
|
|
1505
|
+
containerPort: 5672,
|
|
1506
|
+
},
|
|
1507
|
+
{
|
|
1508
|
+
service: 'rabbitmq',
|
|
1509
|
+
envVar: 'RABBITMQ_MGMT_PORT',
|
|
1510
|
+
defaultPort: 15672,
|
|
1511
|
+
containerPort: 15672,
|
|
1512
|
+
},
|
|
1513
|
+
]);
|
|
1514
|
+
});
|
|
1515
|
+
|
|
1516
|
+
it('should parse serverless template with redis variants', () => {
|
|
1517
|
+
const composePath = join(testDir, 'docker-compose.yml');
|
|
1518
|
+
writeFileSync(
|
|
1519
|
+
composePath,
|
|
1520
|
+
`
|
|
1521
|
+
services:
|
|
1522
|
+
postgres:
|
|
1523
|
+
image: postgres:17
|
|
1524
|
+
ports:
|
|
1525
|
+
- '\${POSTGRES_HOST_PORT:-5432}:5432'
|
|
1526
|
+
redis:
|
|
1527
|
+
image: redis:7
|
|
1528
|
+
ports:
|
|
1529
|
+
- '\${REDIS_HOST_PORT:-6379}:6379'
|
|
1530
|
+
serverless-redis-http:
|
|
1531
|
+
image: hiett/serverless-redis-http:latest
|
|
1532
|
+
ports:
|
|
1533
|
+
- '\${SRH_PORT:-8079}:80'
|
|
1534
|
+
`,
|
|
1535
|
+
);
|
|
1536
|
+
|
|
1537
|
+
const mappings = parseComposePortMappings(composePath);
|
|
1538
|
+
expect(mappings).toEqual([
|
|
1539
|
+
{
|
|
1540
|
+
service: 'postgres',
|
|
1541
|
+
envVar: 'POSTGRES_HOST_PORT',
|
|
1542
|
+
defaultPort: 5432,
|
|
1543
|
+
containerPort: 5432,
|
|
1544
|
+
},
|
|
1545
|
+
{
|
|
1546
|
+
service: 'redis',
|
|
1547
|
+
envVar: 'REDIS_HOST_PORT',
|
|
1548
|
+
defaultPort: 6379,
|
|
1549
|
+
containerPort: 6379,
|
|
1550
|
+
},
|
|
1551
|
+
{
|
|
1552
|
+
service: 'serverless-redis-http',
|
|
1553
|
+
envVar: 'SRH_PORT',
|
|
1554
|
+
defaultPort: 8079,
|
|
1555
|
+
containerPort: 80,
|
|
1556
|
+
},
|
|
1557
|
+
]);
|
|
1558
|
+
});
|
|
1559
|
+
|
|
1560
|
+
it('should handle custom user-added services', () => {
|
|
1561
|
+
const composePath = join(testDir, 'docker-compose.yml');
|
|
1562
|
+
writeFileSync(
|
|
1563
|
+
composePath,
|
|
1564
|
+
`
|
|
1565
|
+
services:
|
|
1566
|
+
postgres:
|
|
1567
|
+
image: postgres:17
|
|
1568
|
+
ports:
|
|
1569
|
+
- '\${POSTGRES_HOST_PORT:-5432}:5432'
|
|
1570
|
+
pgadmin:
|
|
1571
|
+
image: dpage/pgadmin4
|
|
1572
|
+
ports:
|
|
1573
|
+
- '\${PGADMIN_HOST_PORT:-5050}:80'
|
|
1574
|
+
minio:
|
|
1575
|
+
image: minio/minio
|
|
1576
|
+
ports:
|
|
1577
|
+
- '\${MINIO_API_PORT:-9000}:9000'
|
|
1578
|
+
- '\${MINIO_CONSOLE_PORT:-9001}:9001'
|
|
1579
|
+
`,
|
|
1580
|
+
);
|
|
1581
|
+
|
|
1582
|
+
const mappings = parseComposePortMappings(composePath);
|
|
1583
|
+
expect(mappings).toEqual([
|
|
1584
|
+
{
|
|
1585
|
+
service: 'postgres',
|
|
1586
|
+
envVar: 'POSTGRES_HOST_PORT',
|
|
1587
|
+
defaultPort: 5432,
|
|
1588
|
+
containerPort: 5432,
|
|
1589
|
+
},
|
|
1590
|
+
{
|
|
1591
|
+
service: 'pgadmin',
|
|
1592
|
+
envVar: 'PGADMIN_HOST_PORT',
|
|
1593
|
+
defaultPort: 5050,
|
|
1594
|
+
containerPort: 80,
|
|
1595
|
+
},
|
|
1596
|
+
{
|
|
1597
|
+
service: 'minio',
|
|
1598
|
+
envVar: 'MINIO_API_PORT',
|
|
1599
|
+
defaultPort: 9000,
|
|
1600
|
+
containerPort: 9000,
|
|
1601
|
+
},
|
|
1602
|
+
{
|
|
1603
|
+
service: 'minio',
|
|
1604
|
+
envVar: 'MINIO_CONSOLE_PORT',
|
|
1605
|
+
defaultPort: 9001,
|
|
1606
|
+
containerPort: 9001,
|
|
1607
|
+
},
|
|
1608
|
+
]);
|
|
1609
|
+
});
|
|
1610
|
+
|
|
1611
|
+
it('should skip fixed port mappings without env vars', () => {
|
|
1612
|
+
const composePath = join(testDir, 'docker-compose.yml');
|
|
1613
|
+
writeFileSync(
|
|
1614
|
+
composePath,
|
|
1615
|
+
`
|
|
1616
|
+
services:
|
|
1617
|
+
postgres:
|
|
1618
|
+
image: postgres:17
|
|
1619
|
+
ports:
|
|
1620
|
+
- '\${POSTGRES_HOST_PORT:-5432}:5432'
|
|
1621
|
+
nginx:
|
|
1622
|
+
image: nginx
|
|
1623
|
+
ports:
|
|
1624
|
+
- '8080:80'
|
|
1625
|
+
- '443:443'
|
|
1626
|
+
`,
|
|
1627
|
+
);
|
|
1628
|
+
|
|
1629
|
+
const mappings = parseComposePortMappings(composePath);
|
|
1630
|
+
expect(mappings).toEqual([
|
|
1631
|
+
{
|
|
1632
|
+
service: 'postgres',
|
|
1633
|
+
envVar: 'POSTGRES_HOST_PORT',
|
|
1634
|
+
defaultPort: 5432,
|
|
1635
|
+
containerPort: 5432,
|
|
1636
|
+
},
|
|
1637
|
+
]);
|
|
1638
|
+
});
|
|
1639
|
+
|
|
1640
|
+
it('should skip services without ports', () => {
|
|
1641
|
+
const composePath = join(testDir, 'docker-compose.yml');
|
|
1642
|
+
writeFileSync(
|
|
1643
|
+
composePath,
|
|
1644
|
+
`
|
|
1645
|
+
services:
|
|
1646
|
+
postgres:
|
|
1647
|
+
image: postgres:17
|
|
1648
|
+
ports:
|
|
1649
|
+
- '\${POSTGRES_HOST_PORT:-5432}:5432'
|
|
1650
|
+
worker:
|
|
1651
|
+
image: node:22
|
|
1652
|
+
command: npm start
|
|
1653
|
+
`,
|
|
1654
|
+
);
|
|
1655
|
+
|
|
1656
|
+
const mappings = parseComposePortMappings(composePath);
|
|
1657
|
+
expect(mappings).toEqual([
|
|
1658
|
+
{
|
|
1659
|
+
service: 'postgres',
|
|
1660
|
+
envVar: 'POSTGRES_HOST_PORT',
|
|
1661
|
+
defaultPort: 5432,
|
|
1662
|
+
containerPort: 5432,
|
|
1663
|
+
},
|
|
1664
|
+
]);
|
|
1665
|
+
});
|
|
1666
|
+
|
|
1667
|
+
it('should return empty array when file does not exist', () => {
|
|
1668
|
+
const composePath = join(testDir, 'nonexistent.yml');
|
|
1669
|
+
const mappings = parseComposePortMappings(composePath);
|
|
1670
|
+
expect(mappings).toEqual([]);
|
|
1671
|
+
});
|
|
1672
|
+
|
|
1673
|
+
it('should return empty array when no services defined', () => {
|
|
1674
|
+
const composePath = join(testDir, 'docker-compose.yml');
|
|
1675
|
+
writeFileSync(composePath, 'version: "3.8"\n');
|
|
1676
|
+
|
|
1677
|
+
const mappings = parseComposePortMappings(composePath);
|
|
1678
|
+
expect(mappings).toEqual([]);
|
|
1679
|
+
});
|
|
1680
|
+
});
|