generated from stijnvanhulle/template
-
-
Notifications
You must be signed in to change notification settings - Fork 127
Open
Labels
@kubb/core@kubb/plugin-client@kubb/plugin-msw@kubb/plugin-oas@kubb/plugin-ts@kubb/plugin-zoddocsImprovements or additions to documentationImprovements or additions to documentation
Description
What is the type of issue?
Documentation is confusing
What is the issue?
I have been trying to migrate from templates to generators but have been having a really hard time. Asking for a more involved example if possible. This was my old template. Not asking for the migration to be done for me, but some pointers or a more involved example in the docs would be nice. also added by kubb.config.ts for reference. Happy to provide openapi spec if that helps.
import { PackageManager } from "@kubb/core";
import transformers from "@kubb/core/transformers";
import { Function } from "@kubb/react";
import { QueryOptions } from "@kubb/swagger-tanstack-query/components";
import type React from "react";
const reactQueryDepRegex = /@tanstack\/(react|solid|vue|svelte)-query/;
export const templates = {
queryOptions: {
...QueryOptions.templates,
react: ({
name,
params,
JSDoc,
client,
hook,
dataReturnType,
infinite,
parser,
returnType,
generics,
}: React.ComponentProps<typeof QueryOptions.templates.react>) => {
const isV5 = new PackageManager().isValidSync(reactQueryDepRegex, ">=5");
const isFormData = client.contentType === "multipart/form-data";
const headers = [
client.contentType !== "application/json"
? `'Content-Type': '${client.contentType}'`
: undefined,
client.withHeaders ? "...headers" : undefined,
]
.filter(Boolean)
.join(", ");
const clientOptions = [
`method: "${client.method}"`,
`url: ${client.path.template}`,
`signal: signal`,
client.withQueryParams && !infinite ? "params" : undefined,
client.withData && !isFormData ? "data" : undefined,
client.withData && isFormData ? "data: formData" : undefined,
headers.length
? `headers: { ${headers}, ...options.headers }`
: undefined,
"...options",
client.withQueryParams && !!infinite
? `params: {
...params,
['${infinite.queryParam}']: pageParam,
...(options.params || {}),
}`
: undefined,
].filter(Boolean);
const queryOptions = [
isV5 && !!infinite
? `initialPageParam: ${infinite.initialPageParam}`
: undefined,
isV5 && !!infinite && !!infinite.cursorParam
? `getNextPageParam: (lastPage) => lastPage['${infinite.cursorParam}']`
: undefined,
isV5 && !!infinite && !!infinite.cursorParam
? `getPreviousPageParam: (firstPage) => firstPage['${infinite.cursorParam}']`
: undefined,
isV5 && !!infinite && !infinite.cursorParam && dataReturnType === "full"
? "getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage.data) && lastPage.data.length === 0 ? undefined : lastPageParam + 1"
: undefined,
isV5 && !!infinite && !infinite.cursorParam && dataReturnType === "data"
? "getNextPageParam: (lastPage, _allPages, lastPageParam) => ((lastPage as any).page?.totalPages ?? 0) > ((lastPage as any).page?.number ?? 0) + 1 ? ((lastPage as any).page?.number ?? 0) + 1 : undefined"
: undefined,
isV5 && !!infinite && !infinite.cursorParam
? "getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1"
: undefined,
].filter(Boolean);
const resolvedClientOptions = `${transformers.createIndent(4)}${clientOptions.join(`,\n${transformers.createIndent(4)}`)}`;
const resolvedQueryOptions = `${transformers.createIndent(4)}${queryOptions.join(`,\n${transformers.createIndent(4)}`)}`;
let returnRes = parser ? `return ${parser}(res.data)` : "return res.data";
if (dataReturnType === "full") {
returnRes = parser
? `return {...res, data: ${parser}(res.data)}`
: "return res";
}
const formData = isFormData
? `
const formData = new FormData()
if(data) {
Object.keys(data).forEach((key) => {
const value = data[key];
if (typeof key === "string" && (typeof value === "string" || value instanceof Blob)) {
formData.append(key, value);
}
})
}
`
: undefined;
if (infinite) {
if (isV5) {
return (
<Function name={name} export params={params} JSDoc={JSDoc}>
{`
const queryKey = ${hook.queryKey}
return infiniteQueryOptions({
queryKey,
queryFn: async ({ pageParam, signal }) => {
${hook.children || ""}
${formData || ""}
const res = await client<${client.generics}>({
${resolvedClientOptions}
})
${returnRes}
},
${resolvedQueryOptions}
})
`}
</Function>
);
}
return (
<Function
name={name}
export
generics={generics}
returnType={returnType}
params={params}
JSDoc={JSDoc}
>
{`
const queryKey = ${hook.queryKey}
return {
queryKey,
queryFn: async ({ pageParam, signal }) => {
${hook.children || ""}
${formData || ""}
const res = await client<${client.generics}>({
${resolvedClientOptions}
})
${returnRes}
},
${resolvedQueryOptions}
}
`}
</Function>
);
}
const timed = `
async function timed<T>(
name: string,
fn: () => Promise<T> | T,
): Promise<T> {
const start = performance.now();
try {
const result = await fn();
const d = performance.now() - start;
console.log(\`[perf] \${name}: \${d.toFixed(1)}ms\`);
return result;
} catch (e) {
const d = performance.now() - start;
console.log(\`[perf] \${name}: threw after \${d.toFixed(1)}ms\`);
throw e;
}
}
`
if (isV5) {
return (
<Function name={name} export params={params} JSDoc={JSDoc}>
{`
const queryKey = ${hook.queryKey}
${timed}
return queryOptions({
queryKey,
queryFn: async ({signal}) => {
${hook.children || ""}
${formData || ""}
const res = await timed(\`${name}\`, async () => client<${client.generics}>({
${resolvedClientOptions}
}))
${returnRes}
},
${resolvedQueryOptions}
})
`}
</Function>
);
}
return (
<Function
name={name}
export
generics={generics}
returnType={returnType}
params={params}
JSDoc={JSDoc}
>
{`
const queryKey = ${hook.queryKey}
return {
queryKey,
queryFn: async ({signal}) => {
${hook.children || ""}
${formData || ""}
const res = await client<${client.generics}>({
${resolvedClientOptions}
})
${returnRes}
},
${resolvedQueryOptions}
}
`}
</Function>
);
},
},
};
import { defineConfig, UserConfig } from "@kubb/core";
import { pluginOas } from "@kubb/plugin-oas";
import { pluginClient } from "@kubb/swagger-client";
import { pluginFaker } from "@kubb/swagger-faker";
import { pluginMsw } from "@kubb/swagger-msw";
import { pluginTanstackQuery } from "@kubb/swagger-tanstack-query";
import { pluginTs as createSwaggerTs } from "@kubb/swagger-ts";
import fs from "fs";
import { pluginZod } from "@kubb/swagger-zod";
import { Oas } from "./src/codegen/Oas";
import { templates } from "./src/codegen/kubb/templates/templates";
export default defineConfig(async () => {
let configs: UserConfig[] = [];
// Try fetching the springdoc config
try {
const springDoc = await fetch(
"http://localhost:9090/actuator/openapi/springdocDefault",
);
const springDocJson = await springDoc.json();
configs.push({
root: ".",
input: {
data: springDocJson,
},
output: {
path: "./src/spring-generated",
},
hooks: {
done: [
"npx prettier --experimental-cli --write ./src/spring-generated",
],
},
plugins: [
pluginOas({ oasClass: Oas, output: false }),
createSwaggerTs({
enumType: "enum",
}),
pluginZod({
output: {
path: "./schemas",
},
typed: true,
coercion: true,
}),
pluginFaker({
output: {
path: "./faker",
},
}),
pluginMsw({
output: {
path: "./msw",
},
}),
pluginClient({
client: {
importPath: "../../config/client",
},
include: [
{
type: "operationId",
pattern: "streamCandidatePurchaseOrderItems",
},
{
type: "operationId",
pattern: "getPurchaseOrderItemTransferSuggestions",
},
{
type: "operationId",
pattern: "updateCustomerHouseAccountCreditLimit",
},
{
type: "operationId",
pattern: "deleteCohortVendor",
},
{
type: "operationId",
pattern: "getPurchaseOrderCandidateItems",
},
{
type: "operationId",
pattern: "getPurchaseOrderItemTransfers",
},
{
type: "operationId",
pattern: "setUserConfiguration",
},
],
output: {
path: "./operations",
},
}),
pluginTanstackQuery({
framework: "react",
infinite: {
queryParam: "page",
},
client: {
importPath: "../../config/client",
},
output: {
path: "./hooks",
},
mutate: {
variablesType: "mutate",
methods: ["post", "put", "delete", "patch"],
},
exclude: [{ type: "operationId", pattern: "emailPurchaseOrder" }],
templates,
}),
],
});
} catch (error) {
console.error("Failed to fetch spring doc:", error);
}
// try fetching phoenix config
try {
const phoenixDoc = await fetch("http://localhost:8081/swagger/doc.json");
const phoenixDocJson = await phoenixDoc.json();
configs.push({
root: ".",
input: {
data: phoenixDocJson,
},
output: {
path: "./src/phoenix-generated",
clean: true,
},
hooks: {
done: ["npx prettier --write ./src/phoenix-generated"],
},
plugins: [
pluginOas({ oasClass: Oas, output: false }),
createSwaggerTs({
enumType: "enum",
}),
pluginClient({
client: {
importPath: "../../config/phoenix-client",
},
include: [
{ type: "operationId", pattern: "updateOrderItemDecision" },
{ type: "operationId", pattern: "createWebsocketConnection" },
{ type: "operationId", pattern: "removeWebsocketConnection" },
{ type: "operationId", pattern: "getTransactionByTransactionItem" },
{ type: "operationId", pattern: "createAssetForDataLoad" },
{ type: "operationId", pattern: "mapAdventFiles" },
],
}),
pluginTanstackQuery({
framework: "react",
infinite: false,
client: {
importPath: "../../config/phoenix-client",
},
output: {
path: "./hooks",
},
mutate: {
variablesType: "mutate",
methods: ["post", "put", "delete", "patch"],
},
templates,
}),
],
});
} catch (error) {
console.error("Failed to fetch phoenix doc:", error);
}
// Always add the POSServiceModel config
configs.push({
root: ".",
input: {
data: fs.readFileSync(
"./POSServiceModel/postman/schemas/index.yaml",
"utf-8",
),
},
output: {
path: "./src/generated",
},
hooks: {
done: ["npx prettier --experimental-cli --write ./src/generated"],
},
plugins: [
pluginOas({ oasClass: Oas, output: false }),
createSwaggerTs({
enumType: "enum",
}),
pluginFaker({
output: {
path: "./faker",
},
}),
pluginMsw({
output: {
path: "./msw",
},
}),
pluginClient({
client: {
importPath: "../../config/client",
},
include: [
{ type: "operationId", pattern: "getEntityConfigs" },
{ type: "operationId", pattern: "getCartPricing" },
{ type: "operationId", pattern: "getSalesByItemId" },
{ type: "operationId", pattern: "deleteUserFromEntity" },
{ type: "operationId", pattern: "patchUserEntity" },
{ type: "operationId", pattern: "authorizeEmployee" },
{ type: "operationId", pattern: "authorizeUser" },
],
output: {
path: "./operations",
},
}),
pluginTanstackQuery({
framework: "react",
infinite: {
queryParam: "page",
},
client: {
importPath: "../../config/client",
},
output: {
path: "./hooks",
},
templates,
}),
],
});
return configs;
});
"@kubb/cli": "^2.28.4",
"@kubb/core": "^2.28.4",
"@kubb/plugin-oas": "^2.28.4",
"@kubb/swagger": "^2.28.4",
"@kubb/swagger-client": "^2.28.4",
"@kubb/swagger-faker": "^2.28.4",
"@kubb/swagger-msw": "^2.28.4",
"@kubb/swagger-tanstack-query": "^2.28.4",
"@kubb/swagger-ts": "^2.28.4",
"@kubb/swagger-zod": "^2.28.4",
Where did you find it?
dosubotCopilot
Metadata
Metadata
Assignees
Labels
@kubb/core@kubb/plugin-client@kubb/plugin-msw@kubb/plugin-oas@kubb/plugin-ts@kubb/plugin-zoddocsImprovements or additions to documentationImprovements or additions to documentation