@geekmidas/cli 0.18.0 → 0.20.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/dist/{bundler-C74EKlNa.cjs → bundler-CyHg1v_T.cjs} +3 -3
- package/dist/{bundler-C74EKlNa.cjs.map → bundler-CyHg1v_T.cjs.map} +1 -1
- package/dist/{bundler-B6z6HEeh.mjs → bundler-DQIuE3Kn.mjs} +3 -3
- package/dist/{bundler-B6z6HEeh.mjs.map → bundler-DQIuE3Kn.mjs.map} +1 -1
- package/dist/{config-DYULeEv8.mjs → config-BaYqrF3n.mjs} +48 -10
- package/dist/config-BaYqrF3n.mjs.map +1 -0
- package/dist/{config-AmInkU7k.cjs → config-CxrLu8ia.cjs} +53 -9
- package/dist/config-CxrLu8ia.cjs.map +1 -0
- package/dist/config.cjs +4 -1
- package/dist/config.d.cts +27 -2
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +27 -2
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +3 -2
- package/dist/dokploy-api-B0w17y4_.mjs +3 -0
- package/dist/{dokploy-api-CaETb2L6.mjs → dokploy-api-B9qR2Yn1.mjs} +1 -1
- package/dist/{dokploy-api-CaETb2L6.mjs.map → dokploy-api-B9qR2Yn1.mjs.map} +1 -1
- package/dist/dokploy-api-BnGeUqN4.cjs +3 -0
- package/dist/{dokploy-api-C7F9VykY.cjs → dokploy-api-C5czOZoc.cjs} +1 -1
- package/dist/{dokploy-api-C7F9VykY.cjs.map → dokploy-api-C5czOZoc.cjs.map} +1 -1
- package/dist/{encryption-D7Efcdi9.cjs → encryption-BAz0xQ1Q.cjs} +1 -1
- package/dist/{encryption-D7Efcdi9.cjs.map → encryption-BAz0xQ1Q.cjs.map} +1 -1
- package/dist/{encryption-h4Nb6W-M.mjs → encryption-JtMsiGNp.mjs} +2 -2
- package/dist/{encryption-h4Nb6W-M.mjs.map → encryption-JtMsiGNp.mjs.map} +1 -1
- package/dist/index-CWN-bgrO.d.mts +495 -0
- package/dist/index-CWN-bgrO.d.mts.map +1 -0
- package/dist/index-DEWYvYvg.d.cts +495 -0
- package/dist/index-DEWYvYvg.d.cts.map +1 -0
- package/dist/index.cjs +2640 -564
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2635 -564
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-CZVcfxk-.mjs → openapi-CgqR6Jkw.mjs} +3 -3
- package/dist/{openapi-CZVcfxk-.mjs.map → openapi-CgqR6Jkw.mjs.map} +1 -1
- package/dist/{openapi-C89hhkZC.cjs → openapi-DfpxS0xv.cjs} +8 -2
- package/dist/{openapi-C89hhkZC.cjs.map → openapi-DfpxS0xv.cjs.map} +1 -1
- package/dist/{openapi-react-query-CM2_qlW9.mjs → openapi-react-query-5rSortLH.mjs} +1 -1
- package/dist/{openapi-react-query-CM2_qlW9.mjs.map → openapi-react-query-5rSortLH.mjs.map} +1 -1
- package/dist/{openapi-react-query-iKjfLzff.cjs → openapi-react-query-DvNpdDpM.cjs} +1 -1
- package/dist/{openapi-react-query-iKjfLzff.cjs.map → openapi-react-query-DvNpdDpM.cjs.map} +1 -1
- package/dist/openapi-react-query.cjs +1 -1
- package/dist/openapi-react-query.mjs +1 -1
- package/dist/openapi.cjs +3 -2
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +3 -2
- package/dist/{storage-Bn3K9Ccu.cjs → storage-BPRgh3DU.cjs} +136 -5
- package/dist/storage-BPRgh3DU.cjs.map +1 -0
- package/dist/{storage-nkGIjeXt.mjs → storage-DNj_I11J.mjs} +1 -1
- package/dist/storage-Dhst7BhI.mjs +272 -0
- package/dist/storage-Dhst7BhI.mjs.map +1 -0
- package/dist/{storage-UfyTn7Zm.cjs → storage-fOR8dMu5.cjs} +1 -1
- package/dist/{types-iFk5ms7y.d.mts → types-K2uQJ-FO.d.mts} +2 -2
- package/dist/{types-BgaMXsUa.d.cts.map → types-K2uQJ-FO.d.mts.map} +1 -1
- package/dist/{types-BgaMXsUa.d.cts → types-l53qUmGt.d.cts} +2 -2
- package/dist/{types-iFk5ms7y.d.mts.map → types-l53qUmGt.d.cts.map} +1 -1
- package/dist/workspace/index.cjs +19 -0
- package/dist/workspace/index.d.cts +3 -0
- package/dist/workspace/index.d.mts +3 -0
- package/dist/workspace/index.mjs +3 -0
- package/dist/workspace-CPLEZDZf.mjs +3788 -0
- package/dist/workspace-CPLEZDZf.mjs.map +1 -0
- package/dist/workspace-iWgBlX6h.cjs +3885 -0
- package/dist/workspace-iWgBlX6h.cjs.map +1 -0
- package/package.json +9 -4
- package/src/build/__tests__/workspace-build.spec.ts +215 -0
- package/src/build/index.ts +189 -1
- package/src/config.ts +71 -14
- package/src/deploy/__tests__/docker.spec.ts +1 -1
- package/src/deploy/__tests__/index.spec.ts +305 -1
- package/src/deploy/index.ts +426 -4
- package/src/deploy/types.ts +32 -0
- package/src/dev/__tests__/index.spec.ts +572 -1
- package/src/dev/index.ts +582 -2
- package/src/docker/__tests__/compose.spec.ts +425 -0
- package/src/docker/__tests__/templates.spec.ts +145 -0
- package/src/docker/compose.ts +248 -0
- package/src/docker/index.ts +159 -3
- package/src/docker/templates.ts +219 -4
- package/src/index.ts +24 -0
- package/src/init/__tests__/generators.spec.ts +17 -24
- package/src/init/__tests__/init.spec.ts +157 -5
- package/src/init/generators/auth.ts +220 -0
- package/src/init/generators/config.ts +61 -4
- package/src/init/generators/docker.ts +115 -8
- package/src/init/generators/env.ts +7 -127
- package/src/init/generators/index.ts +1 -0
- package/src/init/generators/models.ts +3 -1
- package/src/init/generators/monorepo.ts +154 -10
- package/src/init/generators/package.ts +5 -3
- package/src/init/generators/web.ts +213 -0
- package/src/init/index.ts +290 -58
- package/src/init/templates/api.ts +38 -29
- package/src/init/templates/index.ts +132 -4
- package/src/init/templates/minimal.ts +33 -35
- package/src/init/templates/serverless.ts +16 -19
- package/src/init/templates/worker.ts +50 -25
- package/src/init/versions.ts +47 -0
- package/src/secrets/keystore.ts +144 -0
- package/src/secrets/storage.ts +109 -6
- package/src/test/index.ts +97 -0
- package/src/workspace/__tests__/client-generator.spec.ts +357 -0
- package/src/workspace/__tests__/index.spec.ts +543 -0
- package/src/workspace/__tests__/schema.spec.ts +519 -0
- package/src/workspace/__tests__/type-inference.spec.ts +251 -0
- package/src/workspace/client-generator.ts +307 -0
- package/src/workspace/index.ts +372 -0
- package/src/workspace/schema.ts +368 -0
- package/src/workspace/types.ts +336 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/tsdown.config.ts +1 -0
- package/dist/config-AmInkU7k.cjs.map +0 -1
- package/dist/config-DYULeEv8.mjs.map +0 -1
- package/dist/dokploy-api-B7KxOQr3.cjs +0 -3
- package/dist/dokploy-api-DHvfmWbi.mjs +0 -3
- package/dist/storage-BaOP55oq.mjs +0 -147
- package/dist/storage-BaOP55oq.mjs.map +0 -1
- package/dist/storage-Bn3K9Ccu.cjs.map +0 -1
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import type { GkmConfig } from '../../types.ts';
|
|
3
|
+
import {
|
|
4
|
+
defineWorkspace,
|
|
5
|
+
getAppBuildOrder,
|
|
6
|
+
getAppGkmConfig,
|
|
7
|
+
getDependencyEnvVars,
|
|
8
|
+
isWorkspaceConfig,
|
|
9
|
+
normalizeWorkspace,
|
|
10
|
+
processConfig,
|
|
11
|
+
wrapSingleAppAsWorkspace,
|
|
12
|
+
} from '../index.ts';
|
|
13
|
+
import type { WorkspaceConfig } from '../types.ts';
|
|
14
|
+
|
|
15
|
+
describe('defineWorkspace', () => {
|
|
16
|
+
it('should return valid workspace config unchanged', () => {
|
|
17
|
+
const config: WorkspaceConfig = {
|
|
18
|
+
name: 'my-saas',
|
|
19
|
+
apps: {
|
|
20
|
+
api: {
|
|
21
|
+
type: 'backend',
|
|
22
|
+
path: 'apps/api',
|
|
23
|
+
port: 3000,
|
|
24
|
+
routes: './src/endpoints/**/*.ts',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const result = defineWorkspace(config);
|
|
30
|
+
|
|
31
|
+
expect(result).toEqual(config);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should throw on invalid config', () => {
|
|
35
|
+
const config = {
|
|
36
|
+
apps: {},
|
|
37
|
+
} as WorkspaceConfig;
|
|
38
|
+
|
|
39
|
+
expect(() => defineWorkspace(config)).toThrow(
|
|
40
|
+
'Workspace configuration validation failed',
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should throw with descriptive error for missing routes', () => {
|
|
45
|
+
const config = {
|
|
46
|
+
apps: {
|
|
47
|
+
api: {
|
|
48
|
+
type: 'backend',
|
|
49
|
+
path: 'apps/api',
|
|
50
|
+
port: 3000,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
} as WorkspaceConfig;
|
|
54
|
+
|
|
55
|
+
expect(() => defineWorkspace(config)).toThrow(
|
|
56
|
+
'Backend apps must have routes defined',
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('isWorkspaceConfig', () => {
|
|
62
|
+
it('should return true for workspace config', () => {
|
|
63
|
+
const config: WorkspaceConfig = {
|
|
64
|
+
apps: {
|
|
65
|
+
api: {
|
|
66
|
+
type: 'backend',
|
|
67
|
+
path: 'apps/api',
|
|
68
|
+
port: 3000,
|
|
69
|
+
routes: './src/**/*.ts',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
expect(isWorkspaceConfig(config)).toBe(true);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should return false for single-app GkmConfig', () => {
|
|
78
|
+
const config: GkmConfig = {
|
|
79
|
+
routes: './src/endpoints/**/*.ts',
|
|
80
|
+
envParser: './src/config/env',
|
|
81
|
+
logger: './src/logger',
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
expect(isWorkspaceConfig(config)).toBe(false);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should return false for null', () => {
|
|
88
|
+
expect(isWorkspaceConfig(null as unknown as GkmConfig)).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('normalizeWorkspace', () => {
|
|
93
|
+
it('should normalize workspace with defaults', () => {
|
|
94
|
+
const config: WorkspaceConfig = {
|
|
95
|
+
apps: {
|
|
96
|
+
api: {
|
|
97
|
+
type: 'backend',
|
|
98
|
+
path: 'apps/api',
|
|
99
|
+
port: 3000,
|
|
100
|
+
routes: './src/**/*.ts',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const result = normalizeWorkspace(config, '/project');
|
|
106
|
+
|
|
107
|
+
expect(result.root).toBe('/project');
|
|
108
|
+
expect(result.apps.api.type).toBe('backend');
|
|
109
|
+
expect(result.apps.api.dependencies).toEqual([]);
|
|
110
|
+
expect(result.services).toEqual({});
|
|
111
|
+
expect(result.deploy).toEqual({ default: 'dokploy' });
|
|
112
|
+
expect(result.shared).toEqual({ packages: ['packages/*'] });
|
|
113
|
+
expect(result.secrets).toEqual({});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should use provided name', () => {
|
|
117
|
+
const config: WorkspaceConfig = {
|
|
118
|
+
name: 'custom-name',
|
|
119
|
+
apps: {
|
|
120
|
+
api: {
|
|
121
|
+
type: 'backend',
|
|
122
|
+
path: 'apps/api',
|
|
123
|
+
port: 3000,
|
|
124
|
+
routes: './src/**/*.ts',
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const result = normalizeWorkspace(config, '/project');
|
|
130
|
+
|
|
131
|
+
expect(result.name).toBe('custom-name');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should preserve all app properties', () => {
|
|
135
|
+
const config: WorkspaceConfig = {
|
|
136
|
+
apps: {
|
|
137
|
+
api: {
|
|
138
|
+
type: 'backend',
|
|
139
|
+
path: 'apps/api',
|
|
140
|
+
port: 3000,
|
|
141
|
+
routes: './src/**/*.ts',
|
|
142
|
+
envParser: './src/env',
|
|
143
|
+
logger: './src/logger',
|
|
144
|
+
telescope: { enabled: true },
|
|
145
|
+
openapi: { enabled: true },
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const result = normalizeWorkspace(config, '/project');
|
|
151
|
+
|
|
152
|
+
expect(result.apps.api.envParser).toBe('./src/env');
|
|
153
|
+
expect(result.apps.api.logger).toBe('./src/logger');
|
|
154
|
+
expect(result.apps.api.telescope).toEqual({ enabled: true });
|
|
155
|
+
expect(result.apps.api.openapi).toEqual({ enabled: true });
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should resolve deploy target to dokploy by default', () => {
|
|
159
|
+
const config: WorkspaceConfig = {
|
|
160
|
+
apps: {
|
|
161
|
+
api: {
|
|
162
|
+
type: 'backend',
|
|
163
|
+
path: 'apps/api',
|
|
164
|
+
port: 3000,
|
|
165
|
+
routes: './src/**/*.ts',
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const result = normalizeWorkspace(config, '/project');
|
|
171
|
+
|
|
172
|
+
expect(result.apps.api.resolvedDeployTarget).toBe('dokploy');
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('should use deploy.default as fallback for resolvedDeployTarget', () => {
|
|
176
|
+
const config: WorkspaceConfig = {
|
|
177
|
+
apps: {
|
|
178
|
+
api: {
|
|
179
|
+
type: 'backend',
|
|
180
|
+
path: 'apps/api',
|
|
181
|
+
port: 3000,
|
|
182
|
+
routes: './src/**/*.ts',
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
deploy: {
|
|
186
|
+
default: 'dokploy',
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const result = normalizeWorkspace(config, '/project');
|
|
191
|
+
|
|
192
|
+
expect(result.apps.api.resolvedDeployTarget).toBe('dokploy');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('should use per-app deploy target when specified', () => {
|
|
196
|
+
const config: WorkspaceConfig = {
|
|
197
|
+
apps: {
|
|
198
|
+
api: {
|
|
199
|
+
type: 'backend',
|
|
200
|
+
path: 'apps/api',
|
|
201
|
+
port: 3000,
|
|
202
|
+
routes: './src/**/*.ts',
|
|
203
|
+
deploy: 'dokploy',
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
deploy: {
|
|
207
|
+
default: 'dokploy',
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const result = normalizeWorkspace(config, '/project');
|
|
212
|
+
|
|
213
|
+
expect(result.apps.api.resolvedDeployTarget).toBe('dokploy');
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe('wrapSingleAppAsWorkspace', () => {
|
|
218
|
+
it('should wrap single-app config as workspace', () => {
|
|
219
|
+
const config: GkmConfig = {
|
|
220
|
+
routes: './src/endpoints/**/*.ts',
|
|
221
|
+
envParser: './src/config/env',
|
|
222
|
+
logger: './src/logger',
|
|
223
|
+
telescope: true,
|
|
224
|
+
openapi: { enabled: true },
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const result = wrapSingleAppAsWorkspace(config, '/project/myapp');
|
|
228
|
+
|
|
229
|
+
expect(result.name).toBe('myapp');
|
|
230
|
+
expect(result.root).toBe('/project/myapp');
|
|
231
|
+
expect(result.apps.api).toBeDefined();
|
|
232
|
+
expect(result.apps.api.type).toBe('backend');
|
|
233
|
+
expect(result.apps.api.path).toBe('.');
|
|
234
|
+
expect(result.apps.api.port).toBe(3000);
|
|
235
|
+
expect(result.apps.api.routes).toBe('./src/endpoints/**/*.ts');
|
|
236
|
+
expect(result.apps.api.envParser).toBe('./src/config/env');
|
|
237
|
+
expect(result.apps.api.logger).toBe('./src/logger');
|
|
238
|
+
expect(result.apps.api.telescope).toBe(true);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('should extract docker compose services', () => {
|
|
242
|
+
const config: GkmConfig = {
|
|
243
|
+
routes: './src/**/*.ts',
|
|
244
|
+
envParser: './src/env',
|
|
245
|
+
logger: './src/logger',
|
|
246
|
+
docker: {
|
|
247
|
+
compose: {
|
|
248
|
+
services: ['postgres', 'redis'],
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
const result = wrapSingleAppAsWorkspace(config, '/project');
|
|
254
|
+
|
|
255
|
+
expect(result.services.db).toBe(true);
|
|
256
|
+
expect(result.services.cache).toBe(true);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should set resolvedDeployTarget to dokploy', () => {
|
|
260
|
+
const config: GkmConfig = {
|
|
261
|
+
routes: './src/**/*.ts',
|
|
262
|
+
envParser: './src/env',
|
|
263
|
+
logger: './src/logger',
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const result = wrapSingleAppAsWorkspace(config, '/project');
|
|
267
|
+
|
|
268
|
+
expect(result.apps.api.resolvedDeployTarget).toBe('dokploy');
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
describe('processConfig', () => {
|
|
273
|
+
it('should process workspace config', () => {
|
|
274
|
+
const config: WorkspaceConfig = {
|
|
275
|
+
name: 'test-workspace',
|
|
276
|
+
apps: {
|
|
277
|
+
api: {
|
|
278
|
+
type: 'backend',
|
|
279
|
+
path: 'apps/api',
|
|
280
|
+
port: 3000,
|
|
281
|
+
routes: './src/**/*.ts',
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const result = processConfig(config, '/project');
|
|
287
|
+
|
|
288
|
+
expect(result.type).toBe('workspace');
|
|
289
|
+
expect(result.raw).toBe(config);
|
|
290
|
+
expect(result.workspace.name).toBe('test-workspace');
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it('should process single-app config', () => {
|
|
294
|
+
const config: GkmConfig = {
|
|
295
|
+
routes: './src/**/*.ts',
|
|
296
|
+
envParser: './src/env',
|
|
297
|
+
logger: './src/logger',
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const result = processConfig(config, '/project/myapp');
|
|
301
|
+
|
|
302
|
+
expect(result.type).toBe('single');
|
|
303
|
+
expect(result.raw).toBe(config);
|
|
304
|
+
expect(result.workspace.apps.api).toBeDefined();
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('should throw on invalid workspace config', () => {
|
|
308
|
+
const config: WorkspaceConfig = {
|
|
309
|
+
apps: {},
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
expect(() => processConfig(config, '/project')).toThrow(
|
|
313
|
+
'Workspace configuration validation failed',
|
|
314
|
+
);
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
describe('getAppGkmConfig', () => {
|
|
319
|
+
it('should return GkmConfig for backend app', () => {
|
|
320
|
+
const config: WorkspaceConfig = {
|
|
321
|
+
apps: {
|
|
322
|
+
api: {
|
|
323
|
+
type: 'backend',
|
|
324
|
+
path: 'apps/api',
|
|
325
|
+
port: 3000,
|
|
326
|
+
routes: './src/**/*.ts',
|
|
327
|
+
envParser: './src/env',
|
|
328
|
+
logger: './src/logger',
|
|
329
|
+
telescope: true,
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
const workspace = normalizeWorkspace(config, '/project');
|
|
335
|
+
const gkmConfig = getAppGkmConfig(workspace, 'api');
|
|
336
|
+
|
|
337
|
+
expect(gkmConfig).toBeDefined();
|
|
338
|
+
expect(gkmConfig?.routes).toBe('./src/**/*.ts');
|
|
339
|
+
expect(gkmConfig?.envParser).toBe('./src/env');
|
|
340
|
+
expect(gkmConfig?.logger).toBe('./src/logger');
|
|
341
|
+
expect(gkmConfig?.telescope).toBe(true);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
it('should return undefined for frontend app', () => {
|
|
345
|
+
const config: WorkspaceConfig = {
|
|
346
|
+
apps: {
|
|
347
|
+
web: {
|
|
348
|
+
type: 'frontend',
|
|
349
|
+
path: 'apps/web',
|
|
350
|
+
port: 3001,
|
|
351
|
+
framework: 'nextjs',
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
const workspace = normalizeWorkspace(config, '/project');
|
|
357
|
+
const gkmConfig = getAppGkmConfig(workspace, 'web');
|
|
358
|
+
|
|
359
|
+
expect(gkmConfig).toBeUndefined();
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
it('should return undefined for non-existent app', () => {
|
|
363
|
+
const config: WorkspaceConfig = {
|
|
364
|
+
apps: {
|
|
365
|
+
api: {
|
|
366
|
+
type: 'backend',
|
|
367
|
+
path: 'apps/api',
|
|
368
|
+
port: 3000,
|
|
369
|
+
routes: './src/**/*.ts',
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
const workspace = normalizeWorkspace(config, '/project');
|
|
375
|
+
const gkmConfig = getAppGkmConfig(workspace, 'nonexistent');
|
|
376
|
+
|
|
377
|
+
expect(gkmConfig).toBeUndefined();
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
describe('getAppBuildOrder', () => {
|
|
382
|
+
it('should return apps in dependency order', () => {
|
|
383
|
+
const config: WorkspaceConfig = {
|
|
384
|
+
apps: {
|
|
385
|
+
web: {
|
|
386
|
+
type: 'frontend',
|
|
387
|
+
path: 'apps/web',
|
|
388
|
+
port: 3001,
|
|
389
|
+
framework: 'nextjs',
|
|
390
|
+
dependencies: ['api'],
|
|
391
|
+
},
|
|
392
|
+
api: {
|
|
393
|
+
type: 'backend',
|
|
394
|
+
path: 'apps/api',
|
|
395
|
+
port: 3000,
|
|
396
|
+
routes: './src/**/*.ts',
|
|
397
|
+
dependencies: ['worker'],
|
|
398
|
+
},
|
|
399
|
+
worker: {
|
|
400
|
+
type: 'backend',
|
|
401
|
+
path: 'apps/worker',
|
|
402
|
+
port: 3002,
|
|
403
|
+
routes: './src/**/*.ts',
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
const workspace = normalizeWorkspace(config, '/project');
|
|
409
|
+
const order = getAppBuildOrder(workspace);
|
|
410
|
+
|
|
411
|
+
const workerIndex = order.indexOf('worker');
|
|
412
|
+
const apiIndex = order.indexOf('api');
|
|
413
|
+
const webIndex = order.indexOf('web');
|
|
414
|
+
|
|
415
|
+
expect(workerIndex).toBeLessThan(apiIndex);
|
|
416
|
+
expect(apiIndex).toBeLessThan(webIndex);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it('should handle apps without dependencies', () => {
|
|
420
|
+
const config: WorkspaceConfig = {
|
|
421
|
+
apps: {
|
|
422
|
+
api: {
|
|
423
|
+
type: 'backend',
|
|
424
|
+
path: 'apps/api',
|
|
425
|
+
port: 3000,
|
|
426
|
+
routes: './src/**/*.ts',
|
|
427
|
+
},
|
|
428
|
+
worker: {
|
|
429
|
+
type: 'backend',
|
|
430
|
+
path: 'apps/worker',
|
|
431
|
+
port: 3001,
|
|
432
|
+
routes: './src/**/*.ts',
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
const workspace = normalizeWorkspace(config, '/project');
|
|
438
|
+
const order = getAppBuildOrder(workspace);
|
|
439
|
+
|
|
440
|
+
expect(order).toHaveLength(2);
|
|
441
|
+
expect(order).toContain('api');
|
|
442
|
+
expect(order).toContain('worker');
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
describe('getDependencyEnvVars', () => {
|
|
447
|
+
it('should generate env vars for dependencies', () => {
|
|
448
|
+
const config: WorkspaceConfig = {
|
|
449
|
+
apps: {
|
|
450
|
+
web: {
|
|
451
|
+
type: 'frontend',
|
|
452
|
+
path: 'apps/web',
|
|
453
|
+
port: 3001,
|
|
454
|
+
framework: 'nextjs',
|
|
455
|
+
dependencies: ['api', 'auth'],
|
|
456
|
+
},
|
|
457
|
+
api: {
|
|
458
|
+
type: 'backend',
|
|
459
|
+
path: 'apps/api',
|
|
460
|
+
port: 3000,
|
|
461
|
+
routes: './src/**/*.ts',
|
|
462
|
+
},
|
|
463
|
+
auth: {
|
|
464
|
+
type: 'backend',
|
|
465
|
+
path: 'apps/auth',
|
|
466
|
+
port: 3002,
|
|
467
|
+
routes: './src/**/*.ts',
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
const workspace = normalizeWorkspace(config, '/project');
|
|
473
|
+
const envVars = getDependencyEnvVars(workspace, 'web');
|
|
474
|
+
|
|
475
|
+
expect(envVars).toEqual({
|
|
476
|
+
API_URL: 'http://localhost:3000',
|
|
477
|
+
AUTH_URL: 'http://localhost:3002',
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
it('should use custom URL prefix', () => {
|
|
482
|
+
const config: WorkspaceConfig = {
|
|
483
|
+
apps: {
|
|
484
|
+
web: {
|
|
485
|
+
type: 'frontend',
|
|
486
|
+
path: 'apps/web',
|
|
487
|
+
port: 3001,
|
|
488
|
+
framework: 'nextjs',
|
|
489
|
+
dependencies: ['api'],
|
|
490
|
+
},
|
|
491
|
+
api: {
|
|
492
|
+
type: 'backend',
|
|
493
|
+
path: 'apps/api',
|
|
494
|
+
port: 3000,
|
|
495
|
+
routes: './src/**/*.ts',
|
|
496
|
+
},
|
|
497
|
+
},
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
const workspace = normalizeWorkspace(config, '/project');
|
|
501
|
+
const envVars = getDependencyEnvVars(workspace, 'web', 'https://internal');
|
|
502
|
+
|
|
503
|
+
expect(envVars).toEqual({
|
|
504
|
+
API_URL: 'https://internal:3000',
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
it('should return empty object for app without dependencies', () => {
|
|
509
|
+
const config: WorkspaceConfig = {
|
|
510
|
+
apps: {
|
|
511
|
+
api: {
|
|
512
|
+
type: 'backend',
|
|
513
|
+
path: 'apps/api',
|
|
514
|
+
port: 3000,
|
|
515
|
+
routes: './src/**/*.ts',
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const workspace = normalizeWorkspace(config, '/project');
|
|
521
|
+
const envVars = getDependencyEnvVars(workspace, 'api');
|
|
522
|
+
|
|
523
|
+
expect(envVars).toEqual({});
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
it('should return empty object for non-existent app', () => {
|
|
527
|
+
const config: WorkspaceConfig = {
|
|
528
|
+
apps: {
|
|
529
|
+
api: {
|
|
530
|
+
type: 'backend',
|
|
531
|
+
path: 'apps/api',
|
|
532
|
+
port: 3000,
|
|
533
|
+
routes: './src/**/*.ts',
|
|
534
|
+
},
|
|
535
|
+
},
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
const workspace = normalizeWorkspace(config, '/project');
|
|
539
|
+
const envVars = getDependencyEnvVars(workspace, 'nonexistent');
|
|
540
|
+
|
|
541
|
+
expect(envVars).toEqual({});
|
|
542
|
+
});
|
|
543
|
+
});
|