lambder 2.0.18 → 3.0.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 +162 -41
- package/dist/Lambder.d.ts +154 -46
- package/dist/Lambder.js +312 -166
- package/dist/LambderCaller.js +6 -3
- package/dist/LambderContext.d.ts +20 -9
- package/dist/LambderContext.js +57 -17
- package/dist/LambderCors.d.ts +12 -0
- package/dist/LambderCors.js +30 -0
- package/dist/LambderHtml.d.ts +33 -0
- package/dist/LambderHtml.js +62 -0
- package/dist/LambderMSW.d.ts +16 -1
- package/dist/LambderMSW.js +5 -9
- package/dist/LambderPublicFiles.d.ts +47 -0
- package/dist/LambderPublicFiles.js +108 -0
- package/dist/LambderResolver.d.ts +30 -31
- package/dist/LambderResolver.js +29 -43
- package/dist/LambderResponse.d.ts +71 -0
- package/dist/LambderResponse.js +196 -0
- package/dist/LambderResponseBuilder.d.ts +58 -33
- package/dist/LambderResponseBuilder.js +114 -167
- package/dist/LambderRouting.d.ts +23 -0
- package/dist/LambderRouting.js +67 -0
- package/dist/LambderSessionController.d.ts +13 -1
- package/dist/LambderSessionController.js +33 -10
- package/dist/LambderSessionManager.d.ts +3 -1
- package/dist/LambderSessionManager.js +15 -6
- package/dist/LambderTemplatingEngine.d.ts +87 -0
- package/dist/LambderTemplatingEngine.js +156 -0
- package/dist/index.d.ts +14 -2
- package/dist/index.js +10 -1
- package/dist/node-polyfills.d.ts +4 -2
- package/dist/node-polyfills.js +28 -0
- package/package.json +7 -5
- package/.eslintrc.cjs +0 -26
- package/.vscode/settings.json +0 -26
- package/deploy +0 -22
- package/dist/LambderUtils.d.ts +0 -10
- package/dist/LambderUtils.js +0 -70
- package/docs/DYNAMODB_SETUP.md +0 -96
- package/docs/LAMBDER_MSW.md +0 -409
- package/docs/TYPE_SAFE_QUICK_START.md +0 -77
- package/examples/msw-testing-example.ts +0 -280
- package/examples/secure-session-example.ts +0 -207
- package/examples/zod-chained-api-example.ts +0 -63
- package/src/Lambder.ts +0 -430
- package/src/LambderApiContract.ts +0 -20
- package/src/LambderCaller.ts +0 -238
- package/src/LambderContext.ts +0 -78
- package/src/LambderMSW.ts +0 -180
- package/src/LambderResolver.ts +0 -101
- package/src/LambderResponseBuilder.ts +0 -332
- package/src/LambderSessionController.ts +0 -114
- package/src/LambderSessionManager.ts +0 -217
- package/src/LambderUtils.ts +0 -75
- package/src/index.ts +0 -17
- package/src/node-polyfills.ts +0 -27
- package/tests/error-handling.test.ts +0 -585
- package/tests/file-serving.test.ts +0 -194
- package/tests/fixtures/public/index.html +0 -1
- package/tests/fixtures/public/main.css +0 -1
- package/tests/hooks.test.ts +0 -561
- package/tests/output-type-runtime.test.ts +0 -381
- package/tests/redirect.test.ts +0 -88
- package/tests/routes.test.ts +0 -543
- package/tests/session.test.ts +0 -1083
- package/tests/use-plugin.test.ts +0 -460
- package/tsconfig.json +0 -24
package/docs/LAMBDER_MSW.md
DELETED
|
@@ -1,409 +0,0 @@
|
|
|
1
|
-
# LambderMSW - Mock Service Worker Integration
|
|
2
|
-
|
|
3
|
-
LambderMSW provides seamless integration with [MSW (Mock Service Worker)](https://mswjs.io/) for testing your Lambder APIs. It allows you to mock API endpoints with full type safety when using TypeScript API contracts.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
First, install MSW as a dev dependency:
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install msw --save-dev
|
|
11
|
-
# or
|
|
12
|
-
yarn add msw --dev
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Basic Setup
|
|
16
|
-
|
|
17
|
-
```typescript
|
|
18
|
-
import { LambderMSW } from 'lambder';
|
|
19
|
-
import { setupServer } from 'msw/node';
|
|
20
|
-
|
|
21
|
-
// Create an MSW instance
|
|
22
|
-
const lambderMSW = new LambderMSW({
|
|
23
|
-
apiPath: '/secure', // Must match your Lambder backend apiPath
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
// Create mock handlers
|
|
27
|
-
const handlers = [
|
|
28
|
-
lambderMSW.mockApi('getUserById', async (payload) => {
|
|
29
|
-
return {
|
|
30
|
-
id: payload.userId,
|
|
31
|
-
name: 'John Doe',
|
|
32
|
-
email: 'john@example.com'
|
|
33
|
-
};
|
|
34
|
-
})
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
// Setup MSW server
|
|
38
|
-
const server = setupServer(...handlers);
|
|
39
|
-
|
|
40
|
-
// Start server before tests
|
|
41
|
-
beforeAll(() => server.listen());
|
|
42
|
-
afterEach(() => server.resetHandlers());
|
|
43
|
-
afterAll(() => server.close());
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Type-Safe Mocking
|
|
47
|
-
|
|
48
|
-
When using TypeScript API contracts, LambderMSW provides full type safety:
|
|
49
|
-
|
|
50
|
-
```typescript
|
|
51
|
-
// backend/index.ts (define your APIs with Lambder)
|
|
52
|
-
import { z } from 'zod';
|
|
53
|
-
import Lambder from 'lambder';
|
|
54
|
-
|
|
55
|
-
const lambder = new Lambder({ apiPath: '/secure', publicPath: './public' })
|
|
56
|
-
.addApi('getUserById', {
|
|
57
|
-
input: z.object({ userId: z.string() }),
|
|
58
|
-
output: z.object({ id: z.string(), name: z.string(), email: z.string() })
|
|
59
|
-
}, async (ctx, resolver) => {
|
|
60
|
-
// Implementation...
|
|
61
|
-
return resolver.api({ id: ctx.apiPayload.userId, name: 'John', email: 'john@example.com' });
|
|
62
|
-
})
|
|
63
|
-
.addApi('createUser', {
|
|
64
|
-
input: z.object({ name: z.string(), email: z.string() }),
|
|
65
|
-
output: z.object({ id: z.string(), name: z.string(), email: z.string() })
|
|
66
|
-
}, async (ctx, resolver) => {
|
|
67
|
-
// Implementation...
|
|
68
|
-
return resolver.api({ id: '123', ...ctx.apiPayload });
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Export the inferred contract type
|
|
72
|
-
export type ApiContractType = typeof lambder.ApiContract;
|
|
73
|
-
|
|
74
|
-
// test/setup.ts
|
|
75
|
-
import { LambderMSW } from 'lambder';
|
|
76
|
-
import type { ApiContractType } from '../backend';
|
|
77
|
-
|
|
78
|
-
const lambderMSW = new LambderMSW<ApiContractType>({
|
|
79
|
-
apiPath: '/secure',
|
|
80
|
-
apiVersion: '1.0.0'
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// Now mockApi is fully typed! ✨
|
|
84
|
-
const handler = lambderMSW.mockApi('getUserById', async (payload) => {
|
|
85
|
-
// payload is automatically typed as { userId: string }
|
|
86
|
-
// Return value is type-checked against output type
|
|
87
|
-
return {
|
|
88
|
-
id: payload.userId,
|
|
89
|
-
name: 'John Doe',
|
|
90
|
-
email: 'john@example.com'
|
|
91
|
-
};
|
|
92
|
-
});
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## API Reference
|
|
96
|
-
|
|
97
|
-
### `new LambderMSW(options)`
|
|
98
|
-
|
|
99
|
-
Creates a new LambderMSW instance.
|
|
100
|
-
|
|
101
|
-
**Parameters:**
|
|
102
|
-
- `apiPath` (string): The API endpoint path (must match your Lambder backend)
|
|
103
|
-
- `apiVersion` (string, optional): API version to include in responses
|
|
104
|
-
|
|
105
|
-
### `mockApi(apiName, handler, options?)`
|
|
106
|
-
|
|
107
|
-
Mock an API endpoint with a custom handler.
|
|
108
|
-
|
|
109
|
-
**Parameters:**
|
|
110
|
-
- `apiName` (string): Name of the API to mock
|
|
111
|
-
- `handler` (function): Async or sync function that returns the mock payload
|
|
112
|
-
- Input: API payload from the request
|
|
113
|
-
- Output: The mocked response payload
|
|
114
|
-
- `options` (object, optional):
|
|
115
|
-
- `versionExpired` (boolean): Simulate version expired error
|
|
116
|
-
- `sessionExpired` (boolean): Simulate session expired error
|
|
117
|
-
- `notAuthorized` (boolean): Simulate not authorized error
|
|
118
|
-
- `message` (any): Custom message to include in response
|
|
119
|
-
- `errorMessage` (any): Error message to include in response
|
|
120
|
-
- `logList` (array): Array of log entries
|
|
121
|
-
- `delay` (number): Artificial delay in milliseconds to simulate network latency
|
|
122
|
-
|
|
123
|
-
**Returns:** MSW RequestHandler
|
|
124
|
-
|
|
125
|
-
**Example:**
|
|
126
|
-
```typescript
|
|
127
|
-
lambderMSW.mockApi('getCompanyPage', async (payload) => {
|
|
128
|
-
return {
|
|
129
|
-
companyName: payload.companyName,
|
|
130
|
-
description: 'Mock company description',
|
|
131
|
-
employees: 100
|
|
132
|
-
};
|
|
133
|
-
}, {
|
|
134
|
-
delay: 500, // Simulate 500ms network delay
|
|
135
|
-
message: 'Data fetched successfully'
|
|
136
|
-
});
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### `mockSessionExpired(apiName)`
|
|
140
|
-
|
|
141
|
-
Mock an API that returns a session expired error.
|
|
142
|
-
|
|
143
|
-
**Parameters:**
|
|
144
|
-
- `apiName` (string): Name of the API to mock
|
|
145
|
-
|
|
146
|
-
**Example:**
|
|
147
|
-
```typescript
|
|
148
|
-
lambderMSW.mockSessionExpired('getProtectedData');
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### `mockVersionExpired(apiName)`
|
|
152
|
-
|
|
153
|
-
Mock an API that returns a version expired error.
|
|
154
|
-
|
|
155
|
-
**Parameters:**
|
|
156
|
-
- `apiName` (string): Name of the API to mock
|
|
157
|
-
|
|
158
|
-
**Example:**
|
|
159
|
-
```typescript
|
|
160
|
-
lambderMSW.mockVersionExpired('getUserProfile');
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
### `mockNotAuthorized(apiName)`
|
|
164
|
-
|
|
165
|
-
Mock an API that returns a not authorized error.
|
|
166
|
-
|
|
167
|
-
**Parameters:**
|
|
168
|
-
- `apiName` (string): Name of the API to mock
|
|
169
|
-
|
|
170
|
-
**Example:**
|
|
171
|
-
```typescript
|
|
172
|
-
lambderMSW.mockNotAuthorized('deleteUser');
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### `mockError(apiName, errorMessage)`
|
|
176
|
-
|
|
177
|
-
Mock an API that returns a custom error message.
|
|
178
|
-
|
|
179
|
-
**Parameters:**
|
|
180
|
-
- `apiName` (string): Name of the API to mock
|
|
181
|
-
- `errorMessage` (string): The error message to return
|
|
182
|
-
|
|
183
|
-
**Example:**
|
|
184
|
-
```typescript
|
|
185
|
-
lambderMSW.mockError('submitOrder', 'Payment processing failed');
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
### `mockWithMessage(apiName, handler, message)`
|
|
189
|
-
|
|
190
|
-
Mock an API with a custom success message.
|
|
191
|
-
|
|
192
|
-
**Parameters:**
|
|
193
|
-
- `apiName` (string): Name of the API to mock
|
|
194
|
-
- `handler` (function): Handler function that returns the mock payload
|
|
195
|
-
- `message` (any): Custom message to include in response
|
|
196
|
-
|
|
197
|
-
**Example:**
|
|
198
|
-
```typescript
|
|
199
|
-
lambderMSW.mockWithMessage('updateProfile', async (payload) => {
|
|
200
|
-
return { userId: payload.userId, updated: true };
|
|
201
|
-
}, 'Profile updated successfully');
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
## Complete Testing Example
|
|
205
|
-
|
|
206
|
-
```typescript
|
|
207
|
-
// test/api.test.ts
|
|
208
|
-
import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest';
|
|
209
|
-
import { setupServer } from 'msw/node';
|
|
210
|
-
import { LambderMSW, LambderCaller } from 'lambder';
|
|
211
|
-
import type { ApiContractType } from '../backend'; // Type-only import from your backend
|
|
212
|
-
|
|
213
|
-
// Setup MSW
|
|
214
|
-
const lambderMSW = new LambderMSW<ApiContractType>({
|
|
215
|
-
apiPath: '/secure',
|
|
216
|
-
apiVersion: '1.0.0'
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
const handlers = [
|
|
220
|
-
lambderMSW.mockApi('getUserById', async (payload) => {
|
|
221
|
-
if (payload.userId === '123') {
|
|
222
|
-
return {
|
|
223
|
-
id: '123',
|
|
224
|
-
name: 'John Doe',
|
|
225
|
-
email: 'john@example.com'
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
return null;
|
|
229
|
-
}),
|
|
230
|
-
|
|
231
|
-
lambderMSW.mockApi('createUser', async (payload) => {
|
|
232
|
-
return {
|
|
233
|
-
id: Math.random().toString(),
|
|
234
|
-
name: payload.name,
|
|
235
|
-
email: payload.email
|
|
236
|
-
};
|
|
237
|
-
}, { delay: 100 }), // Simulate 100ms delay
|
|
238
|
-
|
|
239
|
-
lambderMSW.mockSessionExpired('getProtectedData'),
|
|
240
|
-
|
|
241
|
-
lambderMSW.mockError('failingApi', 'Something went wrong')
|
|
242
|
-
];
|
|
243
|
-
|
|
244
|
-
const server = setupServer(...handlers);
|
|
245
|
-
|
|
246
|
-
beforeAll(() => server.listen());
|
|
247
|
-
afterEach(() => server.resetHandlers());
|
|
248
|
-
afterAll(() => server.close());
|
|
249
|
-
|
|
250
|
-
// Setup LambderCaller
|
|
251
|
-
const lambderCaller = new LambderCaller<ApiContractType>({
|
|
252
|
-
apiPath: '/secure',
|
|
253
|
-
isCorsEnabled: false
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
describe('User APIs', () => {
|
|
257
|
-
it('should fetch user by id', async () => {
|
|
258
|
-
const result = await lambderCaller.api('getUserById', { userId: '123' });
|
|
259
|
-
|
|
260
|
-
expect(result).toEqual({
|
|
261
|
-
id: '123',
|
|
262
|
-
name: 'John Doe',
|
|
263
|
-
email: 'john@example.com'
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it('should create a new user', async () => {
|
|
268
|
-
const result = await lambderCaller.api('createUser', {
|
|
269
|
-
name: 'Jane Smith',
|
|
270
|
-
email: 'jane@example.com'
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
expect(result?.name).toBe('Jane Smith');
|
|
274
|
-
expect(result?.email).toBe('jane@example.com');
|
|
275
|
-
expect(result?.id).toBeDefined();
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
it('should handle session expired', async () => {
|
|
279
|
-
try {
|
|
280
|
-
await lambderCaller.api('getProtectedData', {});
|
|
281
|
-
// Should not reach here
|
|
282
|
-
expect(true).toBe(false);
|
|
283
|
-
} catch (error: any) {
|
|
284
|
-
expect(error.sessionExpired).toBe(true);
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
it('should handle errors', async () => {
|
|
289
|
-
try {
|
|
290
|
-
await lambderCaller.api('failingApi', {});
|
|
291
|
-
// Should not reach here
|
|
292
|
-
expect(true).toBe(false);
|
|
293
|
-
} catch (error: any) {
|
|
294
|
-
expect(error.errorMessage).toBe('Something went wrong');
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
## Browser Testing
|
|
301
|
-
|
|
302
|
-
LambderMSW also works in browser environments with MSW's browser integration:
|
|
303
|
-
|
|
304
|
-
```typescript
|
|
305
|
-
// test/browser-setup.ts
|
|
306
|
-
import { setupWorker } from 'msw/browser';
|
|
307
|
-
import { LambderMSW } from 'lambder';
|
|
308
|
-
import type { ApiContractType } from '../backend'; // Type-only import from your backend
|
|
309
|
-
|
|
310
|
-
const lambderMSW = new LambderMSW<ApiContractType>({
|
|
311
|
-
apiPath: '/secure'
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
const handlers = [
|
|
315
|
-
lambderMSW.mockApi('getUserById', async (payload) => {
|
|
316
|
-
return {
|
|
317
|
-
id: payload.userId,
|
|
318
|
-
name: 'John Doe',
|
|
319
|
-
email: 'john@example.com'
|
|
320
|
-
};
|
|
321
|
-
})
|
|
322
|
-
];
|
|
323
|
-
|
|
324
|
-
const worker = setupWorker(...handlers);
|
|
325
|
-
|
|
326
|
-
// Start the worker
|
|
327
|
-
worker.start();
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
## Advanced Usage
|
|
331
|
-
|
|
332
|
-
### Dynamic Mock Responses
|
|
333
|
-
|
|
334
|
-
```typescript
|
|
335
|
-
lambderMSW.mockApi('searchUsers', async (payload) => {
|
|
336
|
-
const { query, limit } = payload;
|
|
337
|
-
|
|
338
|
-
// Return different responses based on input
|
|
339
|
-
if (query === 'admin') {
|
|
340
|
-
return [{
|
|
341
|
-
id: '1',
|
|
342
|
-
name: 'Admin User',
|
|
343
|
-
role: 'admin'
|
|
344
|
-
}];
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
return Array.from({ length: limit }, (_, i) => ({
|
|
348
|
-
id: `${i}`,
|
|
349
|
-
name: `User ${i}`,
|
|
350
|
-
role: 'user'
|
|
351
|
-
}));
|
|
352
|
-
});
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
### Override Handlers Per Test
|
|
356
|
-
|
|
357
|
-
```typescript
|
|
358
|
-
it('should handle specific user', async () => {
|
|
359
|
-
// Override the default handler for this test
|
|
360
|
-
server.use(
|
|
361
|
-
lambderMSW.mockApi('getUserById', async (payload) => {
|
|
362
|
-
return {
|
|
363
|
-
id: payload.userId,
|
|
364
|
-
name: 'Special User',
|
|
365
|
-
email: 'special@example.com'
|
|
366
|
-
};
|
|
367
|
-
})
|
|
368
|
-
);
|
|
369
|
-
|
|
370
|
-
const result = await lambderCaller.api('getUserById', { userId: '999' });
|
|
371
|
-
expect(result?.name).toBe('Special User');
|
|
372
|
-
});
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
## Benefits
|
|
376
|
-
|
|
377
|
-
- Full TypeScript support with API contracts
|
|
378
|
-
- Intuitive methods matching Lambder's API structure
|
|
379
|
-
- Test isolation without real backend dependencies
|
|
380
|
-
- Simulate real-world scenarios (delays, errors, etc.)
|
|
381
|
-
|
|
382
|
-
## Troubleshooting
|
|
383
|
-
|
|
384
|
-
### MSW Not Found Error
|
|
385
|
-
|
|
386
|
-
If you see "MSW (Mock Service Worker) is required", make sure MSW is installed:
|
|
387
|
-
|
|
388
|
-
```bash
|
|
389
|
-
npm install msw --save-dev
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
### Handler Not Matching
|
|
393
|
-
|
|
394
|
-
LambderMSW matches handlers based on the `apiName` in the request body. Make sure:
|
|
395
|
-
1. Your `apiPath` matches between backend, frontend, and mocks
|
|
396
|
-
2. The API name string matches exactly
|
|
397
|
-
3. Handlers are registered before making requests
|
|
398
|
-
|
|
399
|
-
### Console Warnings
|
|
400
|
-
|
|
401
|
-
LambderMSW logs matching information to console for debugging. To see these logs:
|
|
402
|
-
- Check browser console for "LambderMSW called for:" messages
|
|
403
|
-
- Verify "Matched!" appears when handler should execute
|
|
404
|
-
|
|
405
|
-
## See Also
|
|
406
|
-
|
|
407
|
-
- [MSW Documentation](https://mswjs.io/)
|
|
408
|
-
- [Type-Safe Quick Start](./TYPE_SAFE_QUICK_START.md)
|
|
409
|
-
- [Lambder Main Documentation](../Readme.md)
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# Type-Safe API Quick Start (v2.0)
|
|
2
|
-
|
|
3
|
-
## In 3 Simple Steps
|
|
4
|
-
|
|
5
|
-
### 1. Define & Implement APIs (Backend)
|
|
6
|
-
|
|
7
|
-
Use Zod schemas to define your API contract inline. Lambder will automatically validate inputs at runtime and infer types for compile-time safety.
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
import { z } from "zod";
|
|
11
|
-
import Lambder from "lambder";
|
|
12
|
-
|
|
13
|
-
// Initialize
|
|
14
|
-
const lambder = new Lambder({
|
|
15
|
-
publicPath: "./public",
|
|
16
|
-
apiPath: "/api"
|
|
17
|
-
})
|
|
18
|
-
// Chain APIs
|
|
19
|
-
.addApi("getUser", {
|
|
20
|
-
input: z.object({ userId: z.string() }),
|
|
21
|
-
output: z.object({ id: z.string(), name: z.string() })
|
|
22
|
-
}, async (ctx, resolver) => {
|
|
23
|
-
// ctx.apiPayload is typed as { userId: string }
|
|
24
|
-
// Runtime validation is already performed!
|
|
25
|
-
return resolver.api({
|
|
26
|
-
id: ctx.apiPayload.userId,
|
|
27
|
-
name: "John Doe"
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
// Export the inferred contract type
|
|
32
|
-
export type ApiContractType = typeof lambder.ApiContract;
|
|
33
|
-
|
|
34
|
-
export const handler = lambder.getHandler();
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### 2. Use in Frontend
|
|
38
|
-
|
|
39
|
-
Import the type (not the code) and use `LambderCaller`.
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
import { LambderCaller } from "lambder";
|
|
43
|
-
import type { ApiContractType } from "./backend"; // Type-only import
|
|
44
|
-
|
|
45
|
-
const lambderCaller = new LambderCaller<ApiContractType>({
|
|
46
|
-
apiPath: "/api"
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
// Fully typed!
|
|
50
|
-
// TypeScript knows 'getUser' takes { userId: string } and returns { id: string, name: string }
|
|
51
|
-
const user = await lambderCaller.api("getUser", { userId: "123" });
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### 3. Modular APIs (Optional)
|
|
55
|
-
|
|
56
|
-
For larger apps, split your APIs into modules using `.use()`.
|
|
57
|
-
|
|
58
|
-
```typescript
|
|
59
|
-
// api.user.ts
|
|
60
|
-
import { z } from "zod";
|
|
61
|
-
import Lambder from "lambder";
|
|
62
|
-
|
|
63
|
-
export const userApi = <T>(l: Lambder<T>) => {
|
|
64
|
-
return l.addApi("login", {
|
|
65
|
-
input: z.object({ email: z.string() }),
|
|
66
|
-
output: z.boolean()
|
|
67
|
-
}, async (ctx, resolver) => {
|
|
68
|
-
return resolver.api(true);
|
|
69
|
-
});
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// index.ts
|
|
73
|
-
import { userApi } from "./api.user";
|
|
74
|
-
|
|
75
|
-
const lambder = new Lambder({ publicPath: './public' })
|
|
76
|
-
.use(userApi); // Types are preserved!
|
|
77
|
-
```
|