@lokalise/api-contracts 6.4.0 → 6.5.1

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.
@@ -10,13 +10,13 @@ import type { SSEEventSchemas } from './sse/sseTypes.ts';
10
10
  * Universal contract builder that creates either REST or SSE contracts based on configuration.
11
11
  *
12
12
  * This is a unified entry point that delegates to:
13
- * - `buildRestContract` when no `sseEvents` is provided
14
- * - `buildSseContract` when `sseEvents` is provided
13
+ * - `buildRestContract` when no `serverSentEventSchemas` is provided
14
+ * - `buildSseContract` when `serverSentEventSchemas` is provided
15
15
  *
16
16
  * ## Contract Type Detection
17
17
  *
18
- * | `sseEvents` | `syncResponseBody` | `requestBody`/`requestBodySchema` | Result |
19
- * |-------------|-------------------|-----------------------------------|--------|
18
+ * | `serverSentEventSchemas` | `successResponseBodySchema` | `requestBodySchema` | Result |
19
+ * |--------------------|----------------------------|---------------------|--------|
20
20
  * | ❌ | - | ❌ | REST GET |
21
21
  * | ❌ | - | ✅ (method: post/put/patch) | REST Payload |
22
22
  * | ❌ | - | ❌ (method: delete) | REST DELETE |
@@ -29,6 +29,7 @@ import type { SSEEventSchemas } from './sse/sseTypes.ts';
29
29
  * ```typescript
30
30
  * // REST GET route
31
31
  * const getUsers = buildContract({
32
+ * method: 'get',
32
33
  * successResponseBodySchema: z.array(userSchema),
33
34
  * pathResolver: () => '/api/users',
34
35
  * })
@@ -50,11 +51,12 @@ import type { SSEEventSchemas } from './sse/sseTypes.ts';
50
51
  *
51
52
  * // SSE-only streaming endpoint
52
53
  * const notifications = buildContract({
54
+ * method: 'get',
53
55
  * pathResolver: () => '/api/notifications/stream',
54
- * params: z.object({}),
55
- * query: z.object({}),
56
- * requestHeaders: z.object({}),
57
- * sseEvents: {
56
+ * requestPathParamsSchema: z.object({}),
57
+ * requestQuerySchema: z.object({}),
58
+ * requestHeaderSchema: z.object({}),
59
+ * serverSentEventSchemas: {
58
60
  * notification: z.object({ id: z.string(), message: z.string() }),
59
61
  * },
60
62
  * })
@@ -63,12 +65,12 @@ import type { SSEEventSchemas } from './sse/sseTypes.ts';
63
65
  * const chatCompletion = buildContract({
64
66
  * method: 'post',
65
67
  * pathResolver: () => '/api/chat/completions',
66
- * params: z.object({}),
67
- * query: z.object({}),
68
- * requestHeaders: z.object({}),
69
- * requestBody: z.object({ message: z.string() }),
70
- * syncResponseBody: z.object({ reply: z.string() }),
71
- * sseEvents: {
68
+ * requestPathParamsSchema: z.object({}),
69
+ * requestQuerySchema: z.object({}),
70
+ * requestHeaderSchema: z.object({}),
71
+ * requestBodySchema: z.object({ message: z.string() }),
72
+ * successResponseBodySchema: z.object({ reply: z.string() }),
73
+ * serverSentEventSchemas: {
72
74
  * chunk: z.object({ delta: z.string() }),
73
75
  * done: z.object({ usage: z.object({ tokens: z.number() }) }),
74
76
  * },
@@ -6,7 +6,7 @@ import { buildSseContract, } from "./sse/sseContractBuilders.js";
6
6
  export function buildContract(
7
7
  // biome-ignore lint/suspicious/noExplicitAny: Union of all config types
8
8
  config) {
9
- const hasSseEvents = 'sseEvents' in config && config.sseEvents !== undefined;
9
+ const hasSseEvents = 'serverSentEventSchemas' in config && config.serverSentEventSchemas !== undefined;
10
10
  if (hasSseEvents) {
11
11
  // Delegate to SSE contract builder
12
12
  return buildSseContract(config);
@@ -1 +1 @@
1
- {"version":3,"file":"contractBuilder.js","sourceRoot":"","sources":["../src/contractBuilder.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,iBAAiB,GAIlB,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EACL,gBAAgB,GAKjB,MAAM,8BAA8B,CAAA;AAqTrC,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,MAAM,UAAU,aAAa;AAC3B,wEAAwE;AACxE,MAAW;IAGX,MAAM,YAAY,GAAG,WAAW,IAAI,MAAM,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,CAAA;IAE5E,IAAI,YAAY,EAAE,CAAC;QACjB,mCAAmC;QACnC,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACjC,CAAC;IAED,oCAAoC;IACpC,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAA;AAClC,CAAC"}
1
+ {"version":3,"file":"contractBuilder.js","sourceRoot":"","sources":["../src/contractBuilder.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,iBAAiB,GAIlB,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EACL,gBAAgB,GAKjB,MAAM,8BAA8B,CAAA;AAuTrC,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,MAAM,UAAU,aAAa;AAC3B,wEAAwE;AACxE,MAAW;IAGX,MAAM,YAAY,GAChB,wBAAwB,IAAI,MAAM,IAAI,MAAM,CAAC,sBAAsB,KAAK,SAAS,CAAA;IAEnF,IAAI,YAAY,EAAE,CAAC;QACjB,mCAAmC;QACnC,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACjC,CAAC;IAED,oCAAoC;IACpC,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAA;AAClC,CAAC"}
@@ -3,13 +3,13 @@ import type { CommonRouteDefinition, DeleteRouteDefinition, GetRouteDefinition,
3
3
  import type { HttpStatusCode } from '../HttpStatusCodes.ts';
4
4
  /**
5
5
  * Configuration for building a GET route.
6
- * GET routes have no request body and the method is inferred automatically.
6
+ * GET routes have no request body and require method: 'get'.
7
7
  */
8
8
  export type GetContractConfig<SuccessResponseBodySchema extends z.Schema | undefined = undefined, PathParamsSchema extends z.Schema | undefined = undefined, RequestQuerySchema extends z.Schema | undefined = undefined, RequestHeaderSchema extends z.Schema | undefined = undefined, ResponseHeaderSchema extends z.Schema | undefined = undefined, IsNonJSONResponseExpected extends boolean = false, IsEmptyResponseExpected extends boolean = false, ResponseSchemasByStatusCode extends Partial<Record<HttpStatusCode, z.Schema>> | undefined = undefined> = Omit<CommonRouteDefinition<SuccessResponseBodySchema, PathParamsSchema, RequestQuerySchema, RequestHeaderSchema, ResponseHeaderSchema, IsNonJSONResponseExpected, IsEmptyResponseExpected, ResponseSchemasByStatusCode>, 'method'> & {
9
- method?: never;
9
+ method: 'get';
10
10
  requestBodySchema?: never;
11
11
  /** Discriminator to distinguish from SSE contracts in buildContract */
12
- sseEvents?: never;
12
+ serverSentEventSchemas?: never;
13
13
  };
14
14
  /**
15
15
  * Configuration for building a DELETE route.
@@ -19,7 +19,7 @@ export type DeleteContractConfig<SuccessResponseBodySchema extends z.Schema | un
19
19
  method: 'delete';
20
20
  requestBodySchema?: never;
21
21
  /** Discriminator to distinguish from SSE contracts in buildContract */
22
- sseEvents?: never;
22
+ serverSentEventSchemas?: never;
23
23
  };
24
24
  /**
25
25
  * Configuration for building a payload route (POST, PUT, PATCH).
@@ -29,7 +29,7 @@ export type PayloadContractConfig<RequestBodySchema extends z.Schema | undefined
29
29
  method: 'post' | 'put' | 'patch';
30
30
  requestBodySchema: RequestBodySchema;
31
31
  /** Discriminator to distinguish from SSE contracts in buildContract */
32
- sseEvents?: never;
32
+ serverSentEventSchemas?: never;
33
33
  };
34
34
  /**
35
35
  * Builds REST API contracts with automatic type inference.
@@ -41,20 +41,22 @@ export type PayloadContractConfig<RequestBodySchema extends z.Schema | undefined
41
41
  *
42
42
  * | `method` | `requestBodySchema` | Result |
43
43
  * |----------|---------------------|--------|
44
- * | omitted/undefined | ❌ | GET route |
44
+ * | `'get'` | ❌ | GET route |
45
45
  * | `'delete'` | ❌ | DELETE route |
46
46
  * | `'post'`/`'put'`/`'patch'` | ✅ | Payload route |
47
47
  *
48
48
  * @example
49
49
  * ```typescript
50
- * // GET route - method is inferred automatically
50
+ * // GET route - method: 'get' is required
51
51
  * const getUsers = buildRestContract({
52
+ * method: 'get',
52
53
  * pathResolver: () => '/api/users',
53
54
  * successResponseBodySchema: z.array(userSchema),
54
55
  * })
55
56
  *
56
57
  * // GET route with path params
57
58
  * const getUser = buildRestContract({
59
+ * method: 'get',
58
60
  * pathResolver: (params) => `/api/users/${params.userId}`,
59
61
  * requestPathParamsSchema: z.object({ userId: z.string() }),
60
62
  * successResponseBodySchema: userSchema,
@@ -36,7 +36,7 @@ export function buildRestContract(config) {
36
36
  method: 'delete',
37
37
  };
38
38
  }
39
- // GET route (default)
39
+ // GET route
40
40
  return {
41
41
  ...baseFields,
42
42
  method: 'get',
@@ -1 +1 @@
1
- {"version":3,"file":"restContractBuilder.js","sourceRoot":"","sources":["../../src/rest/restContractBuilder.ts"],"names":[],"mappings":"AA+RA,iBAAiB;AACjB,MAAM,UAAU,iBAAiB,CAC/B,MAKsE;IAGtE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;IAC5B,MAAM,OAAO,GAAG,mBAAmB,IAAI,MAAM,IAAI,MAAM,CAAC,iBAAiB,KAAK,SAAS,CAAA;IAEvF,oEAAoE;IACpE,MAAM,aAAa,GAAG,MAAM,KAAK,QAAQ,CAAA;IACzC,MAAM,8BAA8B,GAAG,aAAa,CAAA;IAEpD,MAAM,UAAU,GAAG;QACjB,uBAAuB,EAAE,MAAM,CAAC,uBAAuB,IAAI,8BAA8B;QACzF,yBAAyB,EAAE,MAAM,CAAC,yBAAyB,IAAI,KAAK;QACpE,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;QAC/C,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;QACjD,uBAAuB,EAAE,MAAM,CAAC,uBAAuB;QACvD,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,yBAAyB,EAAE,MAAM,CAAC,yBAAyB;QAC3D,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,2BAA2B,EAAE,MAAM,CAAC,2BAA2B;QAC/D,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,IAAI,EAAE,MAAM,CAAC,IAAI;KAClB,CAAA;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,iCAAiC;QACjC,OAAO;YACL,GAAG,UAAU;YACb,MAAM,EAAE,MAAkC;YAC1C,qFAAqF;YACrF,iBAAiB,EAAG,MAAqC,CAAC,iBAAiB;SAC5E,CAAA;IACH,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAClB,eAAe;QACf,OAAO;YACL,GAAG,UAAU;YACb,MAAM,EAAE,QAAiB;SAC1B,CAAA;IACH,CAAC;IAED,sBAAsB;IACtB,OAAO;QACL,GAAG,UAAU;QACb,MAAM,EAAE,KAAc;KACvB,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"restContractBuilder.js","sourceRoot":"","sources":["../../src/rest/restContractBuilder.ts"],"names":[],"mappings":"AAiSA,iBAAiB;AACjB,MAAM,UAAU,iBAAiB,CAC/B,MAKsE;IAGtE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;IAC5B,MAAM,OAAO,GAAG,mBAAmB,IAAI,MAAM,IAAI,MAAM,CAAC,iBAAiB,KAAK,SAAS,CAAA;IAEvF,oEAAoE;IACpE,MAAM,aAAa,GAAG,MAAM,KAAK,QAAQ,CAAA;IACzC,MAAM,8BAA8B,GAAG,aAAa,CAAA;IAEpD,MAAM,UAAU,GAAG;QACjB,uBAAuB,EAAE,MAAM,CAAC,uBAAuB,IAAI,8BAA8B;QACzF,yBAAyB,EAAE,MAAM,CAAC,yBAAyB,IAAI,KAAK;QACpE,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;QAC/C,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;QACjD,uBAAuB,EAAE,MAAM,CAAC,uBAAuB;QACvD,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,yBAAyB,EAAE,MAAM,CAAC,yBAAyB;QAC3D,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,2BAA2B,EAAE,MAAM,CAAC,2BAA2B;QAC/D,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,IAAI,EAAE,MAAM,CAAC,IAAI;KAClB,CAAA;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,iCAAiC;QACjC,OAAO;YACL,GAAG,UAAU;YACb,MAAM,EAAE,MAAkC;YAC1C,qFAAqF;YACrF,iBAAiB,EAAG,MAAqC,CAAC,iBAAiB;SAC5E,CAAA;IACH,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAClB,eAAe;QACf,OAAO;YACL,GAAG,UAAU;YACb,MAAM,EAAE,QAAiB;SAC1B,CAAA;IACH,CAAC;IAED,YAAY;IACZ,OAAO;QACL,GAAG,UAAU;QACb,MAAM,EAAE,KAAc;KACvB,CAAA;AACH,CAAC"}
@@ -5,13 +5,13 @@ import type { SSEMethod } from './sseContracts.ts';
5
5
  import type { SSEEventSchemas } from './sseTypes.ts';
6
6
  /**
7
7
  * Definition for a dual-mode route.
8
- * Use `syncResponseBody` for the non-streaming response schema.
8
+ * Use `successResponseBodySchema` for the non-streaming response schema.
9
9
  *
10
10
  * @template Method - HTTP method (GET, POST, PUT, PATCH)
11
11
  * @template Params - Path parameters schema
12
12
  * @template Query - Query string parameters schema
13
13
  * @template RequestHeaders - Request headers schema
14
- * @template Body - Request requestBody schema (for POST/PUT/PATCH)
14
+ * @template Body - Request body schema (for POST/PUT/PATCH)
15
15
  * @template SyncResponse - Sync response schema (for Accept: application/json)
16
16
  * @template Events - SSE event schemas (for Accept: text/event-stream)
17
17
  * @template ResponseHeaders - Response headers schema (for sync mode)
@@ -20,27 +20,27 @@ import type { SSEEventSchemas } from './sseTypes.ts';
20
20
  export type DualModeContractDefinition<Method extends SSEMethod = SSEMethod, Params extends z.ZodTypeAny = z.ZodTypeAny, Query extends z.ZodTypeAny = z.ZodTypeAny, RequestHeaders extends z.ZodTypeAny = z.ZodTypeAny, Body extends z.ZodTypeAny | undefined = undefined, SyncResponse extends z.ZodTypeAny = z.ZodTypeAny, Events extends SSEEventSchemas = SSEEventSchemas, ResponseHeaders extends z.ZodTypeAny | undefined = undefined, ResponseSchemasByStatusCode extends Partial<Record<HttpStatusCode, z.ZodTypeAny>> | undefined = undefined> = {
21
21
  method: Method;
22
22
  pathResolver: RoutePathResolver<z.infer<Params>>;
23
- params: Params;
24
- query: Query;
25
- requestHeaders: RequestHeaders;
26
- requestBody: Body;
23
+ requestPathParamsSchema: Params;
24
+ requestQuerySchema: Query;
25
+ requestHeaderSchema: RequestHeaders;
26
+ requestBodySchema: Body;
27
27
  /** Sync response schema - use with `sync` handler */
28
- syncResponseBody: SyncResponse;
29
- responseHeaders?: ResponseHeaders;
28
+ successResponseBodySchema: SyncResponse;
29
+ responseHeaderSchema?: ResponseHeaders;
30
30
  /**
31
31
  * Alternative response schemas by HTTP status code.
32
32
  * Used to define different response shapes for error cases (e.g., 400, 404, 500).
33
33
  *
34
34
  * @example
35
35
  * ```ts
36
- * responseSchemasByStatusCode: {
36
+ * responseBodySchemasByStatusCode: {
37
37
  * 400: z.object({ error: z.string(), details: z.array(z.string()) }),
38
38
  * 404: z.object({ error: z.string() }),
39
39
  * }
40
40
  * ```
41
41
  */
42
- responseSchemasByStatusCode?: ResponseSchemasByStatusCode;
43
- sseEvents: Events;
42
+ responseBodySchemasByStatusCode?: ResponseSchemasByStatusCode;
43
+ serverSentEventSchemas: Events;
44
44
  isDualMode: true;
45
45
  };
46
46
  /**
@@ -50,14 +50,14 @@ export type DualModeContractDefinition<Method extends SSEMethod = SSEMethod, Par
50
50
  export type AnyDualModeContractDefinition = {
51
51
  method: SSEMethod;
52
52
  pathResolver: RoutePathResolver<any>;
53
- params: z.ZodTypeAny;
54
- query: z.ZodTypeAny;
55
- requestHeaders: z.ZodTypeAny;
56
- requestBody: z.ZodTypeAny | undefined;
57
- /** Sync response schema */
58
- syncResponseBody: z.ZodTypeAny;
59
- responseHeaders?: z.ZodTypeAny;
60
- responseSchemasByStatusCode?: Partial<Record<HttpStatusCode, z.ZodTypeAny>>;
61
- sseEvents: SSEEventSchemas;
53
+ requestPathParamsSchema: z.ZodTypeAny;
54
+ requestQuerySchema: z.ZodTypeAny;
55
+ requestHeaderSchema: z.ZodTypeAny;
56
+ requestBodySchema: z.ZodTypeAny | undefined;
57
+ /** Sync response schema - use with `sync` handler */
58
+ successResponseBodySchema: z.ZodTypeAny;
59
+ responseHeaderSchema?: z.ZodTypeAny;
60
+ responseBodySchemasByStatusCode?: Partial<Record<HttpStatusCode, z.ZodTypeAny>>;
61
+ serverSentEventSchemas: SSEEventSchemas;
62
62
  isDualMode: true;
63
63
  };
@@ -6,14 +6,15 @@ import type { SSEContractDefinition } from './sseContracts.ts';
6
6
  import type { SSEEventSchemas } from './sseTypes.ts';
7
7
  /**
8
8
  * Configuration for building a GET SSE route.
9
- * Forbids requestBody for GET variants.
9
+ * Forbids requestBodySchema for GET variants.
10
10
  */
11
11
  export type SSEGetContractConfig<Params extends z.ZodTypeAny, Query extends z.ZodTypeAny, RequestHeaders extends z.ZodTypeAny, Events extends SSEEventSchemas, ResponseSchemasByStatusCode extends Partial<Record<HttpStatusCode, z.ZodTypeAny>> | undefined = undefined> = {
12
+ method: 'get';
12
13
  pathResolver: RoutePathResolver<z.infer<Params>>;
13
- params: Params;
14
- query: Query;
15
- requestHeaders: RequestHeaders;
16
- sseEvents: Events;
14
+ requestPathParamsSchema: Params;
15
+ requestQuerySchema: Query;
16
+ requestHeaderSchema: RequestHeaders;
17
+ serverSentEventSchemas: Events;
17
18
  /**
18
19
  * Error response schemas by HTTP status code.
19
20
  * Used to define response shapes for errors that occur before streaming starts
@@ -21,28 +22,28 @@ export type SSEGetContractConfig<Params extends z.ZodTypeAny, Query extends z.Zo
21
22
  *
22
23
  * @example
23
24
  * ```ts
24
- * responseSchemasByStatusCode: {
25
+ * responseBodySchemasByStatusCode: {
25
26
  * 401: z.object({ error: z.literal('Unauthorized') }),
26
27
  * 404: z.object({ error: z.string() }),
27
28
  * }
28
29
  * ```
29
30
  */
30
- responseSchemasByStatusCode?: ResponseSchemasByStatusCode;
31
- requestBody?: never;
32
- syncResponseBody?: never;
31
+ responseBodySchemasByStatusCode?: ResponseSchemasByStatusCode;
32
+ requestBodySchema?: never;
33
+ successResponseBodySchema?: never;
33
34
  };
34
35
  /**
35
- * Configuration for building a POST/PUT/PATCH SSE route with request requestBody.
36
- * Requires requestBody for payload variants.
36
+ * Configuration for building a POST/PUT/PATCH SSE route with request body.
37
+ * Requires requestBodySchema for payload variants.
37
38
  */
38
39
  export type SSEPayloadContractConfig<Params extends z.ZodTypeAny, Query extends z.ZodTypeAny, RequestHeaders extends z.ZodTypeAny, Body extends z.ZodTypeAny, Events extends SSEEventSchemas, ResponseSchemasByStatusCode extends Partial<Record<HttpStatusCode, z.ZodTypeAny>> | undefined = undefined> = {
39
- method?: 'post' | 'put' | 'patch';
40
+ method: 'post' | 'put' | 'patch';
40
41
  pathResolver: RoutePathResolver<z.infer<Params>>;
41
- params: Params;
42
- query: Query;
43
- requestHeaders: RequestHeaders;
44
- requestBody: Body;
45
- sseEvents: Events;
42
+ requestPathParamsSchema: Params;
43
+ requestQuerySchema: Query;
44
+ requestHeaderSchema: RequestHeaders;
45
+ requestBodySchema: Body;
46
+ serverSentEventSchemas: Events;
46
47
  /**
47
48
  * Error response schemas by HTTP status code.
48
49
  * Used to define response shapes for errors that occur before streaming starts
@@ -50,95 +51,96 @@ export type SSEPayloadContractConfig<Params extends z.ZodTypeAny, Query extends
50
51
  *
51
52
  * @example
52
53
  * ```ts
53
- * responseSchemasByStatusCode: {
54
+ * responseBodySchemasByStatusCode: {
54
55
  * 401: z.object({ error: z.literal('Unauthorized') }),
55
56
  * 404: z.object({ error: z.string() }),
56
57
  * }
57
58
  * ```
58
59
  */
59
- responseSchemasByStatusCode?: ResponseSchemasByStatusCode;
60
- syncResponseBody?: never;
60
+ responseBodySchemasByStatusCode?: ResponseSchemasByStatusCode;
61
+ successResponseBodySchema?: never;
61
62
  };
62
63
  /**
63
64
  * Configuration for building a GET dual-mode route.
64
- * Requires syncResponseBody, forbids requestBody.
65
+ * Requires successResponseBodySchema, forbids requestBodySchema.
65
66
  */
66
67
  export type DualModeGetContractConfig<Params extends z.ZodTypeAny, Query extends z.ZodTypeAny, RequestHeaders extends z.ZodTypeAny, JsonResponse extends z.ZodTypeAny, Events extends SSEEventSchemas, ResponseHeaders extends z.ZodTypeAny | undefined = undefined, ResponseSchemasByStatusCode extends Partial<Record<HttpStatusCode, z.ZodTypeAny>> | undefined = undefined> = {
68
+ method: 'get';
67
69
  pathResolver: RoutePathResolver<z.infer<Params>>;
68
- params: Params;
69
- query: Query;
70
- requestHeaders: RequestHeaders;
70
+ requestPathParamsSchema: Params;
71
+ requestQuerySchema: Query;
72
+ requestHeaderSchema: RequestHeaders;
71
73
  /** Single sync response schema */
72
- syncResponseBody: JsonResponse;
74
+ successResponseBodySchema: JsonResponse;
73
75
  /**
74
76
  * Schema for validating response headers (sync mode only).
75
77
  * Used to define and validate headers that the server will send in the response.
76
78
  *
77
79
  * @example
78
80
  * ```ts
79
- * responseHeaders: z.object({
81
+ * responseHeaderSchema: z.object({
80
82
  * 'x-ratelimit-limit': z.string(),
81
83
  * 'x-ratelimit-remaining': z.string(),
82
84
  * })
83
85
  * ```
84
86
  */
85
- responseHeaders?: ResponseHeaders;
87
+ responseHeaderSchema?: ResponseHeaders;
86
88
  /**
87
89
  * Alternative response schemas by HTTP status code.
88
90
  * Used to define different response shapes for error cases.
89
91
  *
90
92
  * @example
91
93
  * ```ts
92
- * responseSchemasByStatusCode: {
94
+ * responseBodySchemasByStatusCode: {
93
95
  * 400: z.object({ error: z.string(), details: z.array(z.string()) }),
94
96
  * 404: z.object({ error: z.string() }),
95
97
  * }
96
98
  * ```
97
99
  */
98
- responseSchemasByStatusCode?: ResponseSchemasByStatusCode;
99
- sseEvents: Events;
100
- requestBody?: never;
100
+ responseBodySchemasByStatusCode?: ResponseSchemasByStatusCode;
101
+ serverSentEventSchemas: Events;
102
+ requestBodySchema?: never;
101
103
  };
102
104
  /**
103
- * Configuration for building a POST/PUT/PATCH dual-mode route with request requestBody.
104
- * Requires both requestBody and syncResponseBody.
105
+ * Configuration for building a POST/PUT/PATCH dual-mode route with request body.
106
+ * Requires both requestBodySchema and successResponseBodySchema.
105
107
  */
106
108
  export type DualModePayloadContractConfig<Params extends z.ZodTypeAny, Query extends z.ZodTypeAny, RequestHeaders extends z.ZodTypeAny, Body extends z.ZodTypeAny, JsonResponse extends z.ZodTypeAny, Events extends SSEEventSchemas, ResponseHeaders extends z.ZodTypeAny | undefined = undefined, ResponseSchemasByStatusCode extends Partial<Record<HttpStatusCode, z.ZodTypeAny>> | undefined = undefined> = {
107
- method?: 'post' | 'put' | 'patch';
109
+ method: 'post' | 'put' | 'patch';
108
110
  pathResolver: RoutePathResolver<z.infer<Params>>;
109
- params: Params;
110
- query: Query;
111
- requestHeaders: RequestHeaders;
112
- requestBody: Body;
111
+ requestPathParamsSchema: Params;
112
+ requestQuerySchema: Query;
113
+ requestHeaderSchema: RequestHeaders;
114
+ requestBodySchema: Body;
113
115
  /** Single sync response schema */
114
- syncResponseBody: JsonResponse;
116
+ successResponseBodySchema: JsonResponse;
115
117
  /**
116
118
  * Schema for validating response headers (sync mode only).
117
119
  * Used to define and validate headers that the server will send in the response.
118
120
  *
119
121
  * @example
120
122
  * ```ts
121
- * responseHeaders: z.object({
123
+ * responseHeaderSchema: z.object({
122
124
  * 'x-ratelimit-limit': z.string(),
123
125
  * 'x-ratelimit-remaining': z.string(),
124
126
  * })
125
127
  * ```
126
128
  */
127
- responseHeaders?: ResponseHeaders;
129
+ responseHeaderSchema?: ResponseHeaders;
128
130
  /**
129
131
  * Alternative response schemas by HTTP status code.
130
132
  * Used to define different response shapes for error cases.
131
133
  *
132
134
  * @example
133
135
  * ```ts
134
- * responseSchemasByStatusCode: {
136
+ * responseBodySchemasByStatusCode: {
135
137
  * 400: z.object({ error: z.string(), details: z.array(z.string()) }),
136
138
  * 404: z.object({ error: z.string() }),
137
139
  * }
138
140
  * ```
139
141
  */
140
- responseSchemasByStatusCode?: ResponseSchemasByStatusCode;
141
- sseEvents: Events;
142
+ responseBodySchemasByStatusCode?: ResponseSchemasByStatusCode;
143
+ serverSentEventSchemas: Events;
142
144
  };
143
145
  export declare function buildSseContract<Params extends z.ZodTypeAny, Query extends z.ZodTypeAny, RequestHeaders extends z.ZodTypeAny, JsonResponse extends z.ZodTypeAny, Events extends SSEEventSchemas, ResponseHeaders extends z.ZodTypeAny | undefined = undefined, ResponseSchemasByStatusCode extends Partial<Record<HttpStatusCode, z.ZodTypeAny>> | undefined = undefined>(config: DualModeGetContractConfig<Params, Query, RequestHeaders, JsonResponse, Events, ResponseHeaders, ResponseSchemasByStatusCode>): DualModeContractDefinition<'get', Params, Query, RequestHeaders, undefined, JsonResponse, Events, ResponseHeaders, ResponseSchemasByStatusCode>;
144
146
  export declare function buildSseContract<Params extends z.ZodTypeAny, Query extends z.ZodTypeAny, RequestHeaders extends z.ZodTypeAny, Events extends SSEEventSchemas, ResponseSchemasByStatusCode extends Partial<Record<HttpStatusCode, z.ZodTypeAny>> | undefined = undefined>(config: SSEGetContractConfig<Params, Query, RequestHeaders, Events, ResponseSchemasByStatusCode>): SSEContractDefinition<'get', Params, Query, RequestHeaders, undefined, Events, ResponseSchemasByStatusCode>;
@@ -12,10 +12,10 @@
12
12
  * This is ideal for AI/LLM APIs (like OpenAI) where clients can choose between
13
13
  * getting the full response at once or streaming it token-by-token.
14
14
  *
15
- * The contract type is automatically determined based on the presence of `syncResponseBody`:
15
+ * The contract type is automatically determined based on the presence of `successResponseBodySchema`:
16
16
  *
17
- * | `syncResponseBody` | `requestBody` | Result |
18
- * |--------------------|---------------|--------|
17
+ * | `successResponseBodySchema` | `requestBodySchema` | Result |
18
+ * |----------------------------|---------------------|--------|
19
19
  * | ❌ | ❌ | SSE-only GET |
20
20
  * | ❌ | ✅ | SSE-only POST/PUT/PATCH |
21
21
  * | ✅ | ❌ | Dual-mode GET |
@@ -26,10 +26,10 @@
26
26
  * // SSE-only: Pure streaming endpoint (e.g., live notifications)
27
27
  * const notificationsStream = buildSseContract({
28
28
  * pathResolver: () => '/api/notifications/stream',
29
- * params: z.object({}),
30
- * query: z.object({ userId: z.string().optional() }),
31
- * requestHeaders: z.object({}),
32
- * sseEvents: {
29
+ * requestPathParamsSchema: z.object({}),
30
+ * requestQuerySchema: z.object({ userId: z.string().optional() }),
31
+ * requestHeaderSchema: z.object({}),
32
+ * serverSentEventSchemas: {
33
33
  * notification: z.object({ id: z.string(), message: z.string() }),
34
34
  * },
35
35
  * })
@@ -40,12 +40,12 @@
40
40
  * const chatCompletion = buildSseContract({
41
41
  * method: 'POST',
42
42
  * pathResolver: () => '/api/chat/completions',
43
- * params: z.object({}),
44
- * query: z.object({}),
45
- * requestHeaders: z.object({}),
46
- * requestBody: z.object({ message: z.string() }),
47
- * syncResponseBody: z.object({ reply: z.string(), usage: z.object({ tokens: z.number() }) }),
48
- * sseEvents: {
43
+ * requestPathParamsSchema: z.object({}),
44
+ * requestQuerySchema: z.object({}),
45
+ * requestHeaderSchema: z.object({}),
46
+ * requestBodySchema: z.object({ message: z.string() }),
47
+ * successResponseBodySchema: z.object({ reply: z.string(), usage: z.object({ tokens: z.number() }) }),
48
+ * serverSentEventSchemas: {
49
49
  * chunk: z.object({ delta: z.string() }),
50
50
  * done: z.object({ usage: z.object({ total: z.number() }) }),
51
51
  * },
@@ -57,40 +57,41 @@
57
57
  function buildBaseFields(config, hasBody) {
58
58
  return {
59
59
  pathResolver: config.pathResolver,
60
- params: config.params,
61
- query: config.query,
62
- requestHeaders: config.requestHeaders,
63
- requestBody: hasBody ? config.requestBody : undefined,
64
- sseEvents: config.sseEvents,
60
+ requestPathParamsSchema: config.requestPathParamsSchema,
61
+ requestQuerySchema: config.requestQuerySchema,
62
+ requestHeaderSchema: config.requestHeaderSchema,
63
+ requestBodySchema: hasBody ? config.requestBodySchema : undefined,
64
+ serverSentEventSchemas: config.serverSentEventSchemas,
65
65
  };
66
66
  }
67
67
  // Helper to determine method
68
- function determineMethod(config, hasBody, defaultMethod) {
69
- return hasBody ? (config.method ?? defaultMethod) : 'get';
68
+ function determineMethod(config) {
69
+ return config.method;
70
70
  }
71
71
  // Implementation
72
72
  export function buildSseContract(config) {
73
- const hasSyncResponseBody = 'syncResponseBody' in config && config.syncResponseBody !== undefined;
74
- const hasBody = 'requestBody' in config && config.requestBody !== undefined;
73
+ const hasSyncResponseBody = 'successResponseBodySchema' in config && config.successResponseBodySchema !== undefined;
74
+ const hasBody = 'requestBodySchema' in config && config.requestBodySchema !== undefined;
75
75
  const base = buildBaseFields(config, hasBody);
76
76
  if (hasSyncResponseBody) {
77
77
  // Dual-mode contract
78
78
  return {
79
79
  ...base,
80
- method: determineMethod(config, hasBody, 'post'),
81
- syncResponseBody: config.syncResponseBody,
82
- responseHeaders: config.responseHeaders,
83
- responseSchemasByStatusCode: config
84
- .responseSchemasByStatusCode,
80
+ method: determineMethod(config),
81
+ successResponseBodySchema: config
82
+ .successResponseBodySchema,
83
+ responseHeaderSchema: config.responseHeaderSchema,
84
+ responseBodySchemasByStatusCode: config
85
+ .responseBodySchemasByStatusCode,
85
86
  isDualMode: true,
86
87
  };
87
88
  }
88
89
  // SSE-only contract
89
90
  return {
90
91
  ...base,
91
- method: determineMethod(config, hasBody, 'post'),
92
- responseSchemasByStatusCode: config
93
- .responseSchemasByStatusCode,
92
+ method: determineMethod(config),
93
+ responseBodySchemasByStatusCode: config
94
+ .responseBodySchemasByStatusCode,
94
95
  isSSE: true,
95
96
  };
96
97
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sseContractBuilders.js","sourceRoot":"","sources":["../../src/sse/sseContractBuilders.ts"],"names":[],"mappings":"AAyLA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAEH,uCAAuC;AACvC,gEAAgE;AAChE,SAAS,eAAe,CAAC,MAAW,EAAE,OAAgB;IACpD,OAAO;QACL,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;QACrD,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAA;AACH,CAAC;AAED,6BAA6B;AAC7B,SAAS,eAAe,CAAC,MAA2B,EAAE,OAAgB,EAAE,aAAqB;IAC3F,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;AAC3D,CAAC;AAwHD,iBAAiB;AACjB,MAAM,UAAU,gBAAgB,CAC9B,MAOiD;IAGjD,MAAM,mBAAmB,GAAG,kBAAkB,IAAI,MAAM,IAAI,MAAM,CAAC,gBAAgB,KAAK,SAAS,CAAA;IACjG,MAAM,OAAO,GAAG,aAAa,IAAI,MAAM,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,CAAA;IAC3E,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAE7C,IAAI,mBAAmB,EAAE,CAAC;QACxB,qBAAqB;QACrB,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,eAAe,CAAC,MAA6B,EAAE,OAAO,EAAE,MAAM,CAAC;YACvE,gBAAgB,EAAG,MAAwC,CAAC,gBAAgB;YAC5E,eAAe,EAAG,MAAwC,CAAC,eAAe;YAC1E,2BAA2B,EAAG,MAAoD;iBAC/E,2BAA2B;YAC9B,UAAU,EAAE,IAAI;SACjB,CAAA;IACH,CAAC;IAED,oBAAoB;IACpB,OAAO;QACL,GAAG,IAAI;QACP,MAAM,EAAE,eAAe,CAAC,MAA6B,EAAE,OAAO,EAAE,MAAM,CAAC;QACvE,2BAA2B,EAAG,MAAoD;aAC/E,2BAA2B;QAC9B,KAAK,EAAE,IAAI;KACZ,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"sseContractBuilders.js","sourceRoot":"","sources":["../../src/sse/sseContractBuilders.ts"],"names":[],"mappings":"AA2LA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAEH,uCAAuC;AACvC,gEAAgE;AAChE,SAAS,eAAe,CAAC,MAAW,EAAE,OAAgB;IACpD,OAAO;QACL,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,uBAAuB,EAAE,MAAM,CAAC,uBAAuB;QACvD,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;QAC/C,iBAAiB,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS;QACjE,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;KACtD,CAAA;AACH,CAAC;AAED,6BAA6B;AAC7B,SAAS,eAAe,CAAC,MAA0B;IACjD,OAAO,MAAM,CAAC,MAAM,CAAA;AACtB,CAAC;AAwHD,iBAAiB;AACjB,MAAM,UAAU,gBAAgB,CAC9B,MAOiD;IAGjD,MAAM,mBAAmB,GACvB,2BAA2B,IAAI,MAAM,IAAI,MAAM,CAAC,yBAAyB,KAAK,SAAS,CAAA;IACzF,MAAM,OAAO,GAAG,mBAAmB,IAAI,MAAM,IAAI,MAAM,CAAC,iBAAiB,KAAK,SAAS,CAAA;IACvF,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAE7C,IAAI,mBAAmB,EAAE,CAAC;QACxB,qBAAqB;QACrB,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,eAAe,CAAC,MAA4B,CAAC;YACrD,yBAAyB,EAAG,MAAiD;iBAC1E,yBAAyB;YAC5B,oBAAoB,EAAG,MAA6C,CAAC,oBAAoB;YACzF,+BAA+B,EAAG,MAAwD;iBACvF,+BAA+B;YAClC,UAAU,EAAE,IAAI;SACjB,CAAA;IACH,CAAC;IAED,oBAAoB;IACpB,OAAO;QACL,GAAG,IAAI;QACP,MAAM,EAAE,eAAe,CAAC,MAA4B,CAAC;QACrD,+BAA+B,EAAG,MAAwD;aACvF,+BAA+B;QAClC,KAAK,EAAE,IAAI;KACZ,CAAA;AACH,CAAC"}
@@ -15,7 +15,7 @@ export type SSEMethod = 'get' | 'post' | 'put' | 'patch';
15
15
  * @template Params - Path parameters schema
16
16
  * @template Query - Query string parameters schema
17
17
  * @template RequestHeaders - Request headers schema
18
- * @template Body - Request requestBody schema (for POST/PUT/PATCH)
18
+ * @template Body - Request body schema (for POST/PUT/PATCH)
19
19
  * @template Events - Map of event name to event data schema
20
20
  * @template ResponseSchemasByStatusCode - Error response schemas by HTTP status code
21
21
  */
@@ -26,11 +26,11 @@ export type SSEContractDefinition<Method extends SSEMethod = SSEMethod, Params e
26
26
  * Receives typed params and returns the URL path string.
27
27
  */
28
28
  pathResolver: RoutePathResolver<z.infer<Params>>;
29
- params: Params;
30
- query: Query;
31
- requestHeaders: RequestHeaders;
32
- requestBody: Body;
33
- sseEvents: Events;
29
+ requestPathParamsSchema: Params;
30
+ requestQuerySchema: Query;
31
+ requestHeaderSchema: RequestHeaders;
32
+ requestBodySchema: Body;
33
+ serverSentEventSchemas: Events;
34
34
  /**
35
35
  * Error response schemas by HTTP status code.
36
36
  * Used to define response shapes for errors that occur before streaming starts
@@ -38,13 +38,13 @@ export type SSEContractDefinition<Method extends SSEMethod = SSEMethod, Params e
38
38
  *
39
39
  * @example
40
40
  * ```ts
41
- * responseSchemasByStatusCode: {
41
+ * responseBodySchemasByStatusCode: {
42
42
  * 401: z.object({ error: z.literal('Unauthorized') }),
43
43
  * 404: z.object({ error: z.string() }),
44
44
  * }
45
45
  * ```
46
46
  */
47
- responseSchemasByStatusCode?: ResponseSchemasByStatusCode;
47
+ responseBodySchemasByStatusCode?: ResponseSchemasByStatusCode;
48
48
  isSSE: true;
49
49
  };
50
50
  /**
@@ -54,11 +54,11 @@ export type SSEContractDefinition<Method extends SSEMethod = SSEMethod, Params e
54
54
  export type AnySSEContractDefinition = {
55
55
  method: SSEMethod;
56
56
  pathResolver: RoutePathResolver<any>;
57
- params: z.ZodTypeAny;
58
- query: z.ZodTypeAny;
59
- requestHeaders: z.ZodTypeAny;
60
- requestBody: z.ZodTypeAny | undefined;
61
- sseEvents: SSEEventSchemas;
62
- responseSchemasByStatusCode?: Partial<Record<HttpStatusCode, z.ZodTypeAny>>;
57
+ requestPathParamsSchema: z.ZodTypeAny;
58
+ requestQuerySchema: z.ZodTypeAny;
59
+ requestHeaderSchema: z.ZodTypeAny;
60
+ requestBodySchema: z.ZodTypeAny | undefined;
61
+ serverSentEventSchemas: SSEEventSchemas;
62
+ responseBodySchemasByStatusCode?: Partial<Record<HttpStatusCode, z.ZodTypeAny>>;
63
63
  isSSE: true;
64
64
  };
@@ -11,19 +11,19 @@ export type SSEEventSchemas = Record<string, z.ZodTypeAny>;
11
11
  * @example
12
12
  * ```typescript
13
13
  * type Contracts = {
14
- * notifications: { sseEvents: { alert: z.ZodObject<...> } }
15
- * chat: { sseEvents: { message: z.ZodObject<...>, done: z.ZodObject<...> } }
14
+ * notifications: { serverSentEventSchemas: { alert: z.ZodObject<...> } }
15
+ * chat: { serverSentEventSchemas: { message: z.ZodObject<...>, done: z.ZodObject<...> } }
16
16
  * }
17
17
  * // AllContractEventNames<Contracts> = 'alert' | 'message' | 'done'
18
18
  * ```
19
19
  */
20
- export type AllContractEventNames<Contracts extends Record<string, AnySSEContractDefinition>> = Contracts[keyof Contracts]['sseEvents'] extends infer E ? E extends SSEEventSchemas ? keyof E & string : never : never;
20
+ export type AllContractEventNames<Contracts extends Record<string, AnySSEContractDefinition>> = Contracts[keyof Contracts]['serverSentEventSchemas'] extends infer E ? E extends SSEEventSchemas ? keyof E & string : never : never;
21
21
  /**
22
22
  * Extract the schema for a specific event name across all contracts.
23
23
  * Returns the Zod schema for the event, or never if not found.
24
24
  */
25
25
  export type ExtractEventSchema<Contracts extends Record<string, AnySSEContractDefinition>, EventName extends string> = {
26
- [K in keyof Contracts]: EventName extends keyof Contracts[K]['sseEvents'] ? Contracts[K]['sseEvents'][EventName] : never;
26
+ [K in keyof Contracts]: EventName extends keyof Contracts[K]['serverSentEventSchemas'] ? Contracts[K]['serverSentEventSchemas'][EventName] : never;
27
27
  }[keyof Contracts];
28
28
  /**
29
29
  * Flatten all events from all contracts into a single record.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lokalise/api-contracts",
3
- "version": "6.4.0",
3
+ "version": "6.5.1",
4
4
  "files": [
5
5
  "dist"
6
6
  ],