@specverse/engine-realize 3.5.3
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/assets/examples/09-api/ai-spec.yaml +194 -0
- package/assets/examples/09-api/converted.yaml +95 -0
- package/assets/examples/09-api/diagram-architecture.mmd +10 -0
- package/assets/examples/09-api/diagram-er.mmd +10 -0
- package/assets/examples/09-api/documentation.html +104 -0
- package/assets/examples/09-api/documentation.md +95 -0
- package/assets/examples/09-api/inferred-spec.yaml +420 -0
- package/assets/examples/09-api/openapi.json +61 -0
- package/assets/examples/10-api/README.md +216 -0
- package/assets/examples/10-api/ai-spec.yaml +194 -0
- package/assets/examples/10-api/converted.yaml +96 -0
- package/assets/examples/10-api/diagram-architecture.mmd +10 -0
- package/assets/examples/10-api/diagram-er.mmd +10 -0
- package/assets/examples/10-api/documentation.html +104 -0
- package/assets/examples/10-api/documentation.md +95 -0
- package/assets/examples/10-api/inferred-spec.yaml +7 -0
- package/assets/examples/10-api/metadata.yaml +89 -0
- package/assets/examples/10-api/openapi.json +61 -0
- package/assets/examples/10-api/package-integration-test.js +177 -0
- package/assets/examples/10-api/usage-example.js +323 -0
- package/assets/examples/10-api/usage-example.ts +363 -0
- package/assets/examples/10-api/workflow-test.js +113 -0
- package/assets/examples/manifests/01-simple-default-mappings.yaml +36 -0
- package/assets/examples/manifests/02-capability-mappings.yaml +55 -0
- package/assets/examples/manifests/03-hybrid-mappings.yaml +109 -0
- package/assets/examples/manifests/README.md +245 -0
- package/assets/examples/manifests/backend-only.yaml +43 -0
- package/assets/examples/manifests/blog-api.md +78 -0
- package/assets/examples/manifests/blog-api.specly +79 -0
- package/assets/examples/manifests/frontend-only.yaml +27 -0
- package/assets/examples/manifests/fullstack-app.yaml +44 -0
- package/assets/examples/manifests/fullstack-monorepo.yaml +62 -0
- package/assets/examples/validate-examples-with-expected-failures.cjs +328 -0
- package/assets/examples/validate-examples.cjs +225 -0
- package/assets/examples-decomposed/cloud-native-manifest.example.yaml +8 -0
- package/assets/examples-decomposed/cloud-native-manifest.md +379 -0
- package/assets/examples-decomposed/cloud-native-manifest.specly +60 -0
- package/assets/examples-decomposed/docker-compose-manifest.example.yaml +8 -0
- package/assets/examples-decomposed/docker-compose-manifest.md +326 -0
- package/assets/examples-decomposed/docker-compose-manifest.specly +40 -0
- package/assets/examples-decomposed/kubernetes-deployment-manifest.example.yaml +8 -0
- package/assets/examples-decomposed/kubernetes-deployment-manifest.md +237 -0
- package/assets/examples-decomposed/kubernetes-deployment-manifest.specly +41 -0
- package/assets/templates/README.md +559 -0
- package/assets/templates/TEMPLATE-ENHANCEMENTS-V33.md +462 -0
- package/assets/templates/backend-only/CLAUDE.md +73 -0
- package/assets/templates/backend-only/README.md +197 -0
- package/assets/templates/backend-only/deployments/README.md +149 -0
- package/assets/templates/backend-only/deployments/development.specly +53 -0
- package/assets/templates/backend-only/deployments/production.specly +87 -0
- package/assets/templates/backend-only/docs/README.md +50 -0
- package/assets/templates/backend-only/docs/api/README.md +7 -0
- package/assets/templates/backend-only/docs/diagrams/README.md +85 -0
- package/assets/templates/backend-only/docs/example-documentation-template.md +269 -0
- package/assets/templates/backend-only/docs/guides/README.md +15 -0
- package/assets/templates/backend-only/dot.env.example +18 -0
- package/assets/templates/backend-only/generated/README.md +56 -0
- package/assets/templates/backend-only/generated/code/integration-test.template.js +320 -0
- package/assets/templates/backend-only/generated/code/package.json.template +34 -0
- package/assets/templates/backend-only/generated/docs/README.md +49 -0
- package/assets/templates/backend-only/gitignore +54 -0
- package/assets/templates/backend-only/manifests/README.md +72 -0
- package/assets/templates/backend-only/manifests/docker-compose.specly +91 -0
- package/assets/templates/backend-only/manifests/implementation.yaml +100 -0
- package/assets/templates/backend-only/manifests/kubernetes.specly +140 -0
- package/assets/templates/backend-only/package.json +59 -0
- package/assets/templates/backend-only/scripts/test-all.sh +160 -0
- package/assets/templates/backend-only/scripts/test-generated-code.sh +165 -0
- package/assets/templates/backend-only/specs/main.specly +67 -0
- package/assets/templates/default/CLAUDE.md +141 -0
- package/assets/templates/default/README.md +404 -0
- package/assets/templates/default/deployments/README.md +149 -0
- package/assets/templates/default/deployments/development.specly +53 -0
- package/assets/templates/default/deployments/production.specly +87 -0
- package/assets/templates/default/docs/README.md +50 -0
- package/assets/templates/default/docs/api/README.md +7 -0
- package/assets/templates/default/docs/diagrams/README.md +85 -0
- package/assets/templates/default/docs/example-documentation-template.md +269 -0
- package/assets/templates/default/docs/guides/README.md +15 -0
- package/assets/templates/default/dot.env.example +18 -0
- package/assets/templates/default/generated/README.md +56 -0
- package/assets/templates/default/generated/code/integration-test.template.js +320 -0
- package/assets/templates/default/generated/code/package.json.template +34 -0
- package/assets/templates/default/generated/docs/README.md +49 -0
- package/assets/templates/default/gitignore +54 -0
- package/assets/templates/default/manifests/README.md +72 -0
- package/assets/templates/default/manifests/docker-compose.specly +91 -0
- package/assets/templates/default/manifests/implementation.yaml +176 -0
- package/assets/templates/default/manifests/kubernetes.specly +140 -0
- package/assets/templates/default/package.json +61 -0
- package/assets/templates/default/scripts/test-all.sh +160 -0
- package/assets/templates/default/scripts/test-generated-code.sh +165 -0
- package/assets/templates/default/specs/main.specly +67 -0
- package/assets/templates/frontend-only/CLAUDE.md +75 -0
- package/assets/templates/frontend-only/README.md +231 -0
- package/assets/templates/frontend-only/deployments/README.md +149 -0
- package/assets/templates/frontend-only/deployments/development.specly +53 -0
- package/assets/templates/frontend-only/deployments/production.specly +87 -0
- package/assets/templates/frontend-only/docs/README.md +50 -0
- package/assets/templates/frontend-only/docs/api/README.md +7 -0
- package/assets/templates/frontend-only/docs/diagrams/README.md +85 -0
- package/assets/templates/frontend-only/docs/example-documentation-template.md +269 -0
- package/assets/templates/frontend-only/docs/guides/README.md +15 -0
- package/assets/templates/frontend-only/dot.env.example +18 -0
- package/assets/templates/frontend-only/generated/README.md +56 -0
- package/assets/templates/frontend-only/generated/code/integration-test.template.js +320 -0
- package/assets/templates/frontend-only/generated/code/package.json.template +34 -0
- package/assets/templates/frontend-only/generated/docs/README.md +49 -0
- package/assets/templates/frontend-only/gitignore +54 -0
- package/assets/templates/frontend-only/manifests/README.md +72 -0
- package/assets/templates/frontend-only/manifests/docker-compose.specly +91 -0
- package/assets/templates/frontend-only/manifests/implementation.yaml +58 -0
- package/assets/templates/frontend-only/manifests/kubernetes.specly +140 -0
- package/assets/templates/frontend-only/package.json +59 -0
- package/assets/templates/frontend-only/scripts/test-all.sh +160 -0
- package/assets/templates/frontend-only/scripts/test-generated-code.sh +165 -0
- package/assets/templates/frontend-only/specs/main.specly +57 -0
- package/assets/templates/full-stack/AI-GUIDE.md +60 -0
- package/assets/templates/full-stack/CLAUDE.md +141 -0
- package/assets/templates/full-stack/README.md +382 -0
- package/assets/templates/full-stack/archive/AI-GUIDE-legacy.md +392 -0
- package/assets/templates/full-stack/deployments/README.md +149 -0
- package/assets/templates/full-stack/deployments/development.specly +53 -0
- package/assets/templates/full-stack/deployments/production.specly +87 -0
- package/assets/templates/full-stack/docs/README.md +51 -0
- package/assets/templates/full-stack/docs/api/README.md +7 -0
- package/assets/templates/full-stack/docs/diagrams/README.md +85 -0
- package/assets/templates/full-stack/docs/example-documentation-template.md +269 -0
- package/assets/templates/full-stack/docs/guides/README.md +15 -0
- package/assets/templates/full-stack/generated/README.md +56 -0
- package/assets/templates/full-stack/generated/code/integration-test.template.js +320 -0
- package/assets/templates/full-stack/generated/code/package.json.template +34 -0
- package/assets/templates/full-stack/generated/docs/README.md +49 -0
- package/assets/templates/full-stack/gitignore +54 -0
- package/assets/templates/full-stack/manifests/README.md +72 -0
- package/assets/templates/full-stack/manifests/docker-compose.specly +91 -0
- package/assets/templates/full-stack/manifests/implementation.yaml +155 -0
- package/assets/templates/full-stack/manifests/kubernetes.specly +140 -0
- package/assets/templates/full-stack/package.json +45 -0
- package/assets/templates/full-stack/scripts/test-all.sh +160 -0
- package/assets/templates/full-stack/scripts/test-generated-code.sh +165 -0
- package/assets/templates/full-stack/specs/example-v33.specly +297 -0
- package/assets/templates/full-stack/specs/main-simple.specly +73 -0
- package/assets/templates/full-stack/specs/main.specly +408 -0
- package/dist/engines/code-generator.d.ts +86 -0
- package/dist/engines/code-generator.d.ts.map +1 -0
- package/dist/engines/code-generator.js +159 -0
- package/dist/engines/code-generator.js.map +1 -0
- package/dist/engines/engine-registry.d.ts +94 -0
- package/dist/engines/engine-registry.d.ts.map +1 -0
- package/dist/engines/engine-registry.js +163 -0
- package/dist/engines/engine-registry.js.map +1 -0
- package/dist/engines/index.d.ts +10 -0
- package/dist/engines/index.d.ts.map +1 -0
- package/dist/engines/index.js +12 -0
- package/dist/engines/index.js.map +1 -0
- package/dist/engines/typescript-engine.d.ts +74 -0
- package/dist/engines/typescript-engine.d.ts.map +1 -0
- package/dist/engines/typescript-engine.js +288 -0
- package/dist/engines/typescript-engine.js.map +1 -0
- package/dist/generators/index.d.ts +11 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +11 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +434 -0
- package/dist/index.js.map +1 -0
- package/dist/library/index.d.ts +12 -0
- package/dist/library/index.d.ts.map +1 -0
- package/dist/library/index.js +15 -0
- package/dist/library/index.js.map +1 -0
- package/dist/library/library.d.ts +132 -0
- package/dist/library/library.d.ts.map +1 -0
- package/dist/library/library.js +343 -0
- package/dist/library/library.js.map +1 -0
- package/dist/library/loader.d.ts +73 -0
- package/dist/library/loader.d.ts.map +1 -0
- package/dist/library/loader.js +150 -0
- package/dist/library/loader.js.map +1 -0
- package/dist/library/resolver.d.ts +104 -0
- package/dist/library/resolver.d.ts.map +1 -0
- package/dist/library/resolver.js +299 -0
- package/dist/library/resolver.js.map +1 -0
- package/dist/library/validator.d.ts +65 -0
- package/dist/library/validator.d.ts.map +1 -0
- package/dist/library/validator.js +203 -0
- package/dist/library/validator.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/instance-factory.d.ts +289 -0
- package/dist/types/instance-factory.d.ts.map +1 -0
- package/dist/types/instance-factory.js +8 -0
- package/dist/types/instance-factory.js.map +1 -0
- package/dist/types/unified-mappings.d.ts +163 -0
- package/dist/types/unified-mappings.d.ts.map +1 -0
- package/dist/types/unified-mappings.js +110 -0
- package/dist/types/unified-mappings.js.map +1 -0
- package/dist/utils/ai-spec-loader.d.ts +77 -0
- package/dist/utils/ai-spec-loader.d.ts.map +1 -0
- package/dist/utils/ai-spec-loader.js +138 -0
- package/dist/utils/ai-spec-loader.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/manifest-loader.d.ts +107 -0
- package/dist/utils/manifest-loader.d.ts.map +1 -0
- package/dist/utils/manifest-loader.js +168 -0
- package/dist/utils/manifest-loader.js.map +1 -0
- package/dist/utils/mapping-migration.d.ts +53 -0
- package/dist/utils/mapping-migration.d.ts.map +1 -0
- package/dist/utils/mapping-migration.js +194 -0
- package/dist/utils/mapping-migration.js.map +1 -0
- package/libs/instance-factories/CURVED-INTERFACE.md +278 -0
- package/libs/instance-factories/README.md +433 -0
- package/libs/instance-factories/applications/generic-app.yaml +52 -0
- package/libs/instance-factories/applications/react-app.yaml +186 -0
- package/libs/instance-factories/applications/templates/generic/backend-env-generator.ts +31 -0
- package/libs/instance-factories/applications/templates/generic/backend-package-json-generator.ts +80 -0
- package/libs/instance-factories/applications/templates/generic/backend-tsconfig-generator.ts +69 -0
- package/libs/instance-factories/applications/templates/generic/main-generator.ts +308 -0
- package/libs/instance-factories/applications/templates/react/_view-components-source.ts +555 -0
- package/libs/instance-factories/applications/templates/react/api-client-generator.ts +436 -0
- package/libs/instance-factories/applications/templates/react/api-types-generator.ts +153 -0
- package/libs/instance-factories/applications/templates/react/app-tsx-generator.ts +94 -0
- package/libs/instance-factories/applications/templates/react/env-example-generator.ts +24 -0
- package/libs/instance-factories/applications/templates/react/field-helpers-generator.ts +106 -0
- package/libs/instance-factories/applications/templates/react/gitignore-generator.ts +38 -0
- package/libs/instance-factories/applications/templates/react/index-css-generator.ts +85 -0
- package/libs/instance-factories/applications/templates/react/index-html-generator.ts +30 -0
- package/libs/instance-factories/applications/templates/react/main-tsx-generator.ts +34 -0
- package/libs/instance-factories/applications/templates/react/package-json-generator.ts +54 -0
- package/libs/instance-factories/applications/templates/react/pattern-adapter-generator.ts +179 -0
- package/libs/instance-factories/applications/templates/react/react-pattern-adapter.tsx +1347 -0
- package/libs/instance-factories/applications/templates/react/relationship-field-generator.ts +150 -0
- package/libs/instance-factories/applications/templates/react/tailwind-adapter-generator.ts +704 -0
- package/libs/instance-factories/applications/templates/react/tailwind-adapter-wrapper-generator.ts +84 -0
- package/libs/instance-factories/applications/templates/react/tsconfig-generator.ts +35 -0
- package/libs/instance-factories/applications/templates/react/use-api-hooks-generator.ts +121 -0
- package/libs/instance-factories/applications/templates/react/view-dashboard-generator.ts +150 -0
- package/libs/instance-factories/applications/templates/react/view-detail-generator.ts +150 -0
- package/libs/instance-factories/applications/templates/react/view-form-generator.ts +362 -0
- package/libs/instance-factories/applications/templates/react/view-list-generator.ts +98 -0
- package/libs/instance-factories/applications/templates/react/view-router-generator.ts +89 -0
- package/libs/instance-factories/applications/templates/react/vite-config-generator.ts +49 -0
- package/libs/instance-factories/archived/fastify-prisma.yaml +104 -0
- package/libs/instance-factories/cli/commander-js.yaml +55 -0
- package/libs/instance-factories/cli/templates/commander/cli-entry-generator.d.ts +12 -0
- package/libs/instance-factories/cli/templates/commander/cli-entry-generator.d.ts.map +1 -0
- package/libs/instance-factories/cli/templates/commander/cli-entry-generator.js +115 -0
- package/libs/instance-factories/cli/templates/commander/cli-entry-generator.js.map +1 -0
- package/libs/instance-factories/cli/templates/commander/cli-entry-generator.ts +145 -0
- package/libs/instance-factories/cli/templates/commander/command-generator.d.ts +14 -0
- package/libs/instance-factories/cli/templates/commander/command-generator.d.ts.map +1 -0
- package/libs/instance-factories/cli/templates/commander/command-generator.js +182 -0
- package/libs/instance-factories/cli/templates/commander/command-generator.js.map +1 -0
- package/libs/instance-factories/cli/templates/commander/command-generator.ts +992 -0
- package/libs/instance-factories/communication/event-emitter.yaml +56 -0
- package/libs/instance-factories/communication/rabbitmq-events.yaml +87 -0
- package/libs/instance-factories/communication/templates/eventemitter/bus-generator.ts +93 -0
- package/libs/instance-factories/communication/templates/eventemitter/publisher-generator.ts +117 -0
- package/libs/instance-factories/communication/templates/eventemitter/subscriber-generator.ts +101 -0
- package/libs/instance-factories/controllers/fastify.yaml +127 -0
- package/libs/instance-factories/controllers/templates/fastify/meta-routes-generator.ts +103 -0
- package/libs/instance-factories/controllers/templates/fastify/routes-generator.ts +389 -0
- package/libs/instance-factories/controllers/templates/fastify/server-generator.ts +76 -0
- package/libs/instance-factories/infrastructure/docker-k8s.yaml +61 -0
- package/libs/instance-factories/infrastructure/templates/docker-k8s/infrastructure-generator.ts +46 -0
- package/libs/instance-factories/orms/prisma.yaml +89 -0
- package/libs/instance-factories/orms/templates/prisma/schema-generator.ts +563 -0
- package/libs/instance-factories/orms/templates/prisma/services-generator.ts +408 -0
- package/libs/instance-factories/scaffolding/generic-scaffold.yaml +65 -0
- package/libs/instance-factories/scaffolding/templates/generic/env-example-generator.ts +73 -0
- package/libs/instance-factories/scaffolding/templates/generic/env-generator.ts +85 -0
- package/libs/instance-factories/scaffolding/templates/generic/gitignore-generator.ts +69 -0
- package/libs/instance-factories/scaffolding/templates/generic/package-json-generator.ts +176 -0
- package/libs/instance-factories/scaffolding/templates/generic/readme-generator.ts +207 -0
- package/libs/instance-factories/scaffolding/templates/generic/tsconfig-generator.ts +78 -0
- package/libs/instance-factories/scaffolding/templates/generic/tsconfig-react-generator.ts +41 -0
- package/libs/instance-factories/sdks/python-sdk.yaml +66 -0
- package/libs/instance-factories/sdks/templates/python/sdk-generator.ts +50 -0
- package/libs/instance-factories/sdks/templates/typescript/sdk-generator.ts +49 -0
- package/libs/instance-factories/sdks/typescript-sdk.yaml +59 -0
- package/libs/instance-factories/services/prisma-services.yaml +71 -0
- package/libs/instance-factories/services/templates/prisma/behavior-generator.ts +303 -0
- package/libs/instance-factories/services/templates/prisma/controller-generator.ts +532 -0
- package/libs/instance-factories/services/templates/prisma/service-generator.ts +315 -0
- package/libs/instance-factories/shared/path-resolver.ts +111 -0
- package/libs/instance-factories/storage/mongodb.yaml +79 -0
- package/libs/instance-factories/storage/postgresql.yaml +75 -0
- package/libs/instance-factories/storage/redis.yaml +79 -0
- package/libs/instance-factories/storage/templates/mongodb/config-generator.ts +15 -0
- package/libs/instance-factories/storage/templates/mongodb/docker-generator.ts +18 -0
- package/libs/instance-factories/storage/templates/postgresql/config-generator.ts +54 -0
- package/libs/instance-factories/storage/templates/postgresql/docker-generator.ts +55 -0
- package/libs/instance-factories/storage/templates/redis/config-generator.ts +16 -0
- package/libs/instance-factories/storage/templates/redis/docker-generator.ts +18 -0
- package/libs/instance-factories/test-generation.ts +192 -0
- package/libs/instance-factories/testing/templates/vitest/tests-generator.ts +51 -0
- package/libs/instance-factories/testing/vitest-tests.yaml +63 -0
- package/libs/instance-factories/tools/templates/mcp/mcp-server-generator.ts +136 -0
- package/libs/instance-factories/tools/templates/mcp/static/docs/DEPLOYMENT_GUIDE.md +630 -0
- package/libs/instance-factories/tools/templates/mcp/static/docs/HYBRID_RESOURCE_SYSTEM.md +330 -0
- package/libs/instance-factories/tools/templates/mcp/static/docs/deployments/EXTENSION_DEPLOYMENT.md +552 -0
- package/libs/instance-factories/tools/templates/mcp/static/docs/deployments/LOCAL_DEPLOYMENT.md +164 -0
- package/libs/instance-factories/tools/templates/mcp/static/docs/deployments/WEB_DEPLOYMENT.md +247 -0
- package/libs/instance-factories/tools/templates/mcp/static/package.json +92 -0
- package/libs/instance-factories/tools/templates/mcp/static/scripts/build-enterprise.js +284 -0
- package/libs/instance-factories/tools/templates/mcp/static/scripts/build-extension.js +139 -0
- package/libs/instance-factories/tools/templates/mcp/static/scripts/build-local.js +74 -0
- package/libs/instance-factories/tools/templates/mcp/static/scripts/build-web.js +156 -0
- package/libs/instance-factories/tools/templates/mcp/static/scripts/copy-canonical-files.js +41 -0
- package/libs/instance-factories/tools/templates/mcp/static/scripts/test-deployments.js +259 -0
- package/libs/instance-factories/tools/templates/mcp/static/scripts/test-hybrid-resources.js +231 -0
- package/libs/instance-factories/tools/templates/mcp/static/scripts/test-hybrid-simple.js +196 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/controllers/MCPServerController.ts +293 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/events/EventEmitter.ts +90 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/index.ts +24 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/interfaces/ResourceProvider.ts +15 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/models/LibrarySuggestion.ts +106 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/models/SpecVerseResource.ts +75 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/server/mcp-server.ts +239 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/services/CLIProxyService.ts +1501 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/services/EmbeddedResourcesAdapter.ts +211 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/services/EntityModuleService.ts +308 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/services/HybridResourcesProvider.ts +210 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/services/LibraryToolsService.ts +356 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/services/OrchestratorBridge.ts +524 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/services/OrchestratorToolsService.ts +530 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/services/PromptToolsService.ts +594 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/services/ResourcesProviderService.ts +170 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/tests/unit/CLIProxyService.init.test.ts +544 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/tests/unit/CLIProxyService.test.ts +189 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/tests/unit/ResourcesProviderService.test.ts +89 -0
- package/libs/instance-factories/tools/templates/mcp/static/src/types/index.ts +110 -0
- package/libs/instance-factories/tools/templates/mcp/static/tsconfig.json +28 -0
- package/libs/instance-factories/tools/templates/vscode/static/extension.ts +1195 -0
- package/libs/instance-factories/tools/templates/vscode/static/language-configuration.json +34 -0
- package/libs/instance-factories/tools/templates/vscode/static/schemas/specverse-v3-schema.json +4279 -0
- package/libs/instance-factories/tools/templates/vscode/static/syntaxes/specverse.tmLanguage.json +138 -0
- package/libs/instance-factories/tools/templates/vscode/static/themes/README.md +74 -0
- package/libs/instance-factories/tools/templates/vscode/static/themes/complete-specverse-colors.json +122 -0
- package/libs/instance-factories/tools/templates/vscode/static/themes/specverse-basic-theme.json +65 -0
- package/libs/instance-factories/tools/templates/vscode/static/themes/specverse-complete-theme.json +123 -0
- package/libs/instance-factories/tools/templates/vscode/static/themes/specverse-theme-colors.json +64 -0
- package/libs/instance-factories/tools/templates/vscode/vscode-extension-generator.ts +214 -0
- package/libs/instance-factories/validation/templates/zod/validation-generator.ts +46 -0
- package/libs/instance-factories/validation/zod.yaml +56 -0
- package/libs/instance-factories/views/index.d.ts +13 -0
- package/libs/instance-factories/views/index.d.ts.map +1 -0
- package/libs/instance-factories/views/index.js +18 -0
- package/libs/instance-factories/views/index.js.map +1 -0
- package/libs/instance-factories/views/index.ts +45 -0
- package/libs/instance-factories/views/react-components.yaml +129 -0
- package/libs/instance-factories/views/templates/ARCHITECTURE.md +198 -0
- package/libs/instance-factories/views/templates/react/adapters/antd-adapter.ts +869 -0
- package/libs/instance-factories/views/templates/react/adapters/mui-adapter.ts +953 -0
- package/libs/instance-factories/views/templates/react/adapters/shadcn-adapter.ts +806 -0
- package/libs/instance-factories/views/templates/react/app-generator.ts +55 -0
- package/libs/instance-factories/views/templates/react/components-generator.ts +391 -0
- package/libs/instance-factories/views/templates/react/forms-generator.ts +343 -0
- package/libs/instance-factories/views/templates/react/frontend-package-json-generator.ts +54 -0
- package/libs/instance-factories/views/templates/react/hooks-generator.ts +122 -0
- package/libs/instance-factories/views/templates/react/index-css-generator.ts +209 -0
- package/libs/instance-factories/views/templates/react/index-html-generator.ts +34 -0
- package/libs/instance-factories/views/templates/react/main-tsx-generator.ts +29 -0
- package/libs/instance-factories/views/templates/react/react-component-generator.d.ts +152 -0
- package/libs/instance-factories/views/templates/react/react-component-generator.d.ts.map +1 -0
- package/libs/instance-factories/views/templates/react/react-component-generator.js +398 -0
- package/libs/instance-factories/views/templates/react/react-component-generator.js.map +1 -0
- package/libs/instance-factories/views/templates/react/react-component-generator.ts +533 -0
- package/libs/instance-factories/views/templates/react/router-generator.ts +197 -0
- package/libs/instance-factories/views/templates/react/router-generic-generator.ts +103 -0
- package/libs/instance-factories/views/templates/react/spec-json-generator.ts +17 -0
- package/libs/instance-factories/views/templates/react/types-generator.ts +76 -0
- package/libs/instance-factories/views/templates/react/views-metadata-generator.ts +42 -0
- package/libs/instance-factories/views/templates/react/vite-config-generator.ts +38 -0
- package/libs/instance-factories/views/templates/runtime/runtime-view-renderer.d.ts.map +1 -0
- package/libs/instance-factories/views/templates/runtime/runtime-view-renderer.js.map +1 -0
- package/libs/instance-factories/views/templates/runtime/runtime-view-renderer.ts +474 -0
- package/libs/instance-factories/views/templates/shared/__tests__/composite-patterns.test.ts +242 -0
- package/libs/instance-factories/views/templates/shared/adapter-types.d.ts +77 -0
- package/libs/instance-factories/views/templates/shared/adapter-types.d.ts.map +1 -0
- package/libs/instance-factories/views/templates/shared/adapter-types.js +47 -0
- package/libs/instance-factories/views/templates/shared/adapter-types.js.map +1 -0
- package/libs/instance-factories/views/templates/shared/adapter-types.ts +142 -0
- package/libs/instance-factories/views/templates/shared/atomic-components-registry.d.ts +63 -0
- package/libs/instance-factories/views/templates/shared/atomic-components-registry.d.ts.map +1 -0
- package/libs/instance-factories/views/templates/shared/atomic-components-registry.js +822 -0
- package/libs/instance-factories/views/templates/shared/atomic-components-registry.js.map +1 -0
- package/libs/instance-factories/views/templates/shared/atomic-components-registry.ts +908 -0
- package/libs/instance-factories/views/templates/shared/base-generator.d.ts +247 -0
- package/libs/instance-factories/views/templates/shared/base-generator.d.ts.map +1 -0
- package/libs/instance-factories/views/templates/shared/base-generator.js +363 -0
- package/libs/instance-factories/views/templates/shared/base-generator.js.map +1 -0
- package/libs/instance-factories/views/templates/shared/base-generator.ts +608 -0
- package/libs/instance-factories/views/templates/shared/component-metadata.d.ts +254 -0
- package/libs/instance-factories/views/templates/shared/component-metadata.d.ts.map +1 -0
- package/libs/instance-factories/views/templates/shared/component-metadata.js +602 -0
- package/libs/instance-factories/views/templates/shared/component-metadata.js.map +1 -0
- package/libs/instance-factories/views/templates/shared/component-metadata.ts +803 -0
- package/libs/instance-factories/views/templates/shared/composite-pattern-types.ts +250 -0
- package/libs/instance-factories/views/templates/shared/composite-patterns.ts +535 -0
- package/libs/instance-factories/views/templates/shared/index.ts +68 -0
- package/libs/instance-factories/views/templates/shared/pattern-validator.ts +279 -0
- package/libs/instance-factories/views/templates/shared/property-mapper.d.ts +149 -0
- package/libs/instance-factories/views/templates/shared/property-mapper.d.ts.map +1 -0
- package/libs/instance-factories/views/templates/shared/property-mapper.js +580 -0
- package/libs/instance-factories/views/templates/shared/property-mapper.js.map +1 -0
- package/libs/instance-factories/views/templates/shared/property-mapper.ts +700 -0
- package/libs/instance-factories/views/templates/shared/syntax-mapper.d.ts +143 -0
- package/libs/instance-factories/views/templates/shared/syntax-mapper.d.ts.map +1 -0
- package/libs/instance-factories/views/templates/shared/syntax-mapper.js +420 -0
- package/libs/instance-factories/views/templates/shared/syntax-mapper.js.map +1 -0
- package/libs/instance-factories/views/templates/shared/syntax-mapper.ts +539 -0
- package/package.json +42 -0
- package/schema/SPECVERSE-SCHEMA.json +4274 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prisma Schema Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates Prisma schema from SpecVerse models
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { TemplateContext } from '@specverse/engine-realize';
|
|
8
|
+
import { pluralize } from '@specverse/types';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate Prisma schema
|
|
12
|
+
*/
|
|
13
|
+
export default function generatePrismaSchema(context: TemplateContext): string {
|
|
14
|
+
const { spec, models, implType } = context;
|
|
15
|
+
|
|
16
|
+
const allModels = models || spec?.models || [];
|
|
17
|
+
|
|
18
|
+
if (allModels.length === 0) {
|
|
19
|
+
throw new Error('No models found in context for schema generation');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Build relation map: track all references to each target model
|
|
23
|
+
// so we can add @relation("name") when a target is referenced multiple times
|
|
24
|
+
const relationMap = buildRelationMap(allModels);
|
|
25
|
+
|
|
26
|
+
// Build missing back-references: when Model A has hasMany B but B has no belongsTo A,
|
|
27
|
+
// Prisma requires the back-reference field on B. We auto-generate these.
|
|
28
|
+
const backRefs = buildMissingBackRefs(allModels, relationMap);
|
|
29
|
+
|
|
30
|
+
// Build set of "ParentModel->ChildModel" for hasOne relations
|
|
31
|
+
// Used to add @unique to FK fields on the child side of a hasOne
|
|
32
|
+
const hasOneTargets = new Set<string>();
|
|
33
|
+
for (const m of allModels) {
|
|
34
|
+
const rels = Array.isArray(m.relationships) ? m.relationships : Object.values(m.relationships || {});
|
|
35
|
+
for (const r of rels as any[]) {
|
|
36
|
+
if (r.type === 'hasOne') {
|
|
37
|
+
hasOneTargets.add(`${m.name}->${r.target}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Generate header
|
|
43
|
+
const header = generateHeader(implType);
|
|
44
|
+
|
|
45
|
+
// Generate models
|
|
46
|
+
const modelSchemas = allModels.map((model: any) =>
|
|
47
|
+
generateModelSchema(model, relationMap, backRefs, hasOneTargets, allModels)
|
|
48
|
+
).join('\n\n');
|
|
49
|
+
|
|
50
|
+
return `${header}\n\n${modelSchemas}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Build a relation name map that assigns consistent names to both sides of each relation.
|
|
55
|
+
*
|
|
56
|
+
* Prisma requires that when @relation("name") is used, BOTH sides use the same name.
|
|
57
|
+
* We need disambiguation when a model is referenced by multiple fields across all models.
|
|
58
|
+
*
|
|
59
|
+
* Returns: Map<"SourceModel.fieldName", relationName | null>
|
|
60
|
+
* - null means no @relation annotation needed
|
|
61
|
+
* - string means use @relation("name") on this field
|
|
62
|
+
*/
|
|
63
|
+
function buildRelationMap(allModels: any[]): Map<string, string | null> {
|
|
64
|
+
// Step 1: Collect all relations grouped by target model
|
|
65
|
+
type RelRef = { sourceModel: string; fieldName: string; relType: string };
|
|
66
|
+
const targetRefs = new Map<string, RelRef[]>();
|
|
67
|
+
|
|
68
|
+
for (const model of allModels) {
|
|
69
|
+
const relationships = Array.isArray(model.relationships)
|
|
70
|
+
? model.relationships
|
|
71
|
+
: Object.values(model.relationships || {});
|
|
72
|
+
|
|
73
|
+
for (const rel of relationships as any[]) {
|
|
74
|
+
const target = rel.target;
|
|
75
|
+
if (!target) continue;
|
|
76
|
+
|
|
77
|
+
const fieldName = rel.name || (rel.type === 'hasMany' || rel.type === 'manyToMany'
|
|
78
|
+
? pluralize(target.toLowerCase())
|
|
79
|
+
: target.toLowerCase());
|
|
80
|
+
|
|
81
|
+
if (!targetRefs.has(target)) {
|
|
82
|
+
targetRefs.set(target, []);
|
|
83
|
+
}
|
|
84
|
+
targetRefs.get(target)!.push({
|
|
85
|
+
sourceModel: model.name,
|
|
86
|
+
fieldName,
|
|
87
|
+
relType: rel.type
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Step 2: For ALL belongsTo relations, find the matching parent-side name.
|
|
93
|
+
// Since we always name relations, every belongsTo must use the parent's canonical name.
|
|
94
|
+
const nameMap = new Map<string, string | null>();
|
|
95
|
+
|
|
96
|
+
for (const [target, refs] of targetRefs) {
|
|
97
|
+
for (const ref of refs) {
|
|
98
|
+
const key = `${ref.sourceModel}.${ref.fieldName}`;
|
|
99
|
+
if (ref.relType === 'belongsTo') {
|
|
100
|
+
// Child side: find the matching parent-side relation
|
|
101
|
+
const parentRefs = targetRefs.get(ref.sourceModel) || [];
|
|
102
|
+
const matchingParent = parentRefs.find(p =>
|
|
103
|
+
p.sourceModel === target &&
|
|
104
|
+
(p.relType === 'hasMany' || p.relType === 'hasOne')
|
|
105
|
+
);
|
|
106
|
+
if (matchingParent) {
|
|
107
|
+
// Use the parent's canonical name so both sides match
|
|
108
|
+
nameMap.set(key, `${matchingParent.sourceModel}_${matchingParent.fieldName}`);
|
|
109
|
+
}
|
|
110
|
+
// If no matching parent, leave unmapped — getRelationName will use default
|
|
111
|
+
}
|
|
112
|
+
// hasMany/hasOne/manyToMany use default naming in getRelationName
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return nameMap;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Build missing back-reference fields.
|
|
121
|
+
* When Model A has `hasMany B` or `hasOne B`, Prisma requires B to have a
|
|
122
|
+
* corresponding FK + relation field pointing back to A.
|
|
123
|
+
* If B already has a `belongsTo A`, it's covered. Otherwise we need to inject one.
|
|
124
|
+
*
|
|
125
|
+
* Returns: Map<targetModelName, Array<{ fkField, relationField }>>
|
|
126
|
+
*/
|
|
127
|
+
function buildMissingBackRefs(
|
|
128
|
+
allModels: any[],
|
|
129
|
+
relationMap: Map<string, string | null>
|
|
130
|
+
): Map<string, string[]> {
|
|
131
|
+
// Build set of existing belongsTo relations: "ChildModel->ParentModel"
|
|
132
|
+
const existingBelongsTo = new Set<string>();
|
|
133
|
+
for (const model of allModels) {
|
|
134
|
+
const relationships = Array.isArray(model.relationships)
|
|
135
|
+
? model.relationships
|
|
136
|
+
: Object.values(model.relationships || {});
|
|
137
|
+
for (const rel of relationships as any[]) {
|
|
138
|
+
if (rel.type === 'belongsTo') {
|
|
139
|
+
existingBelongsTo.add(`${model.name}->${rel.target}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// For each hasMany/hasOne, check if the target has a belongsTo back
|
|
145
|
+
const backRefs = new Map<string, string[]>();
|
|
146
|
+
|
|
147
|
+
for (const model of allModels) {
|
|
148
|
+
const relationships = Array.isArray(model.relationships)
|
|
149
|
+
? model.relationships
|
|
150
|
+
: Object.values(model.relationships || {});
|
|
151
|
+
for (const rel of relationships as any[]) {
|
|
152
|
+
if (rel.type !== 'hasMany' && rel.type !== 'hasOne') continue;
|
|
153
|
+
|
|
154
|
+
const target = rel.target;
|
|
155
|
+
const backKey = `${target}->${model.name}`;
|
|
156
|
+
|
|
157
|
+
if (!existingBelongsTo.has(backKey)) {
|
|
158
|
+
// Target model is missing a belongsTo for this relation — inject one
|
|
159
|
+
const fieldName = rel.name || (rel.type === 'hasMany'
|
|
160
|
+
? pluralize(target.toLowerCase())
|
|
161
|
+
: target.toLowerCase());
|
|
162
|
+
// Always use the parent's canonical relation name
|
|
163
|
+
const relName = `${model.name}_${fieldName}`;
|
|
164
|
+
|
|
165
|
+
// Check if the parent model has multiple hasMany/hasOne relations to the same target
|
|
166
|
+
// If so, include the field name in the FK to avoid collisions
|
|
167
|
+
const parentRelsToSameTarget = relationships.filter((r: any) =>
|
|
168
|
+
r.target === target && (r.type === 'hasMany' || r.type === 'hasOne')
|
|
169
|
+
);
|
|
170
|
+
const needsFieldInFk = parentRelsToSameTarget.length > 1;
|
|
171
|
+
const fkSuffix = needsFieldInFk
|
|
172
|
+
? camelToSnake(fieldName) + '_id'
|
|
173
|
+
: camelToSnake(model.name.charAt(0).toLowerCase() + model.name.slice(1)) + '_id';
|
|
174
|
+
const fkName = fkSuffix;
|
|
175
|
+
const fkPadding = ' '.repeat(Math.max(1, 15 - fkName.length));
|
|
176
|
+
const refFieldName = needsFieldInFk
|
|
177
|
+
? fieldName + model.name
|
|
178
|
+
: model.name.charAt(0).toLowerCase() + model.name.slice(1);
|
|
179
|
+
const refPadding = ' '.repeat(Math.max(1, 15 - refFieldName.length));
|
|
180
|
+
|
|
181
|
+
let relDef = `${refFieldName}${refPadding}${model.name}`;
|
|
182
|
+
relDef += ` @relation("${relName}", fields: [${fkName}], references: [id])`;
|
|
183
|
+
|
|
184
|
+
if (!backRefs.has(target)) {
|
|
185
|
+
backRefs.set(target, []);
|
|
186
|
+
}
|
|
187
|
+
const uniqueModifier = rel.type === 'hasOne' ? ' @unique' : '';
|
|
188
|
+
backRefs.get(target)!.push(`${fkName}${fkPadding}String${uniqueModifier}`);
|
|
189
|
+
backRefs.get(target)!.push(relDef);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Also handle the reverse: belongsTo without matching hasMany/hasOne on parent
|
|
195
|
+
// Build set of existing hasMany/hasOne: "ParentModel->ChildModel"
|
|
196
|
+
const existingHasRelation = new Set<string>();
|
|
197
|
+
for (const model of allModels) {
|
|
198
|
+
const rels = Array.isArray(model.relationships)
|
|
199
|
+
? model.relationships
|
|
200
|
+
: Object.values(model.relationships || {});
|
|
201
|
+
for (const rel of rels as any[]) {
|
|
202
|
+
if (rel.type === 'hasMany' || rel.type === 'hasOne') {
|
|
203
|
+
existingHasRelation.add(`${model.name}->${rel.target}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
for (const model of allModels) {
|
|
209
|
+
const relationships = Array.isArray(model.relationships)
|
|
210
|
+
? model.relationships
|
|
211
|
+
: Object.values(model.relationships || {});
|
|
212
|
+
for (const rel of relationships as any[]) {
|
|
213
|
+
if (rel.type !== 'belongsTo') continue;
|
|
214
|
+
|
|
215
|
+
const parent = rel.target;
|
|
216
|
+
const forwardKey = `${parent}->${model.name}`;
|
|
217
|
+
|
|
218
|
+
if (!existingHasRelation.has(forwardKey)) {
|
|
219
|
+
// Parent model is missing a hasMany/hasOne for this belongsTo — inject array
|
|
220
|
+
const fieldName = rel.name || parent.toLowerCase();
|
|
221
|
+
const relName = getRelationName(model.name, fieldName, parent, relationMap);
|
|
222
|
+
const arrayFieldName = pluralize(model.name.charAt(0).toLowerCase() + model.name.slice(1));
|
|
223
|
+
const padding = ' '.repeat(Math.max(1, 15 - arrayFieldName.length));
|
|
224
|
+
|
|
225
|
+
if (!backRefs.has(parent)) {
|
|
226
|
+
backRefs.set(parent, []);
|
|
227
|
+
}
|
|
228
|
+
backRefs.get(parent)!.push(`${arrayFieldName}${padding}${model.name}[] @relation("${relName}")`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return backRefs;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Get the relation name for a given source model + field.
|
|
238
|
+
* ALWAYS returns a name — Prisma accepts explicit names even when not strictly required,
|
|
239
|
+
* and it avoids all ambiguity issues with complex schemas.
|
|
240
|
+
*
|
|
241
|
+
* For hasMany/hasOne: name = "SourceModel_fieldName" (canonical, parent-side)
|
|
242
|
+
* For belongsTo: looks up the matching parent-side name from the relation map
|
|
243
|
+
*/
|
|
244
|
+
function getRelationName(
|
|
245
|
+
sourceModel: string,
|
|
246
|
+
fieldName: string,
|
|
247
|
+
target: string,
|
|
248
|
+
relationMap: Map<string, string | null>
|
|
249
|
+
): string {
|
|
250
|
+
// Check if there's a mapped name (for belongsTo matching a parent's hasMany)
|
|
251
|
+
const mapped = relationMap.get(`${sourceModel}.${fieldName}`);
|
|
252
|
+
if (mapped) return mapped;
|
|
253
|
+
|
|
254
|
+
// Default: use canonical naming
|
|
255
|
+
return `${sourceModel}_${fieldName}`;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Generate Prisma schema header
|
|
260
|
+
*/
|
|
261
|
+
function generateHeader(implType: any): string {
|
|
262
|
+
const provider = implType?.configuration?.orm?.provider || 'sqlite';
|
|
263
|
+
|
|
264
|
+
return `// Generated Prisma schema from SpecVerse specification
|
|
265
|
+
// This is your Prisma schema file
|
|
266
|
+
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
|
267
|
+
|
|
268
|
+
generator client {
|
|
269
|
+
provider = "prisma-client-js"
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
datasource db {
|
|
273
|
+
provider = "${provider}"
|
|
274
|
+
url = ${provider === 'sqlite' ? '"file:./dev.db"' : 'env("DATABASE_URL")'}
|
|
275
|
+
}`;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Generate a single model schema
|
|
280
|
+
*/
|
|
281
|
+
function generateModelSchema(
|
|
282
|
+
model: any,
|
|
283
|
+
relationMap: Map<string, string | null>,
|
|
284
|
+
backRefs: Map<string, string[]>,
|
|
285
|
+
hasOneTargets: Set<string>,
|
|
286
|
+
allModels?: any[]
|
|
287
|
+
): string {
|
|
288
|
+
const modelName = model.name;
|
|
289
|
+
let schema = `model ${modelName} {\n`;
|
|
290
|
+
|
|
291
|
+
// Convert attributes from object to array if needed
|
|
292
|
+
const attributes = Array.isArray(model.attributes)
|
|
293
|
+
? model.attributes
|
|
294
|
+
: Object.values(model.attributes || {});
|
|
295
|
+
|
|
296
|
+
// Convert relationships from object to array if needed
|
|
297
|
+
const relationships = Array.isArray(model.relationships)
|
|
298
|
+
? model.relationships
|
|
299
|
+
: Object.values(model.relationships || {});
|
|
300
|
+
|
|
301
|
+
// Add attributes
|
|
302
|
+
attributes.forEach((attr: any) => {
|
|
303
|
+
schema += ` ${generateField(attr, model)}\n`;
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// Add lifecycle status fields (if model has lifecycles)
|
|
307
|
+
const rawLifecycles = model.lifecycles || [];
|
|
308
|
+
const lifecycleList = Array.isArray(rawLifecycles)
|
|
309
|
+
? rawLifecycles
|
|
310
|
+
: Object.entries(rawLifecycles).map(([name, lc]: [string, any]) => ({ name, ...(typeof lc === 'object' ? lc : {}) }));
|
|
311
|
+
for (const lifecycle of lifecycleList) {
|
|
312
|
+
const fieldName = lifecycle.name || 'status';
|
|
313
|
+
const exists = attributes.some((a: any) => a.name === fieldName);
|
|
314
|
+
if (!exists && lifecycle.states?.length > 0) {
|
|
315
|
+
const defaultState = lifecycle.states[0];
|
|
316
|
+
const padding = ' '.repeat(Math.max(1, 15 - fieldName.length));
|
|
317
|
+
schema += ` ${fieldName}${padding}String @default("${defaultState}")\n`;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Add relationships
|
|
322
|
+
relationships.forEach((rel: any) => {
|
|
323
|
+
const fields = generateRelationship(rel, model, relationMap, hasOneTargets, allModels);
|
|
324
|
+
fields.forEach(field => {
|
|
325
|
+
schema += ` ${field}\n`;
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// Add auto-generated back-references (for hasMany/hasOne without corresponding belongsTo)
|
|
330
|
+
const modelBackRefs = backRefs.get(modelName);
|
|
331
|
+
if (modelBackRefs) {
|
|
332
|
+
for (const line of modelBackRefs) {
|
|
333
|
+
schema += ` ${line}\n`;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
schema += `}`;
|
|
338
|
+
|
|
339
|
+
return schema;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Generate a field definition
|
|
344
|
+
*/
|
|
345
|
+
function generateField(attr: any, model: any): string {
|
|
346
|
+
const name = attr.name;
|
|
347
|
+
const prismaType = mapTypeToPrisma(attr.type, attr.dbMapping?.columnType);
|
|
348
|
+
const isOptional = !(attr.required || attr.constraints?.required);
|
|
349
|
+
const isUnique = attr.unique || attr.constraints?.unique;
|
|
350
|
+
const metadata = model?.metadata || {};
|
|
351
|
+
|
|
352
|
+
let modifiers = '';
|
|
353
|
+
|
|
354
|
+
// Primary key detection
|
|
355
|
+
if (name.toLowerCase() === 'id') {
|
|
356
|
+
modifiers += ' @id';
|
|
357
|
+
if (metadata.id === 'uuid' || metadata.id === 'auto' || prismaType === 'String') {
|
|
358
|
+
modifiers += ' @default(uuid())';
|
|
359
|
+
} else if (metadata.id === 'integer' || prismaType === 'Int') {
|
|
360
|
+
modifiers += ' @default(autoincrement())';
|
|
361
|
+
}
|
|
362
|
+
} else if (isUnique) {
|
|
363
|
+
modifiers += ' @unique';
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Auto-generated fields (auto=now, auto=uuid, etc.)
|
|
367
|
+
if (attr.auto) {
|
|
368
|
+
const autoValue = typeof attr.auto === 'string' ? attr.auto.toLowerCase() : attr.auto;
|
|
369
|
+
if (autoValue === 'now' || autoValue === true) {
|
|
370
|
+
if (prismaType === 'DateTime') {
|
|
371
|
+
modifiers += ' @default(now())';
|
|
372
|
+
}
|
|
373
|
+
} else if (autoValue === 'uuid' || autoValue === 'uuid4') {
|
|
374
|
+
if (prismaType === 'String') {
|
|
375
|
+
modifiers += ' @default(uuid())';
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
} else {
|
|
379
|
+
// Workaround: Handle common auto-timestamp fields (parser not preserving auto directive)
|
|
380
|
+
const autoTimestampFields = ['joinedAt', 'registeredAt', 'enrolledAt', 'startedAt', 'completedAt', 'verifiedAt'];
|
|
381
|
+
if (autoTimestampFields.includes(name) && prismaType === 'DateTime') {
|
|
382
|
+
modifiers += ' @default(now())';
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Audit fields
|
|
387
|
+
if (metadata.audit && isAuditField(name)) {
|
|
388
|
+
if (name === 'createdAt' || name === 'created_at') {
|
|
389
|
+
if (!attr.auto) { // Don't override if already handled by auto
|
|
390
|
+
modifiers += ' @default(now())';
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
if (name === 'updatedAt' || name === 'updated_at') {
|
|
394
|
+
modifiers += ' @updatedAt';
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Soft delete fields
|
|
399
|
+
if (metadata.softDelete && isSoftDeleteField(name)) {
|
|
400
|
+
if (name === 'isDeleted' || name === 'is_deleted') {
|
|
401
|
+
modifiers += ' @default(false)';
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Version field
|
|
406
|
+
if (metadata.version && isVersionField(name)) {
|
|
407
|
+
modifiers += ' @default(0)';
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Database-specific type annotations
|
|
411
|
+
if (attr.dbMapping?.columnType === 'TEXT') {
|
|
412
|
+
modifiers += ' @db.Text';
|
|
413
|
+
} else if (attr.dbMapping?.columnType?.startsWith('VARCHAR')) {
|
|
414
|
+
const match = attr.dbMapping.columnType.match(/VARCHAR\((\d+)\)/);
|
|
415
|
+
if (match) {
|
|
416
|
+
modifiers += ` @db.VarChar(${match[1]})`;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const padding = ' '.repeat(Math.max(1, 15 - name.length));
|
|
421
|
+
const typeStr = isOptional ? `${prismaType}?` : prismaType;
|
|
422
|
+
|
|
423
|
+
return `${name}${padding}${typeStr}${modifiers}`;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Generate relationship fields
|
|
428
|
+
*/
|
|
429
|
+
function generateRelationship(rel: any, model: any, relationMap: Map<string, string | null>, hasOneTargets: Set<string>, allModels?: any[]): string[] {
|
|
430
|
+
const fields: string[] = [];
|
|
431
|
+
const name = rel.name || rel.target.toLowerCase();
|
|
432
|
+
const padding = ' '.repeat(Math.max(1, 15 - name.length));
|
|
433
|
+
const isOptional = rel.optional || false;
|
|
434
|
+
|
|
435
|
+
// Always add explicit relation names for Prisma — avoids all ambiguity
|
|
436
|
+
const relName = getRelationName(model.name, name, rel.target, relationMap);
|
|
437
|
+
const relAnnotation = ` @relation("${relName}")`;
|
|
438
|
+
|
|
439
|
+
switch (rel.type) {
|
|
440
|
+
case 'belongsTo':
|
|
441
|
+
// Foreign key field — use snake_case for the FK column name
|
|
442
|
+
const fkBase = rel.foreignKey || camelToSnake(name) + '_id';
|
|
443
|
+
const fkPadding = ' '.repeat(Math.max(1, 15 - fkBase.length));
|
|
444
|
+
// Add @unique if the parent has a hasOne relation pointing to this model
|
|
445
|
+
const isUniqueFK = hasOneTargets.has(`${rel.target}->${model.name}`);
|
|
446
|
+
// FK type must match the target model's ID type
|
|
447
|
+
let fkType = 'String';
|
|
448
|
+
if (allModels) {
|
|
449
|
+
const targetModel = allModels.find((m: any) => m.name === rel.target);
|
|
450
|
+
if (targetModel) {
|
|
451
|
+
const idAttr = (Array.isArray(targetModel.attributes) ? targetModel.attributes : Object.values(targetModel.attributes || {}))
|
|
452
|
+
.find((a: any) => a.name === 'id');
|
|
453
|
+
if (idAttr) {
|
|
454
|
+
const idType = idAttr.type || 'String';
|
|
455
|
+
fkType = mapTypeToPrisma(idType);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
fields.push(`${fkBase}${fkPadding}${fkType}${isOptional ? '?' : ''}${isUniqueFK ? ' @unique' : ''}`);
|
|
460
|
+
|
|
461
|
+
// Relation field with @relation including fields/references + optional name
|
|
462
|
+
let relationDef = `${name}${padding}${rel.target}${isOptional ? '?' : ''}`;
|
|
463
|
+
relationDef += ` @relation(`;
|
|
464
|
+
if (relName) {
|
|
465
|
+
relationDef += `"${relName}", `;
|
|
466
|
+
}
|
|
467
|
+
relationDef += `fields: [${fkBase}], references: [id]`;
|
|
468
|
+
|
|
469
|
+
if (rel.onDelete) {
|
|
470
|
+
relationDef += `, onDelete: ${rel.onDelete}`;
|
|
471
|
+
}
|
|
472
|
+
if (rel.onUpdate) {
|
|
473
|
+
relationDef += `, onUpdate: ${rel.onUpdate}`;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
relationDef += ')';
|
|
477
|
+
fields.push(relationDef);
|
|
478
|
+
break;
|
|
479
|
+
|
|
480
|
+
case 'hasOne':
|
|
481
|
+
// Prisma requires hasOne relation fields to be optional
|
|
482
|
+
fields.push(`${name}${padding}${rel.target}?${relAnnotation}`);
|
|
483
|
+
break;
|
|
484
|
+
|
|
485
|
+
case 'hasMany':
|
|
486
|
+
const pluralName = rel.name || pluralize(rel.target.toLowerCase());
|
|
487
|
+
const manyPadding = ' '.repeat(Math.max(1, 15 - pluralName.length));
|
|
488
|
+
fields.push(`${pluralName}${manyPadding}${rel.target}[]${relAnnotation}`);
|
|
489
|
+
break;
|
|
490
|
+
|
|
491
|
+
case 'manyToMany':
|
|
492
|
+
const manyName = rel.name || pluralize(rel.target.toLowerCase());
|
|
493
|
+
const m2mPadding = ' '.repeat(Math.max(1, 15 - manyName.length));
|
|
494
|
+
fields.push(`${manyName}${m2mPadding}${rel.target}[]${relAnnotation}`);
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return fields;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Convert camelCase to snake_case
|
|
503
|
+
*/
|
|
504
|
+
function camelToSnake(str: string): string {
|
|
505
|
+
return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Map SpecVerse type to Prisma type
|
|
510
|
+
*/
|
|
511
|
+
function mapTypeToPrisma(type: string, dbType?: string): string {
|
|
512
|
+
// Use database type if provided
|
|
513
|
+
if (dbType) {
|
|
514
|
+
if (dbType.startsWith('VARCHAR') || dbType === 'TEXT') return 'String';
|
|
515
|
+
|
|
516
|
+
const typeMap: Record<string, string> = {
|
|
517
|
+
'INTEGER': 'Int',
|
|
518
|
+
'BIGINT': 'BigInt',
|
|
519
|
+
'DECIMAL': 'Decimal',
|
|
520
|
+
'BOOLEAN': 'Boolean',
|
|
521
|
+
'DATE': 'DateTime',
|
|
522
|
+
'TIMESTAMP': 'DateTime',
|
|
523
|
+
'UUID': 'String',
|
|
524
|
+
'JSONB': 'Json',
|
|
525
|
+
'JSON': 'Json',
|
|
526
|
+
'FLOAT': 'Float'
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
if (typeMap[dbType]) return typeMap[dbType];
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Infer from SpecVerse type
|
|
533
|
+
const typeLower = type.toLowerCase();
|
|
534
|
+
|
|
535
|
+
if (typeLower.includes('string') || typeLower.includes('text')) return 'String';
|
|
536
|
+
if (typeLower.includes('int')) return 'Int';
|
|
537
|
+
if (typeLower.includes('bool')) return 'Boolean';
|
|
538
|
+
if (typeLower.includes('date') || typeLower.includes('time')) return 'DateTime';
|
|
539
|
+
if (typeLower.includes('float') || typeLower.includes('decimal')) return 'Float';
|
|
540
|
+
if (typeLower.includes('json')) return 'Json';
|
|
541
|
+
|
|
542
|
+
return 'String'; // default
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Helper functions
|
|
547
|
+
*/
|
|
548
|
+
function isAuditField(name: string): boolean {
|
|
549
|
+
const auditFields = ['createdAt', 'updatedAt', 'createdBy', 'updatedBy',
|
|
550
|
+
'created_at', 'updated_at', 'created_by', 'updated_by'];
|
|
551
|
+
return auditFields.includes(name);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
function isSoftDeleteField(name: string): boolean {
|
|
555
|
+
const softDeleteFields = ['deletedAt', 'isDeleted', 'deleted_at', 'is_deleted'];
|
|
556
|
+
return softDeleteFields.includes(name);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
function isVersionField(name: string): boolean {
|
|
560
|
+
const versionFields = ['version', 'versionNumber', 'version_number'];
|
|
561
|
+
return versionFields.includes(name);
|
|
562
|
+
}
|
|
563
|
+
|