@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.
- package/README.md +488 -71
- package/dist/{EndpointGenerator-C73wNoih.cjs → EndpointGenerator-BxNCkus4.cjs} +60 -6
- package/dist/EndpointGenerator-BxNCkus4.cjs.map +1 -0
- package/dist/{EndpointGenerator-CWh18d92.mjs → EndpointGenerator-CzDhG7Or.mjs} +60 -6
- package/dist/EndpointGenerator-CzDhG7Or.mjs.map +1 -0
- package/dist/OpenApiTsGenerator-NBNEoaeO.cjs +501 -0
- package/dist/OpenApiTsGenerator-NBNEoaeO.cjs.map +1 -0
- package/dist/OpenApiTsGenerator-q3aWNkuM.mjs +495 -0
- package/dist/OpenApiTsGenerator-q3aWNkuM.mjs.map +1 -0
- package/dist/build/index.cjs +4 -4
- package/dist/build/index.mjs +4 -4
- package/dist/build/manifests.cjs +3 -2
- package/dist/build/manifests.mjs +2 -2
- package/dist/{build-BVng9MQX.cjs → build-CWtHnJMQ.cjs} +19 -17
- package/dist/build-CWtHnJMQ.cjs.map +1 -0
- package/dist/{build-BqexeI-W.mjs → build-DyDgu_D1.mjs} +20 -18
- package/dist/build-DyDgu_D1.mjs.map +1 -0
- package/dist/{config-U-mdW-7Y.mjs → config-AFmFKmU0.mjs} +3 -3
- package/dist/config-AFmFKmU0.mjs.map +1 -0
- package/dist/{config-D1EpSGk6.cjs → config-BVIJpAsa.cjs} +3 -3
- package/dist/config-BVIJpAsa.cjs.map +1 -0
- package/dist/config.cjs +1 -1
- package/dist/config.mjs +1 -1
- package/dist/dev/index.cjs +5 -4
- package/dist/dev/index.mjs +4 -4
- package/dist/{dev-DbtyToc7.cjs → dev-CgDYC4o8.cjs} +95 -31
- package/dist/dev-CgDYC4o8.cjs.map +1 -0
- package/dist/{dev-DnGYXuMn.mjs → dev-CpA8AQPX.mjs} +90 -32
- package/dist/dev-CpA8AQPX.mjs.map +1 -0
- package/dist/generators/EndpointGenerator.cjs +1 -1
- package/dist/generators/EndpointGenerator.mjs +1 -1
- package/dist/generators/OpenApiTsGenerator.cjs +3 -0
- package/dist/generators/OpenApiTsGenerator.mjs +3 -0
- package/dist/generators/index.cjs +1 -1
- package/dist/generators/index.mjs +1 -1
- package/dist/index.cjs +16 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +16 -10
- package/dist/index.mjs.map +1 -1
- package/dist/manifests-C2eMoMUm.mjs +68 -0
- package/dist/manifests-C2eMoMUm.mjs.map +1 -0
- package/dist/manifests-CK1VV_pM.cjs +80 -0
- package/dist/manifests-CK1VV_pM.cjs.map +1 -0
- package/dist/openapi-DRTRGhTt.mjs +50 -0
- package/dist/openapi-DRTRGhTt.mjs.map +1 -0
- package/dist/openapi-DhK4b0lB.cjs +56 -0
- package/dist/openapi-DhK4b0lB.cjs.map +1 -0
- package/dist/openapi.cjs +4 -3
- package/dist/openapi.mjs +4 -3
- package/docs/OPENAPI_TYPESCRIPT_DESIGN.md +408 -0
- package/docs/manifest-refactor-design.md +287 -0
- package/package.json +10 -3
- package/src/__tests__/openapi.spec.ts +78 -63
- package/src/build/__tests__/index-new.spec.ts +43 -72
- package/src/build/__tests__/manifests.spec.ts +346 -0
- package/src/build/index.ts +59 -62
- package/src/build/manifests.ts +85 -13
- package/src/build/types.ts +13 -2
- package/src/config.ts +4 -2
- package/src/dev/__tests__/index.spec.ts +98 -1
- package/src/dev/index.ts +152 -25
- package/src/generators/EndpointGenerator.ts +69 -5
- package/src/generators/OpenApiTsGenerator.ts +798 -0
- package/src/index.ts +6 -3
- package/src/openapi.ts +36 -15
- package/src/types.ts +23 -7
- package/dist/EndpointGenerator-C73wNoih.cjs.map +0 -1
- package/dist/EndpointGenerator-CWh18d92.mjs.map +0 -1
- package/dist/build-BVng9MQX.cjs.map +0 -1
- package/dist/build-BqexeI-W.mjs.map +0 -1
- package/dist/config-D1EpSGk6.cjs.map +0 -1
- package/dist/config-U-mdW-7Y.mjs.map +0 -1
- package/dist/dev-DbtyToc7.cjs.map +0 -1
- package/dist/dev-DnGYXuMn.mjs.map +0 -1
- package/dist/manifests-BrJXpHrf.mjs +0 -21
- package/dist/manifests-BrJXpHrf.mjs.map +0 -1
- package/dist/manifests-D0saShvH.cjs +0 -27
- package/dist/manifests-D0saShvH.cjs.map +0 -1
- package/dist/openapi-BTHbPrxS.mjs +0 -36
- package/dist/openapi-BTHbPrxS.mjs.map +0 -1
- package/dist/openapi-CewcfoRH.cjs +0 -42
- package/dist/openapi-CewcfoRH.cjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geekmidas/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs",
|
|
4
5
|
"private": false,
|
|
5
6
|
"type": "module",
|
|
6
7
|
"exports": {
|
|
@@ -44,11 +45,17 @@
|
|
|
44
45
|
"@geekmidas/testkit": "0.0.17"
|
|
45
46
|
},
|
|
46
47
|
"peerDependencies": {
|
|
47
|
-
"@geekmidas/constructs": "~0.0
|
|
48
|
-
"@geekmidas/envkit": "~0.0
|
|
48
|
+
"@geekmidas/constructs": "~0.1.0",
|
|
49
|
+
"@geekmidas/envkit": "~0.1.0",
|
|
49
50
|
"@geekmidas/logger": "~0.0.1",
|
|
51
|
+
"@geekmidas/telescope": "~0.0.1",
|
|
50
52
|
"@geekmidas/schema": "~0.0.2"
|
|
51
53
|
},
|
|
54
|
+
"peerDependenciesMeta": {
|
|
55
|
+
"@geekmidas/telescope": {
|
|
56
|
+
"optional": true
|
|
57
|
+
}
|
|
58
|
+
},
|
|
52
59
|
"scripts": {
|
|
53
60
|
"ts": "tsc --noEmit --skipLibCheck src/**/*.ts",
|
|
54
61
|
"test": "vitest",
|
|
@@ -22,9 +22,8 @@ describe('OpenAPI Generation', () => {
|
|
|
22
22
|
vi.restoreAllMocks();
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
describe('openapiCommand', () => {
|
|
26
|
-
it('should generate
|
|
27
|
-
// Create endpoint file
|
|
25
|
+
describe('openapiCommand - TypeScript output (default)', () => {
|
|
26
|
+
it('should generate TypeScript module by default', async () => {
|
|
28
27
|
await createMockEndpointFile(
|
|
29
28
|
tempDir,
|
|
30
29
|
'getUser.ts',
|
|
@@ -33,7 +32,6 @@ describe('OpenAPI Generation', () => {
|
|
|
33
32
|
'GET',
|
|
34
33
|
);
|
|
35
34
|
|
|
36
|
-
// Create config file
|
|
37
35
|
await createTestFile(
|
|
38
36
|
tempDir,
|
|
39
37
|
'gkm.config.json',
|
|
@@ -42,56 +40,58 @@ describe('OpenAPI Generation', () => {
|
|
|
42
40
|
}),
|
|
43
41
|
);
|
|
44
42
|
|
|
45
|
-
const outputPath = join(tempDir, 'openapi.
|
|
46
|
-
|
|
47
|
-
// Mock process.cwd
|
|
48
|
-
vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
|
|
43
|
+
const outputPath = join(tempDir, 'openapi.ts');
|
|
49
44
|
|
|
50
|
-
await openapiCommand({ output: outputPath });
|
|
45
|
+
await openapiCommand({ output: outputPath, cwd: tempDir });
|
|
51
46
|
|
|
52
|
-
// Verify file was created
|
|
53
47
|
expect(existsSync(outputPath)).toBe(true);
|
|
54
48
|
|
|
55
|
-
// Verify content
|
|
56
49
|
const content = await readFile(outputPath, 'utf-8');
|
|
57
|
-
const spec = JSON.parse(content);
|
|
58
50
|
|
|
59
|
-
expect(
|
|
60
|
-
expect(
|
|
61
|
-
expect(
|
|
62
|
-
expect(
|
|
63
|
-
expect(Object.keys(spec.paths).length).toBeGreaterThan(0);
|
|
51
|
+
expect(content).toContain('// Auto-generated by @geekmidas/cli');
|
|
52
|
+
expect(content).toContain('export const securitySchemes');
|
|
53
|
+
expect(content).toContain('export const endpointAuth');
|
|
54
|
+
expect(content).toContain('export interface paths');
|
|
64
55
|
});
|
|
65
56
|
|
|
66
|
-
it('should
|
|
67
|
-
|
|
57
|
+
it('should include endpoint auth map', async () => {
|
|
58
|
+
await createMockEndpointFile(
|
|
59
|
+
tempDir,
|
|
60
|
+
'getUser.ts',
|
|
61
|
+
'getUser',
|
|
62
|
+
'/users/:id',
|
|
63
|
+
'GET',
|
|
64
|
+
);
|
|
65
|
+
|
|
68
66
|
await createTestFile(
|
|
69
67
|
tempDir,
|
|
70
68
|
'gkm.config.json',
|
|
71
69
|
JSON.stringify({
|
|
72
|
-
routes: [`${tempDir}
|
|
70
|
+
routes: [`${tempDir}/**/*.ts`],
|
|
73
71
|
}),
|
|
74
72
|
);
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
const consoleSpy = vi.spyOn(console, 'log');
|
|
74
|
+
const outputPath = join(tempDir, 'openapi.ts');
|
|
78
75
|
|
|
79
|
-
await openapiCommand({ output:
|
|
76
|
+
await openapiCommand({ output: outputPath, cwd: tempDir });
|
|
80
77
|
|
|
81
|
-
|
|
78
|
+
const content = await readFile(outputPath, 'utf-8');
|
|
79
|
+
|
|
80
|
+
expect(content).toContain('endpointAuth');
|
|
81
|
+
expect(content).toContain("'GET /users/{id}'");
|
|
82
82
|
});
|
|
83
|
+
});
|
|
83
84
|
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
describe('openapiCommand - JSON output (legacy)', () => {
|
|
86
|
+
it('should generate JSON OpenAPI spec with --json flag', async () => {
|
|
86
87
|
await createMockEndpointFile(
|
|
87
88
|
tempDir,
|
|
88
|
-
'
|
|
89
|
-
'
|
|
90
|
-
'/
|
|
89
|
+
'getUser.ts',
|
|
90
|
+
'getUser',
|
|
91
|
+
'/users/:id',
|
|
91
92
|
'GET',
|
|
92
93
|
);
|
|
93
94
|
|
|
94
|
-
// Create config
|
|
95
95
|
await createTestFile(
|
|
96
96
|
tempDir,
|
|
97
97
|
'gkm.config.json',
|
|
@@ -100,16 +100,43 @@ describe('OpenAPI Generation', () => {
|
|
|
100
100
|
}),
|
|
101
101
|
);
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
const outputPath = join(tempDir, 'openapi.json');
|
|
104
|
+
|
|
105
|
+
await openapiCommand({ output: outputPath, json: true, cwd: tempDir });
|
|
106
|
+
|
|
107
|
+
expect(existsSync(outputPath)).toBe(true);
|
|
108
|
+
|
|
109
|
+
const content = await readFile(outputPath, 'utf-8');
|
|
110
|
+
const spec = JSON.parse(content);
|
|
111
|
+
|
|
112
|
+
expect(spec).toHaveProperty('openapi');
|
|
113
|
+
expect(spec).toHaveProperty('info');
|
|
114
|
+
expect(spec.info.title).toBe('API Documentation');
|
|
115
|
+
expect(spec).toHaveProperty('paths');
|
|
116
|
+
expect(Object.keys(spec.paths).length).toBeGreaterThan(0);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should handle no endpoints found', async () => {
|
|
120
|
+
await createTestFile(
|
|
121
|
+
tempDir,
|
|
122
|
+
'gkm.config.json',
|
|
123
|
+
JSON.stringify({
|
|
124
|
+
routes: [`${tempDir}/nonexistent/**/*.ts`],
|
|
125
|
+
}),
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const consoleSpy = vi.spyOn(console, 'log');
|
|
104
129
|
|
|
105
|
-
await openapiCommand(
|
|
130
|
+
await openapiCommand({
|
|
131
|
+
output: join(tempDir, 'openapi.json'),
|
|
132
|
+
json: true,
|
|
133
|
+
cwd: tempDir,
|
|
134
|
+
});
|
|
106
135
|
|
|
107
|
-
|
|
108
|
-
expect(existsSync(join(tempDir, 'openapi.json'))).toBe(true);
|
|
136
|
+
expect(consoleSpy).toHaveBeenCalledWith('No valid endpoints found');
|
|
109
137
|
});
|
|
110
138
|
|
|
111
139
|
it('should generate spec with multiple endpoints', async () => {
|
|
112
|
-
// Create multiple endpoint files
|
|
113
140
|
await createMockEndpointFile(
|
|
114
141
|
tempDir,
|
|
115
142
|
'getUsers.ts',
|
|
@@ -132,7 +159,6 @@ describe('OpenAPI Generation', () => {
|
|
|
132
159
|
'DELETE',
|
|
133
160
|
);
|
|
134
161
|
|
|
135
|
-
// Create config
|
|
136
162
|
await createTestFile(
|
|
137
163
|
tempDir,
|
|
138
164
|
'gkm.config.json',
|
|
@@ -142,19 +168,16 @@ describe('OpenAPI Generation', () => {
|
|
|
142
168
|
);
|
|
143
169
|
|
|
144
170
|
const outputPath = join(tempDir, 'openapi.json');
|
|
145
|
-
vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
|
|
146
171
|
|
|
147
|
-
await openapiCommand({ output: outputPath });
|
|
172
|
+
await openapiCommand({ output: outputPath, json: true, cwd: tempDir });
|
|
148
173
|
|
|
149
174
|
const content = await readFile(outputPath, 'utf-8');
|
|
150
175
|
const spec = JSON.parse(content);
|
|
151
176
|
|
|
152
|
-
// Should have multiple paths
|
|
153
177
|
expect(Object.keys(spec.paths).length).toBeGreaterThanOrEqual(1);
|
|
154
178
|
});
|
|
155
179
|
|
|
156
180
|
it('should create output directory if it does not exist', async () => {
|
|
157
|
-
// Create endpoint file
|
|
158
181
|
await createMockEndpointFile(
|
|
159
182
|
tempDir,
|
|
160
183
|
'endpoint.ts',
|
|
@@ -163,7 +186,6 @@ describe('OpenAPI Generation', () => {
|
|
|
163
186
|
'GET',
|
|
164
187
|
);
|
|
165
188
|
|
|
166
|
-
// Create config
|
|
167
189
|
await createTestFile(
|
|
168
190
|
tempDir,
|
|
169
191
|
'gkm.config.json',
|
|
@@ -173,15 +195,13 @@ describe('OpenAPI Generation', () => {
|
|
|
173
195
|
);
|
|
174
196
|
|
|
175
197
|
const outputPath = join(tempDir, 'nested', 'dir', 'openapi.json');
|
|
176
|
-
vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
|
|
177
198
|
|
|
178
|
-
await openapiCommand({ output: outputPath });
|
|
199
|
+
await openapiCommand({ output: outputPath, json: true, cwd: tempDir });
|
|
179
200
|
|
|
180
201
|
expect(existsSync(outputPath)).toBe(true);
|
|
181
202
|
});
|
|
182
203
|
|
|
183
204
|
it('should include API metadata in spec', async () => {
|
|
184
|
-
// Create endpoint
|
|
185
205
|
await createMockEndpointFile(
|
|
186
206
|
tempDir,
|
|
187
207
|
'endpoint.ts',
|
|
@@ -190,7 +210,6 @@ describe('OpenAPI Generation', () => {
|
|
|
190
210
|
'GET',
|
|
191
211
|
);
|
|
192
212
|
|
|
193
|
-
// Create config
|
|
194
213
|
await createTestFile(
|
|
195
214
|
tempDir,
|
|
196
215
|
'gkm.config.json',
|
|
@@ -200,9 +219,8 @@ describe('OpenAPI Generation', () => {
|
|
|
200
219
|
);
|
|
201
220
|
|
|
202
221
|
const outputPath = join(tempDir, 'openapi.json');
|
|
203
|
-
vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
|
|
204
222
|
|
|
205
|
-
await openapiCommand({ output: outputPath });
|
|
223
|
+
await openapiCommand({ output: outputPath, json: true, cwd: tempDir });
|
|
206
224
|
|
|
207
225
|
const content = await readFile(outputPath, 'utf-8');
|
|
208
226
|
const spec = JSON.parse(content);
|
|
@@ -214,7 +232,7 @@ describe('OpenAPI Generation', () => {
|
|
|
214
232
|
});
|
|
215
233
|
});
|
|
216
234
|
|
|
217
|
-
it('should log generation success', async () => {
|
|
235
|
+
it('should log generation success for JSON', async () => {
|
|
218
236
|
// Create endpoint
|
|
219
237
|
await createMockEndpointFile(
|
|
220
238
|
tempDir,
|
|
@@ -234,13 +252,12 @@ describe('OpenAPI Generation', () => {
|
|
|
234
252
|
);
|
|
235
253
|
|
|
236
254
|
const outputPath = join(tempDir, 'openapi.json');
|
|
237
|
-
vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
|
|
238
255
|
const consoleSpy = vi.spyOn(console, 'log');
|
|
239
256
|
|
|
240
|
-
await openapiCommand({ output: outputPath });
|
|
257
|
+
await openapiCommand({ output: outputPath, json: true, cwd: tempDir });
|
|
241
258
|
|
|
242
259
|
expect(consoleSpy).toHaveBeenCalledWith(
|
|
243
|
-
expect.stringContaining('OpenAPI spec generated'),
|
|
260
|
+
expect.stringContaining('OpenAPI JSON spec generated'),
|
|
244
261
|
);
|
|
245
262
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Found'));
|
|
246
263
|
expect(consoleSpy).toHaveBeenCalledWith(
|
|
@@ -250,11 +267,9 @@ describe('OpenAPI Generation', () => {
|
|
|
250
267
|
|
|
251
268
|
it('should throw error when config loading fails', async () => {
|
|
252
269
|
// No config file created
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
/OpenAPI generation failed/,
|
|
257
|
-
);
|
|
270
|
+
await expect(
|
|
271
|
+
openapiCommand({ json: true, cwd: tempDir }),
|
|
272
|
+
).rejects.toThrow(/OpenAPI generation failed/);
|
|
258
273
|
});
|
|
259
274
|
|
|
260
275
|
it('should throw error for invalid TypeScript files', async () => {
|
|
@@ -274,11 +289,13 @@ describe('OpenAPI Generation', () => {
|
|
|
274
289
|
}),
|
|
275
290
|
);
|
|
276
291
|
|
|
277
|
-
vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
|
|
278
|
-
|
|
279
292
|
// Should throw error for syntax errors
|
|
280
293
|
await expect(
|
|
281
|
-
openapiCommand({
|
|
294
|
+
openapiCommand({
|
|
295
|
+
output: join(tempDir, 'openapi.json'),
|
|
296
|
+
json: true,
|
|
297
|
+
cwd: tempDir,
|
|
298
|
+
}),
|
|
282
299
|
).rejects.toThrow(/OpenAPI generation failed/);
|
|
283
300
|
});
|
|
284
301
|
|
|
@@ -302,9 +319,8 @@ describe('OpenAPI Generation', () => {
|
|
|
302
319
|
);
|
|
303
320
|
|
|
304
321
|
const outputPath = join(tempDir, 'openapi.json');
|
|
305
|
-
vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
|
|
306
322
|
|
|
307
|
-
await openapiCommand({ output: outputPath });
|
|
323
|
+
await openapiCommand({ output: outputPath, json: true, cwd: tempDir });
|
|
308
324
|
|
|
309
325
|
const content = await readFile(outputPath, 'utf-8');
|
|
310
326
|
|
|
@@ -348,9 +364,8 @@ export const complexEndpoint = e
|
|
|
348
364
|
);
|
|
349
365
|
|
|
350
366
|
const outputPath = join(tempDir, 'openapi.json');
|
|
351
|
-
vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
|
|
352
367
|
|
|
353
|
-
await openapiCommand({ output: outputPath });
|
|
368
|
+
await openapiCommand({ output: outputPath, json: true, cwd: tempDir });
|
|
354
369
|
|
|
355
370
|
const content = await readFile(outputPath, 'utf-8');
|
|
356
371
|
const spec = JSON.parse(content);
|
|
@@ -82,6 +82,20 @@ export default {
|
|
|
82
82
|
'utf-8',
|
|
83
83
|
);
|
|
84
84
|
expect(endpointsContent).toContain('HonoEndpoint');
|
|
85
|
+
|
|
86
|
+
// Verify server manifest was created at .gkm/manifest/server.ts
|
|
87
|
+
const manifestPath = join(dir, '.gkm', 'manifest', 'server.ts');
|
|
88
|
+
const manifestContent = await readFile(manifestPath, 'utf-8');
|
|
89
|
+
|
|
90
|
+
// Verify manifest structure
|
|
91
|
+
expect(manifestContent).toContain('export const manifest = {');
|
|
92
|
+
expect(manifestContent).toContain('} as const;');
|
|
93
|
+
expect(manifestContent).toContain('app:');
|
|
94
|
+
expect(manifestContent).toContain('routes:');
|
|
95
|
+
|
|
96
|
+
// Verify derived types are exported
|
|
97
|
+
expect(manifestContent).toContain('export type Route =');
|
|
98
|
+
expect(manifestContent).toContain('export type Authorizer =');
|
|
85
99
|
} finally {
|
|
86
100
|
process.chdir(originalCwd);
|
|
87
101
|
}
|
|
@@ -202,78 +216,35 @@ export default {
|
|
|
202
216
|
),
|
|
203
217
|
).toContain('AmazonApiGatewayV2Endpoint');
|
|
204
218
|
|
|
205
|
-
// Verify
|
|
206
|
-
const manifestPath = join(dir, '.gkm', 'manifest.
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
// Verify manifest
|
|
210
|
-
expect(
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
path: '/posts',
|
|
235
|
-
method: 'POST',
|
|
236
|
-
handler: expect.stringContaining('getPostsEndpoint.handler'),
|
|
237
|
-
}),
|
|
238
|
-
]),
|
|
239
|
-
functions: expect.arrayContaining([
|
|
240
|
-
expect.objectContaining({
|
|
241
|
-
name: 'processDataFunction',
|
|
242
|
-
handler: expect.stringContaining(
|
|
243
|
-
'functions/processDataFunction.handler',
|
|
244
|
-
),
|
|
245
|
-
timeout: 300,
|
|
246
|
-
}),
|
|
247
|
-
expect.objectContaining({
|
|
248
|
-
name: 'sendEmailFunction',
|
|
249
|
-
handler: expect.stringContaining(
|
|
250
|
-
'functions/sendEmailFunction.handler',
|
|
251
|
-
),
|
|
252
|
-
timeout: 30,
|
|
253
|
-
}),
|
|
254
|
-
]),
|
|
255
|
-
crons: expect.arrayContaining([
|
|
256
|
-
expect.objectContaining({
|
|
257
|
-
name: 'dailyCleanupCron',
|
|
258
|
-
handler: expect.stringContaining(
|
|
259
|
-
'crons/dailyCleanupCron.handler',
|
|
260
|
-
),
|
|
261
|
-
schedule: 'rate(1 day)',
|
|
262
|
-
}),
|
|
263
|
-
expect.objectContaining({
|
|
264
|
-
name: 'hourlyReportCron',
|
|
265
|
-
handler: expect.stringContaining(
|
|
266
|
-
'crons/hourlyReportCron.handler',
|
|
267
|
-
),
|
|
268
|
-
schedule: 'cron(0 * * * ? *)',
|
|
269
|
-
}),
|
|
270
|
-
]),
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
// Verify counts - should have duplicated routes (one for each provider)
|
|
274
|
-
expect(manifest.routes).toHaveLength(4); // 2 routes x 2 providers
|
|
275
|
-
expect(manifest.functions).toHaveLength(2);
|
|
276
|
-
expect(manifest.crons).toHaveLength(2);
|
|
219
|
+
// Verify AWS manifest was created at .gkm/manifest/aws.ts
|
|
220
|
+
const manifestPath = join(dir, '.gkm', 'manifest', 'aws.ts');
|
|
221
|
+
const manifestContent = await readFile(manifestPath, 'utf-8');
|
|
222
|
+
|
|
223
|
+
// Verify manifest is TypeScript with as const
|
|
224
|
+
expect(manifestContent).toContain('export const manifest = {');
|
|
225
|
+
expect(manifestContent).toContain('} as const;');
|
|
226
|
+
|
|
227
|
+
// Verify derived types are exported
|
|
228
|
+
expect(manifestContent).toContain('export type Route =');
|
|
229
|
+
expect(manifestContent).toContain('export type Function =');
|
|
230
|
+
expect(manifestContent).toContain('export type Cron =');
|
|
231
|
+
expect(manifestContent).toContain('export type Authorizer =');
|
|
232
|
+
|
|
233
|
+
// Verify routes are included (JSON.stringify output uses quoted keys/values)
|
|
234
|
+
expect(manifestContent).toContain('/users');
|
|
235
|
+
expect(manifestContent).toContain('/posts');
|
|
236
|
+
expect(manifestContent).toContain('GET');
|
|
237
|
+
expect(manifestContent).toContain('POST');
|
|
238
|
+
|
|
239
|
+
// Verify functions are included
|
|
240
|
+
expect(manifestContent).toContain('processDataFunction');
|
|
241
|
+
expect(manifestContent).toContain('sendEmailFunction');
|
|
242
|
+
|
|
243
|
+
// Verify crons are included
|
|
244
|
+
expect(manifestContent).toContain('dailyCleanupCron');
|
|
245
|
+
expect(manifestContent).toContain('hourlyReportCron');
|
|
246
|
+
expect(manifestContent).toContain('rate(1 day)');
|
|
247
|
+
expect(manifestContent).toContain('cron(0 * * * ? *)');
|
|
277
248
|
} finally {
|
|
278
249
|
process.chdir(originalCwd);
|
|
279
250
|
}
|