@next-vibe/checker 1.0.11 → 1.0.13
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/bin/vibe-runtime.js +26 -22
- package/.dist/bin/vibe-runtime.js.map +5 -5
- package/.dist/oxlint-plugins/i18n.js +4 -0
- package/.dist/oxlint-plugins/i18n.js.map +1 -0
- package/.dist/oxlint-plugins/jsx-capitalization.js +4 -0
- package/.dist/oxlint-plugins/jsx-capitalization.js.map +1 -0
- package/.dist/oxlint-plugins/restricted-syntax.js +4 -0
- package/.dist/oxlint-plugins/restricted-syntax.js.map +1 -0
- package/check.config.ts +4 -12
- package/package.json +2 -9
- package/src/app/api/[locale]/LICENSE +674 -0
- package/src/app/api/[locale]/i18n/de/index.ts +13 -0
- package/src/app/api/[locale]/i18n/en/index.ts +12 -0
- package/src/app/api/[locale]/i18n/pl/index.ts +11 -0
- package/src/app/api/[locale]/shared/i18n/de/index.ts +85 -0
- package/src/app/api/[locale]/shared/i18n/en/index.ts +83 -0
- package/src/app/api/[locale]/shared/i18n/pl/index.ts +85 -0
- package/src/app/api/[locale]/shared/stats-filtering.ts +202 -0
- package/src/app/api/[locale]/shared/types/common.schema.ts +55 -0
- package/src/app/api/[locale]/shared/types/response.schema.ts +372 -0
- package/src/app/api/[locale]/shared/types/stats-filtering.schema.ts +375 -0
- package/src/app/api/[locale]/shared/types/utils.ts +190 -0
- package/src/app/api/[locale]/shared/utils/base64.ts +49 -0
- package/src/app/api/[locale]/shared/utils/env-util.ts +40 -0
- package/src/app/api/[locale]/shared/utils/i18n/de/index.ts +21 -0
- package/src/app/api/[locale]/shared/utils/i18n/en/index.ts +19 -0
- package/src/app/api/[locale]/shared/utils/i18n/pl/index.ts +21 -0
- package/src/app/api/[locale]/shared/utils/index.ts +11 -0
- package/src/app/api/[locale]/shared/utils/object-path.ts +41 -0
- package/src/app/api/[locale]/shared/utils/object.test.ts +82 -0
- package/src/app/api/[locale]/shared/utils/object.ts +75 -0
- package/src/app/api/[locale]/shared/utils/parse-error.ts +134 -0
- package/src/app/api/[locale]/shared/utils/parse-json.ts +70 -0
- package/src/app/api/[locale]/shared/utils/time.ts +53 -0
- package/src/app/api/[locale]/shared/utils/validation.ts +127 -0
- package/src/app/api/[locale]/shared/utils/zod-required-fields.ts +116 -0
- package/src/app/api/[locale]/system/builder/definition.ts +1942 -0
- package/src/app/api/[locale]/system/builder/enum.ts +78 -0
- package/src/app/api/[locale]/system/builder/i18n/de/index.ts +677 -0
- package/src/app/api/[locale]/system/builder/i18n/en/index.ts +665 -0
- package/src/app/api/[locale]/system/builder/i18n/pl/index.ts +668 -0
- package/src/app/api/[locale]/system/builder/repository/build-executor.test.ts +182 -0
- package/src/app/api/[locale]/system/builder/repository/build-executor.ts +583 -0
- package/src/app/api/[locale]/system/builder/repository/bun-compiler.ts +261 -0
- package/src/app/api/[locale]/system/builder/repository/bundle-analyzer.ts +197 -0
- package/src/app/api/[locale]/system/builder/repository/config-loader.ts +159 -0
- package/src/app/api/[locale]/system/builder/repository/config-validator.ts +97 -0
- package/src/app/api/[locale]/system/builder/repository/constants.ts +125 -0
- package/src/app/api/[locale]/system/builder/repository/error-suggester.ts +75 -0
- package/src/app/api/[locale]/system/builder/repository/file-copier.ts +98 -0
- package/src/app/api/[locale]/system/builder/repository/folder-cleaner.ts +80 -0
- package/src/app/api/[locale]/system/builder/repository/index.ts +2 -0
- package/src/app/api/[locale]/system/builder/repository/npm-package-generator.ts +146 -0
- package/src/app/api/[locale]/system/builder/repository/output-formatter.ts +104 -0
- package/src/app/api/[locale]/system/builder/repository/profile-service.ts +79 -0
- package/src/app/api/[locale]/system/builder/repository/report-generator.ts +125 -0
- package/src/app/api/[locale]/system/builder/repository/vite-compiler.ts +291 -0
- package/src/app/api/[locale]/system/builder/route.ts +21 -0
- package/src/app/api/[locale]/system/builder/test-files/file1.ts +2 -0
- package/src/app/api/[locale]/system/builder/test-files/file2.tsx +10 -0
- package/src/app/api/[locale]/system/builder/test-files/file3.tsx +16 -0
- package/src/app/api/[locale]/system/builder/test-files/folderToCopy/fileInFolder.ts +2 -0
- package/src/app/api/[locale]/system/builder/test-files/test-config.ts +38 -0
- package/src/app/api/[locale]/system/builder/test-files/test-delete-config.ts +8 -0
- package/src/app/api/[locale]/system/builder/test-files/test-project/package.json +24 -0
- package/src/app/api/[locale]/system/builder/test-files/test-project/src/constants.ts +6 -0
- package/src/app/api/[locale]/system/builder/test-files/test-project/src/greet.ts +18 -0
- package/src/app/api/[locale]/system/builder/test-files/test-project/src/index.ts +7 -0
- package/src/app/api/[locale]/system/builder/test-files/test-project/src/utils/calculate.ts +27 -0
- package/src/app/api/[locale]/system/builder/test-files/test-project/tsconfig.json +19 -0
- package/src/app/api/[locale]/system/builder/test-files/test-project/tsconfig.tsbuildinfo +1 -0
- package/src/app/api/[locale]/system/builder/test-files/test3.css +1 -0
- package/src/app/api/[locale]/system/check/config/repository.ts +886 -0
- package/src/app/api/[locale]/system/check/config/shared.ts +396 -0
- package/src/app/api/[locale]/system/check/config/types.ts +616 -0
- package/src/app/api/[locale]/system/check/config/utils.ts +171 -0
- package/src/app/api/[locale]/system/check/i18n/de/index.ts +15 -0
- package/src/app/api/[locale]/system/check/i18n/en/index.ts +14 -0
- package/src/app/api/[locale]/system/check/i18n/pl/index.ts +15 -0
- package/src/app/api/[locale]/system/check/lint/definition.ts +414 -0
- package/src/app/api/[locale]/system/check/lint/enum.ts +37 -0
- package/src/app/api/[locale]/system/check/lint/i18n/de/index.ts +164 -0
- package/src/app/api/[locale]/system/check/lint/i18n/en/index.ts +162 -0
- package/src/app/api/[locale]/system/check/lint/i18n/pl/index.ts +164 -0
- package/src/app/api/[locale]/system/check/lint/repository.ts +753 -0
- package/src/app/api/[locale]/system/check/lint/route.ts +21 -0
- package/src/app/api/[locale]/system/check/oxlint/README.md +190 -0
- package/src/app/api/[locale]/system/check/oxlint/definition.ts +414 -0
- package/src/app/api/[locale]/system/check/oxlint/enum.ts +37 -0
- package/src/app/api/[locale]/system/check/oxlint/i18n/de/index.ts +171 -0
- package/src/app/api/[locale]/system/check/oxlint/i18n/en/index.ts +168 -0
- package/src/app/api/[locale]/system/check/oxlint/i18n/pl/index.ts +172 -0
- package/src/app/api/[locale]/system/check/oxlint/plugins/i18n/src/index.ts +372 -0
- package/src/app/api/[locale]/system/check/oxlint/plugins/jsx-capitalization/README.md +246 -0
- package/src/app/api/[locale]/system/check/oxlint/plugins/jsx-capitalization/src/index.ts +583 -0
- package/src/app/api/[locale]/system/check/oxlint/plugins/restricted-syntax/src/index.ts +500 -0
- package/src/app/api/[locale]/system/check/oxlint/plugins/restricted-syntax/test.tsx +74 -0
- package/src/app/api/[locale]/system/check/oxlint/plugins/shared/config-loader.ts +305 -0
- package/src/app/api/[locale]/system/check/oxlint/repository.ts +959 -0
- package/src/app/api/[locale]/system/check/oxlint/route.ts +21 -0
- package/src/app/api/[locale]/system/check/oxlint/types.ts +193 -0
- package/src/app/api/[locale]/system/check/test-project/bun.lock +532 -0
- package/src/app/api/[locale]/system/check/test-project/check.config.ts +981 -0
- package/src/app/api/[locale]/system/check/test-project/package.json +12 -0
- package/src/app/api/[locale]/system/check/test-project/src/constants.ts +6 -0
- package/src/app/api/[locale]/system/check/test-project/src/greet.ts +18 -0
- package/src/app/api/[locale]/system/check/test-project/src/test-issues/a11y-issues.tsx +107 -0
- package/src/app/api/[locale]/system/check/test-project/src/test-issues/eslint-issues.tsx +37 -0
- package/src/app/api/[locale]/system/check/test-project/src/test-issues/general-issues.ts +137 -0
- package/src/app/api/[locale]/system/check/test-project/src/test-issues/i18n-issues.tsx +129 -0
- package/src/app/api/[locale]/system/check/test-project/src/test-issues/jsx-capitalization-issues.tsx +131 -0
- package/src/app/api/[locale]/system/check/test-project/src/test-issues/nextjs-issues.tsx +95 -0
- package/src/app/api/[locale]/system/check/test-project/src/test-issues/promise-issues.ts +76 -0
- package/src/app/api/[locale]/system/check/test-project/src/test-issues/react-issues.tsx +95 -0
- package/src/app/api/[locale]/system/check/test-project/src/test-issues/restricted-syntax-issues.tsx +61 -0
- package/src/app/api/[locale]/system/check/test-project/src/test-issues/typescript-issues.ts +80 -0
- package/src/app/api/[locale]/system/check/test-project/src/utils/calculate.ts +27 -0
- package/src/app/api/[locale]/system/check/test-project/tsconfig.json +34 -0
- package/src/app/api/[locale]/system/check/test-project/tsconfig.tsbuildinfo +1 -0
- package/src/app/api/[locale]/system/check/typecheck/definition.ts +369 -0
- package/src/app/api/[locale]/system/check/typecheck/enum.ts +37 -0
- package/src/app/api/[locale]/system/check/typecheck/i18n/de/index.ts +159 -0
- package/src/app/api/[locale]/system/check/typecheck/i18n/en/index.ts +150 -0
- package/src/app/api/[locale]/system/check/typecheck/i18n/pl/index.ts +155 -0
- package/src/app/api/[locale]/system/check/typecheck/repository.ts +919 -0
- package/src/app/api/[locale]/system/check/typecheck/route.ts +22 -0
- package/src/app/api/[locale]/system/check/typecheck/utils.ts +168 -0
- package/src/app/api/[locale]/system/check/vibe-check/definition.ts +568 -0
- package/src/app/api/[locale]/system/check/vibe-check/enum.ts +69 -0
- package/src/app/api/[locale]/system/check/vibe-check/i18n/de/index.ts +192 -0
- package/src/app/api/[locale]/system/check/vibe-check/i18n/en/index.ts +189 -0
- package/src/app/api/[locale]/system/check/vibe-check/i18n/pl/index.ts +192 -0
- package/src/app/api/[locale]/system/check/vibe-check/repository.ts +545 -0
- package/src/app/api/[locale]/system/check/vibe-check/route.test.ts +1142 -0
- package/src/app/api/[locale]/system/check/vibe-check/route.ts +21 -0
- package/src/app/api/[locale]/system/generated/endpoint.ts +313 -0
- package/src/app/api/[locale]/system/generated/endpoints.ts +156 -0
- package/src/app/api/[locale]/system/generated/route-handlers.ts +224 -0
- package/src/app/api/[locale]/system/generators/endpoint/definition.ts +193 -0
- package/src/app/api/[locale]/system/generators/endpoint/i18n/de/index.ts +48 -0
- package/src/app/api/[locale]/system/generators/endpoint/i18n/en/index.ts +48 -0
- package/src/app/api/[locale]/system/generators/endpoint/i18n/pl/index.ts +50 -0
- package/src/app/api/[locale]/system/generators/endpoint/repository.ts +291 -0
- package/src/app/api/[locale]/system/generators/endpoint/route.ts +21 -0
- package/src/app/api/[locale]/system/generators/endpoints/definition.ts +246 -0
- package/src/app/api/[locale]/system/generators/endpoints/i18n/de/index.ts +54 -0
- package/src/app/api/[locale]/system/generators/endpoints/i18n/en/index.ts +52 -0
- package/src/app/api/[locale]/system/generators/endpoints/i18n/pl/index.ts +54 -0
- package/src/app/api/[locale]/system/generators/endpoints/options-repository.ts +463 -0
- package/src/app/api/[locale]/system/generators/endpoints/repository.ts +383 -0
- package/src/app/api/[locale]/system/generators/endpoints/route.ts +18 -0
- package/src/app/api/[locale]/system/generators/endpoints-index/definition.ts +194 -0
- package/src/app/api/[locale]/system/generators/endpoints-index/i18n/de/index.ts +71 -0
- package/src/app/api/[locale]/system/generators/endpoints-index/i18n/en/index.ts +69 -0
- package/src/app/api/[locale]/system/generators/endpoints-index/i18n/pl/index.ts +71 -0
- package/src/app/api/[locale]/system/generators/endpoints-index/repository.ts +294 -0
- package/src/app/api/[locale]/system/generators/endpoints-index/route.ts +18 -0
- package/src/app/api/[locale]/system/generators/generate-all/definition.ts +355 -0
- package/src/app/api/[locale]/system/generators/generate-all/i18n/de/index.ts +96 -0
- package/src/app/api/[locale]/system/generators/generate-all/i18n/en/index.ts +94 -0
- package/src/app/api/[locale]/system/generators/generate-all/i18n/pl/index.ts +96 -0
- package/src/app/api/[locale]/system/generators/generate-all/repository.ts +257 -0
- package/src/app/api/[locale]/system/generators/generate-all/route.ts +20 -0
- package/src/app/api/[locale]/system/generators/i18n/de/index.ts +15 -0
- package/src/app/api/[locale]/system/generators/i18n/en/index.ts +14 -0
- package/src/app/api/[locale]/system/generators/i18n/pl/index.ts +15 -0
- package/src/app/api/[locale]/system/generators/route-handlers/definition.ts +198 -0
- package/src/app/api/[locale]/system/generators/route-handlers/i18n/de/index.ts +48 -0
- package/src/app/api/[locale]/system/generators/route-handlers/i18n/en/index.ts +48 -0
- package/src/app/api/[locale]/system/generators/route-handlers/i18n/pl/index.ts +50 -0
- package/src/app/api/[locale]/system/generators/route-handlers/repository.ts +277 -0
- package/src/app/api/[locale]/system/generators/route-handlers/route.ts +17 -0
- package/src/app/api/[locale]/system/generators/shared/utils.ts +233 -0
- package/src/app/api/[locale]/system/help/definition.ts +445 -0
- package/src/app/api/[locale]/system/help/i18n/de/index.ts +267 -0
- package/src/app/api/[locale]/system/help/i18n/en/index.ts +262 -0
- package/src/app/api/[locale]/system/help/i18n/pl/index.ts +265 -0
- package/src/app/api/[locale]/system/help/interactive/definition.ts +125 -0
- package/src/app/api/[locale]/system/help/interactive/i18n/de/index.ts +22 -0
- package/src/app/api/[locale]/system/help/interactive/i18n/en/index.ts +19 -0
- package/src/app/api/[locale]/system/help/interactive/i18n/pl/index.ts +22 -0
- package/src/app/api/[locale]/system/help/interactive/repository.ts +1025 -0
- package/src/app/api/[locale]/system/help/interactive/route.ts +53 -0
- package/src/app/api/[locale]/system/help/list/definition.ts +372 -0
- package/src/app/api/[locale]/system/help/list/repository.ts +110 -0
- package/src/app/api/[locale]/system/help/list/route.ts +21 -0
- package/src/app/api/[locale]/system/help/repository.ts +212 -0
- package/src/app/api/[locale]/system/help/route.ts +16 -0
- package/src/app/api/[locale]/system/i18n/de/index.ts +68 -0
- package/src/app/api/[locale]/system/i18n/en/index.ts +65 -0
- package/src/app/api/[locale]/system/i18n/pl/index.ts +66 -0
- package/src/app/api/[locale]/system/release-tool/definition.ts +3104 -0
- package/src/app/api/[locale]/system/release-tool/i18n/de/index.ts +813 -0
- package/src/app/api/[locale]/system/release-tool/i18n/en/index.ts +797 -0
- package/src/app/api/[locale]/system/release-tool/i18n/pl/index.ts +810 -0
- package/src/app/api/[locale]/system/release-tool/repository/asset-zipper.ts +128 -0
- package/src/app/api/[locale]/system/release-tool/repository/changelog-generator.ts +212 -0
- package/src/app/api/[locale]/system/release-tool/repository/ci-detector.ts +566 -0
- package/src/app/api/[locale]/system/release-tool/repository/config.ts +113 -0
- package/src/app/api/[locale]/system/release-tool/repository/constants.ts +407 -0
- package/src/app/api/[locale]/system/release-tool/repository/dependency-manager.ts +527 -0
- package/src/app/api/[locale]/system/release-tool/repository/git-service.ts +403 -0
- package/src/app/api/[locale]/system/release-tool/repository/hook-runner.ts +100 -0
- package/src/app/api/[locale]/system/release-tool/repository/index.ts +1 -0
- package/src/app/api/[locale]/system/release-tool/repository/notification-service.ts +638 -0
- package/src/app/api/[locale]/system/release-tool/repository/package-service.ts +169 -0
- package/src/app/api/[locale]/system/release-tool/repository/publisher.ts +253 -0
- package/src/app/api/[locale]/system/release-tool/repository/quality-runner.ts +428 -0
- package/src/app/api/[locale]/system/release-tool/repository/release-creator.ts +293 -0
- package/src/app/api/[locale]/system/release-tool/repository/release-executor.ts +1198 -0
- package/src/app/api/[locale]/system/release-tool/repository/snyk-service.ts +136 -0
- package/src/app/api/[locale]/system/release-tool/repository/utils.ts +642 -0
- package/src/app/api/[locale]/system/release-tool/repository/validation.ts +288 -0
- package/src/app/api/[locale]/system/release-tool/repository/version-service.ts +297 -0
- package/src/app/api/[locale]/system/release-tool/route.ts +21 -0
- package/src/app/api/[locale]/system/unified-interface/README.md +328 -0
- package/src/app/api/[locale]/system/unified-interface/cli/README.md +349 -0
- package/src/app/api/[locale]/system/unified-interface/cli/auth/cli-handler.ts +95 -0
- package/src/app/api/[locale]/system/unified-interface/cli/auth/cli-user.ts +146 -0
- package/src/app/api/[locale]/system/unified-interface/cli/auth/session-file.ts +266 -0
- package/src/app/api/[locale]/system/unified-interface/cli/env.ts +26 -0
- package/src/app/api/[locale]/system/unified-interface/cli/i18n/de/index.ts +157 -0
- package/src/app/api/[locale]/system/unified-interface/cli/i18n/en/index.ts +155 -0
- package/src/app/api/[locale]/system/unified-interface/cli/i18n/pl/index.ts +158 -0
- package/src/app/api/[locale]/system/unified-interface/cli/runtime/debug.ts +595 -0
- package/src/app/api/[locale]/system/unified-interface/cli/runtime/entry-point.ts +129 -0
- package/src/app/api/[locale]/system/unified-interface/cli/runtime/environment.ts +155 -0
- package/src/app/api/[locale]/system/unified-interface/cli/runtime/execution-errors.ts +452 -0
- package/src/app/api/[locale]/system/unified-interface/cli/runtime/parsing.ts +297 -0
- package/src/app/api/[locale]/system/unified-interface/cli/runtime/route-executor.ts +859 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/i18n/de/index.ts +12 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/i18n/en/index.ts +11 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/i18n/pl/index.ts +12 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/install/definition.ts +262 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/install/i18n/de/index.ts +54 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/install/i18n/en/index.ts +52 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/install/i18n/pl/index.ts +54 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/install/repository.ts +421 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/install/route.ts +25 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/status/definition.ts +181 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/status/i18n/de/index.ts +61 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/status/i18n/en/index.ts +59 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/status/i18n/pl/index.ts +61 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/status/repository.ts +195 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/status/route.ts +22 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/uninstall/definition.ts +188 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/uninstall/i18n/de/index.ts +54 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/uninstall/i18n/en/index.ts +52 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/uninstall/i18n/pl/index.ts +54 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/uninstall/repository.ts +209 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/uninstall/route.ts +24 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/update/definition.ts +200 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/update/i18n/de/index.ts +54 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/update/i18n/en/index.ts +52 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/update/i18n/pl/index.ts +54 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/update/repository.ts +113 -0
- package/src/app/api/[locale]/system/unified-interface/cli/setup/update/route.ts +22 -0
- package/src/app/api/[locale]/system/unified-interface/cli/vibe-runtime.ts +304 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/core/base-renderer.ts +270 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/core/registry.ts +309 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/core/types.ts +126 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/i18n/de/index.ts +67 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/i18n/en/index.ts +65 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/i18n/pl/index.ts +67 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/accordion.ts +74 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/avatar.ts +39 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/badge.ts +54 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/code-output.ts +298 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/code-quality-files.ts +89 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/code-quality-list.ts +298 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/code-quality-summary.ts +96 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/container.ts +186 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/data-card.ts +65 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/data-cards.ts +570 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/data-list.ts +80 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/data-table.ts +385 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/editable-text.ts +99 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/empty-state.ts +55 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/errors.ts +67 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/grouped-list.ts +729 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/link-card.ts +87 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/link-list.ts +112 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/link.ts +59 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/loading.ts +50 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/markdown.ts +131 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/metric.ts +291 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/section.ts +120 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/stats-grid.ts +149 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/tabs.ts +61 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/text.ts +78 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/implementations/title.ts +42 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/renderers/response-renderer.ts +418 -0
- package/src/app/api/[locale]/system/unified-interface/cli/widgets/renderers/schema-handler.ts +534 -0
- package/src/app/api/[locale]/system/unified-interface/i18n/de/index.ts +42 -0
- package/src/app/api/[locale]/system/unified-interface/i18n/en/index.ts +40 -0
- package/src/app/api/[locale]/system/unified-interface/i18n/pl/index.ts +43 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/README.md +114 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/converter.ts +146 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/i18n/de/index.ts +182 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/i18n/en/index.ts +179 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/i18n/pl/index.ts +181 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/registry.ts +343 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/serve/definition.ts +147 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/serve/repository.ts +38 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/serve/route.ts +14 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/server/protocol-handler.ts +309 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/server/server.ts +154 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/server/stdio-transport.ts +193 -0
- package/src/app/api/[locale]/system/unified-interface/mcp/types.ts +246 -0
- package/src/app/api/[locale]/system/unified-interface/shared/endpoints/definition/create-form.ts +1510 -0
- package/src/app/api/[locale]/system/unified-interface/shared/endpoints/definition/create.ts +581 -0
- package/src/app/api/[locale]/system/unified-interface/shared/endpoints/definition/endpoint-to-metadata.ts +52 -0
- package/src/app/api/[locale]/system/unified-interface/shared/endpoints/definition/loader.ts +152 -0
- package/src/app/api/[locale]/system/unified-interface/shared/endpoints/definitions/registry.ts +265 -0
- package/src/app/api/[locale]/system/unified-interface/shared/endpoints/permissions/registry.ts +680 -0
- package/src/app/api/[locale]/system/unified-interface/shared/endpoints/route/executor.ts +220 -0
- package/src/app/api/[locale]/system/unified-interface/shared/endpoints/route/handler.ts +325 -0
- package/src/app/api/[locale]/system/unified-interface/shared/endpoints/route/multi.ts +184 -0
- package/src/app/api/[locale]/system/unified-interface/shared/endpoints/route/request-validator.ts +201 -0
- package/src/app/api/[locale]/system/unified-interface/shared/endpoints/route/single.ts +58 -0
- package/src/app/api/[locale]/system/unified-interface/shared/env/define-env-client.ts +49 -0
- package/src/app/api/[locale]/system/unified-interface/shared/env/define-env.ts +47 -0
- package/src/app/api/[locale]/system/unified-interface/shared/env/validation-logger.ts +58 -0
- package/src/app/api/[locale]/system/unified-interface/shared/field/enum.ts +110 -0
- package/src/app/api/[locale]/system/unified-interface/shared/field/specialized.ts +339 -0
- package/src/app/api/[locale]/system/unified-interface/shared/field/utils.test.ts +408 -0
- package/src/app/api/[locale]/system/unified-interface/shared/field/utils.ts +1349 -0
- package/src/app/api/[locale]/system/unified-interface/shared/field-config/endpoint-field-types.ts +107 -0
- package/src/app/api/[locale]/system/unified-interface/shared/field-config/field-config-types.ts +268 -0
- package/src/app/api/[locale]/system/unified-interface/shared/logger/colors.ts +114 -0
- package/src/app/api/[locale]/system/unified-interface/shared/logger/endpoint.ts +169 -0
- package/src/app/api/[locale]/system/unified-interface/shared/logger/file-logger.ts +88 -0
- package/src/app/api/[locale]/system/unified-interface/shared/logger/formatters.ts +177 -0
- package/src/app/api/[locale]/system/unified-interface/shared/server-only/auth/base-auth-handler.ts +82 -0
- package/src/app/api/[locale]/system/unified-interface/shared/server-only/auth/factory.ts +33 -0
- package/src/app/api/[locale]/system/unified-interface/shared/server-only/server-only.ts +4 -0
- package/src/app/api/[locale]/system/unified-interface/shared/types/actions.ts +289 -0
- package/src/app/api/[locale]/system/unified-interface/shared/types/endpoint.ts +1167 -0
- package/src/app/api/[locale]/system/unified-interface/shared/types/enums.ts +382 -0
- package/src/app/api/[locale]/system/unified-interface/shared/types/platform.ts +34 -0
- package/src/app/api/[locale]/system/unified-interface/shared/types/types.ts +80 -0
- package/src/app/api/[locale]/system/unified-interface/shared/types/ui-config.ts +76 -0
- package/src/app/api/[locale]/system/unified-interface/shared/utils/error-types.ts +27 -0
- package/src/app/api/[locale]/system/unified-interface/shared/utils/path.ts +63 -0
- package/src/app/api/[locale]/system/unified-interface/shared/utils/scanner.ts +241 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/actions.ts +256 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/configs.ts +1158 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/helpers.ts +80 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/accordion.ts +82 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/avatar.ts +75 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/badge.ts +89 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/code-output.ts +302 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/code-quality-list.ts +202 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/container.ts +129 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/data-card.ts +81 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/data-cards.ts +258 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/data-list.ts +123 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/data-table.ts +387 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/editable-text.ts +89 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/empty-state.ts +78 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/errors.ts +93 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/grouped-list.ts +448 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/index.ts +38 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/link-card.ts +130 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/link-list.ts +127 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/link.ts +68 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/loading.ts +81 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/markdown.ts +176 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/metric-card.ts +241 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/section.ts +90 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/stats-grid.ts +71 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/tabs.ts +80 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/text.ts +105 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/logic/title.ts +72 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/types.ts +240 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/utils/field-helpers.ts +137 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/utils/formatting.ts +437 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/utils/url.ts +40 -0
- package/src/app/api/[locale]/system/unified-interface/shared/widgets/utils/widget-helpers.ts +465 -0
- package/src/app/api/[locale]/user/auth/enum.ts +16 -0
- package/src/app/api/[locale]/user/auth/i18n/de/index.ts +227 -0
- package/src/app/api/[locale]/user/auth/i18n/en/index.ts +205 -0
- package/src/app/api/[locale]/user/auth/i18n/pl/index.ts +219 -0
- package/src/app/api/[locale]/user/auth/types.ts +110 -0
- package/src/app/api/[locale]/user/enum.ts +64 -0
- package/src/app/api/[locale]/user/private/i18n/de/index.ts +3 -0
- package/src/app/api/[locale]/user/private/i18n/en/index.ts +1 -0
- package/src/app/api/[locale]/user/private/i18n/pl/index.ts +3 -0
- package/src/app/api/[locale]/user/types.ts +118 -0
- package/src/app/api/[locale]/user/user-roles/enum.ts +112 -0
- package/src/app/api/[locale]/user/user-roles/i18n/de/index.ts +85 -0
- package/src/app/api/[locale]/user/user-roles/i18n/en/index.ts +83 -0
- package/src/app/api/[locale]/user/user-roles/i18n/pl/index.ts +86 -0
- package/src/app/api/[locale]/user/user-roles/types.ts +34 -0
- package/src/app/api/i18n/de/index.ts +6 -0
- package/src/app/api/i18n/en/index.ts +5 -0
- package/src/app/api/i18n/pl/index.ts +5 -0
- package/src/app/i18n/de/index.ts +6 -0
- package/src/app/i18n/en/index.ts +5 -0
- package/src/app/i18n/pl/index.ts +5 -0
|
@@ -0,0 +1,1349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field Utilities
|
|
3
|
+
*
|
|
4
|
+
* Utility functions for creating and working with unified fields.
|
|
5
|
+
* These utilities were moved from individual definition files for better organization.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
10
|
+
import type { TranslationKey } from "@/i18n/core/static-types";
|
|
11
|
+
|
|
12
|
+
import type { EndpointLogger } from "../logger/endpoint";
|
|
13
|
+
import type {
|
|
14
|
+
ArrayField,
|
|
15
|
+
ArrayOptionalField,
|
|
16
|
+
FieldUsageConfig,
|
|
17
|
+
InferSchemaFromField,
|
|
18
|
+
ObjectField,
|
|
19
|
+
ObjectOptionalField,
|
|
20
|
+
ObjectUnionField,
|
|
21
|
+
PrimitiveField,
|
|
22
|
+
UnifiedField,
|
|
23
|
+
WidgetField,
|
|
24
|
+
} from "../types/endpoint";
|
|
25
|
+
import type { CacheStrategy } from "../types/enums";
|
|
26
|
+
import { FieldUsage } from "../types/enums";
|
|
27
|
+
import type { WidgetConfig } from "../widgets/configs";
|
|
28
|
+
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// TYPE GUARDS
|
|
31
|
+
// ============================================================================
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Type guard to check if a value is a Zod schema
|
|
35
|
+
*/
|
|
36
|
+
// eslint-disable-next-line oxlint-plugin-restricted/restricted-syntax -- Type guard: Must accept unknown to narrow any value to z.ZodTypeAny. This is the standard TypeScript pattern for type guards.
|
|
37
|
+
function isZodSchema(value: unknown): value is z.ZodTypeAny {
|
|
38
|
+
return typeof value === "object" && value !== null && "_def" in value;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// SCHEMA DEFAULT VALUE EXTRACTION
|
|
43
|
+
// ============================================================================
|
|
44
|
+
|
|
45
|
+
interface ZodDefShape {
|
|
46
|
+
// eslint-disable-next-line oxlint-plugin-restricted/restricted-syntax -- Type guard for Zod internal structure requires unknown type
|
|
47
|
+
_def: Record<string, unknown>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Type guard to check if a value is a Zod schema (has _def property)
|
|
52
|
+
*/
|
|
53
|
+
// eslint-disable-next-line oxlint-plugin-restricted/restricted-syntax -- Type guard parameter must accept unknown to narrow any value
|
|
54
|
+
function hasZodDef(value: unknown): value is ZodDefShape {
|
|
55
|
+
return typeof value === "object" && value !== null && "_def" in value;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Safely get a property from an object if it exists
|
|
60
|
+
*/
|
|
61
|
+
function getDefProperty<T>(
|
|
62
|
+
// eslint-disable-next-line oxlint-plugin-restricted/restricted-syntax -- Generic type parameter for flexible property extraction
|
|
63
|
+
def: Record<string, unknown>,
|
|
64
|
+
key: string,
|
|
65
|
+
): T | undefined {
|
|
66
|
+
if (key in def) {
|
|
67
|
+
return def[key] as T;
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Recursively extracts default values from a Zod schema.
|
|
74
|
+
* This traverses the entire schema tree and builds an object with all default values.
|
|
75
|
+
*
|
|
76
|
+
* Key behavior for nested objects:
|
|
77
|
+
* - If a nested object has ANY child with defaults, the object itself is included
|
|
78
|
+
* - This ensures required nested objects get populated with their children's defaults
|
|
79
|
+
*
|
|
80
|
+
* Handles:
|
|
81
|
+
* - ZodDefault: Extracts the default value
|
|
82
|
+
* - ZodOptional: Recursively checks inner schema for defaults
|
|
83
|
+
* - ZodObject: Recursively extracts defaults from all properties
|
|
84
|
+
* - ZodEffects (refinements/transforms): Unwraps to inner schema
|
|
85
|
+
* - ZodNullable: Recursively checks inner schema
|
|
86
|
+
*
|
|
87
|
+
* @param schema - The Zod schema to extract defaults from
|
|
88
|
+
* @param logger - Optional logger for error reporting
|
|
89
|
+
* @param path - Current path in schema (for debugging)
|
|
90
|
+
* @param forFormInit - When true, returns empty values for primitives (empty string, 0, false, [])
|
|
91
|
+
* to properly initialize form fields and avoid "expected X, received undefined" errors
|
|
92
|
+
* @returns An object containing all extracted default values, or undefined if no defaults
|
|
93
|
+
*/
|
|
94
|
+
export function extractSchemaDefaults<T>(
|
|
95
|
+
schema: z.ZodTypeAny,
|
|
96
|
+
logger?: EndpointLogger,
|
|
97
|
+
path = "",
|
|
98
|
+
forFormInit = false,
|
|
99
|
+
): T | Partial<T> | undefined {
|
|
100
|
+
try {
|
|
101
|
+
if (!hasZodDef(schema)) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
const def = schema._def;
|
|
105
|
+
const typeName = getDefProperty<string>(def, "typeName");
|
|
106
|
+
// In Zod v4, typeName is undefined but def.type exists
|
|
107
|
+
const defType = getDefProperty<string>(def, "type");
|
|
108
|
+
|
|
109
|
+
// Handle ZodDefault - has a defaultValue (can be value or function depending on Zod version)
|
|
110
|
+
if (schema instanceof z.ZodDefault) {
|
|
111
|
+
// eslint-disable-next-line oxlint-plugin-restricted/restricted-syntax -- Zod internal _def structure requires unknown type, no definition.ts type available
|
|
112
|
+
const defaultValueOrFn = getDefProperty<unknown>(def, "defaultValue");
|
|
113
|
+
// In Zod v4, defaultValue is the actual value; in older versions it may be a function
|
|
114
|
+
const defaultValue =
|
|
115
|
+
typeof defaultValueOrFn === "function"
|
|
116
|
+
? // eslint-disable-next-line oxlint-plugin-restricted/restricted-syntax -- Zod callback pattern requires unknown return type
|
|
117
|
+
(defaultValueOrFn as () => unknown)()
|
|
118
|
+
: defaultValueOrFn;
|
|
119
|
+
|
|
120
|
+
// If the inner type is an object, merge with extracted defaults from children
|
|
121
|
+
const innerType = getDefProperty<z.ZodTypeAny>(def, "innerType");
|
|
122
|
+
if (innerType && hasZodDef(innerType)) {
|
|
123
|
+
const innerDefaults = extractSchemaDefaults<T>(
|
|
124
|
+
innerType,
|
|
125
|
+
logger,
|
|
126
|
+
`${path}.inner`,
|
|
127
|
+
forFormInit,
|
|
128
|
+
);
|
|
129
|
+
if (
|
|
130
|
+
typeof defaultValue === "object" &&
|
|
131
|
+
defaultValue !== null &&
|
|
132
|
+
typeof innerDefaults === "object" &&
|
|
133
|
+
innerDefaults !== null
|
|
134
|
+
) {
|
|
135
|
+
return { ...innerDefaults, ...defaultValue } as Partial<T>;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return defaultValue as Partial<T>;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Handle ZodObject - recursively extract from all shape properties
|
|
142
|
+
if (schema instanceof z.ZodObject) {
|
|
143
|
+
const shapeFnOrObj = getDefProperty<
|
|
144
|
+
(() => Record<string, z.ZodTypeAny>) | Record<string, z.ZodTypeAny>
|
|
145
|
+
>(def, "shape");
|
|
146
|
+
if (!shapeFnOrObj) {
|
|
147
|
+
return {} as Partial<T>;
|
|
148
|
+
}
|
|
149
|
+
const shapeObj =
|
|
150
|
+
typeof shapeFnOrObj === "function" ? shapeFnOrObj() : shapeFnOrObj;
|
|
151
|
+
if (typeof shapeObj !== "object" || shapeObj === null) {
|
|
152
|
+
return {} as Partial<T>;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// eslint-disable-next-line oxlint-plugin-restricted/restricted-syntax -- Building dynamic object from Zod schema requires unknown values
|
|
156
|
+
const result: Record<string, unknown> = {};
|
|
157
|
+
for (const [key, fieldSchema] of Object.entries(shapeObj)) {
|
|
158
|
+
if (hasZodDef(fieldSchema)) {
|
|
159
|
+
const fieldDefaults = extractSchemaDefaults(
|
|
160
|
+
fieldSchema,
|
|
161
|
+
logger,
|
|
162
|
+
`${path}.${key}`,
|
|
163
|
+
forFormInit,
|
|
164
|
+
);
|
|
165
|
+
if (fieldDefaults !== undefined) {
|
|
166
|
+
result[key] = fieldDefaults;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Always return the result object for ZodObject (even if empty)
|
|
171
|
+
return result as Partial<T>;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Handle ZodOptional - check inner schema for defaults
|
|
175
|
+
if (schema instanceof z.ZodOptional) {
|
|
176
|
+
const innerType = getDefProperty<z.ZodTypeAny>(def, "innerType");
|
|
177
|
+
if (innerType && hasZodDef(innerType)) {
|
|
178
|
+
return extractSchemaDefaults<T>(
|
|
179
|
+
innerType,
|
|
180
|
+
logger,
|
|
181
|
+
`${path}.optional`,
|
|
182
|
+
forFormInit,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Handle ZodNullable - check inner schema for defaults
|
|
188
|
+
if (schema instanceof z.ZodNullable) {
|
|
189
|
+
const innerType = getDefProperty<z.ZodTypeAny>(def, "innerType");
|
|
190
|
+
if (innerType && hasZodDef(innerType)) {
|
|
191
|
+
return extractSchemaDefaults<T>(
|
|
192
|
+
innerType,
|
|
193
|
+
logger,
|
|
194
|
+
`${path}.nullable`,
|
|
195
|
+
forFormInit,
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Handle ZodEffects (refinements, transforms)
|
|
201
|
+
// In Zod v4, check typeName or use "effect" in traits
|
|
202
|
+
const isZodEffects = typeName === "ZodEffects" || defType === "effect";
|
|
203
|
+
if (isZodEffects) {
|
|
204
|
+
const innerSchema = getDefProperty<z.ZodTypeAny>(def, "schema");
|
|
205
|
+
if (innerSchema && hasZodDef(innerSchema)) {
|
|
206
|
+
return extractSchemaDefaults<T>(
|
|
207
|
+
innerSchema,
|
|
208
|
+
logger,
|
|
209
|
+
`${path}.effects`,
|
|
210
|
+
forFormInit,
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Handle ZodPipeline (Zod v4 uses this for transforms)
|
|
216
|
+
// In Zod v4, check def.type === "pipe"
|
|
217
|
+
const isZodPipeline = typeName === "ZodPipeline" || defType === "pipe";
|
|
218
|
+
if (isZodPipeline) {
|
|
219
|
+
const inSchema = getDefProperty<z.ZodTypeAny>(def, "in");
|
|
220
|
+
if (inSchema && hasZodDef(inSchema)) {
|
|
221
|
+
return extractSchemaDefaults<T>(
|
|
222
|
+
inSchema,
|
|
223
|
+
logger,
|
|
224
|
+
`${path}.pipeline`,
|
|
225
|
+
forFormInit,
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Handle ZodLazy - evaluate and extract
|
|
231
|
+
if (schema instanceof z.ZodLazy) {
|
|
232
|
+
const getter = getDefProperty<() => z.ZodTypeAny>(def, "getter");
|
|
233
|
+
if (typeof getter === "function") {
|
|
234
|
+
const lazySchema = getter();
|
|
235
|
+
if (hasZodDef(lazySchema)) {
|
|
236
|
+
return extractSchemaDefaults<T>(
|
|
237
|
+
lazySchema,
|
|
238
|
+
logger,
|
|
239
|
+
`${path}.lazy`,
|
|
240
|
+
forFormInit,
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// For form initialization, return appropriate empty defaults for primitives
|
|
247
|
+
// This ensures form fields start with valid values instead of undefined,
|
|
248
|
+
// which prevents "expected string, received undefined" validation errors
|
|
249
|
+
if (forFormInit) {
|
|
250
|
+
// Use both instanceof and def.type for Zod v4 compatibility
|
|
251
|
+
// Note: Type assertions are necessary here because we're doing runtime schema introspection
|
|
252
|
+
// and TypeScript can't verify at compile time that T matches the schema type
|
|
253
|
+
if (
|
|
254
|
+
schema instanceof z.ZodArray ||
|
|
255
|
+
typeName === "ZodArray" ||
|
|
256
|
+
defType === "array"
|
|
257
|
+
) {
|
|
258
|
+
return [] as T;
|
|
259
|
+
}
|
|
260
|
+
if (
|
|
261
|
+
schema instanceof z.ZodString ||
|
|
262
|
+
typeName === "ZodString" ||
|
|
263
|
+
defType === "string"
|
|
264
|
+
) {
|
|
265
|
+
return "" as T;
|
|
266
|
+
}
|
|
267
|
+
if (
|
|
268
|
+
schema instanceof z.ZodNumber ||
|
|
269
|
+
typeName === "ZodNumber" ||
|
|
270
|
+
defType === "number"
|
|
271
|
+
) {
|
|
272
|
+
return 0 as T;
|
|
273
|
+
}
|
|
274
|
+
if (
|
|
275
|
+
schema instanceof z.ZodBoolean ||
|
|
276
|
+
typeName === "ZodBoolean" ||
|
|
277
|
+
defType === "boolean"
|
|
278
|
+
) {
|
|
279
|
+
return false as T;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// For other types without defaults, return undefined
|
|
284
|
+
return undefined;
|
|
285
|
+
} catch (error) {
|
|
286
|
+
if (logger) {
|
|
287
|
+
logger.error("Error extracting schema defaults", {
|
|
288
|
+
path,
|
|
289
|
+
error: String(error),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return undefined;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// ============================================================================
|
|
297
|
+
// FIELD CREATORS
|
|
298
|
+
// ============================================================================
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Create a primitive field (string, number, boolean, etc.)
|
|
302
|
+
*/
|
|
303
|
+
export function field<
|
|
304
|
+
TKey extends string = TranslationKey,
|
|
305
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
306
|
+
const TSchema extends z.ZodTypeAny,
|
|
307
|
+
const TUsage extends FieldUsageConfig,
|
|
308
|
+
>(
|
|
309
|
+
schema: TSchema,
|
|
310
|
+
usage: TUsage,
|
|
311
|
+
ui: TUIConfig,
|
|
312
|
+
cache?: CacheStrategy,
|
|
313
|
+
): PrimitiveField<TSchema, TUsage, TKey, TUIConfig> {
|
|
314
|
+
return {
|
|
315
|
+
type: "primitive" as const,
|
|
316
|
+
schema,
|
|
317
|
+
usage,
|
|
318
|
+
ui,
|
|
319
|
+
cache,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Create a field that can be both request and response
|
|
325
|
+
*/
|
|
326
|
+
export function requestResponseField<
|
|
327
|
+
TKey extends string = TranslationKey,
|
|
328
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
329
|
+
TSchema extends z.ZodTypeAny = z.ZodTypeAny,
|
|
330
|
+
>(
|
|
331
|
+
ui: TUIConfig,
|
|
332
|
+
schema: TSchema,
|
|
333
|
+
cache?: CacheStrategy,
|
|
334
|
+
requestAsUrlParams?: false,
|
|
335
|
+
): PrimitiveField<
|
|
336
|
+
TSchema,
|
|
337
|
+
{ request: "data"; response: true },
|
|
338
|
+
TKey,
|
|
339
|
+
TUIConfig
|
|
340
|
+
>;
|
|
341
|
+
// eslint-disable-next-line no-redeclare
|
|
342
|
+
export function requestResponseField<
|
|
343
|
+
TKey extends string = TranslationKey,
|
|
344
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
345
|
+
TSchema extends z.ZodTypeAny = z.ZodTypeAny,
|
|
346
|
+
>(
|
|
347
|
+
ui: TUIConfig,
|
|
348
|
+
schema: TSchema,
|
|
349
|
+
cache?: CacheStrategy,
|
|
350
|
+
requestAsUrlParams?: true,
|
|
351
|
+
): PrimitiveField<
|
|
352
|
+
TSchema,
|
|
353
|
+
{ request: "urlPathParams"; response: true },
|
|
354
|
+
TKey,
|
|
355
|
+
TUIConfig
|
|
356
|
+
>;
|
|
357
|
+
// eslint-disable-next-line no-redeclare
|
|
358
|
+
export function requestResponseField<
|
|
359
|
+
TKey extends string = TranslationKey,
|
|
360
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
361
|
+
TSchema extends z.ZodTypeAny = z.ZodTypeAny,
|
|
362
|
+
>(
|
|
363
|
+
ui: TUIConfig,
|
|
364
|
+
schema: TSchema,
|
|
365
|
+
cache?: CacheStrategy,
|
|
366
|
+
requestAsUrlParams?: boolean,
|
|
367
|
+
): PrimitiveField<
|
|
368
|
+
TSchema,
|
|
369
|
+
{ request: "data" | "urlPathParams"; response: true },
|
|
370
|
+
TKey,
|
|
371
|
+
TUIConfig
|
|
372
|
+
> {
|
|
373
|
+
const requestType = requestAsUrlParams ? "urlPathParams" : "data";
|
|
374
|
+
return {
|
|
375
|
+
type: "primitive" as const,
|
|
376
|
+
schema,
|
|
377
|
+
usage: { request: requestType, response: true },
|
|
378
|
+
ui,
|
|
379
|
+
cache,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Create a request data field
|
|
385
|
+
*/
|
|
386
|
+
export function requestDataField<
|
|
387
|
+
TKey extends string = TranslationKey,
|
|
388
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
389
|
+
TSchema extends z.ZodTypeAny,
|
|
390
|
+
>(
|
|
391
|
+
ui: TUIConfig,
|
|
392
|
+
schema: TSchema,
|
|
393
|
+
cache?: CacheStrategy,
|
|
394
|
+
): PrimitiveField<TSchema, { request: "data" }, TKey, TUIConfig> {
|
|
395
|
+
return {
|
|
396
|
+
type: "primitive" as const,
|
|
397
|
+
schema,
|
|
398
|
+
usage: { request: "data" },
|
|
399
|
+
ui,
|
|
400
|
+
cache,
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Create a request URL params field
|
|
406
|
+
*/
|
|
407
|
+
export function requestUrlPathParamsField<
|
|
408
|
+
TKey extends string = TranslationKey,
|
|
409
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
410
|
+
TSchema extends z.ZodTypeAny,
|
|
411
|
+
>(
|
|
412
|
+
ui: TUIConfig,
|
|
413
|
+
schema: TSchema,
|
|
414
|
+
cache?: CacheStrategy,
|
|
415
|
+
): PrimitiveField<
|
|
416
|
+
TSchema,
|
|
417
|
+
{ request: "urlPathParams"; response?: never },
|
|
418
|
+
TKey,
|
|
419
|
+
TUIConfig
|
|
420
|
+
> {
|
|
421
|
+
return {
|
|
422
|
+
type: "primitive" as const,
|
|
423
|
+
schema,
|
|
424
|
+
usage: { request: "urlPathParams" },
|
|
425
|
+
ui,
|
|
426
|
+
cache,
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Create a response field
|
|
432
|
+
*/
|
|
433
|
+
export function responseField<
|
|
434
|
+
TKey extends string = TranslationKey,
|
|
435
|
+
TSchema extends z.ZodTypeAny,
|
|
436
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
437
|
+
>(
|
|
438
|
+
ui: TUIConfig,
|
|
439
|
+
schema: TSchema,
|
|
440
|
+
cache?: CacheStrategy,
|
|
441
|
+
): PrimitiveField<TSchema, { response: true }, TKey, TUIConfig> {
|
|
442
|
+
return {
|
|
443
|
+
type: "primitive" as const,
|
|
444
|
+
schema,
|
|
445
|
+
usage: { response: true },
|
|
446
|
+
ui,
|
|
447
|
+
cache,
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Create a widget-only field (buttons, alerts, static content)
|
|
453
|
+
*/
|
|
454
|
+
export function widgetField<
|
|
455
|
+
TKey extends string = TranslationKey,
|
|
456
|
+
TUsage extends FieldUsageConfig,
|
|
457
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
458
|
+
>(
|
|
459
|
+
ui: TUIConfig,
|
|
460
|
+
usage: TUsage,
|
|
461
|
+
cache?: CacheStrategy,
|
|
462
|
+
): WidgetField<TUsage, TKey, TUIConfig> {
|
|
463
|
+
return {
|
|
464
|
+
type: "widget" as const,
|
|
465
|
+
usage,
|
|
466
|
+
ui,
|
|
467
|
+
cache,
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Create an object field containing other fields
|
|
473
|
+
*
|
|
474
|
+
* Uses TranslationKey by default for automatic validation.
|
|
475
|
+
* For scoped translations, provide the scoped key type:
|
|
476
|
+
* objectField<ScopedKeyType>({ ... }, usage, children)
|
|
477
|
+
*/
|
|
478
|
+
export function objectField<
|
|
479
|
+
TKey extends string = TranslationKey,
|
|
480
|
+
TChildren extends Record<string, UnifiedField<string, z.ZodTypeAny>> = Record<
|
|
481
|
+
string,
|
|
482
|
+
UnifiedField<string, z.ZodTypeAny>
|
|
483
|
+
>,
|
|
484
|
+
TUsage extends FieldUsageConfig = FieldUsageConfig,
|
|
485
|
+
const TUIConfig extends WidgetConfig<TKey> = WidgetConfig<TKey>,
|
|
486
|
+
>(
|
|
487
|
+
ui: TUIConfig,
|
|
488
|
+
usage: TUsage,
|
|
489
|
+
children: TChildren,
|
|
490
|
+
cache?: CacheStrategy,
|
|
491
|
+
): ObjectField<TChildren, TUsage, TKey, TUIConfig> {
|
|
492
|
+
return {
|
|
493
|
+
type: "object" as const,
|
|
494
|
+
children,
|
|
495
|
+
usage,
|
|
496
|
+
ui,
|
|
497
|
+
cache,
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Create an array field containing repeated items
|
|
503
|
+
*/
|
|
504
|
+
export function arrayField<
|
|
505
|
+
Child,
|
|
506
|
+
const TKey extends string = TranslationKey,
|
|
507
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
508
|
+
>(
|
|
509
|
+
usage: FieldUsageConfig,
|
|
510
|
+
ui: TUIConfig,
|
|
511
|
+
child: Child,
|
|
512
|
+
cache?: CacheStrategy,
|
|
513
|
+
): ArrayField<Child, FieldUsageConfig, TKey, TUIConfig> {
|
|
514
|
+
return {
|
|
515
|
+
type: "array" as const,
|
|
516
|
+
child,
|
|
517
|
+
usage,
|
|
518
|
+
ui,
|
|
519
|
+
cache,
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Create a request array field
|
|
525
|
+
*/
|
|
526
|
+
export function requestDataArrayField<
|
|
527
|
+
Child,
|
|
528
|
+
const TKey extends string = TranslationKey,
|
|
529
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
530
|
+
>(
|
|
531
|
+
ui: TUIConfig,
|
|
532
|
+
child: Child,
|
|
533
|
+
cache?: CacheStrategy,
|
|
534
|
+
): ArrayField<Child, { request: "data" }, TKey, TUIConfig> {
|
|
535
|
+
return {
|
|
536
|
+
type: "array" as const,
|
|
537
|
+
child,
|
|
538
|
+
usage: { request: "data" },
|
|
539
|
+
ui,
|
|
540
|
+
cache,
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Create a response array field
|
|
546
|
+
*/
|
|
547
|
+
export function responseArrayField<
|
|
548
|
+
Child,
|
|
549
|
+
const TKey extends string = TranslationKey,
|
|
550
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
551
|
+
>(
|
|
552
|
+
ui: TUIConfig,
|
|
553
|
+
child: Child,
|
|
554
|
+
cache?: CacheStrategy,
|
|
555
|
+
): ArrayField<Child, { response: true }, TKey, TUIConfig> {
|
|
556
|
+
return {
|
|
557
|
+
type: "array" as const,
|
|
558
|
+
child,
|
|
559
|
+
usage: { response: true },
|
|
560
|
+
ui,
|
|
561
|
+
cache,
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Create an optional object field
|
|
567
|
+
*/
|
|
568
|
+
export function objectOptionalField<
|
|
569
|
+
C,
|
|
570
|
+
U extends FieldUsageConfig,
|
|
571
|
+
const TKey extends string = TranslationKey,
|
|
572
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
573
|
+
>(
|
|
574
|
+
ui: TUIConfig,
|
|
575
|
+
usage: U,
|
|
576
|
+
children: C,
|
|
577
|
+
cache?: CacheStrategy,
|
|
578
|
+
): ObjectOptionalField<C, U, TKey, TUIConfig> {
|
|
579
|
+
return {
|
|
580
|
+
type: "object-optional" as const,
|
|
581
|
+
children,
|
|
582
|
+
usage,
|
|
583
|
+
ui,
|
|
584
|
+
cache,
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Create a discriminated union object field
|
|
590
|
+
*/
|
|
591
|
+
export function objectUnionField<
|
|
592
|
+
TDiscriminator extends string,
|
|
593
|
+
TVariants extends readonly [
|
|
594
|
+
ObjectField<
|
|
595
|
+
Record<string, UnifiedField<TKey, z.ZodTypeAny>>,
|
|
596
|
+
FieldUsageConfig,
|
|
597
|
+
TKey,
|
|
598
|
+
WidgetConfig<TKey>
|
|
599
|
+
>,
|
|
600
|
+
...ObjectField<
|
|
601
|
+
Record<string, UnifiedField<TKey, z.ZodTypeAny>>,
|
|
602
|
+
FieldUsageConfig,
|
|
603
|
+
TKey,
|
|
604
|
+
WidgetConfig<TKey>
|
|
605
|
+
>[],
|
|
606
|
+
],
|
|
607
|
+
TUsage extends FieldUsageConfig,
|
|
608
|
+
const TKey extends string = TranslationKey,
|
|
609
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
610
|
+
>(
|
|
611
|
+
ui: TUIConfig,
|
|
612
|
+
usage: TUsage,
|
|
613
|
+
discriminator: TDiscriminator,
|
|
614
|
+
variants: TVariants,
|
|
615
|
+
cache?: CacheStrategy,
|
|
616
|
+
): ObjectUnionField<TDiscriminator, TKey, TVariants, TUsage, TUIConfig> {
|
|
617
|
+
return {
|
|
618
|
+
type: "object-union" as const,
|
|
619
|
+
discriminator,
|
|
620
|
+
variants,
|
|
621
|
+
usage,
|
|
622
|
+
ui,
|
|
623
|
+
cache,
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Create an optional array field
|
|
629
|
+
*/
|
|
630
|
+
export function arrayOptionalField<
|
|
631
|
+
Child,
|
|
632
|
+
const TKey extends string = TranslationKey,
|
|
633
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
634
|
+
>(
|
|
635
|
+
usage: FieldUsageConfig,
|
|
636
|
+
ui: TUIConfig,
|
|
637
|
+
child: Child,
|
|
638
|
+
cache?: CacheStrategy,
|
|
639
|
+
): ArrayOptionalField<Child, FieldUsageConfig, TKey, TUIConfig> {
|
|
640
|
+
return {
|
|
641
|
+
type: "array-optional" as const,
|
|
642
|
+
child,
|
|
643
|
+
usage,
|
|
644
|
+
ui,
|
|
645
|
+
cache,
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Create an optional request array field
|
|
651
|
+
*/
|
|
652
|
+
export function requestDataArrayOptionalField<
|
|
653
|
+
Child,
|
|
654
|
+
const TKey extends string = TranslationKey,
|
|
655
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
656
|
+
>(
|
|
657
|
+
ui: TUIConfig,
|
|
658
|
+
child: Child,
|
|
659
|
+
cache?: CacheStrategy,
|
|
660
|
+
): ArrayOptionalField<Child, { request: "data" }, TKey, TUIConfig> {
|
|
661
|
+
return {
|
|
662
|
+
type: "array-optional" as const,
|
|
663
|
+
child,
|
|
664
|
+
usage: { request: "data" },
|
|
665
|
+
ui,
|
|
666
|
+
cache,
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Create an optional response array field
|
|
672
|
+
*/
|
|
673
|
+
export function responseArrayOptionalField<
|
|
674
|
+
Child,
|
|
675
|
+
const TKey extends string = TranslationKey,
|
|
676
|
+
const TUIConfig extends WidgetConfig<TKey>,
|
|
677
|
+
>(
|
|
678
|
+
ui: TUIConfig,
|
|
679
|
+
child: Child,
|
|
680
|
+
cache?: CacheStrategy,
|
|
681
|
+
): ArrayOptionalField<Child, { response: true }, TKey, TUIConfig> {
|
|
682
|
+
return {
|
|
683
|
+
type: "array-optional" as const,
|
|
684
|
+
child,
|
|
685
|
+
usage: { response: true },
|
|
686
|
+
ui,
|
|
687
|
+
cache,
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// ============================================================================
|
|
692
|
+
// FIELD TYPE INFERENCE UTILITIES
|
|
693
|
+
// ============================================================================
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Check if a field usage has response capability
|
|
697
|
+
*/
|
|
698
|
+
export type HasResponseUsage<U> = U extends { response: true } ? true : false;
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Check if a field usage has request data capability
|
|
702
|
+
*/
|
|
703
|
+
export type HasRequestDataUsage<U> = U extends { request: "data" }
|
|
704
|
+
? true
|
|
705
|
+
: U extends { request: "data&urlPathParams" }
|
|
706
|
+
? true
|
|
707
|
+
: false;
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Check if a field usage has request URL params capability
|
|
711
|
+
*/
|
|
712
|
+
export type HasRequestUrlParamsUsage<U> = U extends { request: "urlPathParams" }
|
|
713
|
+
? true
|
|
714
|
+
: U extends { request: "data&urlPathParams" }
|
|
715
|
+
? true
|
|
716
|
+
: false;
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* Extract the core properties of a field
|
|
720
|
+
*/
|
|
721
|
+
export type FieldCore<F> = F extends {
|
|
722
|
+
type: infer T;
|
|
723
|
+
usage: infer U;
|
|
724
|
+
schema: infer S;
|
|
725
|
+
}
|
|
726
|
+
? { type: T; usage: U; schema: S }
|
|
727
|
+
: F extends {
|
|
728
|
+
type: infer T;
|
|
729
|
+
usage: infer U;
|
|
730
|
+
}
|
|
731
|
+
? { type: T; usage: U }
|
|
732
|
+
: F extends {
|
|
733
|
+
type: infer T;
|
|
734
|
+
schema: infer S;
|
|
735
|
+
}
|
|
736
|
+
? { type: T; schema: S }
|
|
737
|
+
: F extends {
|
|
738
|
+
type: infer T;
|
|
739
|
+
}
|
|
740
|
+
? { type: T }
|
|
741
|
+
: never;
|
|
742
|
+
/**
|
|
743
|
+
* Check if a field has optional flag in UI config
|
|
744
|
+
* This type checks at the VALUE level, not just the type level
|
|
745
|
+
* It preserves literal types when the UI config is passed with proper inference
|
|
746
|
+
*/
|
|
747
|
+
type IsOptionalField<F> =
|
|
748
|
+
// Check if field type is explicitly optional (array-optional, object-optional)
|
|
749
|
+
F extends { type: "array-optional" | "object-optional" }
|
|
750
|
+
? true
|
|
751
|
+
: // Otherwise check ui.optional flag
|
|
752
|
+
F extends {
|
|
753
|
+
ui: infer UI;
|
|
754
|
+
}
|
|
755
|
+
? UI extends { optional?: infer O }
|
|
756
|
+
? [O] extends [true]
|
|
757
|
+
? true
|
|
758
|
+
: [O] extends [false]
|
|
759
|
+
? false
|
|
760
|
+
: false
|
|
761
|
+
: false
|
|
762
|
+
: false;
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Make type optional with nullable support (T | null | undefined)
|
|
766
|
+
*/
|
|
767
|
+
type MakeOptional<T, IsOptional extends boolean> = IsOptional extends true
|
|
768
|
+
? T | null | undefined
|
|
769
|
+
: T;
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* Infer union type from ObjectUnionField variants
|
|
773
|
+
*/
|
|
774
|
+
export type InferUnionType<
|
|
775
|
+
TTranslatedKey extends string,
|
|
776
|
+
TVariants extends readonly ObjectField<
|
|
777
|
+
Record<string, UnifiedField<TTranslatedKey, z.ZodTypeAny>>,
|
|
778
|
+
FieldUsageConfig,
|
|
779
|
+
TTranslatedKey,
|
|
780
|
+
WidgetConfig<TTranslatedKey>
|
|
781
|
+
>[],
|
|
782
|
+
Usage extends FieldUsage,
|
|
783
|
+
> = TVariants extends readonly [infer Head, ...infer Tail]
|
|
784
|
+
? Head extends ObjectField<
|
|
785
|
+
Record<string, UnifiedField<TTranslatedKey, z.ZodTypeAny>>,
|
|
786
|
+
FieldUsageConfig,
|
|
787
|
+
TTranslatedKey,
|
|
788
|
+
WidgetConfig<TTranslatedKey>
|
|
789
|
+
>
|
|
790
|
+
? Tail extends ObjectField<
|
|
791
|
+
Record<string, UnifiedField<TTranslatedKey, z.ZodTypeAny>>,
|
|
792
|
+
FieldUsageConfig,
|
|
793
|
+
TTranslatedKey,
|
|
794
|
+
WidgetConfig<TTranslatedKey>
|
|
795
|
+
>[]
|
|
796
|
+
?
|
|
797
|
+
| InferFieldType<Head, Usage, TTranslatedKey>
|
|
798
|
+
| InferUnionType<TTranslatedKey, Tail, Usage>
|
|
799
|
+
: InferFieldType<Head, Usage, TTranslatedKey>
|
|
800
|
+
: never
|
|
801
|
+
: never;
|
|
802
|
+
|
|
803
|
+
/**
|
|
804
|
+
* Infer field type based on usage
|
|
805
|
+
*/
|
|
806
|
+
export type InferFieldType<F, Usage extends FieldUsage, TKey extends string> =
|
|
807
|
+
F extends UnifiedField<TKey, infer TSchema>
|
|
808
|
+
? F extends {
|
|
809
|
+
type: "primitive";
|
|
810
|
+
usage: infer U;
|
|
811
|
+
}
|
|
812
|
+
? Usage extends FieldUsage.Response
|
|
813
|
+
? HasResponseUsage<U> extends true
|
|
814
|
+
? z.output<TSchema>
|
|
815
|
+
: never
|
|
816
|
+
: Usage extends FieldUsage.RequestData
|
|
817
|
+
? HasRequestDataUsage<U> extends true
|
|
818
|
+
? z.output<TSchema>
|
|
819
|
+
: never
|
|
820
|
+
: Usage extends FieldUsage.RequestUrlParams
|
|
821
|
+
? HasRequestUrlParamsUsage<U> extends true
|
|
822
|
+
? z.output<TSchema>
|
|
823
|
+
: never
|
|
824
|
+
: never
|
|
825
|
+
: F extends {
|
|
826
|
+
type: "array" | "array-optional";
|
|
827
|
+
child: infer Child;
|
|
828
|
+
usage: infer U;
|
|
829
|
+
}
|
|
830
|
+
? Usage extends FieldUsage.Response
|
|
831
|
+
? HasResponseUsage<U> extends true
|
|
832
|
+
? MakeOptional<
|
|
833
|
+
Array<InferFieldType<Child, Usage, TKey>>,
|
|
834
|
+
IsOptionalField<F>
|
|
835
|
+
>
|
|
836
|
+
: never
|
|
837
|
+
: Usage extends FieldUsage.RequestData
|
|
838
|
+
? HasRequestDataUsage<U> extends true
|
|
839
|
+
? MakeOptional<
|
|
840
|
+
Array<InferFieldType<Child, Usage, TKey>>,
|
|
841
|
+
IsOptionalField<F>
|
|
842
|
+
>
|
|
843
|
+
: never
|
|
844
|
+
: Usage extends FieldUsage.RequestUrlParams
|
|
845
|
+
? HasRequestUrlParamsUsage<U> extends true
|
|
846
|
+
? MakeOptional<
|
|
847
|
+
Array<InferFieldType<Child, Usage, TKey>>,
|
|
848
|
+
IsOptionalField<F>
|
|
849
|
+
>
|
|
850
|
+
: never
|
|
851
|
+
: never
|
|
852
|
+
: F extends {
|
|
853
|
+
type: "object-union";
|
|
854
|
+
variants: infer TVariants;
|
|
855
|
+
usage: infer U;
|
|
856
|
+
}
|
|
857
|
+
? TVariants extends readonly ObjectField<
|
|
858
|
+
Record<string, UnifiedField<TKey, z.ZodTypeAny>>,
|
|
859
|
+
FieldUsageConfig,
|
|
860
|
+
TKey,
|
|
861
|
+
WidgetConfig<TKey>
|
|
862
|
+
>[]
|
|
863
|
+
? Usage extends FieldUsage.Response
|
|
864
|
+
? HasResponseUsage<U> extends true
|
|
865
|
+
? InferUnionType<TKey, TVariants, Usage>
|
|
866
|
+
: never
|
|
867
|
+
: Usage extends FieldUsage.RequestData
|
|
868
|
+
? HasRequestDataUsage<U> extends true
|
|
869
|
+
? InferUnionType<TKey, TVariants, Usage>
|
|
870
|
+
: never
|
|
871
|
+
: Usage extends FieldUsage.RequestUrlParams
|
|
872
|
+
? HasRequestUrlParamsUsage<U> extends true
|
|
873
|
+
? InferUnionType<TKey, TVariants, Usage>
|
|
874
|
+
: never
|
|
875
|
+
: never
|
|
876
|
+
: never
|
|
877
|
+
: F extends {
|
|
878
|
+
type: "object" | "object-optional";
|
|
879
|
+
children: infer C;
|
|
880
|
+
usage: infer U;
|
|
881
|
+
}
|
|
882
|
+
? Usage extends FieldUsage.Response
|
|
883
|
+
? HasResponseUsage<U> extends true
|
|
884
|
+
? MakeOptional<
|
|
885
|
+
InferObjectType<C, Usage, TKey>,
|
|
886
|
+
IsOptionalField<F>
|
|
887
|
+
>
|
|
888
|
+
: never
|
|
889
|
+
: Usage extends FieldUsage.RequestData
|
|
890
|
+
? HasRequestDataUsage<U> extends true
|
|
891
|
+
? MakeOptional<
|
|
892
|
+
InferObjectType<C, Usage, TKey>,
|
|
893
|
+
IsOptionalField<F>
|
|
894
|
+
>
|
|
895
|
+
: never
|
|
896
|
+
: Usage extends FieldUsage.RequestUrlParams
|
|
897
|
+
? HasRequestUrlParamsUsage<U> extends true
|
|
898
|
+
? MakeOptional<
|
|
899
|
+
InferObjectType<C, Usage, TKey>,
|
|
900
|
+
IsOptionalField<F>
|
|
901
|
+
>
|
|
902
|
+
: never
|
|
903
|
+
: never
|
|
904
|
+
: F extends {
|
|
905
|
+
type: "object" | "object-optional";
|
|
906
|
+
children: infer C;
|
|
907
|
+
}
|
|
908
|
+
? MakeOptional<
|
|
909
|
+
InferObjectType<C, Usage, TKey>,
|
|
910
|
+
IsOptionalField<F>
|
|
911
|
+
>
|
|
912
|
+
: never
|
|
913
|
+
: never;
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Infer object type from children fields
|
|
917
|
+
* Uses flexible constraint that accepts both readonly and mutable properties
|
|
918
|
+
* Checks each field's optional flag to make properties optional in the resulting type
|
|
919
|
+
*/
|
|
920
|
+
export type InferObjectType<C, Usage extends FieldUsage, TKey extends string> =
|
|
921
|
+
C extends Record<string, UnifiedField<TKey, z.ZodTypeAny>>
|
|
922
|
+
? {
|
|
923
|
+
-readonly [K in keyof C as InferFieldType<
|
|
924
|
+
C[K],
|
|
925
|
+
Usage,
|
|
926
|
+
TKey
|
|
927
|
+
> extends never
|
|
928
|
+
? never
|
|
929
|
+
: IsOptionalField<C[K]> extends true
|
|
930
|
+
? never
|
|
931
|
+
: K]: InferFieldType<C[K], Usage, TKey>;
|
|
932
|
+
} & {
|
|
933
|
+
-readonly [K in keyof C as InferFieldType<
|
|
934
|
+
C[K],
|
|
935
|
+
Usage,
|
|
936
|
+
TKey
|
|
937
|
+
> extends never
|
|
938
|
+
? never
|
|
939
|
+
: IsOptionalField<C[K]> extends true
|
|
940
|
+
? K
|
|
941
|
+
: never]?: InferFieldType<C[K], Usage, TKey>;
|
|
942
|
+
}
|
|
943
|
+
: never;
|
|
944
|
+
|
|
945
|
+
// ============================================================================
|
|
946
|
+
// SCHEMA GENERATION UTILITIES
|
|
947
|
+
// ============================================================================
|
|
948
|
+
|
|
949
|
+
/**
|
|
950
|
+
* Generate schema for a specific usage from unified fields
|
|
951
|
+
* CRITICAL: This function must preserve the actual Zod schema types to enable
|
|
952
|
+
* proper input/output type differentiation using z.ZodType<Output, ZodTypeDef, Input>.
|
|
953
|
+
*
|
|
954
|
+
* We return the actual inferred schema type to preserve input/output differentiation.
|
|
955
|
+
*/
|
|
956
|
+
export function generateSchemaForUsage<F, Usage extends FieldUsage>(
|
|
957
|
+
field: F,
|
|
958
|
+
targetUsage: Usage,
|
|
959
|
+
): InferSchemaFromField<F, Usage> {
|
|
960
|
+
// Defensive check: ensure field is defined
|
|
961
|
+
if (!field || typeof field !== "object") {
|
|
962
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
const hasUsage = (usage: FieldUsageConfig | undefined): boolean => {
|
|
966
|
+
if (!usage) {
|
|
967
|
+
return false;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
switch (targetUsage) {
|
|
971
|
+
case FieldUsage.Response:
|
|
972
|
+
return "response" in usage && usage.response === true;
|
|
973
|
+
case FieldUsage.RequestData:
|
|
974
|
+
return (
|
|
975
|
+
"request" in usage &&
|
|
976
|
+
(usage.request === "data" || usage.request === "data&urlPathParams")
|
|
977
|
+
);
|
|
978
|
+
case FieldUsage.RequestUrlParams:
|
|
979
|
+
return (
|
|
980
|
+
"request" in usage &&
|
|
981
|
+
(usage.request === "urlPathParams" ||
|
|
982
|
+
usage.request === "data&urlPathParams")
|
|
983
|
+
);
|
|
984
|
+
default:
|
|
985
|
+
return false;
|
|
986
|
+
}
|
|
987
|
+
};
|
|
988
|
+
|
|
989
|
+
interface FieldWithType {
|
|
990
|
+
type:
|
|
991
|
+
| "primitive"
|
|
992
|
+
| "widget"
|
|
993
|
+
| "object"
|
|
994
|
+
| "object-optional"
|
|
995
|
+
| "object-union"
|
|
996
|
+
| "array"
|
|
997
|
+
| "array-optional";
|
|
998
|
+
usage?: FieldUsageConfig;
|
|
999
|
+
schema?: z.ZodTypeAny;
|
|
1000
|
+
children?: Record<string, UnifiedField<string, z.ZodTypeAny>>;
|
|
1001
|
+
child?: UnifiedField<string, z.ZodTypeAny>;
|
|
1002
|
+
discriminator?: string;
|
|
1003
|
+
variants?: readonly ObjectField<
|
|
1004
|
+
Record<string, UnifiedField<string, z.ZodTypeAny>>,
|
|
1005
|
+
FieldUsageConfig,
|
|
1006
|
+
string,
|
|
1007
|
+
WidgetConfig<string>
|
|
1008
|
+
>[];
|
|
1009
|
+
ui?: WidgetConfig<string>;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
const typedField = field as F & FieldWithType;
|
|
1013
|
+
|
|
1014
|
+
// Create a reference z.never() type for comparison - ensures runtime correctness
|
|
1015
|
+
const neverType = z.never()._def.type;
|
|
1016
|
+
|
|
1017
|
+
// Widget-only fields have no schema and are skipped during schema generation
|
|
1018
|
+
if (typedField.type === "widget") {
|
|
1019
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
if (typedField.type === "primitive") {
|
|
1023
|
+
if (hasUsage(typedField.usage)) {
|
|
1024
|
+
return typedField.schema as InferSchemaFromField<F, Usage>;
|
|
1025
|
+
}
|
|
1026
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
if (typedField.type === "object") {
|
|
1030
|
+
// Check if the object itself has the required usage
|
|
1031
|
+
// If it has explicit usage that doesn't match, skip processing children
|
|
1032
|
+
const objectHasUsage = typedField.usage ? hasUsage(typedField.usage) : true;
|
|
1033
|
+
|
|
1034
|
+
if (typedField.usage && !objectHasUsage) {
|
|
1035
|
+
// For request data, return empty object (endpoints with no parameters)
|
|
1036
|
+
// This is critical for OpenAI function calling which requires type: "object"
|
|
1037
|
+
if (targetUsage === FieldUsage.RequestData) {
|
|
1038
|
+
const emptySchema = z.object({});
|
|
1039
|
+
return emptySchema as InferSchemaFromField<F, Usage>;
|
|
1040
|
+
}
|
|
1041
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
// Build shape object with proper typing to preserve schema types
|
|
1045
|
+
// We need to avoid using Record<string, z.ZodTypeAny> which loses type information
|
|
1046
|
+
const shape: Record<string, z.ZodTypeAny> = {};
|
|
1047
|
+
|
|
1048
|
+
if (typedField.children) {
|
|
1049
|
+
for (const [key, childField] of Object.entries(typedField.children)) {
|
|
1050
|
+
// CRITICAL: Skip widget fields completely - they should NEVER be in validation schemas
|
|
1051
|
+
// Widget fields (formAlert, submitButton, etc.) are UI-only and don't send/receive data
|
|
1052
|
+
const isWidgetField =
|
|
1053
|
+
"type" in childField && childField.type === "widget";
|
|
1054
|
+
if (isWidgetField) {
|
|
1055
|
+
continue;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
// CRITICAL: Skip objectFields that only contain widget children - they're UI-only containers
|
|
1059
|
+
// Examples: footerLinks container with only widget links inside
|
|
1060
|
+
const isObjectFieldWithOnlyWidgets =
|
|
1061
|
+
childField.type === "object" &&
|
|
1062
|
+
childField.children &&
|
|
1063
|
+
Object.values(childField.children).every(
|
|
1064
|
+
(grandchild) =>
|
|
1065
|
+
"type" in grandchild && grandchild.type === "widget",
|
|
1066
|
+
);
|
|
1067
|
+
if (isObjectFieldWithOnlyWidgets) {
|
|
1068
|
+
continue;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
// Check if the child field has the required usage BEFORE generating the schema
|
|
1072
|
+
// This is more efficient and avoids issues with z.never() detection
|
|
1073
|
+
if (childField.usage) {
|
|
1074
|
+
const childHasUsage =
|
|
1075
|
+
targetUsage === FieldUsage.Response
|
|
1076
|
+
? "response" in childField.usage &&
|
|
1077
|
+
childField.usage.response === true
|
|
1078
|
+
: targetUsage === FieldUsage.RequestData
|
|
1079
|
+
? "request" in childField.usage &&
|
|
1080
|
+
(childField.usage.request === "data" ||
|
|
1081
|
+
childField.usage.request === "data&urlPathParams")
|
|
1082
|
+
: targetUsage === FieldUsage.RequestUrlParams
|
|
1083
|
+
? "request" in childField.usage &&
|
|
1084
|
+
(childField.usage.request === "urlPathParams" ||
|
|
1085
|
+
childField.usage.request === "data&urlPathParams")
|
|
1086
|
+
: false;
|
|
1087
|
+
|
|
1088
|
+
// Skip fields that don't have the required usage
|
|
1089
|
+
if (!childHasUsage) {
|
|
1090
|
+
continue;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
const childSchema = generateSchemaForUsage<typeof childField, Usage>(
|
|
1095
|
+
childField,
|
|
1096
|
+
targetUsage,
|
|
1097
|
+
);
|
|
1098
|
+
// Check if schema is z.never() by comparing type to actual z.never() instance
|
|
1099
|
+
if (childSchema._def.type !== neverType) {
|
|
1100
|
+
shape[key] = childSchema;
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// If no children matched the usage, return z.never()
|
|
1106
|
+
// This handles cases like container fields with only widget children
|
|
1107
|
+
// These UI-only containers shouldn't be in validation schemas
|
|
1108
|
+
if (Object.keys(shape).length === 0) {
|
|
1109
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
// Create the object schema and let TypeScript infer the exact type
|
|
1113
|
+
// This preserves the specific field types instead of collapsing to ZodTypeAny
|
|
1114
|
+
let objectSchema = z.object(shape);
|
|
1115
|
+
|
|
1116
|
+
// Apply optional modifier if specified in UI config
|
|
1117
|
+
if (
|
|
1118
|
+
typedField.ui &&
|
|
1119
|
+
"optional" in typedField.ui &&
|
|
1120
|
+
typedField.ui.optional
|
|
1121
|
+
) {
|
|
1122
|
+
const optionalSchema = objectSchema.nullable().optional();
|
|
1123
|
+
// eslint-disable-next-line oxlint-plugin-restricted/restricted-syntax -- Type casting: Complex Zod schema inference requires unknown as intermediate step for type safety between incompatible generic structures.
|
|
1124
|
+
return optionalSchema as unknown as InferSchemaFromField<F, Usage>;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
return objectSchema as InferSchemaFromField<F, Usage>;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
if (typedField.type === "object-optional") {
|
|
1131
|
+
// Check if the object itself has the required usage
|
|
1132
|
+
const objectHasUsage = typedField.usage ? hasUsage(typedField.usage) : true;
|
|
1133
|
+
|
|
1134
|
+
if (typedField.usage && !objectHasUsage) {
|
|
1135
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
// Build shape object with proper typing to preserve schema types
|
|
1139
|
+
const shape: Record<string, z.ZodTypeAny> = {};
|
|
1140
|
+
|
|
1141
|
+
if (typedField.children) {
|
|
1142
|
+
for (const [key, childField] of Object.entries(typedField.children)) {
|
|
1143
|
+
// Skip widget fields - they're UI-only
|
|
1144
|
+
const isWidgetField =
|
|
1145
|
+
"type" in childField && childField.type === "widget";
|
|
1146
|
+
if (isWidgetField) {
|
|
1147
|
+
continue;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
const childSchema = generateSchemaForUsage<typeof childField, Usage>(
|
|
1151
|
+
childField,
|
|
1152
|
+
targetUsage,
|
|
1153
|
+
);
|
|
1154
|
+
if (childSchema._def.type !== neverType) {
|
|
1155
|
+
shape[key] = childSchema;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
// If no children matched the usage, return z.never()
|
|
1161
|
+
if (Object.keys(shape).length === 0) {
|
|
1162
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
// Create the object schema and wrap in nullable().optional() for object-optional
|
|
1166
|
+
const objectSchema = z.object(shape).nullable().optional();
|
|
1167
|
+
return objectSchema as InferSchemaFromField<F, Usage>;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
if (typedField.type === "object-union") {
|
|
1171
|
+
// Check if the union itself has the required usage
|
|
1172
|
+
const unionHasUsage = typedField.usage ? hasUsage(typedField.usage) : true;
|
|
1173
|
+
|
|
1174
|
+
if (typedField.usage && !unionHasUsage) {
|
|
1175
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
// Validate discriminator and variants exist
|
|
1179
|
+
if (!typedField.discriminator || !typedField.variants) {
|
|
1180
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
// Generate schemas for each variant
|
|
1184
|
+
const variantSchemas: z.ZodObject<z.ZodRawShape>[] = [];
|
|
1185
|
+
|
|
1186
|
+
for (const variant of typedField.variants) {
|
|
1187
|
+
// Generate schema for this variant using the same target usage
|
|
1188
|
+
const variantSchema = generateSchemaForUsage<typeof variant, Usage>(
|
|
1189
|
+
variant,
|
|
1190
|
+
targetUsage,
|
|
1191
|
+
);
|
|
1192
|
+
|
|
1193
|
+
// Skip variants that don't match the usage
|
|
1194
|
+
if (variantSchema._def.type === neverType) {
|
|
1195
|
+
continue;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
// Ensure the variant schema is a ZodObject (required for discriminated unions)
|
|
1199
|
+
if (variantSchema instanceof z.ZodObject) {
|
|
1200
|
+
variantSchemas.push(variantSchema);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// If no variants matched the usage, return z.never()
|
|
1205
|
+
if (variantSchemas.length === 0) {
|
|
1206
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
// If only one variant, just return it (no need for union)
|
|
1210
|
+
if (variantSchemas.length === 1) {
|
|
1211
|
+
return variantSchemas[0] as InferSchemaFromField<F, Usage>;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
// Create discriminated union with at least 2 variants
|
|
1215
|
+
const unionSchema = z.discriminatedUnion(
|
|
1216
|
+
typedField.discriminator,
|
|
1217
|
+
variantSchemas as [
|
|
1218
|
+
z.ZodObject<z.ZodRawShape>,
|
|
1219
|
+
z.ZodObject<z.ZodRawShape>,
|
|
1220
|
+
...z.ZodObject<z.ZodRawShape>[],
|
|
1221
|
+
],
|
|
1222
|
+
);
|
|
1223
|
+
|
|
1224
|
+
// eslint-disable-next-line oxlint-plugin-restricted/restricted-syntax, @typescript-eslint/no-explicit-any -- Schema generation requires type assertion for proper inference
|
|
1225
|
+
return unionSchema as any as InferSchemaFromField<F, Usage>;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
if (typedField.type === "array") {
|
|
1229
|
+
if (hasUsage(typedField.usage)) {
|
|
1230
|
+
// Check if child exists
|
|
1231
|
+
if (!typedField.child) {
|
|
1232
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
let childSchema: z.ZodTypeAny;
|
|
1236
|
+
if (isZodSchema(typedField.child)) {
|
|
1237
|
+
// Child is already a Zod schema, use it directly
|
|
1238
|
+
childSchema = typedField.child;
|
|
1239
|
+
} else {
|
|
1240
|
+
// Child is a UnifiedField, generate schema from it
|
|
1241
|
+
childSchema = generateSchemaForUsage<typeof typedField.child, Usage>(
|
|
1242
|
+
typedField.child,
|
|
1243
|
+
targetUsage,
|
|
1244
|
+
);
|
|
1245
|
+
// Check if schema is z.never() using _def.type check
|
|
1246
|
+
if (childSchema._def.type === neverType) {
|
|
1247
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
let arraySchema = z.array(childSchema);
|
|
1252
|
+
|
|
1253
|
+
// Apply optional modifier if specified in UI config
|
|
1254
|
+
if (
|
|
1255
|
+
typedField.ui &&
|
|
1256
|
+
"optional" in typedField.ui &&
|
|
1257
|
+
typedField.ui.optional
|
|
1258
|
+
) {
|
|
1259
|
+
const optionalArraySchema = arraySchema.nullable().optional();
|
|
1260
|
+
// eslint-disable-next-line oxlint-plugin-restricted/restricted-syntax -- Type casting: Complex Zod schema inference requires unknown as intermediate step for type safety between incompatible generic structures.
|
|
1261
|
+
return optionalArraySchema as unknown as InferSchemaFromField<F, Usage>;
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
return arraySchema as InferSchemaFromField<F, Usage>;
|
|
1265
|
+
}
|
|
1266
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
if (typedField.type === "array-optional") {
|
|
1270
|
+
if (hasUsage(typedField.usage)) {
|
|
1271
|
+
// Check if child exists
|
|
1272
|
+
if (!typedField.child) {
|
|
1273
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
let childSchema: z.ZodTypeAny;
|
|
1277
|
+
if (isZodSchema(typedField.child)) {
|
|
1278
|
+
// Child is already a Zod schema, use it directly
|
|
1279
|
+
childSchema = typedField.child;
|
|
1280
|
+
} else {
|
|
1281
|
+
// Child is a UnifiedField, generate schema from it
|
|
1282
|
+
childSchema = generateSchemaForUsage<typeof typedField.child, Usage>(
|
|
1283
|
+
typedField.child,
|
|
1284
|
+
targetUsage,
|
|
1285
|
+
);
|
|
1286
|
+
// Check if schema is z.never() using _def.type check
|
|
1287
|
+
if (childSchema._def.type === neverType) {
|
|
1288
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
// For array-optional, always apply nullable and optional
|
|
1293
|
+
const arrayOptionalSchema = z.array(childSchema).nullable().optional();
|
|
1294
|
+
|
|
1295
|
+
// eslint-disable-next-line oxlint-plugin-restricted/restricted-syntax -- Type casting: Complex Zod schema inference requires unknown as intermediate step for type safety between incompatible generic structures.
|
|
1296
|
+
return arrayOptionalSchema as unknown as InferSchemaFromField<F, Usage>;
|
|
1297
|
+
}
|
|
1298
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
return z.never() as InferSchemaFromField<F, Usage>;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
// Utility types that work with z.ZodType<Output, ZodTypeDef, Input> to properly infer types
|
|
1305
|
+
// These preserve the input/output type differentiation from Zod schemas
|
|
1306
|
+
|
|
1307
|
+
export type InferFieldSchemaInputType<F, Usage extends FieldUsage> = z.input<
|
|
1308
|
+
ReturnType<typeof generateSchemaForUsage<F, Usage>>
|
|
1309
|
+
>;
|
|
1310
|
+
|
|
1311
|
+
export type InferFieldSchemaOutputType<F, Usage extends FieldUsage> = z.output<
|
|
1312
|
+
ReturnType<typeof generateSchemaForUsage<F, Usage>>
|
|
1313
|
+
>;
|
|
1314
|
+
|
|
1315
|
+
/**
|
|
1316
|
+
* Generate request data schema with proper input/output type differentiation
|
|
1317
|
+
*/
|
|
1318
|
+
export function generateRequestDataSchema<F>(
|
|
1319
|
+
field: F,
|
|
1320
|
+
): InferSchemaFromField<F, FieldUsage.RequestData> {
|
|
1321
|
+
return generateSchemaForUsage<F, FieldUsage.RequestData>(
|
|
1322
|
+
field,
|
|
1323
|
+
FieldUsage.RequestData,
|
|
1324
|
+
);
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
/**
|
|
1328
|
+
* Generate request URL params schema with proper input/output type differentiation
|
|
1329
|
+
*/
|
|
1330
|
+
export function generateRequestUrlSchema<F>(
|
|
1331
|
+
field: F,
|
|
1332
|
+
): InferSchemaFromField<F, FieldUsage.RequestUrlParams> {
|
|
1333
|
+
return generateSchemaForUsage<F, FieldUsage.RequestUrlParams>(
|
|
1334
|
+
field,
|
|
1335
|
+
FieldUsage.RequestUrlParams,
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
/**
|
|
1340
|
+
* Generate response schema with proper input/output type differentiation
|
|
1341
|
+
*/
|
|
1342
|
+
export function generateResponseSchema<F>(
|
|
1343
|
+
field: F,
|
|
1344
|
+
): InferSchemaFromField<F, FieldUsage.Response> {
|
|
1345
|
+
return generateSchemaForUsage<F, FieldUsage.Response>(
|
|
1346
|
+
field,
|
|
1347
|
+
FieldUsage.Response,
|
|
1348
|
+
);
|
|
1349
|
+
}
|