blockmine 1.24.0 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/README.en.md +427 -0
- package/README.md +40 -0
- package/backend/cli.js +1 -1
- package/backend/src/ai/plugin-assistant-system-prompt.md +664 -5
- package/backend/src/api/routes/bots.js +13 -0
- package/backend/src/api/routes/servers.js +14 -2
- package/backend/src/core/BotProcess.js +98 -2
- package/backend/src/core/PluginLoader.js +83 -3
- package/backend/src/core/PluginManager.js +75 -5
- package/backend/src/core/services/BotLifecycleService.js +186 -2
- package/backend/src/server.js +11 -1
- package/frontend/dist/assets/browser-ponyfill-DN7pwmHT.js +2 -0
- package/frontend/dist/assets/index-LSy71uwm.js +11261 -0
- package/frontend/dist/assets/index-SfhKxI4-.css +32 -0
- package/frontend/dist/flags/en.svg +32 -0
- package/frontend/dist/flags/ru.svg +5 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/dist/locales/en/admin.json +100 -0
- package/frontend/dist/locales/en/api-keys.json +58 -0
- package/frontend/dist/locales/en/bots.json +110 -0
- package/frontend/dist/locales/en/common.json +47 -0
- package/frontend/dist/locales/en/configuration.json +22 -0
- package/frontend/dist/locales/en/console.json +10 -0
- package/frontend/dist/locales/en/dashboard.json +85 -0
- package/frontend/dist/locales/en/dialogs.json +70 -0
- package/frontend/dist/locales/en/event-graphs.json +50 -0
- package/frontend/dist/locales/en/graph-store.json +70 -0
- package/frontend/dist/locales/en/login.json +34 -0
- package/frontend/dist/locales/en/management.json +114 -0
- package/frontend/dist/locales/en/minecraft-viewer.json +27 -0
- package/frontend/dist/locales/en/nodes.json +1077 -0
- package/frontend/dist/locales/en/permissions.json +50 -0
- package/frontend/dist/locales/en/plugin-detail.json +49 -0
- package/frontend/dist/locales/en/plugins.json +110 -0
- package/frontend/dist/locales/en/proxies.json +81 -0
- package/frontend/dist/locales/en/servers.json +39 -0
- package/frontend/dist/locales/en/setup.json +17 -0
- package/frontend/dist/locales/en/sidebar.json +27 -0
- package/frontend/dist/locales/en/tasks.json +62 -0
- package/frontend/dist/locales/en/visual-editor.json +219 -0
- package/frontend/dist/locales/en/websocket.json +86 -0
- package/frontend/dist/locales/ru/admin.json +100 -0
- package/frontend/dist/locales/ru/api-keys.json +58 -0
- package/frontend/dist/locales/ru/bots.json +110 -0
- package/frontend/dist/locales/ru/common.json +49 -0
- package/frontend/dist/locales/ru/configuration.json +22 -0
- package/frontend/dist/locales/ru/console.json +10 -0
- package/frontend/dist/locales/ru/dashboard.json +85 -0
- package/frontend/dist/locales/ru/dialogs.json +70 -0
- package/frontend/dist/locales/ru/event-graphs.json +50 -0
- package/frontend/dist/locales/ru/graph-store.json +70 -0
- package/frontend/dist/locales/ru/login.json +34 -0
- package/frontend/dist/locales/ru/management.json +114 -0
- package/frontend/dist/locales/ru/minecraft-viewer.json +27 -0
- package/frontend/dist/locales/ru/nodes.json +1077 -0
- package/frontend/dist/locales/ru/permissions.json +50 -0
- package/frontend/dist/locales/ru/plugin-detail.json +49 -0
- package/frontend/dist/locales/ru/plugins.json +110 -0
- package/frontend/dist/locales/ru/proxies.json +81 -0
- package/frontend/dist/locales/ru/servers.json +39 -0
- package/frontend/dist/locales/ru/setup.json +17 -0
- package/frontend/dist/locales/ru/sidebar.json +27 -0
- package/frontend/dist/locales/ru/tasks.json +62 -0
- package/frontend/dist/locales/ru/visual-editor.json +221 -0
- package/frontend/dist/locales/ru/websocket.json +86 -0
- package/frontend/dist/monacoeditorwork/css.worker.bundle.js +7 -7
- package/frontend/dist/monacoeditorwork/html.worker.bundle.js +7 -7
- package/frontend/dist/monacoeditorwork/json.worker.bundle.js +7 -7
- package/frontend/dist/monacoeditorwork/ts.worker.bundle.js +3 -3
- package/frontend/package.json +4 -0
- package/package.json +1 -1
- package/screen/3dviewer.png +0 -0
- package/screen/console.png +0 -0
- package/screen/dashboard.png +0 -0
- package/screen/graph_collabe.png +0 -0
- package/screen/graph_live_debug.png +0 -0
- package/screen/language_selector.png +0 -0
- package/screen/management_command.png +0 -0
- package/screen/node_debug_trace.png +0 -0
- package/screen/plugin_/320/276/320/261/320/267/320/276/321/200.png +0 -0
- package/screen/websocket.png +0 -0
- package/screen//320/275/320/260/321/201/321/202/321/200/320/276/320/271/320/272/320/270_/320/276/321/202/320/264/320/265/320/273/321/214/320/275/321/213/321/205_/320/272/320/276/320/274/320/260/320/275/320/264_/320/272/320/260/320/266/320/264/321/203_/320/272/320/276/320/274/320/260/320/275/320/273/320/264/321/203_/320/274/320/276/320/266/320/275/320/276_/320/275/320/260/321/201/321/202/321/200/320/260/320/270/320/262/320/260/321/202/321/214.png +0 -0
- package/screen//320/277/320/273/320/260/320/275/320/270/321/200/320/276/320/262/321/211/320/270/320/272_/320/274/320/276/320/266/320/275/320/276_/320/267/320/260/320/264/320/260/320/262/320/260/321/202/321/214_/320/264/320/265/320/271/321/201/321/202/320/262/320/270/321/217_/320/277/320/276_/320/262/321/200/320/265/320/274/320/265/320/275/320/270.png +0 -0
- package/.claude/agents/README.md +0 -469
- package/.claude/agents/auth-route-debugger.md +0 -118
- package/.claude/agents/auth-route-tester.md +0 -93
- package/.claude/agents/auto-error-resolver.md +0 -97
- package/.claude/agents/build-optimizer.md +0 -236
- package/.claude/agents/code-architect.md +0 -34
- package/.claude/agents/code-architecture-reviewer.md +0 -83
- package/.claude/agents/code-explorer.md +0 -51
- package/.claude/agents/code-refactor-master.md +0 -94
- package/.claude/agents/code-reviewer.md +0 -46
- package/.claude/agents/cost-optimizer.md +0 -134
- package/.claude/agents/deployment-orchestrator.md +0 -113
- package/.claude/agents/documentation-architect.md +0 -82
- package/.claude/agents/frontend-error-fixer.md +0 -77
- package/.claude/agents/iac-code-generator.md +0 -71
- package/.claude/agents/incident-responder.md +0 -346
- package/.claude/agents/infrastructure-architect.md +0 -31
- package/.claude/agents/kubernetes-specialist.md +0 -56
- package/.claude/agents/migration-planner.md +0 -181
- package/.claude/agents/network-architect.md +0 -196
- package/.claude/agents/plan-reviewer.md +0 -52
- package/.claude/agents/refactor-planner.md +0 -63
- package/.claude/agents/security-scanner.md +0 -102
- package/.claude/agents/web-research-specialist.md +0 -78
- package/.claude/commands/cost-analysis.md +0 -315
- package/.claude/commands/dev-docs-update.md +0 -55
- package/.claude/commands/dev-docs.md +0 -51
- package/.claude/commands/feature-dev.md +0 -125
- package/.claude/commands/incident-debug.md +0 -247
- package/.claude/commands/infra-plan.md +0 -81
- package/.claude/commands/migration-plan.md +0 -478
- package/.claude/commands/route-research-for-testing.md +0 -37
- package/.claude/commands/security-review.md +0 -66
- package/.claude/hooks/CONFIG.md +0 -448
- package/.claude/hooks/README.md +0 -163
- package/.claude/hooks/SKILL_ACTIVATION_COMPLETE.md +0 -226
- package/.claude/hooks/WINDOWS_HOOKS_README.md +0 -151
- package/.claude/hooks/add-skill-activation-banners.ts +0 -132
- package/.claude/hooks/comprehensive-skill-test.ts +0 -1315
- package/.claude/hooks/error-handling-reminder.sh +0 -12
- package/.claude/hooks/error-handling-reminder.ts +0 -222
- package/.claude/hooks/k8s-manifest-validator.sh +0 -56
- package/.claude/hooks/package-lock.json +0 -556
- package/.claude/hooks/package.json +0 -16
- package/.claude/hooks/post-tool-use-tracker.ps1 +0 -174
- package/.claude/hooks/post-tool-use-tracker.sh +0 -183
- package/.claude/hooks/security-policy-check.sh +0 -247
- package/.claude/hooks/skill-activation-prompt.ps1 +0 -10
- package/.claude/hooks/skill-activation-prompt.sh +0 -10
- package/.claude/hooks/skill-activation-prompt.ts +0 -141
- package/.claude/hooks/stop-build-check-enhanced.sh +0 -130
- package/.claude/hooks/terraform-validator.sh +0 -53
- package/.claude/hooks/test-input.json +0 -7
- package/.claude/hooks/test-skill-activation.ts +0 -427
- package/.claude/hooks/trigger-build-resolver.sh +0 -79
- package/.claude/hooks/tsc-check.sh +0 -173
- package/.claude/hooks/tsconfig.json +0 -19
- package/.claude/settings.json +0 -59
- package/.claude/settings.local.json +0 -67
- package/.claude/skills/README.md +0 -507
- package/.claude/skills/api-engineering/SKILL.md +0 -63
- package/.claude/skills/api-engineering/resources/api-versioning.md +0 -88
- package/.claude/skills/api-engineering/resources/graphql-patterns.md +0 -106
- package/.claude/skills/api-engineering/resources/rate-limiting.md +0 -118
- package/.claude/skills/api-engineering/resources/rest-api-design.md +0 -105
- package/.claude/skills/backend-dev-guidelines/SKILL.md +0 -306
- package/.claude/skills/backend-dev-guidelines/resources/architecture-overview.md +0 -451
- package/.claude/skills/backend-dev-guidelines/resources/async-and-errors.md +0 -307
- package/.claude/skills/backend-dev-guidelines/resources/complete-examples.md +0 -638
- package/.claude/skills/backend-dev-guidelines/resources/configuration.md +0 -275
- package/.claude/skills/backend-dev-guidelines/resources/database-patterns.md +0 -224
- package/.claude/skills/backend-dev-guidelines/resources/middleware-guide.md +0 -213
- package/.claude/skills/backend-dev-guidelines/resources/routing-and-controllers.md +0 -756
- package/.claude/skills/backend-dev-guidelines/resources/sentry-and-monitoring.md +0 -336
- package/.claude/skills/backend-dev-guidelines/resources/services-and-repositories.md +0 -789
- package/.claude/skills/backend-dev-guidelines/resources/testing-guide.md +0 -235
- package/.claude/skills/backend-dev-guidelines/resources/validation-patterns.md +0 -754
- package/.claude/skills/budget-and-cost-management/SKILL.md +0 -850
- package/.claude/skills/build-engineering/SKILL.md +0 -431
- package/.claude/skills/build-engineering/resources/artifact-repositories.md +0 -72
- package/.claude/skills/build-engineering/resources/build-caching.md +0 -96
- package/.claude/skills/build-engineering/resources/build-pipelines.md +0 -105
- package/.claude/skills/build-engineering/resources/build-security.md +0 -95
- package/.claude/skills/build-engineering/resources/build-systems.md +0 -389
- package/.claude/skills/build-engineering/resources/compilation-optimization.md +0 -201
- package/.claude/skills/build-engineering/resources/dependency-management.md +0 -73
- package/.claude/skills/build-engineering/resources/monorepo-builds.md +0 -110
- package/.claude/skills/build-engineering/resources/performance-optimization.md +0 -113
- package/.claude/skills/build-engineering/resources/reproducible-builds.md +0 -82
- package/.claude/skills/cloud-engineering/SKILL.md +0 -675
- package/.claude/skills/cloud-engineering/resources/aws-patterns.md +0 -742
- package/.claude/skills/cloud-engineering/resources/azure-patterns.md +0 -714
- package/.claude/skills/cloud-engineering/resources/cleared-cloud-environments.md +0 -987
- package/.claude/skills/cloud-engineering/resources/cloud-cost-optimization.md +0 -757
- package/.claude/skills/cloud-engineering/resources/cloud-networking.md +0 -1058
- package/.claude/skills/cloud-engineering/resources/cloud-security-tools.md +0 -1530
- package/.claude/skills/cloud-engineering/resources/cloud-security.md +0 -990
- package/.claude/skills/cloud-engineering/resources/gcp-patterns.md +0 -758
- package/.claude/skills/cloud-engineering/resources/migration-strategies.md +0 -820
- package/.claude/skills/cloud-engineering/resources/multi-cloud-strategies.md +0 -670
- package/.claude/skills/cloud-engineering/resources/oci-patterns.md +0 -1198
- package/.claude/skills/cloud-engineering/resources/serverless-patterns.md +0 -795
- package/.claude/skills/cloud-engineering/resources/well-architected-frameworks.md +0 -966
- package/.claude/skills/cybersecurity/SKILL.md +0 -409
- package/.claude/skills/cybersecurity/resources/security-architecture.md +0 -266
- package/.claude/skills/database-engineering/SKILL.md +0 -61
- package/.claude/skills/database-engineering/resources/backup-and-recovery.md +0 -72
- package/.claude/skills/database-engineering/resources/database-replication.md +0 -63
- package/.claude/skills/database-engineering/resources/postgresql-fundamentals.md +0 -70
- package/.claude/skills/database-engineering/resources/query-optimization.md +0 -68
- package/.claude/skills/devsecops/SKILL.md +0 -374
- package/.claude/skills/devsecops/resources/ci-cd-security.md +0 -204
- package/.claude/skills/devsecops/resources/compliance-automation.md +0 -530
- package/.claude/skills/devsecops/resources/compliance-frameworks.md +0 -2322
- package/.claude/skills/devsecops/resources/container-security.md +0 -915
- package/.claude/skills/devsecops/resources/cspm-integration.md +0 -1440
- package/.claude/skills/devsecops/resources/policy-enforcement.md +0 -619
- package/.claude/skills/devsecops/resources/secrets-management.md +0 -755
- package/.claude/skills/devsecops/resources/security-monitoring.md +0 -146
- package/.claude/skills/devsecops/resources/security-scanning.md +0 -887
- package/.claude/skills/devsecops/resources/security-testing.md +0 -203
- package/.claude/skills/devsecops/resources/supply-chain-security.md +0 -518
- package/.claude/skills/devsecops/resources/vulnerability-management.md +0 -481
- package/.claude/skills/devsecops/resources/zero-trust-architecture.md +0 -177
- package/.claude/skills/documentation-as-code/SKILL.md +0 -323
- package/.claude/skills/documentation-as-code/resources/api-documentation.md +0 -90
- package/.claude/skills/documentation-as-code/resources/changelog-management.md +0 -79
- package/.claude/skills/documentation-as-code/resources/diagram-generation.md +0 -44
- package/.claude/skills/documentation-as-code/resources/docs-as-code-workflow.md +0 -99
- package/.claude/skills/documentation-as-code/resources/documentation-automation.md +0 -68
- package/.claude/skills/documentation-as-code/resources/documentation-sites.md +0 -79
- package/.claude/skills/documentation-as-code/resources/markdown-best-practices.md +0 -162
- package/.claude/skills/documentation-as-code/resources/openapi-specification.md +0 -77
- package/.claude/skills/documentation-as-code/resources/readme-engineering.md +0 -60
- package/.claude/skills/documentation-as-code/resources/technical-writing-guide.md +0 -202
- package/.claude/skills/engineering-management/SKILL.md +0 -356
- package/.claude/skills/engineering-management/resources/career-ladders.md +0 -609
- package/.claude/skills/engineering-management/resources/hiring-and-assessment.md +0 -555
- package/.claude/skills/engineering-management/resources/one-on-one-guides.md +0 -609
- package/.claude/skills/engineering-management/resources/resource-planning.md +0 -557
- package/.claude/skills/engineering-management/resources/team-organization-patterns.md +0 -491
- package/.claude/skills/engineering-management/resources/technical-interviews.md +0 -474
- package/.claude/skills/engineering-operations-management/SKILL.md +0 -817
- package/.claude/skills/error-tracking/SKILL.md +0 -379
- package/.claude/skills/frontend-design/SKILL.md +0 -42
- package/.claude/skills/frontend-dev-guidelines/SKILL.md +0 -403
- package/.claude/skills/frontend-dev-guidelines/resources/common-patterns.md +0 -331
- package/.claude/skills/frontend-dev-guidelines/resources/complete-examples.md +0 -872
- package/.claude/skills/frontend-dev-guidelines/resources/component-patterns.md +0 -502
- package/.claude/skills/frontend-dev-guidelines/resources/data-fetching.md +0 -767
- package/.claude/skills/frontend-dev-guidelines/resources/file-organization.md +0 -502
- package/.claude/skills/frontend-dev-guidelines/resources/loading-and-error-states.md +0 -501
- package/.claude/skills/frontend-dev-guidelines/resources/performance.md +0 -406
- package/.claude/skills/frontend-dev-guidelines/resources/routing-guide.md +0 -364
- package/.claude/skills/frontend-dev-guidelines/resources/styling-guide.md +0 -428
- package/.claude/skills/frontend-dev-guidelines/resources/typescript-standards.md +0 -418
- package/.claude/skills/general-it-engineering/SKILL.md +0 -393
- package/.claude/skills/general-it-engineering/resources/asset-management.md +0 -712
- package/.claude/skills/general-it-engineering/resources/automation-orchestration.md +0 -817
- package/.claude/skills/general-it-engineering/resources/business-continuity.md +0 -786
- package/.claude/skills/general-it-engineering/resources/change-management.md +0 -715
- package/.claude/skills/general-it-engineering/resources/enterprise-monitoring.md +0 -729
- package/.claude/skills/general-it-engineering/resources/help-desk-operations.md +0 -738
- package/.claude/skills/general-it-engineering/resources/incident-service-management.md +0 -834
- package/.claude/skills/general-it-engineering/resources/it-governance.md +0 -753
- package/.claude/skills/general-it-engineering/resources/itil-framework.md +0 -503
- package/.claude/skills/general-it-engineering/resources/service-management.md +0 -669
- package/.claude/skills/infrastructure-architecture/SKILL.md +0 -328
- package/.claude/skills/infrastructure-architecture/resources/architecture-decision-records.md +0 -505
- package/.claude/skills/infrastructure-architecture/resources/architecture-patterns.md +0 -528
- package/.claude/skills/infrastructure-architecture/resources/capacity-planning.md +0 -453
- package/.claude/skills/infrastructure-architecture/resources/cleared-environment-architecture.md +0 -773
- package/.claude/skills/infrastructure-architecture/resources/cost-architecture.md +0 -499
- package/.claude/skills/infrastructure-architecture/resources/data-architecture.md +0 -501
- package/.claude/skills/infrastructure-architecture/resources/disaster-recovery.md +0 -535
- package/.claude/skills/infrastructure-architecture/resources/migration-architecture.md +0 -512
- package/.claude/skills/infrastructure-architecture/resources/multi-region-design.md +0 -608
- package/.claude/skills/infrastructure-architecture/resources/reference-architectures.md +0 -562
- package/.claude/skills/infrastructure-architecture/resources/security-architecture.md +0 -538
- package/.claude/skills/infrastructure-architecture/resources/system-design-principles.md +0 -489
- package/.claude/skills/infrastructure-architecture/resources/workload-classification.md +0 -1000
- package/.claude/skills/infrastructure-strategy/SKILL.md +0 -924
- package/.claude/skills/network-engineering/SKILL.md +0 -385
- package/.claude/skills/network-engineering/resources/dns-management.md +0 -738
- package/.claude/skills/network-engineering/resources/load-balancing.md +0 -820
- package/.claude/skills/network-engineering/resources/network-architecture.md +0 -546
- package/.claude/skills/network-engineering/resources/network-security.md +0 -921
- package/.claude/skills/network-engineering/resources/network-troubleshooting.md +0 -749
- package/.claude/skills/network-engineering/resources/routing-switching.md +0 -373
- package/.claude/skills/network-engineering/resources/sdn-networking.md +0 -695
- package/.claude/skills/network-engineering/resources/service-mesh-networking.md +0 -777
- package/.claude/skills/network-engineering/resources/tcp-ip-protocols.md +0 -444
- package/.claude/skills/network-engineering/resources/vpn-connectivity.md +0 -672
- package/.claude/skills/node-development/SKILL.md +0 -317
- package/.claude/skills/observability-engineering/SKILL.md +0 -101
- package/.claude/skills/observability-engineering/resources/apm-tools.md +0 -97
- package/.claude/skills/observability-engineering/resources/correlation-strategies.md +0 -87
- package/.claude/skills/observability-engineering/resources/distributed-tracing.md +0 -98
- package/.claude/skills/observability-engineering/resources/logs-aggregation.md +0 -118
- package/.claude/skills/observability-engineering/resources/observability-cost-optimization.md +0 -141
- package/.claude/skills/observability-engineering/resources/opentelemetry.md +0 -110
- package/.claude/skills/platform-engineering/SKILL.md +0 -555
- package/.claude/skills/platform-engineering/resources/architecture-overview.md +0 -600
- package/.claude/skills/platform-engineering/resources/container-orchestration.md +0 -916
- package/.claude/skills/platform-engineering/resources/cost-optimization.md +0 -634
- package/.claude/skills/platform-engineering/resources/developer-platforms.md +0 -670
- package/.claude/skills/platform-engineering/resources/gitops-automation.md +0 -650
- package/.claude/skills/platform-engineering/resources/infrastructure-as-code.md +0 -778
- package/.claude/skills/platform-engineering/resources/infrastructure-standards.md +0 -708
- package/.claude/skills/platform-engineering/resources/multi-tenancy.md +0 -602
- package/.claude/skills/platform-engineering/resources/platform-security.md +0 -711
- package/.claude/skills/platform-engineering/resources/resource-management.md +0 -592
- package/.claude/skills/platform-engineering/resources/service-mesh.md +0 -628
- package/.claude/skills/release-engineering/SKILL.md +0 -393
- package/.claude/skills/release-engineering/resources/artifact-management.md +0 -108
- package/.claude/skills/release-engineering/resources/build-optimization.md +0 -84
- package/.claude/skills/release-engineering/resources/ci-cd-pipelines.md +0 -411
- package/.claude/skills/release-engineering/resources/deployment-strategies.md +0 -197
- package/.claude/skills/release-engineering/resources/pipeline-security.md +0 -62
- package/.claude/skills/release-engineering/resources/progressive-delivery.md +0 -83
- package/.claude/skills/release-engineering/resources/release-automation.md +0 -68
- package/.claude/skills/release-engineering/resources/release-orchestration.md +0 -77
- package/.claude/skills/release-engineering/resources/rollback-strategies.md +0 -66
- package/.claude/skills/release-engineering/resources/versioning-strategies.md +0 -59
- package/.claude/skills/route-tester/SKILL.md +0 -392
- package/.claude/skills/skill-developer/ADVANCED.md +0 -197
- package/.claude/skills/skill-developer/HOOK_MECHANISMS.md +0 -306
- package/.claude/skills/skill-developer/PATTERNS_LIBRARY.md +0 -152
- package/.claude/skills/skill-developer/SKILL.md +0 -430
- package/.claude/skills/skill-developer/SKILL_RULES_REFERENCE.md +0 -315
- package/.claude/skills/skill-developer/TRIGGER_TYPES.md +0 -305
- package/.claude/skills/skill-developer/TROUBLESHOOTING.md +0 -514
- package/.claude/skills/skill-rules.json +0 -2989
- package/.claude/skills/sre/SKILL.md +0 -464
- package/.claude/skills/sre/resources/alerting-best-practices.md +0 -282
- package/.claude/skills/sre/resources/capacity-planning.md +0 -226
- package/.claude/skills/sre/resources/chaos-engineering.md +0 -193
- package/.claude/skills/sre/resources/disaster-recovery.md +0 -232
- package/.claude/skills/sre/resources/incident-management.md +0 -436
- package/.claude/skills/sre/resources/observability-stack.md +0 -240
- package/.claude/skills/sre/resources/on-call-runbooks.md +0 -167
- package/.claude/skills/sre/resources/performance-optimization.md +0 -108
- package/.claude/skills/sre/resources/reliability-patterns.md +0 -183
- package/.claude/skills/sre/resources/slo-sli-sla.md +0 -464
- package/.claude/skills/sre/resources/toil-reduction.md +0 -145
- package/.claude/skills/systems-engineering/SKILL.md +0 -648
- package/.claude/skills/systems-engineering/resources/automation-patterns.md +0 -771
- package/.claude/skills/systems-engineering/resources/configuration-management.md +0 -998
- package/.claude/skills/systems-engineering/resources/linux-administration.md +0 -672
- package/.claude/skills/systems-engineering/resources/networking-fundamentals.md +0 -982
- package/.claude/skills/systems-engineering/resources/performance-tuning.md +0 -871
- package/.claude/skills/systems-engineering/resources/powershell-scripting.md +0 -482
- package/.claude/skills/systems-engineering/resources/security-hardening.md +0 -739
- package/.claude/skills/systems-engineering/resources/shell-scripting.md +0 -915
- package/.claude/skills/systems-engineering/resources/storage-management.md +0 -628
- package/.claude/skills/systems-engineering/resources/system-monitoring.md +0 -787
- package/.claude/skills/systems-engineering/resources/troubleshooting-guide.md +0 -753
- package/.claude/skills/systems-engineering/resources/windows-administration.md +0 -738
- package/.claude/skills/technical-leadership/SKILL.md +0 -728
- package/backend/docs/SECRETS_DOCUMENTATION.md +0 -327
- package/frontend/dist/assets/index-BC-NbKXi.css +0 -32
- package/frontend/dist/assets/index-DqJXZMHY.js +0 -11266
|
@@ -1,754 +0,0 @@
|
|
|
1
|
-
# Validation Patterns - Input Validation with Zod
|
|
2
|
-
|
|
3
|
-
Complete guide to input validation using Zod schemas for type-safe validation.
|
|
4
|
-
|
|
5
|
-
## Table of Contents
|
|
6
|
-
|
|
7
|
-
- [Why Zod?](#why-zod)
|
|
8
|
-
- [Basic Zod Patterns](#basic-zod-patterns)
|
|
9
|
-
- [Schema Examples from Codebase](#schema-examples-from-codebase)
|
|
10
|
-
- [Route-Level Validation](#route-level-validation)
|
|
11
|
-
- [Controller Validation](#controller-validation)
|
|
12
|
-
- [DTO Pattern](#dto-pattern)
|
|
13
|
-
- [Error Handling](#error-handling)
|
|
14
|
-
- [Advanced Patterns](#advanced-patterns)
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## Why Zod?
|
|
19
|
-
|
|
20
|
-
### Benefits Over Joi/Other Libraries
|
|
21
|
-
|
|
22
|
-
**Type Safety:**
|
|
23
|
-
- ✅ Full TypeScript inference
|
|
24
|
-
- ✅ Runtime + compile-time validation
|
|
25
|
-
- ✅ Automatic type generation
|
|
26
|
-
|
|
27
|
-
**Developer Experience:**
|
|
28
|
-
- ✅ Intuitive API
|
|
29
|
-
- ✅ Composable schemas
|
|
30
|
-
- ✅ Excellent error messages
|
|
31
|
-
|
|
32
|
-
**Performance:**
|
|
33
|
-
- ✅ Fast validation
|
|
34
|
-
- ✅ Small bundle size
|
|
35
|
-
- ✅ Tree-shakeable
|
|
36
|
-
|
|
37
|
-
### Migration from Joi
|
|
38
|
-
|
|
39
|
-
Modern validation uses Zod instead of Joi:
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
// ❌ OLD - Joi (being phased out)
|
|
43
|
-
const schema = Joi.object({
|
|
44
|
-
email: Joi.string().email().required(),
|
|
45
|
-
name: Joi.string().min(3).required(),
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
// ✅ NEW - Zod (preferred)
|
|
49
|
-
const schema = z.object({
|
|
50
|
-
email: z.string().email(),
|
|
51
|
-
name: z.string().min(3),
|
|
52
|
-
});
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## Basic Zod Patterns
|
|
58
|
-
|
|
59
|
-
### Primitive Types
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
import { z } from 'zod';
|
|
63
|
-
|
|
64
|
-
// Strings
|
|
65
|
-
const nameSchema = z.string();
|
|
66
|
-
const emailSchema = z.string().email();
|
|
67
|
-
const urlSchema = z.string().url();
|
|
68
|
-
const uuidSchema = z.string().uuid();
|
|
69
|
-
const minLengthSchema = z.string().min(3);
|
|
70
|
-
const maxLengthSchema = z.string().max(100);
|
|
71
|
-
|
|
72
|
-
// Numbers
|
|
73
|
-
const ageSchema = z.number().int().positive();
|
|
74
|
-
const priceSchema = z.number().positive();
|
|
75
|
-
const rangeSchema = z.number().min(0).max(100);
|
|
76
|
-
|
|
77
|
-
// Booleans
|
|
78
|
-
const activeSchema = z.boolean();
|
|
79
|
-
|
|
80
|
-
// Dates
|
|
81
|
-
const dateSchema = z.string().datetime(); // ISO 8601 string
|
|
82
|
-
const nativeDateSchema = z.date(); // Native Date object
|
|
83
|
-
|
|
84
|
-
// Enums
|
|
85
|
-
const roleSchema = z.enum(['admin', 'operations', 'user']);
|
|
86
|
-
const statusSchema = z.enum(['PENDING', 'APPROVED', 'REJECTED']);
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Objects
|
|
90
|
-
|
|
91
|
-
```typescript
|
|
92
|
-
// Simple object
|
|
93
|
-
const userSchema = z.object({
|
|
94
|
-
email: z.string().email(),
|
|
95
|
-
name: z.string(),
|
|
96
|
-
age: z.number().int().positive(),
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
// Nested objects
|
|
100
|
-
const addressSchema = z.object({
|
|
101
|
-
street: z.string(),
|
|
102
|
-
city: z.string(),
|
|
103
|
-
zipCode: z.string().regex(/^\d{5}$/),
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const userWithAddressSchema = z.object({
|
|
107
|
-
name: z.string(),
|
|
108
|
-
address: addressSchema,
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Optional fields
|
|
112
|
-
const userSchema = z.object({
|
|
113
|
-
name: z.string(),
|
|
114
|
-
email: z.string().email().optional(),
|
|
115
|
-
phone: z.string().optional(),
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Nullable fields
|
|
119
|
-
const userSchema = z.object({
|
|
120
|
-
name: z.string(),
|
|
121
|
-
middleName: z.string().nullable(),
|
|
122
|
-
});
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### Arrays
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
// Array of primitives
|
|
129
|
-
const rolesSchema = z.array(z.string());
|
|
130
|
-
const numbersSchema = z.array(z.number());
|
|
131
|
-
|
|
132
|
-
// Array of objects
|
|
133
|
-
const usersSchema = z.array(
|
|
134
|
-
z.object({
|
|
135
|
-
id: z.string(),
|
|
136
|
-
name: z.string(),
|
|
137
|
-
})
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
// Array with constraints
|
|
141
|
-
const tagsSchema = z.array(z.string()).min(1).max(10);
|
|
142
|
-
const nonEmptyArray = z.array(z.string()).nonempty();
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
---
|
|
146
|
-
|
|
147
|
-
## Schema Examples from Codebase
|
|
148
|
-
|
|
149
|
-
### Form Validation Schemas
|
|
150
|
-
|
|
151
|
-
**File:** `/form/src/helpers/zodSchemas.ts`
|
|
152
|
-
|
|
153
|
-
```typescript
|
|
154
|
-
import { z } from 'zod';
|
|
155
|
-
|
|
156
|
-
// Question types enum
|
|
157
|
-
export const questionTypeSchema = z.enum([
|
|
158
|
-
'input',
|
|
159
|
-
'textbox',
|
|
160
|
-
'editor',
|
|
161
|
-
'dropdown',
|
|
162
|
-
'autocomplete',
|
|
163
|
-
'checkbox',
|
|
164
|
-
'radio',
|
|
165
|
-
'upload',
|
|
166
|
-
]);
|
|
167
|
-
|
|
168
|
-
// Upload types
|
|
169
|
-
export const uploadTypeSchema = z.array(
|
|
170
|
-
z.enum(['pdf', 'image', 'excel', 'video', 'powerpoint', 'word']).nullable()
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
// Input types
|
|
174
|
-
export const inputTypeSchema = z
|
|
175
|
-
.enum(['date', 'number', 'input', 'currency'])
|
|
176
|
-
.nullable();
|
|
177
|
-
|
|
178
|
-
// Question option
|
|
179
|
-
export const questionOptionSchema = z.object({
|
|
180
|
-
id: z.number().int().positive().optional(),
|
|
181
|
-
controlTag: z.string().max(150).nullable().optional(),
|
|
182
|
-
label: z.string().max(100).nullable().optional(),
|
|
183
|
-
order: z.number().int().min(0).default(0),
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
// Question schema
|
|
187
|
-
export const questionSchema = z.object({
|
|
188
|
-
id: z.number().int().positive().optional(),
|
|
189
|
-
formID: z.number().int().positive(),
|
|
190
|
-
sectionID: z.number().int().positive().optional(),
|
|
191
|
-
options: z.array(questionOptionSchema).optional(),
|
|
192
|
-
label: z.string().max(500),
|
|
193
|
-
description: z.string().max(5000).optional(),
|
|
194
|
-
type: questionTypeSchema,
|
|
195
|
-
uploadTypes: uploadTypeSchema.optional(),
|
|
196
|
-
inputType: inputTypeSchema.optional(),
|
|
197
|
-
tags: z.array(z.string().max(150)).optional(),
|
|
198
|
-
required: z.boolean(),
|
|
199
|
-
isStandard: z.boolean().optional(),
|
|
200
|
-
deprecatedKey: z.string().nullable().optional(),
|
|
201
|
-
maxLength: z.number().int().positive().nullable().optional(),
|
|
202
|
-
isOptionsSorted: z.boolean().optional(),
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
// Form section schema
|
|
206
|
-
export const formSectionSchema = z.object({
|
|
207
|
-
id: z.number().int().positive(),
|
|
208
|
-
formID: z.number().int().positive(),
|
|
209
|
-
questions: z.array(questionSchema).optional(),
|
|
210
|
-
label: z.string().max(500),
|
|
211
|
-
description: z.string().max(5000).optional(),
|
|
212
|
-
isStandard: z.boolean(),
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
// Create form schema
|
|
216
|
-
export const createFormSchema = z.object({
|
|
217
|
-
id: z.number().int().positive(),
|
|
218
|
-
label: z.string().max(150),
|
|
219
|
-
description: z.string().max(6000).nullable().optional(),
|
|
220
|
-
isPhase: z.boolean().optional(),
|
|
221
|
-
username: z.string(),
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
// Update order schema
|
|
225
|
-
export const updateOrderSchema = z.object({
|
|
226
|
-
source: z.object({
|
|
227
|
-
index: z.number().int().min(0),
|
|
228
|
-
sectionID: z.number().int().min(0),
|
|
229
|
-
}),
|
|
230
|
-
destination: z.object({
|
|
231
|
-
index: z.number().int().min(0),
|
|
232
|
-
sectionID: z.number().int().min(0),
|
|
233
|
-
}),
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
// Controller-specific validation schemas
|
|
237
|
-
export const createQuestionValidationSchema = z.object({
|
|
238
|
-
formID: z.number().int().positive(),
|
|
239
|
-
sectionID: z.number().int().positive(),
|
|
240
|
-
question: questionSchema,
|
|
241
|
-
index: z.number().int().min(0).nullable().optional(),
|
|
242
|
-
username: z.string(),
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
export const updateQuestionValidationSchema = z.object({
|
|
246
|
-
questionID: z.number().int().positive(),
|
|
247
|
-
username: z.string(),
|
|
248
|
-
question: questionSchema,
|
|
249
|
-
});
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
### Proxy Relationship Schema
|
|
253
|
-
|
|
254
|
-
```typescript
|
|
255
|
-
// Proxy relationship validation
|
|
256
|
-
const createProxySchema = z.object({
|
|
257
|
-
originalUserID: z.string().min(1),
|
|
258
|
-
proxyUserID: z.string().min(1),
|
|
259
|
-
startsAt: z.string().datetime(),
|
|
260
|
-
expiresAt: z.string().datetime(),
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
// With custom validation
|
|
264
|
-
const createProxySchemaWithValidation = createProxySchema.refine(
|
|
265
|
-
(data) => new Date(data.expiresAt) > new Date(data.startsAt),
|
|
266
|
-
{
|
|
267
|
-
message: 'expiresAt must be after startsAt',
|
|
268
|
-
path: ['expiresAt'],
|
|
269
|
-
}
|
|
270
|
-
);
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
### Workflow Validation
|
|
274
|
-
|
|
275
|
-
```typescript
|
|
276
|
-
// Workflow start schema
|
|
277
|
-
const startWorkflowSchema = z.object({
|
|
278
|
-
workflowCode: z.string().min(1),
|
|
279
|
-
entityType: z.enum(['Post', 'User', 'Comment']),
|
|
280
|
-
entityID: z.number().int().positive(),
|
|
281
|
-
dryRun: z.boolean().optional().default(false),
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
// Workflow step completion schema
|
|
285
|
-
const completeStepSchema = z.object({
|
|
286
|
-
stepInstanceID: z.number().int().positive(),
|
|
287
|
-
answers: z.record(z.string(), z.any()),
|
|
288
|
-
dryRun: z.boolean().optional().default(false),
|
|
289
|
-
});
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
---
|
|
293
|
-
|
|
294
|
-
## Route-Level Validation
|
|
295
|
-
|
|
296
|
-
### Pattern 1: Inline Validation
|
|
297
|
-
|
|
298
|
-
```typescript
|
|
299
|
-
// routes/proxyRoutes.ts
|
|
300
|
-
import { z } from 'zod';
|
|
301
|
-
|
|
302
|
-
const createProxySchema = z.object({
|
|
303
|
-
originalUserID: z.string().min(1),
|
|
304
|
-
proxyUserID: z.string().min(1),
|
|
305
|
-
startsAt: z.string().datetime(),
|
|
306
|
-
expiresAt: z.string().datetime(),
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
router.post(
|
|
310
|
-
'/',
|
|
311
|
-
SSOMiddlewareClient.verifyLoginStatus,
|
|
312
|
-
async (req, res) => {
|
|
313
|
-
try {
|
|
314
|
-
// Validate at route level
|
|
315
|
-
const validated = createProxySchema.parse(req.body);
|
|
316
|
-
|
|
317
|
-
// Delegate to service
|
|
318
|
-
const proxy = await proxyService.createProxyRelationship(validated);
|
|
319
|
-
|
|
320
|
-
res.status(201).json({ success: true, data: proxy });
|
|
321
|
-
} catch (error) {
|
|
322
|
-
if (error instanceof z.ZodError) {
|
|
323
|
-
return res.status(400).json({
|
|
324
|
-
success: false,
|
|
325
|
-
error: {
|
|
326
|
-
message: 'Validation failed',
|
|
327
|
-
details: error.errors,
|
|
328
|
-
},
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
handler.handleException(res, error);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
);
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
**Pros:**
|
|
338
|
-
- Quick and simple
|
|
339
|
-
- Good for simple routes
|
|
340
|
-
|
|
341
|
-
**Cons:**
|
|
342
|
-
- Validation logic in routes
|
|
343
|
-
- Harder to test
|
|
344
|
-
- Not reusable
|
|
345
|
-
|
|
346
|
-
---
|
|
347
|
-
|
|
348
|
-
## Controller Validation
|
|
349
|
-
|
|
350
|
-
### Pattern 2: Controller Validation (Recommended)
|
|
351
|
-
|
|
352
|
-
```typescript
|
|
353
|
-
// validators/userSchemas.ts
|
|
354
|
-
import { z } from 'zod';
|
|
355
|
-
|
|
356
|
-
export const createUserSchema = z.object({
|
|
357
|
-
email: z.string().email(),
|
|
358
|
-
name: z.string().min(2).max(100),
|
|
359
|
-
roles: z.array(z.enum(['admin', 'operations', 'user'])),
|
|
360
|
-
isActive: z.boolean().default(true),
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
export const updateUserSchema = z.object({
|
|
364
|
-
email: z.string().email().optional(),
|
|
365
|
-
name: z.string().min(2).max(100).optional(),
|
|
366
|
-
roles: z.array(z.enum(['admin', 'operations', 'user'])).optional(),
|
|
367
|
-
isActive: z.boolean().optional(),
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
export type CreateUserDTO = z.infer<typeof createUserSchema>;
|
|
371
|
-
export type UpdateUserDTO = z.infer<typeof updateUserSchema>;
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
```typescript
|
|
375
|
-
// controllers/UserController.ts
|
|
376
|
-
import { Request, Response } from 'express';
|
|
377
|
-
import { BaseController } from './BaseController';
|
|
378
|
-
import { UserService } from '../services/userService';
|
|
379
|
-
import { createUserSchema, updateUserSchema } from '../validators/userSchemas';
|
|
380
|
-
import { z } from 'zod';
|
|
381
|
-
|
|
382
|
-
export class UserController extends BaseController {
|
|
383
|
-
private userService: UserService;
|
|
384
|
-
|
|
385
|
-
constructor() {
|
|
386
|
-
super();
|
|
387
|
-
this.userService = new UserService();
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
async createUser(req: Request, res: Response): Promise<void> {
|
|
391
|
-
try {
|
|
392
|
-
// Validate input
|
|
393
|
-
const validated = createUserSchema.parse(req.body);
|
|
394
|
-
|
|
395
|
-
// Call service
|
|
396
|
-
const user = await this.userService.createUser(validated);
|
|
397
|
-
|
|
398
|
-
this.handleSuccess(res, user, 'User created successfully', 201);
|
|
399
|
-
} catch (error) {
|
|
400
|
-
if (error instanceof z.ZodError) {
|
|
401
|
-
// Handle validation errors with 400 status
|
|
402
|
-
return this.handleError(error, res, 'createUser', 400);
|
|
403
|
-
}
|
|
404
|
-
this.handleError(error, res, 'createUser');
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
async updateUser(req: Request, res: Response): Promise<void> {
|
|
409
|
-
try {
|
|
410
|
-
// Validate params and body
|
|
411
|
-
const userId = req.params.id;
|
|
412
|
-
const validated = updateUserSchema.parse(req.body);
|
|
413
|
-
|
|
414
|
-
const user = await this.userService.updateUser(userId, validated);
|
|
415
|
-
|
|
416
|
-
this.handleSuccess(res, user, 'User updated successfully');
|
|
417
|
-
} catch (error) {
|
|
418
|
-
if (error instanceof z.ZodError) {
|
|
419
|
-
return this.handleError(error, res, 'updateUser', 400);
|
|
420
|
-
}
|
|
421
|
-
this.handleError(error, res, 'updateUser');
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
**Pros:**
|
|
428
|
-
- Clean separation
|
|
429
|
-
- Reusable schemas
|
|
430
|
-
- Easy to test
|
|
431
|
-
- Type-safe DTOs
|
|
432
|
-
|
|
433
|
-
**Cons:**
|
|
434
|
-
- More files to manage
|
|
435
|
-
|
|
436
|
-
---
|
|
437
|
-
|
|
438
|
-
## DTO Pattern
|
|
439
|
-
|
|
440
|
-
### Type Inference from Schemas
|
|
441
|
-
|
|
442
|
-
```typescript
|
|
443
|
-
import { z } from 'zod';
|
|
444
|
-
|
|
445
|
-
// Define schema
|
|
446
|
-
const createUserSchema = z.object({
|
|
447
|
-
email: z.string().email(),
|
|
448
|
-
name: z.string(),
|
|
449
|
-
age: z.number().int().positive(),
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
// Infer TypeScript type from schema
|
|
453
|
-
type CreateUserDTO = z.infer<typeof createUserSchema>;
|
|
454
|
-
|
|
455
|
-
// Equivalent to:
|
|
456
|
-
// type CreateUserDTO = {
|
|
457
|
-
// email: string;
|
|
458
|
-
// name: string;
|
|
459
|
-
// age: number;
|
|
460
|
-
// }
|
|
461
|
-
|
|
462
|
-
// Use in service
|
|
463
|
-
class UserService {
|
|
464
|
-
async createUser(data: CreateUserDTO): Promise<User> {
|
|
465
|
-
// data is fully typed!
|
|
466
|
-
console.log(data.email); // ✅ TypeScript knows this exists
|
|
467
|
-
console.log(data.invalid); // ❌ TypeScript error!
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
### Input vs Output Types
|
|
473
|
-
|
|
474
|
-
```typescript
|
|
475
|
-
// Input schema (what API receives)
|
|
476
|
-
const createUserInputSchema = z.object({
|
|
477
|
-
email: z.string().email(),
|
|
478
|
-
name: z.string(),
|
|
479
|
-
password: z.string().min(8),
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
// Output schema (what API returns)
|
|
483
|
-
const userOutputSchema = z.object({
|
|
484
|
-
id: z.string().uuid(),
|
|
485
|
-
email: z.string().email(),
|
|
486
|
-
name: z.string(),
|
|
487
|
-
createdAt: z.string().datetime(),
|
|
488
|
-
// password excluded!
|
|
489
|
-
});
|
|
490
|
-
|
|
491
|
-
type CreateUserInput = z.infer<typeof createUserInputSchema>;
|
|
492
|
-
type UserOutput = z.infer<typeof userOutputSchema>;
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
---
|
|
496
|
-
|
|
497
|
-
## Error Handling
|
|
498
|
-
|
|
499
|
-
### Zod Error Format
|
|
500
|
-
|
|
501
|
-
```typescript
|
|
502
|
-
try {
|
|
503
|
-
const validated = schema.parse(data);
|
|
504
|
-
} catch (error) {
|
|
505
|
-
if (error instanceof z.ZodError) {
|
|
506
|
-
console.log(error.errors);
|
|
507
|
-
// [
|
|
508
|
-
// {
|
|
509
|
-
// code: 'invalid_type',
|
|
510
|
-
// expected: 'string',
|
|
511
|
-
// received: 'number',
|
|
512
|
-
// path: ['email'],
|
|
513
|
-
// message: 'Expected string, received number'
|
|
514
|
-
// }
|
|
515
|
-
// ]
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
### Custom Error Messages
|
|
521
|
-
|
|
522
|
-
```typescript
|
|
523
|
-
const userSchema = z.object({
|
|
524
|
-
email: z.string().email({ message: 'Please provide a valid email address' }),
|
|
525
|
-
name: z.string().min(2, { message: 'Name must be at least 2 characters' }),
|
|
526
|
-
age: z.number().int().positive({ message: 'Age must be a positive number' }),
|
|
527
|
-
});
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
### Formatted Error Response
|
|
531
|
-
|
|
532
|
-
```typescript
|
|
533
|
-
// Helper function to format Zod errors
|
|
534
|
-
function formatZodError(error: z.ZodError) {
|
|
535
|
-
return {
|
|
536
|
-
message: 'Validation failed',
|
|
537
|
-
errors: error.errors.map((err) => ({
|
|
538
|
-
field: err.path.join('.'),
|
|
539
|
-
message: err.message,
|
|
540
|
-
code: err.code,
|
|
541
|
-
})),
|
|
542
|
-
};
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
// In controller
|
|
546
|
-
catch (error) {
|
|
547
|
-
if (error instanceof z.ZodError) {
|
|
548
|
-
return res.status(400).json({
|
|
549
|
-
success: false,
|
|
550
|
-
error: formatZodError(error),
|
|
551
|
-
});
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
// Response example:
|
|
556
|
-
// {
|
|
557
|
-
// "success": false,
|
|
558
|
-
// "error": {
|
|
559
|
-
// "message": "Validation failed",
|
|
560
|
-
// "errors": [
|
|
561
|
-
// {
|
|
562
|
-
// "field": "email",
|
|
563
|
-
// "message": "Invalid email",
|
|
564
|
-
// "code": "invalid_string"
|
|
565
|
-
// }
|
|
566
|
-
// ]
|
|
567
|
-
// }
|
|
568
|
-
// }
|
|
569
|
-
```
|
|
570
|
-
|
|
571
|
-
---
|
|
572
|
-
|
|
573
|
-
## Advanced Patterns
|
|
574
|
-
|
|
575
|
-
### Conditional Validation
|
|
576
|
-
|
|
577
|
-
```typescript
|
|
578
|
-
// Validate based on other field values
|
|
579
|
-
const submissionSchema = z.object({
|
|
580
|
-
type: z.enum(['NEW', 'UPDATE']),
|
|
581
|
-
postId: z.number().optional(),
|
|
582
|
-
}).refine(
|
|
583
|
-
(data) => {
|
|
584
|
-
// If type is UPDATE, postId is required
|
|
585
|
-
if (data.type === 'UPDATE') {
|
|
586
|
-
return data.postId !== undefined;
|
|
587
|
-
}
|
|
588
|
-
return true;
|
|
589
|
-
},
|
|
590
|
-
{
|
|
591
|
-
message: 'postId is required when type is UPDATE',
|
|
592
|
-
path: ['postId'],
|
|
593
|
-
}
|
|
594
|
-
);
|
|
595
|
-
```
|
|
596
|
-
|
|
597
|
-
### Transform Data
|
|
598
|
-
|
|
599
|
-
```typescript
|
|
600
|
-
// Transform strings to numbers
|
|
601
|
-
const userSchema = z.object({
|
|
602
|
-
name: z.string(),
|
|
603
|
-
age: z.string().transform((val) => parseInt(val, 10)),
|
|
604
|
-
});
|
|
605
|
-
|
|
606
|
-
// Transform dates
|
|
607
|
-
const eventSchema = z.object({
|
|
608
|
-
name: z.string(),
|
|
609
|
-
date: z.string().transform((str) => new Date(str)),
|
|
610
|
-
});
|
|
611
|
-
```
|
|
612
|
-
|
|
613
|
-
### Preprocess Data
|
|
614
|
-
|
|
615
|
-
```typescript
|
|
616
|
-
// Trim strings before validation
|
|
617
|
-
const userSchema = z.object({
|
|
618
|
-
email: z.preprocess(
|
|
619
|
-
(val) => typeof val === 'string' ? val.trim().toLowerCase() : val,
|
|
620
|
-
z.string().email()
|
|
621
|
-
),
|
|
622
|
-
name: z.preprocess(
|
|
623
|
-
(val) => typeof val === 'string' ? val.trim() : val,
|
|
624
|
-
z.string().min(2)
|
|
625
|
-
),
|
|
626
|
-
});
|
|
627
|
-
```
|
|
628
|
-
|
|
629
|
-
### Union Types
|
|
630
|
-
|
|
631
|
-
```typescript
|
|
632
|
-
// Multiple possible types
|
|
633
|
-
const idSchema = z.union([z.string(), z.number()]);
|
|
634
|
-
|
|
635
|
-
// Discriminated unions
|
|
636
|
-
const notificationSchema = z.discriminatedUnion('type', [
|
|
637
|
-
z.object({
|
|
638
|
-
type: z.literal('email'),
|
|
639
|
-
recipient: z.string().email(),
|
|
640
|
-
subject: z.string(),
|
|
641
|
-
}),
|
|
642
|
-
z.object({
|
|
643
|
-
type: z.literal('sms'),
|
|
644
|
-
phoneNumber: z.string(),
|
|
645
|
-
message: z.string(),
|
|
646
|
-
}),
|
|
647
|
-
]);
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
### Recursive Schemas
|
|
651
|
-
|
|
652
|
-
```typescript
|
|
653
|
-
// For nested structures like trees
|
|
654
|
-
type Category = {
|
|
655
|
-
id: number;
|
|
656
|
-
name: string;
|
|
657
|
-
children?: Category[];
|
|
658
|
-
};
|
|
659
|
-
|
|
660
|
-
const categorySchema: z.ZodType<Category> = z.lazy(() =>
|
|
661
|
-
z.object({
|
|
662
|
-
id: z.number(),
|
|
663
|
-
name: z.string(),
|
|
664
|
-
children: z.array(categorySchema).optional(),
|
|
665
|
-
})
|
|
666
|
-
);
|
|
667
|
-
```
|
|
668
|
-
|
|
669
|
-
### Schema Composition
|
|
670
|
-
|
|
671
|
-
```typescript
|
|
672
|
-
// Base schemas
|
|
673
|
-
const timestampsSchema = z.object({
|
|
674
|
-
createdAt: z.string().datetime(),
|
|
675
|
-
updatedAt: z.string().datetime(),
|
|
676
|
-
});
|
|
677
|
-
|
|
678
|
-
const auditSchema = z.object({
|
|
679
|
-
createdBy: z.string(),
|
|
680
|
-
updatedBy: z.string(),
|
|
681
|
-
});
|
|
682
|
-
|
|
683
|
-
// Compose schemas
|
|
684
|
-
const userSchema = z.object({
|
|
685
|
-
id: z.string(),
|
|
686
|
-
email: z.string().email(),
|
|
687
|
-
name: z.string(),
|
|
688
|
-
}).merge(timestampsSchema).merge(auditSchema);
|
|
689
|
-
|
|
690
|
-
// Extend schemas
|
|
691
|
-
const adminUserSchema = userSchema.extend({
|
|
692
|
-
adminLevel: z.number().int().min(1).max(5),
|
|
693
|
-
permissions: z.array(z.string()),
|
|
694
|
-
});
|
|
695
|
-
|
|
696
|
-
// Pick specific fields
|
|
697
|
-
const publicUserSchema = userSchema.pick({
|
|
698
|
-
id: true,
|
|
699
|
-
name: true,
|
|
700
|
-
// email excluded
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
// Omit fields
|
|
704
|
-
const userWithoutTimestamps = userSchema.omit({
|
|
705
|
-
createdAt: true,
|
|
706
|
-
updatedAt: true,
|
|
707
|
-
});
|
|
708
|
-
```
|
|
709
|
-
|
|
710
|
-
### Validation Middleware
|
|
711
|
-
|
|
712
|
-
```typescript
|
|
713
|
-
// Create reusable validation middleware
|
|
714
|
-
import { Request, Response, NextFunction } from 'express';
|
|
715
|
-
import { z } from 'zod';
|
|
716
|
-
|
|
717
|
-
export function validateBody<T extends z.ZodType>(schema: T) {
|
|
718
|
-
return (req: Request, res: Response, next: NextFunction) => {
|
|
719
|
-
try {
|
|
720
|
-
req.body = schema.parse(req.body);
|
|
721
|
-
next();
|
|
722
|
-
} catch (error) {
|
|
723
|
-
if (error instanceof z.ZodError) {
|
|
724
|
-
return res.status(400).json({
|
|
725
|
-
success: false,
|
|
726
|
-
error: {
|
|
727
|
-
message: 'Validation failed',
|
|
728
|
-
details: error.errors,
|
|
729
|
-
},
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
|
-
next(error);
|
|
733
|
-
}
|
|
734
|
-
};
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
// Usage
|
|
738
|
-
router.post('/users',
|
|
739
|
-
validateBody(createUserSchema),
|
|
740
|
-
async (req, res) => {
|
|
741
|
-
// req.body is validated and typed!
|
|
742
|
-
const user = await userService.createUser(req.body);
|
|
743
|
-
res.json({ success: true, data: user });
|
|
744
|
-
}
|
|
745
|
-
);
|
|
746
|
-
```
|
|
747
|
-
|
|
748
|
-
---
|
|
749
|
-
|
|
750
|
-
**Related Files:**
|
|
751
|
-
- [SKILL.md](SKILL.md) - Main guide
|
|
752
|
-
- [routing-and-controllers.md](routing-and-controllers.md) - Using validation in controllers
|
|
753
|
-
- [services-and-repositories.md](services-and-repositories.md) - Using DTOs in services
|
|
754
|
-
- [async-and-errors.md](async-and-errors.md) - Error handling patterns
|