From 97adc0faf3475176b8d5779bf413627285fc64e2 Mon Sep 17 00:00:00 2001 From: tadej <89967862+tadejrebernjak@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:28:47 +0100 Subject: [PATCH 01/10] task: add translations to error handling --- package.json | 1 + src/index.ts | 3 ++ src/lib/assets/locales/en/translation.json | 11 ++++++ src/lib/assets/locales/sl/translation.json | 11 ++++++ src/lib/config/i18n.ts | 31 ++++++++++++++++ src/lib/rest/error-handling.ts | 43 ++++++++++++++-------- yarn.lock | 22 +++++++++++ 7 files changed, 107 insertions(+), 15 deletions(-) create mode 100644 src/lib/assets/locales/en/translation.json create mode 100644 src/lib/assets/locales/sl/translation.json create mode 100644 src/lib/config/i18n.ts diff --git a/package.json b/package.json index 84ca51c..2100b91 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ }, "license": "BSD-3-Clause", "dependencies": { + "i18next": "^25.7.3", "import-fresh": "^3.3.1" }, "peerDependencies": { diff --git a/src/index.ts b/src/index.ts index 4728469..acb8ac6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,6 +20,9 @@ export type { AppQueryOptions, AppMutationOptions, AppInfiniteQueryOptions } fro export { OpenApiRouter } from "./lib/config/router.context"; export { OpenApiQueryConfig } from "./lib/config/queryConfig.context"; +// i18n resources (for consumer apps to merge into their i18n config) +export { ns, resources } from "./lib/config/i18n"; + // Auth export { AuthContext } from "./lib/auth/auth.context"; export { AuthGuard } from "./lib/auth/AuthGuard"; diff --git a/src/lib/assets/locales/en/translation.json b/src/lib/assets/locales/en/translation.json new file mode 100644 index 0000000..7fc5402 --- /dev/null +++ b/src/lib/assets/locales/en/translation.json @@ -0,0 +1,11 @@ +{ + "openapi": { + "sharedErrors": { + "dataValidation": "An error occurred while validating the data", + "internalError": "An internal error occurred. This is most likely a bug on our end. Please try again later.", + "networkError": "A network error occurred. Are you connected to the internet?", + "canceledError": "The request was canceled.", + "unknownError": "An unknown error occurred. Please try again later." + } + } +} diff --git a/src/lib/assets/locales/sl/translation.json b/src/lib/assets/locales/sl/translation.json new file mode 100644 index 0000000..9edd3bd --- /dev/null +++ b/src/lib/assets/locales/sl/translation.json @@ -0,0 +1,11 @@ +{ + "openapi": { + "sharedErrors": { + "dataValidation": "Pri preverjanju podatkov je prišlo do napake", + "internalError": "Prišlo je do notranje napake.", + "networkError": "Prišlo je do napake v omrežju.", + "canceledError": "Zahteva je bila preklicana.", + "unknownError": "Prišlo je do neznane napake." + } + } +} diff --git a/src/lib/config/i18n.ts b/src/lib/config/i18n.ts new file mode 100644 index 0000000..b216926 --- /dev/null +++ b/src/lib/config/i18n.ts @@ -0,0 +1,31 @@ +import i18next from "i18next"; + +import translationEN from "src/lib/assets/locales/en/translation.json"; +import translationSL from "src/lib/assets/locales/sl/translation.json"; + +export const ns = "openapi"; +export const resources = { + en: { + [ns]: translationEN, + }, + sl: { + [ns]: translationSL, + }, +} as const; + +const defaultLanguage = "en"; + +const i18n = i18next.createInstance(); +i18n.init({ + compatibilityJSON: "v4", + lng: defaultLanguage, + fallbackLng: defaultLanguage, + resources, + ns: Object.keys(resources.en), + defaultNS: ns, + interpolation: { + escapeValue: false, + }, +}); + +export const defaultT = i18n.t.bind(i18n); diff --git a/src/lib/rest/error-handling.ts b/src/lib/rest/error-handling.ts index 0958413..071ad0b 100644 --- a/src/lib/rest/error-handling.ts +++ b/src/lib/rest/error-handling.ts @@ -1,9 +1,10 @@ import axios from "axios"; +import { type TFunction } from "i18next"; import { z } from "zod"; +import { defaultT } from "src/lib/config/i18n"; import { RestUtils } from "./rest.utils"; -// codes that we want to handle in every scenario export type GeneralErrorCodes = | "DATA_VALIDATION_ERROR" | "NETWORK_ERROR" @@ -26,31 +27,32 @@ export class ApplicationException extends Error { export interface ErrorEntry { code: CodeT; - condition: (error: unknown) => boolean; - getMessage: (error: unknown) => string; + condition?: (error: unknown) => boolean; + getMessage: (error: unknown, t: TFunction) => string; } export interface ErrorHandlerOptions { entries: ErrorEntry[]; + t?: TFunction; onRethrowError?: (error: unknown, exception: ApplicationException) => void; } export class ErrorHandler { entries: ErrorEntry[] = []; + private t: TFunction; private onRethrowError?: (error: unknown, exception: ApplicationException) => void; - constructor({ entries, onRethrowError }: ErrorHandlerOptions) { + constructor({ entries, t = defaultT, onRethrowError }: ErrorHandlerOptions) { + this.t = t; this.onRethrowError = onRethrowError; type ICodeT = CodeT | GeneralErrorCodes; - // implement checking for each of the general errors - const dataValidationError: ErrorEntry = { code: "DATA_VALIDATION_ERROR", condition: (e) => { return e instanceof z.ZodError; }, - getMessage: () => "An error occurred while validating the data", + getMessage: () => this.t("openapi.sharedErrors.dataValidation"), }; const internalError: ErrorEntry = { @@ -62,7 +64,7 @@ export class ErrorHandler { return false; }, - getMessage: () => "An internal error occurred. This is most likely a bug on our end. Please try again later.", + getMessage: () => this.t("openapi.sharedErrors.internalError"), }; const networkError: ErrorEntry = { @@ -74,7 +76,7 @@ export class ErrorHandler { return false; }, - getMessage: () => "A network error occurred. Are you connected to the internet?", + getMessage: () => this.t("openapi.sharedErrors.networkError"), }; const canceledError: ErrorEntry = { @@ -90,25 +92,36 @@ export class ErrorHandler { return false; }, - getMessage: () => "The request was canceled.", + getMessage: () => this.t("openapi.sharedErrors.canceledError"), }; const unknownError: ErrorEntry = { code: "UNKNOWN_ERROR", condition: () => true, - getMessage: () => "An unknown error occurred. Please try again later.", + getMessage: () => this.t("openapi.sharedErrors.unknownError"), }; // general errors have the lowest priority this.entries = [...entries, dataValidationError, internalError, networkError, canceledError, unknownError]; } - // convert the error into an application exception + private matchesEntry(error: unknown, entry: ErrorEntry, code: string | null): boolean { + if (entry.condition) { + return entry.condition(error); + } + return code === entry.code; + } + + public setTranslateFunction(t: TFunction) { + this.t = t; + } + public rethrowError(error: unknown): ApplicationException { - const errorEntry = this.entries.find((entry) => entry.condition(error ?? {}))!; + const code = RestUtils.extractServerResponseCode(error); + const errorEntry = this.entries.find((entry) => this.matchesEntry(error, entry, code))!; const serverMessage = RestUtils.extractServerErrorMessage(error); - const exception = new ApplicationException(errorEntry.getMessage(error), errorEntry.code, serverMessage); + const exception = new ApplicationException(errorEntry.getMessage(error, this.t), errorEntry.code, serverMessage); this.onRethrowError?.(error, exception); @@ -145,7 +158,7 @@ export class ErrorHandler { } if (fallbackToUnknown) { - return "An unknown error occurred. Please try again later."; + return defaultT("openapi.sharedErrors.unknownError"); } return null; diff --git a/yarn.lock b/yarn.lock index 47f6a9d..0baae11 100644 --- a/yarn.lock +++ b/yarn.lock @@ -57,6 +57,13 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/runtime@npm:7.28.4" + checksum: 10c0/792ce7af9750fb9b93879cc9d1db175701c4689da890e6ced242ea0207c9da411ccf16dc04e689cc01158b28d7898c40d75598f4559109f761c12ce01e959bf7 + languageName: node + linkType: hard + "@casl/ability@npm:^6.7.3": version: 6.7.5 resolution: "@casl/ability@npm:6.7.5" @@ -651,6 +658,7 @@ __metadata: eslint-plugin-no-relative-import-paths: "npm:^1.6.1" eslint-plugin-prettier: "npm:^5.1.3" handlebars: "npm:^4.7.8" + i18next: "npm:^25.7.3" import-fresh: "npm:^3.3.1" openapi-types: "npm:^12.1.3" prettier: "npm:^3.2.5" @@ -2507,6 +2515,20 @@ __metadata: languageName: node linkType: hard +"i18next@npm:^25.7.3": + version: 25.7.4 + resolution: "i18next@npm:25.7.4" + dependencies: + "@babel/runtime": "npm:^7.28.4" + peerDependencies: + typescript: ^5 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/d30e4f9a1c31adc0570c9f4a22ab226257620f2465e2275f8cdd5ef7f52668716cc9be3b741031aeacb39e2196be5a5f656e12d89787b4248098f681e99f72ea + languageName: node + linkType: hard + "iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" From 9d2958f3f39097a0d6d0a47fe79dc12ea18de4f3 Mon Sep 17 00:00:00 2001 From: tadej <89967862+tadejrebernjak@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:29:09 +0100 Subject: [PATCH 02/10] chore: bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2100b91..7d6df06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@povio/openapi-codegen-cli", - "version": "2.0.1", + "version": "2.0.2-rc.0", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { From 570c53ad031e6f431b04a8774e4a09d2f4f21572 Mon Sep 17 00:00:00 2001 From: tadej <89967862+tadejrebernjak@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:32:46 +0100 Subject: [PATCH 03/10] task: add unknownErrorWithCode locale --- src/lib/assets/locales/en/translation.json | 3 ++- src/lib/assets/locales/sl/translation.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/assets/locales/en/translation.json b/src/lib/assets/locales/en/translation.json index 7fc5402..716738a 100644 --- a/src/lib/assets/locales/en/translation.json +++ b/src/lib/assets/locales/en/translation.json @@ -5,7 +5,8 @@ "internalError": "An internal error occurred. This is most likely a bug on our end. Please try again later.", "networkError": "A network error occurred. Are you connected to the internet?", "canceledError": "The request was canceled.", - "unknownError": "An unknown error occurred. Please try again later." + "unknownError": "An unknown error occurred. Please try again later.", + "unknownErrorWithCode": "An unknown error occurred. Error code: \"{{code}}\"" } } } diff --git a/src/lib/assets/locales/sl/translation.json b/src/lib/assets/locales/sl/translation.json index 9edd3bd..f00c3dd 100644 --- a/src/lib/assets/locales/sl/translation.json +++ b/src/lib/assets/locales/sl/translation.json @@ -5,7 +5,8 @@ "internalError": "Prišlo je do notranje napake.", "networkError": "Prišlo je do napake v omrežju.", "canceledError": "Zahteva je bila preklicana.", - "unknownError": "Prišlo je do neznane napake." + "unknownError": "Prišlo je do neznane napake.", + "unknownErrorWithCode": "Prišlo je do neznane napake. Koda napake: \"{{code}}\"" } } } From 1a6f735547331b83abd75e4ed367d44cde9ae73d Mon Sep 17 00:00:00 2001 From: tadej <89967862+tadejrebernjak@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:23:24 +0100 Subject: [PATCH 04/10] tweak: switch around getMessage params of ErrorEntry --- package.json | 2 +- src/lib/rest/error-handling.ts | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 7d6df06..7867480 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@povio/openapi-codegen-cli", - "version": "2.0.2-rc.0", + "version": "2.0.2-rc.1", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { diff --git a/src/lib/rest/error-handling.ts b/src/lib/rest/error-handling.ts index 071ad0b..f0d17da 100644 --- a/src/lib/rest/error-handling.ts +++ b/src/lib/rest/error-handling.ts @@ -28,7 +28,7 @@ export class ApplicationException extends Error { export interface ErrorEntry { code: CodeT; condition?: (error: unknown) => boolean; - getMessage: (error: unknown, t: TFunction) => string; + getMessage: (t: TFunction, error: unknown) => string; } export interface ErrorHandlerOptions { @@ -98,7 +98,14 @@ export class ErrorHandler { const unknownError: ErrorEntry = { code: "UNKNOWN_ERROR", condition: () => true, - getMessage: () => this.t("openapi.sharedErrors.unknownError"), + getMessage: (e) => { + if (axios.isAxiosError(e) && e.response?.data?.code) { + return this.t("openapi.sharedErrors.unknownErrorWithCode", { + code: e.response.data.code, + }); + } + return this.t("openapi.sharedErrors.unknownError"); + }, }; // general errors have the lowest priority @@ -121,7 +128,7 @@ export class ErrorHandler { const errorEntry = this.entries.find((entry) => this.matchesEntry(error, entry, code))!; const serverMessage = RestUtils.extractServerErrorMessage(error); - const exception = new ApplicationException(errorEntry.getMessage(error, this.t), errorEntry.code, serverMessage); + const exception = new ApplicationException(errorEntry.getMessage(this.t, error), errorEntry.code, serverMessage); this.onRethrowError?.(error, exception); From ec22134d9b9a7d8d0af54dab150d86536fc2efad Mon Sep 17 00:00:00 2001 From: tadej <89967862+tadejrebernjak@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:55:00 +0100 Subject: [PATCH 05/10] debug: t is not a function --- package.json | 2 +- src/lib/rest/error-handling.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7867480..a5ba400 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@povio/openapi-codegen-cli", - "version": "2.0.2-rc.1", + "version": "2.0.2-rc.2", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { diff --git a/src/lib/rest/error-handling.ts b/src/lib/rest/error-handling.ts index f0d17da..6ed5781 100644 --- a/src/lib/rest/error-handling.ts +++ b/src/lib/rest/error-handling.ts @@ -98,7 +98,7 @@ export class ErrorHandler { const unknownError: ErrorEntry = { code: "UNKNOWN_ERROR", condition: () => true, - getMessage: (e) => { + getMessage: (_, e) => { if (axios.isAxiosError(e) && e.response?.data?.code) { return this.t("openapi.sharedErrors.unknownErrorWithCode", { code: e.response.data.code, @@ -127,6 +127,9 @@ export class ErrorHandler { const code = RestUtils.extractServerResponseCode(error); const errorEntry = this.entries.find((entry) => this.matchesEntry(error, entry, code))!; + // eslint-disable-next-line no-console + console.log("[ErrorHandler] this.t:", this.t, "typeof:", typeof this.t); + const serverMessage = RestUtils.extractServerErrorMessage(error); const exception = new ApplicationException(errorEntry.getMessage(this.t, error), errorEntry.code, serverMessage); From d7ada2193ba2bb7fda621cd2a47a70c5e89cd79d Mon Sep 17 00:00:00 2001 From: tadej <89967862+tadejrebernjak@users.noreply.github.com> Date: Mon, 12 Jan 2026 17:03:32 +0100 Subject: [PATCH 06/10] chore: remove console log --- package.json | 2 +- src/lib/rest/error-handling.ts | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/package.json b/package.json index a5ba400..30178f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@povio/openapi-codegen-cli", - "version": "2.0.2-rc.2", + "version": "2.0.2-rc.3", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { diff --git a/src/lib/rest/error-handling.ts b/src/lib/rest/error-handling.ts index 6ed5781..36921f0 100644 --- a/src/lib/rest/error-handling.ts +++ b/src/lib/rest/error-handling.ts @@ -127,9 +127,6 @@ export class ErrorHandler { const code = RestUtils.extractServerResponseCode(error); const errorEntry = this.entries.find((entry) => this.matchesEntry(error, entry, code))!; - // eslint-disable-next-line no-console - console.log("[ErrorHandler] this.t:", this.t, "typeof:", typeof this.t); - const serverMessage = RestUtils.extractServerErrorMessage(error); const exception = new ApplicationException(errorEntry.getMessage(this.t, error), errorEntry.code, serverMessage); From f3c18474672a2276adad866856df89cd72929485 Mon Sep 17 00:00:00 2001 From: Jure Rotar Date: Mon, 19 Jan 2026 11:53:34 +0100 Subject: [PATCH 07/10] chore: bumped react-query and updated onSuccess signature --- package.json | 2 +- .../templates/partials/query-use-mutation.hbs | 12 ++++++------ yarn.lock | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 30178f4..fdc518e 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "peerDependencies": { "@casl/ability": "^6.7.3", "@casl/react": "^5.0.0", - "@tanstack/react-query": "^5.85.9", + "@tanstack/react-query": "^5.89.0", "axios": "^1.13.1", "react": "^19.1.0", "zod": "^4.1.12" diff --git a/src/generators/templates/partials/query-use-mutation.hbs b/src/generators/templates/partials/query-use-mutation.hbs index 89ac3fd..9b1c7dc 100644 --- a/src/generators/templates/partials/query-use-mutation.hbs +++ b/src/generators/templates/partials/query-use-mutation.hbs @@ -10,8 +10,8 @@ export const {{queryName endpoint mutation=true}} = (options?: AppMutationOption return {{queryHook}}({ mutationFn: {{#if endpoint.mediaUpload}}async {{/if}}({{#if (endpointParams endpoint includeFileParam=true)}} { {{{endpointArgs endpoint includeFileParam=true}}}{{#if endpoint.mediaUpload}}, abortController, onUploadProgress{{/if}} } {{/if}}) => {{#if hasMutationFnBody}} { {{/if}} {{#if hasAclCheck}}{{{genAclCheckCall endpoint}}}{{/if}} - {{#if endpoint.mediaUpload}}const uploadInstructions = await {{importedEndpointName endpoint}}({{{endpointArgs endpoint}}}{{#if hasAxiosRequestConfig}}{{#if (endpointArgs endpoint)}}, {{/if}}{{axiosRequestConfigName}}{{/if}}); - + {{#if endpoint.mediaUpload}}const uploadInstructions = await {{importedEndpointName endpoint}}({{{endpointArgs endpoint}}}{{#if hasAxiosRequestConfig}}{{#if (endpointArgs endpoint)}}, {{/if}}{{axiosRequestConfigName}}{{/if}}); + if (file && uploadInstructions.url) { const method = (data?.method?.toLowerCase() ?? "put") as 'put' | 'post'; let dataToSend: File | FormData = file; @@ -34,21 +34,21 @@ export const {{queryName endpoint mutation=true}} = (options?: AppMutationOption : undefined, }); } - + return uploadInstructions; {{else}} {{#if hasMutationFnBody}}return {{/if}}{{importedEndpointName endpoint}}({{{endpointArgs endpoint}}}{{#if hasAxiosRequestConfig}}{{#if (endpointArgs endpoint)}}, {{/if}}{{axiosRequestConfigName}}{{/if}}) {{/if}} {{#if hasMutationFnBody}} }{{/if}}, ...options, {{#if hasMutationEffects}} - onSuccess: async (resData, variables, context) => { + onSuccess: async (resData, variables, onMutateResult, context) => { {{! Mutation effects }} {{#if updateQueryEndpoints}} {{#if destructuredVariables}}const { {{commaSeparated destructuredVariables }} } = variables;{{/if}} const updateKeys = [{{#each updateQueryEndpoints as | endpoint |}}keys.{{endpointName endpoint}}({{{endpointArgs endpoint includeOnlyRequiredParams=true}}}), {{/each}}]; {{/if}} await runMutationEffects(resData, options{{#if updateQueryEndpoints}}, updateKeys{{/if}}); - options?.onSuccess?.(resData, variables, context); + options?.onSuccess?.(resData, variables, onMutateResult, context); },{{/if}} }); -}; \ No newline at end of file +}; diff --git a/yarn.lock b/yarn.lock index 0baae11..f923fb3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -676,7 +676,7 @@ __metadata: peerDependencies: "@casl/ability": ^6.7.3 "@casl/react": ^5.0.0 - "@tanstack/react-query": ^5.85.9 + "@tanstack/react-query": ^5.89.0 axios: ^1.13.1 react: ^19.1.0 zod: ^4.1.12 From cc3a26485a9f80a0c1bf84107889519001bafb57 Mon Sep 17 00:00:00 2001 From: Jure Rotar Date: Tue, 20 Jan 2026 07:53:36 +0100 Subject: [PATCH 08/10] feat: added custom error format for unknown errors --- src/lib/rest/error-handling.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/lib/rest/error-handling.ts b/src/lib/rest/error-handling.ts index 36921f0..7ca6c26 100644 --- a/src/lib/rest/error-handling.ts +++ b/src/lib/rest/error-handling.ts @@ -99,11 +99,17 @@ export class ErrorHandler { code: "UNKNOWN_ERROR", condition: () => true, getMessage: (_, e) => { - if (axios.isAxiosError(e) && e.response?.data?.code) { - return this.t("openapi.sharedErrors.unknownErrorWithCode", { - code: e.response.data.code, - }); + const code = RestUtils.extractServerResponseCode(e); + const serverMessage = RestUtils.extractServerErrorMessage(e); + + if (code) { + let message = `Unknown error, message from server: ${code}`; + if (serverMessage) { + message += ` ${serverMessage}`; + } + return message; } + return this.t("openapi.sharedErrors.unknownError"); }, }; From ade0d066775441e031f7838fdbe041886d2f9b1b Mon Sep 17 00:00:00 2001 From: Jure Rotar Date: Tue, 20 Jan 2026 07:59:17 +0100 Subject: [PATCH 09/10] feat: added custom error format for unknown errors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fdc518e..66bbac1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@povio/openapi-codegen-cli", - "version": "2.0.2-rc.3", + "version": "2.0.2-rc.4", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { From 49aad321b40a8bd7824746bacc6ce65208a419c5 Mon Sep 17 00:00:00 2001 From: Jure Rotar Date: Fri, 23 Jan 2026 08:06:26 +0100 Subject: [PATCH 10/10] fix: fixed schema extends --- package.json | 2 +- src/generators/core/zod/getZodSchema.test.ts | 4 ++-- src/generators/core/zod/getZodSchema.ts | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 66bbac1..d427470 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@povio/openapi-codegen-cli", - "version": "2.0.2-rc.4", + "version": "2.0.2-rc.6", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { diff --git a/src/generators/core/zod/getZodSchema.test.ts b/src/generators/core/zod/getZodSchema.test.ts index 051df61..20221ee 100644 --- a/src/generators/core/zod/getZodSchema.test.ts +++ b/src/generators/core/zod/getZodSchema.test.ts @@ -267,7 +267,7 @@ describe("getZodSchema", () => { discriminator: { propertyName: "type" }, }), ).toStrictEqual( - 'z.union([z.object({ type: z.enum(["a"]), a: z.string() }).merge(z.object({ type: z.enum(["c"]), c: z.string() })), z.object({ type: z.enum(["b"]), b: z.string() }).merge(z.object({ type: z.enum(["d"]), d: z.string() }))])', + 'z.union([z.object({ ...z.object({ type: z.enum(["a"]), a: z.string() }).shape, ...z.object({ type: z.enum(["c"]), c: z.string() }).shape }), z.object({ ...z.object({ type: z.enum(["b"]), b: z.string() }).shape, ...z.object({ type: z.enum(["d"]), d: z.string() }).shape })])', ); expect( @@ -286,7 +286,7 @@ describe("getZodSchema", () => { intersection: { allOf: [{ type: "string" }, { type: "number" }] }, }, }), - ).toStrictEqual("z.object({ intersection: z.string().merge(z.number()) }).partial()"); + ).toStrictEqual("z.object({ intersection: z.object({ ...z.string().shape, ...z.number().shape }) }).partial()"); expect(getZodSchemaString({ type: "string", enum: ["aaa", "bbb", "ccc"] })).toStrictEqual( 'z.enum(["aaa", "bbb", "ccc"])', diff --git a/src/generators/core/zod/getZodSchema.ts b/src/generators/core/zod/getZodSchema.ts index aa409dc..e215c18 100644 --- a/src/generators/core/zod/getZodSchema.ts +++ b/src/generators/core/zod/getZodSchema.ts @@ -307,10 +307,10 @@ function getAllOfZodSchema({ schema, zodSchema, resolver, meta, tag }: GetPartia const first = types.at(0)!; const rest = types .slice(1) - .map((type) => `merge(${type.getCodeString(tag, resolver.options)})`) - .join("."); + .map((type) => `...${type.getCodeString(tag, resolver.options)}.shape`) + .join(", "); - return zodSchema.assign(`${first.getCodeString(tag, resolver.options)}.${rest}`); + return zodSchema.assign(`z.object({ ...${first.getCodeString(tag, resolver.options)}.shape, ${rest} })`); } function getPrimitiveZodSchema({ schema, zodSchema, resolver, meta, tag }: GetPartialZodSchemaParams) {