From 2867e83cd0559e7875c111eb0e000249206670db Mon Sep 17 00:00:00 2001 From: Yangshun Date: Mon, 17 Mar 2025 18:24:06 +0800 Subject: [PATCH] [translens] add test project --- .gitignore | 3 + apps/i18n-test/package.json | 14 ++ apps/i18n-test/src/locales/en-US.json | 5 + .../src/locales/en-US.translens.json | 12 ++ apps/i18n-test/src/locales/ja-JP.json | 5 + apps/i18n-test/src/locales/zh-CN.json | 5 + apps/i18n-test/translens.config.json | 18 ++ apps/web/package.json | 2 +- packages/translens/package.json | 7 +- .../translation/DeepSeekTranslationService.ts | 28 +-- pnpm-lock.yaml | 183 +++++++++++++----- 11 files changed, 206 insertions(+), 76 deletions(-) create mode 100644 apps/i18n-test/package.json create mode 100644 apps/i18n-test/src/locales/en-US.json create mode 100644 apps/i18n-test/src/locales/en-US.translens.json create mode 100644 apps/i18n-test/src/locales/ja-JP.json create mode 100644 apps/i18n-test/src/locales/zh-CN.json create mode 100644 apps/i18n-test/translens.config.json diff --git a/.gitignore b/.gitignore index c9b019f58..5674b18cc 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,6 @@ crowdin.yml # angular .angular + +# env +.env diff --git a/apps/i18n-test/package.json b/apps/i18n-test/package.json new file mode 100644 index 000000000..9b927f0f4 --- /dev/null +++ b/apps/i18n-test/package.json @@ -0,0 +1,14 @@ +{ + "name": "i18n-test", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "translens": "translens" + }, + "keywords": [], + "devDependencies": { + "translens": "workspace:0.0.0" + } +} diff --git a/apps/i18n-test/src/locales/en-US.json b/apps/i18n-test/src/locales/en-US.json new file mode 100644 index 000000000..7d20512e9 --- /dev/null +++ b/apps/i18n-test/src/locales/en-US.json @@ -0,0 +1,5 @@ +{ + "hello": "Hello world!", + "bye": "Goodbye earth...", + "smart": "You're so smart, what a pancake!" +} diff --git a/apps/i18n-test/src/locales/en-US.translens.json b/apps/i18n-test/src/locales/en-US.translens.json new file mode 100644 index 000000000..e7c8dce80 --- /dev/null +++ b/apps/i18n-test/src/locales/en-US.translens.json @@ -0,0 +1,12 @@ +{ + "hashes": { + "hello": "627b0c2c", + "bye": "48112765", + "smart": "553ab50e" + }, + "hash": "c206299b", + "translatedLocales": [ + "zh-CN", + "ja-JP" + ] +} \ No newline at end of file diff --git a/apps/i18n-test/src/locales/ja-JP.json b/apps/i18n-test/src/locales/ja-JP.json new file mode 100644 index 000000000..d39ddd376 --- /dev/null +++ b/apps/i18n-test/src/locales/ja-JP.json @@ -0,0 +1,5 @@ +{ + "hello": "Hello world!", + "bye": "Goodbye earth...", + "smart": "あなたはとても賢いね、なんてパンケーキなんだ!" +} \ No newline at end of file diff --git a/apps/i18n-test/src/locales/zh-CN.json b/apps/i18n-test/src/locales/zh-CN.json new file mode 100644 index 000000000..ac2cbbe9a --- /dev/null +++ b/apps/i18n-test/src/locales/zh-CN.json @@ -0,0 +1,5 @@ +{ + "hello": "Hello world!", + "bye": "Goodbye earth...", + "smart": "你真聪明,真是个天才!" +} \ No newline at end of file diff --git a/apps/i18n-test/translens.config.json b/apps/i18n-test/translens.config.json new file mode 100644 index 000000000..24b006355 --- /dev/null +++ b/apps/i18n-test/translens.config.json @@ -0,0 +1,18 @@ +{ + "localeConfig": { + "source": "en-US", + "target": ["zh-CN", "ja-JP"] + }, + "groups": [ + { + "name": "App JSON", + "handler": "json", + "files": [ + { + "source": "./src/locales/en-US.json", + "target": "./src/locales/{locale}.json" + } + ] + } + ] +} diff --git a/apps/web/package.json b/apps/web/package.json index 41c372c6b..15da0b2b4 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -38,7 +38,6 @@ "@codesandbox/sandpack-react": "2.13.8", "@formatjs/intl": "^2.9.9", "@formatjs/intl-localematcher": "^0.2.32", - "@gfe/translens": "workspace:0.0.0", "@hookform/resolvers": "^3.3.2", "@lexical/code": "^0.13.1", "@lexical/headless": "^0.13.1", @@ -191,6 +190,7 @@ "strip-comments": "^2.0.1", "supabase": "^1.115.5", "tailwindcss": "^3.4.13", + "translens": "workspace:0.0.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.2", "tsx": "^4.7.1", diff --git a/packages/translens/package.json b/packages/translens/package.json index 9abff135b..3cc1132a4 100644 --- a/packages/translens/package.json +++ b/packages/translens/package.json @@ -1,8 +1,7 @@ { - "name": "@gfe/translens", + "name": "translens", "version": "0.0.0", "description": "Modern translation toolchain", - "author": "Nitesh Seram ", "license": "MIT", "type": "module", "main": "dist/index.js", @@ -23,9 +22,9 @@ "prepublishOnly": "npm run verify" }, "dependencies": { - "@ai-sdk/openai": "^0.0.33", + "@ai-sdk/deepseek": "^0.1.15", "@clack/prompts": "^0.9.1", - "ai": "^3.2.8", + "ai": "^4.1.61", "chalk": "^5.2.0", "dotenv": "^16.3.1", "glob": "^11.0.1", diff --git a/packages/translens/src/translation/DeepSeekTranslationService.ts b/packages/translens/src/translation/DeepSeekTranslationService.ts index dd6902bb5..fd8d6200a 100644 --- a/packages/translens/src/translation/DeepSeekTranslationService.ts +++ b/packages/translens/src/translation/DeepSeekTranslationService.ts @@ -1,25 +1,15 @@ import { ITranslationService } from '../interfaces'; import { generateText } from 'ai'; -import { createOpenAI } from '@ai-sdk/openai'; +import { deepseek } from '@ai-sdk/deepseek'; export default class DeepSeekTranslationService implements ITranslationService { - private openai; - constructor() { - const apiKey = process.env.DEEPSEEK_API_KEY; - if (!apiKey) { - throw new Error('DEEPSEEK_API_KEY is not added.'); - } - this.openai = createOpenAI({ - apiKey, - }); - } private async translateAPI(prompt: string): Promise { - const result = await generateText({ - model: this.openai('gpt-4o-mini'), - prompt: prompt, + const { text } = await generateText({ + model: deepseek('deepseek-chat'), + prompt, }); - return JSON.parse(result.text); + return JSON.parse(text); } private constructPrompt( @@ -28,9 +18,9 @@ export default class DeepSeekTranslationService implements ITranslationService { ): string { return `You are a professional translator. Translate the following text to ${targetLocale}. Maintain the original meaning, tone, and formatting. Only return the translated text, no explanations or additional content. -It is a JSON object, translate it values and return the translated content in the same format with its key and value. +It is a JSON object, translate its values and return the translated content in the same format with its key and value. -Text to translate: +JSON to translate: ${JSON.stringify(content)}`; } @@ -39,7 +29,7 @@ ${JSON.stringify(content)}`; targetLocale: string, ): Promise> { const prompt = this.constructPrompt(items, targetLocale); - const translation = await this.translateAPI(prompt); - return translation; + + return await this.translateAPI(prompt); } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 04881bffc..925836236 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -76,6 +76,12 @@ importers: specifier: ^5.3.3 version: 5.3.3 + apps/i18n-test: + devDependencies: + translens: + specifier: workspace:0.0.0 + version: link:../../packages/translens + apps/socialmon: dependencies: '@ai-sdk/openai': @@ -262,9 +268,6 @@ importers: '@formatjs/intl-localematcher': specifier: ^0.2.32 version: 0.2.32 - '@gfe/translens': - specifier: workspace:0.0.0 - version: link:../../packages/translens '@hookform/resolvers': specifier: ^3.3.2 version: 3.3.2(react-hook-form@7.48.2) @@ -716,6 +719,9 @@ importers: tailwindcss: specifier: ^3.4.13 version: 3.4.13(ts-node@10.9.2) + translens: + specifier: workspace:0.0.0 + version: link:../../packages/translens ts-jest: specifier: ^29.1.1 version: 29.1.1(@babel/core@7.24.7)(esbuild@0.17.19)(jest@29.7.0)(typescript@5.7.2) @@ -809,15 +815,15 @@ importers: packages/translens: dependencies: - '@ai-sdk/openai': - specifier: ^0.0.33 - version: 0.0.33(zod@3.22.4) + '@ai-sdk/deepseek': + specifier: ^0.1.15 + version: 0.1.15(zod@3.24.2) '@clack/prompts': specifier: ^0.9.1 version: 0.9.1 ai: - specifier: ^3.2.8 - version: 3.2.8(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.18)(vue@3.4.31)(zod@3.22.4) + specifier: ^4.1.61 + version: 4.1.61(react@18.3.1)(zod@3.24.2) chalk: specifier: ^5.2.0 version: 5.3.0 @@ -858,6 +864,29 @@ packages: resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} engines: {node: '>=0.10.0'} + /@ai-sdk/deepseek@0.1.15(zod@3.24.2): + resolution: {integrity: sha512-0sB3G71eXI7ND4fa9MwBIyN+tTwnH0MQs2Sc+8gGluMy6FtlQi1x49j0yWp1jWSp8E0T31zU7Po7U77NEM0Wxw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + dependencies: + '@ai-sdk/openai-compatible': 0.1.15(zod@3.24.2) + '@ai-sdk/provider': 1.0.11 + '@ai-sdk/provider-utils': 2.1.13(zod@3.24.2) + zod: 3.24.2 + dev: false + + /@ai-sdk/openai-compatible@0.1.15(zod@3.24.2): + resolution: {integrity: sha512-iuylARLylTkaVYXKdgA1GeGU2TwANaJ3RlhJqmN0cVO5uEt3qVKvedrzR3jrQIyy9hu3gngsiXfFBMW2UQ7Ntg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + dependencies: + '@ai-sdk/provider': 1.0.11 + '@ai-sdk/provider-utils': 2.1.13(zod@3.24.2) + zod: 3.24.2 + dev: false + /@ai-sdk/openai@0.0.33(zod@3.22.4): resolution: {integrity: sha512-siVeHnagh08UFgdwflPdUKTdrVvfU/JWqSa8nCsMy6DvSri8T7zTzPZoCxXiMKPXkhQDd/KsaXhweOShGLQ1uQ==} engines: {node: '>=18'} @@ -885,6 +914,22 @@ packages: zod: 3.22.4 dev: false + /@ai-sdk/provider-utils@2.1.13(zod@3.24.2): + resolution: {integrity: sha512-kLjqsfOdONr6DGcGEntFYM1niXz1H05vyZNf9OAzK+KKKc64izyP4/q/9HX7W4+6g8hm6BnmKxu8vkr6FSOqDg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + peerDependenciesMeta: + zod: + optional: true + dependencies: + '@ai-sdk/provider': 1.0.11 + eventsource-parser: 3.0.0 + nanoid: 3.3.8 + secure-json-parse: 2.7.0 + zod: 3.24.2 + dev: false + /@ai-sdk/provider@0.0.10: resolution: {integrity: sha512-NzkrtREQpHID1cTqY/C4CI30PVOaXWKYytDR2EcytmFgnP7Z6+CrGIA/YCnNhYAuUm6Nx+nGpRL/Hmyrv7NYzg==} engines: {node: '>=18'} @@ -892,6 +937,13 @@ packages: json-schema: 0.4.0 dev: false + /@ai-sdk/provider@1.0.11: + resolution: {integrity: sha512-CPyImHGiT3svyfmvPvAFTianZzWFtm0qK82XjwlQIA1C3IQ2iku/PMQXi7aFyrX0TyMh3VTkJPB03tjU2VXVrw==} + engines: {node: '>=18'} + dependencies: + json-schema: 0.4.0 + dev: false + /@ai-sdk/react@0.0.8(react@18.2.0)(zod@3.22.4): resolution: {integrity: sha512-YASx575akiHuH8izwojwpA4NH7PqsezmRnz/Kmc/4dS4JN38uu4domd8y4fzOT/oO1nfdJ5xB+8aRa4NaQdu2Q==} engines: {node: '>=18'} @@ -911,11 +963,11 @@ packages: zod: 3.22.4 dev: false - /@ai-sdk/react@0.0.8(react@18.3.1)(zod@3.22.4): - resolution: {integrity: sha512-YASx575akiHuH8izwojwpA4NH7PqsezmRnz/Kmc/4dS4JN38uu4domd8y4fzOT/oO1nfdJ5xB+8aRa4NaQdu2Q==} + /@ai-sdk/react@1.1.23(react@18.3.1)(zod@3.24.2): + resolution: {integrity: sha512-R+PG9ya0GLs6orzt+1MxmjrWFuZM0gVs+l8ihBr1u+42wwkVeojY4CAtQjW4nrfGTVbdJYkl5y+r/VKfjr42aQ==} engines: {node: '>=18'} peerDependencies: - react: ^18 || ^19 + react: ^18 || ^19 || ^19.0.0-rc zod: ^3.0.0 peerDependenciesMeta: react: @@ -923,11 +975,12 @@ packages: zod: optional: true dependencies: - '@ai-sdk/provider-utils': 0.0.16(zod@3.22.4) - '@ai-sdk/ui-utils': 0.0.6(zod@3.22.4) + '@ai-sdk/provider-utils': 2.1.13(zod@3.24.2) + '@ai-sdk/ui-utils': 1.1.19(zod@3.24.2) react: 18.3.1 - swr: 2.2.0(react@18.3.1) - zod: 3.22.4 + swr: 2.3.3(react@18.3.1) + throttleit: 2.1.0 + zod: 3.24.2 dev: false /@ai-sdk/solid@0.0.7(solid-js@1.8.17)(zod@3.22.4): @@ -978,6 +1031,21 @@ packages: zod: 3.22.4 dev: false + /@ai-sdk/ui-utils@1.1.19(zod@3.24.2): + resolution: {integrity: sha512-rDHy2uxlPMt3jjS9L6mBrsfhEInZ5BVoWevmD13fsAt2s/XWy2OwwKmgmUQkdLlY4mn/eyeYAfDGK8+5CbOAgg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + peerDependenciesMeta: + zod: + optional: true + dependencies: + '@ai-sdk/provider': 1.0.11 + '@ai-sdk/provider-utils': 2.1.13(zod@3.24.2) + zod: 3.24.2 + zod-to-json-schema: 3.24.4(zod@3.24.2) + dev: false + /@ai-sdk/vue@0.0.7(vue@3.4.31)(zod@3.22.4): resolution: {integrity: sha512-bGDkYHdSDrIxS1EhjzLrzQecnDvLRr6ksx7yPg+V28J4+PzU5gH23M3Z2g71KIhX5B80Jrv8CsOFYDAKm3at5Q==} engines: {node: '>=18'} @@ -5123,6 +5191,11 @@ packages: resolution: {integrity: sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw==} engines: {node: '>=8.0.0'} + /@opentelemetry/api@1.9.0: + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + dev: false + /@opentelemetry/context-async-hooks@1.18.1(@opentelemetry/api@1.7.0): resolution: {integrity: sha512-HHfJR32NH2x0b69CACCwH8m1dpNALoCTtpgmIWMNkeMGNUeKT48d4AX4xsF4uIRuUoRTbTgtSBRvS+cF97qwCQ==} engines: {node: '>=14'} @@ -8324,44 +8397,27 @@ packages: - vue dev: false - /ai@3.2.8(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.18)(vue@3.4.31)(zod@3.22.4): - resolution: {integrity: sha512-lcWABN/pQ3crTKr9UvteKuWwTtvhZCGtP/lwo02cRyfCMuGaOxK/E/VXklo8WabuVLk9l1CRXCWdQcw6peg11g==} + /ai@4.1.61(react@18.3.1)(zod@3.24.2): + resolution: {integrity: sha512-Y9SAyGJEeW23F6C7PSHZXYNEvbH2cqJm0rVW2AoeFaXFT13ttx8rAqs8wz2w466C1UB329yl5PXayFcHqofSEA==} engines: {node: '>=18'} peerDependencies: - openai: ^4.42.0 - react: ^18 || ^19 - svelte: ^3.0.0 || ^4.0.0 + react: ^18 || ^19 || ^19.0.0-rc zod: ^3.0.0 peerDependenciesMeta: - openai: - optional: true react: optional: true - svelte: - optional: true zod: optional: true dependencies: - '@ai-sdk/provider': 0.0.10 - '@ai-sdk/provider-utils': 0.0.16(zod@3.22.4) - '@ai-sdk/react': 0.0.8(react@18.3.1)(zod@3.22.4) - '@ai-sdk/solid': 0.0.7(solid-js@1.8.17)(zod@3.22.4) - '@ai-sdk/svelte': 0.0.7(svelte@4.2.18)(zod@3.22.4) - '@ai-sdk/ui-utils': 0.0.6(zod@3.22.4) - '@ai-sdk/vue': 0.0.7(vue@3.4.31)(zod@3.22.4) - eventsource-parser: 1.1.2 - json-schema: 0.4.0 + '@ai-sdk/provider': 1.0.11 + '@ai-sdk/provider-utils': 2.1.13(zod@3.24.2) + '@ai-sdk/react': 1.1.23(react@18.3.1)(zod@3.24.2) + '@ai-sdk/ui-utils': 1.1.19(zod@3.24.2) + '@opentelemetry/api': 1.9.0 + eventsource-parser: 3.0.0 jsondiffpatch: 0.6.0 - nanoid: 3.3.6 react: 18.3.1 - secure-json-parse: 2.7.0 - sswr: 2.1.0(svelte@4.2.18) - svelte: 4.2.18 - zod: 3.22.4 - zod-to-json-schema: 3.22.5(zod@3.22.4) - transitivePeerDependencies: - - solid-js - - vue + zod: 3.24.2 dev: false /ajv-keywords@3.5.2(ajv@6.12.6): @@ -10445,7 +10501,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.34.0)(typescript@5.7.2) + '@typescript-eslint/parser': 5.62.0(eslint@8.34.0)(typescript@5.3.3) debug: 3.2.7 eslint: 8.34.0 eslint-import-resolver-node: 0.3.9 @@ -10486,7 +10542,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.34.0)(typescript@5.7.2) + '@typescript-eslint/parser': 5.62.0(eslint@8.34.0)(typescript@5.3.3) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 @@ -10812,6 +10868,11 @@ packages: engines: {node: '>=14.18'} dev: false + /eventsource-parser@3.0.0: + resolution: {integrity: sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==} + engines: {node: '>=18.0.0'} + dev: false + /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -16897,13 +16958,14 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false - /swr@2.2.0(react@18.3.1): - resolution: {integrity: sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==} + /swr@2.3.3(react@18.3.1): + resolution: {integrity: sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==} peerDependencies: - react: ^16.11.0 || ^17.0.0 || ^18.0.0 + react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 dependencies: + dequal: 2.0.3 react: 18.3.1 - use-sync-external-store: 1.2.0(react@18.3.1) + use-sync-external-store: 1.4.0(react@18.3.1) dev: false /swrev@4.0.0: @@ -17158,6 +17220,11 @@ packages: engines: {node: '>=10'} dev: false + /throttleit@2.1.0: + resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} + engines: {node: '>=18'} + dev: false + /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: false @@ -17433,7 +17500,7 @@ packages: '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 '@types/node': 18.19.2 - acorn: 8.12.0 + acorn: 8.11.2 acorn-walk: 8.3.1 arg: 4.1.3 create-require: 1.1.1 @@ -18029,10 +18096,10 @@ packages: react: 18.2.0 dev: false - /use-sync-external-store@1.2.0(react@18.3.1): - resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + /use-sync-external-store@1.4.0(react@18.3.1): + resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 dependencies: react: 18.3.1 dev: false @@ -18604,9 +18671,21 @@ packages: zod: 3.22.4 dev: false + /zod-to-json-schema@3.24.4(zod@3.24.2): + resolution: {integrity: sha512-0uNlcvgabyrni9Ag8Vghj21drk7+7tp7VTwwR7KxxXXc/3pbXz2PHlDgj3cICahgF1kHm4dExBFj7BXrZJXzig==} + peerDependencies: + zod: ^3.24.1 + dependencies: + zod: 3.24.2 + dev: false + /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false + /zod@3.24.2: + resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} + dev: false + /zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}