@pattern-stack/codegen 0.3.2 → 0.4.1

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.
Files changed (29) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +2 -1
  3. package/dist/runtime/shared/openapi/error-response.dto.d.ts +33 -0
  4. package/dist/runtime/shared/openapi/error-response.dto.js +13 -0
  5. package/dist/runtime/shared/openapi/error-response.dto.js.map +1 -0
  6. package/dist/runtime/shared/openapi/errors.d.ts +30 -0
  7. package/dist/runtime/shared/openapi/errors.js +24 -0
  8. package/dist/runtime/shared/openapi/errors.js.map +1 -0
  9. package/dist/runtime/shared/openapi/index.d.ts +5 -0
  10. package/dist/runtime/shared/openapi/index.js +115 -0
  11. package/dist/runtime/shared/openapi/index.js.map +1 -0
  12. package/dist/runtime/shared/openapi/registry.d.ts +82 -0
  13. package/dist/runtime/shared/openapi/registry.js +107 -0
  14. package/dist/runtime/shared/openapi/registry.js.map +1 -0
  15. package/dist/runtime/shared/openapi/registry.tokens.d.ts +15 -0
  16. package/dist/runtime/shared/openapi/registry.tokens.js +6 -0
  17. package/dist/runtime/shared/openapi/registry.tokens.js.map +1 -0
  18. package/dist/runtime/subsystems/sync/sync-audit.schema.d.ts +2 -2
  19. package/dist/src/cli/index.js +1888 -1074
  20. package/dist/src/cli/index.js.map +1 -1
  21. package/package.json +10 -1
  22. package/templates/entity/new/backend/application/schemas/dto.ejs.t +31 -0
  23. package/templates/entity/new/backend/modules/core/module.ejs.t +21 -2
  24. package/templates/entity/new/backend/presentation/controller.ejs.t +74 -0
  25. package/templates/entity/new/clean-lite-ps/controller.ejs.t +48 -0
  26. package/templates/entity/new/clean-lite-ps/module.ejs.t +24 -2
  27. package/templates/entity/new/prompt.js +2 -0
  28. package/templates/subsystem/openapi-config/codegen-config-openapi-block.ejs.t +35 -0
  29. package/templates/subsystem/openapi-config/prompt.js +23 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.4.1] — 2026-04-21
8
+
9
+ ### Added
10
+ - **`codegen project upgrade-openapi`** — surgical AST-based codemod that brings an existing consumer `src/app.module.ts` + `src/main.ts` up to the OPENAPI-4 shape `project init` emits on a fresh project. Merges `@nestjs/common` imports, adds `OpenApiModule` (the `@Global()` wrapper around `OPENAPI_REGISTRY`), wires it into `AppModule.imports`, injects the two-pass Swagger bootstrap into `main.ts`, and vendors `src/shared/openapi/*`. Idempotent; `--dry-run` and `--path` supported. Proof-of-concept for issue #188 (additive subsystem install, targeted for 0.5.0).
11
+ - **`src/cli/shared/ast-patch.ts`** — ts-morph patching primitives (`ensureImport`, `ensureClassDeclaration`, `ensureModuleImportEntry`, `ensureMainSwaggerBlock`). Each is idempotent and bails cleanly on exotic shapes (factory-based modules, non-array `imports`, missing `@Module()` decorator).
12
+
13
+ ### Changed
14
+ - **`project init` skip reasons** — when `app.module.ts` or `main.ts` exist, the skip message now points at `codegen project upgrade-openapi` as the automated path (previously instructed manual wiring only).
15
+
16
+ ### Dependencies
17
+ - Added `ts-morph` (runtime dep; CLI-side) for AST manipulation.
18
+
19
+
20
+
7
21
  ### Added
8
22
  - **Noun-verb CLI** — Clipanion-based CLI replacing the legacy single-file handler. Commands: `entity`, `subsystem`, `project`, `dev`. Each noun has a summary pane with dynamic hints. (ADR-015)
9
23
  - **UI toolkit** — chalk theme tokens, icons with ASCII fallback, Ora spinners, pane/hints rendering, `--json` mode across all commands. (ADR-016)
package/README.md CHANGED
@@ -96,12 +96,13 @@ codegen subsystem install cache # key-value cache with TTL
96
96
  codegen subsystem install storage # file storage (local filesystem)
97
97
  codegen subsystem install sync # external-system sync engine (IChangeSource + orchestrator + audit log)
98
98
  codegen subsystem install bridge # event-to-job bridge (durable async fanout via @JobHandler.triggers)
99
+ codegen subsystem install openapi-config # OpenAPI/Swagger — Zod DTOs as /docs-json + Swagger UI. See docs/CONSUMER-SETUP.md §OpenAPI
99
100
  codegen subsystem list # show installed + available
100
101
 
101
102
  codegen events consumers <type> # list all Tier 1/2/3 consumers of an event type
102
103
  ```
103
104
 
104
- Each subsystem generates a protocol (interface), Drizzle backend (Postgres), memory backend (tests), and a NestJS module with `forRoot({ backend })` factory.
105
+ Each subsystem generates a protocol (interface), Drizzle backend (Postgres), memory backend (tests), and a NestJS module with `forRoot({ backend })` factory. The `openapi-config` subsystem is config-only — the runtime helpers ship with `codegen project init`.
105
106
 
106
107
  ### Project Commands
107
108
 
@@ -0,0 +1,33 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Shared error response schema (OPENAPI-3).
5
+ *
6
+ * Generated controllers `@ApiResponse(...)` decorators reference this
7
+ * schema by `$ref` (name `ErrorResponseDto`) for non-success status codes
8
+ * (400, 401, 404, etc.). Shape matches NestJS's default `HttpException`
9
+ * JSON body — see `packages/common/src/exceptions/http.exception.ts`.
10
+ *
11
+ * The registry auto-registers this schema on construction so every
12
+ * consumer project exposes `components.schemas.ErrorResponseDto` on
13
+ * `/docs-json` without per-entity duplication.
14
+ */
15
+
16
+ declare const errorResponseSchema: z.ZodObject<{
17
+ statusCode: z.ZodNumber;
18
+ message: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
19
+ error: z.ZodOptional<z.ZodString>;
20
+ }, "strip", z.ZodTypeAny, {
21
+ statusCode: number;
22
+ message: string | string[];
23
+ error?: string | undefined;
24
+ }, {
25
+ statusCode: number;
26
+ message: string | string[];
27
+ error?: string | undefined;
28
+ }>;
29
+ type ErrorResponseDto = z.infer<typeof errorResponseSchema>;
30
+ /** Canonical name used across `$ref` URIs in generated controllers. */
31
+ declare const ERROR_RESPONSE_SCHEMA_NAME = "ErrorResponseDto";
32
+
33
+ export { ERROR_RESPONSE_SCHEMA_NAME, type ErrorResponseDto, errorResponseSchema };
@@ -0,0 +1,13 @@
1
+ // runtime/shared/openapi/error-response.dto.ts
2
+ import { z } from "zod";
3
+ var errorResponseSchema = z.object({
4
+ statusCode: z.number().int(),
5
+ message: z.union([z.string(), z.array(z.string())]),
6
+ error: z.string().optional()
7
+ });
8
+ var ERROR_RESPONSE_SCHEMA_NAME = "ErrorResponseDto";
9
+ export {
10
+ ERROR_RESPONSE_SCHEMA_NAME,
11
+ errorResponseSchema
12
+ };
13
+ //# sourceMappingURL=error-response.dto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../runtime/shared/openapi/error-response.dto.ts"],"sourcesContent":["/**\n * Shared error response schema (OPENAPI-3).\n *\n * Generated controllers `@ApiResponse(...)` decorators reference this\n * schema by `$ref` (name `ErrorResponseDto`) for non-success status codes\n * (400, 401, 404, etc.). Shape matches NestJS's default `HttpException`\n * JSON body — see `packages/common/src/exceptions/http.exception.ts`.\n *\n * The registry auto-registers this schema on construction so every\n * consumer project exposes `components.schemas.ErrorResponseDto` on\n * `/docs-json` without per-entity duplication.\n */\nimport { z } from 'zod';\n\nexport const errorResponseSchema = z.object({\n statusCode: z.number().int(),\n message: z.union([z.string(), z.array(z.string())]),\n error: z.string().optional(),\n});\n\nexport type ErrorResponseDto = z.infer<typeof errorResponseSchema>;\n\n/** Canonical name used across `$ref` URIs in generated controllers. */\nexport const ERROR_RESPONSE_SCHEMA_NAME = 'ErrorResponseDto';\n"],"mappings":";AAYA,SAAS,SAAS;AAEX,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,YAAY,EAAE,OAAO,EAAE,IAAI;AAAA,EAC3B,SAAS,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAAA,EAClD,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAKM,IAAM,6BAA6B;","names":[]}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Typed errors for the OpenAPI registry (OPENAPI-1).
3
+ *
4
+ * Same shape as `runtime/subsystems/bridge/bridge-errors.ts` so consumers
5
+ * can catch them with the same exception-filter pattern used elsewhere.
6
+ */
7
+ /**
8
+ * Thrown by `OpenApiRegistry.build()` when `@anatine/zod-openapi` is not
9
+ * resolvable. The peer is declared optional (`peerDependenciesMeta`) so
10
+ * consumer apps that don't care about OpenAPI still boot; the cost is a
11
+ * deferred failure here on first `build()`.
12
+ */
13
+ declare class OpenApiPeerDepMissingError extends Error {
14
+ readonly name = "OpenApiPeerDepMissingError";
15
+ constructor(message?: string);
16
+ }
17
+ /**
18
+ * Thrown by `OpenApiRegistry.registerSchema(name, ...)` when `name` is
19
+ * already registered. Silent overwrite would make debugging
20
+ * double-registration bugs (e.g. two entity pipelines both emitting a
21
+ * `User` DTO) painful; loud failure lets the mismatch surface at module
22
+ * init where the stack trace is clear.
23
+ */
24
+ declare class DuplicateSchemaError extends Error {
25
+ readonly schemaName: string;
26
+ readonly name = "DuplicateSchemaError";
27
+ constructor(schemaName: string);
28
+ }
29
+
30
+ export { DuplicateSchemaError, OpenApiPeerDepMissingError };
@@ -0,0 +1,24 @@
1
+ // runtime/shared/openapi/errors.ts
2
+ var OpenApiPeerDepMissingError = class extends Error {
3
+ name = "OpenApiPeerDepMissingError";
4
+ constructor(message) {
5
+ super(
6
+ message ?? "OpenApiRegistry requires @anatine/zod-openapi. Install it: bun add @anatine/zod-openapi"
7
+ );
8
+ }
9
+ };
10
+ var DuplicateSchemaError = class extends Error {
11
+ constructor(schemaName) {
12
+ super(
13
+ `DuplicateSchemaError: schema '${schemaName}' is already registered. Each schema name must be unique within the OpenApiRegistry.`
14
+ );
15
+ this.schemaName = schemaName;
16
+ }
17
+ schemaName;
18
+ name = "DuplicateSchemaError";
19
+ };
20
+ export {
21
+ DuplicateSchemaError,
22
+ OpenApiPeerDepMissingError
23
+ };
24
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../runtime/shared/openapi/errors.ts"],"sourcesContent":["/**\n * Typed errors for the OpenAPI registry (OPENAPI-1).\n *\n * Same shape as `runtime/subsystems/bridge/bridge-errors.ts` so consumers\n * can catch them with the same exception-filter pattern used elsewhere.\n */\n\n/**\n * Thrown by `OpenApiRegistry.build()` when `@anatine/zod-openapi` is not\n * resolvable. The peer is declared optional (`peerDependenciesMeta`) so\n * consumer apps that don't care about OpenAPI still boot; the cost is a\n * deferred failure here on first `build()`.\n */\nexport class OpenApiPeerDepMissingError extends Error {\n override readonly name = 'OpenApiPeerDepMissingError';\n constructor(message?: string) {\n super(\n message ??\n 'OpenApiRegistry requires @anatine/zod-openapi. Install it: bun add @anatine/zod-openapi',\n );\n }\n}\n\n/**\n * Thrown by `OpenApiRegistry.registerSchema(name, ...)` when `name` is\n * already registered. Silent overwrite would make debugging\n * double-registration bugs (e.g. two entity pipelines both emitting a\n * `User` DTO) painful; loud failure lets the mismatch surface at module\n * init where the stack trace is clear.\n */\nexport class DuplicateSchemaError extends Error {\n override readonly name = 'DuplicateSchemaError';\n constructor(public readonly schemaName: string) {\n super(\n `DuplicateSchemaError: schema '${schemaName}' is already registered. ` +\n `Each schema name must be unique within the OpenApiRegistry.`,\n );\n }\n}\n"],"mappings":";AAaO,IAAM,6BAAN,cAAyC,MAAM;AAAA,EAClC,OAAO;AAAA,EACzB,YAAY,SAAkB;AAC5B;AAAA,MACE,WACE;AAAA,IACJ;AAAA,EACF;AACF;AASO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAE9C,YAA4B,YAAoB;AAC9C;AAAA,MACE,iCAAiC,UAAU;AAAA,IAE7C;AAJ0B;AAAA,EAK5B;AAAA,EAL4B;AAAA,EADV,OAAO;AAO3B;","names":[]}
@@ -0,0 +1,5 @@
1
+ export { HttpMethod, OpenAPIInfo, OpenAPIObject, OpenApiRegistry, PathSpec } from './registry.js';
2
+ export { OPENAPI_REGISTRY } from './registry.tokens.js';
3
+ export { DuplicateSchemaError, OpenApiPeerDepMissingError } from './errors.js';
4
+ export { ERROR_RESPONSE_SCHEMA_NAME, ErrorResponseDto, errorResponseSchema } from './error-response.dto.js';
5
+ import 'zod';
@@ -0,0 +1,115 @@
1
+ // runtime/shared/openapi/error-response.dto.ts
2
+ import { z } from "zod";
3
+ var errorResponseSchema = z.object({
4
+ statusCode: z.number().int(),
5
+ message: z.union([z.string(), z.array(z.string())]),
6
+ error: z.string().optional()
7
+ });
8
+ var ERROR_RESPONSE_SCHEMA_NAME = "ErrorResponseDto";
9
+
10
+ // runtime/shared/openapi/errors.ts
11
+ var OpenApiPeerDepMissingError = class extends Error {
12
+ name = "OpenApiPeerDepMissingError";
13
+ constructor(message) {
14
+ super(
15
+ message ?? "OpenApiRegistry requires @anatine/zod-openapi. Install it: bun add @anatine/zod-openapi"
16
+ );
17
+ }
18
+ };
19
+ var DuplicateSchemaError = class extends Error {
20
+ constructor(schemaName) {
21
+ super(
22
+ `DuplicateSchemaError: schema '${schemaName}' is already registered. Each schema name must be unique within the OpenApiRegistry.`
23
+ );
24
+ this.schemaName = schemaName;
25
+ }
26
+ schemaName;
27
+ name = "DuplicateSchemaError";
28
+ };
29
+
30
+ // runtime/shared/openapi/registry.ts
31
+ var OpenApiRegistry = class {
32
+ zodSchemas = /* @__PURE__ */ new Map();
33
+ pathEntries = /* @__PURE__ */ new Map();
34
+ peer = null;
35
+ constructor() {
36
+ this.zodSchemas.set(ERROR_RESPONSE_SCHEMA_NAME, errorResponseSchema);
37
+ }
38
+ registerSchema(name, schema) {
39
+ if (this.zodSchemas.has(name)) {
40
+ throw new DuplicateSchemaError(name);
41
+ }
42
+ this.zodSchemas.set(name, schema);
43
+ }
44
+ registerPath(path, method, spec) {
45
+ let methods = this.pathEntries.get(path);
46
+ if (!methods) {
47
+ methods = /* @__PURE__ */ new Map();
48
+ this.pathEntries.set(path, methods);
49
+ }
50
+ methods.set(method, spec);
51
+ }
52
+ /**
53
+ * Emit the full OpenAPI document. Lazy-imports `@anatine/zod-openapi`
54
+ * on first call; failure to resolve raises `OpenApiPeerDepMissingError`
55
+ * (matches the `CubeAnalyticsBackend.onModuleInit` precedent).
56
+ *
57
+ * OpenAPI version is pinned to `3.0.3` — Swagger UI tooling is most
58
+ * stable on 3.0.x (see OPENAPI-PHASE-1-PLAN §Four locked decisions).
59
+ */
60
+ async build(info) {
61
+ const peer = await this.loadPeer();
62
+ const schemas = {};
63
+ for (const [name, zodSchema] of this.zodSchemas) {
64
+ schemas[name] = peer.generateSchema(zodSchema, false, "3.0");
65
+ }
66
+ const paths = {};
67
+ for (const [path, methods] of this.pathEntries) {
68
+ const methodMap = {};
69
+ for (const [method, spec] of methods) {
70
+ methodMap[method] = spec;
71
+ }
72
+ paths[path] = methodMap;
73
+ }
74
+ return {
75
+ openapi: "3.0.3",
76
+ info,
77
+ paths,
78
+ components: { schemas }
79
+ };
80
+ }
81
+ /**
82
+ * Test helper — clears registered schemas and paths, then re-seeds the
83
+ * core `ErrorResponseDto` entry so post-reset state matches the
84
+ * invariant established in the constructor.
85
+ */
86
+ reset() {
87
+ this.zodSchemas.clear();
88
+ this.pathEntries.clear();
89
+ this.peer = null;
90
+ this.zodSchemas.set(ERROR_RESPONSE_SCHEMA_NAME, errorResponseSchema);
91
+ }
92
+ async loadPeer() {
93
+ if (this.peer) return this.peer;
94
+ try {
95
+ const specifier = "@anatine/zod-openapi";
96
+ const mod = await import(specifier);
97
+ this.peer = mod;
98
+ return mod;
99
+ } catch {
100
+ throw new OpenApiPeerDepMissingError();
101
+ }
102
+ }
103
+ };
104
+
105
+ // runtime/shared/openapi/registry.tokens.ts
106
+ var OPENAPI_REGISTRY = "OPENAPI_REGISTRY";
107
+ export {
108
+ DuplicateSchemaError,
109
+ ERROR_RESPONSE_SCHEMA_NAME,
110
+ OPENAPI_REGISTRY,
111
+ OpenApiPeerDepMissingError,
112
+ OpenApiRegistry,
113
+ errorResponseSchema
114
+ };
115
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../runtime/shared/openapi/error-response.dto.ts","../../../../runtime/shared/openapi/errors.ts","../../../../runtime/shared/openapi/registry.ts","../../../../runtime/shared/openapi/registry.tokens.ts"],"sourcesContent":["/**\n * Shared error response schema (OPENAPI-3).\n *\n * Generated controllers `@ApiResponse(...)` decorators reference this\n * schema by `$ref` (name `ErrorResponseDto`) for non-success status codes\n * (400, 401, 404, etc.). Shape matches NestJS's default `HttpException`\n * JSON body — see `packages/common/src/exceptions/http.exception.ts`.\n *\n * The registry auto-registers this schema on construction so every\n * consumer project exposes `components.schemas.ErrorResponseDto` on\n * `/docs-json` without per-entity duplication.\n */\nimport { z } from 'zod';\n\nexport const errorResponseSchema = z.object({\n statusCode: z.number().int(),\n message: z.union([z.string(), z.array(z.string())]),\n error: z.string().optional(),\n});\n\nexport type ErrorResponseDto = z.infer<typeof errorResponseSchema>;\n\n/** Canonical name used across `$ref` URIs in generated controllers. */\nexport const ERROR_RESPONSE_SCHEMA_NAME = 'ErrorResponseDto';\n","/**\n * Typed errors for the OpenAPI registry (OPENAPI-1).\n *\n * Same shape as `runtime/subsystems/bridge/bridge-errors.ts` so consumers\n * can catch them with the same exception-filter pattern used elsewhere.\n */\n\n/**\n * Thrown by `OpenApiRegistry.build()` when `@anatine/zod-openapi` is not\n * resolvable. The peer is declared optional (`peerDependenciesMeta`) so\n * consumer apps that don't care about OpenAPI still boot; the cost is a\n * deferred failure here on first `build()`.\n */\nexport class OpenApiPeerDepMissingError extends Error {\n override readonly name = 'OpenApiPeerDepMissingError';\n constructor(message?: string) {\n super(\n message ??\n 'OpenApiRegistry requires @anatine/zod-openapi. Install it: bun add @anatine/zod-openapi',\n );\n }\n}\n\n/**\n * Thrown by `OpenApiRegistry.registerSchema(name, ...)` when `name` is\n * already registered. Silent overwrite would make debugging\n * double-registration bugs (e.g. two entity pipelines both emitting a\n * `User` DTO) painful; loud failure lets the mismatch surface at module\n * init where the stack trace is clear.\n */\nexport class DuplicateSchemaError extends Error {\n override readonly name = 'DuplicateSchemaError';\n constructor(public readonly schemaName: string) {\n super(\n `DuplicateSchemaError: schema '${schemaName}' is already registered. ` +\n `Each schema name must be unique within the OpenApiRegistry.`,\n );\n }\n}\n","/**\n * OpenApiRegistry — collects Zod schemas and path specs, emits a\n * complete `OpenAPIObject` on `build()` (OPENAPI-1).\n *\n * Wraps `@anatine/zod-openapi` as an **optional peer dependency** using\n * the lazy-import pattern from `runtime/subsystems/analytics/cube-backend.ts`\n * — consumer apps that never call `build()` still boot even if\n * `@anatine/zod-openapi` isn't installed.\n *\n * The registry is the single source of truth consumed by OPENAPI-2\n * (generated DTOs register their Zod schemas at module init), OPENAPI-3\n * (controller decorators reference those schemas), and OPENAPI-4\n * (Swagger UI bootstrap calls `build()` once at startup).\n */\nimport type { z } from 'zod';\n\nimport { ERROR_RESPONSE_SCHEMA_NAME, errorResponseSchema } from './error-response.dto';\nimport { OpenApiPeerDepMissingError, DuplicateSchemaError } from './errors';\n\nexport type HttpMethod = 'get' | 'post' | 'patch' | 'delete' | 'put';\n\n/**\n * OpenAPI path spec. Structurally compatible with `openapi3-ts`'s\n * `OperationObject` but typed loosely here because the peer type package\n * isn't installed as a direct dep — consumers supply whatever their\n * codegen emits.\n */\nexport interface PathSpec {\n summary?: string;\n description?: string;\n operationId?: string;\n tags?: string[];\n parameters?: unknown[];\n requestBody?: unknown;\n responses?: Record<string, unknown>;\n security?: unknown[];\n [key: string]: unknown;\n}\n\nexport interface OpenAPIInfo {\n title: string;\n version: string;\n description?: string;\n}\n\n/**\n * Minimal OpenAPIObject shape. We redeclare rather than pull\n * `openapi3-ts` types through the peer — the peer's `generateSchema`\n * returns a `SchemaObject`, but the final document assembly is ours.\n */\nexport interface OpenAPIObject {\n openapi: string;\n info: OpenAPIInfo;\n paths: Record<string, Record<string, PathSpec>>;\n components: {\n schemas: Record<string, unknown>;\n };\n}\n\ninterface PeerModule {\n generateSchema: (zodRef: unknown, useOutput?: boolean, version?: '3.0' | '3.1') => unknown;\n}\n\nexport class OpenApiRegistry {\n private zodSchemas = new Map<string, z.ZodType>();\n private pathEntries = new Map<string, Map<HttpMethod, PathSpec>>();\n private peer: PeerModule | null = null;\n\n constructor() {\n // Auto-register the shared error response schema so controllers that\n // reference `#/components/schemas/ErrorResponseDto` always resolve\n // (OPENAPI-3). Consumers can `reset()` + re-register in tests.\n this.zodSchemas.set(ERROR_RESPONSE_SCHEMA_NAME, errorResponseSchema);\n }\n\n registerSchema(name: string, schema: z.ZodType): void {\n if (this.zodSchemas.has(name)) {\n throw new DuplicateSchemaError(name);\n }\n this.zodSchemas.set(name, schema);\n }\n\n registerPath(path: string, method: HttpMethod, spec: PathSpec): void {\n let methods = this.pathEntries.get(path);\n if (!methods) {\n methods = new Map();\n this.pathEntries.set(path, methods);\n }\n methods.set(method, spec);\n }\n\n /**\n * Emit the full OpenAPI document. Lazy-imports `@anatine/zod-openapi`\n * on first call; failure to resolve raises `OpenApiPeerDepMissingError`\n * (matches the `CubeAnalyticsBackend.onModuleInit` precedent).\n *\n * OpenAPI version is pinned to `3.0.3` — Swagger UI tooling is most\n * stable on 3.0.x (see OPENAPI-PHASE-1-PLAN §Four locked decisions).\n */\n async build(info: OpenAPIInfo): Promise<OpenAPIObject> {\n const peer = await this.loadPeer();\n\n const schemas: Record<string, unknown> = {};\n for (const [name, zodSchema] of this.zodSchemas) {\n schemas[name] = peer.generateSchema(zodSchema, false, '3.0');\n }\n\n const paths: Record<string, Record<string, PathSpec>> = {};\n for (const [path, methods] of this.pathEntries) {\n const methodMap: Record<string, PathSpec> = {};\n for (const [method, spec] of methods) {\n methodMap[method] = spec;\n }\n paths[path] = methodMap;\n }\n\n return {\n openapi: '3.0.3',\n info,\n paths,\n components: { schemas },\n };\n }\n\n /**\n * Test helper — clears registered schemas and paths, then re-seeds the\n * core `ErrorResponseDto` entry so post-reset state matches the\n * invariant established in the constructor.\n */\n reset(): void {\n this.zodSchemas.clear();\n this.pathEntries.clear();\n this.peer = null;\n this.zodSchemas.set(ERROR_RESPONSE_SCHEMA_NAME, errorResponseSchema);\n }\n\n protected async loadPeer(): Promise<PeerModule> {\n if (this.peer) return this.peer;\n try {\n // Computed specifier: prevents tsc from resolving this import at\n // typecheck time. Consumers vendor this file but may not install\n // @anatine/zod-openapi (optional peer).\n const specifier: string = '@anatine/zod-openapi';\n const mod = (await import(specifier)) as PeerModule;\n this.peer = mod;\n return mod;\n } catch {\n throw new OpenApiPeerDepMissingError();\n }\n }\n}\n","/**\n * Injection token for the OpenAPI registry (OPENAPI-1).\n *\n * String constant (not a Symbol) so it matches by value across import\n * boundaries — same convention as `ANALYTICS_QUERY` in analytics and\n * `EVENT_BUS` / `BRIDGE_DELIVERY_REPO` in events / bridge. The OPENAPI-1\n * spec sketched a Symbol, but the repo-wide convention wins — codebase\n * consistency matters more than the spec's initial guess.\n *\n * Consumed by generated DTO providers (OPENAPI-2), controllers\n * (OPENAPI-3), and the Swagger bootstrap (OPENAPI-4).\n */\nexport const OPENAPI_REGISTRY = 'OPENAPI_REGISTRY' as const;\n"],"mappings":";AAYA,SAAS,SAAS;AAEX,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,YAAY,EAAE,OAAO,EAAE,IAAI;AAAA,EAC3B,SAAS,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAAA,EAClD,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAKM,IAAM,6BAA6B;;;ACVnC,IAAM,6BAAN,cAAyC,MAAM;AAAA,EAClC,OAAO;AAAA,EACzB,YAAY,SAAkB;AAC5B;AAAA,MACE,WACE;AAAA,IACJ;AAAA,EACF;AACF;AASO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAE9C,YAA4B,YAAoB;AAC9C;AAAA,MACE,iCAAiC,UAAU;AAAA,IAE7C;AAJ0B;AAAA,EAK5B;AAAA,EAL4B;AAAA,EADV,OAAO;AAO3B;;;ACyBO,IAAM,kBAAN,MAAsB;AAAA,EACnB,aAAa,oBAAI,IAAuB;AAAA,EACxC,cAAc,oBAAI,IAAuC;AAAA,EACzD,OAA0B;AAAA,EAElC,cAAc;AAIZ,SAAK,WAAW,IAAI,4BAA4B,mBAAmB;AAAA,EACrE;AAAA,EAEA,eAAe,MAAc,QAAyB;AACpD,QAAI,KAAK,WAAW,IAAI,IAAI,GAAG;AAC7B,YAAM,IAAI,qBAAqB,IAAI;AAAA,IACrC;AACA,SAAK,WAAW,IAAI,MAAM,MAAM;AAAA,EAClC;AAAA,EAEA,aAAa,MAAc,QAAoB,MAAsB;AACnE,QAAI,UAAU,KAAK,YAAY,IAAI,IAAI;AACvC,QAAI,CAAC,SAAS;AACZ,gBAAU,oBAAI,IAAI;AAClB,WAAK,YAAY,IAAI,MAAM,OAAO;AAAA,IACpC;AACA,YAAQ,IAAI,QAAQ,IAAI;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,MAAM,MAA2C;AACrD,UAAM,OAAO,MAAM,KAAK,SAAS;AAEjC,UAAM,UAAmC,CAAC;AAC1C,eAAW,CAAC,MAAM,SAAS,KAAK,KAAK,YAAY;AAC/C,cAAQ,IAAI,IAAI,KAAK,eAAe,WAAW,OAAO,KAAK;AAAA,IAC7D;AAEA,UAAM,QAAkD,CAAC;AACzD,eAAW,CAAC,MAAM,OAAO,KAAK,KAAK,aAAa;AAC9C,YAAM,YAAsC,CAAC;AAC7C,iBAAW,CAAC,QAAQ,IAAI,KAAK,SAAS;AACpC,kBAAU,MAAM,IAAI;AAAA,MACtB;AACA,YAAM,IAAI,IAAI;AAAA,IAChB;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,YAAY,EAAE,QAAQ;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAc;AACZ,SAAK,WAAW,MAAM;AACtB,SAAK,YAAY,MAAM;AACvB,SAAK,OAAO;AACZ,SAAK,WAAW,IAAI,4BAA4B,mBAAmB;AAAA,EACrE;AAAA,EAEA,MAAgB,WAAgC;AAC9C,QAAI,KAAK,KAAM,QAAO,KAAK;AAC3B,QAAI;AAIF,YAAM,YAAoB;AAC1B,YAAM,MAAO,MAAM,OAAO;AAC1B,WAAK,OAAO;AACZ,aAAO;AAAA,IACT,QAAQ;AACN,YAAM,IAAI,2BAA2B;AAAA,IACvC;AAAA,EACF;AACF;;;AC1IO,IAAM,mBAAmB;","names":[]}
@@ -0,0 +1,82 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * OpenApiRegistry — collects Zod schemas and path specs, emits a
5
+ * complete `OpenAPIObject` on `build()` (OPENAPI-1).
6
+ *
7
+ * Wraps `@anatine/zod-openapi` as an **optional peer dependency** using
8
+ * the lazy-import pattern from `runtime/subsystems/analytics/cube-backend.ts`
9
+ * — consumer apps that never call `build()` still boot even if
10
+ * `@anatine/zod-openapi` isn't installed.
11
+ *
12
+ * The registry is the single source of truth consumed by OPENAPI-2
13
+ * (generated DTOs register their Zod schemas at module init), OPENAPI-3
14
+ * (controller decorators reference those schemas), and OPENAPI-4
15
+ * (Swagger UI bootstrap calls `build()` once at startup).
16
+ */
17
+
18
+ type HttpMethod = 'get' | 'post' | 'patch' | 'delete' | 'put';
19
+ /**
20
+ * OpenAPI path spec. Structurally compatible with `openapi3-ts`'s
21
+ * `OperationObject` but typed loosely here because the peer type package
22
+ * isn't installed as a direct dep — consumers supply whatever their
23
+ * codegen emits.
24
+ */
25
+ interface PathSpec {
26
+ summary?: string;
27
+ description?: string;
28
+ operationId?: string;
29
+ tags?: string[];
30
+ parameters?: unknown[];
31
+ requestBody?: unknown;
32
+ responses?: Record<string, unknown>;
33
+ security?: unknown[];
34
+ [key: string]: unknown;
35
+ }
36
+ interface OpenAPIInfo {
37
+ title: string;
38
+ version: string;
39
+ description?: string;
40
+ }
41
+ /**
42
+ * Minimal OpenAPIObject shape. We redeclare rather than pull
43
+ * `openapi3-ts` types through the peer — the peer's `generateSchema`
44
+ * returns a `SchemaObject`, but the final document assembly is ours.
45
+ */
46
+ interface OpenAPIObject {
47
+ openapi: string;
48
+ info: OpenAPIInfo;
49
+ paths: Record<string, Record<string, PathSpec>>;
50
+ components: {
51
+ schemas: Record<string, unknown>;
52
+ };
53
+ }
54
+ interface PeerModule {
55
+ generateSchema: (zodRef: unknown, useOutput?: boolean, version?: '3.0' | '3.1') => unknown;
56
+ }
57
+ declare class OpenApiRegistry {
58
+ private zodSchemas;
59
+ private pathEntries;
60
+ private peer;
61
+ constructor();
62
+ registerSchema(name: string, schema: z.ZodType): void;
63
+ registerPath(path: string, method: HttpMethod, spec: PathSpec): void;
64
+ /**
65
+ * Emit the full OpenAPI document. Lazy-imports `@anatine/zod-openapi`
66
+ * on first call; failure to resolve raises `OpenApiPeerDepMissingError`
67
+ * (matches the `CubeAnalyticsBackend.onModuleInit` precedent).
68
+ *
69
+ * OpenAPI version is pinned to `3.0.3` — Swagger UI tooling is most
70
+ * stable on 3.0.x (see OPENAPI-PHASE-1-PLAN §Four locked decisions).
71
+ */
72
+ build(info: OpenAPIInfo): Promise<OpenAPIObject>;
73
+ /**
74
+ * Test helper — clears registered schemas and paths, then re-seeds the
75
+ * core `ErrorResponseDto` entry so post-reset state matches the
76
+ * invariant established in the constructor.
77
+ */
78
+ reset(): void;
79
+ protected loadPeer(): Promise<PeerModule>;
80
+ }
81
+
82
+ export { type HttpMethod, type OpenAPIInfo, type OpenAPIObject, OpenApiRegistry, type PathSpec };
@@ -0,0 +1,107 @@
1
+ // runtime/shared/openapi/error-response.dto.ts
2
+ import { z } from "zod";
3
+ var errorResponseSchema = z.object({
4
+ statusCode: z.number().int(),
5
+ message: z.union([z.string(), z.array(z.string())]),
6
+ error: z.string().optional()
7
+ });
8
+ var ERROR_RESPONSE_SCHEMA_NAME = "ErrorResponseDto";
9
+
10
+ // runtime/shared/openapi/errors.ts
11
+ var OpenApiPeerDepMissingError = class extends Error {
12
+ name = "OpenApiPeerDepMissingError";
13
+ constructor(message) {
14
+ super(
15
+ message ?? "OpenApiRegistry requires @anatine/zod-openapi. Install it: bun add @anatine/zod-openapi"
16
+ );
17
+ }
18
+ };
19
+ var DuplicateSchemaError = class extends Error {
20
+ constructor(schemaName) {
21
+ super(
22
+ `DuplicateSchemaError: schema '${schemaName}' is already registered. Each schema name must be unique within the OpenApiRegistry.`
23
+ );
24
+ this.schemaName = schemaName;
25
+ }
26
+ schemaName;
27
+ name = "DuplicateSchemaError";
28
+ };
29
+
30
+ // runtime/shared/openapi/registry.ts
31
+ var OpenApiRegistry = class {
32
+ zodSchemas = /* @__PURE__ */ new Map();
33
+ pathEntries = /* @__PURE__ */ new Map();
34
+ peer = null;
35
+ constructor() {
36
+ this.zodSchemas.set(ERROR_RESPONSE_SCHEMA_NAME, errorResponseSchema);
37
+ }
38
+ registerSchema(name, schema) {
39
+ if (this.zodSchemas.has(name)) {
40
+ throw new DuplicateSchemaError(name);
41
+ }
42
+ this.zodSchemas.set(name, schema);
43
+ }
44
+ registerPath(path, method, spec) {
45
+ let methods = this.pathEntries.get(path);
46
+ if (!methods) {
47
+ methods = /* @__PURE__ */ new Map();
48
+ this.pathEntries.set(path, methods);
49
+ }
50
+ methods.set(method, spec);
51
+ }
52
+ /**
53
+ * Emit the full OpenAPI document. Lazy-imports `@anatine/zod-openapi`
54
+ * on first call; failure to resolve raises `OpenApiPeerDepMissingError`
55
+ * (matches the `CubeAnalyticsBackend.onModuleInit` precedent).
56
+ *
57
+ * OpenAPI version is pinned to `3.0.3` — Swagger UI tooling is most
58
+ * stable on 3.0.x (see OPENAPI-PHASE-1-PLAN §Four locked decisions).
59
+ */
60
+ async build(info) {
61
+ const peer = await this.loadPeer();
62
+ const schemas = {};
63
+ for (const [name, zodSchema] of this.zodSchemas) {
64
+ schemas[name] = peer.generateSchema(zodSchema, false, "3.0");
65
+ }
66
+ const paths = {};
67
+ for (const [path, methods] of this.pathEntries) {
68
+ const methodMap = {};
69
+ for (const [method, spec] of methods) {
70
+ methodMap[method] = spec;
71
+ }
72
+ paths[path] = methodMap;
73
+ }
74
+ return {
75
+ openapi: "3.0.3",
76
+ info,
77
+ paths,
78
+ components: { schemas }
79
+ };
80
+ }
81
+ /**
82
+ * Test helper — clears registered schemas and paths, then re-seeds the
83
+ * core `ErrorResponseDto` entry so post-reset state matches the
84
+ * invariant established in the constructor.
85
+ */
86
+ reset() {
87
+ this.zodSchemas.clear();
88
+ this.pathEntries.clear();
89
+ this.peer = null;
90
+ this.zodSchemas.set(ERROR_RESPONSE_SCHEMA_NAME, errorResponseSchema);
91
+ }
92
+ async loadPeer() {
93
+ if (this.peer) return this.peer;
94
+ try {
95
+ const specifier = "@anatine/zod-openapi";
96
+ const mod = await import(specifier);
97
+ this.peer = mod;
98
+ return mod;
99
+ } catch {
100
+ throw new OpenApiPeerDepMissingError();
101
+ }
102
+ }
103
+ };
104
+ export {
105
+ OpenApiRegistry
106
+ };
107
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../runtime/shared/openapi/error-response.dto.ts","../../../../runtime/shared/openapi/errors.ts","../../../../runtime/shared/openapi/registry.ts"],"sourcesContent":["/**\n * Shared error response schema (OPENAPI-3).\n *\n * Generated controllers `@ApiResponse(...)` decorators reference this\n * schema by `$ref` (name `ErrorResponseDto`) for non-success status codes\n * (400, 401, 404, etc.). Shape matches NestJS's default `HttpException`\n * JSON body — see `packages/common/src/exceptions/http.exception.ts`.\n *\n * The registry auto-registers this schema on construction so every\n * consumer project exposes `components.schemas.ErrorResponseDto` on\n * `/docs-json` without per-entity duplication.\n */\nimport { z } from 'zod';\n\nexport const errorResponseSchema = z.object({\n statusCode: z.number().int(),\n message: z.union([z.string(), z.array(z.string())]),\n error: z.string().optional(),\n});\n\nexport type ErrorResponseDto = z.infer<typeof errorResponseSchema>;\n\n/** Canonical name used across `$ref` URIs in generated controllers. */\nexport const ERROR_RESPONSE_SCHEMA_NAME = 'ErrorResponseDto';\n","/**\n * Typed errors for the OpenAPI registry (OPENAPI-1).\n *\n * Same shape as `runtime/subsystems/bridge/bridge-errors.ts` so consumers\n * can catch them with the same exception-filter pattern used elsewhere.\n */\n\n/**\n * Thrown by `OpenApiRegistry.build()` when `@anatine/zod-openapi` is not\n * resolvable. The peer is declared optional (`peerDependenciesMeta`) so\n * consumer apps that don't care about OpenAPI still boot; the cost is a\n * deferred failure here on first `build()`.\n */\nexport class OpenApiPeerDepMissingError extends Error {\n override readonly name = 'OpenApiPeerDepMissingError';\n constructor(message?: string) {\n super(\n message ??\n 'OpenApiRegistry requires @anatine/zod-openapi. Install it: bun add @anatine/zod-openapi',\n );\n }\n}\n\n/**\n * Thrown by `OpenApiRegistry.registerSchema(name, ...)` when `name` is\n * already registered. Silent overwrite would make debugging\n * double-registration bugs (e.g. two entity pipelines both emitting a\n * `User` DTO) painful; loud failure lets the mismatch surface at module\n * init where the stack trace is clear.\n */\nexport class DuplicateSchemaError extends Error {\n override readonly name = 'DuplicateSchemaError';\n constructor(public readonly schemaName: string) {\n super(\n `DuplicateSchemaError: schema '${schemaName}' is already registered. ` +\n `Each schema name must be unique within the OpenApiRegistry.`,\n );\n }\n}\n","/**\n * OpenApiRegistry — collects Zod schemas and path specs, emits a\n * complete `OpenAPIObject` on `build()` (OPENAPI-1).\n *\n * Wraps `@anatine/zod-openapi` as an **optional peer dependency** using\n * the lazy-import pattern from `runtime/subsystems/analytics/cube-backend.ts`\n * — consumer apps that never call `build()` still boot even if\n * `@anatine/zod-openapi` isn't installed.\n *\n * The registry is the single source of truth consumed by OPENAPI-2\n * (generated DTOs register their Zod schemas at module init), OPENAPI-3\n * (controller decorators reference those schemas), and OPENAPI-4\n * (Swagger UI bootstrap calls `build()` once at startup).\n */\nimport type { z } from 'zod';\n\nimport { ERROR_RESPONSE_SCHEMA_NAME, errorResponseSchema } from './error-response.dto';\nimport { OpenApiPeerDepMissingError, DuplicateSchemaError } from './errors';\n\nexport type HttpMethod = 'get' | 'post' | 'patch' | 'delete' | 'put';\n\n/**\n * OpenAPI path spec. Structurally compatible with `openapi3-ts`'s\n * `OperationObject` but typed loosely here because the peer type package\n * isn't installed as a direct dep — consumers supply whatever their\n * codegen emits.\n */\nexport interface PathSpec {\n summary?: string;\n description?: string;\n operationId?: string;\n tags?: string[];\n parameters?: unknown[];\n requestBody?: unknown;\n responses?: Record<string, unknown>;\n security?: unknown[];\n [key: string]: unknown;\n}\n\nexport interface OpenAPIInfo {\n title: string;\n version: string;\n description?: string;\n}\n\n/**\n * Minimal OpenAPIObject shape. We redeclare rather than pull\n * `openapi3-ts` types through the peer — the peer's `generateSchema`\n * returns a `SchemaObject`, but the final document assembly is ours.\n */\nexport interface OpenAPIObject {\n openapi: string;\n info: OpenAPIInfo;\n paths: Record<string, Record<string, PathSpec>>;\n components: {\n schemas: Record<string, unknown>;\n };\n}\n\ninterface PeerModule {\n generateSchema: (zodRef: unknown, useOutput?: boolean, version?: '3.0' | '3.1') => unknown;\n}\n\nexport class OpenApiRegistry {\n private zodSchemas = new Map<string, z.ZodType>();\n private pathEntries = new Map<string, Map<HttpMethod, PathSpec>>();\n private peer: PeerModule | null = null;\n\n constructor() {\n // Auto-register the shared error response schema so controllers that\n // reference `#/components/schemas/ErrorResponseDto` always resolve\n // (OPENAPI-3). Consumers can `reset()` + re-register in tests.\n this.zodSchemas.set(ERROR_RESPONSE_SCHEMA_NAME, errorResponseSchema);\n }\n\n registerSchema(name: string, schema: z.ZodType): void {\n if (this.zodSchemas.has(name)) {\n throw new DuplicateSchemaError(name);\n }\n this.zodSchemas.set(name, schema);\n }\n\n registerPath(path: string, method: HttpMethod, spec: PathSpec): void {\n let methods = this.pathEntries.get(path);\n if (!methods) {\n methods = new Map();\n this.pathEntries.set(path, methods);\n }\n methods.set(method, spec);\n }\n\n /**\n * Emit the full OpenAPI document. Lazy-imports `@anatine/zod-openapi`\n * on first call; failure to resolve raises `OpenApiPeerDepMissingError`\n * (matches the `CubeAnalyticsBackend.onModuleInit` precedent).\n *\n * OpenAPI version is pinned to `3.0.3` — Swagger UI tooling is most\n * stable on 3.0.x (see OPENAPI-PHASE-1-PLAN §Four locked decisions).\n */\n async build(info: OpenAPIInfo): Promise<OpenAPIObject> {\n const peer = await this.loadPeer();\n\n const schemas: Record<string, unknown> = {};\n for (const [name, zodSchema] of this.zodSchemas) {\n schemas[name] = peer.generateSchema(zodSchema, false, '3.0');\n }\n\n const paths: Record<string, Record<string, PathSpec>> = {};\n for (const [path, methods] of this.pathEntries) {\n const methodMap: Record<string, PathSpec> = {};\n for (const [method, spec] of methods) {\n methodMap[method] = spec;\n }\n paths[path] = methodMap;\n }\n\n return {\n openapi: '3.0.3',\n info,\n paths,\n components: { schemas },\n };\n }\n\n /**\n * Test helper — clears registered schemas and paths, then re-seeds the\n * core `ErrorResponseDto` entry so post-reset state matches the\n * invariant established in the constructor.\n */\n reset(): void {\n this.zodSchemas.clear();\n this.pathEntries.clear();\n this.peer = null;\n this.zodSchemas.set(ERROR_RESPONSE_SCHEMA_NAME, errorResponseSchema);\n }\n\n protected async loadPeer(): Promise<PeerModule> {\n if (this.peer) return this.peer;\n try {\n // Computed specifier: prevents tsc from resolving this import at\n // typecheck time. Consumers vendor this file but may not install\n // @anatine/zod-openapi (optional peer).\n const specifier: string = '@anatine/zod-openapi';\n const mod = (await import(specifier)) as PeerModule;\n this.peer = mod;\n return mod;\n } catch {\n throw new OpenApiPeerDepMissingError();\n }\n }\n}\n"],"mappings":";AAYA,SAAS,SAAS;AAEX,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,YAAY,EAAE,OAAO,EAAE,IAAI;AAAA,EAC3B,SAAS,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAAA,EAClD,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAKM,IAAM,6BAA6B;;;ACVnC,IAAM,6BAAN,cAAyC,MAAM;AAAA,EAClC,OAAO;AAAA,EACzB,YAAY,SAAkB;AAC5B;AAAA,MACE,WACE;AAAA,IACJ;AAAA,EACF;AACF;AASO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAE9C,YAA4B,YAAoB;AAC9C;AAAA,MACE,iCAAiC,UAAU;AAAA,IAE7C;AAJ0B;AAAA,EAK5B;AAAA,EAL4B;AAAA,EADV,OAAO;AAO3B;;;ACyBO,IAAM,kBAAN,MAAsB;AAAA,EACnB,aAAa,oBAAI,IAAuB;AAAA,EACxC,cAAc,oBAAI,IAAuC;AAAA,EACzD,OAA0B;AAAA,EAElC,cAAc;AAIZ,SAAK,WAAW,IAAI,4BAA4B,mBAAmB;AAAA,EACrE;AAAA,EAEA,eAAe,MAAc,QAAyB;AACpD,QAAI,KAAK,WAAW,IAAI,IAAI,GAAG;AAC7B,YAAM,IAAI,qBAAqB,IAAI;AAAA,IACrC;AACA,SAAK,WAAW,IAAI,MAAM,MAAM;AAAA,EAClC;AAAA,EAEA,aAAa,MAAc,QAAoB,MAAsB;AACnE,QAAI,UAAU,KAAK,YAAY,IAAI,IAAI;AACvC,QAAI,CAAC,SAAS;AACZ,gBAAU,oBAAI,IAAI;AAClB,WAAK,YAAY,IAAI,MAAM,OAAO;AAAA,IACpC;AACA,YAAQ,IAAI,QAAQ,IAAI;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,MAAM,MAA2C;AACrD,UAAM,OAAO,MAAM,KAAK,SAAS;AAEjC,UAAM,UAAmC,CAAC;AAC1C,eAAW,CAAC,MAAM,SAAS,KAAK,KAAK,YAAY;AAC/C,cAAQ,IAAI,IAAI,KAAK,eAAe,WAAW,OAAO,KAAK;AAAA,IAC7D;AAEA,UAAM,QAAkD,CAAC;AACzD,eAAW,CAAC,MAAM,OAAO,KAAK,KAAK,aAAa;AAC9C,YAAM,YAAsC,CAAC;AAC7C,iBAAW,CAAC,QAAQ,IAAI,KAAK,SAAS;AACpC,kBAAU,MAAM,IAAI;AAAA,MACtB;AACA,YAAM,IAAI,IAAI;AAAA,IAChB;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,YAAY,EAAE,QAAQ;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAc;AACZ,SAAK,WAAW,MAAM;AACtB,SAAK,YAAY,MAAM;AACvB,SAAK,OAAO;AACZ,SAAK,WAAW,IAAI,4BAA4B,mBAAmB;AAAA,EACrE;AAAA,EAEA,MAAgB,WAAgC;AAC9C,QAAI,KAAK,KAAM,QAAO,KAAK;AAC3B,QAAI;AAIF,YAAM,YAAoB;AAC1B,YAAM,MAAO,MAAM,OAAO;AAC1B,WAAK,OAAO;AACZ,aAAO;AAAA,IACT,QAAQ;AACN,YAAM,IAAI,2BAA2B;AAAA,IACvC;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Injection token for the OpenAPI registry (OPENAPI-1).
3
+ *
4
+ * String constant (not a Symbol) so it matches by value across import
5
+ * boundaries — same convention as `ANALYTICS_QUERY` in analytics and
6
+ * `EVENT_BUS` / `BRIDGE_DELIVERY_REPO` in events / bridge. The OPENAPI-1
7
+ * spec sketched a Symbol, but the repo-wide convention wins — codebase
8
+ * consistency matters more than the spec's initial guess.
9
+ *
10
+ * Consumed by generated DTO providers (OPENAPI-2), controllers
11
+ * (OPENAPI-3), and the Swagger bootstrap (OPENAPI-4).
12
+ */
13
+ declare const OPENAPI_REGISTRY: "OPENAPI_REGISTRY";
14
+
15
+ export { OPENAPI_REGISTRY };
@@ -0,0 +1,6 @@
1
+ // runtime/shared/openapi/registry.tokens.ts
2
+ var OPENAPI_REGISTRY = "OPENAPI_REGISTRY";
3
+ export {
4
+ OPENAPI_REGISTRY
5
+ };
6
+ //# sourceMappingURL=registry.tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../runtime/shared/openapi/registry.tokens.ts"],"sourcesContent":["/**\n * Injection token for the OpenAPI registry (OPENAPI-1).\n *\n * String constant (not a Symbol) so it matches by value across import\n * boundaries — same convention as `ANALYTICS_QUERY` in analytics and\n * `EVENT_BUS` / `BRIDGE_DELIVERY_REPO` in events / bridge. The OPENAPI-1\n * spec sketched a Symbol, but the repo-wide convention wins — codebase\n * consistency matters more than the spec's initial guess.\n *\n * Consumed by generated DTO providers (OPENAPI-2), controllers\n * (OPENAPI-3), and the Swagger bootstrap (OPENAPI-4).\n */\nexport const OPENAPI_REGISTRY = 'OPENAPI_REGISTRY' as const;\n"],"mappings":";AAYO,IAAM,mBAAmB;","names":[]}
@@ -357,7 +357,7 @@ declare const syncRuns: drizzle_orm_pg_core.PgTableWithColumns<{
357
357
  tableName: "sync_runs";
358
358
  dataType: "string";
359
359
  columnType: "PgEnumColumn";
360
- data: "success" | "no_changes" | "failed" | "running";
360
+ data: "success" | "failed" | "no_changes" | "running";
361
361
  driverParam: string;
362
362
  notNull: true;
363
363
  hasDefault: true;
@@ -639,7 +639,7 @@ declare const syncRunItems: drizzle_orm_pg_core.PgTableWithColumns<{
639
639
  tableName: "sync_run_items";
640
640
  dataType: "string";
641
641
  columnType: "PgEnumColumn";
642
- data: "created" | "updated" | "deleted" | "noop";
642
+ data: "noop" | "created" | "updated" | "deleted";
643
643
  driverParam: string;
644
644
  notNull: true;
645
645
  hasDefault: false;