@geekmidas/cli 0.2.4 → 0.4.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.
Files changed (82) hide show
  1. package/README.md +488 -71
  2. package/dist/{EndpointGenerator-C73wNoih.cjs → EndpointGenerator-BxNCkus4.cjs} +60 -6
  3. package/dist/EndpointGenerator-BxNCkus4.cjs.map +1 -0
  4. package/dist/{EndpointGenerator-CWh18d92.mjs → EndpointGenerator-CzDhG7Or.mjs} +60 -6
  5. package/dist/EndpointGenerator-CzDhG7Or.mjs.map +1 -0
  6. package/dist/OpenApiTsGenerator-NBNEoaeO.cjs +501 -0
  7. package/dist/OpenApiTsGenerator-NBNEoaeO.cjs.map +1 -0
  8. package/dist/OpenApiTsGenerator-q3aWNkuM.mjs +495 -0
  9. package/dist/OpenApiTsGenerator-q3aWNkuM.mjs.map +1 -0
  10. package/dist/build/index.cjs +4 -4
  11. package/dist/build/index.mjs +4 -4
  12. package/dist/build/manifests.cjs +3 -2
  13. package/dist/build/manifests.mjs +2 -2
  14. package/dist/{build-BVng9MQX.cjs → build-CWtHnJMQ.cjs} +19 -17
  15. package/dist/build-CWtHnJMQ.cjs.map +1 -0
  16. package/dist/{build-BqexeI-W.mjs → build-DyDgu_D1.mjs} +20 -18
  17. package/dist/build-DyDgu_D1.mjs.map +1 -0
  18. package/dist/{config-U-mdW-7Y.mjs → config-AFmFKmU0.mjs} +3 -3
  19. package/dist/config-AFmFKmU0.mjs.map +1 -0
  20. package/dist/{config-D1EpSGk6.cjs → config-BVIJpAsa.cjs} +3 -3
  21. package/dist/config-BVIJpAsa.cjs.map +1 -0
  22. package/dist/config.cjs +1 -1
  23. package/dist/config.mjs +1 -1
  24. package/dist/dev/index.cjs +5 -4
  25. package/dist/dev/index.mjs +4 -4
  26. package/dist/{dev-DbtyToc7.cjs → dev-CgDYC4o8.cjs} +95 -31
  27. package/dist/dev-CgDYC4o8.cjs.map +1 -0
  28. package/dist/{dev-DnGYXuMn.mjs → dev-CpA8AQPX.mjs} +90 -32
  29. package/dist/dev-CpA8AQPX.mjs.map +1 -0
  30. package/dist/generators/EndpointGenerator.cjs +1 -1
  31. package/dist/generators/EndpointGenerator.mjs +1 -1
  32. package/dist/generators/OpenApiTsGenerator.cjs +3 -0
  33. package/dist/generators/OpenApiTsGenerator.mjs +3 -0
  34. package/dist/generators/index.cjs +1 -1
  35. package/dist/generators/index.mjs +1 -1
  36. package/dist/index.cjs +16 -10
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.mjs +16 -10
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/manifests-C2eMoMUm.mjs +68 -0
  41. package/dist/manifests-C2eMoMUm.mjs.map +1 -0
  42. package/dist/manifests-CK1VV_pM.cjs +80 -0
  43. package/dist/manifests-CK1VV_pM.cjs.map +1 -0
  44. package/dist/openapi-DRTRGhTt.mjs +50 -0
  45. package/dist/openapi-DRTRGhTt.mjs.map +1 -0
  46. package/dist/openapi-DhK4b0lB.cjs +56 -0
  47. package/dist/openapi-DhK4b0lB.cjs.map +1 -0
  48. package/dist/openapi.cjs +4 -3
  49. package/dist/openapi.mjs +4 -3
  50. package/docs/OPENAPI_TYPESCRIPT_DESIGN.md +408 -0
  51. package/docs/manifest-refactor-design.md +287 -0
  52. package/package.json +10 -3
  53. package/src/__tests__/openapi.spec.ts +78 -63
  54. package/src/build/__tests__/index-new.spec.ts +43 -72
  55. package/src/build/__tests__/manifests.spec.ts +346 -0
  56. package/src/build/index.ts +59 -62
  57. package/src/build/manifests.ts +85 -13
  58. package/src/build/types.ts +13 -2
  59. package/src/config.ts +4 -2
  60. package/src/dev/__tests__/index.spec.ts +98 -1
  61. package/src/dev/index.ts +152 -25
  62. package/src/generators/EndpointGenerator.ts +69 -5
  63. package/src/generators/OpenApiTsGenerator.ts +798 -0
  64. package/src/index.ts +6 -3
  65. package/src/openapi.ts +36 -15
  66. package/src/types.ts +23 -7
  67. package/dist/EndpointGenerator-C73wNoih.cjs.map +0 -1
  68. package/dist/EndpointGenerator-CWh18d92.mjs.map +0 -1
  69. package/dist/build-BVng9MQX.cjs.map +0 -1
  70. package/dist/build-BqexeI-W.mjs.map +0 -1
  71. package/dist/config-D1EpSGk6.cjs.map +0 -1
  72. package/dist/config-U-mdW-7Y.mjs.map +0 -1
  73. package/dist/dev-DbtyToc7.cjs.map +0 -1
  74. package/dist/dev-DnGYXuMn.mjs.map +0 -1
  75. package/dist/manifests-BrJXpHrf.mjs +0 -21
  76. package/dist/manifests-BrJXpHrf.mjs.map +0 -1
  77. package/dist/manifests-D0saShvH.cjs +0 -27
  78. package/dist/manifests-D0saShvH.cjs.map +0 -1
  79. package/dist/openapi-BTHbPrxS.mjs +0 -36
  80. package/dist/openapi-BTHbPrxS.mjs.map +0 -1
  81. package/dist/openapi-CewcfoRH.cjs +0 -42
  82. package/dist/openapi-CewcfoRH.cjs.map +0 -1
@@ -0,0 +1,346 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { itWithDir } from '@geekmidas/testkit/os';
4
+ import { describe, expect, vi } from 'vitest';
5
+ import type {
6
+ CronInfo,
7
+ FunctionInfo,
8
+ RouteInfo,
9
+ SubscriberInfo,
10
+ } from '../../types';
11
+ import { generateAwsManifest, generateServerManifest } from '../manifests';
12
+
13
+ describe('generateAwsManifest', () => {
14
+ itWithDir('should generate AWS manifest with routes', async ({ dir }) => {
15
+ const routes: RouteInfo[] = [
16
+ {
17
+ path: '/users',
18
+ method: 'GET',
19
+ handler: '.gkm/aws/getUsers.handler',
20
+ authorizer: 'jwt',
21
+ },
22
+ {
23
+ path: '/users',
24
+ method: 'POST',
25
+ handler: '.gkm/aws/createUser.handler',
26
+ authorizer: 'jwt',
27
+ },
28
+ ];
29
+
30
+ await generateAwsManifest(dir, routes, [], [], []);
31
+
32
+ const manifestPath = join(dir, 'manifest', 'aws.ts');
33
+ const content = await readFile(manifestPath, 'utf-8');
34
+
35
+ expect(content).toContain('export const manifest = {');
36
+ expect(content).toContain('} as const;');
37
+ expect(content).toContain('/users');
38
+ expect(content).toContain('GET');
39
+ expect(content).toContain('POST');
40
+ expect(content).toContain('jwt');
41
+ });
42
+
43
+ itWithDir(
44
+ 'should filter out ALL method routes from AWS manifest',
45
+ async ({ dir }) => {
46
+ const routes: RouteInfo[] = [
47
+ {
48
+ path: '/users',
49
+ method: 'GET',
50
+ handler: '.gkm/aws/getUsers.handler',
51
+ authorizer: 'jwt',
52
+ },
53
+ {
54
+ path: '*',
55
+ method: 'ALL',
56
+ handler: '.gkm/server/app.ts',
57
+ authorizer: 'none',
58
+ },
59
+ ];
60
+
61
+ await generateAwsManifest(dir, routes, [], [], []);
62
+
63
+ const manifestPath = join(dir, 'manifest', 'aws.ts');
64
+ const content = await readFile(manifestPath, 'utf-8');
65
+
66
+ expect(content).toContain('/users');
67
+ expect(content).toContain('GET');
68
+ expect(content).not.toContain('"ALL"');
69
+ },
70
+ );
71
+
72
+ itWithDir('should generate AWS manifest with functions', async ({ dir }) => {
73
+ const functions: FunctionInfo[] = [
74
+ {
75
+ name: 'processData',
76
+ handler: '.gkm/aws/processData.handler',
77
+ timeout: 300,
78
+ memorySize: 512,
79
+ environment: ['DATABASE_URL'],
80
+ },
81
+ ];
82
+
83
+ await generateAwsManifest(dir, [], functions, [], []);
84
+
85
+ const manifestPath = join(dir, 'manifest', 'aws.ts');
86
+ const content = await readFile(manifestPath, 'utf-8');
87
+
88
+ expect(content).toContain('processData');
89
+ expect(content).toContain('300');
90
+ expect(content).toContain('512');
91
+ expect(content).toContain('DATABASE_URL');
92
+ });
93
+
94
+ itWithDir('should generate AWS manifest with crons', async ({ dir }) => {
95
+ const crons: CronInfo[] = [
96
+ {
97
+ name: 'dailyCleanup',
98
+ handler: '.gkm/aws/dailyCleanup.handler',
99
+ schedule: 'rate(1 day)',
100
+ timeout: 300,
101
+ memorySize: 256,
102
+ environment: [],
103
+ },
104
+ ];
105
+
106
+ await generateAwsManifest(dir, [], [], crons, []);
107
+
108
+ const manifestPath = join(dir, 'manifest', 'aws.ts');
109
+ const content = await readFile(manifestPath, 'utf-8');
110
+
111
+ expect(content).toContain('dailyCleanup');
112
+ expect(content).toContain('rate(1 day)');
113
+ });
114
+
115
+ itWithDir(
116
+ 'should generate AWS manifest with subscribers',
117
+ async ({ dir }) => {
118
+ const subscribers: SubscriberInfo[] = [
119
+ {
120
+ name: 'orderHandler',
121
+ handler: '.gkm/aws/orderHandler.handler',
122
+ subscribedEvents: ['order.created', 'order.updated'],
123
+ timeout: 30,
124
+ memorySize: 256,
125
+ environment: [],
126
+ },
127
+ ];
128
+
129
+ await generateAwsManifest(dir, [], [], [], subscribers);
130
+
131
+ const manifestPath = join(dir, 'manifest', 'aws.ts');
132
+ const content = await readFile(manifestPath, 'utf-8');
133
+
134
+ expect(content).toContain('orderHandler');
135
+ expect(content).toContain('order.created');
136
+ expect(content).toContain('order.updated');
137
+ },
138
+ );
139
+
140
+ itWithDir('should export derived types', async ({ dir }) => {
141
+ await generateAwsManifest(dir, [], [], [], []);
142
+
143
+ const manifestPath = join(dir, 'manifest', 'aws.ts');
144
+ const content = await readFile(manifestPath, 'utf-8');
145
+
146
+ expect(content).toContain('export type Route =');
147
+ expect(content).toContain('export type Function =');
148
+ expect(content).toContain('export type Cron =');
149
+ expect(content).toContain('export type Subscriber =');
150
+ expect(content).toContain('export type Authorizer =');
151
+ expect(content).toContain('export type HttpMethod =');
152
+ expect(content).toContain('export type RoutePath =');
153
+ });
154
+
155
+ itWithDir('should log manifest generation info', async ({ dir }) => {
156
+ const logSpy = vi.spyOn(console, 'log');
157
+
158
+ const routes: RouteInfo[] = [
159
+ {
160
+ path: '/users',
161
+ method: 'GET',
162
+ handler: '.gkm/aws/getUsers.handler',
163
+ authorizer: 'jwt',
164
+ },
165
+ ];
166
+
167
+ await generateAwsManifest(dir, routes, [], [], []);
168
+
169
+ expect(logSpy).toHaveBeenCalledWith(
170
+ 'Generated AWS manifest with 1 routes, 0 functions, 0 crons, 0 subscribers',
171
+ );
172
+ expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('Manifest:'));
173
+
174
+ logSpy.mockRestore();
175
+ });
176
+ });
177
+
178
+ describe('generateServerManifest', () => {
179
+ itWithDir(
180
+ 'should generate server manifest with app info',
181
+ async ({ dir }) => {
182
+ const appInfo = {
183
+ handler: '.gkm/server/app.ts',
184
+ endpoints: '.gkm/server/endpoints.ts',
185
+ };
186
+
187
+ await generateServerManifest(dir, appInfo, [], []);
188
+
189
+ const manifestPath = join(dir, 'manifest', 'server.ts');
190
+ const content = await readFile(manifestPath, 'utf-8');
191
+
192
+ expect(content).toContain('export const manifest = {');
193
+ expect(content).toContain('} as const;');
194
+ expect(content).toContain('app:');
195
+ expect(content).toContain('.gkm/server/app.ts');
196
+ expect(content).toContain('.gkm/server/endpoints.ts');
197
+ },
198
+ );
199
+
200
+ itWithDir(
201
+ 'should generate server manifest with route metadata',
202
+ async ({ dir }) => {
203
+ const appInfo = {
204
+ handler: '.gkm/server/app.ts',
205
+ endpoints: '.gkm/server/endpoints.ts',
206
+ };
207
+
208
+ const routes: RouteInfo[] = [
209
+ {
210
+ path: '/users',
211
+ method: 'GET',
212
+ handler: '', // Not used for server
213
+ authorizer: 'jwt',
214
+ },
215
+ {
216
+ path: '/posts',
217
+ method: 'POST',
218
+ handler: '',
219
+ authorizer: 'apiKey',
220
+ },
221
+ ];
222
+
223
+ await generateServerManifest(dir, appInfo, routes, []);
224
+
225
+ const manifestPath = join(dir, 'manifest', 'server.ts');
226
+ const content = await readFile(manifestPath, 'utf-8');
227
+
228
+ expect(content).toContain('/users');
229
+ expect(content).toContain('/posts');
230
+ expect(content).toContain('GET');
231
+ expect(content).toContain('POST');
232
+ expect(content).toContain('jwt');
233
+ expect(content).toContain('apiKey');
234
+ },
235
+ );
236
+
237
+ itWithDir(
238
+ 'should filter out ALL method routes from server manifest',
239
+ async ({ dir }) => {
240
+ const appInfo = {
241
+ handler: '.gkm/server/app.ts',
242
+ endpoints: '.gkm/server/endpoints.ts',
243
+ };
244
+
245
+ const routes: RouteInfo[] = [
246
+ {
247
+ path: '/users',
248
+ method: 'GET',
249
+ handler: '',
250
+ authorizer: 'jwt',
251
+ },
252
+ {
253
+ path: '*',
254
+ method: 'ALL',
255
+ handler: '',
256
+ authorizer: 'none',
257
+ },
258
+ ];
259
+
260
+ await generateServerManifest(dir, appInfo, routes, []);
261
+
262
+ const manifestPath = join(dir, 'manifest', 'server.ts');
263
+ const content = await readFile(manifestPath, 'utf-8');
264
+
265
+ expect(content).toContain('/users');
266
+ expect(content).not.toContain('"ALL"');
267
+ },
268
+ );
269
+
270
+ itWithDir(
271
+ 'should generate server manifest with subscribers',
272
+ async ({ dir }) => {
273
+ const appInfo = {
274
+ handler: '.gkm/server/app.ts',
275
+ endpoints: '.gkm/server/endpoints.ts',
276
+ };
277
+
278
+ const subscribers: SubscriberInfo[] = [
279
+ {
280
+ name: 'orderHandler',
281
+ handler: '.gkm/server/orderHandler.ts',
282
+ subscribedEvents: ['order.created'],
283
+ timeout: 30,
284
+ memorySize: 256,
285
+ environment: [],
286
+ },
287
+ ];
288
+
289
+ await generateServerManifest(dir, appInfo, [], subscribers);
290
+
291
+ const manifestPath = join(dir, 'manifest', 'server.ts');
292
+ const content = await readFile(manifestPath, 'utf-8');
293
+
294
+ // Server manifest only includes name and events for subscribers
295
+ expect(content).toContain('orderHandler');
296
+ expect(content).toContain('order.created');
297
+ // Should not include handler path in server manifest subscribers
298
+ expect(content).not.toContain('.gkm/server/orderHandler.ts');
299
+ },
300
+ );
301
+
302
+ itWithDir('should export derived types for server', async ({ dir }) => {
303
+ const appInfo = {
304
+ handler: '.gkm/server/app.ts',
305
+ endpoints: '.gkm/server/endpoints.ts',
306
+ };
307
+
308
+ await generateServerManifest(dir, appInfo, [], []);
309
+
310
+ const manifestPath = join(dir, 'manifest', 'server.ts');
311
+ const content = await readFile(manifestPath, 'utf-8');
312
+
313
+ expect(content).toContain('export type Route =');
314
+ expect(content).toContain('export type Subscriber =');
315
+ expect(content).toContain('export type Authorizer =');
316
+ expect(content).toContain('export type HttpMethod =');
317
+ expect(content).toContain('export type RoutePath =');
318
+ });
319
+
320
+ itWithDir('should log manifest generation info', async ({ dir }) => {
321
+ const logSpy = vi.spyOn(console, 'log');
322
+
323
+ const appInfo = {
324
+ handler: '.gkm/server/app.ts',
325
+ endpoints: '.gkm/server/endpoints.ts',
326
+ };
327
+
328
+ const routes: RouteInfo[] = [
329
+ {
330
+ path: '/users',
331
+ method: 'GET',
332
+ handler: '',
333
+ authorizer: 'jwt',
334
+ },
335
+ ];
336
+
337
+ await generateServerManifest(dir, appInfo, routes, []);
338
+
339
+ expect(logSpy).toHaveBeenCalledWith(
340
+ 'Generated server manifest with 1 routes, 0 subscribers',
341
+ );
342
+ expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('Manifest:'));
343
+
344
+ logSpy.mockRestore();
345
+ });
346
+ });
@@ -1,5 +1,5 @@
1
1
  import { mkdir } from 'node:fs/promises';
2
- import { join } from 'node:path';
2
+ import { join, relative } from 'node:path';
3
3
  import type { Cron } from '@geekmidas/constructs/crons';
4
4
  import type { Endpoint } from '@geekmidas/constructs/endpoints';
5
5
  import type { Function } from '@geekmidas/constructs/functions';
@@ -12,15 +12,12 @@ import {
12
12
  type GeneratedConstruct,
13
13
  SubscriberGenerator,
14
14
  } from '../generators';
15
- import type {
16
- BuildOptions,
17
- CronInfo,
18
- FunctionInfo,
19
- LegacyProvider,
20
- RouteInfo,
21
- SubscriberInfo,
22
- } from '../types';
23
- import { generateManifests } from './manifests';
15
+ import type { BuildOptions, LegacyProvider, RouteInfo } from '../types';
16
+ import {
17
+ type ServerAppInfo,
18
+ generateAwsManifest,
19
+ generateServerManifest,
20
+ } from './manifests';
24
21
  import { resolveProviders } from './providerResolver';
25
22
  import type { BuildContext } from './types';
26
23
 
@@ -104,55 +101,29 @@ export async function buildCommand(options: BuildOptions): Promise<void> {
104
101
  const rootOutputDir = join(process.cwd(), '.gkm');
105
102
  await mkdir(rootOutputDir, { recursive: true });
106
103
 
107
- // Collect all build results from each provider
108
- const allBuildResults = await Promise.all(
109
- resolved.providers.map((provider) =>
110
- buildForProvider(
111
- provider,
112
- buildContext,
113
- endpointGenerator,
114
- functionGenerator,
115
- cronGenerator,
116
- subscriberGenerator,
117
- allEndpoints,
118
- allFunctions,
119
- allCrons,
120
- allSubscribers,
121
- resolved.enableOpenApi,
122
- ),
123
- ),
124
- );
125
-
126
- // Aggregate all routes, functions, crons, and subscribers from all providers
127
- const aggregatedRoutes = allBuildResults.flatMap((result) => result.routes);
128
- const aggregatedFunctions = allBuildResults.flatMap(
129
- (result) => result.functions,
130
- );
131
- const aggregatedCrons = allBuildResults.flatMap((result) => result.crons);
132
- const aggregatedSubscribers = allBuildResults.flatMap(
133
- (result) => result.subscribers,
134
- );
135
-
136
- // Generate single manifest at root .gkm directory
137
- await generateManifests(
138
- rootOutputDir,
139
- aggregatedRoutes,
140
- aggregatedFunctions,
141
- aggregatedCrons,
142
- aggregatedSubscribers,
143
- );
144
- }
145
-
146
- interface BuildResult {
147
- routes: RouteInfo[];
148
- functions: FunctionInfo[];
149
- crons: CronInfo[];
150
- subscribers: SubscriberInfo[];
104
+ // Build for each provider and generate per-provider manifests
105
+ for (const provider of resolved.providers) {
106
+ await buildForProvider(
107
+ provider,
108
+ buildContext,
109
+ rootOutputDir,
110
+ endpointGenerator,
111
+ functionGenerator,
112
+ cronGenerator,
113
+ subscriberGenerator,
114
+ allEndpoints,
115
+ allFunctions,
116
+ allCrons,
117
+ allSubscribers,
118
+ resolved.enableOpenApi,
119
+ );
120
+ }
151
121
  }
152
122
 
153
123
  async function buildForProvider(
154
124
  provider: LegacyProvider,
155
125
  context: BuildContext,
126
+ rootOutputDir: string,
156
127
  endpointGenerator: EndpointGenerator,
157
128
  functionGenerator: FunctionGenerator,
158
129
  cronGenerator: CronGenerator,
@@ -162,7 +133,7 @@ async function buildForProvider(
162
133
  crons: GeneratedConstruct<Cron<any, any, any, any>>[],
163
134
  subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],
164
135
  enableOpenApi: boolean,
165
- ): Promise<BuildResult> {
136
+ ): Promise<void> {
166
137
  const outputDir = join(process.cwd(), '.gkm', provider);
167
138
 
168
139
  // Ensure output directory exists
@@ -187,11 +158,37 @@ async function buildForProvider(
187
158
  `Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`,
188
159
  );
189
160
 
190
- // Return build results instead of generating manifest here
191
- return {
192
- routes,
193
- functions: functionInfos,
194
- crons: cronInfos,
195
- subscribers: subscriberInfos,
196
- };
161
+ // Generate provider-specific manifest
162
+ if (provider === 'server') {
163
+ // For server, collect actual route metadata from endpoint constructs
164
+ const routeMetadata: RouteInfo[] = await Promise.all(
165
+ endpoints.map(async ({ construct }) => ({
166
+ path: construct._path,
167
+ method: construct.method,
168
+ handler: '', // Not needed for server manifest
169
+ authorizer: construct.authorizer?.name ?? 'none',
170
+ })),
171
+ );
172
+
173
+ const appInfo: ServerAppInfo = {
174
+ handler: relative(process.cwd(), join(outputDir, 'app.ts')),
175
+ endpoints: relative(process.cwd(), join(outputDir, 'endpoints.ts')),
176
+ };
177
+
178
+ await generateServerManifest(
179
+ rootOutputDir,
180
+ appInfo,
181
+ routeMetadata,
182
+ subscriberInfos,
183
+ );
184
+ } else {
185
+ // For AWS providers, generate AWS manifest
186
+ await generateAwsManifest(
187
+ rootOutputDir,
188
+ routes,
189
+ functionInfos,
190
+ cronInfos,
191
+ subscriberInfos,
192
+ );
193
+ }
197
194
  }
@@ -1,7 +1,6 @@
1
- import { writeFile } from 'node:fs/promises';
1
+ import { mkdir, writeFile } from 'node:fs/promises';
2
2
  import { join, relative } from 'path';
3
3
  import type {
4
- BuildManifest,
5
4
  CronInfo,
6
5
  FunctionInfo,
7
6
  RouteInfo,
@@ -10,26 +9,99 @@ import type {
10
9
 
11
10
  const logger = console;
12
11
 
13
- export async function generateManifests(
12
+ export type ManifestProvider = 'aws' | 'server';
13
+
14
+ export interface ServerAppInfo {
15
+ handler: string;
16
+ endpoints: string;
17
+ }
18
+
19
+ export async function generateAwsManifest(
14
20
  outputDir: string,
15
21
  routes: RouteInfo[],
16
22
  functions: FunctionInfo[],
17
23
  crons: CronInfo[],
18
24
  subscribers: SubscriberInfo[],
19
25
  ): Promise<void> {
20
- // Generate unified manifest for all providers
21
- const manifest: BuildManifest = {
22
- routes,
23
- functions,
24
- crons,
25
- subscribers,
26
- };
26
+ const manifestDir = join(outputDir, 'manifest');
27
+ await mkdir(manifestDir, { recursive: true });
28
+
29
+ // Filter out 'ALL' method routes (server-specific)
30
+ const awsRoutes = routes.filter((r) => r.method !== 'ALL');
31
+
32
+ const content = `export const manifest = {
33
+ routes: ${JSON.stringify(awsRoutes, null, 2)},
34
+ functions: ${JSON.stringify(functions, null, 2)},
35
+ crons: ${JSON.stringify(crons, null, 2)},
36
+ subscribers: ${JSON.stringify(subscribers, null, 2)},
37
+ } as const;
38
+
39
+ // Derived types
40
+ export type Route = (typeof manifest.routes)[number];
41
+ export type Function = (typeof manifest.functions)[number];
42
+ export type Cron = (typeof manifest.crons)[number];
43
+ export type Subscriber = (typeof manifest.subscribers)[number];
44
+
45
+ // Useful union types
46
+ export type Authorizer = Route['authorizer'];
47
+ export type HttpMethod = Route['method'];
48
+ export type RoutePath = Route['path'];
49
+ `;
50
+
51
+ const manifestPath = join(manifestDir, 'aws.ts');
52
+ await writeFile(manifestPath, content);
53
+
54
+ logger.log(
55
+ `Generated AWS manifest with ${awsRoutes.length} routes, ${functions.length} functions, ${crons.length} crons, ${subscribers.length} subscribers`,
56
+ );
57
+ logger.log(`Manifest: ${relative(process.cwd(), manifestPath)}`);
58
+ }
59
+
60
+ export async function generateServerManifest(
61
+ outputDir: string,
62
+ appInfo: ServerAppInfo,
63
+ routes: RouteInfo[],
64
+ subscribers: SubscriberInfo[],
65
+ ): Promise<void> {
66
+ const manifestDir = join(outputDir, 'manifest');
67
+ await mkdir(manifestDir, { recursive: true });
68
+
69
+ // For server, extract route metadata (path, method, authorizer)
70
+ const serverRoutes = routes
71
+ .filter((r) => r.method !== 'ALL')
72
+ .map((r) => ({
73
+ path: r.path,
74
+ method: r.method,
75
+ authorizer: r.authorizer,
76
+ }));
77
+
78
+ // Server subscribers only need name and events
79
+ const serverSubscribers = subscribers.map((s) => ({
80
+ name: s.name,
81
+ subscribedEvents: s.subscribedEvents,
82
+ }));
83
+
84
+ const content = `export const manifest = {
85
+ app: ${JSON.stringify(appInfo, null, 2)},
86
+ routes: ${JSON.stringify(serverRoutes, null, 2)},
87
+ subscribers: ${JSON.stringify(serverSubscribers, null, 2)},
88
+ } as const;
89
+
90
+ // Derived types
91
+ export type Route = (typeof manifest.routes)[number];
92
+ export type Subscriber = (typeof manifest.subscribers)[number];
93
+
94
+ // Useful union types
95
+ export type Authorizer = Route['authorizer'];
96
+ export type HttpMethod = Route['method'];
97
+ export type RoutePath = Route['path'];
98
+ `;
27
99
 
28
- const manifestPath = join(outputDir, 'manifest.json');
29
- await writeFile(manifestPath, JSON.stringify(manifest, null, 2));
100
+ const manifestPath = join(manifestDir, 'server.ts');
101
+ await writeFile(manifestPath, content);
30
102
 
31
103
  logger.log(
32
- `\nGenerated unified manifest with ${routes.length} routes, ${functions.length} functions, ${crons.length} crons, ${subscribers.length} subscribers`,
104
+ `Generated server manifest with ${serverRoutes.length} routes, ${serverSubscribers.length} subscribers`,
33
105
  );
34
106
  logger.log(`Manifest: ${relative(process.cwd(), manifestPath)}`);
35
107
  }
@@ -1,5 +1,6 @@
1
- import type { Cron, Function } from '@geekmidas/constructs';
2
- import type { Endpoint } from '@geekmidas/constructs';
1
+ import type { Cron } from '@geekmidas/constructs/crons';
2
+ import type { Endpoint } from '@geekmidas/constructs/endpoints';
3
+ import type { Function } from '@geekmidas/constructs/functions';
3
4
 
4
5
  import type { CronInfo, FunctionInfo, RouteInfo } from '../types';
5
6
 
@@ -23,11 +24,21 @@ export interface ProcessedCron {
23
24
  schedule?: string;
24
25
  }
25
26
 
27
+ export interface NormalizedTelescopeConfig {
28
+ enabled: boolean;
29
+ path: string;
30
+ ignore: string[];
31
+ recordBody: boolean;
32
+ maxEntries: number;
33
+ websocket: boolean;
34
+ }
35
+
26
36
  export interface BuildContext {
27
37
  envParserPath: string;
28
38
  envParserImportPattern: string;
29
39
  loggerPath: string;
30
40
  loggerImportPattern: string;
41
+ telescope?: NormalizedTelescopeConfig;
31
42
  }
32
43
 
33
44
  export interface ProviderBuildResult {
package/src/config.ts CHANGED
@@ -2,12 +2,14 @@ import { existsSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import type { GkmConfig } from './types.ts';
4
4
 
5
- export async function loadConfig(): Promise<GkmConfig> {
5
+ export async function loadConfig(
6
+ cwd: string = process.cwd(),
7
+ ): Promise<GkmConfig> {
6
8
  const files = ['gkm.config.json', 'gkm.config.ts', 'gkm.config.js'];
7
9
  let configPath = '';
8
10
 
9
11
  for (const file of files) {
10
- const path = join(process.cwd(), file);
12
+ const path = join(cwd, file);
11
13
  if (existsSync(path)) {
12
14
  configPath = path;
13
15
  break;