@geekmidas/cli 0.13.0 → 0.14.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-B1qy9b-j.cjs → bundler-BjholBlA.cjs} +26 -7
- package/dist/bundler-BjholBlA.cjs.map +1 -0
- package/dist/{bundler-DskIqW2t.mjs → bundler-DWctKN1z.mjs} +27 -8
- package/dist/bundler-DWctKN1z.mjs.map +1 -0
- package/dist/config.d.cts +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/dokploy-api-B7KxOQr3.cjs +3 -0
- package/dist/dokploy-api-C7F9VykY.cjs +317 -0
- package/dist/dokploy-api-C7F9VykY.cjs.map +1 -0
- package/dist/dokploy-api-CaETb2L6.mjs +305 -0
- package/dist/dokploy-api-CaETb2L6.mjs.map +1 -0
- package/dist/dokploy-api-DHvfmWbi.mjs +3 -0
- package/dist/{encryption-Dyf_r1h-.cjs → encryption-D7Efcdi9.cjs} +1 -1
- package/dist/{encryption-Dyf_r1h-.cjs.map → encryption-D7Efcdi9.cjs.map} +1 -1
- package/dist/{encryption-C8H-38Yy.mjs → encryption-h4Nb6W-M.mjs} +1 -1
- package/dist/{encryption-C8H-38Yy.mjs.map → encryption-h4Nb6W-M.mjs.map} +1 -1
- package/dist/index.cjs +1513 -1136
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1513 -1136
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-Bt_1FDpT.cjs → openapi-C89hhkZC.cjs} +3 -3
- package/dist/{openapi-Bt_1FDpT.cjs.map → openapi-C89hhkZC.cjs.map} +1 -1
- package/dist/{openapi-BfFlOBCG.mjs → openapi-CZVcfxk-.mjs} +3 -3
- package/dist/{openapi-BfFlOBCG.mjs.map → openapi-CZVcfxk-.mjs.map} +1 -1
- package/dist/{openapi-react-query-B6XTeGqS.mjs → openapi-react-query-CM2_qlW9.mjs} +1 -1
- package/dist/{openapi-react-query-B6XTeGqS.mjs.map → openapi-react-query-CM2_qlW9.mjs.map} +1 -1
- package/dist/{openapi-react-query-B-sNWHFU.cjs → openapi-react-query-iKjfLzff.cjs} +1 -1
- package/dist/{openapi-react-query-B-sNWHFU.cjs.map → openapi-react-query-iKjfLzff.cjs.map} +1 -1
- package/dist/openapi-react-query.cjs +1 -1
- package/dist/openapi-react-query.mjs +1 -1
- package/dist/openapi.cjs +1 -1
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +1 -1
- package/dist/{storage-kSxTjkNb.mjs → storage-BaOP55oq.mjs} +16 -2
- package/dist/storage-BaOP55oq.mjs.map +1 -0
- package/dist/{storage-Bj1E26lU.cjs → storage-Bn3K9Ccu.cjs} +21 -1
- package/dist/storage-Bn3K9Ccu.cjs.map +1 -0
- package/dist/storage-UfyTn7Zm.cjs +7 -0
- package/dist/storage-nkGIjeXt.mjs +3 -0
- package/dist/{types-BhkZc-vm.d.cts → types-BgaMXsUa.d.cts} +3 -1
- package/dist/{types-BR0M2v_c.d.mts.map → types-BgaMXsUa.d.cts.map} +1 -1
- package/dist/{types-BR0M2v_c.d.mts → types-iFk5ms7y.d.mts} +3 -1
- package/dist/{types-BhkZc-vm.d.cts.map → types-iFk5ms7y.d.mts.map} +1 -1
- package/package.json +3 -3
- package/src/auth/__tests__/credentials.spec.ts +127 -0
- package/src/auth/__tests__/index.spec.ts +69 -0
- package/src/auth/credentials.ts +33 -0
- package/src/auth/index.ts +57 -50
- package/src/build/__tests__/bundler.spec.ts +1 -1
- package/src/build/__tests__/endpoint-analyzer.spec.ts +623 -0
- package/src/build/__tests__/handler-templates.spec.ts +272 -0
- package/src/build/bundler.ts +53 -4
- package/src/build/index.ts +21 -0
- package/src/build/types.ts +6 -0
- package/src/deploy/__tests__/dokploy-api.spec.ts +698 -0
- package/src/deploy/__tests__/dokploy.spec.ts +196 -6
- package/src/deploy/__tests__/index.spec.ts +339 -0
- package/src/deploy/__tests__/init.spec.ts +147 -16
- package/src/deploy/docker.ts +32 -3
- package/src/deploy/dokploy-api.ts +581 -0
- package/src/deploy/dokploy.ts +66 -93
- package/src/deploy/index.ts +587 -32
- package/src/deploy/init.ts +192 -249
- package/src/deploy/types.ts +19 -1
- package/src/dev/__tests__/index.spec.ts +95 -0
- package/src/docker/__tests__/templates.spec.ts +144 -0
- package/src/docker/index.ts +96 -6
- package/src/docker/templates.ts +114 -27
- package/src/generators/EndpointGenerator.ts +2 -2
- package/src/index.ts +34 -13
- package/src/secrets/storage.ts +15 -0
- package/src/types.ts +2 -0
- package/dist/bundler-B1qy9b-j.cjs.map +0 -1
- package/dist/bundler-DskIqW2t.mjs.map +0 -1
- package/dist/storage-BOOpAF8N.cjs +0 -5
- package/dist/storage-Bj1E26lU.cjs.map +0 -1
- package/dist/storage-kSxTjkNb.mjs.map +0 -1
- package/dist/storage-tgZSUnKl.mjs +0 -3
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import type { EndpointAnalysis, EndpointFeatures } from '../endpoint-analyzer';
|
|
3
|
+
import {
|
|
4
|
+
generateOptimizedImports,
|
|
5
|
+
generateValidatorFactories,
|
|
6
|
+
} from '../handler-templates';
|
|
7
|
+
|
|
8
|
+
// Helper to create endpoint features
|
|
9
|
+
function createFeatures(
|
|
10
|
+
overrides: Partial<EndpointFeatures> = {},
|
|
11
|
+
): EndpointFeatures {
|
|
12
|
+
return {
|
|
13
|
+
hasAuth: false,
|
|
14
|
+
hasServices: false,
|
|
15
|
+
hasDatabase: false,
|
|
16
|
+
hasBodyValidation: false,
|
|
17
|
+
hasQueryValidation: false,
|
|
18
|
+
hasParamValidation: false,
|
|
19
|
+
hasAudits: false,
|
|
20
|
+
hasEvents: false,
|
|
21
|
+
hasRateLimit: false,
|
|
22
|
+
hasRls: false,
|
|
23
|
+
hasOutputValidation: false,
|
|
24
|
+
...overrides,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Helper to create analysis
|
|
29
|
+
function createAnalysis(
|
|
30
|
+
overrides: Partial<EndpointAnalysis> = {},
|
|
31
|
+
): EndpointAnalysis {
|
|
32
|
+
return {
|
|
33
|
+
route: '/test',
|
|
34
|
+
method: 'GET',
|
|
35
|
+
exportName: 'testEndpoint',
|
|
36
|
+
tier: 'minimal',
|
|
37
|
+
serviceNames: [],
|
|
38
|
+
features: createFeatures(),
|
|
39
|
+
...overrides,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
describe('handler-templates', () => {
|
|
44
|
+
describe('generateOptimizedImports', () => {
|
|
45
|
+
it('should always include base imports', () => {
|
|
46
|
+
const result = generateOptimizedImports([]);
|
|
47
|
+
|
|
48
|
+
expect(result).toContain('import type { EnvironmentParser }');
|
|
49
|
+
expect(result).toContain('import type { Logger }');
|
|
50
|
+
expect(result).toContain('import type { Hono }');
|
|
51
|
+
expect(result).toContain('import { Endpoint }');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should include validator import when body validation needed', () => {
|
|
55
|
+
const analyses = [
|
|
56
|
+
createAnalysis({
|
|
57
|
+
features: createFeatures({ hasBodyValidation: true }),
|
|
58
|
+
}),
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
const result = generateOptimizedImports(analyses);
|
|
62
|
+
expect(result).toContain('import { validator }');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should include validator import when query validation needed', () => {
|
|
66
|
+
const analyses = [
|
|
67
|
+
createAnalysis({
|
|
68
|
+
features: createFeatures({ hasQueryValidation: true }),
|
|
69
|
+
}),
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const result = generateOptimizedImports(analyses);
|
|
73
|
+
expect(result).toContain('import { validator }');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should include validator import when param validation needed', () => {
|
|
77
|
+
const analyses = [
|
|
78
|
+
createAnalysis({
|
|
79
|
+
features: createFeatures({ hasParamValidation: true }),
|
|
80
|
+
}),
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
const result = generateOptimizedImports(analyses);
|
|
84
|
+
expect(result).toContain('import { validator }');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should include ResponseBuilder for standard tier', () => {
|
|
88
|
+
const analyses = [
|
|
89
|
+
createAnalysis({
|
|
90
|
+
tier: 'standard',
|
|
91
|
+
features: createFeatures({ hasAuth: true }),
|
|
92
|
+
}),
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
const result = generateOptimizedImports(analyses);
|
|
96
|
+
expect(result).toContain('import { ResponseBuilder }');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should include ResponseBuilder for full tier', () => {
|
|
100
|
+
const analyses = [
|
|
101
|
+
createAnalysis({
|
|
102
|
+
tier: 'full',
|
|
103
|
+
features: createFeatures({ hasAudits: true }),
|
|
104
|
+
}),
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
const result = generateOptimizedImports(analyses);
|
|
108
|
+
expect(result).toContain('import { ResponseBuilder }');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should include ServiceDiscovery when services are used', () => {
|
|
112
|
+
const analyses = [
|
|
113
|
+
createAnalysis({
|
|
114
|
+
features: createFeatures({ hasServices: true }),
|
|
115
|
+
}),
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
const result = generateOptimizedImports(analyses);
|
|
119
|
+
expect(result).toContain('import { ServiceDiscovery }');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should include ServiceDiscovery when database is used', () => {
|
|
123
|
+
const analyses = [
|
|
124
|
+
createAnalysis({
|
|
125
|
+
features: createFeatures({ hasDatabase: true }),
|
|
126
|
+
}),
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
const result = generateOptimizedImports(analyses);
|
|
130
|
+
expect(result).toContain('import { ServiceDiscovery }');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should include events import when events are used', () => {
|
|
134
|
+
const analyses = [
|
|
135
|
+
createAnalysis({
|
|
136
|
+
features: createFeatures({ hasEvents: true }),
|
|
137
|
+
}),
|
|
138
|
+
];
|
|
139
|
+
|
|
140
|
+
const result = generateOptimizedImports(analyses);
|
|
141
|
+
expect(result).toContain('import { publishConstructEvents }');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should include audit imports when audits are used', () => {
|
|
145
|
+
const analyses = [
|
|
146
|
+
createAnalysis({
|
|
147
|
+
features: createFeatures({ hasAudits: true }),
|
|
148
|
+
}),
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
const result = generateOptimizedImports(analyses);
|
|
152
|
+
expect(result).toContain('createAuditContext');
|
|
153
|
+
expect(result).toContain('withAuditableEndpointTransaction');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should include createError when rate limiting is used', () => {
|
|
157
|
+
const analyses = [
|
|
158
|
+
createAnalysis({
|
|
159
|
+
features: createFeatures({ hasRateLimit: true }),
|
|
160
|
+
}),
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
const result = generateOptimizedImports(analyses);
|
|
164
|
+
expect(result).toContain('import { createError }');
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('should include RLS imports when RLS is used', () => {
|
|
168
|
+
const analyses = [
|
|
169
|
+
createAnalysis({
|
|
170
|
+
features: createFeatures({ hasRls: true }),
|
|
171
|
+
}),
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
const result = generateOptimizedImports(analyses);
|
|
175
|
+
expect(result).toContain('withRlsContext');
|
|
176
|
+
expect(result).toContain('extractRlsContext');
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should not include optional imports when not needed', () => {
|
|
180
|
+
const analyses = [createAnalysis()];
|
|
181
|
+
|
|
182
|
+
const result = generateOptimizedImports(analyses);
|
|
183
|
+
expect(result).not.toContain('import { validator }');
|
|
184
|
+
expect(result).not.toContain('ServiceDiscovery');
|
|
185
|
+
expect(result).not.toContain('publishConstructEvents');
|
|
186
|
+
expect(result).not.toContain('createAuditContext');
|
|
187
|
+
expect(result).not.toContain('createError');
|
|
188
|
+
expect(result).not.toContain('withRlsContext');
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
describe('generateValidatorFactories', () => {
|
|
193
|
+
it('should return empty string when no validation needed', () => {
|
|
194
|
+
const result = generateValidatorFactories([createAnalysis()]);
|
|
195
|
+
expect(result).toBe('');
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('should generate body validator when body validation needed', () => {
|
|
199
|
+
const analyses = [
|
|
200
|
+
createAnalysis({
|
|
201
|
+
features: createFeatures({ hasBodyValidation: true }),
|
|
202
|
+
}),
|
|
203
|
+
];
|
|
204
|
+
|
|
205
|
+
const result = generateValidatorFactories(analyses);
|
|
206
|
+
expect(result).toContain('validateBody');
|
|
207
|
+
expect(result).toContain("validator('json'");
|
|
208
|
+
expect(result).toContain('endpoint.input?.body');
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should generate query validator when query validation needed', () => {
|
|
212
|
+
const analyses = [
|
|
213
|
+
createAnalysis({
|
|
214
|
+
features: createFeatures({ hasQueryValidation: true }),
|
|
215
|
+
}),
|
|
216
|
+
];
|
|
217
|
+
|
|
218
|
+
const result = generateValidatorFactories(analyses);
|
|
219
|
+
expect(result).toContain('validateQuery');
|
|
220
|
+
expect(result).toContain("validator('query'");
|
|
221
|
+
expect(result).toContain('endpoint.input?.query');
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('should generate params validator when param validation needed', () => {
|
|
225
|
+
const analyses = [
|
|
226
|
+
createAnalysis({
|
|
227
|
+
features: createFeatures({ hasParamValidation: true }),
|
|
228
|
+
}),
|
|
229
|
+
];
|
|
230
|
+
|
|
231
|
+
const result = generateValidatorFactories(analyses);
|
|
232
|
+
expect(result).toContain('validateParams');
|
|
233
|
+
expect(result).toContain("validator('param'");
|
|
234
|
+
expect(result).toContain('endpoint.input?.params');
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('should generate all validators when all validation types needed', () => {
|
|
238
|
+
const analyses = [
|
|
239
|
+
createAnalysis({
|
|
240
|
+
features: createFeatures({
|
|
241
|
+
hasBodyValidation: true,
|
|
242
|
+
hasQueryValidation: true,
|
|
243
|
+
hasParamValidation: true,
|
|
244
|
+
}),
|
|
245
|
+
}),
|
|
246
|
+
];
|
|
247
|
+
|
|
248
|
+
const result = generateValidatorFactories(analyses);
|
|
249
|
+
expect(result).toContain('validateBody');
|
|
250
|
+
expect(result).toContain('validateQuery');
|
|
251
|
+
expect(result).toContain('validateParams');
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('should handle multiple endpoints with different validation', () => {
|
|
255
|
+
const analyses = [
|
|
256
|
+
createAnalysis({
|
|
257
|
+
exportName: 'endpoint1',
|
|
258
|
+
features: createFeatures({ hasBodyValidation: true }),
|
|
259
|
+
}),
|
|
260
|
+
createAnalysis({
|
|
261
|
+
exportName: 'endpoint2',
|
|
262
|
+
features: createFeatures({ hasQueryValidation: true }),
|
|
263
|
+
}),
|
|
264
|
+
];
|
|
265
|
+
|
|
266
|
+
const result = generateValidatorFactories(analyses);
|
|
267
|
+
expect(result).toContain('validateBody');
|
|
268
|
+
expect(result).toContain('validateQuery');
|
|
269
|
+
expect(result).not.toContain('validateParams');
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
});
|
package/src/build/bundler.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
3
|
import { mkdir, rename, writeFile } from 'node:fs/promises';
|
|
4
4
|
import { join } from 'node:path';
|
|
@@ -19,6 +19,12 @@ export interface BundleOptions {
|
|
|
19
19
|
stage?: string;
|
|
20
20
|
/** Constructs to validate environment variables for */
|
|
21
21
|
constructs?: Construct[];
|
|
22
|
+
/** Docker compose services configured (for auto-populating env vars) */
|
|
23
|
+
dockerServices?: {
|
|
24
|
+
postgres?: boolean;
|
|
25
|
+
redis?: boolean;
|
|
26
|
+
rabbitmq?: boolean;
|
|
27
|
+
};
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
export interface BundleResult {
|
|
@@ -54,6 +60,19 @@ async function collectRequiredEnvVars(
|
|
|
54
60
|
* @param options - Bundle configuration options
|
|
55
61
|
* @returns Bundle result with output path and optional master key
|
|
56
62
|
*/
|
|
63
|
+
/** Default env var values for docker compose services */
|
|
64
|
+
const DOCKER_SERVICE_ENV_VARS: Record<string, Record<string, string>> = {
|
|
65
|
+
postgres: {
|
|
66
|
+
DATABASE_URL: 'postgresql://postgres:postgres@postgres:5432/app',
|
|
67
|
+
},
|
|
68
|
+
redis: {
|
|
69
|
+
REDIS_URL: 'redis://redis:6379',
|
|
70
|
+
},
|
|
71
|
+
rabbitmq: {
|
|
72
|
+
RABBITMQ_URL: 'amqp://rabbitmq:5672',
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
57
76
|
export async function bundleServer(
|
|
58
77
|
options: BundleOptions,
|
|
59
78
|
): Promise<BundleResult> {
|
|
@@ -65,6 +84,7 @@ export async function bundleServer(
|
|
|
65
84
|
external,
|
|
66
85
|
stage,
|
|
67
86
|
constructs,
|
|
87
|
+
dockerServices,
|
|
68
88
|
} = options;
|
|
69
89
|
|
|
70
90
|
// Ensure output directory exists
|
|
@@ -124,6 +144,24 @@ export async function bundleServer(
|
|
|
124
144
|
);
|
|
125
145
|
}
|
|
126
146
|
|
|
147
|
+
// Auto-populate env vars from docker compose services
|
|
148
|
+
if (dockerServices) {
|
|
149
|
+
for (const [service, enabled] of Object.entries(dockerServices)) {
|
|
150
|
+
if (enabled && DOCKER_SERVICE_ENV_VARS[service]) {
|
|
151
|
+
for (const [envVar, defaultValue] of Object.entries(
|
|
152
|
+
DOCKER_SERVICE_ENV_VARS[service],
|
|
153
|
+
)) {
|
|
154
|
+
// Check if not already in urls or custom
|
|
155
|
+
const urlKey = envVar as keyof typeof secrets.urls;
|
|
156
|
+
if (!secrets.urls[urlKey] && !secrets.custom[envVar]) {
|
|
157
|
+
secrets.urls[urlKey] = defaultValue;
|
|
158
|
+
console.log(` Auto-populated ${envVar} from docker compose`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
127
165
|
// Validate environment variables if constructs are provided
|
|
128
166
|
if (constructs && constructs.length > 0) {
|
|
129
167
|
console.log(' Analyzing environment variable requirements...');
|
|
@@ -165,10 +203,10 @@ export async function bundleServer(
|
|
|
165
203
|
const encrypted = encryptSecrets(embeddable);
|
|
166
204
|
masterKey = encrypted.masterKey;
|
|
167
205
|
|
|
168
|
-
// Add define options for build-time injection
|
|
206
|
+
// Add define options for build-time injection using tsdown's --env.* format
|
|
169
207
|
const defines = generateDefineOptions(encrypted);
|
|
170
208
|
for (const [key, value] of Object.entries(defines)) {
|
|
171
|
-
args.push(
|
|
209
|
+
args.push(`--env.${key}`, value);
|
|
172
210
|
}
|
|
173
211
|
|
|
174
212
|
console.log(` Secrets encrypted for stage "${stage}"`);
|
|
@@ -178,11 +216,22 @@ export async function bundleServer(
|
|
|
178
216
|
|
|
179
217
|
try {
|
|
180
218
|
// Run tsdown with command-line arguments
|
|
181
|
-
|
|
219
|
+
// Use spawnSync with args array to avoid shell escaping issues with --define values
|
|
220
|
+
// args is always populated with ['npx', 'tsdown', ...] so cmd is never undefined
|
|
221
|
+
const [cmd, ...cmdArgs] = args as [string, ...string[]];
|
|
222
|
+
const result = spawnSync(cmd, cmdArgs, {
|
|
182
223
|
cwd: process.cwd(),
|
|
183
224
|
stdio: 'inherit',
|
|
225
|
+
shell: process.platform === 'win32', // Only use shell on Windows for npx resolution
|
|
184
226
|
});
|
|
185
227
|
|
|
228
|
+
if (result.error) {
|
|
229
|
+
throw result.error;
|
|
230
|
+
}
|
|
231
|
+
if (result.status !== 0) {
|
|
232
|
+
throw new Error(`tsdown exited with code ${result.status}`);
|
|
233
|
+
}
|
|
234
|
+
|
|
186
235
|
// Rename output to .mjs for explicit ESM
|
|
187
236
|
// tsdown outputs as server.js for ESM format
|
|
188
237
|
const jsOutput = join(outputDir, 'server.js');
|
package/src/build/index.ts
CHANGED
|
@@ -93,6 +93,22 @@ export async function buildCommand(
|
|
|
93
93
|
logger.log(`🪝 Server hooks enabled`);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
// Extract docker compose services for env var auto-population
|
|
97
|
+
const services = config.docker?.compose?.services;
|
|
98
|
+
const dockerServices = services
|
|
99
|
+
? Array.isArray(services)
|
|
100
|
+
? {
|
|
101
|
+
postgres: services.includes('postgres'),
|
|
102
|
+
redis: services.includes('redis'),
|
|
103
|
+
rabbitmq: services.includes('rabbitmq'),
|
|
104
|
+
}
|
|
105
|
+
: {
|
|
106
|
+
postgres: Boolean(services.postgres),
|
|
107
|
+
redis: Boolean(services.redis),
|
|
108
|
+
rabbitmq: Boolean(services.rabbitmq),
|
|
109
|
+
}
|
|
110
|
+
: undefined;
|
|
111
|
+
|
|
96
112
|
const buildContext: BuildContext = {
|
|
97
113
|
envParserPath,
|
|
98
114
|
envParserImportPattern,
|
|
@@ -102,6 +118,7 @@ export async function buildCommand(
|
|
|
102
118
|
studio,
|
|
103
119
|
hooks,
|
|
104
120
|
production,
|
|
121
|
+
dockerServices,
|
|
105
122
|
};
|
|
106
123
|
|
|
107
124
|
// Initialize generators
|
|
@@ -245,6 +262,9 @@ async function buildForProvider(
|
|
|
245
262
|
...subscribers.map((s) => s.construct),
|
|
246
263
|
];
|
|
247
264
|
|
|
265
|
+
// Get docker compose services for auto-populating env vars
|
|
266
|
+
const dockerServices = context.dockerServices;
|
|
267
|
+
|
|
248
268
|
const bundleResult = await bundleServer({
|
|
249
269
|
entryPoint: join(outputDir, 'server.ts'),
|
|
250
270
|
outputDir: join(outputDir, 'dist'),
|
|
@@ -253,6 +273,7 @@ async function buildForProvider(
|
|
|
253
273
|
external: context.production.external,
|
|
254
274
|
stage,
|
|
255
275
|
constructs: allConstructs,
|
|
276
|
+
dockerServices,
|
|
256
277
|
});
|
|
257
278
|
masterKey = bundleResult.masterKey;
|
|
258
279
|
logger.log(`✅ Bundle complete: .gkm/server/dist/server.mjs`);
|
package/src/build/types.ts
CHANGED
|
@@ -84,6 +84,12 @@ export interface BuildContext {
|
|
|
84
84
|
hooks?: NormalizedHooksConfig;
|
|
85
85
|
/** Production build configuration */
|
|
86
86
|
production?: NormalizedProductionConfig;
|
|
87
|
+
/** Docker compose services for auto-populating env vars */
|
|
88
|
+
dockerServices?: {
|
|
89
|
+
postgres?: boolean;
|
|
90
|
+
redis?: boolean;
|
|
91
|
+
rabbitmq?: boolean;
|
|
92
|
+
};
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
export interface ProviderBuildResult {
|