@palbase/backend 30.0.1 → 33.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/palbase-backend.cjs +210 -24
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +7 -7
- package/dist/{chunk-TWX6JTGJ.js → chunk-26GH54D2.js} +3 -5
- package/dist/{chunk-TWX6JTGJ.js.map → chunk-26GH54D2.js.map} +1 -1
- package/dist/{chunk-VVMJEVQP.js → chunk-BRLJOXWS.js} +2 -2
- package/dist/{chunk-3TUJWHC2.js → chunk-C4ZA5AT2.js} +378 -19
- package/dist/chunk-C4ZA5AT2.js.map +1 -0
- package/dist/{chunk-RADVOY7Y.js → chunk-DCDHAKF3.js} +147 -33
- package/dist/chunk-DCDHAKF3.js.map +1 -0
- package/dist/{chunk-ENZ2RFFJ.js → chunk-GOPZPM2A.js} +3 -310
- package/dist/chunk-GOPZPM2A.js.map +1 -0
- package/dist/{chunk-CGNN2PUH.js → chunk-KATPXCJ5.js} +37 -4
- package/dist/{chunk-CGNN2PUH.js.map → chunk-KATPXCJ5.js.map} +1 -1
- package/dist/{chunk-YRVIWHJC.js → chunk-N54QZER3.js} +23 -323
- package/dist/chunk-N54QZER3.js.map +1 -0
- package/dist/chunk-QMFOL2K6.js +371 -0
- package/dist/chunk-QMFOL2K6.js.map +1 -0
- package/dist/chunk-XOX6RFPZ.js +383 -0
- package/dist/chunk-XOX6RFPZ.js.map +1 -0
- package/dist/db/index.cjs +41 -2
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.js +12 -13
- package/dist/engine/index.cjs +210 -24
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +3 -3
- package/dist/engine/index.d.ts +3 -3
- package/dist/engine/index.js +7 -7
- package/dist/{index-DtCgaZAg.d.cts → index-BWgnGj68.d.cts} +185 -35
- package/dist/{index-b-Q3l7W5.d.ts → index-Bi74dcOu.d.ts} +9 -2
- package/dist/{index-8qy3kIuA.d.ts → index-Dg10RnZO.d.ts} +185 -35
- package/dist/{index-Zi7MptvP.d.cts → index-g6iQyYci.d.cts} +9 -2
- package/dist/index.cjs +135 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -23
- package/dist/index.d.ts +6 -23
- package/dist/index.js +48 -48
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.d.cts +2 -2
- package/dist/openapi/index.d.ts +2 -2
- package/dist/openapi/index.js +3 -4
- package/dist/openapi/index.js.map +1 -1
- package/dist/{registry-CEYLH-Iz.d.cts → registry-6VT5RPeO.d.cts} +1 -1
- package/dist/{registry-BGJ-Al6F.d.ts → registry-B-sxJJN0.d.ts} +1 -1
- package/dist/test/index.cjs +733 -17
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.d.cts +59 -4
- package/dist/test/index.d.ts +59 -4
- package/dist/test/index.js +56 -16
- package/dist/test/index.js.map +1 -1
- package/docs/README.md +1 -1
- package/docs/auth.md +102 -20
- package/docs/database.md +54 -0
- package/docs/llms-full.txt +215 -21
- package/docs/schema.md +58 -0
- package/package.json +1 -1
- package/template/db/public.ts +23 -0
- package/template/package.json +1 -1
- package/dist/chunk-3TUJWHC2.js.map +0 -1
- package/dist/chunk-ENZ2RFFJ.js.map +0 -1
- package/dist/chunk-RADVOY7Y.js.map +0 -1
- package/dist/chunk-SG4UTNOP.js +0 -374
- package/dist/chunk-SG4UTNOP.js.map +0 -1
- package/dist/chunk-VXPNPVAG.js +0 -40
- package/dist/chunk-VXPNPVAG.js.map +0 -1
- package/dist/chunk-YRVIWHJC.js.map +0 -1
- /package/dist/{chunk-VVMJEVQP.js.map → chunk-BRLJOXWS.js.map} +0 -0
|
@@ -3,17 +3,17 @@ import {
|
|
|
3
3
|
BootRefused,
|
|
4
4
|
createApp,
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-DCDHAKF3.js";
|
|
7
|
+
import "../chunk-N54QZER3.js";
|
|
8
|
+
import "../chunk-QMFOL2K6.js";
|
|
9
|
+
import "../chunk-XOX6RFPZ.js";
|
|
10
|
+
import "../chunk-C4ZA5AT2.js";
|
|
10
11
|
import {
|
|
11
12
|
getRegisteredControllers
|
|
12
|
-
} from "../chunk-
|
|
13
|
-
import "../chunk-CGNN2PUH.js";
|
|
13
|
+
} from "../chunk-BRLJOXWS.js";
|
|
14
14
|
import {
|
|
15
15
|
__name
|
|
16
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-KATPXCJ5.js";
|
|
17
17
|
|
|
18
18
|
// src/bin/palbase-backend.ts
|
|
19
19
|
import { readdir } from "fs/promises";
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
HttpError
|
|
3
|
-
} from "./chunk-CGNN2PUH.js";
|
|
4
|
-
import {
|
|
2
|
+
HttpError,
|
|
5
3
|
__name
|
|
6
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KATPXCJ5.js";
|
|
7
5
|
|
|
8
6
|
// src/error-registry.ts
|
|
9
7
|
import { OpenAPIRegistry, OpenApiGeneratorV31, extendZodWithOpenApi } from "@asteasolutions/zod-to-openapi";
|
|
@@ -161,4 +159,4 @@ export {
|
|
|
161
159
|
getErrorRegistry,
|
|
162
160
|
defineError
|
|
163
161
|
};
|
|
164
|
-
//# sourceMappingURL=chunk-
|
|
162
|
+
//# sourceMappingURL=chunk-26GH54D2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/error-registry.ts"],"sourcesContent":["// defineError — project-defined typed error classes + the module-global error\n// registry the OpenAPI spec twins join against.\n//\n// `defineError(code, status, dataSchema?)` returns an `HttpError` subclass whose\n// constructor is typed by the zod schema (`new TodoLocked({ retryAfter: 30 })`).\n// Each call self-registers `{ code, status, className, dataSchema }` in a\n// registry anchored on `globalThis` under `Symbol.for(...)` — mirroring the\n// ROUTES pattern — so the deploy bundle's registrations land on the single SDK\n// instance the extractor `require()`s. The registry is pre-seeded with the named\n// built-in classes (`NotFound`, `Conflict`, …) so throw inference can resolve\n// ad-hoc `throw new NotFound(...)` sites by their canonical wire codes.\n//\n// Duplicate code with a DIFFERENT shape (status OR converted data schema) is a\n// hard error at registration time (deploy fails loudly — error codes are\n// project-unique); structurally-identical re-registration is idempotent (each\n// controller BUNDLE carries its own copy of a shared models/errors.ts, so the\n// same defineError line legitimately runs once per bundle in one process).\nimport {\n OpenAPIRegistry,\n OpenApiGeneratorV31,\n extendZodWithOpenApi,\n} from \"@asteasolutions/zod-to-openapi\";\nimport { z, type ZodTypeAny } from \"zod\";\nimport { HttpError } from \"./errors.js\";\n\nextendZodWithOpenApi(z);\n\n/** One registered error: the wire code, HTTP status, the class name the\n * analyzer sees, the optional data payload schema, and whether it is one of the\n * pre-seeded built-in named classes. */\nexport interface RegisteredError {\n code: string;\n status: number;\n className: string;\n dataSchema?: ZodTypeAny;\n /** JSON.stringify of the converted JSON schema — equal digest ⇔ the spec\n * twins would emit an identical `data` schema for this error. */\n dataDigest?: string;\n builtin: boolean;\n}\n\n/** The cross-module-instance registry anchor (the pinned contract symbol). */\nconst ERROR_REGISTRY: unique symbol = Symbol.for(\"palbase.backend.errorRegistry\");\n\ninterface RegistryCarrier {\n [ERROR_REGISTRY]?: Map<string, RegisteredError>;\n}\n\n/** Get (creating + pre-seeding if absent) the project-global error registry,\n * keyed by wire code. Anchored on `globalThis` so every copy of the SDK in a\n * process shares the one registry. */\n/** The fixed data schemas the built-in named errors ship. Declared HERE (not in\n * errors.ts, which stays zod-free) because this is where the registry converts\n * them to JSON-schema for the spec — keying codegen's typed `error.data`. Only\n * the errors that semantically carry a payload have a schema; the rest are\n * data-less. `.int()` is preserved so the wire/codegen sees an integer. */\nconst BUILTIN_DATA_SCHEMAS: Record<string, ZodTypeAny> = {\n bad_request: z.object({\n fields: z.array(z.object({ field: z.string(), message: z.string() })),\n }),\n too_many_requests: z.object({ retryAfter: z.number().int() }),\n};\n\nexport function getErrorRegistry(): Map<string, RegisteredError> {\n const g = globalThis as RegistryCarrier;\n if (!g[ERROR_REGISTRY]) {\n const m = new Map<string, RegisteredError>();\n for (const [code, status, className] of [\n [\"bad_request\", 400, \"BadRequest\"],\n [\"unauthorized\", 401, \"Unauthorized\"],\n [\"forbidden\", 403, \"Forbidden\"],\n [\"not_found\", 404, \"NotFound\"],\n [\"conflict\", 409, \"Conflict\"],\n // The engine's own 23505 conversion (engine/db.ts) throws this, and an\n // author may too. Registered like every other built-in so the spec\n // emitter resolves it — an unregistered code is SKIPPED silently there\n // (openapi/convert.ts) and would degrade to the client's `.other` case.\n [\"unique_violation\", 409, \"UniqueViolation\"],\n [\"too_many_requests\", 429, \"TooManyRequests\"],\n ] as const) {\n const dataSchema = BUILTIN_DATA_SCHEMAS[code];\n m.set(code, {\n code,\n status,\n className,\n builtin: true,\n ...(dataSchema ? { dataSchema, dataDigest: digestOf(code, dataSchema) } : {}),\n });\n }\n g[ERROR_REGISTRY] = m;\n }\n return g[ERROR_REGISTRY];\n}\n\n/** Class returned for schema-bearing errors: ctor(data, message?). */\nexport interface DefinedErrorWithData<S extends ZodTypeAny> {\n new (data: z.input<S>, message?: string): HttpError;\n readonly code: string;\n readonly status: number;\n}\n\n/** Class returned for schema-less errors: ctor(message?). */\nexport interface DefinedError {\n new (message?: string): HttpError;\n readonly code: string;\n readonly status: number;\n}\n\n/**\n * Define a project error class. MUST be called with literal args (string\n * literal `code`, numeric literal `status`) at module top level — the deploy\n * stager's static analyzer reads those literals to resolve throw sites.\n *\n * @example\n * // models/todos/errors.ts\n * export const TodoLocked = defineError(\"todo_locked\", 409, z.object({ retryAfter: z.number() }));\n * // services/todo.service.ts\n * throw new TodoLocked({ retryAfter: 30 });\n */\nexport function defineError<S extends ZodTypeAny>(\n code: string,\n status: number,\n dataSchema: S,\n): DefinedErrorWithData<S>;\nexport function defineError(code: string, status: number): DefinedError;\nexport function defineError(code: string, status: number, dataSchema?: ZodTypeAny): unknown {\n if (!Number.isInteger(status) || status < 400 || status > 599) {\n throw new Error(\n `defineError: status for \"${code}\" must be a 4xx/5xx integer, got ${status} — ` +\n `error responses must not clobber success responses in the project spec.`,\n );\n }\n const registry = getErrorRegistry();\n const existing = registry.get(code);\n const className = defaultClassName(code);\n const dataDigest = dataSchema ? digestOf(code, dataSchema) : undefined;\n if (existing) {\n const sameShape =\n existing.status === status && !existing.builtin && existing.dataDigest === dataDigest;\n if (!sameShape) {\n throw new Error(\n `defineError: duplicate error code \"${code}\" with a different shape ` +\n `(existing: status ${existing.status}${existing.builtin ? \", built-in\" : \"\"}` +\n `${existing.status === status && !existing.builtin ? \", different data schema\" : \"\"}). ` +\n `Error codes are project-unique.`,\n );\n }\n }\n // Local factories so the class-constructor closures capture a NON-optional\n // schema binding (narrowing does not flow into closures created in a branch).\n const makeWithData = (schema: ZodTypeAny) =>\n class extends HttpError {\n static readonly code = code;\n static readonly status = status;\n constructor(data: unknown, message?: string) {\n super(status, code, message ?? humanize(code), schema.parse(data));\n this.name = className;\n }\n };\n const makeWithoutData = () =>\n class extends HttpError {\n static readonly code = code;\n static readonly status = status;\n constructor(message?: string) {\n super(status, code, message ?? humanize(code));\n this.name = className;\n }\n };\n const cls = dataSchema ? makeWithData(dataSchema) : makeWithoutData();\n Object.defineProperty(cls, \"name\", { value: className });\n registry.set(code, {\n code,\n status,\n className,\n builtin: false,\n ...(dataSchema ? { dataSchema } : {}),\n ...(dataDigest !== undefined ? { dataDigest } : {}),\n });\n return cls;\n}\n\n/** Convert a data schema through the SAME library the spec twins use and\n * return its JSON-schema digest (the duplicate-shape comparison key). Doubles\n * as the self-containment guard: a schema carrying `.openapi(refId)` metadata\n * (top-level or nested) converts to `$ref` pointers into components the\n * project spec never emits — a dangling ref every spec consumer would choke\n * on — so it is rejected here, at the definition site, with a fixable message. */\nfunction digestOf(code: string, dataSchema: ZodTypeAny): string {\n const TMP_REF = \"__PalbaseErrorDataDigest\";\n const tmpRegistry = new OpenAPIRegistry();\n // Wrap the schema as a property — exactly how the envelope embeds it — so a\n // TOP-LEVEL .openapi(refId) is not masked by the registration refId and\n // surfaces as the same $ref the real emission would produce.\n tmpRegistry.register(TMP_REF, z.object({ data: dataSchema }).openapi(TMP_REF));\n const generated = new OpenApiGeneratorV31(tmpRegistry.definitions).generateComponents();\n const out = generated.components?.schemas?.[TMP_REF];\n const digest = JSON.stringify(out ?? null);\n if (digest.includes('\"$ref\"')) {\n throw new Error(\n `defineError: dataSchema for \"${code}\" carries .openapi(refId) metadata — ` +\n `it would emit dangling $ref pointers in the project spec. ` +\n `Use a plain zod schema (z.object({...})) without .openapi(...).`,\n );\n }\n return digest;\n}\n\n/** \"todo_locked\" → \"TodoLocked\" (used as Error.name; the source class NAME the\n * analyzer sees is whatever the user assigned the const to — they should match\n * by convention, and the descriptor carries the analyzed const name anyway). */\nfunction defaultClassName(code: string): string {\n return code\n .split(\"_\")\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1))\n .join(\"\");\n}\n\n/** \"todo_locked\" → \"Todo locked\" — the default human-readable message. */\nfunction humanize(code: string): string {\n const s = code.replace(/_/g, \" \");\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n"],"mappings":"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","names":["OpenAPIRegistry","OpenApiGeneratorV31","extendZodWithOpenApi","z","extendZodWithOpenApi","z","ERROR_REGISTRY","Symbol","for","BUILTIN_DATA_SCHEMAS","bad_request","object","fields","array","field","string","message","too_many_requests","retryAfter","number","int","getErrorRegistry","g","globalThis","m","Map","code","status","className","dataSchema","set","builtin","dataDigest","digestOf","defineError","Number","isInteger","Error","registry","existing","get","defaultClassName","undefined","sameShape","makeWithData","schema","HttpError","data","humanize","parse","name","makeWithoutData","cls","Object","defineProperty","value","TMP_REF","tmpRegistry","OpenAPIRegistry","register","openapi","generated","OpenApiGeneratorV31","definitions","generateComponents","out","components","schemas","digest","JSON","stringify","includes","split","map","p","charAt","toUpperCase","slice","join","s","replace"]}
|
|
1
|
+
{"version":3,"sources":["../src/error-registry.ts"],"sourcesContent":["// defineError — project-defined typed error classes + the module-global error\n// registry the OpenAPI spec twins join against.\n//\n// `defineError(code, status, dataSchema?)` returns an `HttpError` subclass whose\n// constructor is typed by the zod schema (`new TodoLocked({ retryAfter: 30 })`).\n// Each call self-registers `{ code, status, className, dataSchema }` in a\n// registry anchored on `globalThis` under `Symbol.for(...)` — mirroring the\n// ROUTES pattern — so the deploy bundle's registrations land on the single SDK\n// instance the extractor `require()`s. The registry is pre-seeded with the named\n// built-in classes (`NotFound`, `Conflict`, …) so throw inference can resolve\n// ad-hoc `throw new NotFound(...)` sites by their canonical wire codes.\n//\n// Duplicate code with a DIFFERENT shape (status OR converted data schema) is a\n// hard error at registration time (deploy fails loudly — error codes are\n// project-unique); structurally-identical re-registration is idempotent (each\n// controller BUNDLE carries its own copy of a shared models/errors.ts, so the\n// same defineError line legitimately runs once per bundle in one process).\nimport {\n OpenAPIRegistry,\n OpenApiGeneratorV31,\n extendZodWithOpenApi,\n} from \"@asteasolutions/zod-to-openapi\";\nimport { z, type ZodTypeAny } from \"zod\";\nimport { HttpError } from \"./errors.js\";\n\nextendZodWithOpenApi(z);\n\n/** One registered error: the wire code, HTTP status, the class name the\n * analyzer sees, the optional data payload schema, and whether it is one of the\n * pre-seeded built-in named classes. */\nexport interface RegisteredError {\n code: string;\n status: number;\n className: string;\n dataSchema?: ZodTypeAny;\n /** JSON.stringify of the converted JSON schema — equal digest ⇔ the spec\n * twins would emit an identical `data` schema for this error. */\n dataDigest?: string;\n builtin: boolean;\n}\n\n/** The cross-module-instance registry anchor (the pinned contract symbol). */\nconst ERROR_REGISTRY: unique symbol = Symbol.for(\"palbase.backend.errorRegistry\");\n\ninterface RegistryCarrier {\n [ERROR_REGISTRY]?: Map<string, RegisteredError>;\n}\n\n/** Get (creating + pre-seeding if absent) the project-global error registry,\n * keyed by wire code. Anchored on `globalThis` so every copy of the SDK in a\n * process shares the one registry. */\n/** The fixed data schemas the built-in named errors ship. Declared HERE (not in\n * errors.ts, which stays zod-free) because this is where the registry converts\n * them to JSON-schema for the spec — keying codegen's typed `error.data`. Only\n * the errors that semantically carry a payload have a schema; the rest are\n * data-less. `.int()` is preserved so the wire/codegen sees an integer. */\nconst BUILTIN_DATA_SCHEMAS: Record<string, ZodTypeAny> = {\n bad_request: z.object({\n fields: z.array(z.object({ field: z.string(), message: z.string() })),\n }),\n too_many_requests: z.object({ retryAfter: z.number().int() }),\n};\n\nexport function getErrorRegistry(): Map<string, RegisteredError> {\n const g = globalThis as RegistryCarrier;\n if (!g[ERROR_REGISTRY]) {\n const m = new Map<string, RegisteredError>();\n for (const [code, status, className] of [\n [\"bad_request\", 400, \"BadRequest\"],\n [\"unauthorized\", 401, \"Unauthorized\"],\n [\"forbidden\", 403, \"Forbidden\"],\n [\"not_found\", 404, \"NotFound\"],\n [\"conflict\", 409, \"Conflict\"],\n // The engine's own 23505 conversion (engine/db.ts) throws this, and an\n // author may too. Registered like every other built-in so the spec\n // emitter resolves it — an unregistered code is SKIPPED silently there\n // (openapi/convert.ts) and would degrade to the client's `.other` case.\n [\"unique_violation\", 409, \"UniqueViolation\"],\n [\"too_many_requests\", 429, \"TooManyRequests\"],\n ] as const) {\n const dataSchema = BUILTIN_DATA_SCHEMAS[code];\n m.set(code, {\n code,\n status,\n className,\n builtin: true,\n ...(dataSchema ? { dataSchema, dataDigest: digestOf(code, dataSchema) } : {}),\n });\n }\n g[ERROR_REGISTRY] = m;\n }\n return g[ERROR_REGISTRY];\n}\n\n/** Class returned for schema-bearing errors: ctor(data, message?). */\nexport interface DefinedErrorWithData<S extends ZodTypeAny> {\n new (data: z.input<S>, message?: string): HttpError;\n readonly code: string;\n readonly status: number;\n}\n\n/** Class returned for schema-less errors: ctor(message?). */\nexport interface DefinedError {\n new (message?: string): HttpError;\n readonly code: string;\n readonly status: number;\n}\n\n/**\n * Define a project error class. MUST be called with literal args (string\n * literal `code`, numeric literal `status`) at module top level — the deploy\n * stager's static analyzer reads those literals to resolve throw sites.\n *\n * @example\n * // models/todos/errors.ts\n * export const TodoLocked = defineError(\"todo_locked\", 409, z.object({ retryAfter: z.number() }));\n * // services/todo.service.ts\n * throw new TodoLocked({ retryAfter: 30 });\n */\nexport function defineError<S extends ZodTypeAny>(\n code: string,\n status: number,\n dataSchema: S,\n): DefinedErrorWithData<S>;\nexport function defineError(code: string, status: number): DefinedError;\nexport function defineError(code: string, status: number, dataSchema?: ZodTypeAny): unknown {\n if (!Number.isInteger(status) || status < 400 || status > 599) {\n throw new Error(\n `defineError: status for \"${code}\" must be a 4xx/5xx integer, got ${status} — ` +\n `error responses must not clobber success responses in the project spec.`,\n );\n }\n const registry = getErrorRegistry();\n const existing = registry.get(code);\n const className = defaultClassName(code);\n const dataDigest = dataSchema ? digestOf(code, dataSchema) : undefined;\n if (existing) {\n const sameShape =\n existing.status === status && !existing.builtin && existing.dataDigest === dataDigest;\n if (!sameShape) {\n throw new Error(\n `defineError: duplicate error code \"${code}\" with a different shape ` +\n `(existing: status ${existing.status}${existing.builtin ? \", built-in\" : \"\"}` +\n `${existing.status === status && !existing.builtin ? \", different data schema\" : \"\"}). ` +\n `Error codes are project-unique.`,\n );\n }\n }\n // Local factories so the class-constructor closures capture a NON-optional\n // schema binding (narrowing does not flow into closures created in a branch).\n const makeWithData = (schema: ZodTypeAny) =>\n class extends HttpError {\n static readonly code = code;\n static readonly status = status;\n constructor(data: unknown, message?: string) {\n super(status, code, message ?? humanize(code), schema.parse(data));\n this.name = className;\n }\n };\n const makeWithoutData = () =>\n class extends HttpError {\n static readonly code = code;\n static readonly status = status;\n constructor(message?: string) {\n super(status, code, message ?? humanize(code));\n this.name = className;\n }\n };\n const cls = dataSchema ? makeWithData(dataSchema) : makeWithoutData();\n Object.defineProperty(cls, \"name\", { value: className });\n registry.set(code, {\n code,\n status,\n className,\n builtin: false,\n ...(dataSchema ? { dataSchema } : {}),\n ...(dataDigest !== undefined ? { dataDigest } : {}),\n });\n return cls;\n}\n\n/** Convert a data schema through the SAME library the spec twins use and\n * return its JSON-schema digest (the duplicate-shape comparison key). Doubles\n * as the self-containment guard: a schema carrying `.openapi(refId)` metadata\n * (top-level or nested) converts to `$ref` pointers into components the\n * project spec never emits — a dangling ref every spec consumer would choke\n * on — so it is rejected here, at the definition site, with a fixable message. */\nfunction digestOf(code: string, dataSchema: ZodTypeAny): string {\n const TMP_REF = \"__PalbaseErrorDataDigest\";\n const tmpRegistry = new OpenAPIRegistry();\n // Wrap the schema as a property — exactly how the envelope embeds it — so a\n // TOP-LEVEL .openapi(refId) is not masked by the registration refId and\n // surfaces as the same $ref the real emission would produce.\n tmpRegistry.register(TMP_REF, z.object({ data: dataSchema }).openapi(TMP_REF));\n const generated = new OpenApiGeneratorV31(tmpRegistry.definitions).generateComponents();\n const out = generated.components?.schemas?.[TMP_REF];\n const digest = JSON.stringify(out ?? null);\n if (digest.includes('\"$ref\"')) {\n throw new Error(\n `defineError: dataSchema for \"${code}\" carries .openapi(refId) metadata — ` +\n `it would emit dangling $ref pointers in the project spec. ` +\n `Use a plain zod schema (z.object({...})) without .openapi(...).`,\n );\n }\n return digest;\n}\n\n/** \"todo_locked\" → \"TodoLocked\" (used as Error.name; the source class NAME the\n * analyzer sees is whatever the user assigned the const to — they should match\n * by convention, and the descriptor carries the analyzed const name anyway). */\nfunction defaultClassName(code: string): string {\n return code\n .split(\"_\")\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1))\n .join(\"\");\n}\n\n/** \"todo_locked\" → \"Todo locked\" — the default human-readable message. */\nfunction humanize(code: string): string {\n const s = code.replace(/_/g, \" \");\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n"],"mappings":"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","names":["OpenAPIRegistry","OpenApiGeneratorV31","extendZodWithOpenApi","z","extendZodWithOpenApi","z","ERROR_REGISTRY","Symbol","for","BUILTIN_DATA_SCHEMAS","bad_request","object","fields","array","field","string","message","too_many_requests","retryAfter","number","int","getErrorRegistry","g","globalThis","m","Map","code","status","className","dataSchema","set","builtin","dataDigest","digestOf","defineError","Number","isInteger","Error","registry","existing","get","defaultClassName","undefined","sameShape","makeWithData","schema","HttpError","data","humanize","parse","name","makeWithoutData","cls","Object","defineProperty","value","TMP_REF","tmpRegistry","OpenAPIRegistry","register","openapi","generated","OpenApiGeneratorV31","definitions","generateComponents","out","components","schemas","digest","JSON","stringify","includes","split","map","p","charAt","toUpperCase","slice","join","s","replace"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
__name
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KATPXCJ5.js";
|
|
4
4
|
|
|
5
5
|
// src/decorators/registry.ts
|
|
6
6
|
var ROUTES = /* @__PURE__ */ Symbol.for("palbase.backend.routes");
|
|
@@ -290,4 +290,4 @@ export {
|
|
|
290
290
|
resolveController,
|
|
291
291
|
assertZeroArgConstructor
|
|
292
292
|
};
|
|
293
|
-
//# sourceMappingURL=chunk-
|
|
293
|
+
//# sourceMappingURL=chunk-BRLJOXWS.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
__name
|
|
3
|
-
|
|
2
|
+
__name,
|
|
3
|
+
isRetryable
|
|
4
|
+
} from "./chunk-KATPXCJ5.js";
|
|
4
5
|
|
|
5
6
|
// src/db/input-guards.ts
|
|
6
7
|
var REF_BRAND = /* @__PURE__ */ Symbol.for("palbase.db.ref");
|
|
@@ -113,23 +114,23 @@ function assertUsableFilter(caller, table, where) {
|
|
|
113
114
|
]);
|
|
114
115
|
if (!where) return;
|
|
115
116
|
if (isSqlFragment(where)) return;
|
|
116
|
-
for (const [
|
|
117
|
-
if (COMPOSITES.has(
|
|
118
|
-
const branches =
|
|
117
|
+
for (const [col2, cond] of Object.entries(where)) {
|
|
118
|
+
if (COMPOSITES.has(col2)) {
|
|
119
|
+
const branches = col2 === "NOT" ? [
|
|
119
120
|
cond
|
|
120
121
|
] : cond;
|
|
121
|
-
if (!Array.isArray(branches) &&
|
|
122
|
-
throw new Error(`${caller}(${table}): where.${
|
|
122
|
+
if (!Array.isArray(branches) && col2 !== "NOT") {
|
|
123
|
+
throw new Error(`${caller}(${table}): where.${col2} bir dizi olmal\u0131`);
|
|
123
124
|
}
|
|
124
125
|
for (const b of branches) {
|
|
125
126
|
if (b === null || typeof b !== "object") {
|
|
126
|
-
throw new Error(`${caller}(${table}): where.${
|
|
127
|
+
throw new Error(`${caller}(${table}): where.${col2} dallar\u0131 filtre nesnesi olmal\u0131`);
|
|
127
128
|
}
|
|
128
129
|
assertUsableFilter(caller, table, b);
|
|
129
130
|
}
|
|
130
131
|
continue;
|
|
131
132
|
}
|
|
132
|
-
if (
|
|
133
|
+
if (col2 === "has") {
|
|
133
134
|
if (cond === null || typeof cond !== "object" || Array.isArray(cond)) {
|
|
134
135
|
throw new Error(`${caller}(${table}): where.has bir ili\u015Fki haritas\u0131 olmal\u0131 ({ <ili\u015Fki>: { \u2026 } })`);
|
|
135
136
|
}
|
|
@@ -142,31 +143,31 @@ function assertUsableFilter(caller, table, where) {
|
|
|
142
143
|
continue;
|
|
143
144
|
}
|
|
144
145
|
if (cond === void 0) {
|
|
145
|
-
throw new Error(`${caller}(${table}): where.${
|
|
146
|
+
throw new Error(`${caller}(${table}): where.${col2} de\u011Feri undefined \u2014 bu bir filtre de\u011Feri de\u011Fil. Ba\u011Flan\u0131nca NULL olur ve '= NULL' hi\xE7bir sat\u0131ra uymaz, yani sorgu sessizce bo\u015F sonu\xE7 d\xF6nerdi. De\u011Fer yoksa anahtar\u0131 filtreye hi\xE7 koymay\u0131n.`);
|
|
146
147
|
}
|
|
147
148
|
if (cond === null || typeof cond !== "object" || Array.isArray(cond)) continue;
|
|
148
149
|
if (isColRef(cond)) continue;
|
|
149
150
|
if (isNowExpr(cond)) continue;
|
|
150
151
|
const entries = Object.entries(cond);
|
|
151
152
|
if (entries.length === 0) {
|
|
152
|
-
throw new Error(`${caller}(${table}): where.${
|
|
153
|
+
throw new Error(`${caller}(${table}): where.${col2} bo\u015F bir operat\xF6r nesnesi ({}) \u2014 hi\xE7bir ko\u015Ful \xFCretmez, yani bu alan filtreden sessizce D\xDC\u015EERD\u0130. Ko\u015Ful kurulmayacaksa anahtar\u0131 filtreye hi\xE7 koymay\u0131n (D-21).`);
|
|
153
154
|
}
|
|
154
155
|
for (const [op, v] of entries) {
|
|
155
156
|
if (op === "in") {
|
|
156
|
-
if (!Array.isArray(v)) throw new Error(`${caller}(${table}): where.${
|
|
157
|
+
if (!Array.isArray(v)) throw new Error(`${caller}(${table}): where.${col2}.in bir dizi olmal\u0131`);
|
|
157
158
|
if (v.some((x) => x === void 0)) {
|
|
158
|
-
throw new Error(`${caller}(${table}): where.${
|
|
159
|
+
throw new Error(`${caller}(${table}): where.${col2}.in listesinde undefined var \u2014 sessizce NULL'a ba\u011Flan\u0131r ve o eleman hi\xE7bir sat\u0131rla e\u015Fle\u015Fmez. Listeyi kurarken eleyin.`);
|
|
159
160
|
}
|
|
160
161
|
continue;
|
|
161
162
|
}
|
|
162
163
|
if (REFUSED_OPS[op] !== void 0) {
|
|
163
|
-
throw new Error(`${caller}(${table}): where.${
|
|
164
|
+
throw new Error(`${caller}(${table}): where.${col2}.${op} bu filtre dilinde yok \u2014 ${REFUSED_OPS[op]}`);
|
|
164
165
|
}
|
|
165
166
|
if (!KNOWN_OPS.has(op)) {
|
|
166
|
-
throw new Error(`${caller}(${table}): where.${
|
|
167
|
+
throw new Error(`${caller}(${table}): where.${col2} bilinmeyen operat\xF6r "${op}" (gt/gte/lt/lte/neq/in/contains/icontains/startsWith/endsWith/isNull)`);
|
|
167
168
|
}
|
|
168
169
|
if (v === void 0) {
|
|
169
|
-
throw new Error(`${caller}(${table}): where.${
|
|
170
|
+
throw new Error(`${caller}(${table}): where.${col2}.${op} de\u011Feri undefined \u2014 kar\u015F\u0131la\u015Ft\u0131rman\u0131n sa\u011F taraf\u0131 NULL olur ve sonu\xE7 hi\xE7bir sat\u0131ra uymaz. Ko\u015Fulu kurmay\u0131n.`);
|
|
170
171
|
}
|
|
171
172
|
}
|
|
172
173
|
}
|
|
@@ -707,8 +708,360 @@ function translateRejection(err, builder) {
|
|
|
707
708
|
}
|
|
708
709
|
__name(translateRejection, "translateRejection");
|
|
709
710
|
|
|
711
|
+
// src/db/typed-db.ts
|
|
712
|
+
function makeTypedTable(name, raw) {
|
|
713
|
+
return {
|
|
714
|
+
insert: /* @__PURE__ */ __name((data) => raw.insert(name, data), "insert"),
|
|
715
|
+
aggregate: /* @__PURE__ */ __name((q) => raw.aggregate(name, q), "aggregate"),
|
|
716
|
+
insertMany: /* @__PURE__ */ __name((rows, opts) => raw.insertMany(name, rows, opts), "insertMany"),
|
|
717
|
+
put: /* @__PURE__ */ __name((q) => raw.put(name, q.data, {
|
|
718
|
+
onConflict: q.onConflict
|
|
719
|
+
}), "put"),
|
|
720
|
+
update: /* @__PURE__ */ __name((q) => raw.update(name, q.where.id, q.set), "update"),
|
|
721
|
+
delete: /* @__PURE__ */ __name((id) => raw.delete(name, id), "delete"),
|
|
722
|
+
findById: /* @__PURE__ */ __name((id) => raw.findById(name, id), "findById"),
|
|
723
|
+
findMany: /* @__PURE__ */ __name((q) => {
|
|
724
|
+
const { where, ...opts } = q ?? {};
|
|
725
|
+
return raw.findMany(name, where, opts);
|
|
726
|
+
}, "findMany"),
|
|
727
|
+
updateMany: /* @__PURE__ */ __name((q) => raw.updateMany(name, q.where, q.set, q.returning === void 0 ? void 0 : {
|
|
728
|
+
returning: q.returning
|
|
729
|
+
}), "updateMany"),
|
|
730
|
+
deleteMany: /* @__PURE__ */ __name((q) => raw.deleteMany(name, q.where), "deleteMany"),
|
|
731
|
+
count: /* @__PURE__ */ __name((q) => raw.count(name, q?.where), "count")
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
__name(makeTypedTable, "makeTypedTable");
|
|
735
|
+
function makeTypedDB(schema, raw) {
|
|
736
|
+
const tables = {};
|
|
737
|
+
for (const key of Object.keys(schema.tables)) {
|
|
738
|
+
const tableDef = schema.tables[key];
|
|
739
|
+
if (tableDef !== void 0) {
|
|
740
|
+
tables[key] = makeTypedTable(tableDef.name, raw);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
const result = {
|
|
744
|
+
tables,
|
|
745
|
+
transaction(fn) {
|
|
746
|
+
const builder = new TxPlanBuilder();
|
|
747
|
+
const planTables = {};
|
|
748
|
+
for (const key of Object.keys(schema.tables)) {
|
|
749
|
+
const tableDef = schema.tables[key];
|
|
750
|
+
if (tableDef !== void 0) planTables[key] = builder.table(tableDef.name);
|
|
751
|
+
}
|
|
752
|
+
return runTxPlan(raw, {
|
|
753
|
+
tables: planTables
|
|
754
|
+
}, builder, fn);
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
return result;
|
|
758
|
+
}
|
|
759
|
+
__name(makeTypedDB, "makeTypedDB");
|
|
760
|
+
function col(name) {
|
|
761
|
+
return brandRef({
|
|
762
|
+
$col: name
|
|
763
|
+
}, "col");
|
|
764
|
+
}
|
|
765
|
+
__name(col, "col");
|
|
766
|
+
async function withRetry(fn, opts = {}) {
|
|
767
|
+
const budget = opts.retry ?? 0;
|
|
768
|
+
let attempt = 0;
|
|
769
|
+
for (; ; ) {
|
|
770
|
+
try {
|
|
771
|
+
return await fn();
|
|
772
|
+
} catch (e) {
|
|
773
|
+
if (attempt >= budget || !isRetryable(e)) throw e;
|
|
774
|
+
attempt += 1;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
__name(withRetry, "withRetry");
|
|
779
|
+
function sqlFragment(strings, ...values) {
|
|
780
|
+
return brandRef({
|
|
781
|
+
$sql: {
|
|
782
|
+
text: [
|
|
783
|
+
...strings
|
|
784
|
+
],
|
|
785
|
+
values
|
|
786
|
+
}
|
|
787
|
+
}, "sql");
|
|
788
|
+
}
|
|
789
|
+
__name(sqlFragment, "sqlFragment");
|
|
790
|
+
|
|
791
|
+
// src/db/schema-json.ts
|
|
792
|
+
function defOf(column) {
|
|
793
|
+
return "_def" in column ? column._def : column;
|
|
794
|
+
}
|
|
795
|
+
__name(defOf, "defOf");
|
|
796
|
+
function columnToJSON(column) {
|
|
797
|
+
const def = defOf(column);
|
|
798
|
+
const out = {
|
|
799
|
+
type: def.type,
|
|
800
|
+
nullable: def.nullable,
|
|
801
|
+
primaryKey: def.primaryKey
|
|
802
|
+
};
|
|
803
|
+
if (def.defaultValue !== void 0) out.defaultValue = def.defaultValue;
|
|
804
|
+
if (def.defaultRandom === true) out.defaultRandom = true;
|
|
805
|
+
if (def.defaultNow === true) out.defaultNow = true;
|
|
806
|
+
if (def.renamedFrom !== void 0) out.renamedFrom = def.renamedFrom;
|
|
807
|
+
if (def.ignored === true) out.ignored = true;
|
|
808
|
+
if (def.owns === true) out.owns = true;
|
|
809
|
+
if (def.references !== void 0) {
|
|
810
|
+
out.references = {
|
|
811
|
+
table: def.references.table,
|
|
812
|
+
column: def.references.column
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
if (def.onDeleteAction !== void 0) out.onDeleteAction = def.onDeleteAction;
|
|
816
|
+
if (def.index === false) out.index = false;
|
|
817
|
+
if (def.counter === true) out.counter = true;
|
|
818
|
+
if (def.enumName !== void 0) out.enumName = def.enumName;
|
|
819
|
+
if (def.enumValues !== void 0) out.enumValues = [
|
|
820
|
+
...def.enumValues
|
|
821
|
+
];
|
|
822
|
+
if (def.unique === true) out.unique = true;
|
|
823
|
+
if (def.dimensions !== void 0) out.dimensions = def.dimensions;
|
|
824
|
+
return out;
|
|
825
|
+
}
|
|
826
|
+
__name(columnToJSON, "columnToJSON");
|
|
827
|
+
function policyToJSON(policy) {
|
|
828
|
+
return {
|
|
829
|
+
name: policy.name,
|
|
830
|
+
command: policy.command ?? "all",
|
|
831
|
+
roles: policy.roles ? [
|
|
832
|
+
...policy.roles
|
|
833
|
+
] : [],
|
|
834
|
+
// null rather than omitted: a policy with no USING clause is a different
|
|
835
|
+
// thing from one whose clause the emitter forgot, and Go reads the
|
|
836
|
+
// difference.
|
|
837
|
+
using: policy.using ?? null,
|
|
838
|
+
withCheck: policy.withCheck ?? null,
|
|
839
|
+
permissive: policy.permissive !== false
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
__name(policyToJSON, "policyToJSON");
|
|
843
|
+
function commonSearchFields(search, out) {
|
|
844
|
+
if (search.synonyms !== void 0 && Object.keys(search.synonyms).length > 0) {
|
|
845
|
+
out.synonyms = Object.fromEntries(Object.entries(search.synonyms).map(([word, alts]) => [
|
|
846
|
+
word,
|
|
847
|
+
[
|
|
848
|
+
...alts
|
|
849
|
+
]
|
|
850
|
+
]));
|
|
851
|
+
}
|
|
852
|
+
if (search.validity === true) out.validity = true;
|
|
853
|
+
}
|
|
854
|
+
__name(commonSearchFields, "commonSearchFields");
|
|
855
|
+
function searchToJSON(search, vectorColumn) {
|
|
856
|
+
if (search.from !== void 0 && search.model !== void 0) {
|
|
857
|
+
const out2 = {};
|
|
858
|
+
const textCols = search.text === false ? void 0 : Array.isArray(search.text) && search.text.length > 0 ? search.text : search.from;
|
|
859
|
+
if (textCols !== void 0) out2.text = {
|
|
860
|
+
columns: [
|
|
861
|
+
...textCols
|
|
862
|
+
]
|
|
863
|
+
};
|
|
864
|
+
const v = {
|
|
865
|
+
metric: search.metric ?? "cosine"
|
|
866
|
+
};
|
|
867
|
+
if (vectorColumn !== void 0) v.column = vectorColumn;
|
|
868
|
+
v.embed = {
|
|
869
|
+
provider: search.model.provider,
|
|
870
|
+
model: search.model.model,
|
|
871
|
+
from: [
|
|
872
|
+
...search.from
|
|
873
|
+
],
|
|
874
|
+
...search.model.apiKeyName !== void 0 ? {
|
|
875
|
+
apiKeyName: search.model.apiKeyName
|
|
876
|
+
} : {},
|
|
877
|
+
...search.model.dimensions !== void 0 ? {
|
|
878
|
+
dimensions: search.model.dimensions
|
|
879
|
+
} : {},
|
|
880
|
+
...search.model.baseURL !== void 0 ? {
|
|
881
|
+
baseURL: search.model.baseURL
|
|
882
|
+
} : {}
|
|
883
|
+
};
|
|
884
|
+
if (search.staleness !== void 0) v.staleness = search.staleness;
|
|
885
|
+
if (vectorColumn === void 0) {
|
|
886
|
+
v.mode = "chunks";
|
|
887
|
+
if (search.chunks !== void 0) {
|
|
888
|
+
const c = {};
|
|
889
|
+
if (search.chunks.size !== void 0 && search.chunks.size > 0) c.sizeChars = search.chunks.size;
|
|
890
|
+
if (search.chunks.overlap !== void 0 && search.chunks.overlap > 0) c.overlapChars = search.chunks.overlap;
|
|
891
|
+
if (Object.keys(c).length > 0) v.chunks = c;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
out2.vector = [
|
|
895
|
+
v
|
|
896
|
+
];
|
|
897
|
+
commonSearchFields(search, out2);
|
|
898
|
+
return out2;
|
|
899
|
+
}
|
|
900
|
+
const out = {};
|
|
901
|
+
if (Array.isArray(search.text) && search.text.length > 0) out.text = {
|
|
902
|
+
columns: [
|
|
903
|
+
...search.text
|
|
904
|
+
]
|
|
905
|
+
};
|
|
906
|
+
const legs = search.vector === void 0 ? [] : Array.isArray(search.vector) ? search.vector : [
|
|
907
|
+
search.vector
|
|
908
|
+
];
|
|
909
|
+
if (legs.length > 0) {
|
|
910
|
+
out.vector = legs.map((leg) => {
|
|
911
|
+
const v = {
|
|
912
|
+
metric: leg.metric ?? "cosine"
|
|
913
|
+
};
|
|
914
|
+
if (leg.column !== void 0) v.column = leg.column;
|
|
915
|
+
if (leg.staleness !== void 0) v.staleness = leg.staleness;
|
|
916
|
+
if (leg.model !== void 0) {
|
|
917
|
+
v.embed = {
|
|
918
|
+
provider: leg.model.provider,
|
|
919
|
+
model: leg.model.model,
|
|
920
|
+
from: [
|
|
921
|
+
...leg.from ?? []
|
|
922
|
+
],
|
|
923
|
+
...leg.model.apiKeyName !== void 0 ? {
|
|
924
|
+
apiKeyName: leg.model.apiKeyName
|
|
925
|
+
} : {},
|
|
926
|
+
...leg.model.dimensions !== void 0 ? {
|
|
927
|
+
dimensions: leg.model.dimensions
|
|
928
|
+
} : {},
|
|
929
|
+
...leg.model.baseURL !== void 0 ? {
|
|
930
|
+
baseURL: leg.model.baseURL
|
|
931
|
+
} : {}
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
return v;
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
commonSearchFields(search, out);
|
|
938
|
+
return out;
|
|
939
|
+
}
|
|
940
|
+
__name(searchToJSON, "searchToJSON");
|
|
941
|
+
function memoryToJSON(m) {
|
|
942
|
+
return {
|
|
943
|
+
from: [
|
|
944
|
+
...m.from
|
|
945
|
+
],
|
|
946
|
+
into: m.into,
|
|
947
|
+
...m.subject !== void 0 ? {
|
|
948
|
+
subject: m.subject
|
|
949
|
+
} : {},
|
|
950
|
+
extract: {
|
|
951
|
+
provider: m.extract.provider,
|
|
952
|
+
model: m.extract.model
|
|
953
|
+
}
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
__name(memoryToJSON, "memoryToJSON");
|
|
957
|
+
function tableToJSON(table, schemaName) {
|
|
958
|
+
const columns = {};
|
|
959
|
+
for (const [name, column] of Object.entries(table.columns)) {
|
|
960
|
+
columns[name] = columnToJSON(column);
|
|
961
|
+
}
|
|
962
|
+
const out = {
|
|
963
|
+
name: table.name,
|
|
964
|
+
schema: schemaName,
|
|
965
|
+
columns,
|
|
966
|
+
// Read, not re-derived. `defineSchema` already resolves the fail-closed
|
|
967
|
+
// default (RLS on unless the author wrote `rls: false`, and forced on by any
|
|
968
|
+
// policy), and a second copy of a SECURITY default is exactly the thing that
|
|
969
|
+
// drifts — the direction it drifted last time was "expose everything", and
|
|
970
|
+
// the live proof was one user reading another's rows.
|
|
971
|
+
rls: table.rls,
|
|
972
|
+
policies: (table.policies ?? []).map(policyToJSON)
|
|
973
|
+
};
|
|
974
|
+
if (table.primaryKey !== void 0 && table.primaryKey.length > 0) {
|
|
975
|
+
out.primaryKey = [
|
|
976
|
+
...table.primaryKey
|
|
977
|
+
];
|
|
978
|
+
}
|
|
979
|
+
if (table.unique !== void 0 && table.unique.length > 0) {
|
|
980
|
+
out.uniqueConstraints = table.unique.map((u) => ({
|
|
981
|
+
name: u.name,
|
|
982
|
+
columns: [
|
|
983
|
+
...u.columns
|
|
984
|
+
]
|
|
985
|
+
}));
|
|
986
|
+
}
|
|
987
|
+
if (table.raw !== void 0 && table.raw.length > 0) {
|
|
988
|
+
out.rawConstraints = table.raw.map((r) => ({
|
|
989
|
+
name: r.name,
|
|
990
|
+
up: r.up,
|
|
991
|
+
down: r.down ?? null
|
|
992
|
+
}));
|
|
993
|
+
}
|
|
994
|
+
if (table.checks !== void 0 && table.checks.length > 0) {
|
|
995
|
+
out.checks = table.checks.map((c) => ({
|
|
996
|
+
name: c.name,
|
|
997
|
+
expr: c.expr
|
|
998
|
+
}));
|
|
999
|
+
}
|
|
1000
|
+
if (table.indexes !== void 0 && table.indexes.length > 0) {
|
|
1001
|
+
out.indexes = table.indexes.map((i) => {
|
|
1002
|
+
const ix = {
|
|
1003
|
+
name: i.name,
|
|
1004
|
+
columns: i.columns ? [
|
|
1005
|
+
...i.columns
|
|
1006
|
+
] : []
|
|
1007
|
+
};
|
|
1008
|
+
if (i.where !== void 0) ix.where = i.where;
|
|
1009
|
+
if (i.expression !== void 0) ix.expression = i.expression;
|
|
1010
|
+
if (i.sort !== void 0) ix.sort = i.sort;
|
|
1011
|
+
if (i.nulls !== void 0) ix.nulls = i.nulls;
|
|
1012
|
+
if (i.include !== void 0) ix.include = [
|
|
1013
|
+
...i.include
|
|
1014
|
+
];
|
|
1015
|
+
return ix;
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
if (table.appendOnly === true) out.appendOnly = true;
|
|
1019
|
+
if (table.search !== void 0) {
|
|
1020
|
+
const vectorColumn = Object.entries(columns).find(([, c]) => c.dimensions !== void 0)?.[0];
|
|
1021
|
+
const sj = searchToJSON(table.search, vectorColumn);
|
|
1022
|
+
if (sj.text !== void 0 || sj.vector !== void 0) out.search = sj;
|
|
1023
|
+
}
|
|
1024
|
+
if (table.memory !== void 0) {
|
|
1025
|
+
out.memory = memoryToJSON(table.memory);
|
|
1026
|
+
}
|
|
1027
|
+
return out;
|
|
1028
|
+
}
|
|
1029
|
+
__name(tableToJSON, "tableToJSON");
|
|
1030
|
+
function qualifiedTableKey(schemaName, tableName) {
|
|
1031
|
+
return schemaName === "" || schemaName === "public" ? tableName : `${schemaName}.${tableName}`;
|
|
1032
|
+
}
|
|
1033
|
+
__name(qualifiedTableKey, "qualifiedTableKey");
|
|
1034
|
+
function toSchemaJSON(schemas) {
|
|
1035
|
+
const tables = {};
|
|
1036
|
+
const extensions = [];
|
|
1037
|
+
const meta = [];
|
|
1038
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1039
|
+
for (const schema of schemas) {
|
|
1040
|
+
if (seen.has(schema.name)) {
|
|
1041
|
+
throw new Error(`two schemas declare the name "${schema.name}" \u2014 schema names must be unique`);
|
|
1042
|
+
}
|
|
1043
|
+
seen.add(schema.name);
|
|
1044
|
+
for (const table of Object.values(schema.tables)) {
|
|
1045
|
+
const json = tableToJSON(table, schema.name);
|
|
1046
|
+
tables[qualifiedTableKey(schema.name, json.name)] = json;
|
|
1047
|
+
}
|
|
1048
|
+
extensions.push(...schema.extensions ?? []);
|
|
1049
|
+
meta.push({
|
|
1050
|
+
name: schema.name,
|
|
1051
|
+
exposed: schema.exposed
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
1054
|
+
return {
|
|
1055
|
+
tables,
|
|
1056
|
+
extensions: [
|
|
1057
|
+
...new Set(extensions)
|
|
1058
|
+
],
|
|
1059
|
+
schemas: meta
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
1062
|
+
__name(toSchemaJSON, "toSchemaJSON");
|
|
1063
|
+
|
|
710
1064
|
export {
|
|
711
|
-
brandRef,
|
|
712
1065
|
looksLikeUnbrandedRef,
|
|
713
1066
|
isColRef,
|
|
714
1067
|
isPlanRef,
|
|
@@ -728,6 +1081,12 @@ export {
|
|
|
728
1081
|
dec,
|
|
729
1082
|
columnExprOf,
|
|
730
1083
|
TxPlanBuilder,
|
|
731
|
-
runTxPlan
|
|
1084
|
+
runTxPlan,
|
|
1085
|
+
makeTypedDB,
|
|
1086
|
+
col,
|
|
1087
|
+
withRetry,
|
|
1088
|
+
sqlFragment,
|
|
1089
|
+
qualifiedTableKey,
|
|
1090
|
+
toSchemaJSON
|
|
732
1091
|
};
|
|
733
|
-
//# sourceMappingURL=chunk-
|
|
1092
|
+
//# sourceMappingURL=chunk-C4ZA5AT2.js.map
|