lambder 1.0.147 → 2.0.2

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 (39) hide show
  1. package/Readme.md +355 -410
  2. package/dist/Lambder.d.ts +47 -21
  3. package/dist/Lambder.js +79 -24
  4. package/dist/LambderApiContract.d.ts +10 -42
  5. package/dist/LambderApiContract.js +2 -22
  6. package/dist/LambderCaller.js +2 -2
  7. package/dist/LambderMSW.js +0 -4
  8. package/dist/LambderResolver.d.ts +16 -17
  9. package/dist/LambderResponseBuilder.d.ts +2 -3
  10. package/dist/LambderResponseBuilder.js +1 -3
  11. package/dist/LambderUtils.js +1 -3
  12. package/dist/index.d.ts +1 -1
  13. package/docs/LAMBDER_MSW.md +6 -6
  14. package/docs/TYPE_SAFE_QUICK_START.md +54 -177
  15. package/examples/msw-testing-example.ts +36 -33
  16. package/examples/secure-session-example.ts +50 -34
  17. package/examples/zod-chained-api-example.ts +63 -0
  18. package/package.json +3 -2
  19. package/src/Lambder.ts +124 -83
  20. package/src/LambderApiContract.ts +7 -50
  21. package/src/LambderCaller.ts +2 -2
  22. package/src/LambderMSW.ts +0 -7
  23. package/src/LambderResolver.ts +21 -24
  24. package/src/LambderResponseBuilder.ts +4 -7
  25. package/src/LambderUtils.ts +1 -3
  26. package/src/index.ts +0 -3
  27. package/tests/UNTESTED_FEATURES.md +263 -0
  28. package/tests/error-handling.test.ts +585 -0
  29. package/tests/hooks.test.ts +561 -0
  30. package/tests/output-type-runtime.test.ts +80 -64
  31. package/tests/routes.test.ts +542 -0
  32. package/tests/session.test.ts +38 -24
  33. package/tests/type-safety.test.ts +147 -97
  34. package/tests/use-plugin.test.ts +437 -0
  35. package/OUTPUT_TYPE_ENFORCEMENT_SUMMARY.md +0 -90
  36. package/examples/output-type-enforcement-example.ts +0 -218
  37. package/examples/simplified-typed-api-example.ts +0 -365
  38. package/examples/test-output-type-enforcement.ts +0 -101
  39. package/test-type-enforcement.ts +0 -111
@@ -1,218 +0,0 @@
1
- /**
2
- * Output Type Enforcement Example
3
- *
4
- * This example demonstrates how Lambder now enforces output types
5
- * in addition to input types for type-safe APIs.
6
- */
7
-
8
- import Lambder from '../src/Lambder.js';
9
- import type { ApiContract } from '../src/index.js';
10
-
11
- // ============================================================================
12
- // Define Types
13
- // ============================================================================
14
-
15
- type User = {
16
- id: string;
17
- name: string;
18
- email: string;
19
- age: number;
20
- };
21
-
22
- type Product = {
23
- id: string;
24
- name: string;
25
- price: number;
26
- inStock: boolean;
27
- };
28
-
29
- type Stats = {
30
- totalUsers: number;
31
- totalProducts: number;
32
- revenue: number;
33
- };
34
-
35
- // ============================================================================
36
- // Define API Contract
37
- // ============================================================================
38
-
39
- type MyApiContract = ApiContract<{
40
- // Simple primitive outputs
41
- getCount: { input: void, output: number },
42
- getMessage: { input: { id: string }, output: string },
43
- isActive: { input: void, output: boolean },
44
-
45
- // Complex object outputs
46
- getUser: { input: { userId: string }, output: User },
47
- getProduct: { input: { productId: string }, output: Product },
48
-
49
- // Array outputs
50
- listUsers: { input: void, output: User[] },
51
- listProducts: { input: { category: string }, output: Product[] },
52
-
53
- // Complex nested outputs
54
- getStats: { input: void, output: Stats },
55
-
56
- // Nullable outputs
57
- findUser: { input: { email: string }, output: User | null },
58
- }>;
59
-
60
- // ============================================================================
61
- // Setup Backend with Type Enforcement
62
- // ============================================================================
63
-
64
- const lambder = new Lambder<MyApiContract>({
65
- publicPath: './public',
66
- apiPath: '/api',
67
- });
68
-
69
- // ✅ EXAMPLE 1: Simple primitive outputs are enforced
70
- lambder.addApi('getCount', async (ctx, resolver) => {
71
- const count = 42;
72
- return resolver.api(count); // ✅ TypeScript validates this is a number
73
- });
74
-
75
- lambder.addApi('getMessage', async (ctx, resolver) => {
76
- const message = `Message for ${ctx.apiPayload.id}`;
77
- return resolver.api(message); // ✅ TypeScript validates this is a string
78
- });
79
-
80
- lambder.addApi('isActive', async (ctx, resolver) => {
81
- const active = true;
82
- return resolver.api(active); // ✅ TypeScript validates this is a boolean
83
- });
84
-
85
- // ✅ EXAMPLE 2: Complex objects must match the shape
86
- lambder.addApi('getUser', async (ctx, resolver) => {
87
- const user: User = {
88
- id: ctx.apiPayload.userId,
89
- name: "John Doe",
90
- email: "john@example.com",
91
- age: 30,
92
- };
93
- return resolver.api(user); // ✅ All required fields are present
94
- });
95
-
96
- lambder.addApi('getProduct', async (ctx, resolver) => {
97
- const product: Product = {
98
- id: ctx.apiPayload.productId,
99
- name: "Widget",
100
- price: 99.99,
101
- inStock: true,
102
- };
103
- return resolver.api(product); // ✅ Correct shape
104
- });
105
-
106
- // ✅ EXAMPLE 3: Arrays are type-checked
107
- lambder.addApi('listUsers', async (ctx, resolver) => {
108
- const users: User[] = [
109
- { id: "1", name: "Alice", email: "alice@example.com", age: 25 },
110
- { id: "2", name: "Bob", email: "bob@example.com", age: 30 },
111
- ];
112
- return resolver.api(users); // ✅ Array of User objects
113
- });
114
-
115
- lambder.addApi('listProducts', async (ctx, resolver) => {
116
- const category = ctx.apiPayload.category;
117
- const products: Product[] = [
118
- { id: "1", name: "Item 1", price: 10, inStock: true },
119
- { id: "2", name: "Item 2", price: 20, inStock: false },
120
- ];
121
- return resolver.api(products); // ✅ Array of Product objects
122
- });
123
-
124
- // ✅ EXAMPLE 4: Nested objects are validated
125
- lambder.addApi('getStats', async (ctx, resolver) => {
126
- const stats: Stats = {
127
- totalUsers: 100,
128
- totalProducts: 50,
129
- revenue: 10000,
130
- };
131
- return resolver.api(stats); // ✅ Matches Stats shape
132
- });
133
-
134
- // ✅ EXAMPLE 5: Nullable types work correctly
135
- lambder.addApi('findUser', async (ctx, resolver) => {
136
- const email = ctx.apiPayload.email;
137
-
138
- if (email === "john@example.com") {
139
- // Found user
140
- const user: User = {
141
- id: "123",
142
- name: "John",
143
- email: email,
144
- age: 30,
145
- };
146
- return resolver.api(user); // ✅ Can return User
147
- } else {
148
- // Not found
149
- return resolver.api(null); // ✅ Can return null
150
- }
151
- });
152
-
153
- // ✅ EXAMPLE 6: Using die.api() also enforces types
154
- lambder.addApi('getCount', async (ctx, resolver) => {
155
- return resolver.die.api(42); // ✅ die.api() also type-checks
156
- });
157
-
158
- // ✅ EXAMPLE 7: Session APIs also enforce output types
159
- lambder.addSessionApi('getUser', async (ctx, resolver) => {
160
- const user: User = {
161
- id: ctx.apiPayload.userId,
162
- name: "Jane Doe",
163
- email: "jane@example.com",
164
- age: 28,
165
- };
166
- return resolver.api(user); // ✅ Type-safe for session APIs too
167
- });
168
-
169
- // ============================================================================
170
- // What TypeScript Prevents (these would cause compile errors)
171
- // ============================================================================
172
-
173
- /*
174
- // ❌ ERROR: Wrong primitive type
175
- lambder.addApi('getCount', async (ctx, resolver) => {
176
- return resolver.api("not a number"); // Error: string not assignable to number
177
- });
178
-
179
- // ❌ ERROR: Missing required field
180
- lambder.addApi('getUser', async (ctx, resolver) => {
181
- return resolver.api({
182
- id: "123",
183
- name: "John",
184
- email: "john@example.com",
185
- // age is missing! - TypeScript error
186
- });
187
- });
188
-
189
- // ❌ ERROR: Wrong field type
190
- lambder.addApi('getUser', async (ctx, resolver) => {
191
- return resolver.api({
192
- id: "123",
193
- name: "John",
194
- email: "john@example.com",
195
- age: "30", // Error: string not assignable to number
196
- });
197
- });
198
-
199
- // ❌ ERROR: Wrong array element type
200
- lambder.addApi('listUsers', async (ctx, resolver) => {
201
- return resolver.api([
202
- { id: "1", name: "Alice", email: "alice@example.com", age: 25 },
203
- "not a user object", // Error: string not assignable to User
204
- ]);
205
- });
206
-
207
- // ❌ ERROR: Returning wrong type when null is not allowed
208
- lambder.addApi('getUser', async (ctx, resolver) => {
209
- return resolver.api(null); // Error: null not assignable to User (findUser allows null, but getUser doesn't)
210
- });
211
- */
212
-
213
- console.log("✅ All examples demonstrate proper output type enforcement!");
214
- console.log("✅ TypeScript will catch type mismatches at compile time!");
215
- console.log("✅ This works with both resolver.api() and resolver.die.api()!");
216
- console.log("✅ Both addApi() and addSessionApi() enforce output types!");
217
-
218
- export default lambder;
@@ -1,365 +0,0 @@
1
- /**
2
- * Simplified Type-Safe API Example
3
- *
4
- * This example shows how to use Lambder's opt-in type-safe API system.
5
- * Simply pass your API contract type to LambderCaller and Lambder constructors,
6
- * and get full type safety with no extra wrapper functions needed!
7
- */
8
-
9
- import Lambder from '../src/Lambder.js';
10
- import LambderCaller from '../src/LambderCaller.js';
11
- import type { ApiContract } from '../src/index.js';
12
-
13
- // ============================================================================
14
- // Step 1: Define your data types
15
- // ============================================================================
16
-
17
- type User = {
18
- id: string;
19
- name: string;
20
- email: string;
21
- role: 'admin' | 'user';
22
- createdAt: string;
23
- };
24
-
25
- type CreateUserInput = {
26
- name: string;
27
- email: string;
28
- password: string;
29
- };
30
-
31
- type UpdateUserInput = {
32
- userId: string;
33
- name?: string;
34
- email?: string;
35
- };
36
-
37
- type LoginInput = {
38
- email: string;
39
- password: string;
40
- };
41
-
42
- type LoginOutput = {
43
- success: boolean;
44
- user?: User;
45
- token?: string;
46
- error?: string;
47
- };
48
-
49
- // ============================================================================
50
- // Step 2: Define your API contract (shared between frontend and backend)
51
- // ============================================================================
52
-
53
- export type MyApiContract = ApiContract<{
54
- // API with input and output
55
- getUserById: { input: { userId: string }, output: User },
56
-
57
- // API with complex input/output
58
- createUser: { input: CreateUserInput, output: User },
59
- updateUser: { input: UpdateUserInput, output: User },
60
-
61
- // API with void input (no parameters needed)
62
- listUsers: { input: void, output: User[] },
63
- getCurrentUser: { input: void, output: User },
64
-
65
- // API with conditional output
66
- login: { input: LoginInput, output: LoginOutput },
67
-
68
- // API with primitive output
69
- getUserCount: { input: void, output: number },
70
- deleteUser: { input: { userId: string }, output: boolean },
71
- }>;
72
-
73
- // ============================================================================
74
- // Step 3: Backend - Pass contract type to Lambder
75
- // ============================================================================
76
-
77
- export function setupBackend() {
78
- // Pass the contract type as a generic parameter
79
- const lambder = new Lambder<MyApiContract>({
80
- publicPath: './public',
81
- apiPath: '/api',
82
- apiVersion: '1.0.0',
83
- });
84
-
85
- // Now addApi is type-safe! ctx.apiPayload is automatically typed!
86
- lambder.addApi('getUserById', async (ctx, resolver) => {
87
- // ctx.apiPayload is typed as { userId: string }
88
- const userId = ctx.apiPayload.userId; // ✅ TypeScript knows this!
89
-
90
- // Mock database call
91
- const user: User = {
92
- id: userId,
93
- name: 'John Doe',
94
- email: 'john@example.com',
95
- role: 'user',
96
- createdAt: new Date().toISOString(),
97
- };
98
-
99
- return resolver.api(user);
100
- });
101
-
102
- // Session API with typed payload
103
- lambder.addSessionApi('createUser', async (ctx, resolver) => {
104
- // ctx.apiPayload is typed as CreateUserInput
105
- const { name, email, password } = ctx.apiPayload;
106
-
107
- // Validation with type safety
108
- if (!name || !email || !password) {
109
- return resolver.api(null, {
110
- errorMessage: 'Missing required fields'
111
- });
112
- }
113
-
114
- // Create user
115
- const newUser: User = {
116
- id: Math.random().toString(36).substr(2, 9),
117
- name,
118
- email,
119
- role: 'user',
120
- createdAt: new Date().toISOString(),
121
- };
122
-
123
- return resolver.api(newUser);
124
- });
125
-
126
- // API with void input
127
- lambder.addApi('listUsers', async (ctx, resolver) => {
128
- // ctx.apiPayload is void/undefined
129
- const users: User[] = [
130
- { id: '1', name: 'John', email: 'john@example.com', role: 'user', createdAt: new Date().toISOString() },
131
- { id: '2', name: 'Jane', email: 'jane@example.com', role: 'admin', createdAt: new Date().toISOString() },
132
- ];
133
-
134
- return resolver.api(users);
135
- });
136
-
137
- // Complex API with conditional response
138
- lambder.addApi('login', async (ctx, resolver) => {
139
- // ctx.apiPayload is typed as LoginInput
140
- const { email, password } = ctx.apiPayload;
141
-
142
- // Mock authentication
143
- if (email === 'test@example.com' && password === 'password123') {
144
- const result: LoginOutput = {
145
- success: true,
146
- user: {
147
- id: '1',
148
- name: 'Test User',
149
- email: email,
150
- role: 'user',
151
- createdAt: new Date().toISOString(),
152
- },
153
- token: 'mock-jwt-token',
154
- };
155
- return resolver.api(result);
156
- } else {
157
- const result: LoginOutput = {
158
- success: false,
159
- error: 'Invalid credentials',
160
- };
161
- return resolver.api(result);
162
- }
163
- });
164
-
165
- // You can still use RegExp or functions for dynamic patterns (untyped)
166
- lambder.addApi(/^admin\./, async (ctx, resolver) => {
167
- // ctx.apiPayload is any (untyped)
168
- return resolver.api({ message: 'Admin API' });
169
- });
170
-
171
- return lambder;
172
- }
173
-
174
- // ============================================================================
175
- // Step 4: Frontend - Pass contract type to LambderCaller
176
- // ============================================================================
177
-
178
- export function setupFrontend() {
179
- // Pass the contract type as a generic parameter
180
- const caller = new LambderCaller<MyApiContract>({
181
- apiPath: '/api',
182
- apiVersion: '1.0.0',
183
- isCorsEnabled: false,
184
- errorHandler: (err) => {
185
- console.error('API Error:', err);
186
- },
187
- });
188
-
189
- // Now all API calls are type-safe!
190
-
191
- // Example 1: Get user by ID
192
- async function example1() {
193
- // TypeScript knows:
194
- // - First parameter is 'getUserById' (autocomplete shows all API names!)
195
- // - Second parameter must be { userId: string }
196
- // - Return type is User | null | undefined
197
- const user = await caller.api('getUserById', { userId: '123' });
198
-
199
- if (user) {
200
- console.log(user.name); // ✅ TypeScript knows 'name' exists
201
- console.log(user.email); // ✅ TypeScript knows 'email' exists
202
- console.log(user.role); // ✅ TypeScript knows 'role' is 'admin' | 'user'
203
- // console.log(user.age); // ✗ Error: Property 'age' does not exist
204
- }
205
- }
206
-
207
- // Example 2: Create user
208
- async function example2() {
209
- // TypeScript enforces the CreateUserInput type
210
- const newUser = await caller.api('createUser', {
211
- name: 'Alice',
212
- email: 'alice@example.com',
213
- password: 'secret123',
214
- });
215
-
216
- if (newUser) {
217
- console.log('Created user:', newUser.id);
218
- }
219
-
220
- // This would be a TypeScript error:
221
- // await caller.api('createUser', { name: 'Bob' }); // ✗ Missing email and password
222
- }
223
-
224
- // Example 3: Login
225
- async function example3() {
226
- const result = await caller.api('login', {
227
- email: 'test@example.com',
228
- password: 'password123',
229
- });
230
-
231
- if (result?.success && result.user) {
232
- console.log('Logged in as:', result.user.name);
233
- console.log('Token:', result.token);
234
- } else {
235
- console.error('Login failed:', result?.error);
236
- }
237
- }
238
-
239
- // Example 4: List users (void input)
240
- async function example4() {
241
- // For void input, pass undefined
242
- const users = await caller.api('listUsers', undefined);
243
-
244
- if (users) {
245
- users.forEach(user => {
246
- console.log(user.name); // ✅ TypeScript knows the array type
247
- });
248
- }
249
- }
250
-
251
- // Example 5: Get user count (primitive output)
252
- async function example5() {
253
- const count = await caller.api('getUserCount', undefined);
254
- if (count !== null && count !== undefined) {
255
- console.log(`Total users: ${count}`); // count is number
256
- }
257
- }
258
-
259
- // Example 6: With custom headers
260
- async function example6() {
261
- const user = await caller.api(
262
- 'getUserById',
263
- { userId: '456' },
264
- { headers: { 'X-Custom-Header': 'value' } }
265
- );
266
- }
267
-
268
- // Example 7: Using apiRaw for full response
269
- async function example7() {
270
- const response = await caller.apiRaw('getUserById', { userId: '123' });
271
-
272
- if (response) {
273
- console.log('Payload:', response.payload); // User | null
274
- if (response.logList) {
275
- console.log('Logs:', response.logList);
276
- }
277
- if (response.errorMessage) {
278
- console.error('Error:', response.errorMessage);
279
- }
280
- }
281
- }
282
-
283
- return caller;
284
- }
285
-
286
- // ============================================================================
287
- // Without Contract (Backward Compatibility)
288
- // ============================================================================
289
-
290
- export function setupWithoutContract() {
291
- // If you don't pass a contract type, it works like before (untyped)
292
- const caller = new LambderCaller({
293
- apiPath: '/api',
294
- isCorsEnabled: false,
295
- });
296
-
297
- // Still works, but no type safety
298
- async function untypedExample() {
299
- const user = await caller.api('getUserById', { userId: '123' });
300
- // user is any
301
- }
302
-
303
- const lambder = new Lambder({
304
- publicPath: './public',
305
- apiPath: '/api',
306
- });
307
-
308
- // Still works, but no type safety
309
- lambder.addApi('getUserById', async (ctx, resolver) => {
310
- // ctx.apiPayload is any
311
- const user = { id: ctx.apiPayload.userId, name: 'User' };
312
- return resolver.api(user);
313
- });
314
- }
315
-
316
- // ============================================================================
317
- // Type Safety Examples
318
- // ============================================================================
319
-
320
- export function typeSafetyExamples() {
321
- const caller = new LambderCaller<MyApiContract>({ apiPath: '/api', isCorsEnabled: false });
322
-
323
- async function examples() {
324
- // ✓ VALID:
325
- await caller.api('getUserById', { userId: '123' });
326
- await caller.api('createUser', { name: 'Alice', email: 'alice@example.com', password: 'pass' });
327
- await caller.api('listUsers', undefined);
328
-
329
- // ✗ ERRORS (TypeScript prevents):
330
- // await caller.api('getUserById'); // Missing required payload
331
- // await caller.api('getUserById', { id: '123' }); // Wrong property name (should be userId)
332
- // await caller.api('createUser', { name: 'Bob' }); // Missing email and password
333
- // await caller.api('nonExistentApi', {}); // API doesn't exist in contract
334
-
335
- // Type inference works:
336
- const user = await caller.api('getUserById', { userId: '123' });
337
- if (user) {
338
- console.log(user.name); // ✓ TypeScript knows user has name
339
- // console.log(user.age); // ✗ Error: Property 'age' does not exist
340
- }
341
-
342
- const users = await caller.api('listUsers', undefined);
343
- if (users) {
344
- users.forEach(u => {
345
- console.log(u.email); // ✓ TypeScript knows array item structure
346
- });
347
- }
348
- }
349
- }
350
-
351
- // ============================================================================
352
- // Key Benefits
353
- // ============================================================================
354
- //
355
- // 1. ✅ Type Safety - Frontend and backend share the same types
356
- // 2. ✅ Autocomplete - IDE suggests available APIs as you type
357
- // 3. ✅ No Wrappers - Use existing api() and addApi() methods
358
- // 4. ✅ Opt-In - Add types when you want, or don't use them at all
359
- // 5. ✅ Backward Compatible - Existing code works without changes
360
- // 6. ✅ Simple - Just pass type to constructor, that's it!
361
- // 7. ✅ Zero Runtime Overhead - Pure TypeScript types
362
- //
363
- // ============================================================================
364
-
365
- export { Lambder, LambderCaller, type ApiContract };
@@ -1,101 +0,0 @@
1
- /**
2
- * Test file to verify output type enforcement
3
- * This file should have TypeScript errors if output types are not correct
4
- */
5
-
6
- import Lambder from '../src/Lambder.js';
7
- import type { ApiContract } from '../src/index.js';
8
-
9
- // Define a simple API contract
10
- type TestContract = ApiContract<{
11
- getNumber: { input: void, output: number },
12
- getString: { input: { id: string }, output: string },
13
- getUser: { input: { userId: string }, output: { id: string; name: string; age: number } },
14
- }>;
15
-
16
- const lambder = new Lambder<TestContract>({
17
- publicPath: './public',
18
- apiPath: '/api',
19
- });
20
-
21
- // ✅ CORRECT: Returns the right type
22
- lambder.addApi('getNumber', async (ctx, resolver) => {
23
- // This should work - returning number
24
- return resolver.api(42);
25
- });
26
-
27
- // ❌ INCORRECT: Should cause TypeScript error - returning wrong type
28
- lambder.addApi('getNumber', async (ctx, resolver) => {
29
- // @ts-expect-error - Testing type enforcement: should not accept string when output is number
30
- return resolver.api("wrong type");
31
- });
32
-
33
- // ✅ CORRECT: Returns string
34
- lambder.addApi('getString', async (ctx, resolver) => {
35
- const id = ctx.apiPayload.id;
36
- return resolver.api(`String for ${id}`);
37
- });
38
-
39
- // ❌ INCORRECT: Should cause TypeScript error - returning wrong type
40
- lambder.addApi('getString', async (ctx, resolver) => {
41
- // @ts-expect-error - Testing type enforcement: should not accept number when output is string
42
- return resolver.api(123);
43
- });
44
-
45
- // ✅ CORRECT: Returns correct object shape
46
- lambder.addApi('getUser', async (ctx, resolver) => {
47
- return resolver.api({
48
- id: ctx.apiPayload.userId,
49
- name: "John Doe",
50
- age: 30,
51
- });
52
- });
53
-
54
- // ❌ INCORRECT: Should cause TypeScript error - missing required field
55
- lambder.addApi('getUser', async (ctx, resolver) => {
56
- // @ts-expect-error - Testing type enforcement: missing 'age' field
57
- return resolver.api({
58
- id: ctx.apiPayload.userId,
59
- name: "John Doe",
60
- // age is missing
61
- });
62
- });
63
-
64
- // ❌ INCORRECT: Should cause TypeScript error - wrong field type
65
- lambder.addApi('getUser', async (ctx, resolver) => {
66
- return resolver.api({
67
- id: ctx.apiPayload.userId,
68
- name: "John Doe",
69
- // @ts-expect-error - Testing type enforcement: age should be number, not string
70
- age: "30", // wrong type
71
- });
72
- });
73
-
74
- // ✅ CORRECT: Using null is allowed
75
- lambder.addApi('getNumber', async (ctx, resolver) => {
76
- return resolver.api(null);
77
- });
78
-
79
- // ✅ CORRECT: Using resolver.die.api also enforces types
80
- lambder.addApi('getNumber', async (ctx, resolver) => {
81
- return resolver.die.api(42);
82
- });
83
-
84
- // ❌ INCORRECT: resolver.die.api should also enforce types
85
- lambder.addApi('getNumber', async (ctx, resolver) => {
86
- // @ts-expect-error - Testing type enforcement: die.api should also check types
87
- return resolver.die.api("wrong type");
88
- });
89
-
90
- // Test with addSessionApi
91
- lambder.addSessionApi('getString', async (ctx, resolver) => {
92
- // Should also enforce output type for session APIs
93
- return resolver.api("correct string");
94
- });
95
-
96
- lambder.addSessionApi('getString', async (ctx, resolver) => {
97
- // @ts-expect-error - Testing type enforcement: session API should also enforce types
98
- return resolver.api(123);
99
- });
100
-
101
- console.log("If this file compiles with @ts-expect-error comments, output type enforcement is working!");