lambder 2.0.4 → 2.0.5

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 CHANGED
@@ -70,7 +70,7 @@ const app = lambder
70
70
  });
71
71
 
72
72
  // Export the inferred contract for the frontend
73
- export type AppContract = typeof lambder.ApiContractType;
73
+ export type AppContract = typeof lambder.ApiContract;
74
74
 
75
75
  // Export the handler
76
76
  export const handler = lambder.getHandler();
@@ -196,7 +196,7 @@ import { userApi } from "./user-api";
196
196
  const lambder = new Lambder()
197
197
  .use(userApi);
198
198
 
199
- export type AppContract = typeof lambder.ApiContractType;
199
+ export type AppContract = typeof lambder.ApiContract;
200
200
  ```
201
201
 
202
202
 
@@ -457,7 +457,7 @@ const lambder = new Lambder({ apiPath: '/api' })
457
457
  return res.api({ id: ctx.apiPayload.userId, name: "John" });
458
458
  });
459
459
 
460
- export type AppContract = typeof lambder.ApiContractType;
460
+ export type AppContract = typeof lambder.ApiContract;
461
461
  export const handler = lambder.getHandler();
462
462
  ```
463
463
 
package/dist/Lambder.d.ts CHANGED
@@ -77,10 +77,10 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
77
77
  * @example
78
78
  * ```typescript
79
79
  * const lambder = new Lambder().addApi(...).addApi(...);
80
- * export type AppContract = typeof lambder.ApiContractType;
80
+ * export type AppContract = typeof lambder.ApiContract;
81
81
  * ```
82
82
  */
83
- readonly ApiContractType: _TContract;
83
+ readonly ApiContract: _TContract;
84
84
  private actionList;
85
85
  private hookList;
86
86
  private globalErrorHandler;
package/dist/Lambder.js CHANGED
@@ -76,10 +76,10 @@ export default class Lambder {
76
76
  * @example
77
77
  * ```typescript
78
78
  * const lambder = new Lambder().addApi(...).addApi(...);
79
- * export type AppContract = typeof lambder.ApiContractType;
79
+ * export type AppContract = typeof lambder.ApiContract;
80
80
  * ```
81
81
  */
82
- ApiContractType;
82
+ ApiContract;
83
83
  actionList;
84
84
  hookList;
85
85
  globalErrorHandler = null;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Lambder API Contract System
3
3
  *
4
- * Contracts are built via method chaining and inferred using typeof lambder.ApiContractType
4
+ * Contracts are built via method chaining and inferred using typeof lambder.ApiContract
5
5
  */
6
6
  /**
7
7
  * Base shape for API contracts - used by LambderCaller and LambderMSW
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Lambder API Contract System
3
3
  *
4
- * Contracts are built via method chaining and inferred using typeof lambder.ApiContractType
4
+ * Contracts are built via method chaining and inferred using typeof lambder.ApiContract
5
5
  */
6
6
  export {};
@@ -56,23 +56,32 @@ afterAll(() => server.close());
56
56
  When using TypeScript API contracts, LambderMSW provides full type safety:
57
57
 
58
58
  ```typescript
59
- // shared/apiContract.ts
60
- import type { ApiContract } from 'lambder';
61
-
62
- export type MyApiContract = ApiContract<{
63
- getUserById: {
64
- input: { userId: string },
65
- output: { id: string, name: string, email: string }
66
- },
67
- createUser: {
68
- input: { name: string, email: string },
69
- output: { id: string, name: string, email: string }
70
- }
71
- }>;
59
+ // backend/index.ts (define your APIs with Lambder)
60
+ import { z } from 'zod';
61
+ import Lambder from 'lambder';
62
+
63
+ const lambder = new Lambder({ apiPath: '/secure' })
64
+ .addApi('getUserById', {
65
+ input: z.object({ userId: z.string() }),
66
+ output: z.object({ id: z.string(), name: z.string(), email: z.string() })
67
+ }, async (ctx, resolver) => {
68
+ // Implementation...
69
+ return resolver.api({ id: ctx.apiPayload.userId, name: 'John', email: 'john@example.com' });
70
+ })
71
+ .addApi('createUser', {
72
+ input: z.object({ name: z.string(), email: z.string() }),
73
+ output: z.object({ id: z.string(), name: z.string(), email: z.string() })
74
+ }, async (ctx, resolver) => {
75
+ // Implementation...
76
+ return resolver.api({ id: '123', ...ctx.apiPayload });
77
+ });
78
+
79
+ // Export the inferred contract type
80
+ export type MyApiContract = typeof lambder.ApiContract;
72
81
 
73
82
  // test/setup.ts
74
83
  import { LambderMSW } from 'lambder';
75
- import type { MyApiContract } from '../shared/apiContract';
84
+ import type { MyApiContract } from '../backend';
76
85
 
77
86
  const lambderMSW = new LambderMSW<MyApiContract>({
78
87
  apiPath: '/secure',
@@ -208,7 +217,7 @@ import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest';
208
217
  import { setupServer } from 'msw/node';
209
218
  import { LambderMSW } from 'lambder';
210
219
  import { LambderCaller } from 'lambder';
211
- import type { MyApiContract } from '../shared/apiContract';
220
+ import type { MyApiContract } from '../backend'; // Type-only import from your backend
212
221
 
213
222
  // Setup MSW
214
223
  const lambderMSW = new LambderMSW<MyApiContract>({
@@ -305,7 +314,7 @@ LambderMSW also works in browser environments with MSW's browser integration:
305
314
  // test/browser-setup.ts
306
315
  import { setupWorker } from 'msw/browser';
307
316
  import { LambderMSW } from 'lambder';
308
- import type { MyApiContract } from '../shared/apiContract';
317
+ import type { MyApiContract } from '../backend'; // Type-only import from your backend
309
318
 
310
319
  const lambderMSW = new LambderMSW<MyApiContract>({
311
320
  apiPath: '/secure'
@@ -29,7 +29,7 @@ const lambder = new Lambder({
29
29
  });
30
30
 
31
31
  // Export the inferred contract type
32
- export type AppContract = typeof lambder.ApiContractType;
32
+ export type AppContract = typeof lambder.ApiContract;
33
33
 
34
34
  export const handler = lambder.getHandler();
35
35
  ```
@@ -40,7 +40,7 @@ const lambder = new Lambder()
40
40
  output: z.object({ success: z.boolean() })
41
41
  }, async () => ({} as any));
42
42
 
43
- type TestApiContract = typeof lambder.ApiContractType;
43
+ type TestApiContract = typeof lambder.ApiContract;
44
44
 
45
45
  // Setup LambderMSW with type safety
46
46
  const lambderMSW = new LambderMSW<TestApiContract>({
@@ -46,7 +46,7 @@ const lambder = new Lambder({
46
46
  });
47
47
 
48
48
  // 3. Export the inferred contract type for Frontend
49
- export type AppContract = typeof lambder.ApiContractType;
49
+ export type AppContract = typeof lambder.ApiContract;
50
50
 
51
51
  // 4. Modular example using .use()
52
52
  const authApi = <T>(l: Lambder<T>) => {
@@ -60,4 +60,4 @@ const authApi = <T>(l: Lambder<T>) => {
60
60
 
61
61
  const lambderWithAuth = lambder.use(authApi);
62
62
 
63
- export type AuthContract = typeof lambderWithAuth.ApiContractType;
63
+ export type AuthContract = typeof lambderWithAuth.ApiContract;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lambder",
3
- "version": "2.0.4",
3
+ "version": "2.0.5",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/Lambder.ts CHANGED
@@ -133,10 +133,10 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
133
133
  * @example
134
134
  * ```typescript
135
135
  * const lambder = new Lambder().addApi(...).addApi(...);
136
- * export type AppContract = typeof lambder.ApiContractType;
136
+ * export type AppContract = typeof lambder.ApiContract;
137
137
  * ```
138
138
  */
139
- public readonly ApiContractType!: _TContract;
139
+ public readonly ApiContract!: _TContract;
140
140
 
141
141
  private actionList: ActionObject[];
142
142
  private hookList: {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Lambder API Contract System
3
3
  *
4
- * Contracts are built via method chaining and inferred using typeof lambder.ApiContractType
4
+ * Contracts are built via method chaining and inferred using typeof lambder.ApiContract
5
5
  */
6
6
 
7
7
  /**
@@ -34,7 +34,7 @@ describe('LambderCaller Type Safety', () => {
34
34
  return resolver.api({ id: '1', ...ctx.apiPayload });
35
35
  });
36
36
 
37
- type TestApiContract = typeof lambder.ApiContractType;
37
+ type TestApiContract = typeof lambder.ApiContract;
38
38
 
39
39
  const caller = new LambderCaller<TestApiContract>({
40
40
  apiPath: '/api',
@@ -181,7 +181,7 @@ describe('apiRaw Method Type Safety', () => {
181
181
  return resolver.api({ id: ctx.apiPayload.userId, name: 'Test' });
182
182
  });
183
183
 
184
- type TestApiContract = typeof lambder.ApiContractType;
184
+ type TestApiContract = typeof lambder.ApiContract;
185
185
 
186
186
  const caller = new LambderCaller<TestApiContract>({
187
187
  apiPath: '/api',
@@ -70,7 +70,7 @@ describe('Plugin System - Basic Usage', () => {
70
70
  const result = await handler(event, createMockContext());
71
71
 
72
72
  expect(result.statusCode).toBe(200);
73
- const body = JSON.parse(result.body);
73
+ const body = JSON.parse(result.body || '{}');
74
74
  expect(body.payload).toEqual({ id: '123', name: 'John Doe' });
75
75
  });
76
76
 
@@ -90,7 +90,7 @@ describe('Plugin System - Basic Usage', () => {
90
90
  apiPath: '/api'
91
91
  }).use(userPlugin);
92
92
 
93
- type AppContract = typeof lambder.ApiContractType;
93
+ type AppContract = typeof lambder.ApiContract;
94
94
 
95
95
  const caller = new LambderCaller<AppContract>({
96
96
  apiPath: '/api',
@@ -163,19 +163,19 @@ describe('Plugin System - Multiple Plugins', () => {
163
163
  const userEvent = createMockEvent('getUser', { userId: '123' });
164
164
  const userResult = await handler(userEvent, createMockContext());
165
165
  expect(userResult.statusCode).toBe(200);
166
- expect(JSON.parse(userResult.body).payload.name).toBe('John');
166
+ expect(JSON.parse(userResult.body || '{}').payload.name).toBe('John');
167
167
 
168
168
  // Test product API
169
169
  const productEvent = createMockEvent('getProduct', { productId: 'prod-456' });
170
170
  const productResult = await handler(productEvent, createMockContext());
171
171
  expect(productResult.statusCode).toBe(200);
172
- expect(JSON.parse(productResult.body).payload.title).toBe('Test Product');
172
+ expect(JSON.parse(productResult.body || '{}').payload.title).toBe('Test Product');
173
173
 
174
174
  // Test order API
175
175
  const orderEvent = createMockEvent('createOrder', { userId: '123', productId: 'prod-456' });
176
176
  const orderResult = await handler(orderEvent, createMockContext());
177
177
  expect(orderResult.statusCode).toBe(200);
178
- expect(JSON.parse(orderResult.body).payload.orderId).toBe('order-123');
178
+ expect(JSON.parse(orderResult.body || '{}').payload.orderId).toBe('order-123');
179
179
  });
180
180
 
181
181
  it('should accumulate types from multiple plugins', () => {
@@ -206,7 +206,7 @@ describe('Plugin System - Multiple Plugins', () => {
206
206
  .use(userPlugin)
207
207
  .use(productPlugin);
208
208
 
209
- type AppContract = typeof lambder.ApiContractType;
209
+ type AppContract = typeof lambder.ApiContract;
210
210
 
211
211
  const caller = new LambderCaller<AppContract>({
212
212
  apiPath: '/api',
@@ -263,17 +263,17 @@ describe('Plugin System - Mixed Usage', () => {
263
263
  // Test direct API before plugin
264
264
  const healthEvent = createMockEvent('healthCheck', undefined);
265
265
  const healthResult = await handler(healthEvent, createMockContext());
266
- expect(JSON.parse(healthResult.body).payload.status).toBe('ok');
266
+ expect(JSON.parse(healthResult.body || '{}').payload.status).toBe('ok');
267
267
 
268
268
  // Test plugin API
269
269
  const userEvent = createMockEvent('getUser', { userId: '123' });
270
270
  const userResult = await handler(userEvent, createMockContext());
271
- expect(JSON.parse(userResult.body).payload.name).toBe('John');
271
+ expect(JSON.parse(userResult.body || '{}').payload.name).toBe('John');
272
272
 
273
273
  // Test direct API after plugin
274
274
  const versionEvent = createMockEvent('getVersion', undefined);
275
275
  const versionResult = await handler(versionEvent, createMockContext());
276
- expect(JSON.parse(versionResult.body).payload.version).toBe('2.0');
276
+ expect(JSON.parse(versionResult.body || '{}').payload.version).toBe('2.0');
277
277
  });
278
278
  });
279
279
 
@@ -424,7 +424,7 @@ describe('Plugin System - Type Safety', () => {
424
424
  .use(plugin1)
425
425
  .use(plugin2);
426
426
 
427
- type Contract = typeof lambder.ApiContractType;
427
+ type Contract = typeof lambder.ApiContract;
428
428
 
429
429
  // Type assertions - both api1 and api2 should be in the contract
430
430
  // We test this at runtime by creating a caller
@@ -446,12 +446,14 @@ describe('Plugin System - Non-Generic Plugins', () => {
446
446
  const plugin2 = (l: Lambder) => l.addApi('api2', { input: z.void(), output: z.void() }, async (ctx, res) => res.raw({ statusCode: 200, body: '' }));
447
447
 
448
448
  const lambder = new Lambder({ publicPath: '', apiPath: '' })
449
+ .addApi('initialApi', { input: z.void(), output: z.void() }, async (ctx, res) => res.raw({ statusCode: 200, body: '' }))
449
450
  .use(plugin1)
450
451
  .use(plugin2);
451
452
 
452
- type Contract = typeof lambder.ApiContractType;
453
+ type Contract = typeof lambder.ApiContract;
453
454
 
454
455
  // Check if both api1 and api2 exist in Contract
456
+ expectTypeOf<Contract>().toHaveProperty('initialApi');
455
457
  expectTypeOf<Contract>().toHaveProperty('api1');
456
458
  expectTypeOf<Contract>().toHaveProperty('api2');
457
459
  });