@buenojs/bueno 0.8.5 → 0.8.7
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/.claude/settings.local.json +9 -0
- package/README.md +259 -15
- package/dist/cache/index.d.ts +187 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cli/bin.d.ts +8 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +484 -156
- package/dist/cli/commands/add-frontend.d.ts +7 -0
- package/dist/cli/commands/add-frontend.d.ts.map +1 -0
- package/dist/cli/commands/build.d.ts +7 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/dev.d.ts +7 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/generate.d.ts +7 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/help.d.ts +7 -0
- package/dist/cli/commands/help.d.ts.map +1 -0
- package/dist/cli/commands/index.d.ts +59 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/migration.d.ts +7 -0
- package/dist/cli/commands/migration.d.ts.map +1 -0
- package/dist/cli/commands/new.d.ts +7 -0
- package/dist/cli/commands/new.d.ts.map +1 -0
- package/dist/cli/commands/start.d.ts +7 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/core/args.d.ts +61 -0
- package/dist/cli/core/args.d.ts.map +1 -0
- package/dist/cli/core/console.d.ts +135 -0
- package/dist/cli/core/console.d.ts.map +1 -0
- package/dist/cli/core/index.d.ts +10 -0
- package/dist/cli/core/index.d.ts.map +1 -0
- package/dist/cli/core/prompt.d.ts +63 -0
- package/dist/cli/core/prompt.d.ts.map +1 -0
- package/dist/cli/core/spinner.d.ts +111 -0
- package/dist/cli/core/spinner.d.ts.map +1 -0
- package/dist/cli/index.d.ts +47 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/templates/database/index.d.ts +24 -0
- package/dist/cli/templates/database/index.d.ts.map +1 -0
- package/dist/cli/templates/database/mysql.d.ts +6 -0
- package/dist/cli/templates/database/mysql.d.ts.map +1 -0
- package/dist/cli/templates/database/none.d.ts +8 -0
- package/dist/cli/templates/database/none.d.ts.map +1 -0
- package/dist/cli/templates/database/postgresql.d.ts +6 -0
- package/dist/cli/templates/database/postgresql.d.ts.map +1 -0
- package/dist/cli/templates/database/sqlite.d.ts +6 -0
- package/dist/cli/templates/database/sqlite.d.ts.map +1 -0
- package/dist/cli/templates/deploy.d.ts +41 -0
- package/dist/cli/templates/deploy.d.ts.map +1 -0
- package/dist/cli/templates/docker.d.ts +30 -0
- package/dist/cli/templates/docker.d.ts.map +1 -0
- package/dist/cli/templates/frontend/index.d.ts +25 -0
- package/dist/cli/templates/frontend/index.d.ts.map +1 -0
- package/dist/cli/templates/frontend/none.d.ts +8 -0
- package/dist/cli/templates/frontend/none.d.ts.map +1 -0
- package/dist/cli/templates/frontend/react.d.ts +6 -0
- package/dist/cli/templates/frontend/react.d.ts.map +1 -0
- package/dist/cli/templates/frontend/solid.d.ts +6 -0
- package/dist/cli/templates/frontend/solid.d.ts.map +1 -0
- package/dist/cli/templates/frontend/svelte.d.ts +6 -0
- package/dist/cli/templates/frontend/svelte.d.ts.map +1 -0
- package/dist/cli/templates/frontend/vue.d.ts +6 -0
- package/dist/cli/templates/frontend/vue.d.ts.map +1 -0
- package/dist/cli/templates/generators/index.d.ts +29 -0
- package/dist/cli/templates/generators/index.d.ts.map +1 -0
- package/dist/cli/templates/generators/types.d.ts +32 -0
- package/dist/cli/templates/generators/types.d.ts.map +1 -0
- package/dist/cli/templates/index.d.ts +12 -0
- package/dist/cli/templates/index.d.ts.map +1 -0
- package/dist/cli/templates/project/api.d.ts +6 -0
- package/dist/cli/templates/project/api.d.ts.map +1 -0
- package/dist/cli/templates/project/default.d.ts +6 -0
- package/dist/cli/templates/project/default.d.ts.map +1 -0
- package/dist/cli/templates/project/fullstack.d.ts +14 -0
- package/dist/cli/templates/project/fullstack.d.ts.map +1 -0
- package/dist/cli/templates/project/index.d.ts +26 -0
- package/dist/cli/templates/project/index.d.ts.map +1 -0
- package/dist/cli/templates/project/minimal.d.ts +6 -0
- package/dist/cli/templates/project/minimal.d.ts.map +1 -0
- package/dist/cli/templates/project/types.d.ts +80 -0
- package/dist/cli/templates/project/types.d.ts.map +1 -0
- package/dist/cli/templates/project/website.d.ts +8 -0
- package/dist/cli/templates/project/website.d.ts.map +1 -0
- package/dist/cli/utils/fs.d.ts +137 -0
- package/dist/cli/utils/fs.d.ts.map +1 -0
- package/dist/cli/utils/index.d.ts +9 -0
- package/dist/cli/utils/index.d.ts.map +1 -0
- package/dist/cli/utils/strings.d.ts +86 -0
- package/dist/cli/utils/strings.d.ts.map +1 -0
- package/dist/cli/utils/version.d.ts +15 -0
- package/dist/cli/utils/version.d.ts.map +1 -0
- package/dist/config/env-validation.d.ts +49 -0
- package/dist/config/env-validation.d.ts.map +1 -0
- package/dist/config/env.d.ts +167 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/index.d.ts +168 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/loader.d.ts +81 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/merge.d.ts +66 -0
- package/dist/config/merge.d.ts.map +1 -0
- package/dist/config/types.d.ts +322 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/validation.d.ts +100 -0
- package/dist/config/validation.d.ts.map +1 -0
- package/dist/container/forward-ref.d.ts +116 -0
- package/dist/container/forward-ref.d.ts.map +1 -0
- package/dist/container/index.d.ts +95 -0
- package/dist/container/index.d.ts.map +1 -0
- package/dist/container/index.js +26 -3
- package/dist/context/index.d.ts +143 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/database/index.d.ts +219 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/migrations/index.d.ts +146 -0
- package/dist/database/migrations/index.d.ts.map +1 -0
- package/dist/database/orm/builder.d.ts +122 -0
- package/dist/database/orm/builder.d.ts.map +1 -0
- package/dist/database/orm/casts/index.d.ts +16 -0
- package/dist/database/orm/casts/index.d.ts.map +1 -0
- package/dist/database/orm/casts/types.d.ts +16 -0
- package/dist/database/orm/casts/types.d.ts.map +1 -0
- package/dist/database/orm/compiler.d.ts +90 -0
- package/dist/database/orm/compiler.d.ts.map +1 -0
- package/dist/database/orm/hooks/index.d.ts +53 -0
- package/dist/database/orm/hooks/index.d.ts.map +1 -0
- package/dist/database/orm/index.d.ts +21 -0
- package/dist/database/orm/index.d.ts.map +1 -0
- package/dist/database/orm/model-registry.d.ts +33 -0
- package/dist/database/orm/model-registry.d.ts.map +1 -0
- package/dist/database/orm/model.d.ts +245 -0
- package/dist/database/orm/model.d.ts.map +1 -0
- package/dist/database/orm/relationships/base.d.ts +69 -0
- package/dist/database/orm/relationships/base.d.ts.map +1 -0
- package/dist/database/orm/relationships/belongs-to-many.d.ts +47 -0
- package/dist/database/orm/relationships/belongs-to-many.d.ts.map +1 -0
- package/dist/database/orm/relationships/belongs-to.d.ts +17 -0
- package/dist/database/orm/relationships/belongs-to.d.ts.map +1 -0
- package/dist/database/orm/relationships/has-many.d.ts +14 -0
- package/dist/database/orm/relationships/has-many.d.ts.map +1 -0
- package/dist/database/orm/relationships/has-one.d.ts +14 -0
- package/dist/database/orm/relationships/has-one.d.ts.map +1 -0
- package/dist/database/orm/relationships/index.d.ts +10 -0
- package/dist/database/orm/relationships/index.d.ts.map +1 -0
- package/dist/database/orm/scopes/index.d.ts +36 -0
- package/dist/database/orm/scopes/index.d.ts.map +1 -0
- package/dist/database/schema/index.d.ts +155 -0
- package/dist/database/schema/index.d.ts.map +1 -0
- package/dist/events/__tests__/event-system.test.d.ts +2 -0
- package/dist/events/__tests__/event-system.test.d.ts.map +1 -0
- package/dist/events/config.d.ts +16 -0
- package/dist/events/config.d.ts.map +1 -0
- package/dist/events/example-usage.d.ts +12 -0
- package/dist/events/example-usage.d.ts.map +1 -0
- package/dist/events/index.d.ts +27 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/manager.d.ts +33 -0
- package/dist/events/manager.d.ts.map +1 -0
- package/dist/events/registry.d.ts +31 -0
- package/dist/events/registry.d.ts.map +1 -0
- package/dist/events/types.d.ts +105 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/frontend/api-routes.d.ts +189 -0
- package/dist/frontend/api-routes.d.ts.map +1 -0
- package/dist/frontend/bundler.d.ts +99 -0
- package/dist/frontend/bundler.d.ts.map +1 -0
- package/dist/frontend/console-client.d.ts +11 -0
- package/dist/frontend/console-client.d.ts.map +1 -0
- package/dist/frontend/console-stream.d.ts +138 -0
- package/dist/frontend/console-stream.d.ts.map +1 -0
- package/dist/frontend/dev-server.d.ts +174 -0
- package/dist/frontend/dev-server.d.ts.map +1 -0
- package/dist/frontend/file-router.d.ts +170 -0
- package/dist/frontend/file-router.d.ts.map +1 -0
- package/dist/frontend/frameworks/index.d.ts +41 -0
- package/dist/frontend/frameworks/index.d.ts.map +1 -0
- package/dist/frontend/frameworks/react.d.ts +32 -0
- package/dist/frontend/frameworks/react.d.ts.map +1 -0
- package/dist/frontend/frameworks/solid.d.ts +42 -0
- package/dist/frontend/frameworks/solid.d.ts.map +1 -0
- package/dist/frontend/frameworks/svelte.d.ts +57 -0
- package/dist/frontend/frameworks/svelte.d.ts.map +1 -0
- package/dist/frontend/frameworks/vue.d.ts +36 -0
- package/dist/frontend/frameworks/vue.d.ts.map +1 -0
- package/dist/frontend/hmr-client.d.ts +22 -0
- package/dist/frontend/hmr-client.d.ts.map +1 -0
- package/dist/frontend/hmr.d.ts +185 -0
- package/dist/frontend/hmr.d.ts.map +1 -0
- package/dist/frontend/index.d.ts +34 -0
- package/dist/frontend/index.d.ts.map +1 -0
- package/dist/frontend/islands.d.ts +135 -0
- package/dist/frontend/islands.d.ts.map +1 -0
- package/dist/frontend/isr.d.ts +143 -0
- package/dist/frontend/isr.d.ts.map +1 -0
- package/dist/frontend/layout.d.ts +140 -0
- package/dist/frontend/layout.d.ts.map +1 -0
- package/dist/frontend/ssr/react.d.ts +118 -0
- package/dist/frontend/ssr/react.d.ts.map +1 -0
- package/dist/frontend/ssr/solid.d.ts +141 -0
- package/dist/frontend/ssr/solid.d.ts.map +1 -0
- package/dist/frontend/ssr/svelte.d.ts +158 -0
- package/dist/frontend/ssr/svelte.d.ts.map +1 -0
- package/dist/frontend/ssr/vue.d.ts +161 -0
- package/dist/frontend/ssr/vue.d.ts.map +1 -0
- package/dist/frontend/ssr.d.ts +147 -0
- package/dist/frontend/ssr.d.ts.map +1 -0
- package/dist/frontend/types.d.ts +1902 -0
- package/dist/frontend/types.d.ts.map +1 -0
- package/dist/graphql/built-in-engine.d.ts +36 -0
- package/dist/graphql/built-in-engine.d.ts.map +1 -0
- package/dist/graphql/context-builder.d.ts +44 -0
- package/dist/graphql/context-builder.d.ts.map +1 -0
- package/dist/graphql/decorators.d.ts +162 -0
- package/dist/graphql/decorators.d.ts.map +1 -0
- package/dist/graphql/execution-pipeline.d.ts +67 -0
- package/dist/graphql/execution-pipeline.d.ts.map +1 -0
- package/dist/graphql/graphql-module.d.ts +70 -0
- package/dist/graphql/graphql-module.d.ts.map +1 -0
- package/dist/graphql/index.d.ts +48 -0
- package/dist/graphql/index.d.ts.map +1 -0
- package/dist/graphql/index.js +2156 -0
- package/dist/graphql/metadata.d.ts +37 -0
- package/dist/graphql/metadata.d.ts.map +1 -0
- package/dist/graphql/schema-builder.d.ts +34 -0
- package/dist/graphql/schema-builder.d.ts.map +1 -0
- package/dist/graphql/subscription-handler.d.ts +47 -0
- package/dist/graphql/subscription-handler.d.ts.map +1 -0
- package/dist/graphql/types.d.ts +252 -0
- package/dist/graphql/types.d.ts.map +1 -0
- package/dist/health/index.d.ts +176 -0
- package/dist/health/index.d.ts.map +1 -0
- package/dist/i18n/engine.d.ts +105 -0
- package/dist/i18n/engine.d.ts.map +1 -0
- package/dist/i18n/index.d.ts +13 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/loader.d.ts +79 -0
- package/dist/i18n/loader.d.ts.map +1 -0
- package/dist/i18n/middleware.d.ts +96 -0
- package/dist/i18n/middleware.d.ts.map +1 -0
- package/dist/i18n/negotiator.d.ts +84 -0
- package/dist/i18n/negotiator.d.ts.map +1 -0
- package/dist/i18n/types.d.ts +129 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +520 -434
- package/dist/jobs/drivers/memory.d.ts +38 -0
- package/dist/jobs/drivers/memory.d.ts.map +1 -0
- package/dist/jobs/drivers/redis.d.ts +34 -0
- package/dist/jobs/drivers/redis.d.ts.map +1 -0
- package/dist/jobs/index.d.ts +12 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/queue.d.ts +93 -0
- package/dist/jobs/queue.d.ts.map +1 -0
- package/dist/jobs/types.d.ts +193 -0
- package/dist/jobs/types.d.ts.map +1 -0
- package/dist/jobs/worker.d.ts +91 -0
- package/dist/jobs/worker.d.ts.map +1 -0
- package/dist/lock/index.d.ts +141 -0
- package/dist/lock/index.d.ts.map +1 -0
- package/dist/logger/index.d.ts +156 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/transports/index.d.ts +371 -0
- package/dist/logger/transports/index.d.ts.map +1 -0
- package/dist/metrics/index.d.ts +163 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/middleware/built-in.d.ts +50 -0
- package/dist/middleware/built-in.d.ts.map +1 -0
- package/dist/middleware/index.d.ts +40 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/migrations/index.d.ts +10 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/modules/filters.d.ts +150 -0
- package/dist/modules/filters.d.ts.map +1 -0
- package/dist/modules/guards.d.ts +188 -0
- package/dist/modules/guards.d.ts.map +1 -0
- package/dist/modules/index.d.ts +266 -0
- package/dist/modules/index.d.ts.map +1 -0
- package/dist/modules/index.js +514 -449
- package/dist/modules/interceptors.d.ts +242 -0
- package/dist/modules/interceptors.d.ts.map +1 -0
- package/dist/modules/lazy.d.ts +187 -0
- package/dist/modules/lazy.d.ts.map +1 -0
- package/dist/modules/lifecycle.d.ts +221 -0
- package/dist/modules/lifecycle.d.ts.map +1 -0
- package/dist/modules/metadata.d.ts +32 -0
- package/dist/modules/metadata.d.ts.map +1 -0
- package/dist/modules/pipes.d.ts +287 -0
- package/dist/modules/pipes.d.ts.map +1 -0
- package/dist/notification/channels/base.d.ts +32 -0
- package/dist/notification/channels/base.d.ts.map +1 -0
- package/dist/notification/channels/email.d.ts +37 -0
- package/dist/notification/channels/email.d.ts.map +1 -0
- package/dist/notification/channels/push.d.ts +37 -0
- package/dist/notification/channels/push.d.ts.map +1 -0
- package/dist/notification/channels/sms.d.ts +37 -0
- package/dist/notification/channels/sms.d.ts.map +1 -0
- package/dist/notification/channels/whatsapp.d.ts +37 -0
- package/dist/notification/channels/whatsapp.d.ts.map +1 -0
- package/dist/notification/index.d.ts +15 -0
- package/dist/notification/index.d.ts.map +1 -0
- package/dist/notification/service.d.ts +100 -0
- package/dist/notification/service.d.ts.map +1 -0
- package/dist/notification/types.d.ts +253 -0
- package/dist/notification/types.d.ts.map +1 -0
- package/dist/observability/__tests__/observability.test.d.ts +2 -0
- package/dist/observability/__tests__/observability.test.d.ts.map +1 -0
- package/dist/observability/breadcrumbs.d.ts +48 -0
- package/dist/observability/breadcrumbs.d.ts.map +1 -0
- package/dist/observability/index.d.ts +95 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/interceptor.d.ts +19 -0
- package/dist/observability/interceptor.d.ts.map +1 -0
- package/dist/observability/service.d.ts +101 -0
- package/dist/observability/service.d.ts.map +1 -0
- package/dist/observability/trace.d.ts +21 -0
- package/dist/observability/trace.d.ts.map +1 -0
- package/dist/observability/types.d.ts +172 -0
- package/dist/observability/types.d.ts.map +1 -0
- package/dist/openapi/__tests__/decorators.test.d.ts +2 -0
- package/dist/openapi/__tests__/decorators.test.d.ts.map +1 -0
- package/dist/openapi/__tests__/document-builder.test.d.ts +2 -0
- package/dist/openapi/__tests__/document-builder.test.d.ts.map +1 -0
- package/dist/openapi/__tests__/route-scanner.test.d.ts +2 -0
- package/dist/openapi/__tests__/route-scanner.test.d.ts.map +1 -0
- package/dist/openapi/__tests__/schema-generator.test.d.ts +2 -0
- package/dist/openapi/__tests__/schema-generator.test.d.ts.map +1 -0
- package/dist/openapi/decorators.d.ts +173 -0
- package/dist/openapi/decorators.d.ts.map +1 -0
- package/dist/openapi/document-builder.d.ts +82 -0
- package/dist/openapi/document-builder.d.ts.map +1 -0
- package/dist/openapi/index.d.ts +48 -0
- package/dist/openapi/index.d.ts.map +1 -0
- package/dist/openapi/index.js +59 -40
- package/dist/openapi/metadata.d.ts +36 -0
- package/dist/openapi/metadata.d.ts.map +1 -0
- package/dist/openapi/route-scanner.d.ts +34 -0
- package/dist/openapi/route-scanner.d.ts.map +1 -0
- package/dist/openapi/schema-generator.d.ts +53 -0
- package/dist/openapi/schema-generator.d.ts.map +1 -0
- package/dist/openapi/swagger-module.d.ts +57 -0
- package/dist/openapi/swagger-module.d.ts.map +1 -0
- package/dist/openapi/types.d.ts +344 -0
- package/dist/openapi/types.d.ts.map +1 -0
- package/dist/orm/index.d.ts +10 -0
- package/dist/orm/index.d.ts.map +1 -0
- package/dist/router/index.d.ts +73 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/linear.d.ts +54 -0
- package/dist/router/linear.d.ts.map +1 -0
- package/dist/router/regex.d.ts +49 -0
- package/dist/router/regex.d.ts.map +1 -0
- package/dist/router/tree.d.ts +112 -0
- package/dist/router/tree.d.ts.map +1 -0
- package/dist/rpc/index.d.ts +321 -0
- package/dist/rpc/index.d.ts.map +1 -0
- package/dist/schema/index.d.ts +10 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/security/index.d.ts +126 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/ssg/index.d.ts +73 -0
- package/dist/ssg/index.d.ts.map +1 -0
- package/dist/storage/index.d.ts +99 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/telemetry/index.d.ts +376 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/template/index.d.ts +7 -0
- package/dist/template/index.d.ts.map +1 -0
- package/dist/templates/engine.d.ts +60 -0
- package/dist/templates/engine.d.ts.map +1 -0
- package/dist/templates/index.d.ts +9 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/loader.d.ts +45 -0
- package/dist/templates/loader.d.ts.map +1 -0
- package/dist/templates/renderers/markdown.d.ts +46 -0
- package/dist/templates/renderers/markdown.d.ts.map +1 -0
- package/dist/templates/renderers/simple.d.ts +35 -0
- package/dist/templates/renderers/simple.d.ts.map +1 -0
- package/dist/templates/types.d.ts +138 -0
- package/dist/templates/types.d.ts.map +1 -0
- package/dist/testing/index.d.ts +539 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/types/index.d.ts +116 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/validation/index.d.ts +89 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/schemas.d.ts +243 -0
- package/dist/validation/schemas.d.ts.map +1 -0
- package/dist/websocket/index.d.ts +252 -0
- package/dist/websocket/index.d.ts.map +1 -0
- package/llms.txt +231 -0
- package/package.json +6 -2
- package/src/cli/ARCHITECTURE.md +3 -3
- package/src/cli/commands/add-frontend.ts +444 -0
- package/src/cli/commands/new.ts +23 -0
- package/src/cli/index.ts +1 -0
- package/src/cli/templates/frontend/react.ts +2 -1
- package/src/cli/templates/frontend/solid.ts +2 -1
- package/src/cli/templates/frontend/svelte.ts +2 -1
- package/src/cli/templates/frontend/vue.ts +2 -1
- package/src/cli/templates/project/api.ts +1 -1
- package/src/cli/templates/project/default.ts +1 -1
- package/src/cli/templates/project/fullstack.ts +14 -104
- package/src/cli/templates/project/website.ts +63 -12
- package/src/config/types.ts +21 -0
- package/src/graphql/built-in-engine.ts +598 -0
- package/src/graphql/context-builder.ts +110 -0
- package/src/graphql/decorators.ts +358 -0
- package/src/graphql/execution-pipeline.ts +227 -0
- package/src/graphql/graphql-module.ts +563 -0
- package/src/graphql/index.ts +101 -0
- package/src/graphql/metadata.ts +237 -0
- package/src/graphql/schema-builder.ts +319 -0
- package/src/graphql/subscription-handler.ts +283 -0
- package/src/graphql/types.ts +324 -0
- package/src/index.ts +3 -0
- package/src/modules/index.ts +48 -1
- package/tests/integration/cli.test.ts +19 -19
- package/tests/unit/cli.test.ts +1 -1
- package/tests/unit/graphql.test.ts +991 -0
- package/tsconfig.declaration.json +14 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphQL Metadata Storage
|
|
3
|
+
*
|
|
4
|
+
* Isolated metadata storage using WeakMap, following the same pattern
|
|
5
|
+
* as src/openapi/metadata.ts and src/modules/metadata.ts.
|
|
6
|
+
* Fully self-contained — no imports from openapi/ or modules/.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
Constructor,
|
|
11
|
+
FieldMetadata,
|
|
12
|
+
ResolverFieldMetadata,
|
|
13
|
+
ResolverClassMetadata,
|
|
14
|
+
TypeClassMetadata,
|
|
15
|
+
ParamMetadata,
|
|
16
|
+
} from "./types";
|
|
17
|
+
|
|
18
|
+
// ============= Class-Level Metadata =============
|
|
19
|
+
// Stores @Resolver, @ObjectType, @InputType metadata keyed by class constructor
|
|
20
|
+
|
|
21
|
+
const classMetadataStore = new WeakMap<Constructor, Map<string, unknown>>();
|
|
22
|
+
|
|
23
|
+
export function setGqlClassMetadata(
|
|
24
|
+
target: Constructor,
|
|
25
|
+
key: string,
|
|
26
|
+
value: unknown,
|
|
27
|
+
): void {
|
|
28
|
+
if (!classMetadataStore.has(target)) {
|
|
29
|
+
classMetadataStore.set(target, new Map());
|
|
30
|
+
}
|
|
31
|
+
classMetadataStore.get(target)?.set(key, value);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getGqlClassMetadata<T>(
|
|
35
|
+
target: Constructor,
|
|
36
|
+
key: string,
|
|
37
|
+
): T | undefined {
|
|
38
|
+
return classMetadataStore.get(target)?.get(key) as T | undefined;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ============= Prototype-Level Metadata =============
|
|
42
|
+
// Stores @Query, @Mutation, @Subscription, @Args metadata keyed by class prototype
|
|
43
|
+
|
|
44
|
+
const prototypeMetadataStore = new WeakMap<object, Map<string, unknown>>();
|
|
45
|
+
|
|
46
|
+
export function setGqlPrototypeMetadata(
|
|
47
|
+
target: object,
|
|
48
|
+
key: string,
|
|
49
|
+
value: unknown,
|
|
50
|
+
): void {
|
|
51
|
+
if (!prototypeMetadataStore.has(target)) {
|
|
52
|
+
prototypeMetadataStore.set(target, new Map());
|
|
53
|
+
}
|
|
54
|
+
prototypeMetadataStore.get(target)?.set(key, value);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function getGqlPrototypeMetadata<T>(
|
|
58
|
+
target: object,
|
|
59
|
+
key: string,
|
|
60
|
+
): T | undefined {
|
|
61
|
+
return prototypeMetadataStore.get(target)?.get(key) as T | undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ============= Property-Level Metadata =============
|
|
65
|
+
// Stores @Field metadata keyed by class prototype + property name
|
|
66
|
+
|
|
67
|
+
const propertyMetadataStore = new WeakMap<object, Map<string, FieldMetadata>>();
|
|
68
|
+
|
|
69
|
+
export function setGqlPropertyMetadata(
|
|
70
|
+
target: object,
|
|
71
|
+
propertyKey: string | symbol,
|
|
72
|
+
value: FieldMetadata,
|
|
73
|
+
): void {
|
|
74
|
+
if (!propertyMetadataStore.has(target)) {
|
|
75
|
+
propertyMetadataStore.set(target, new Map());
|
|
76
|
+
}
|
|
77
|
+
const key =
|
|
78
|
+
typeof propertyKey === "symbol" ? propertyKey.toString() : propertyKey;
|
|
79
|
+
propertyMetadataStore.get(target)?.set(key, value);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function getGqlPropertyMetadata(
|
|
83
|
+
target: object,
|
|
84
|
+
propertyKey: string | symbol,
|
|
85
|
+
): FieldMetadata | undefined {
|
|
86
|
+
const key =
|
|
87
|
+
typeof propertyKey === "symbol" ? propertyKey.toString() : propertyKey;
|
|
88
|
+
return propertyMetadataStore.get(target)?.get(key);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function getGqlPropertyKeys(target: object): string[] {
|
|
92
|
+
const map = propertyMetadataStore.get(target);
|
|
93
|
+
if (!map) return [];
|
|
94
|
+
return Array.from(map.keys());
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function getAllGqlPropertyMetadata(
|
|
98
|
+
target: object,
|
|
99
|
+
): FieldMetadata[] {
|
|
100
|
+
const map = propertyMetadataStore.get(target);
|
|
101
|
+
if (!map) return [];
|
|
102
|
+
return Array.from(map.values());
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ============= Typed Helpers =============
|
|
106
|
+
|
|
107
|
+
// Metadata keys
|
|
108
|
+
export const GQL_RESOLVER_KEY = "gql:resolver";
|
|
109
|
+
export const GQL_OBJECTTYPE_KEY = "gql:objecttype";
|
|
110
|
+
export const GQL_INPUTTYPE_KEY = "gql:inputtype";
|
|
111
|
+
export const GQL_QUERIES_KEY = "gql:queries";
|
|
112
|
+
export const GQL_MUTATIONS_KEY = "gql:mutations";
|
|
113
|
+
export const GQL_SUBSCRIPTIONS_KEY = "gql:subscriptions";
|
|
114
|
+
export const GQL_PARAMS_PREFIX = "gql:params:";
|
|
115
|
+
|
|
116
|
+
// ============= Resolver metadata helpers =============
|
|
117
|
+
|
|
118
|
+
export function getResolverMetadata(
|
|
119
|
+
target: Constructor,
|
|
120
|
+
): ResolverClassMetadata | undefined {
|
|
121
|
+
return getGqlClassMetadata<ResolverClassMetadata>(target, GQL_RESOLVER_KEY);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function setResolverMetadata(
|
|
125
|
+
target: Constructor,
|
|
126
|
+
metadata: ResolverClassMetadata,
|
|
127
|
+
): void {
|
|
128
|
+
setGqlClassMetadata(target, GQL_RESOLVER_KEY, metadata);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ============= Object/Input type metadata helpers =============
|
|
132
|
+
|
|
133
|
+
export function getTypeMetadata(
|
|
134
|
+
target: Constructor,
|
|
135
|
+
): TypeClassMetadata | undefined {
|
|
136
|
+
return (
|
|
137
|
+
getGqlClassMetadata<TypeClassMetadata>(target, GQL_OBJECTTYPE_KEY) ??
|
|
138
|
+
getGqlClassMetadata<TypeClassMetadata>(target, GQL_INPUTTYPE_KEY)
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function setObjectTypeMetadata(
|
|
143
|
+
target: Constructor,
|
|
144
|
+
metadata: TypeClassMetadata,
|
|
145
|
+
): void {
|
|
146
|
+
setGqlClassMetadata(target, GQL_OBJECTTYPE_KEY, metadata);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function setInputTypeMetadata(
|
|
150
|
+
target: Constructor,
|
|
151
|
+
metadata: TypeClassMetadata,
|
|
152
|
+
): void {
|
|
153
|
+
setGqlClassMetadata(target, GQL_INPUTTYPE_KEY, metadata);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ============= Resolver field metadata helpers =============
|
|
157
|
+
|
|
158
|
+
function getResolverFields(
|
|
159
|
+
prototype: object,
|
|
160
|
+
key: string,
|
|
161
|
+
): ResolverFieldMetadata[] {
|
|
162
|
+
return getGqlPrototypeMetadata<ResolverFieldMetadata[]>(prototype, key) ?? [];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function addResolverField(
|
|
166
|
+
prototype: object,
|
|
167
|
+
key: string,
|
|
168
|
+
field: ResolverFieldMetadata,
|
|
169
|
+
): void {
|
|
170
|
+
const existing = getResolverFields(prototype, key);
|
|
171
|
+
// Replace if methodName already exists (decorator applied multiple times)
|
|
172
|
+
const idx = existing.findIndex((f) => f.methodName === field.methodName);
|
|
173
|
+
if (idx >= 0) {
|
|
174
|
+
existing[idx] = field;
|
|
175
|
+
} else {
|
|
176
|
+
existing.push(field);
|
|
177
|
+
}
|
|
178
|
+
setGqlPrototypeMetadata(prototype, key, existing);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function addQueryField(
|
|
182
|
+
prototype: object,
|
|
183
|
+
field: ResolverFieldMetadata,
|
|
184
|
+
): void {
|
|
185
|
+
addResolverField(prototype, GQL_QUERIES_KEY, field);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function addMutationField(
|
|
189
|
+
prototype: object,
|
|
190
|
+
field: ResolverFieldMetadata,
|
|
191
|
+
): void {
|
|
192
|
+
addResolverField(prototype, GQL_MUTATIONS_KEY, field);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function addSubscriptionField(
|
|
196
|
+
prototype: object,
|
|
197
|
+
field: ResolverFieldMetadata,
|
|
198
|
+
): void {
|
|
199
|
+
addResolverField(prototype, GQL_SUBSCRIPTIONS_KEY, field);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export function getQueryFields(prototype: object): ResolverFieldMetadata[] {
|
|
203
|
+
return getResolverFields(prototype, GQL_QUERIES_KEY);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function getMutationFields(prototype: object): ResolverFieldMetadata[] {
|
|
207
|
+
return getResolverFields(prototype, GQL_MUTATIONS_KEY);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function getSubscriptionFields(
|
|
211
|
+
prototype: object,
|
|
212
|
+
): ResolverFieldMetadata[] {
|
|
213
|
+
return getResolverFields(prototype, GQL_SUBSCRIPTIONS_KEY);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ============= Parameter metadata helpers =============
|
|
217
|
+
|
|
218
|
+
export function setParamMetadata(
|
|
219
|
+
prototype: object,
|
|
220
|
+
methodName: string,
|
|
221
|
+
paramIndex: number,
|
|
222
|
+
meta: ParamMetadata,
|
|
223
|
+
): void {
|
|
224
|
+
const key = `${GQL_PARAMS_PREFIX}${methodName}`;
|
|
225
|
+
const existing =
|
|
226
|
+
getGqlPrototypeMetadata<ParamMetadata[]>(prototype, key) ?? [];
|
|
227
|
+
existing[paramIndex] = meta;
|
|
228
|
+
setGqlPrototypeMetadata(prototype, key, existing);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function getParamMetadata(
|
|
232
|
+
prototype: object,
|
|
233
|
+
methodName: string,
|
|
234
|
+
): ParamMetadata[] {
|
|
235
|
+
const key = `${GQL_PARAMS_PREFIX}${methodName}`;
|
|
236
|
+
return getGqlPrototypeMetadata<ParamMetadata[]>(prototype, key) ?? [];
|
|
237
|
+
}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Builder
|
|
3
|
+
*
|
|
4
|
+
* Reads GraphQL decorator metadata from resolver and type classes,
|
|
5
|
+
* generates SDL (Schema Definition Language), and builds the internal
|
|
6
|
+
* ResolvedSchema used by the built-in engine.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
Constructor,
|
|
11
|
+
TypeFn,
|
|
12
|
+
FieldMetadata,
|
|
13
|
+
ResolverFieldMetadata,
|
|
14
|
+
ResolvedField,
|
|
15
|
+
ResolvedSchema,
|
|
16
|
+
ResolverFieldsByType,
|
|
17
|
+
GraphQLID,
|
|
18
|
+
GraphQLInt,
|
|
19
|
+
GraphQLFloat,
|
|
20
|
+
} from "./types";
|
|
21
|
+
import {
|
|
22
|
+
getResolverMetadata,
|
|
23
|
+
getTypeMetadata,
|
|
24
|
+
getQueryFields,
|
|
25
|
+
getMutationFields,
|
|
26
|
+
getSubscriptionFields,
|
|
27
|
+
getGqlClassMetadata,
|
|
28
|
+
getAllGqlPropertyMetadata,
|
|
29
|
+
GQL_OBJECTTYPE_KEY,
|
|
30
|
+
GQL_INPUTTYPE_KEY,
|
|
31
|
+
} from "./metadata";
|
|
32
|
+
|
|
33
|
+
// ============= Scalar Helpers =============
|
|
34
|
+
|
|
35
|
+
/** Map JS constructors to GraphQL scalar names */
|
|
36
|
+
export function typeFnToScalarName(typeFn: TypeFn): string | null {
|
|
37
|
+
const type = typeFn();
|
|
38
|
+
const resolved = Array.isArray(type) ? type[0] : type;
|
|
39
|
+
if (resolved === String) return "String";
|
|
40
|
+
if (resolved === Number) return "Float";
|
|
41
|
+
if (resolved === Boolean) return "Boolean";
|
|
42
|
+
// Check sentinel classes by name (avoids import cycle)
|
|
43
|
+
const name = (resolved as Constructor).name;
|
|
44
|
+
if (name === "GraphQLID") return "ID";
|
|
45
|
+
if (name === "GraphQLInt") return "Int";
|
|
46
|
+
if (name === "GraphQLFloat") return "Float";
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Convert a TypeFn to an SDL type string */
|
|
51
|
+
export function typeFnToSDL(typeFn: TypeFn, nullable: boolean): string {
|
|
52
|
+
const type = typeFn();
|
|
53
|
+
const isArray = Array.isArray(type);
|
|
54
|
+
const inner = isArray ? (type as Constructor[])[0] : (type as Constructor);
|
|
55
|
+
|
|
56
|
+
let innerName: string;
|
|
57
|
+
const scalarName = typeFnToScalarName(() => inner);
|
|
58
|
+
if (scalarName) {
|
|
59
|
+
innerName = scalarName;
|
|
60
|
+
} else {
|
|
61
|
+
// Use the class name for object / input types
|
|
62
|
+
innerName = (inner as Constructor).name;
|
|
63
|
+
// Strip any __type marker (for sentinel classes already handled above)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Inner type is always non-null (items in list are non-null)
|
|
67
|
+
const innerSdl = isArray ? `[${innerName}!]` : innerName;
|
|
68
|
+
return nullable ? innerSdl : `${innerSdl}!`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ============= Schema Builder =============
|
|
72
|
+
|
|
73
|
+
export interface BuiltSchema {
|
|
74
|
+
sdl: string;
|
|
75
|
+
resolvedSchema: ResolvedSchema;
|
|
76
|
+
resolverFields: ResolverFieldsByType;
|
|
77
|
+
typeFields: Map<string, FieldMetadata[]>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export class SchemaBuilder {
|
|
81
|
+
private resolverInstances: Map<Constructor, unknown>;
|
|
82
|
+
private typeClasses: Set<Constructor> = new Set();
|
|
83
|
+
|
|
84
|
+
constructor(
|
|
85
|
+
private resolverClasses: Constructor[],
|
|
86
|
+
resolverInstances: Map<Constructor, unknown>,
|
|
87
|
+
) {
|
|
88
|
+
this.resolverInstances = resolverInstances;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
build(): BuiltSchema {
|
|
92
|
+
// Collect query/mutation/subscription fields across all resolvers
|
|
93
|
+
const queries = new Map<string, ResolvedField>();
|
|
94
|
+
const mutations = new Map<string, ResolvedField>();
|
|
95
|
+
const subscriptions = new Map<string, ResolvedField>();
|
|
96
|
+
|
|
97
|
+
for (const ResolverClass of this.resolverClasses) {
|
|
98
|
+
const instance = this.resolverInstances.get(ResolverClass);
|
|
99
|
+
|
|
100
|
+
const qFields = getQueryFields(ResolverClass.prototype);
|
|
101
|
+
for (const f of qFields) {
|
|
102
|
+
queries.set(f.fieldName, this.toResolvedField(f, instance));
|
|
103
|
+
this.collectReturnType(f.typeFn);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const mFields = getMutationFields(ResolverClass.prototype);
|
|
107
|
+
for (const f of mFields) {
|
|
108
|
+
mutations.set(f.fieldName, this.toResolvedField(f, instance));
|
|
109
|
+
this.collectReturnType(f.typeFn);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const sFields = getSubscriptionFields(ResolverClass.prototype);
|
|
113
|
+
for (const f of sFields) {
|
|
114
|
+
subscriptions.set(f.fieldName, this.toResolvedField(f, instance));
|
|
115
|
+
this.collectReturnType(f.typeFn);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Also collect types referenced from @Field decorators
|
|
120
|
+
this.collectNestedTypes();
|
|
121
|
+
|
|
122
|
+
// Build type field map
|
|
123
|
+
const typeFields = this.buildTypeFields();
|
|
124
|
+
|
|
125
|
+
// Generate SDL
|
|
126
|
+
const sdl = this.generateSDL(queries, mutations, subscriptions, typeFields);
|
|
127
|
+
|
|
128
|
+
const resolverFields: ResolverFieldsByType = {
|
|
129
|
+
queries,
|
|
130
|
+
mutations,
|
|
131
|
+
subscriptions,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const resolvedSchema: ResolvedSchema = {
|
|
135
|
+
queryFields: queries,
|
|
136
|
+
mutationFields: mutations,
|
|
137
|
+
subscriptionFields: subscriptions,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
return { sdl, resolvedSchema, resolverFields, typeFields };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private toResolvedField(
|
|
144
|
+
field: ResolverFieldMetadata,
|
|
145
|
+
instance: unknown,
|
|
146
|
+
): ResolvedField {
|
|
147
|
+
return {
|
|
148
|
+
resolverInstance: instance,
|
|
149
|
+
methodName: field.methodName,
|
|
150
|
+
paramMetadata: field.paramMetadata,
|
|
151
|
+
typeFn: field.typeFn,
|
|
152
|
+
nullable: field.nullable,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private collectReturnType(typeFn: TypeFn): void {
|
|
157
|
+
const type = typeFn();
|
|
158
|
+
const resolved = Array.isArray(type) ? type[0] : type;
|
|
159
|
+
if (typeof resolved === "function") {
|
|
160
|
+
const meta = getTypeMetadata(resolved as Constructor);
|
|
161
|
+
if (meta) {
|
|
162
|
+
this.typeClasses.add(resolved as Constructor);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private collectNestedTypes(): void {
|
|
168
|
+
// Iterate type classes and collect nested types from @Field typeFns
|
|
169
|
+
let changed = true;
|
|
170
|
+
while (changed) {
|
|
171
|
+
changed = false;
|
|
172
|
+
for (const TypeClass of Array.from(this.typeClasses)) {
|
|
173
|
+
const fields = getAllGqlPropertyMetadata(TypeClass.prototype);
|
|
174
|
+
for (const field of fields) {
|
|
175
|
+
const type = field.typeFn();
|
|
176
|
+
const inner = Array.isArray(type) ? type[0] : type;
|
|
177
|
+
if (typeof inner === "function") {
|
|
178
|
+
const meta = getTypeMetadata(inner as Constructor);
|
|
179
|
+
if (meta && !this.typeClasses.has(inner as Constructor)) {
|
|
180
|
+
this.typeClasses.add(inner as Constructor);
|
|
181
|
+
changed = true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private buildTypeFields(): Map<string, FieldMetadata[]> {
|
|
190
|
+
const result = new Map<string, FieldMetadata[]>();
|
|
191
|
+
for (const TypeClass of this.typeClasses) {
|
|
192
|
+
const meta = getTypeMetadata(TypeClass);
|
|
193
|
+
if (!meta) continue;
|
|
194
|
+
const fields = getAllGqlPropertyMetadata(TypeClass.prototype);
|
|
195
|
+
result.set(meta.name, fields);
|
|
196
|
+
}
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private generateSDL(
|
|
201
|
+
queries: Map<string, ResolvedField>,
|
|
202
|
+
mutations: Map<string, ResolvedField>,
|
|
203
|
+
subscriptions: Map<string, ResolvedField>,
|
|
204
|
+
typeFields: Map<string, FieldMetadata[]>,
|
|
205
|
+
): string {
|
|
206
|
+
const lines: string[] = [];
|
|
207
|
+
|
|
208
|
+
// Object types and input types
|
|
209
|
+
for (const TypeClass of this.typeClasses) {
|
|
210
|
+
const meta = getTypeMetadata(TypeClass);
|
|
211
|
+
if (!meta) continue;
|
|
212
|
+
|
|
213
|
+
const fields = getAllGqlPropertyMetadata(TypeClass.prototype);
|
|
214
|
+
if (fields.length === 0) continue;
|
|
215
|
+
|
|
216
|
+
const keyword = meta.kind === "input" ? "input" : "type";
|
|
217
|
+
if (meta.description) {
|
|
218
|
+
lines.push(`"""${meta.description}"""`);
|
|
219
|
+
}
|
|
220
|
+
lines.push(`${keyword} ${meta.name} {`);
|
|
221
|
+
for (const f of fields) {
|
|
222
|
+
if (f.description) {
|
|
223
|
+
lines.push(` """${f.description}"""`);
|
|
224
|
+
}
|
|
225
|
+
const typeSdl = typeFnToSDL(f.typeFn, f.nullable);
|
|
226
|
+
let fieldLine = ` ${f.propertyKey}: ${typeSdl}`;
|
|
227
|
+
if (f.defaultValue !== undefined) {
|
|
228
|
+
fieldLine += ` = ${JSON.stringify(f.defaultValue)}`;
|
|
229
|
+
}
|
|
230
|
+
lines.push(fieldLine);
|
|
231
|
+
if (f.deprecationReason) {
|
|
232
|
+
lines[lines.length - 1] += ` @deprecated(reason: "${f.deprecationReason}")`;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
lines.push("}");
|
|
236
|
+
lines.push("");
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Query type
|
|
240
|
+
if (queries.size > 0) {
|
|
241
|
+
lines.push("type Query {");
|
|
242
|
+
for (const [fieldName, field] of queries) {
|
|
243
|
+
const args = this.buildArgsSDL(fieldName, queries);
|
|
244
|
+
const typeSdl = typeFnToSDL(field.typeFn, field.nullable);
|
|
245
|
+
lines.push(` ${fieldName}${args}: ${typeSdl}`);
|
|
246
|
+
}
|
|
247
|
+
lines.push("}");
|
|
248
|
+
lines.push("");
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Mutation type
|
|
252
|
+
if (mutations.size > 0) {
|
|
253
|
+
lines.push("type Mutation {");
|
|
254
|
+
for (const [fieldName, field] of mutations) {
|
|
255
|
+
const args = this.buildArgsSDL(fieldName, mutations);
|
|
256
|
+
const typeSdl = typeFnToSDL(field.typeFn, field.nullable);
|
|
257
|
+
lines.push(` ${fieldName}${args}: ${typeSdl}`);
|
|
258
|
+
}
|
|
259
|
+
lines.push("}");
|
|
260
|
+
lines.push("");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Subscription type
|
|
264
|
+
if (subscriptions.size > 0) {
|
|
265
|
+
lines.push("type Subscription {");
|
|
266
|
+
for (const [fieldName, field] of subscriptions) {
|
|
267
|
+
const typeSdl = typeFnToSDL(field.typeFn, field.nullable);
|
|
268
|
+
lines.push(` ${fieldName}: ${typeSdl}`);
|
|
269
|
+
}
|
|
270
|
+
lines.push("}");
|
|
271
|
+
lines.push("");
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return lines.join("\n").trim();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private buildArgsSDL(
|
|
278
|
+
fieldName: string,
|
|
279
|
+
fields: Map<string, ResolvedField>,
|
|
280
|
+
): string {
|
|
281
|
+
const field = fields.get(fieldName);
|
|
282
|
+
if (!field || field.paramMetadata.length === 0) return "";
|
|
283
|
+
|
|
284
|
+
const args: string[] = [];
|
|
285
|
+
for (const param of field.paramMetadata) {
|
|
286
|
+
if (param.kind === "context") continue;
|
|
287
|
+
if (param.kind === "args" && param.argName) {
|
|
288
|
+
// We don't know the type from paramMetadata alone for SDL args.
|
|
289
|
+
// For simple scalars this would need annotation — skip for now
|
|
290
|
+
// (built-in engine resolves by name from incoming args object)
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
if (param.kind === "argsObject" && param.inputTypeFn) {
|
|
294
|
+
const inputType = param.inputTypeFn();
|
|
295
|
+
const typeName = Array.isArray(inputType)
|
|
296
|
+
? (inputType[0] as Constructor).name
|
|
297
|
+
: (inputType as Constructor).name;
|
|
298
|
+
if (param.argName) {
|
|
299
|
+
args.push(`${param.argName}: ${typeName}!`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return args.length > 0 ? `(${args.join(", ")})` : "";
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ============= Registry of known @ObjectType / @InputType classes =============
|
|
309
|
+
|
|
310
|
+
// Global registry populated by @ObjectType / @InputType at decoration time
|
|
311
|
+
const registeredTypeClasses = new Set<Constructor>();
|
|
312
|
+
|
|
313
|
+
export function registerTypeClass(ctor: Constructor): void {
|
|
314
|
+
registeredTypeClasses.add(ctor);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export function getRegisteredTypeClasses(): Constructor[] {
|
|
318
|
+
return Array.from(registeredTypeClasses);
|
|
319
|
+
}
|