@kubb/plugin-client 5.11.0-canary.20261106T171559 → 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) {
@@ -220,17 +263,18 @@ function spreadQuerystring(param) {
220
263
  function getOperationParameters(node) {
221
264
  const cached = operationParameterGroupsByNode.get(node);
222
265
  if (cached) return cached;
223
- const group = (location) => {
266
+ const dedupe = (params) => {
224
267
  const seen = /* @__PURE__ */ new Set();
225
- return node.parameters.filter((param) => {
226
- if (param.in !== location || seen.has(param.name)) return false;
268
+ return params.filter((param) => {
269
+ if (seen.has(param.name)) return false;
227
270
  seen.add(param.name);
228
271
  return true;
229
272
  });
230
273
  };
274
+ const group = (location) => dedupe(node.parameters.filter((param) => param.in === location));
231
275
  const groups = {
232
276
  path: group("path"),
233
- query: [...group("query"), ...group("querystring").flatMap(spreadQuerystring)],
277
+ query: dedupe([...group("query"), ...group("querystring").flatMap(spreadQuerystring)]),
234
278
  header: group("header"),
235
279
  cookie: group("cookie")
236
280
  };
@@ -464,7 +508,7 @@ var compatibility = {
464
508
  "node": ">=22.22"
465
509
  };
466
510
  // package.json
467
- var version = "5.11.0-canary.20261106T171559";
511
+ var version = "5.11.0";
468
512
  // ../../internals/client/src/builders/validatorOptions.ts
469
513
  /**
470
514
  * Returns `true` when any direction of the validator uses zod (used for dependency checks).
@@ -823,6 +867,17 @@ function buildStyles({ node }) {
823
867
  }
824
868
  // ../../internals/client/src/builders/callConfig.ts
825
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
+ /**
826
881
  * Builds the call config literal a generated operation forwards to the client, shared by the standalone
827
882
  * functions and the SDK methods. The `throwOnError` fallback is applied after the `...config` spread.
828
883
  *
@@ -849,7 +904,6 @@ function buildCallConfig({ node, validatorHooks, security, throwOnErrorDefault,
849
904
  "error"
850
905
  ]);
851
906
  const { literal: contentTypeLiteral, merge: mergeContentType } = buildContentType({ node });
852
- const responseType = getResponseType(node);
853
907
  return {
854
908
  callConfig: `{ ${[
855
909
  `method: '${node.method.toUpperCase()}'`,
@@ -858,7 +912,7 @@ function buildCallConfig({ node, validatorHooks, security, throwOnErrorDefault,
858
912
  stylesLiteral ? `styles: ${stylesLiteral}` : null,
859
913
  validatorLiteral,
860
914
  contentTypeLiteral,
861
- responseType ? `responseType: '${responseType}'` : null,
915
+ buildResponseTypeLiteral(node),
862
916
  "...config",
863
917
  `throwOnError: config.throwOnError ?? ${throwOnErrorDefault}`
864
918
  ].filter(Boolean).join(", ")} }`,