@geekmidas/cli 1.10.36 → 1.10.37
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 +10 -0
- package/dist/{config-U-gojtxn.mjs → config-Bbu1JKvf.mjs} +2 -2
- package/dist/{config-U-gojtxn.mjs.map → config-Bbu1JKvf.mjs.map} +1 -1
- package/dist/{config-QnuOcYXp.cjs → config-DujV8DbR.cjs} +2 -2
- package/dist/{config-QnuOcYXp.cjs.map → config-DujV8DbR.cjs.map} +1 -1
- package/dist/config.cjs +2 -2
- package/dist/config.d.cts +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/config.mjs +2 -2
- package/dist/{fullstack-secrets-Bchl2MDd.cjs → fullstack-secrets-BYzi6Hwl.cjs} +3 -2
- package/dist/{fullstack-secrets-Bchl2MDd.cjs.map → fullstack-secrets-BYzi6Hwl.cjs.map} +1 -1
- package/dist/{fullstack-secrets-P84v8zWn.mjs → fullstack-secrets-l8s3II_H.mjs} +3 -2
- package/dist/{fullstack-secrets-P84v8zWn.mjs.map → fullstack-secrets-l8s3II_H.mjs.map} +1 -1
- package/dist/{index-D7iT4dnv.d.mts → index-BBvGMG_A.d.mts} +124 -67
- package/dist/index-BBvGMG_A.d.mts.map +1 -0
- package/dist/{index-DRQq26DF.d.cts → index-Dz2a7xQU.d.cts} +124 -67
- package/dist/index-Dz2a7xQU.d.cts.map +1 -0
- package/dist/index.cjs +244 -91
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +244 -91
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-Bb4UEyZN.cjs → openapi-0JUzU5Tv.cjs} +9 -2
- package/dist/{openapi-Bb4UEyZN.cjs.map → openapi-0JUzU5Tv.cjs.map} +1 -1
- package/dist/{openapi-BA0e3I_s.mjs → openapi-C5AycKTR.mjs} +10 -3
- package/dist/{openapi-BA0e3I_s.mjs.map → openapi-C5AycKTR.mjs.map} +1 -1
- package/dist/openapi.cjs +3 -3
- package/dist/openapi.mjs +3 -3
- package/dist/{reconcile-DAAKa0YR.mjs → reconcile-CYGmqXvq.mjs} +2 -2
- package/dist/{reconcile-DAAKa0YR.mjs.map → reconcile-CYGmqXvq.mjs.map} +1 -1
- package/dist/{reconcile-CZtzdrnc.cjs → reconcile-D93YG7G5.cjs} +2 -2
- package/dist/{reconcile-CZtzdrnc.cjs.map → reconcile-D93YG7G5.cjs.map} +1 -1
- package/dist/workspace/index.cjs +1 -1
- package/dist/workspace/index.d.cts +1 -1
- package/dist/workspace/index.d.mts +1 -1
- package/dist/workspace/index.mjs +1 -1
- package/dist/{workspace-BobDOIG9.cjs → workspace-CQTT7HJQ.cjs} +34 -25
- package/dist/workspace-CQTT7HJQ.cjs.map +1 -0
- package/dist/{workspace-Cgmvgwh8.mjs → workspace-D-37Ylqo.mjs} +34 -25
- package/dist/workspace-D-37Ylqo.mjs.map +1 -0
- package/docs/dev-server-resilience-design.md +189 -0
- package/package.json +5 -5
- package/src/build/__tests__/workspace-build.spec.ts +7 -7
- package/src/build/index.ts +25 -9
- package/src/credentials/__tests__/helpers.ts +1 -1
- package/src/credentials/__tests__/workspaceCredentials.spec.ts +1 -1
- package/src/deploy/__tests__/domain.spec.ts +12 -12
- package/src/deploy/__tests__/env-resolver.spec.ts +1 -1
- package/src/deploy/__tests__/index.spec.ts +14 -14
- package/src/deploy/__tests__/sniffer.spec.ts +9 -9
- package/src/deploy/domain.ts +19 -11
- package/src/deploy/index.ts +12 -1
- package/src/deploy/sniffer.ts +1 -1
- package/src/deploy/types.ts +1 -1
- package/src/dev/__tests__/index.spec.ts +11 -11
- package/src/dev/index.ts +14 -8
- package/src/docker/__tests__/compose.spec.ts +4 -4
- package/src/docker/compose.ts +5 -3
- package/src/docker/index.ts +34 -6
- package/src/docker/templates.ts +138 -0
- package/src/generators/OpenApiTsGenerator.ts +22 -0
- package/src/generators/__tests__/OpenApiTsGenerator.registry.spec.ts +77 -0
- package/src/init/__tests__/init.spec.ts +1 -1
- package/src/init/generators/monorepo.ts +3 -3
- package/src/secrets/__tests__/reconcile.spec.ts +1 -1
- package/src/setup/__tests__/reconcile-secrets.spec.ts +2 -2
- package/src/setup/fullstack-secrets.ts +7 -1
- package/src/setup/index.ts +2 -1
- package/src/test/__tests__/__fixtures__/workspace.ts +1 -1
- package/src/test/__tests__/web.spec.ts +2 -2
- package/src/workspace/__tests__/client-generator.spec.ts +6 -6
- package/src/workspace/__tests__/index.spec.ts +4 -4
- package/src/workspace/__tests__/schema.spec.ts +27 -30
- package/src/workspace/__tests__/type-inference.spec.ts +5 -5
- package/src/workspace/client-generator.ts +10 -7
- package/src/workspace/index.ts +1 -1
- package/src/workspace/publicEnv.ts +2 -4
- package/src/workspace/schema.ts +126 -27
- package/src/workspace/types.ts +40 -69
- package/dist/index-D7iT4dnv.d.mts.map +0 -1
- package/dist/index-DRQq26DF.d.cts.map +0 -1
- package/dist/workspace-BobDOIG9.cjs.map +0 -1
- package/dist/workspace-Cgmvgwh8.mjs.map +0 -1
|
@@ -322,7 +322,7 @@ function generateFrontendAppEntry(options: TemplateOptions): string {
|
|
|
322
322
|
switch (options.frontendFramework) {
|
|
323
323
|
case 'tanstack-start':
|
|
324
324
|
return `web: {
|
|
325
|
-
type: '
|
|
325
|
+
type: 'web',
|
|
326
326
|
framework: 'tanstack-start',
|
|
327
327
|
path: 'apps/web',
|
|
328
328
|
port: 3001,
|
|
@@ -334,7 +334,7 @@ function generateFrontendAppEntry(options: TemplateOptions): string {
|
|
|
334
334
|
},`;
|
|
335
335
|
case 'expo':
|
|
336
336
|
return `app: {
|
|
337
|
-
type: '
|
|
337
|
+
type: 'mobile',
|
|
338
338
|
framework: 'expo',
|
|
339
339
|
path: 'apps/app',
|
|
340
340
|
port: 8081,
|
|
@@ -342,7 +342,7 @@ function generateFrontendAppEntry(options: TemplateOptions): string {
|
|
|
342
342
|
},`;
|
|
343
343
|
default:
|
|
344
344
|
return `web: {
|
|
345
|
-
type: '
|
|
345
|
+
type: 'web',
|
|
346
346
|
framework: 'nextjs',
|
|
347
347
|
path: 'apps/web',
|
|
348
348
|
port: 3001,
|
|
@@ -29,7 +29,7 @@ function createWorkspace(
|
|
|
29
29
|
dependencies: [],
|
|
30
30
|
},
|
|
31
31
|
web: {
|
|
32
|
-
type: '
|
|
32
|
+
type: 'web',
|
|
33
33
|
port: 3002,
|
|
34
34
|
root: '/tmp/test-project/apps/web',
|
|
35
35
|
packageName: '@test/web',
|
|
@@ -333,7 +333,7 @@ describe('generateFullstackCustomSecrets', () => {
|
|
|
333
333
|
dependencies: [],
|
|
334
334
|
},
|
|
335
335
|
web: {
|
|
336
|
-
type: '
|
|
336
|
+
type: 'web',
|
|
337
337
|
port: 3001,
|
|
338
338
|
root: '/tmp/test-project/apps/web',
|
|
339
339
|
path: 'apps/web',
|
|
@@ -55,13 +55,19 @@ export function generateFullstackCustomSecrets(
|
|
|
55
55
|
const frontendPorts: number[] = [];
|
|
56
56
|
|
|
57
57
|
for (const [appName, appConfig] of Object.entries(workspace.apps)) {
|
|
58
|
-
if (appConfig.type === '
|
|
58
|
+
if (appConfig.type === 'web') {
|
|
59
59
|
frontendPorts.push(appConfig.port);
|
|
60
60
|
const upperName = appName.toUpperCase();
|
|
61
61
|
customs[`${upperName}_URL`] = `http://localhost:${appConfig.port}`;
|
|
62
62
|
continue;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
// Mobile apps (Expo, etc.) don't run on a host port the backend
|
|
66
|
+
// cares about for CORS, and don't need DB credentials.
|
|
67
|
+
if (appConfig.type === 'mobile') {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
|
|
65
71
|
// Backend apps with database: generate per-app DB passwords and URLs
|
|
66
72
|
const password = generateDbPassword();
|
|
67
73
|
const upperName = appName.toUpperCase();
|
package/src/setup/index.ts
CHANGED
|
@@ -359,7 +359,8 @@ function printSummary(workspace: NormalizedWorkspace, stage: string): void {
|
|
|
359
359
|
|
|
360
360
|
logger.log('📋 Apps:');
|
|
361
361
|
for (const [name, app] of Object.entries(workspace.apps)) {
|
|
362
|
-
const icon =
|
|
362
|
+
const icon =
|
|
363
|
+
app.type === 'web' ? '🌐' : app.type === 'mobile' ? '📱' : '🔧';
|
|
363
364
|
logger.log(` ${icon} ${name} → http://localhost:${app.port}`);
|
|
364
365
|
}
|
|
365
366
|
|
|
@@ -104,7 +104,7 @@ describe('web (frontend) app context', () => {
|
|
|
104
104
|
dependencies: [],
|
|
105
105
|
},
|
|
106
106
|
web: {
|
|
107
|
-
type: '
|
|
107
|
+
type: 'web',
|
|
108
108
|
path: 'apps/web',
|
|
109
109
|
port: 3001,
|
|
110
110
|
framework: 'nextjs',
|
|
@@ -149,7 +149,7 @@ describe('web (frontend) app context', () => {
|
|
|
149
149
|
dependencies: [],
|
|
150
150
|
},
|
|
151
151
|
web: {
|
|
152
|
-
type: '
|
|
152
|
+
type: 'web',
|
|
153
153
|
path: 'apps/web',
|
|
154
154
|
port: 3001,
|
|
155
155
|
framework: 'nextjs',
|
|
@@ -108,7 +108,7 @@ describe('Client Generator', () => {
|
|
|
108
108
|
resolvedDeployTarget: 'dokploy',
|
|
109
109
|
},
|
|
110
110
|
web: {
|
|
111
|
-
type: '
|
|
111
|
+
type: 'web',
|
|
112
112
|
path: 'apps/web',
|
|
113
113
|
port: 3002,
|
|
114
114
|
dependencies: ['api', 'auth'],
|
|
@@ -147,7 +147,7 @@ describe('Client Generator', () => {
|
|
|
147
147
|
// No routes - not an HTTP backend
|
|
148
148
|
},
|
|
149
149
|
web: {
|
|
150
|
-
type: '
|
|
150
|
+
type: 'web',
|
|
151
151
|
path: 'apps/web',
|
|
152
152
|
port: 3002,
|
|
153
153
|
dependencies: ['api', 'worker'],
|
|
@@ -204,21 +204,21 @@ describe('Client Generator', () => {
|
|
|
204
204
|
resolvedDeployTarget: 'dokploy',
|
|
205
205
|
},
|
|
206
206
|
web: {
|
|
207
|
-
type: '
|
|
207
|
+
type: 'web',
|
|
208
208
|
path: 'apps/web',
|
|
209
209
|
port: 3001,
|
|
210
210
|
dependencies: ['api'],
|
|
211
211
|
resolvedDeployTarget: 'dokploy',
|
|
212
212
|
},
|
|
213
213
|
admin: {
|
|
214
|
-
type: '
|
|
214
|
+
type: 'web',
|
|
215
215
|
path: 'apps/admin',
|
|
216
216
|
port: 3002,
|
|
217
217
|
dependencies: ['api'],
|
|
218
218
|
resolvedDeployTarget: 'dokploy',
|
|
219
219
|
},
|
|
220
220
|
docs: {
|
|
221
|
-
type: '
|
|
221
|
+
type: 'web',
|
|
222
222
|
path: 'apps/docs',
|
|
223
223
|
port: 3003,
|
|
224
224
|
dependencies: [], // No API dependency
|
|
@@ -291,7 +291,7 @@ describe('Client Generator', () => {
|
|
|
291
291
|
root: '/project',
|
|
292
292
|
apps: {
|
|
293
293
|
web: {
|
|
294
|
-
type: '
|
|
294
|
+
type: 'web',
|
|
295
295
|
path: 'apps/web',
|
|
296
296
|
port: 3000,
|
|
297
297
|
dependencies: [],
|
|
@@ -406,7 +406,7 @@ describe('getAppGkmConfig', () => {
|
|
|
406
406
|
const config: WorkspaceConfig = {
|
|
407
407
|
apps: {
|
|
408
408
|
web: {
|
|
409
|
-
type: '
|
|
409
|
+
type: 'web',
|
|
410
410
|
path: 'apps/web',
|
|
411
411
|
port: 3001,
|
|
412
412
|
framework: 'nextjs',
|
|
@@ -444,7 +444,7 @@ describe('getAppBuildOrder', () => {
|
|
|
444
444
|
const config: WorkspaceConfig = {
|
|
445
445
|
apps: {
|
|
446
446
|
web: {
|
|
447
|
-
type: '
|
|
447
|
+
type: 'web',
|
|
448
448
|
path: 'apps/web',
|
|
449
449
|
port: 3001,
|
|
450
450
|
framework: 'nextjs',
|
|
@@ -509,7 +509,7 @@ describe('getDependencyEnvVars', () => {
|
|
|
509
509
|
const config: WorkspaceConfig = {
|
|
510
510
|
apps: {
|
|
511
511
|
web: {
|
|
512
|
-
type: '
|
|
512
|
+
type: 'web',
|
|
513
513
|
path: 'apps/web',
|
|
514
514
|
port: 3001,
|
|
515
515
|
framework: 'nextjs',
|
|
@@ -545,7 +545,7 @@ describe('getDependencyEnvVars', () => {
|
|
|
545
545
|
const config: WorkspaceConfig = {
|
|
546
546
|
apps: {
|
|
547
547
|
web: {
|
|
548
|
-
type: '
|
|
548
|
+
type: 'web',
|
|
549
549
|
path: 'apps/web',
|
|
550
550
|
port: 3001,
|
|
551
551
|
framework: 'nextjs',
|
|
@@ -47,7 +47,7 @@ describe('WorkspaceConfigSchema', () => {
|
|
|
47
47
|
openapi: { enabled: true, title: 'My API' },
|
|
48
48
|
},
|
|
49
49
|
web: {
|
|
50
|
-
type: '
|
|
50
|
+
type: 'web' as const,
|
|
51
51
|
path: 'apps/web',
|
|
52
52
|
port: 3001,
|
|
53
53
|
framework: 'nextjs' as const,
|
|
@@ -82,7 +82,7 @@ describe('WorkspaceConfigSchema', () => {
|
|
|
82
82
|
|
|
83
83
|
expect(result.name).toBe('my-saas');
|
|
84
84
|
expect(result.apps.api.type).toBe('backend');
|
|
85
|
-
expect(result.apps.web.type).toBe('
|
|
85
|
+
expect(result.apps.web.type).toBe('web');
|
|
86
86
|
expect(result.apps.web.dependencies).toEqual(['api']);
|
|
87
87
|
expect(result.shared?.packages).toEqual(['packages/*']);
|
|
88
88
|
expect(result.deploy?.default).toBe('dokploy');
|
|
@@ -163,7 +163,7 @@ describe('WorkspaceConfigSchema', () => {
|
|
|
163
163
|
const config = {
|
|
164
164
|
apps: {
|
|
165
165
|
web: {
|
|
166
|
-
type: '
|
|
166
|
+
type: 'web' as const,
|
|
167
167
|
path: 'apps/web',
|
|
168
168
|
port: 3001,
|
|
169
169
|
// Missing framework
|
|
@@ -197,7 +197,7 @@ describe('WorkspaceConfigSchema', () => {
|
|
|
197
197
|
const config = {
|
|
198
198
|
apps: {
|
|
199
199
|
web: {
|
|
200
|
-
type: '
|
|
200
|
+
type: 'web' as const,
|
|
201
201
|
path: 'apps/web',
|
|
202
202
|
port: 3001,
|
|
203
203
|
framework: 'nextjs' as const,
|
|
@@ -479,53 +479,50 @@ describe('WorkspaceConfigSchema', () => {
|
|
|
479
479
|
});
|
|
480
480
|
|
|
481
481
|
describe('auth app configuration', () => {
|
|
482
|
-
it('should accept auth app with
|
|
482
|
+
it('should accept auth app as backend with better-auth framework', () => {
|
|
483
483
|
const config = {
|
|
484
484
|
apps: {
|
|
485
485
|
auth: {
|
|
486
|
-
type: '
|
|
486
|
+
type: 'backend' as const,
|
|
487
487
|
path: 'apps/auth',
|
|
488
488
|
port: 3002,
|
|
489
|
-
|
|
489
|
+
framework: 'better-auth' as const,
|
|
490
490
|
},
|
|
491
491
|
},
|
|
492
492
|
};
|
|
493
493
|
|
|
494
494
|
const result = validateWorkspaceConfig(config);
|
|
495
495
|
|
|
496
|
-
expect(result.apps.auth.type).toBe('
|
|
497
|
-
expect(result.apps.auth.
|
|
496
|
+
expect(result.apps.auth.type).toBe('backend');
|
|
497
|
+
expect(result.apps.auth.framework).toBe('better-auth');
|
|
498
498
|
});
|
|
499
499
|
|
|
500
|
-
it('should
|
|
500
|
+
it('should accept auth backend without explicit framework', () => {
|
|
501
|
+
// Backend type defaults are permissive — framework is optional.
|
|
501
502
|
const config = {
|
|
502
503
|
apps: {
|
|
503
504
|
auth: {
|
|
504
|
-
type: '
|
|
505
|
+
type: 'backend' as const,
|
|
505
506
|
path: 'apps/auth',
|
|
506
507
|
port: 3002,
|
|
507
|
-
// Missing provider
|
|
508
508
|
},
|
|
509
509
|
},
|
|
510
510
|
};
|
|
511
511
|
|
|
512
|
-
const result =
|
|
512
|
+
const result = validateWorkspaceConfig(config);
|
|
513
513
|
|
|
514
|
-
expect(result.
|
|
515
|
-
|
|
516
|
-
const formatted = formatValidationErrors(result.error);
|
|
517
|
-
expect(formatted).toContain('Auth apps must have provider defined');
|
|
518
|
-
}
|
|
514
|
+
expect(result.apps.auth.type).toBe('backend');
|
|
515
|
+
expect(result.apps.auth.framework).toBeUndefined();
|
|
519
516
|
});
|
|
520
517
|
|
|
521
|
-
it('should allow auth
|
|
518
|
+
it('should allow auth backend with additional backend properties', () => {
|
|
522
519
|
const config = {
|
|
523
520
|
apps: {
|
|
524
521
|
auth: {
|
|
525
|
-
type: '
|
|
522
|
+
type: 'backend' as const,
|
|
526
523
|
path: 'apps/auth',
|
|
527
524
|
port: 3002,
|
|
528
|
-
|
|
525
|
+
framework: 'better-auth' as const,
|
|
529
526
|
envParser: './src/config/env',
|
|
530
527
|
logger: './src/logger',
|
|
531
528
|
telescope: true,
|
|
@@ -535,12 +532,12 @@ describe('WorkspaceConfigSchema', () => {
|
|
|
535
532
|
|
|
536
533
|
const result = validateWorkspaceConfig(config);
|
|
537
534
|
|
|
538
|
-
expect(result.apps.auth.
|
|
535
|
+
expect(result.apps.auth.framework).toBe('better-auth');
|
|
539
536
|
expect(result.apps.auth.envParser).toBe('./src/config/env');
|
|
540
537
|
expect(result.apps.auth.telescope).toBe(true);
|
|
541
538
|
});
|
|
542
539
|
|
|
543
|
-
it('should validate fullstack workspace with auth
|
|
540
|
+
it('should validate fullstack workspace with auth backend', () => {
|
|
544
541
|
const config = {
|
|
545
542
|
name: 'fullstack-app',
|
|
546
543
|
apps: {
|
|
@@ -552,13 +549,13 @@ describe('WorkspaceConfigSchema', () => {
|
|
|
552
549
|
dependencies: ['auth'],
|
|
553
550
|
},
|
|
554
551
|
auth: {
|
|
555
|
-
type: '
|
|
552
|
+
type: 'backend' as const,
|
|
556
553
|
path: 'apps/auth',
|
|
557
554
|
port: 3002,
|
|
558
|
-
|
|
555
|
+
framework: 'better-auth' as const,
|
|
559
556
|
},
|
|
560
557
|
web: {
|
|
561
|
-
type: '
|
|
558
|
+
type: 'web' as const,
|
|
562
559
|
path: 'apps/web',
|
|
563
560
|
port: 3001,
|
|
564
561
|
framework: 'nextjs' as const,
|
|
@@ -570,18 +567,18 @@ describe('WorkspaceConfigSchema', () => {
|
|
|
570
567
|
const result = validateWorkspaceConfig(config);
|
|
571
568
|
|
|
572
569
|
expect(result.apps.api.dependencies).toEqual(['auth']);
|
|
573
|
-
expect(result.apps.auth.
|
|
570
|
+
expect(result.apps.auth.framework).toBe('better-auth');
|
|
574
571
|
expect(result.apps.web.dependencies).toEqual(['api', 'auth']);
|
|
575
572
|
});
|
|
576
573
|
|
|
577
|
-
it('should reject invalid
|
|
574
|
+
it('should reject auth backend with invalid framework value', () => {
|
|
578
575
|
const config = {
|
|
579
576
|
apps: {
|
|
580
577
|
auth: {
|
|
581
|
-
type: '
|
|
578
|
+
type: 'backend' as const,
|
|
582
579
|
path: 'apps/auth',
|
|
583
580
|
port: 3002,
|
|
584
|
-
|
|
581
|
+
framework: 'invalid-framework',
|
|
585
582
|
},
|
|
586
583
|
},
|
|
587
584
|
};
|
|
@@ -14,7 +14,7 @@ describe('Type Inference', () => {
|
|
|
14
14
|
routes: './src/**/*.ts',
|
|
15
15
|
},
|
|
16
16
|
web: {
|
|
17
|
-
type: '
|
|
17
|
+
type: 'web',
|
|
18
18
|
path: 'apps/web',
|
|
19
19
|
port: 3001,
|
|
20
20
|
framework: 'nextjs',
|
|
@@ -46,7 +46,7 @@ describe('Type Inference', () => {
|
|
|
46
46
|
routes: './src/**/*.ts',
|
|
47
47
|
},
|
|
48
48
|
web: {
|
|
49
|
-
type: '
|
|
49
|
+
type: 'web',
|
|
50
50
|
path: 'apps/web',
|
|
51
51
|
port: 3002,
|
|
52
52
|
framework: 'nextjs',
|
|
@@ -69,7 +69,7 @@ describe('Type Inference', () => {
|
|
|
69
69
|
routes: './src/**/*.ts',
|
|
70
70
|
},
|
|
71
71
|
web: {
|
|
72
|
-
type: '
|
|
72
|
+
type: 'web',
|
|
73
73
|
path: 'apps/web',
|
|
74
74
|
port: 3001,
|
|
75
75
|
framework: 'nextjs',
|
|
@@ -186,14 +186,14 @@ describe('Type Inference', () => {
|
|
|
186
186
|
dependencies: ['user-service'],
|
|
187
187
|
},
|
|
188
188
|
'web-app': {
|
|
189
|
-
type: '
|
|
189
|
+
type: 'web',
|
|
190
190
|
path: 'apps/web',
|
|
191
191
|
port: 3003,
|
|
192
192
|
framework: 'nextjs',
|
|
193
193
|
dependencies: ['api-gateway'],
|
|
194
194
|
},
|
|
195
195
|
'admin-dashboard': {
|
|
196
|
-
type: '
|
|
196
|
+
type: 'web',
|
|
197
197
|
path: 'apps/admin',
|
|
198
198
|
port: 3004,
|
|
199
199
|
framework: 'nextjs',
|
|
@@ -55,25 +55,25 @@ export function shouldRegenerateClient(
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
|
-
* Get backend apps that a
|
|
58
|
+
* Get backend apps that a web/mobile client depends on.
|
|
59
59
|
*/
|
|
60
60
|
export function getBackendDependencies(
|
|
61
61
|
workspace: NormalizedWorkspace,
|
|
62
|
-
|
|
62
|
+
clientAppName: string,
|
|
63
63
|
): string[] {
|
|
64
|
-
const
|
|
65
|
-
if (!
|
|
64
|
+
const clientApp = workspace.apps[clientAppName];
|
|
65
|
+
if (!clientApp || (clientApp.type !== 'web' && clientApp.type !== 'mobile')) {
|
|
66
66
|
return [];
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
return
|
|
69
|
+
return clientApp.dependencies.filter((dep) => {
|
|
70
70
|
const depApp = workspace.apps[dep];
|
|
71
71
|
return depApp?.type === 'backend' && depApp.routes;
|
|
72
72
|
});
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
|
-
* Get
|
|
76
|
+
* Get web/mobile apps that depend on a backend app.
|
|
77
77
|
*/
|
|
78
78
|
export function getDependentFrontends(
|
|
79
79
|
workspace: NormalizedWorkspace,
|
|
@@ -82,7 +82,10 @@ export function getDependentFrontends(
|
|
|
82
82
|
const dependentApps: string[] = [];
|
|
83
83
|
|
|
84
84
|
for (const [appName, app] of Object.entries(workspace.apps)) {
|
|
85
|
-
if (
|
|
85
|
+
if (
|
|
86
|
+
(app.type === 'web' || app.type === 'mobile') &&
|
|
87
|
+
app.dependencies.includes(backendAppName)
|
|
88
|
+
) {
|
|
86
89
|
dependentApps.push(appName);
|
|
87
90
|
}
|
|
88
91
|
}
|
package/src/workspace/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Framework } from './types.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* All public env-var prefixes the toolbox understands.
|
|
@@ -27,9 +27,7 @@ export const PUBLIC_ENV_PREFIXES = [
|
|
|
27
27
|
* preserve the historical default. Backend apps never read these vars
|
|
28
28
|
* from a bundle, so the prefix only affects scaffolding/symmetry.
|
|
29
29
|
*/
|
|
30
|
-
export function getPublicEnvPrefix(
|
|
31
|
-
framework?: FrontendFramework | BackendFramework,
|
|
32
|
-
): string {
|
|
30
|
+
export function getPublicEnvPrefix(framework?: Framework): string {
|
|
33
31
|
switch (framework) {
|
|
34
32
|
case 'vite':
|
|
35
33
|
case 'tanstack-start':
|