@kubb/plugin-client 5.11.0-canary.20261106T172015 → 5.11.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.
@@ -124,6 +124,11 @@ type DataShape = {
124
124
  };
125
125
  type RequestCredentials = 'omit' | 'same-origin' | 'include';
126
126
  type ResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream' | 'formdata';
127
+ /**
128
+ * Parser per response content type. Generated when one success response declares several content
129
+ * types that do not share a single parser. Keys are base media types, such as `audio/mpeg` or `audio/*`.
130
+ */
131
+ type ResponseTypeMap = Record<string, ResponseType>;
127
132
  /**
128
133
  * Decodes a response body for a codec's media type.
129
134
  */
@@ -184,7 +189,7 @@ type RequestConfig<TBody = unknown, TRequest = NativeRequest, TResponse = Native
184
189
  credentials?: RequestCredentials;
185
190
  options?: Record<string, unknown>;
186
191
  contentType?: ContentType;
187
- responseType?: ResponseType;
192
+ responseType?: ResponseType | ResponseTypeMap;
188
193
  throwOnError?: boolean;
189
194
  client?: ClientInstance<TRequest, TResponse>;
190
195
  transport?: Transport<TRequest, TResponse>;
@@ -237,7 +242,7 @@ type ResolvedRequest = {
237
242
  signal?: AbortSignal;
238
243
  credentials?: RequestCredentials;
239
244
  options?: Record<string, unknown>;
240
- responseType?: ResponseType;
245
+ responseType?: ResponseType | ResponseTypeMap;
241
246
  };
242
247
  /**
243
248
  * What a transport returns: the parsed body plus the native request and response objects.
@@ -332,6 +337,11 @@ declare function resolveAuth(params: {
332
337
  }): Promise<void>;
333
338
  /** A body a transport left as a stream: a web `ReadableStream` or an async iterable such as a Node readable. */
334
339
  declare function isStreamed(data: unknown): data is ReadableStream<Uint8Array> | AsyncIterable<Uint8Array | string>;
340
+ /**
341
+ * Picks the parser for a response. A string `responseType` wins. A map is matched against the media type: the exact
342
+ * type, then a wildcard such as `audio/*`, then a catch-all entry. Otherwise the parser is guessed from the media type.
343
+ */
344
+ declare function resolveResponseType(responseType: ResponseType | ResponseTypeMap | undefined, contentType: string | null | undefined): ResponseType | undefined;
335
345
  /** The media type of the `Content-Type` response header, without its parameters. */
336
346
  declare function getResponseContentType(headers: Headers | Record<string, string> | undefined): string | undefined;
337
347
  /**
@@ -342,4 +352,4 @@ declare function createClientCore<TRequest = NativeRequest, TResponse = NativeRe
342
352
  } & ClientConfig<TRequest, TResponse>): ClientInstance<TRequest, TResponse>;
343
353
  type NativeRequest = unknown;
344
354
  type NativeResponse = unknown;
345
- export { SuccessResultUnion as A, createClientCore as B, ResolvedRequest as C, ResultByStatus as D, ResponseType as E, TransportResult as F, unwrapResult as G, getResponseContentType as H, Unwrappable as I, withUnwrap as K, UnwrappedResult as L, SuccessVariant as M, ToStatusNumber as N, ResultUnion as O, Transport as P, UrlConfig as R, RequestResult as S, ResponseErrorConfig as T, isStreamed as U, createInterceptorStack as V, resolveAuth as W, InterceptorStack as _, AuthToken as a, RequestConfig as b, ClientInstance as c, ContentType as d, DataOf as f, InterceptorFn as g, ErrorOf as h, AuthResolver as i, SuccessStatusCode as j, SuccessOf as k, Codec as l, Deserializer as m, NativeResponse as n, CallResult as o, DataShape as p, Auth as r, ClientConfig as s, NativeRequest as t, ContentBodySerializer as u, Interceptors as v, ResponseError as w, RequestCredentials as x, Options as y, Validator as z };
355
+ export { SuccessOf as A, Validator as B, ResolvedRequest as C, ResponseTypeMap as D, ResponseType as E, Transport as F, resolveAuth as G, createInterceptorStack as H, TransportResult as I, withUnwrap as J, resolveResponseType as K, Unwrappable as L, SuccessStatusCode as M, SuccessVariant as N, ResultByStatus as O, ToStatusNumber as P, UnwrappedResult as R, RequestResult as S, ResponseErrorConfig as T, getResponseContentType as U, createClientCore as V, isStreamed as W, InterceptorStack as _, AuthToken as a, RequestConfig as b, ClientInstance as c, ContentType as d, DataOf as f, InterceptorFn as g, ErrorOf as h, AuthResolver as i, SuccessResultUnion as j, ResultUnion as k, Codec as l, Deserializer as m, NativeResponse as n, CallResult as o, DataShape as p, unwrapResult as q, Auth as r, ClientConfig as s, NativeRequest as t, ContentBodySerializer as u, Interceptors as v, ResponseError as w, RequestCredentials as x, Options as y, UrlConfig as z };
package/dist/index.cjs CHANGED
@@ -131,22 +131,65 @@ function getEventStream(node) {
131
131
  const content = getEventStreamContent(node);
132
132
  return content ? content.stream?.shape ?? "data" : null;
133
133
  }
134
+ function baseContentType(contentType) {
135
+ return contentType.split(";")[0].trim().toLowerCase();
136
+ }
137
+ function isJsonContentType(baseType) {
138
+ return baseType === "application/json" || baseType.endsWith("+json") || baseType === "text/json";
139
+ }
134
140
  /**
135
- * Derives the default `responseType` for an operation from its primary success response.
141
+ * Parser for one response content entry.
136
142
  *
137
- * Returns a value only when that response declares a single non-JSON content type. `text/event-stream` maps to
138
- * `'stream'`, `application/octet-stream`, `application/pdf`, `image/*`, `audio/*` and `video/*` map to `'blob'`, and
139
- * other `text/*` to `'text'`. Otherwise `undefined`, leaving the runtime client's `Content-Type` auto-detection in charge.
143
+ * JSON stays unset so the runtime detects it. `text/event-stream` is a stream. A binary schema
144
+ * (`format: binary` / `contentMediaType`) is a blob even when the media type is not a well-known
145
+ * binary type. Other `text/*` is text, and `application/octet-stream`, `application/pdf`,
146
+ * `image/*`, `audio/*`, and `video/*` are blobs.
140
147
  */
141
- function getResponseType(node) {
142
- const baseType = getPrimarySuccessContentType(node);
148
+ function responseTypeForContent(contentType, schema) {
149
+ const baseType = baseContentType(contentType);
143
150
  if (!baseType) return void 0;
144
- if (baseType === "application/json" || baseType.endsWith("+json") || baseType === "text/json") return void 0;
151
+ if (isJsonContentType(baseType)) return void 0;
145
152
  if (baseType === "text/event-stream") return "stream";
153
+ if (schema?.type === "blob") return "blob";
146
154
  if (baseType.startsWith("text/")) return "text";
147
155
  if (baseType === "application/octet-stream" || baseType === "application/pdf" || /^(image|audio|video)\//.test(baseType)) return "blob";
148
156
  }
149
157
  /**
158
+ * Derives the default `responseType` string for an operation from its primary success response.
159
+ *
160
+ * One content type uses {@link responseTypeForContent}. Several content types that all use the same
161
+ * parser collapse to that string, so a call can keep `responseType: 'blob'`. Mixed parsers return
162
+ * `undefined`; {@link getResponseTypeMap} carries the per-type choice.
163
+ */
164
+ function getResponseType(node) {
165
+ const entries = getPrimarySuccessResponse(node)?.content ?? [];
166
+ if (entries.length === 0) return void 0;
167
+ const responseTypes = entries.map((entry) => responseTypeForContent(entry.contentType, entry.schema));
168
+ const first = responseTypes[0];
169
+ if (!first) return void 0;
170
+ if (responseTypes.every((responseType) => responseType === first)) return first;
171
+ }
172
+ /**
173
+ * Maps each base content type of a primary success response to its parser when those parsers differ.
174
+ *
175
+ * Keys are lowercased and stripped of parameters. JSON entries are kept as `'json'` so a catch-all
176
+ * entry cannot claim a JSON response. Returns `undefined` when {@link getResponseType} already
177
+ * covers the response with one string, or when no content type needs a parser other than JSON.
178
+ * The runtime matches the response `Content-Type` against this map instead of guessing from the media type.
179
+ */
180
+ function getResponseTypeMap(node) {
181
+ if (getResponseType(node)) return void 0;
182
+ const entries = getPrimarySuccessResponse(node)?.content ?? [];
183
+ if (entries.length <= 1) return void 0;
184
+ const map = {};
185
+ for (const entry of entries) {
186
+ const baseType = baseContentType(entry.contentType);
187
+ const responseType = responseTypeForContent(entry.contentType, entry.schema) ?? (isJsonContentType(baseType) ? "json" : void 0);
188
+ if (baseType && responseType) map[baseType] = responseType;
189
+ }
190
+ return Object.values(map).some((responseType) => responseType !== "json") ? map : void 0;
191
+ }
192
+ /**
150
193
  * Which of the grouped request options an operation carries.
151
194
  */
152
195
  function getRequestGroups(node) {
@@ -465,7 +508,7 @@ var compatibility = {
465
508
  "node": ">=22.22"
466
509
  };
467
510
  // package.json
468
- var version = "5.11.0-canary.20261106T172015";
511
+ var version = "5.11.0";
469
512
  // ../../internals/client/src/builders/validatorOptions.ts
470
513
  /**
471
514
  * Returns `true` when any direction of the validator uses zod (used for dependency checks).
@@ -824,6 +867,17 @@ function buildStyles({ node }) {
824
867
  }
825
868
  // ../../internals/client/src/builders/callConfig.ts
826
869
  /**
870
+ * `responseType` baked into a call. One parser is a string. Several parsers become a map from content
871
+ * type to parser so the runtime can choose from the response `Content-Type`.
872
+ */
873
+ function buildResponseTypeLiteral(node) {
874
+ const responseType = getResponseType(node);
875
+ if (responseType) return `responseType: '${responseType}'`;
876
+ const responseTypes = getResponseTypeMap(node);
877
+ if (!responseTypes) return null;
878
+ return `responseType: { ${Object.entries(responseTypes).map(([contentType, type]) => `${JSON.stringify(contentType)}: '${type}'`).join(", ")} }`;
879
+ }
880
+ /**
827
881
  * Builds the call config literal a generated operation forwards to the client, shared by the standalone
828
882
  * functions and the SDK methods. The `throwOnError` fallback is applied after the `...config` spread.
829
883
  *
@@ -850,7 +904,6 @@ function buildCallConfig({ node, validatorHooks, security, throwOnErrorDefault,
850
904
  "error"
851
905
  ]);
852
906
  const { literal: contentTypeLiteral, merge: mergeContentType } = buildContentType({ node });
853
- const responseType = getResponseType(node);
854
907
  return {
855
908
  callConfig: `{ ${[
856
909
  `method: '${node.method.toUpperCase()}'`,
@@ -859,7 +912,7 @@ function buildCallConfig({ node, validatorHooks, security, throwOnErrorDefault,
859
912
  stylesLiteral ? `styles: ${stylesLiteral}` : null,
860
913
  validatorLiteral,
861
914
  contentTypeLiteral,
862
- responseType ? `responseType: '${responseType}'` : null,
915
+ buildResponseTypeLiteral(node),
863
916
  "...config",
864
917
  `throwOnError: config.throwOnError ?? ${throwOnErrorDefault}`
865
918
  ].filter(Boolean).join(", ")} }`,