@kubb/plugin-fetch 5.13.0-canary.20261105T105941 → 5.13.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.
- package/dist/client-Dn80AjdR.d.ts +39 -0
- package/dist/core-D6FAGTsL.d.ts +2 -0
- package/dist/index.cjs +384 -226
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +385 -227
- package/dist/index.js.map +1 -1
- package/dist/templates/client.d.ts +3 -0
- package/dist/templates/core.d.ts +2 -0
- package/dist/templates/fetch.d.ts +5 -405
- package/dist/templates/serializers.d.ts +1 -179
- package/dist/templates/standardSchema.d.ts +1 -63
- package/docs/guides/server-sent-events.md +281 -45
- package/kubb-extension.json +1 -1
- package/package.json +8 -7
- package/src/generators/clientGenerator.tsx +2 -1
- package/src/plugin.ts +9 -5
- package/src/templates.ts +10 -7
- package/templates/client.ts +111 -0
- package/templates/core.ts +2 -0
- package/templates/fetch.ts +2 -913
- package/templates/serializers.ts +2 -481
- package/templates/standardSchema.ts +2 -109
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ let _kubb_plugin_zod = require("@kubb/plugin-zod");
|
|
|
30
30
|
let _kubb_renderer_jsx = require("@kubb/renderer-jsx");
|
|
31
31
|
let _kubb_plugin_ts = require("@kubb/plugin-ts");
|
|
32
32
|
let _kubb_renderer_jsx_jsx_runtime = require("@kubb/renderer-jsx/jsx-runtime");
|
|
33
|
+
let node_module = require("node:module");
|
|
33
34
|
let node_url = require("node:url");
|
|
34
35
|
// ../../internals/shared/src/operation.ts
|
|
35
36
|
/**
|
|
@@ -111,20 +112,33 @@ function getPrimarySuccessContentType(node) {
|
|
|
111
112
|
return contentTypes[0].split(";")[0].trim().toLowerCase();
|
|
112
113
|
}
|
|
113
114
|
/**
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
|
|
115
|
+
* The `text/event-stream` content of the primary success response, when it is the only content type. A response that also
|
|
116
|
+
* declares another type stays a normal call with its query hooks.
|
|
117
|
+
*/
|
|
118
|
+
function getEventStreamContent(node) {
|
|
119
|
+
return getPrimarySuccessContentType(node) === "text/event-stream" ? getPrimarySuccessResponse(node)?.content?.[0] : void 0;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Whether an operation streams its primary success response as Server-Sent Events (`text/event-stream`). The client
|
|
123
|
+
* generator uses this to return a typed event stream instead of a one-shot `RequestResult`.
|
|
117
124
|
*/
|
|
118
125
|
function isEventStream(node) {
|
|
119
|
-
return
|
|
126
|
+
return getEventStreamContent(node) !== void 0;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* How the document types a `text/event-stream` response, as the adapter read it from `itemSchema`: `event` when each item is
|
|
130
|
+
* the parsed event with its own `event` and `data`, `data` when it is only the payload. Returns `null` without an event stream.
|
|
131
|
+
*/
|
|
132
|
+
function getEventStream(node) {
|
|
133
|
+
const content = getEventStreamContent(node);
|
|
134
|
+
return content ? content.stream?.shape ?? "data" : null;
|
|
120
135
|
}
|
|
121
136
|
/**
|
|
122
137
|
* Derives the default `responseType` for an operation from its primary success response.
|
|
123
138
|
*
|
|
124
|
-
* Returns a value only when that response declares a single non-JSON content type. `text/event-stream`
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* leaving the runtime client's `Content-Type` auto-detection in charge.
|
|
139
|
+
* Returns a value only when that response declares a single non-JSON content type. `text/event-stream` maps to
|
|
140
|
+
* `'stream'`, `application/octet-stream`, `application/pdf`, `image/*`, `audio/*` and `video/*` map to `'blob'`, and
|
|
141
|
+
* other `text/*` to `'text'`. Otherwise `undefined`, leaving the runtime client's `Content-Type` auto-detection in charge.
|
|
128
142
|
*/
|
|
129
143
|
function getResponseType(node) {
|
|
130
144
|
const baseType = getPrimarySuccessContentType(node);
|
|
@@ -184,6 +198,22 @@ function buildOperationComments(node, options = {}) {
|
|
|
184
198
|
}
|
|
185
199
|
const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
|
|
186
200
|
/**
|
|
201
|
+
* An OpenAPI 3.2 `querystring` parameter is the whole query string, so a form-encoded object becomes one query parameter
|
|
202
|
+
* per property, typed and serialized like any other.
|
|
203
|
+
* Another content type, such as JSON, stays one parameter named after it, and the runtime sends its value as the whole query string.
|
|
204
|
+
*/
|
|
205
|
+
function spreadQuerystring(param) {
|
|
206
|
+
const schema = param.schema.type === "ref" ? param.schema.schema : param.schema;
|
|
207
|
+
const formEncoded = !param.contentType || param.contentType.split(";")[0].trim().toLowerCase() === "application/x-www-form-urlencoded";
|
|
208
|
+
if (schema?.type !== "object" || !formEncoded) return [param];
|
|
209
|
+
return schema.properties.map((property) => _kubb_kit.ast.factory.createParameter({
|
|
210
|
+
name: property.name,
|
|
211
|
+
in: "query",
|
|
212
|
+
schema: property.schema,
|
|
213
|
+
required: param.required && property.required
|
|
214
|
+
}));
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
187
217
|
* Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each
|
|
188
218
|
* group by name. Every plugin generator visiting the same `OperationNode` shares one AST instance
|
|
189
219
|
* (see `KubbDriver`), so the result is cached per node to avoid re-filtering and re-deduping the
|
|
@@ -192,17 +222,18 @@ const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
|
|
|
192
222
|
function getOperationParameters(node) {
|
|
193
223
|
const cached = operationParameterGroupsByNode.get(node);
|
|
194
224
|
if (cached) return cached;
|
|
195
|
-
const
|
|
225
|
+
const dedupe = (params) => {
|
|
196
226
|
const seen = /* @__PURE__ */ new Set();
|
|
197
|
-
return
|
|
198
|
-
if (
|
|
227
|
+
return params.filter((param) => {
|
|
228
|
+
if (seen.has(param.name)) return false;
|
|
199
229
|
seen.add(param.name);
|
|
200
230
|
return true;
|
|
201
231
|
});
|
|
202
232
|
};
|
|
233
|
+
const group = (location) => dedupe(node.parameters.filter((param) => param.in === location));
|
|
203
234
|
const groups = {
|
|
204
235
|
path: group("path"),
|
|
205
|
-
query: group("query"),
|
|
236
|
+
query: dedupe([...group("query"), ...group("querystring").flatMap(spreadQuerystring)]),
|
|
206
237
|
header: group("header"),
|
|
207
238
|
cookie: group("cookie")
|
|
208
239
|
};
|
|
@@ -489,6 +520,114 @@ function buildZodErrorParse(node, zodResolver) {
|
|
|
489
520
|
if (!node.responses.some((res) => !isSuccessStatusCode(res.statusCode) && res.content?.some((entry) => entry.schema))) return null;
|
|
490
521
|
return zodResolver.response.error?.(node) || null;
|
|
491
522
|
}
|
|
523
|
+
// ../../internals/client/src/builders/generics.ts
|
|
524
|
+
/**
|
|
525
|
+
* Builds the `RequestResult` generic arguments for one operation: the per-status responses record
|
|
526
|
+
* plus the per-call `ThrowOnError` flag. `SuccessOf` / `ErrorOf` split the record inside the
|
|
527
|
+
* runtime, so this only names the record and threads `ThrowOnError`.
|
|
528
|
+
*
|
|
529
|
+
* @example
|
|
530
|
+
* `buildRequestResultGenerics({ node, types }) // 'AddPetResponses, ThrowOnError'`
|
|
531
|
+
*/
|
|
532
|
+
function buildRequestResultGenerics({ node, types }) {
|
|
533
|
+
return `${types.response.responses(node)}, ThrowOnError`;
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Builds the full return type an operation's function signature uses: `Unwrappable<RequestResult>`
|
|
537
|
+
* for the default `returnType: 'full'`, already a promise so no further wrapping is needed, a plain
|
|
538
|
+
* `Promise<RequestResult>` for the internal `'plain'` shape, or a
|
|
539
|
+
* `Promise` of the runtime's `UnwrappedResult` when `returnType: 'data'` narrows a resolved call
|
|
540
|
+
* down to the bare success body.
|
|
541
|
+
*
|
|
542
|
+
* @example
|
|
543
|
+
* `buildResultType({ node, types, returnType: 'data' }) // 'Promise<UnwrappedResult<AddPetResponses, ThrowOnError>>'`
|
|
544
|
+
*/
|
|
545
|
+
function buildResultType({ node, types, returnType }) {
|
|
546
|
+
const generics = buildRequestResultGenerics({
|
|
547
|
+
node,
|
|
548
|
+
types
|
|
549
|
+
});
|
|
550
|
+
if (returnType === "data") return `Promise<UnwrappedResult<${generics}>>`;
|
|
551
|
+
if (returnType === "plain") return `Promise<RequestResult<${generics}>>`;
|
|
552
|
+
return `Unwrappable<RequestResult<${generics}>>`;
|
|
553
|
+
}
|
|
554
|
+
// ../../internals/client/src/builders/returnStatement.ts
|
|
555
|
+
/**
|
|
556
|
+
* Builds the return statement of a generated operation function. With the default
|
|
557
|
+
* `returnType: 'full'` the runtime call already resolves to `{ data, error, request, response }`.
|
|
558
|
+
* The generated code casts that result to the operation's `RequestResult`, then wraps it with
|
|
559
|
+
* `withUnwrap`, so the caller can `await` it directly or call `.unwrap()` for the bare success
|
|
560
|
+
* body. With `returnType: 'data'` it instead routes the call through the runtime's `unwrapResult`,
|
|
561
|
+
* which narrows the resolved value down to the bare success body the same way `RequestResult`
|
|
562
|
+
* already does, using the plugin default when the call leaves `throwOnError` unset.
|
|
563
|
+
* With `returnType: 'plain'` it returns the runtime call as is, cast to `RequestResult`, with no helper.
|
|
564
|
+
*
|
|
565
|
+
* Cast first, wrap second, for the `'full'` path. That order keeps `withUnwrap`'s generic inferred
|
|
566
|
+
* as `RequestResult` instead of the runtime's own internal result type. Casting an `Unwrappable<A>`
|
|
567
|
+
* straight to `Unwrappable<B>` does not work: the `.then` overload stays pinned to `A`, and `as`
|
|
568
|
+
* rejects that two-generic swap even where `A` and `B` on their own would satisfy it.
|
|
569
|
+
*
|
|
570
|
+
* @example
|
|
571
|
+
* `return withUnwrap(request({ method: 'POST', url: '/pet', ...config }) as Promise<RequestResult<AddPetResponses, ThrowOnError>>)`
|
|
572
|
+
* @example
|
|
573
|
+
* `return unwrapResult(request({ method: 'POST', url: '/pet', ...config }), config.throwOnError ?? false) as Promise<UnwrappedResult<AddPetResponses, ThrowOnError>>`
|
|
574
|
+
* @example
|
|
575
|
+
* `return request({ method: 'POST', url: '/pet', ...config }) as Promise<RequestResult<AddPetResponses, ThrowOnError>>`
|
|
576
|
+
*/
|
|
577
|
+
function buildReturnStatement({ node, types, callConfig, returnType, throwOnErrorDefault }) {
|
|
578
|
+
const request = returnType !== "plain" && hasRequestContentTypeChoice(node) ? `request<${types.response.options(node)}['body']>` : "request";
|
|
579
|
+
if (returnType === "data") return `return unwrapResult(${request}(${callConfig}), config.throwOnError ?? ${throwOnErrorDefault}) as ${buildResultType({
|
|
580
|
+
node,
|
|
581
|
+
types,
|
|
582
|
+
returnType
|
|
583
|
+
})}`;
|
|
584
|
+
if (returnType === "plain") return `return ${request}(${callConfig}) as Promise<RequestResult<${buildRequestResultGenerics({
|
|
585
|
+
node,
|
|
586
|
+
types
|
|
587
|
+
})}>>`;
|
|
588
|
+
return `return withUnwrap(${request}(${callConfig}) as Promise<RequestResult<${buildRequestResultGenerics({
|
|
589
|
+
node,
|
|
590
|
+
types
|
|
591
|
+
})}>>)`;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Builds the return type and statement of a `text/event-stream` operation. The item type is `TypedEvent<...>` when each item
|
|
595
|
+
* declares its own `event` and `data`, and otherwise the payload type, which `EventStreamResult` wraps in `ServerSentEvent`. The call's
|
|
596
|
+
* promise goes through `toEventStream` with the `client` for its defaults, the call's `config`, the shape and the per-event
|
|
597
|
+
* validator. A `returnType: 'plain'` client receives only the promise,
|
|
598
|
+
* `toEventStream(request(config))`, and keeps its response validator in the call config.
|
|
599
|
+
*/
|
|
600
|
+
function buildEventStreamReturn({ node, types, callConfig, returnType, validatorHooks, throwOnErrorDefault }) {
|
|
601
|
+
const shape = getEventStream(node) ?? "data";
|
|
602
|
+
const responses = types.response.responses(node);
|
|
603
|
+
const success = `SuccessOf<${responses}>`;
|
|
604
|
+
const eventType = shape === "event" ? `TypedEvent<${success}>` : success;
|
|
605
|
+
if (returnType === "plain") return {
|
|
606
|
+
returnType: `Promise<EventStreamResult<${eventType}>>`,
|
|
607
|
+
statement: `return toEventStream<${eventType}>(request(${callConfig}))`
|
|
608
|
+
};
|
|
609
|
+
const generics = `${responses}, ThrowOnError${shape === "event" ? `, ${eventType}` : ""}`;
|
|
610
|
+
const call = `toEventStream<${eventType}>(request(${callConfig}), { client: request, config, ${[`shape: '${shape}'`, validatorHooks?.response ? `validator: ${validatorHooks.response}` : null].filter(Boolean).join(", ")} })`;
|
|
611
|
+
if (returnType === "data") {
|
|
612
|
+
const result = `Promise<UnwrappedStreamResult<${generics}>>`;
|
|
613
|
+
return {
|
|
614
|
+
returnType: result,
|
|
615
|
+
statement: `return unwrapResult(${call}, config.throwOnError ?? ${throwOnErrorDefault}) as ${result}`
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
return {
|
|
619
|
+
returnType: `Unwrappable<StreamResult<${generics}>>`,
|
|
620
|
+
statement: `return withUnwrap(${call} as Promise<StreamResult<${generics}>>)`
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
/** The stream types an operation file imports: `StreamResult` and `StreamOptions`, `EventStreamResult` for a plain client, and `TypedEvent` for named events. */
|
|
624
|
+
function buildEventStreamImports({ returnType, typed }) {
|
|
625
|
+
return [...{
|
|
626
|
+
plain: ["EventStreamResult"],
|
|
627
|
+
full: ["StreamResult", "StreamOptions"],
|
|
628
|
+
data: ["UnwrappedStreamResult", "StreamOptions"]
|
|
629
|
+
}[returnType], ...typed ? ["TypedEvent"] : []];
|
|
630
|
+
}
|
|
492
631
|
// ../../internals/client/src/builders/security.ts
|
|
493
632
|
function serializeAuth(auth) {
|
|
494
633
|
const parts = [`type: '${auth.type}'`];
|
|
@@ -644,6 +783,7 @@ function serializeParameter(parameter) {
|
|
|
644
783
|
if (parameter.explode !== void 0) parts.push(`explode: ${parameter.explode}`);
|
|
645
784
|
if (parameter.in === "query" && parameter.allowReserved !== void 0) parts.push(`allowReserved: ${parameter.allowReserved}`);
|
|
646
785
|
if (parameter.in !== "path" && parameter.contentType) parts.push(`contentType: '${parameter.contentType}'`);
|
|
786
|
+
if (parameter.in === "querystring") parts.push("querystring: true");
|
|
647
787
|
return parts.length > 0 ? `{ ${parts.join(", ")} }` : null;
|
|
648
788
|
}
|
|
649
789
|
/**
|
|
@@ -686,10 +826,9 @@ function buildStyles({ node }) {
|
|
|
686
826
|
header: [],
|
|
687
827
|
cookie: []
|
|
688
828
|
};
|
|
689
|
-
for (const parameter of
|
|
829
|
+
for (const [location, parameters] of Object.entries(getOperationParameters(node))) for (const parameter of parameters) {
|
|
690
830
|
const literal = serializeParameter(parameter);
|
|
691
|
-
if (
|
|
692
|
-
groups[parameter.in].push(`${toKey(parameter.name)}: ${literal}`);
|
|
831
|
+
if (literal) groups[location].push(`${toKey(parameter.name)}: ${literal}`);
|
|
693
832
|
}
|
|
694
833
|
const entries = [...Object.keys(groups).filter((location) => groups[location].length > 0).map((location) => `${location}: { ${groups[location].join(", ")} }`), serializeBodyEncoding(node)].filter(Boolean);
|
|
695
834
|
return entries.length > 0 ? `{ ${entries.join(", ")} }` : null;
|
|
@@ -700,12 +839,20 @@ function buildStyles({ node }) {
|
|
|
700
839
|
* functions and the SDK methods. The `throwOnError` fallback is applied after the `...config` spread.
|
|
701
840
|
*
|
|
702
841
|
* `mergeContentType` is `true` when the caller must destructure `contentType` from `options`, and
|
|
703
|
-
* `eventStream` is `true` when the operation returns `text/event-stream`.
|
|
842
|
+
* `eventStream` is `true` when the operation returns `text/event-stream`. Unless `returnType` is `'plain'`, a
|
|
843
|
+
* stream's literal leaves the `response` validator to `toEventStream`, which runs it per event.
|
|
704
844
|
*/
|
|
705
|
-
function buildCallConfig({ node, validatorHooks, security, throwOnErrorDefault }) {
|
|
845
|
+
function buildCallConfig({ node, validatorHooks, security, throwOnErrorDefault, returnType }) {
|
|
846
|
+
const eventStream = isEventStream(node);
|
|
706
847
|
const securityLiteral = buildSecurityMetadata({ security });
|
|
707
848
|
const stylesLiteral = buildStyles({ node });
|
|
708
|
-
const validatorLiteral = buildValidatorLiteral(validatorHooks, [
|
|
849
|
+
const validatorLiteral = buildValidatorLiteral(validatorHooks, eventStream && returnType !== "plain" ? [
|
|
850
|
+
"request",
|
|
851
|
+
"path",
|
|
852
|
+
"query",
|
|
853
|
+
"headers",
|
|
854
|
+
"error"
|
|
855
|
+
] : [
|
|
709
856
|
"request",
|
|
710
857
|
"path",
|
|
711
858
|
"query",
|
|
@@ -728,88 +875,7 @@ function buildCallConfig({ node, validatorHooks, security, throwOnErrorDefault }
|
|
|
728
875
|
`throwOnError: config.throwOnError ?? ${throwOnErrorDefault}`
|
|
729
876
|
].filter(Boolean).join(", ")} }`,
|
|
730
877
|
mergeContentType,
|
|
731
|
-
eventStream
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
|
-
// ../../internals/client/src/builders/generics.ts
|
|
735
|
-
/**
|
|
736
|
-
* Builds the `RequestResult` generic arguments for one operation: the per-status responses record
|
|
737
|
-
* plus the per-call `ThrowOnError` flag. `SuccessOf` / `ErrorOf` split the record inside the
|
|
738
|
-
* runtime, so this only names the record and threads `ThrowOnError`.
|
|
739
|
-
*
|
|
740
|
-
* @example
|
|
741
|
-
* `buildRequestResultGenerics({ node, types }) // 'AddPetResponses, ThrowOnError'`
|
|
742
|
-
*/
|
|
743
|
-
function buildRequestResultGenerics({ node, types }) {
|
|
744
|
-
return `${types.response.responses(node)}, ThrowOnError`;
|
|
745
|
-
}
|
|
746
|
-
/**
|
|
747
|
-
* Builds the full return type an operation's function signature uses: `Unwrappable<RequestResult>`
|
|
748
|
-
* for the default `returnType: 'full'`, already a promise so no further wrapping is needed, a plain
|
|
749
|
-
* `Promise<RequestResult>` for the internal `'plain'` shape, or a
|
|
750
|
-
* `Promise` of the runtime's `UnwrappedResult` when `returnType: 'data'` narrows a resolved call
|
|
751
|
-
* down to the bare success body.
|
|
752
|
-
*
|
|
753
|
-
* @example
|
|
754
|
-
* `buildResultType({ node, types, returnType: 'data' }) // 'Promise<UnwrappedResult<AddPetResponses, ThrowOnError>>'`
|
|
755
|
-
*/
|
|
756
|
-
function buildResultType({ node, types, returnType }) {
|
|
757
|
-
const generics = buildRequestResultGenerics({
|
|
758
|
-
node,
|
|
759
|
-
types
|
|
760
|
-
});
|
|
761
|
-
if (returnType === "data") return `Promise<UnwrappedResult<${generics}>>`;
|
|
762
|
-
if (returnType === "plain") return `Promise<RequestResult<${generics}>>`;
|
|
763
|
-
return `Unwrappable<RequestResult<${generics}>>`;
|
|
764
|
-
}
|
|
765
|
-
// ../../internals/client/src/builders/returnStatement.ts
|
|
766
|
-
/**
|
|
767
|
-
* Builds the return statement of a generated operation function. With the default
|
|
768
|
-
* `returnType: 'full'` the runtime call already resolves to `{ data, error, request, response }`.
|
|
769
|
-
* The generated code casts that result to the operation's `RequestResult`, then wraps it with
|
|
770
|
-
* `withUnwrap`, so the caller can `await` it directly or call `.unwrap()` for the bare success
|
|
771
|
-
* body. With `returnType: 'data'` it instead routes the call through the runtime's `unwrapResult`,
|
|
772
|
-
* which narrows the resolved value down to the bare success body the same way `RequestResult`
|
|
773
|
-
* already does, using the plugin default when the call leaves `throwOnError` unset.
|
|
774
|
-
* With `returnType: 'plain'` it returns the runtime call as is, cast to `RequestResult`, with no helper.
|
|
775
|
-
*
|
|
776
|
-
* Cast first, wrap second, for the `'full'` path. That order keeps `withUnwrap`'s generic inferred
|
|
777
|
-
* as `RequestResult` instead of the runtime's own internal result type. Casting an `Unwrappable<A>`
|
|
778
|
-
* straight to `Unwrappable<B>` does not work: the `.then` overload stays pinned to `A`, and `as`
|
|
779
|
-
* rejects that two-generic swap even where `A` and `B` on their own would satisfy it.
|
|
780
|
-
*
|
|
781
|
-
* @example
|
|
782
|
-
* `return withUnwrap(request({ method: 'POST', url: '/pet', ...config }) as Promise<RequestResult<AddPetResponses, ThrowOnError>>)`
|
|
783
|
-
* @example
|
|
784
|
-
* `return unwrapResult(request({ method: 'POST', url: '/pet', ...config }), config.throwOnError ?? false) as Promise<UnwrappedResult<AddPetResponses, ThrowOnError>>`
|
|
785
|
-
* @example
|
|
786
|
-
* `return request({ method: 'POST', url: '/pet', ...config }) as Promise<RequestResult<AddPetResponses, ThrowOnError>>`
|
|
787
|
-
*/
|
|
788
|
-
function buildReturnStatement({ node, types, callConfig, returnType, throwOnErrorDefault }) {
|
|
789
|
-
const request = returnType !== "plain" && hasRequestContentTypeChoice(node) ? `request<${types.response.options(node)}['body']>` : "request";
|
|
790
|
-
if (returnType === "data") return `return unwrapResult(${request}(${callConfig}), config.throwOnError ?? ${throwOnErrorDefault}) as ${buildResultType({
|
|
791
|
-
node,
|
|
792
|
-
types,
|
|
793
|
-
returnType
|
|
794
|
-
})}`;
|
|
795
|
-
if (returnType === "plain") return `return ${request}(${callConfig}) as Promise<RequestResult<${buildRequestResultGenerics({
|
|
796
|
-
node,
|
|
797
|
-
types
|
|
798
|
-
})}>>`;
|
|
799
|
-
return `return withUnwrap(${request}(${callConfig}) as Promise<RequestResult<${buildRequestResultGenerics({
|
|
800
|
-
node,
|
|
801
|
-
types
|
|
802
|
-
})}>>)`;
|
|
803
|
-
}
|
|
804
|
-
/**
|
|
805
|
-
* Builds the return type and statement of an operation that returns `text/event-stream`: the call
|
|
806
|
-
* is wrapped in `toEventStream`, so the caller iterates the typed success events.
|
|
807
|
-
*/
|
|
808
|
-
function buildEventStreamReturn({ node, types, callConfig }) {
|
|
809
|
-
const eventType = `SuccessOf<${types.response.responses(node)}>`;
|
|
810
|
-
return {
|
|
811
|
-
returnType: `Promise<EventStreamResult<${eventType}>>`,
|
|
812
|
-
statement: `return toEventStream<${eventType}>(request(${callConfig}))`
|
|
878
|
+
eventStream
|
|
813
879
|
};
|
|
814
880
|
}
|
|
815
881
|
// ../../internals/client/src/builders/signature.ts
|
|
@@ -823,13 +889,14 @@ const declarationPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declara
|
|
|
823
889
|
* per-operation input type has to be emitted. Both names come from `types`, which is `plugin-ts` or
|
|
824
890
|
* `plugin-zod`'s inferred types (see `resolveOperationTypes`).
|
|
825
891
|
*/
|
|
826
|
-
function buildGroupedOptionsSignature({ node, types, returnType, throwOnErrorDefault }) {
|
|
892
|
+
function buildGroupedOptionsSignature({ node, types, returnType, throwOnErrorDefault, eventStream = false }) {
|
|
827
893
|
const optionsName = types.response.options(node);
|
|
894
|
+
const optionsType = `${eventStream && returnType !== "plain" ? "StreamOptions" : "Options"}<${optionsName}, ThrowOnError>`;
|
|
828
895
|
const { isOptional } = getRequestGroupOptionality(node);
|
|
829
896
|
return {
|
|
830
897
|
paramsSignature: declarationPrinter.print((0, _kubb_plugin_ts.createFunctionParameters)({ params: [(0, _kubb_plugin_ts.createFunctionParameter)({
|
|
831
898
|
name: "options",
|
|
832
|
-
type:
|
|
899
|
+
type: optionsType,
|
|
833
900
|
...isOptional ? { default: "{}" } : {}
|
|
834
901
|
})] })) ?? "",
|
|
835
902
|
returnType: buildResultType({
|
|
@@ -840,37 +907,63 @@ function buildGroupedOptionsSignature({ node, types, returnType, throwOnErrorDef
|
|
|
840
907
|
generics: [`ThrowOnError extends boolean = ${throwOnErrorDefault}`]
|
|
841
908
|
};
|
|
842
909
|
}
|
|
843
|
-
// ../../internals/client/src/
|
|
910
|
+
// ../../internals/client/src/builders/operationBody.ts
|
|
844
911
|
/**
|
|
845
|
-
*
|
|
846
|
-
*
|
|
847
|
-
*
|
|
848
|
-
* the source.
|
|
912
|
+
* The pieces of a generated operation: its generics, `options` parameter, return type, return statement, and whether the
|
|
913
|
+
* body destructures `contentType` from `options`. Shared by the standalone functions and the SDK methods, so a
|
|
914
|
+
* `text/event-stream` operation is wired to `toEventStream` in one place.
|
|
849
915
|
*/
|
|
850
|
-
function
|
|
851
|
-
|
|
916
|
+
function buildOperationBody({ node, types, validatorHooks, security, returnType, throwOnErrorDefault }) {
|
|
917
|
+
const { callConfig, mergeContentType, eventStream } = buildCallConfig({
|
|
918
|
+
node,
|
|
919
|
+
validatorHooks,
|
|
920
|
+
security,
|
|
921
|
+
throwOnErrorDefault,
|
|
922
|
+
returnType
|
|
923
|
+
});
|
|
852
924
|
const signature = buildGroupedOptionsSignature({
|
|
853
925
|
node,
|
|
854
926
|
types,
|
|
855
927
|
returnType,
|
|
856
|
-
throwOnErrorDefault
|
|
928
|
+
throwOnErrorDefault,
|
|
929
|
+
eventStream
|
|
857
930
|
});
|
|
858
|
-
const
|
|
931
|
+
const stream = eventStream ? buildEventStreamReturn({
|
|
859
932
|
node,
|
|
933
|
+
types,
|
|
934
|
+
callConfig,
|
|
935
|
+
returnType,
|
|
860
936
|
validatorHooks,
|
|
861
|
-
security,
|
|
862
937
|
throwOnErrorDefault
|
|
863
|
-
});
|
|
864
|
-
const eventStreamReturn = eventStream ? buildEventStreamReturn({
|
|
865
|
-
node,
|
|
866
|
-
types,
|
|
867
|
-
callConfig
|
|
868
938
|
}) : null;
|
|
869
|
-
|
|
870
|
-
|
|
939
|
+
return {
|
|
940
|
+
generics: signature.generics,
|
|
941
|
+
paramsSignature: signature.paramsSignature,
|
|
942
|
+
returnType: stream?.returnType ?? signature.returnType,
|
|
943
|
+
statement: stream?.statement ?? buildReturnStatement({
|
|
944
|
+
node,
|
|
945
|
+
types,
|
|
946
|
+
callConfig,
|
|
947
|
+
returnType,
|
|
948
|
+
throwOnErrorDefault
|
|
949
|
+
}),
|
|
950
|
+
mergeContentType
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
// ../../internals/client/src/components/Operation.tsx
|
|
954
|
+
/**
|
|
955
|
+
* Renders one client operation: the grouped `<Name>Request` type and the function that forwards a
|
|
956
|
+
* single `options` object to the resolved client and returns the `Unwrappable<RequestResult>`. The
|
|
957
|
+
* type, signature, and call config are built with the AST factory, and only the jsx-renderer emits
|
|
958
|
+
* the source.
|
|
959
|
+
*/
|
|
960
|
+
function Operation({ name, node, types, validatorHooks, returnType, throwOnErrorDefault, security }) {
|
|
961
|
+
if (!_kubb_kit.ast.isHttpOperationNode(node)) return null;
|
|
962
|
+
const body = buildOperationBody({
|
|
871
963
|
node,
|
|
872
964
|
types,
|
|
873
|
-
|
|
965
|
+
validatorHooks,
|
|
966
|
+
security,
|
|
874
967
|
returnType,
|
|
875
968
|
throwOnErrorDefault
|
|
876
969
|
});
|
|
@@ -881,22 +974,53 @@ function Operation({ name, node, types, validatorHooks, returnType, throwOnError
|
|
|
881
974
|
children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.Function, {
|
|
882
975
|
name,
|
|
883
976
|
export: true,
|
|
884
|
-
generics:
|
|
885
|
-
params:
|
|
886
|
-
returnType:
|
|
977
|
+
generics: body.generics,
|
|
978
|
+
params: body.paramsSignature,
|
|
979
|
+
returnType: body.returnType,
|
|
887
980
|
JSDoc: { comments: buildOperationComments(node, {
|
|
888
981
|
link: "urlPath",
|
|
889
982
|
linkPosition: "beforeDeprecated",
|
|
890
983
|
splitLines: true
|
|
891
984
|
}) },
|
|
892
985
|
children: [
|
|
893
|
-
mergeContentType ? "const { client: request = client, contentType, ...config } = options" : "const { client: request = client, ...config } = options",
|
|
986
|
+
body.mergeContentType ? "const { client: request = client, contentType, ...config } = options" : "const { client: request = client, ...config } = options",
|
|
894
987
|
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)("br", {}),
|
|
895
|
-
|
|
988
|
+
body.statement
|
|
896
989
|
]
|
|
897
990
|
})
|
|
898
991
|
});
|
|
899
992
|
}
|
|
993
|
+
// ../../internals/client/src/components/StreamRuntime.tsx
|
|
994
|
+
/**
|
|
995
|
+
* The `footer` of `.kubb/client.ts`: the `baseURL` set at generation time, and the `sse.ts` re-export when the document
|
|
996
|
+
* streams events, so `ServerSentEvent` and `toEventStream` stay importable from the client as in earlier releases.
|
|
997
|
+
*/
|
|
998
|
+
function buildClientFooter({ baseURL, sse }) {
|
|
999
|
+
const baseURLExpression = baseURL ? baseURL.includes("${") ? `\`${baseURL.replaceAll("`", "\\`")}\`` : JSON.stringify(baseURL) : void 0;
|
|
1000
|
+
return [baseURLExpression ? `client.setConfig({ baseURL: ${baseURLExpression} })` : null, sse ? `export * from './sse.ts'` : null].filter(Boolean).join("\n") || void 0;
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Writes the footer of the `.kubb/client.ts` the plugin injected, the one place it is built, and copies `sse.ts` into
|
|
1004
|
+
* `.kubb/` only for a document with a `text/event-stream` operation, so a document without streams ships no stream runtime.
|
|
1005
|
+
* `sse` is set by the plugins that ship the runtime, so a custom client from `@kubb/plugin-client` gets neither file.
|
|
1006
|
+
*/
|
|
1007
|
+
function StreamRuntime({ nodes, root, sse, baseURL }) {
|
|
1008
|
+
if (!sse) return null;
|
|
1009
|
+
const streams = nodes.some(isEventStream);
|
|
1010
|
+
const footer = buildClientFooter({
|
|
1011
|
+
baseURL,
|
|
1012
|
+
sse: streams
|
|
1013
|
+
});
|
|
1014
|
+
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [streams && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File, {
|
|
1015
|
+
baseName: "sse.ts",
|
|
1016
|
+
path: node_path.default.resolve(root, ".kubb/sse.ts"),
|
|
1017
|
+
copy: sse
|
|
1018
|
+
}), footer && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File, {
|
|
1019
|
+
baseName: "client.ts",
|
|
1020
|
+
path: node_path.default.resolve(root, ".kubb/client.ts"),
|
|
1021
|
+
footer
|
|
1022
|
+
})] });
|
|
1023
|
+
}
|
|
900
1024
|
// ../../internals/client/src/resolveOperationTypes.ts
|
|
901
1025
|
/**
|
|
902
1026
|
* A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`
|
|
@@ -972,13 +1096,24 @@ function resolveOperationTypes(driver, pluginName) {
|
|
|
972
1096
|
* `@kubb/plugin-axios`). Emits one async function per OpenAPI operation using the shared
|
|
973
1097
|
* `Operation` component: a grouped `<Name>Request` type and a function that forwards a single
|
|
974
1098
|
* `options` object to the bundled `client` and returns the `Unwrappable<RequestResult>`. Only the
|
|
975
|
-
* generator `name`
|
|
976
|
-
* identical.
|
|
1099
|
+
* generator `name` and the runtime templates differ between plugins. Every other resolution, import,
|
|
1100
|
+
* and rendering step is identical.
|
|
1101
|
+
*
|
|
1102
|
+
* `sse` is the Server-Sent Events runtime template, copied into `.kubb/sse.ts` only for a document with a
|
|
1103
|
+
* `text/event-stream` operation.
|
|
977
1104
|
*/
|
|
978
|
-
function createClientGenerator(name) {
|
|
1105
|
+
function createClientGenerator(name, { sse } = {}) {
|
|
979
1106
|
return (0, _kubb_kit.defineGenerator)({
|
|
980
1107
|
name,
|
|
981
1108
|
renderer: _kubb_renderer_jsx.jsxRenderer,
|
|
1109
|
+
operations(nodes, ctx) {
|
|
1110
|
+
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(StreamRuntime, {
|
|
1111
|
+
nodes,
|
|
1112
|
+
root: ctx.root,
|
|
1113
|
+
sse,
|
|
1114
|
+
baseURL: ctx.options.baseURL
|
|
1115
|
+
});
|
|
1116
|
+
},
|
|
982
1117
|
operation(node, ctx) {
|
|
983
1118
|
if (!_kubb_kit.ast.isHttpOperationNode(node)) return null;
|
|
984
1119
|
const { config, driver, resolver, root } = ctx;
|
|
@@ -1028,19 +1163,19 @@ function createClientGenerator(name) {
|
|
|
1028
1163
|
const clientPath = importPath ?? node_path.default.resolve(root, ".kubb/client.ts");
|
|
1029
1164
|
const clientRoot = importPath === void 0 ? meta.file.path : void 0;
|
|
1030
1165
|
const standardSchemaPath = importPath ?? node_path.default.resolve(root, ".kubb/standardSchema.ts");
|
|
1031
|
-
const
|
|
1166
|
+
const ssePath = importPath ?? node_path.default.resolve(root, ".kubb/sse.ts");
|
|
1167
|
+
const stream = getEventStream(node);
|
|
1032
1168
|
const clientValueImports = (() => {
|
|
1033
|
-
if (eventStream) return ["client", "toEventStream"];
|
|
1034
1169
|
if (returnType === "plain") return ["client"];
|
|
1035
1170
|
if (returnType === "data") return ["client", "unwrapResult"];
|
|
1036
1171
|
return ["client", "withUnwrap"];
|
|
1037
1172
|
})();
|
|
1038
1173
|
const clientTypeImports = (() => {
|
|
1039
|
-
if (
|
|
1040
|
-
"Options",
|
|
1041
|
-
"
|
|
1042
|
-
"SuccessOf"
|
|
1043
|
-
];
|
|
1174
|
+
if (stream) return {
|
|
1175
|
+
plain: ["Options", "SuccessOf"],
|
|
1176
|
+
data: ["SuccessOf"],
|
|
1177
|
+
full: ["SuccessOf", "Unwrappable"]
|
|
1178
|
+
}[returnType];
|
|
1044
1179
|
if (returnType === "plain") return ["Options", "RequestResult"];
|
|
1045
1180
|
if (returnType === "data") return ["Options", "UnwrappedResult"];
|
|
1046
1181
|
return [
|
|
@@ -1081,6 +1216,20 @@ function createClientGenerator(name) {
|
|
|
1081
1216
|
path: clientPath,
|
|
1082
1217
|
isTypeOnly: true
|
|
1083
1218
|
}),
|
|
1219
|
+
stream && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1220
|
+
name: ["toEventStream"],
|
|
1221
|
+
root: clientRoot,
|
|
1222
|
+
path: ssePath
|
|
1223
|
+
}),
|
|
1224
|
+
stream && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1225
|
+
name: buildEventStreamImports({
|
|
1226
|
+
returnType,
|
|
1227
|
+
typed: stream === "event"
|
|
1228
|
+
}),
|
|
1229
|
+
root: clientRoot,
|
|
1230
|
+
path: ssePath,
|
|
1231
|
+
isTypeOnly: true
|
|
1232
|
+
}),
|
|
1084
1233
|
meta.fileTypes && importedTypeNames.length > 0 && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1085
1234
|
name: Array.from(new Set(importedTypeNames)),
|
|
1086
1235
|
root: meta.file.path,
|
|
@@ -1117,43 +1266,26 @@ function createClientGenerator(name) {
|
|
|
1117
1266
|
*/
|
|
1118
1267
|
function buildSdkMethod({ node, name, types, validatorHooks, security, returnType, throwOnErrorDefault }) {
|
|
1119
1268
|
if (!_kubb_kit.ast.isHttpOperationNode(node)) return "";
|
|
1120
|
-
const
|
|
1269
|
+
const body = buildOperationBody({
|
|
1121
1270
|
node,
|
|
1122
1271
|
types,
|
|
1123
|
-
returnType,
|
|
1124
|
-
throwOnErrorDefault
|
|
1125
|
-
});
|
|
1126
|
-
const { callConfig, mergeContentType, eventStream } = buildCallConfig({
|
|
1127
|
-
node,
|
|
1128
1272
|
validatorHooks,
|
|
1129
1273
|
security,
|
|
1130
|
-
throwOnErrorDefault
|
|
1131
|
-
});
|
|
1132
|
-
const eventStreamReturn = eventStream ? buildEventStreamReturn({
|
|
1133
|
-
node,
|
|
1134
|
-
types,
|
|
1135
|
-
callConfig
|
|
1136
|
-
}) : null;
|
|
1137
|
-
const methodReturnType = eventStreamReturn?.returnType ?? signature.returnType;
|
|
1138
|
-
const returnStatement = eventStreamReturn?.statement ?? buildReturnStatement({
|
|
1139
|
-
node,
|
|
1140
|
-
types,
|
|
1141
|
-
callConfig,
|
|
1142
1274
|
returnType,
|
|
1143
1275
|
throwOnErrorDefault
|
|
1144
1276
|
});
|
|
1145
|
-
const generics =
|
|
1277
|
+
const generics = body.generics.length ? `<${body.generics.join(", ")}>` : "";
|
|
1146
1278
|
const jsdoc = buildJSDoc(buildOperationComments(node, {
|
|
1147
1279
|
link: "urlPath",
|
|
1148
1280
|
linkPosition: "beforeDeprecated",
|
|
1149
1281
|
splitLines: true
|
|
1150
1282
|
}));
|
|
1151
1283
|
const methodBody = [
|
|
1152
|
-
mergeContentType ? "const { client: request = this.client, contentType, ...config } = options" : "const { client: request = this.client, ...config } = options",
|
|
1284
|
+
body.mergeContentType ? "const { client: request = this.client, contentType, ...config } = options" : "const { client: request = this.client, ...config } = options",
|
|
1153
1285
|
"",
|
|
1154
|
-
|
|
1286
|
+
body.statement
|
|
1155
1287
|
].map((line) => line ? ` ${line}` : "").join("\n");
|
|
1156
|
-
return `${jsdoc} public ${name}${generics}(${
|
|
1288
|
+
return `${jsdoc} public ${name}${generics}(${body.paramsSignature}): ${body.returnType} {\n${methodBody}\n }`;
|
|
1157
1289
|
}
|
|
1158
1290
|
/**
|
|
1159
1291
|
* Renders one instance class per tag with one method per operation. The constructor takes a client
|
|
@@ -1309,8 +1441,11 @@ function collectImportsByFile(ops, pick) {
|
|
|
1309
1441
|
* emits one class per tag and, when `sdk.name` is set, a composed root that instantiates every tag
|
|
1310
1442
|
* client. With `sdk.mode: 'flat'` it emits one class named by `sdk.name`, with every operation as a
|
|
1311
1443
|
* direct method.
|
|
1444
|
+
*
|
|
1445
|
+
* `sse` is the Server-Sent Events runtime template, copied into `.kubb/sse.ts` only for a document with a
|
|
1446
|
+
* `text/event-stream` operation.
|
|
1312
1447
|
*/
|
|
1313
|
-
function createSdkGenerator() {
|
|
1448
|
+
function createSdkGenerator({ sse } = {}) {
|
|
1314
1449
|
return (0, _kubb_kit.defineGenerator)({
|
|
1315
1450
|
name: "sdk",
|
|
1316
1451
|
renderer: _kubb_renderer_jsx.jsxRenderer,
|
|
@@ -1331,6 +1466,7 @@ function createSdkGenerator() {
|
|
|
1331
1466
|
const controllers = buildControllers(nodes, ctx, types, validatorEnabled);
|
|
1332
1467
|
const clientPath = node_path.default.resolve(root, ".kubb/client.ts");
|
|
1333
1468
|
const standardSchemaPath = node_path.default.resolve(root, ".kubb/standardSchema.ts");
|
|
1469
|
+
const ssePath = node_path.default.resolve(root, ".kubb/sse.ts");
|
|
1334
1470
|
const banner = (file) => resolver.default.banner(ctx.meta, {
|
|
1335
1471
|
output,
|
|
1336
1472
|
config,
|
|
@@ -1359,7 +1495,8 @@ function createSdkGenerator() {
|
|
|
1359
1495
|
namesByPath: /* @__PURE__ */ new Map(),
|
|
1360
1496
|
filesByPath: /* @__PURE__ */ new Map()
|
|
1361
1497
|
};
|
|
1362
|
-
const
|
|
1498
|
+
const shapes = new Set(ops.map((op) => getEventStream(op.node)).filter(Boolean));
|
|
1499
|
+
const hasEventStream = shapes.size > 0;
|
|
1363
1500
|
const hasResult = ops.some((op) => !isEventStream(op.node));
|
|
1364
1501
|
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
|
|
1365
1502
|
baseName: file.baseName,
|
|
@@ -1369,11 +1506,7 @@ function createSdkGenerator() {
|
|
|
1369
1506
|
footer: footer(file),
|
|
1370
1507
|
children: [
|
|
1371
1508
|
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1372
|
-
name: [
|
|
1373
|
-
"createClient",
|
|
1374
|
-
...hasResult ? [returnType === "data" ? "unwrapResult" : "withUnwrap"] : [],
|
|
1375
|
-
...hasEventStream ? ["toEventStream"] : []
|
|
1376
|
-
],
|
|
1509
|
+
name: ["createClient", returnType === "data" ? "unwrapResult" : "withUnwrap"],
|
|
1377
1510
|
root: file.path,
|
|
1378
1511
|
path: clientPath
|
|
1379
1512
|
}),
|
|
@@ -1382,13 +1515,28 @@ function createSdkGenerator() {
|
|
|
1382
1515
|
"ClientConfig",
|
|
1383
1516
|
"ClientInstance",
|
|
1384
1517
|
"Options",
|
|
1385
|
-
...
|
|
1386
|
-
...
|
|
1518
|
+
...returnType === "data" ? [] : ["Unwrappable"],
|
|
1519
|
+
...hasResult ? [returnType === "data" ? "UnwrappedResult" : "RequestResult"] : [],
|
|
1520
|
+
...hasEventStream ? ["SuccessOf"] : []
|
|
1387
1521
|
],
|
|
1388
1522
|
root: file.path,
|
|
1389
1523
|
path: clientPath,
|
|
1390
1524
|
isTypeOnly: true
|
|
1391
1525
|
}),
|
|
1526
|
+
hasEventStream && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1527
|
+
name: ["toEventStream"],
|
|
1528
|
+
root: file.path,
|
|
1529
|
+
path: ssePath
|
|
1530
|
+
}),
|
|
1531
|
+
hasEventStream && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1532
|
+
name: buildEventStreamImports({
|
|
1533
|
+
returnType,
|
|
1534
|
+
typed: shapes.has("event")
|
|
1535
|
+
}),
|
|
1536
|
+
root: file.path,
|
|
1537
|
+
path: ssePath,
|
|
1538
|
+
isTypeOnly: true
|
|
1539
|
+
}),
|
|
1392
1540
|
validator === "zod" && ops.some((op) => op.node.requestBody?.content?.[0]?.schema != null) && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1393
1541
|
name: ["z"],
|
|
1394
1542
|
path: "zod",
|
|
@@ -1419,61 +1567,66 @@ function createSdkGenerator() {
|
|
|
1419
1567
|
]
|
|
1420
1568
|
}, file.path);
|
|
1421
1569
|
};
|
|
1422
|
-
|
|
1570
|
+
const renderFacadeFile = (name) => {
|
|
1571
|
+
const sdkFile = resolver.file({
|
|
1572
|
+
name,
|
|
1573
|
+
extname: ".ts",
|
|
1574
|
+
root,
|
|
1575
|
+
output,
|
|
1576
|
+
group: group ?? void 0
|
|
1577
|
+
});
|
|
1578
|
+
const members = controllers.map(({ name, tag }) => ({
|
|
1579
|
+
className: name,
|
|
1580
|
+
propName: resolver.propertyName(tag ?? name)
|
|
1581
|
+
}));
|
|
1582
|
+
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
|
|
1583
|
+
baseName: sdkFile.baseName,
|
|
1584
|
+
path: sdkFile.path,
|
|
1585
|
+
meta: sdkFile.meta,
|
|
1586
|
+
banner: banner(sdkFile),
|
|
1587
|
+
footer: footer(sdkFile),
|
|
1588
|
+
children: [
|
|
1589
|
+
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1590
|
+
name: ["ClientConfig"],
|
|
1591
|
+
root: sdkFile.path,
|
|
1592
|
+
path: clientPath,
|
|
1593
|
+
isTypeOnly: true
|
|
1594
|
+
}),
|
|
1595
|
+
controllers.map(({ name, file }) => /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1596
|
+
name: [name],
|
|
1597
|
+
root: sdkFile.path,
|
|
1598
|
+
path: file.path
|
|
1599
|
+
}, name)),
|
|
1600
|
+
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(SdkFacade, {
|
|
1601
|
+
name: resolver.className(name),
|
|
1602
|
+
members
|
|
1603
|
+
})
|
|
1604
|
+
]
|
|
1605
|
+
}, sdkFile.path);
|
|
1606
|
+
};
|
|
1607
|
+
const files = sdk.mode === "flat" ? renderClassFile(resolver.className(sdk.name ?? "sdk"), resolver.file({
|
|
1423
1608
|
name: sdk.name ?? "sdk",
|
|
1424
1609
|
extname: ".ts",
|
|
1425
1610
|
root,
|
|
1426
1611
|
output,
|
|
1427
1612
|
group: group ?? void 0
|
|
1428
|
-
}), controllers.flatMap((controller) => controller.operations));
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
const sdkFile = resolver.file({
|
|
1432
|
-
name: sdk.name,
|
|
1433
|
-
extname: ".ts",
|
|
1613
|
+
}), controllers.flatMap((controller) => controller.operations)) : [...controllers.map(({ name, file, operations: ops }) => renderClassFile(name, file, ops)), sdk.name && renderFacadeFile(sdk.name)];
|
|
1614
|
+
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(StreamRuntime, {
|
|
1615
|
+
nodes,
|
|
1434
1616
|
root,
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
});
|
|
1438
|
-
const facadeName = resolver.className(sdk.name);
|
|
1439
|
-
const members = controllers.map(({ name, tag }) => ({
|
|
1440
|
-
className: name,
|
|
1441
|
-
propName: resolver.propertyName(tag ?? name)
|
|
1442
|
-
}));
|
|
1443
|
-
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [classFiles, /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
|
|
1444
|
-
baseName: sdkFile.baseName,
|
|
1445
|
-
path: sdkFile.path,
|
|
1446
|
-
meta: sdkFile.meta,
|
|
1447
|
-
banner: banner(sdkFile),
|
|
1448
|
-
footer: footer(sdkFile),
|
|
1449
|
-
children: [
|
|
1450
|
-
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1451
|
-
name: ["ClientConfig"],
|
|
1452
|
-
root: sdkFile.path,
|
|
1453
|
-
path: clientPath,
|
|
1454
|
-
isTypeOnly: true
|
|
1455
|
-
}),
|
|
1456
|
-
controllers.map(({ name, file }) => /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1457
|
-
name: [name],
|
|
1458
|
-
root: sdkFile.path,
|
|
1459
|
-
path: file.path
|
|
1460
|
-
}, name)),
|
|
1461
|
-
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(SdkFacade, {
|
|
1462
|
-
name: facadeName,
|
|
1463
|
-
members
|
|
1464
|
-
})
|
|
1465
|
-
]
|
|
1466
|
-
}, sdkFile.path)] });
|
|
1617
|
+
sse,
|
|
1618
|
+
baseURL: ctx.options.baseURL
|
|
1619
|
+
}), files] });
|
|
1467
1620
|
}
|
|
1468
1621
|
});
|
|
1469
1622
|
}
|
|
1470
1623
|
// ../../internals/client/src/macros.ts
|
|
1471
1624
|
/**
|
|
1472
|
-
* Macros the client plugins apply by default, ahead of any user macros. `
|
|
1473
|
-
* drops union members
|
|
1625
|
+
* Macros the client plugins apply by default, ahead of any user macros. `macroDedupeUnion`
|
|
1626
|
+
* drops repeated union members, keeping the generated response and error
|
|
1474
1627
|
* unions tidy. A plugin wires them with `ctx.setMacros([...defaultMacros, ...userMacros])`.
|
|
1475
1628
|
*/
|
|
1476
|
-
const defaultMacros = [_kubb_kit.
|
|
1629
|
+
const defaultMacros = [_kubb_kit.macroDedupeUnion];
|
|
1477
1630
|
// ../../internals/client/src/resolver.ts
|
|
1478
1631
|
/**
|
|
1479
1632
|
* Default resolver shared by the client plugins. Functions use safe camelCase identifiers and
|
|
@@ -1498,30 +1651,32 @@ const resolverClient = (0, _kubb_kit.createResolver)({
|
|
|
1498
1651
|
return ensureValidVarName((0, _kubb_kit.camelCase)(name));
|
|
1499
1652
|
}
|
|
1500
1653
|
});
|
|
1654
|
+
// src/templates.ts
|
|
1655
|
+
const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
1656
|
+
/** Absolute path to the fetch client template, copied into `.kubb/client.ts`. */
|
|
1657
|
+
const fetchClientTemplatePath = (0, node_url.fileURLToPath)(new URL("../templates/client.ts", require("url").pathToFileURL(__filename).href));
|
|
1658
|
+
/**
|
|
1659
|
+
* Absolute paths to the runtime templates `@kubb/plugin-client` ships for every client plugin, copied into `.kubb/core.ts`,
|
|
1660
|
+
* `.kubb/serializers.ts`, `.kubb/standardSchema.ts`, and `.kubb/sse.ts`.
|
|
1661
|
+
*/
|
|
1662
|
+
const coreTemplatePath = require$1.resolve("@kubb/plugin-client/templates/core.ts");
|
|
1663
|
+
const serializersTemplatePath = require$1.resolve("@kubb/plugin-client/templates/serializers.ts");
|
|
1664
|
+
const standardSchemaTemplatePath = require$1.resolve("@kubb/plugin-client/templates/standardSchema.ts");
|
|
1665
|
+
const sseTemplatePath = require$1.resolve("@kubb/plugin-client/templates/sse.ts");
|
|
1501
1666
|
// src/generators/clientGenerator.tsx
|
|
1502
1667
|
/**
|
|
1503
1668
|
* Built-in operation generator for `@kubb/plugin-fetch`. Emits one async function per OpenAPI
|
|
1504
1669
|
* operation using the shared `Operation` component: a grouped `<Name>Request` type and a function
|
|
1505
1670
|
* that forwards a single `options` object to the bundled `client` and returns the `RequestResult`.
|
|
1506
1671
|
*/
|
|
1507
|
-
const clientGenerator = createClientGenerator("fetch");
|
|
1672
|
+
const clientGenerator = createClientGenerator("fetch", { sse: sseTemplatePath });
|
|
1508
1673
|
// kubb-extension.json
|
|
1509
1674
|
var compatibility = {
|
|
1510
|
-
"kubb": ">=5.
|
|
1675
|
+
"kubb": ">=5.16.0",
|
|
1511
1676
|
"node": ">=22.22"
|
|
1512
1677
|
};
|
|
1513
1678
|
// package.json
|
|
1514
|
-
var version = "5.13.0
|
|
1515
|
-
// src/templates.ts
|
|
1516
|
-
/** Absolute path to the fetch client template, copied into `.kubb/client.ts`. */
|
|
1517
|
-
const fetchClientTemplatePath = (0, node_url.fileURLToPath)(new URL("../templates/fetch.ts", require("url").pathToFileURL(__filename).href));
|
|
1518
|
-
/** Absolute path to the fetch serializers template, copied into `.kubb/serializers.ts`. */
|
|
1519
|
-
const fetchSerializersTemplatePath = (0, node_url.fileURLToPath)(new URL("../templates/serializers.ts", require("url").pathToFileURL(__filename).href));
|
|
1520
|
-
/**
|
|
1521
|
-
* Absolute path to the Standard Schema runtime template. Pass it to a file node's `copy` field to
|
|
1522
|
-
* emit the helper into the generated `.kubb/standardSchema.ts` verbatim.
|
|
1523
|
-
*/
|
|
1524
|
-
const standardSchemaTemplatePath = (0, node_url.fileURLToPath)(new URL("../templates/standardSchema.ts", require("url").pathToFileURL(__filename).href));
|
|
1679
|
+
var version = "5.13.0";
|
|
1525
1680
|
// src/plugin.ts
|
|
1526
1681
|
/**
|
|
1527
1682
|
* Canonical plugin name for `@kubb/plugin-fetch`. Used for driver lookups and cross-plugin
|
|
@@ -1585,19 +1740,22 @@ const pluginFetch = (0, _kubb_kit.defineExtension)({
|
|
|
1585
1740
|
};
|
|
1586
1741
|
(0, _kubb_kit.setResolver)(resolved.resolver);
|
|
1587
1742
|
(0, _kubb_kit.setMacros)([...defaultMacros, ...options.macros ?? []]);
|
|
1588
|
-
(0, _kubb_kit.addGenerator)(resolved.sdk ? createSdkGenerator() : clientGenerator);
|
|
1743
|
+
(0, _kubb_kit.addGenerator)(resolved.sdk ? createSdkGenerator({ sse: sseTemplatePath }) : clientGenerator);
|
|
1589
1744
|
const root = node_path.default.resolve(config.root, config.output.path);
|
|
1590
|
-
const baseURLExpression = baseURL ? baseURL.includes("${") ? `\`${baseURL.replaceAll("`", "\\`")}\`` : JSON.stringify(baseURL) : void 0;
|
|
1591
1745
|
(0, _kubb_kit.injectFile)({
|
|
1592
1746
|
baseName: "serializers.ts",
|
|
1593
1747
|
path: node_path.default.resolve(root, ".kubb/serializers.ts"),
|
|
1594
|
-
copy:
|
|
1748
|
+
copy: serializersTemplatePath
|
|
1749
|
+
});
|
|
1750
|
+
(0, _kubb_kit.injectFile)({
|
|
1751
|
+
baseName: "core.ts",
|
|
1752
|
+
path: node_path.default.resolve(root, ".kubb/core.ts"),
|
|
1753
|
+
copy: coreTemplatePath
|
|
1595
1754
|
});
|
|
1596
1755
|
(0, _kubb_kit.injectFile)({
|
|
1597
1756
|
baseName: "client.ts",
|
|
1598
1757
|
path: node_path.default.resolve(root, ".kubb/client.ts"),
|
|
1599
|
-
copy: fetchClientTemplatePath
|
|
1600
|
-
footer: baseURLExpression ? `client.setConfig({ baseURL: ${baseURLExpression} })` : void 0
|
|
1758
|
+
copy: fetchClientTemplatePath
|
|
1601
1759
|
});
|
|
1602
1760
|
(0, _kubb_kit.injectFile)({
|
|
1603
1761
|
baseName: "standardSchema.ts",
|