prisma-ltree 0.5.0 → 0.6.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/README.md +8 -8
- package/dist/{codec-types-BJE-5cwk.d.mts → codec-types-Ba5cQ3bc.d.mts} +15 -12
- package/dist/codec-types-Ba5cQ3bc.d.mts.map +1 -0
- package/dist/codec-types.d.mts +1 -1
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +236 -16
- package/dist/control.mjs.map +1 -1
- package/dist/{descriptor-meta-2In8FI1I.mjs → descriptor-meta-Cc6tmP54.mjs} +69 -35
- package/dist/descriptor-meta-Cc6tmP54.mjs.map +1 -0
- package/dist/pack.d.mts +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/runtime.mjs +1 -1
- package/package.json +11 -10
- package/src/contract.d.ts +87 -20
- package/src/contract.json +22 -1
- package/src/contract.ts +21 -3
- package/src/core/codecs-validation.ts +31 -0
- package/src/core/codecs.ts +32 -55
- package/src/core/contract-space-constants.ts +11 -0
- package/src/core/data-types.ts +36 -2
- package/src/exports/control.ts +36 -1
- package/dist/codec-types-BJE-5cwk.d.mts.map +0 -1
- package/dist/descriptor-meta-2In8FI1I.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descriptor-meta-Cc6tmP54.mjs","names":[],"sources":["../src/core/authoring.ts","../src/core/codecs-validation.ts","../src/core/data-types.ts","../src/core/codecs.ts","../src/core/registry.ts","../src/core/descriptor-meta.ts"],"sourcesContent":["import type { AuthoringTypeNamespace } from \"@prisma/orm-framework/components/authoring\";\nimport { LTREE_ARRAY_CODEC_ID, LTREE_CODEC_ID } from \"./constants\";\n\nexport const ltreeAuthoringTypes = {\n ltree: {\n Ltree: {\n kind: \"typeConstructor\",\n inferred: true,\n output: {\n codecId: LTREE_CODEC_ID,\n },\n },\n LtreeArray: {\n kind: \"typeConstructor\",\n inferred: true,\n output: {\n codecId: LTREE_ARRAY_CODEC_ID,\n },\n },\n },\n} as const satisfies AuthoringTypeNamespace;\n","import { LTREE_MAX_LABEL_LENGTH, LTREE_MAX_LABELS } from \"./constants\";\n\nconst LABEL_PATTERN = /^[A-Za-z0-9_-]+$/;\n\nexport function assertValidLtree(value: unknown): asserts value is string {\n if (typeof value !== \"string\") {\n throw new Error(\"ltree value must be a string\");\n }\n if (value.length === 0) {\n throw new Error(\"ltree value must not be empty\");\n }\n const labels = value.split(\".\");\n if (labels.length > LTREE_MAX_LABELS) {\n throw new Error(`ltree path exceeds max labels: got ${labels.length}, max ${LTREE_MAX_LABELS}`);\n }\n for (const label of labels) {\n if (label.length === 0) {\n throw new Error(`ltree label must not be empty in path \"${value}\"`);\n }\n if (label.length > LTREE_MAX_LABEL_LENGTH) {\n throw new Error(\n `ltree label exceeds max length: got ${label.length}, max ${LTREE_MAX_LABEL_LENGTH}`,\n );\n }\n if (!LABEL_PATTERN.test(label)) {\n throw new Error(\n `ltree label \"${label}\" contains invalid characters; allowed: alphanumeric, underscore, hyphen`,\n );\n }\n }\n}\n","/**\n * Data types this extension owns.\n *\n * `ltree` and `ltree[]` are PostgreSQL types the target does not register.\n * A path's stored form is its label text. An array's stored form is a\n * JSON array of those texts. Both accept text the contract can already write.\n * The texts are what a migration writes and what the catalog reports.\n */\n\nimport type { DataType, DataTypeReader } from \"@prisma/orm-framework/components/codec\";\nimport { refuseJsonValue } from \"@prisma/orm-framework/components/codec\";\nimport { sqlDataType } from \"@prisma/orm-family-sql/contract/data-type\";\nimport { pgText } from \"@prisma/orm-target-postgres/target/data-types\";\nimport { assertValidLtree } from \"./codecs-validation\";\n\nconst readLtree: DataTypeReader = (json) => {\n if (typeof json !== \"string\") {\n return refuseJsonValue(\"ltree/ltree\", \"an ltree path string\", json);\n }\n try {\n assertValidLtree(json);\n } catch {\n return refuseJsonValue(\"ltree/ltree\", \"a valid ltree path string\", json);\n }\n return json;\n};\n\nexport const ltreeDataType = sqlDataType(\"ltree/ltree\", {\n read: readLtree,\n texts: [{ text: \"ltree\", written: true, catalog: true }],\n casts: {\n [pgText.id]: (value) => value,\n },\n});\n\nconst readLtreeArray: DataTypeReader = (json) => {\n const expected = \"an array of ltree path strings\";\n if (!Array.isArray(json)) {\n return refuseJsonValue(\"ltree/ltree-array\", expected, json);\n }\n for (const entry of json) {\n if (typeof entry !== \"string\") {\n return refuseJsonValue(\"ltree/ltree-array\", expected, entry);\n }\n try {\n assertValidLtree(entry);\n } catch {\n return refuseJsonValue(\"ltree/ltree-array\", expected, entry);\n }\n }\n return json;\n};\n\n/**\n * `sqlDataType` accepts parentheses in a type name and refuses square brackets.\n * PostgreSQL writes this type as `ltree[]`, and `format_type` reports `ltree[]`.\n * Declare the type first, then set that text so a migration and a catalog check use it.\n */\nconst ltreeArrayDeclared = sqlDataType(\"ltree/ltree-array\", {\n read: readLtreeArray,\n listCast: {\n of: [pgText.id],\n cast: (elements) => [...elements],\n },\n});\n\nexport const ltreeArrayDataType = {\n ...ltreeArrayDeclared,\n sql: {\n ...ltreeArrayDeclared.sql,\n texts: [{ text: \"ltree[]\", written: true as const, catalog: true as const }],\n },\n} as typeof ltreeArrayDeclared;\n\nexport const ltreeDataTypes: readonly DataType[] = [ltreeDataType, ltreeArrayDataType];\n","import {\n type AnyCodecDescriptor,\n type CodecCallContext,\n CodecImpl,\n type CodecInstanceContext,\n type ColumnHelperFor,\n type ColumnHelperForStrict,\n column,\n type DataTypeValue,\n} from \"@prisma/orm-framework/components/codec\";\nimport type { ExtractCodecTypes, ProjectionExpr } from \"@prisma/orm-family-sql/relational-core/ast\";\nimport { CastExpr } from \"@prisma/orm-family-sql/relational-core/ast\";\nimport {\n definePostgresCodecs,\n PostgresCodecDescriptor,\n} from \"@prisma/orm-target-postgres/target/codec-descriptor\";\nimport { assertValidLtree } from \"./codecs-validation\";\nimport { LTREE_ARRAY_CODEC_ID, LTREE_CODEC_ID } from \"./constants\";\nimport { ltreeArrayDataType, ltreeDataType } from \"./data-types\";\n\nexport { assertValidLtree } from \"./codecs-validation\";\n\nexport class LtreeCodec extends CodecImpl<\n typeof LTREE_CODEC_ID,\n readonly [\"equality\", \"order\"],\n string,\n string\n> {\n constructor(descriptor: AnyCodecDescriptor) {\n super(descriptor, ltreeDataType);\n }\n\n async toWire(value: string, _ctx: CodecCallContext): Promise<string> {\n assertValidLtree(value);\n return value;\n }\n\n async fromWire(wire: string, _ctx: CodecCallContext): Promise<string> {\n return wire;\n }\n\n toDataTypeValue(value: string): DataTypeValue {\n assertValidLtree(value);\n return this.dataTypeValueOf(value);\n }\n\n fromDataTypeValue(value: DataTypeValue): string {\n return value.value as string;\n }\n}\n\nexport class LtreeDescriptor extends PostgresCodecDescriptor<void> {\n override readonly jsonType = \"string\" as const;\n protected override jsonProjection(expression: ProjectionExpr): ProjectionExpr {\n // JSON projections read through fromWire; cast so the wire value is text.\n return CastExpr.as(expression, \"text\");\n }\n override readonly dataType = ltreeDataType.id;\n override readonly codecId = LTREE_CODEC_ID;\n override readonly traits = [\"equality\", \"order\"] as const;\n override readonly paramsSchema = undefined;\n override renderOutputType(): string {\n return \"string\";\n }\n override factory(): (ctx: CodecInstanceContext) => LtreeCodec {\n const shared = new LtreeCodec(this);\n return () => shared;\n }\n}\n\nexport const ltreeDescriptor = new LtreeDescriptor();\n\nexport const ltree = () => column(ltreeDescriptor.factory(), ltreeDescriptor.codecId, undefined);\n\nltree satisfies ColumnHelperFor<LtreeDescriptor>;\nltree satisfies ColumnHelperForStrict<LtreeDescriptor>;\n\nexport class LtreeArrayCodec extends CodecImpl<\n typeof LTREE_ARRAY_CODEC_ID,\n readonly [\"equality\"],\n readonly string[],\n readonly string[]\n> {\n constructor(descriptor: AnyCodecDescriptor) {\n super(descriptor, ltreeArrayDataType);\n }\n\n async toWire(value: readonly string[], _ctx: CodecCallContext): Promise<readonly string[]> {\n for (const entry of value) {\n assertValidLtree(entry);\n }\n return value;\n }\n\n async fromWire(wire: readonly string[], _ctx: CodecCallContext): Promise<readonly string[]> {\n return wire;\n }\n\n toDataTypeValue(value: readonly string[]): DataTypeValue {\n for (const entry of value) {\n assertValidLtree(entry);\n }\n return this.dataTypeValueOf([...value]);\n }\n\n fromDataTypeValue(value: DataTypeValue): readonly string[] {\n const json = value.value;\n if (!Array.isArray(json)) {\n return [];\n }\n return json.map((entry) => String(entry));\n }\n}\n\nexport class LtreeArrayDescriptor extends PostgresCodecDescriptor<void> {\n override readonly jsonType = \"array\" as const;\n protected override jsonProjection(expression: ProjectionExpr): ProjectionExpr {\n // ltree[] already projects as a JSON string array for fromWire.\n return expression;\n }\n override readonly dataType = ltreeArrayDataType.id;\n override readonly codecId = LTREE_ARRAY_CODEC_ID;\n override readonly traits = [\"equality\"] as const;\n override readonly paramsSchema = undefined;\n override renderOutputType(): string {\n return \"readonly string[]\";\n }\n override factory(): (ctx: CodecInstanceContext) => LtreeArrayCodec {\n const shared = new LtreeArrayCodec(this);\n return () => shared;\n }\n}\n\nexport const ltreeArrayDescriptor = new LtreeArrayDescriptor();\n\nexport const ltreeArray = () =>\n column(ltreeArrayDescriptor.factory(), ltreeArrayDescriptor.codecId, undefined);\n\nltreeArray satisfies ColumnHelperFor<LtreeArrayDescriptor>;\nltreeArray satisfies ColumnHelperForStrict<LtreeArrayDescriptor>;\n\nconst codecDescriptorMap = {\n ltree: ltreeDescriptor,\n ltreeArray: ltreeArrayDescriptor,\n} as const;\n\nexport type CodecTypes = ExtractCodecTypes<typeof codecDescriptorMap>;\n\nexport const codecDescriptors = definePostgresCodecs(Object.values(codecDescriptorMap));\n","import { buildCodecDescriptorRegistry } from \"@prisma/orm-family-sql/relational-core/codec-descriptor-registry\";\nimport type { CodecDescriptorRegistry } from \"@prisma/orm-family-sql/relational-core/query-lane-context\";\nimport { codecDescriptors } from \"./codecs\";\n\nexport const ltreeCodecRegistry: CodecDescriptorRegistry =\n buildCodecDescriptorRegistry(codecDescriptors);\n","import type { AnyExpression } from \"@prisma/orm-family-sql/relational-core/ast\";\nimport {\n buildOperation,\n type CodecExpression,\n codecOf,\n type Expression,\n toExpr,\n} from \"@prisma/orm-family-sql/relational-core/expression\";\nimport type { CodecTypes } from \"../types/codec-types\";\nimport type { QueryOperationTypes } from \"../types/operation-types\";\nimport { ltreeAuthoringTypes } from \"./authoring\";\nimport { LTREE_ARRAY_CODEC_ID, LTREE_CODEC_ID } from \"./constants\";\nimport { ltreeDataTypes } from \"./data-types\";\nimport { ltreeCodecRegistry } from \"./registry\";\n\ntype CodecTypesBase = Record<string, { readonly input: unknown; readonly output: unknown }>;\n\ntype BoolReturn = Expression<{ readonly codecId: \"pg/bool@1\"; readonly nullable: false }>;\ntype LtreeReturn = Expression<{ readonly codecId: \"pg/ltree@1\"; readonly nullable: false }>;\ntype IntReturn = Expression<{ readonly codecId: \"pg/int4@1\"; readonly nullable: false }>;\ntype TextReturn = Expression<{ readonly codecId: \"pg/text@1\"; readonly nullable: false }>;\n\nconst BOOL_RETURN = { codecId: \"pg/bool@1\", nullable: false } as const;\nconst LTREE_RETURN = { codecId: \"pg/ltree@1\", nullable: false } as const;\nconst INT_RETURN = { codecId: \"pg/int4@1\", nullable: false } as const;\nconst TEXT_RETURN = { codecId: \"pg/text@1\", nullable: false } as const;\nconst TEXT_CODEC_ID = \"pg/text@1\" as const;\nconst INT_CODEC_ID = \"pg/int4@1\" as const;\n\n/**\n * Build a function-style operation whose SQL is `fnName(self, arg0, arg1, ...)`.\n * The template's placeholder count is derived from the actual argument list, so\n * one helper covers fixed-arity functions (`nlevel`, `subltree`), optional-arg\n * overloads (`subpath`, `index`), and the variadic `lca` (see ADR-001). `args`\n * already carries each value through `toExpr` with its codec; `args[0]` is the\n * `self` receiver.\n */\nfunction funcOp<C extends string>(\n method: string,\n fnName: string,\n returns: { readonly codecId: C; readonly nullable: false },\n args: readonly [AnyExpression, ...AnyExpression[]],\n): Expression<{ readonly codecId: C; readonly nullable: false }> {\n const placeholders = args.map((_, i) => (i === 0 ? \"{{self}}\" : `{{arg${i - 1}}}`)).join(\", \");\n return buildOperation({\n method,\n args,\n returns,\n lowering: {\n targetFamily: \"sql\",\n template: `${fnName}(${placeholders})`,\n },\n });\n}\n\nexport function ltreeQueryOperations<CT extends CodecTypesBase>(): QueryOperationTypes<CT> {\n // Hierarchy operators compare two `ltree` values; the user argument shares the\n // column's `pg/ltree@1` codec. Pattern-match operators take a query/pattern\n // string (or `string[]`) that is NOT an ltree — it is bound as text and cast\n // in-template to `lquery` / `lquery[]` / `ltxtquery` (the validated-string-param\n // approach; verified executable under PGlite).\n const hierarchyOp = (\n method: string,\n operator: string,\n self: CodecExpression<typeof LTREE_CODEC_ID, boolean, CT>,\n other: CodecExpression<typeof LTREE_CODEC_ID, boolean, CT>,\n ): BoolReturn => {\n const selfCodec = codecOf(self);\n return buildOperation({\n method,\n args: [toExpr(self, selfCodec), toExpr(other, selfCodec)],\n returns: BOOL_RETURN,\n lowering: {\n targetFamily: \"sql\",\n template: `{{self}} ${operator} {{arg0}}`,\n },\n });\n };\n\n const patternOp = (\n method: string,\n operator: string,\n castType: string,\n self: CodecExpression<typeof LTREE_CODEC_ID, boolean, CT>,\n arg: unknown,\n many = false,\n ): BoolReturn => {\n const selfCodec = codecOf(self);\n return buildOperation({\n method,\n args: [\n toExpr(self, selfCodec),\n toExpr(arg, many ? { codecId: TEXT_CODEC_ID, many: true } : { codecId: TEXT_CODEC_ID }),\n ],\n returns: BOOL_RETURN,\n lowering: {\n targetFamily: \"sql\",\n template: `{{self}} ${operator} ({{arg0}})::${castType}`,\n },\n });\n };\n\n // Concatenation operators produce a new ltree. `concat` joins two ltree paths\n // (`{{self}} || {{arg0}}`); `concatText`/`prependText` splice a text label onto\n // the right/left. The text operand binds as `pg/text@1` and is cast in-template\n // (PG resolves the `||` overload from the cast). `prependText` places `{{self}}`\n // second because the ltree receiver is the RIGHT operand of `text || ltree`;\n // `args[0]` is still `self` (the renderer binds by placeholder name, not order).\n const concatOp = (\n method: string,\n template: string,\n args: readonly [AnyExpression, ...AnyExpression[]],\n ): LtreeReturn =>\n buildOperation({\n method,\n args,\n returns: LTREE_RETURN,\n lowering: { targetFamily: \"sql\", template },\n });\n\n // Tier 3 — first-match operators on an `ltree[]` receiver (ADR-003).\n const firstMatchOp = (\n method: string,\n operator: string,\n self: CodecExpression<typeof LTREE_ARRAY_CODEC_ID, boolean, CT>,\n arg: unknown,\n argCodecId: typeof LTREE_CODEC_ID | typeof TEXT_CODEC_ID,\n castType?: string,\n ): LtreeReturn => {\n const selfCodec = codecOf(self);\n const template = castType\n ? `{{self}} ${operator} ({{arg0}})::${castType}`\n : `{{self}} ${operator} {{arg0}}`;\n return buildOperation({\n method,\n args: [toExpr(self, selfCodec), toExpr(arg, { codecId: argCodecId })],\n returns: LTREE_RETURN,\n lowering: { targetFamily: \"sql\", template },\n });\n };\n\n return {\n isAncestorOf: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self, other) => hierarchyOp(\"isAncestorOf\", \"@>\", self, other),\n },\n isDescendantOf: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self, other) => hierarchyOp(\"isDescendantOf\", \"<@\", self, other),\n },\n matchesLquery: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self, pattern) => patternOp(\"matchesLquery\", \"~\", \"lquery\", self, pattern),\n },\n matchesLqueryArray: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self, patterns) =>\n patternOp(\"matchesLqueryArray\", \"?\", \"lquery[]\", self, patterns, true),\n },\n matchesLtxtquery: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self, query) => patternOp(\"matchesLtxtquery\", \"@\", \"ltxtquery\", self, query),\n },\n nlevel: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self): IntReturn =>\n funcOp(\"nlevel\", \"nlevel\", INT_RETURN, [toExpr(self, codecOf(self))]),\n },\n subltree: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self, start, end): LtreeReturn =>\n funcOp(\"subltree\", \"subltree\", LTREE_RETURN, [\n toExpr(self, codecOf(self)),\n toExpr(start, { codecId: INT_CODEC_ID }),\n toExpr(end, { codecId: INT_CODEC_ID }),\n ]),\n },\n // `subpath(self, offset, len?)` — `len` omitted lowers to the 2-arg overload.\n subpath: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self, offset, len): LtreeReturn => {\n const head: readonly [AnyExpression, AnyExpression] = [\n toExpr(self, codecOf(self)),\n toExpr(offset, { codecId: INT_CODEC_ID }),\n ];\n return funcOp(\n \"subpath\",\n \"subpath\",\n LTREE_RETURN,\n len === undefined ? head : [...head, toExpr(len, { codecId: INT_CODEC_ID })],\n );\n },\n },\n // `index(self, other, offset?)` — `offset` omitted lowers to the 2-arg overload.\n indexOf: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self, other, offset): IntReturn => {\n const selfCodec = codecOf(self);\n const head: readonly [AnyExpression, AnyExpression] = [\n toExpr(self, selfCodec),\n toExpr(other, selfCodec),\n ];\n return funcOp(\n \"indexOf\",\n \"index\",\n INT_RETURN,\n offset === undefined ? head : [...head, toExpr(offset, { codecId: INT_CODEC_ID })],\n );\n },\n },\n // `lca(self, other, ...rest)` — variadic longest-common-ancestor (ADR-001).\n // PostgreSQL has no single-arg `lca`, so `other` is required (2–8 paths).\n lca: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self, other, ...rest): LtreeReturn => {\n const selfCodec = codecOf(self);\n return funcOp(\"lca\", \"lca\", LTREE_RETURN, [\n toExpr(self, selfCodec),\n toExpr(other, selfCodec),\n ...rest.map((p) => toExpr(p, selfCodec)),\n ]);\n },\n },\n // Tier 2 — concatenation (`||`).\n concat: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self, other): LtreeReturn => {\n const selfCodec = codecOf(self);\n return concatOp(\"concat\", \"{{self}} || {{arg0}}\", [\n toExpr(self, selfCodec),\n toExpr(other, selfCodec),\n ]);\n },\n },\n concatText: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self, label): LtreeReturn =>\n concatOp(\"concatText\", \"{{self}} || ({{arg0}})::text\", [\n toExpr(self, codecOf(self)),\n toExpr(label, { codecId: TEXT_CODEC_ID }),\n ]),\n },\n // `text || ltree` — the ltree receiver is the right operand (ADR-002).\n prependText: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self, prefix): LtreeReturn =>\n concatOp(\"prependText\", \"({{arg0}})::text || {{self}}\", [\n toExpr(self, codecOf(self)),\n toExpr(prefix, { codecId: TEXT_CODEC_ID }),\n ]),\n },\n // Tier 2 — conversion.\n toText: {\n self: { codecId: LTREE_CODEC_ID },\n impl: (self): TextReturn =>\n funcOp(\"toText\", \"ltree2text\", TEXT_RETURN, [toExpr(self, codecOf(self))]),\n },\n // `text2ltree(text)` — rooted on `pg/text@1` (the only reachable form of the\n // free-function `text2ltree`; see ADR-002). Surfaces as `.toLtree()` on text.\n toLtree: {\n self: { codecId: TEXT_CODEC_ID },\n impl: (self): LtreeReturn =>\n funcOp(\"toLtree\", \"text2ltree\", LTREE_RETURN, [toExpr(self, codecOf(self))]),\n },\n // Tier 3 — array first-match operators (ADR-003).\n firstAncestorOf: {\n self: { codecId: LTREE_ARRAY_CODEC_ID },\n impl: (self, other) => firstMatchOp(\"firstAncestorOf\", \"?@>\", self, other, LTREE_CODEC_ID),\n },\n firstDescendantOf: {\n self: { codecId: LTREE_ARRAY_CODEC_ID },\n impl: (self, other) => firstMatchOp(\"firstDescendantOf\", \"?<@\", self, other, LTREE_CODEC_ID),\n },\n firstMatchLquery: {\n self: { codecId: LTREE_ARRAY_CODEC_ID },\n impl: (self, pattern) =>\n firstMatchOp(\"firstMatchLquery\", \"?~\", self, pattern, TEXT_CODEC_ID, \"lquery\"),\n },\n firstMatchLtxtquery: {\n self: { codecId: LTREE_ARRAY_CODEC_ID },\n impl: (self, query) =>\n firstMatchOp(\"firstMatchLtxtquery\", \"?@\", self, query, TEXT_CODEC_ID, \"ltxtquery\"),\n },\n // `lca(ltree[])` — array-receiver form (ADR-001, ADR-005). Named `lcaAll`\n // because prisma-next keys operations by name only (`createOperationRegistry`\n // throws on a duplicate); `lca` is already the variadic scalar method on\n // `pg/ltree@1`. Declares `nullable: false` for parity with the Tier 3\n // first-match ops even though PG returns NULL for an empty/NULL `ltree[]`\n // (see the empty-array integration test) — a family-wide gap, not specific\n // to `lcaAll`.\n lcaAll: {\n self: { codecId: LTREE_ARRAY_CODEC_ID },\n impl: (self): LtreeReturn =>\n funcOp(\"lcaAll\", \"lca\", LTREE_RETURN, [toExpr(self, codecOf(self))]),\n },\n };\n}\n\nconst ltreePackMetaBase = {\n kind: \"extension\",\n id: \"ltree\",\n familyId: \"sql\",\n targetId: \"postgres\",\n version: \"0.1.0\",\n capabilities: {\n postgres: {\n \"ltree.path\": true,\n },\n },\n authoring: {\n type: ltreeAuthoringTypes,\n },\n dataTypes: ltreeDataTypes,\n types: {\n codecTypes: {\n codecDescriptors: Array.from(ltreeCodecRegistry.values()),\n import: {\n package: \"prisma-ltree/codec-types\",\n named: \"CodecTypes\",\n alias: \"LtreeTypes\",\n },\n typeImports: [\n {\n package: \"prisma-ltree/codec-types\",\n named: \"Ltree\",\n alias: \"Ltree\",\n },\n ],\n },\n queryOperationTypes: {\n import: {\n package: \"prisma-ltree/operation-types\",\n named: \"QueryOperationTypes\",\n alias: \"LtreeQueryOperationTypes\",\n },\n },\n },\n} as const;\n\nexport const ltreePackMeta: typeof ltreePackMetaBase & {\n readonly __codecTypes?: CodecTypes;\n} = ltreePackMetaBase;\n"],"mappings":"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"}
|
package/dist/pack.d.mts
CHANGED
package/dist/pack.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as ltreePackMeta } from "./descriptor-meta-
|
|
1
|
+
import { t as ltreePackMeta } from "./descriptor-meta-Cc6tmP54.mjs";
|
|
2
2
|
export { ltreePackMeta as default };
|
package/dist/runtime.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as ltreeQueryOperations, r as ltreeCodecRegistry, t as ltreePackMeta } from "./descriptor-meta-
|
|
1
|
+
import { n as ltreeQueryOperations, r as ltreeCodecRegistry, t as ltreePackMeta } from "./descriptor-meta-Cc6tmP54.mjs";
|
|
2
2
|
//#region src/exports/runtime.ts
|
|
3
3
|
const ltreeRuntimeDescriptor = {
|
|
4
4
|
kind: "extension",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prisma-ltree",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Prisma 8 extension pack for PostgreSQL's ltree hierarchical tree data type.",
|
|
5
5
|
"homepage": "https://prisma-ltree.procka.org",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -28,26 +28,27 @@
|
|
|
28
28
|
"access": "public"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@prisma/orm-family-sql": "8.0.0-rc.
|
|
32
|
-
"@prisma/orm-framework": "8.0.0-rc.
|
|
33
|
-
"@prisma/orm-toolchain": "8.0.0-rc.
|
|
31
|
+
"@prisma/orm-family-sql": "8.0.0-rc.23",
|
|
32
|
+
"@prisma/orm-framework": "8.0.0-rc.23",
|
|
33
|
+
"@prisma/orm-toolchain": "8.0.0-rc.23",
|
|
34
34
|
"@standard-schema/spec": "^1.1.0",
|
|
35
|
-
"arktype": "^2.2.0"
|
|
35
|
+
"arktype": "^2.2.0",
|
|
36
|
+
"temporal-spec": "1.0.1"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@electric-sql/pglite": "^0.5.3",
|
|
39
|
-
"@prisma/cli-engine": "0.
|
|
40
|
-
"@prisma/orm-postgres": "8.0.0-rc.
|
|
41
|
-
"@prisma/orm-target-postgres": "8.0.0-rc.
|
|
40
|
+
"@prisma/cli-engine": "0.9.0",
|
|
41
|
+
"@prisma/orm-postgres": "8.0.0-rc.23",
|
|
42
|
+
"@prisma/orm-target-postgres": "8.0.0-rc.23",
|
|
42
43
|
"@types/node": "^24",
|
|
43
44
|
"@typescript/native-preview": "7.0.0-dev.20260509.2",
|
|
44
45
|
"@vitest/coverage-v8": "4.1.8",
|
|
45
|
-
"prisma": "8.0.0-rc.
|
|
46
|
+
"prisma": "8.0.0-rc.33",
|
|
46
47
|
"typescript": "^5",
|
|
47
48
|
"vite-plus": "0.1.24"
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
50
|
-
"@prisma/orm-target-postgres": "8.0.0-rc.
|
|
51
|
+
"@prisma/orm-target-postgres": "8.0.0-rc.23",
|
|
51
52
|
"typescript": ">=5.9"
|
|
52
53
|
},
|
|
53
54
|
"peerDependenciesMeta": {
|
package/src/contract.d.ts
CHANGED
|
@@ -2,25 +2,13 @@
|
|
|
2
2
|
// This file is automatically generated by 'prisma contract emit'.
|
|
3
3
|
// To regenerate, run: prisma contract emit
|
|
4
4
|
import type {
|
|
5
|
-
Bit,
|
|
6
|
-
Char,
|
|
7
5
|
CodecTypes as PgTypes,
|
|
8
|
-
|
|
9
|
-
JsonValue,
|
|
10
|
-
Numeric,
|
|
11
|
-
Time,
|
|
12
|
-
TimeString,
|
|
13
|
-
Timestamp,
|
|
14
|
-
TimestampString,
|
|
15
|
-
Timestamptz,
|
|
16
|
-
TimestamptzString,
|
|
17
|
-
Timetz,
|
|
18
|
-
VarBit,
|
|
19
|
-
Varchar,
|
|
6
|
+
ParameterizedOutputTypesForTypeParams as PgParameterizedOutputTypes,
|
|
20
7
|
} from '@prisma/orm-postgres/target/codec-types';
|
|
21
8
|
import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types';
|
|
22
9
|
|
|
23
10
|
import type {
|
|
11
|
+
ColumnTypesFromStorage,
|
|
24
12
|
ContractWithTypeMaps,
|
|
25
13
|
RelationKeys,
|
|
26
14
|
TypeMaps as TypeMapsType,
|
|
@@ -28,13 +16,14 @@ import type {
|
|
|
28
16
|
import type {
|
|
29
17
|
Contract as ContractType,
|
|
30
18
|
ExecutionHashBase,
|
|
19
|
+
FieldTypesFromDomain,
|
|
31
20
|
NamespaceId,
|
|
32
21
|
ProfileHashBase,
|
|
33
22
|
StorageHashBase,
|
|
34
23
|
} from '@prisma/orm-postgres/contract/types';
|
|
35
24
|
|
|
36
25
|
export type StorageHash =
|
|
37
|
-
StorageHashBase<'
|
|
26
|
+
StorageHashBase<'6db18d99f118ef4e7fd359cf8bc472b9335bf3edeeefa8a15ee11eaf7742f9fb'>;
|
|
38
27
|
export type ExecutionHash = ExecutionHashBase<string>;
|
|
39
28
|
export type ProfileHash =
|
|
40
29
|
ProfileHashBase<'3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2'>;
|
|
@@ -53,6 +42,10 @@ export type AggregateTypes = {
|
|
|
53
42
|
readonly 'pg/int4@1': { readonly output: 'pg/float8@1'; readonly nullable: true };
|
|
54
43
|
readonly 'pg/int8@1': { readonly output: 'pg/float8@1'; readonly nullable: true };
|
|
55
44
|
readonly 'pg/int8number@1': { readonly output: 'pg/float8@1'; readonly nullable: true };
|
|
45
|
+
readonly 'pg/interval-string@1': {
|
|
46
|
+
readonly output: 'pg/interval-string@1';
|
|
47
|
+
readonly nullable: true;
|
|
48
|
+
};
|
|
56
49
|
readonly 'pg/interval@1': { readonly output: 'pg/interval@1'; readonly nullable: true };
|
|
57
50
|
readonly 'pg/numeric@1': { readonly output: 'pg/numeric@1'; readonly nullable: true };
|
|
58
51
|
readonly 'pg/time-string@1': { readonly output: 'pg/interval@1'; readonly nullable: true };
|
|
@@ -102,8 +95,14 @@ export type AggregateTypes = {
|
|
|
102
95
|
readonly 'pg/int4@1': { readonly output: 'pg/int4@1'; readonly nullable: true };
|
|
103
96
|
readonly 'pg/int8@1': { readonly output: 'pg/int8@1'; readonly nullable: true };
|
|
104
97
|
readonly 'pg/int8number@1': { readonly output: 'pg/int8number@1'; readonly nullable: true };
|
|
98
|
+
readonly 'pg/interval-string@1': {
|
|
99
|
+
readonly output: 'pg/interval-string@1';
|
|
100
|
+
readonly nullable: true;
|
|
101
|
+
};
|
|
105
102
|
readonly 'pg/interval@1': { readonly output: 'pg/interval@1'; readonly nullable: true };
|
|
103
|
+
readonly 'pg/money@1': { readonly output: 'pg/money@1'; readonly nullable: true };
|
|
106
104
|
readonly 'pg/numeric@1': { readonly output: 'pg/numeric@1'; readonly nullable: true };
|
|
105
|
+
readonly 'pg/oid@1': { readonly output: 'pg/oid@1'; readonly nullable: true };
|
|
107
106
|
readonly 'pg/text-array@1': { readonly output: 'pg/text-array@1'; readonly nullable: true };
|
|
108
107
|
readonly 'pg/text@1': { readonly output: 'pg/text@1'; readonly nullable: true };
|
|
109
108
|
readonly 'pg/time-string@1': { readonly output: 'pg/time-string@1'; readonly nullable: true };
|
|
@@ -111,6 +110,14 @@ export type AggregateTypes = {
|
|
|
111
110
|
readonly output: 'pg/time-temporal@1';
|
|
112
111
|
readonly nullable: true;
|
|
113
112
|
};
|
|
113
|
+
readonly 'pg/timestamp-date@1': {
|
|
114
|
+
readonly output: 'pg/timestamp-date@1';
|
|
115
|
+
readonly nullable: true;
|
|
116
|
+
};
|
|
117
|
+
readonly 'pg/timestamp-instant@1': {
|
|
118
|
+
readonly output: 'pg/timestamp-instant@1';
|
|
119
|
+
readonly nullable: true;
|
|
120
|
+
};
|
|
114
121
|
readonly 'pg/timestamp-string@1': {
|
|
115
122
|
readonly output: 'pg/timestamp-string@1';
|
|
116
123
|
readonly nullable: true;
|
|
@@ -162,8 +169,14 @@ export type AggregateTypes = {
|
|
|
162
169
|
readonly 'pg/int4@1': { readonly output: 'pg/int4@1'; readonly nullable: true };
|
|
163
170
|
readonly 'pg/int8@1': { readonly output: 'pg/int8@1'; readonly nullable: true };
|
|
164
171
|
readonly 'pg/int8number@1': { readonly output: 'pg/int8number@1'; readonly nullable: true };
|
|
172
|
+
readonly 'pg/interval-string@1': {
|
|
173
|
+
readonly output: 'pg/interval-string@1';
|
|
174
|
+
readonly nullable: true;
|
|
175
|
+
};
|
|
165
176
|
readonly 'pg/interval@1': { readonly output: 'pg/interval@1'; readonly nullable: true };
|
|
177
|
+
readonly 'pg/money@1': { readonly output: 'pg/money@1'; readonly nullable: true };
|
|
166
178
|
readonly 'pg/numeric@1': { readonly output: 'pg/numeric@1'; readonly nullable: true };
|
|
179
|
+
readonly 'pg/oid@1': { readonly output: 'pg/oid@1'; readonly nullable: true };
|
|
167
180
|
readonly 'pg/text-array@1': { readonly output: 'pg/text-array@1'; readonly nullable: true };
|
|
168
181
|
readonly 'pg/text@1': { readonly output: 'pg/text@1'; readonly nullable: true };
|
|
169
182
|
readonly 'pg/time-string@1': { readonly output: 'pg/time-string@1'; readonly nullable: true };
|
|
@@ -171,6 +184,14 @@ export type AggregateTypes = {
|
|
|
171
184
|
readonly output: 'pg/time-temporal@1';
|
|
172
185
|
readonly nullable: true;
|
|
173
186
|
};
|
|
187
|
+
readonly 'pg/timestamp-date@1': {
|
|
188
|
+
readonly output: 'pg/timestamp-date@1';
|
|
189
|
+
readonly nullable: true;
|
|
190
|
+
};
|
|
191
|
+
readonly 'pg/timestamp-instant@1': {
|
|
192
|
+
readonly output: 'pg/timestamp-instant@1';
|
|
193
|
+
readonly nullable: true;
|
|
194
|
+
};
|
|
174
195
|
readonly 'pg/timestamp-string@1': {
|
|
175
196
|
readonly output: 'pg/timestamp-string@1';
|
|
176
197
|
readonly nullable: true;
|
|
@@ -214,7 +235,12 @@ export type AggregateTypes = {
|
|
|
214
235
|
readonly 'pg/int4@1': { readonly output: 'pg/int8number@1'; readonly nullable: true };
|
|
215
236
|
readonly 'pg/int8@1': { readonly output: 'pg/int8number@1'; readonly nullable: true };
|
|
216
237
|
readonly 'pg/int8number@1': { readonly output: 'pg/int8number@1'; readonly nullable: true };
|
|
238
|
+
readonly 'pg/interval-string@1': {
|
|
239
|
+
readonly output: 'pg/interval-string@1';
|
|
240
|
+
readonly nullable: true;
|
|
241
|
+
};
|
|
217
242
|
readonly 'pg/interval@1': { readonly output: 'pg/interval@1'; readonly nullable: true };
|
|
243
|
+
readonly 'pg/money@1': { readonly output: 'pg/money@1'; readonly nullable: true };
|
|
218
244
|
readonly 'pg/numeric@1': { readonly output: 'pg/numeric@1'; readonly nullable: true };
|
|
219
245
|
readonly 'pg/time-string@1': { readonly output: 'pg/interval@1'; readonly nullable: true };
|
|
220
246
|
readonly 'pg/time-temporal@1': { readonly output: 'pg/interval@1'; readonly nullable: true };
|
|
@@ -246,11 +272,40 @@ type DefaultLiteralValue<CodecId extends string, Encoded> = CodecId extends keyo
|
|
|
246
272
|
? Encoded
|
|
247
273
|
: CodecTypes[CodecId]['json']
|
|
248
274
|
: Encoded;
|
|
275
|
+
type ParameterizedOutputTypeFunctions = PgParameterizedOutputTypes;
|
|
249
276
|
|
|
250
|
-
|
|
251
|
-
export type
|
|
252
|
-
|
|
253
|
-
|
|
277
|
+
type FieldTypeOverrides = {};
|
|
278
|
+
export type FieldOutputTypes = FieldTypesFromDomain<
|
|
279
|
+
ContractBase['domain']['namespaces'],
|
|
280
|
+
CodecTypes,
|
|
281
|
+
ParameterizedOutputTypeFunctions,
|
|
282
|
+
FieldTypeOverrides,
|
|
283
|
+
'output',
|
|
284
|
+
ContractBase['storage']['namespaces']
|
|
285
|
+
>;
|
|
286
|
+
export type FieldInputTypes = FieldTypesFromDomain<
|
|
287
|
+
ContractBase['domain']['namespaces'],
|
|
288
|
+
CodecTypes,
|
|
289
|
+
ParameterizedOutputTypeFunctions,
|
|
290
|
+
FieldTypeOverrides,
|
|
291
|
+
'input',
|
|
292
|
+
ContractBase['storage']['namespaces']
|
|
293
|
+
>;
|
|
294
|
+
type ColumnTypeOverrides = {};
|
|
295
|
+
export type StorageColumnTypes = ColumnTypesFromStorage<
|
|
296
|
+
ContractBase['storage'],
|
|
297
|
+
CodecTypes,
|
|
298
|
+
ParameterizedOutputTypeFunctions,
|
|
299
|
+
ColumnTypeOverrides,
|
|
300
|
+
'output'
|
|
301
|
+
>;
|
|
302
|
+
export type StorageColumnInputTypes = ColumnTypesFromStorage<
|
|
303
|
+
ContractBase['storage'],
|
|
304
|
+
CodecTypes,
|
|
305
|
+
ParameterizedOutputTypeFunctions,
|
|
306
|
+
ColumnTypeOverrides,
|
|
307
|
+
'input'
|
|
308
|
+
>;
|
|
254
309
|
|
|
255
310
|
export namespace Models {}
|
|
256
311
|
|
|
@@ -271,6 +326,11 @@ export type TypeMaps = TypeMapsType<
|
|
|
271
326
|
type ContractBase = Omit<
|
|
272
327
|
ContractType<{
|
|
273
328
|
readonly namespaces: {
|
|
329
|
+
readonly __unbound__: {
|
|
330
|
+
readonly id: '__unbound__';
|
|
331
|
+
readonly kind: 'postgres-unbound-schema';
|
|
332
|
+
readonly entries: { readonly table: {} };
|
|
333
|
+
};
|
|
274
334
|
readonly public: {
|
|
275
335
|
readonly id: 'public';
|
|
276
336
|
readonly kind: 'postgres-schema';
|
|
@@ -308,6 +368,8 @@ type ContractBase = Omit<
|
|
|
308
368
|
readonly capabilities: {
|
|
309
369
|
readonly postgres: {
|
|
310
370
|
readonly distinctOn: true;
|
|
371
|
+
readonly forKeyShare: true;
|
|
372
|
+
readonly forNoKeyUpdate: true;
|
|
311
373
|
readonly jsonAgg: true;
|
|
312
374
|
readonly lateral: true;
|
|
313
375
|
readonly limit: true;
|
|
@@ -318,16 +380,21 @@ type ContractBase = Omit<
|
|
|
318
380
|
readonly checkConstraint: true;
|
|
319
381
|
readonly defaultInInsert: true;
|
|
320
382
|
readonly enums: true;
|
|
383
|
+
readonly forShare: true;
|
|
384
|
+
readonly forUpdate: true;
|
|
321
385
|
readonly insertOnConflictSkip: true;
|
|
386
|
+
readonly insertOnConflictTarget: true;
|
|
322
387
|
readonly insertOnConflictWithoutTarget: true;
|
|
323
388
|
readonly lateral: true;
|
|
389
|
+
readonly lockNowait: true;
|
|
390
|
+
readonly lockOf: true;
|
|
391
|
+
readonly lockSkipLocked: true;
|
|
324
392
|
readonly returning: true;
|
|
325
393
|
readonly scalarList: true;
|
|
326
394
|
};
|
|
327
395
|
};
|
|
328
396
|
readonly extensions: {};
|
|
329
397
|
readonly meta: {};
|
|
330
|
-
|
|
331
398
|
readonly profileHash: ProfileHash;
|
|
332
399
|
};
|
|
333
400
|
|
package/src/contract.json
CHANGED
|
@@ -13,6 +13,19 @@
|
|
|
13
13
|
},
|
|
14
14
|
"storage": {
|
|
15
15
|
"namespaces": {
|
|
16
|
+
"__unbound__": {
|
|
17
|
+
"entries": {
|
|
18
|
+
"extension": {
|
|
19
|
+
"ltree": {
|
|
20
|
+
"kind": "extension",
|
|
21
|
+
"name": "ltree"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"table": {}
|
|
25
|
+
},
|
|
26
|
+
"id": "__unbound__",
|
|
27
|
+
"kind": "postgres-unbound-schema"
|
|
28
|
+
},
|
|
16
29
|
"public": {
|
|
17
30
|
"entries": {
|
|
18
31
|
"table": {}
|
|
@@ -21,7 +34,7 @@
|
|
|
21
34
|
"kind": "postgres-schema"
|
|
22
35
|
}
|
|
23
36
|
},
|
|
24
|
-
"storageHash": "
|
|
37
|
+
"storageHash": "6db18d99f118ef4e7fd359cf8bc472b9335bf3edeeefa8a15ee11eaf7742f9fb",
|
|
25
38
|
"types": {
|
|
26
39
|
"ltree": {
|
|
27
40
|
"codecId": "pg/ltree@1",
|
|
@@ -38,6 +51,8 @@
|
|
|
38
51
|
"capabilities": {
|
|
39
52
|
"postgres": {
|
|
40
53
|
"distinctOn": true,
|
|
54
|
+
"forKeyShare": true,
|
|
55
|
+
"forNoKeyUpdate": true,
|
|
41
56
|
"jsonAgg": true,
|
|
42
57
|
"lateral": true,
|
|
43
58
|
"limit": true,
|
|
@@ -48,9 +63,15 @@
|
|
|
48
63
|
"checkConstraint": true,
|
|
49
64
|
"defaultInInsert": true,
|
|
50
65
|
"enums": true,
|
|
66
|
+
"forShare": true,
|
|
67
|
+
"forUpdate": true,
|
|
51
68
|
"insertOnConflictSkip": true,
|
|
69
|
+
"insertOnConflictTarget": true,
|
|
52
70
|
"insertOnConflictWithoutTarget": true,
|
|
53
71
|
"lateral": true,
|
|
72
|
+
"lockNowait": true,
|
|
73
|
+
"lockOf": true,
|
|
74
|
+
"lockSkipLocked": true,
|
|
54
75
|
"returning": true,
|
|
55
76
|
"scalarList": true
|
|
56
77
|
}
|
package/src/contract.ts
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { assembleDataTypes } from "@prisma/orm-framework/components/codec";
|
|
2
|
+
import { defineContract, extension, unbound } from "@prisma/orm-postgres/contract-builder";
|
|
3
|
+
import { assemblePostgresCodecRegistryWithBuiltins } from "@prisma/orm-target-postgres/target/codecs";
|
|
4
|
+
import { postgresDataTypes } from "@prisma/orm-target-postgres/target/data-types";
|
|
5
|
+
import type { Temporal } from "temporal-spec";
|
|
2
6
|
import { LTREE_ARRAY_CODEC_ID, LTREE_CODEC_ID } from "./core/constants";
|
|
3
7
|
import { LTREE_ARRAY_STORAGE_TYPE, LTREE_NATIVE_TYPE } from "./core/contract-space-constants";
|
|
8
|
+
import { codecDescriptors } from "./core/codecs";
|
|
9
|
+
import { ltreeDataTypes } from "./core/data-types";
|
|
4
10
|
|
|
5
|
-
export
|
|
6
|
-
|
|
11
|
+
export type { Temporal };
|
|
12
|
+
|
|
13
|
+
const dataTypeLookup = assembleDataTypes([
|
|
14
|
+
{ id: "postgres", dataTypes: postgresDataTypes },
|
|
15
|
+
{ id: "ltree", dataTypes: ltreeDataTypes },
|
|
16
|
+
]).lookup;
|
|
17
|
+
const codecLookup = assemblePostgresCodecRegistryWithBuiltins(
|
|
18
|
+
[{ types: { codecTypes: { codecDescriptors: [...codecDescriptors] } } }],
|
|
19
|
+
dataTypeLookup,
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export const contract = defineContract({ codecLookup, dataTypeLookup }, () => ({
|
|
23
|
+
databaseTypes: {
|
|
7
24
|
[LTREE_NATIVE_TYPE]: {
|
|
8
25
|
kind: "codec-instance",
|
|
9
26
|
codecId: LTREE_CODEC_ID,
|
|
@@ -16,6 +33,7 @@ export const contract = defineContract({}, () => ({
|
|
|
16
33
|
},
|
|
17
34
|
},
|
|
18
35
|
models: {},
|
|
36
|
+
entities: [extension("ltree", { namespace: unbound })],
|
|
19
37
|
}));
|
|
20
38
|
|
|
21
39
|
export default contract;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { LTREE_MAX_LABEL_LENGTH, LTREE_MAX_LABELS } from "./constants";
|
|
2
|
+
|
|
3
|
+
const LABEL_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
4
|
+
|
|
5
|
+
export function assertValidLtree(value: unknown): asserts value is string {
|
|
6
|
+
if (typeof value !== "string") {
|
|
7
|
+
throw new Error("ltree value must be a string");
|
|
8
|
+
}
|
|
9
|
+
if (value.length === 0) {
|
|
10
|
+
throw new Error("ltree value must not be empty");
|
|
11
|
+
}
|
|
12
|
+
const labels = value.split(".");
|
|
13
|
+
if (labels.length > LTREE_MAX_LABELS) {
|
|
14
|
+
throw new Error(`ltree path exceeds max labels: got ${labels.length}, max ${LTREE_MAX_LABELS}`);
|
|
15
|
+
}
|
|
16
|
+
for (const label of labels) {
|
|
17
|
+
if (label.length === 0) {
|
|
18
|
+
throw new Error(`ltree label must not be empty in path "${value}"`);
|
|
19
|
+
}
|
|
20
|
+
if (label.length > LTREE_MAX_LABEL_LENGTH) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`ltree label exceeds max length: got ${label.length}, max ${LTREE_MAX_LABEL_LENGTH}`,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
if (!LABEL_PATTERN.test(label)) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`ltree label "${label}" contains invalid characters; allowed: alphanumeric, underscore, hyphen`,
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/core/codecs.ts
CHANGED
|
@@ -1,54 +1,24 @@
|
|
|
1
|
-
import type { JsonValue } from "@prisma/orm-framework/contract/types";
|
|
2
1
|
import {
|
|
2
|
+
type AnyCodecDescriptor,
|
|
3
3
|
type CodecCallContext,
|
|
4
4
|
CodecImpl,
|
|
5
5
|
type CodecInstanceContext,
|
|
6
6
|
type ColumnHelperFor,
|
|
7
7
|
type ColumnHelperForStrict,
|
|
8
8
|
column,
|
|
9
|
+
type DataTypeValue,
|
|
9
10
|
} from "@prisma/orm-framework/components/codec";
|
|
10
11
|
import type { ExtractCodecTypes, ProjectionExpr } from "@prisma/orm-family-sql/relational-core/ast";
|
|
12
|
+
import { CastExpr } from "@prisma/orm-family-sql/relational-core/ast";
|
|
11
13
|
import {
|
|
12
14
|
definePostgresCodecs,
|
|
13
15
|
PostgresCodecDescriptor,
|
|
14
16
|
} from "@prisma/orm-target-postgres/target/codec-descriptor";
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
LTREE_CODEC_ID,
|
|
18
|
-
LTREE_MAX_LABEL_LENGTH,
|
|
19
|
-
LTREE_MAX_LABELS,
|
|
20
|
-
} from "./constants";
|
|
17
|
+
import { assertValidLtree } from "./codecs-validation";
|
|
18
|
+
import { LTREE_ARRAY_CODEC_ID, LTREE_CODEC_ID } from "./constants";
|
|
21
19
|
import { ltreeArrayDataType, ltreeDataType } from "./data-types";
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
export function assertValidLtree(value: unknown): asserts value is string {
|
|
26
|
-
if (typeof value !== "string") {
|
|
27
|
-
throw new Error("ltree value must be a string");
|
|
28
|
-
}
|
|
29
|
-
if (value.length === 0) {
|
|
30
|
-
throw new Error("ltree value must not be empty");
|
|
31
|
-
}
|
|
32
|
-
const labels = value.split(".");
|
|
33
|
-
if (labels.length > LTREE_MAX_LABELS) {
|
|
34
|
-
throw new Error(`ltree path exceeds max labels: got ${labels.length}, max ${LTREE_MAX_LABELS}`);
|
|
35
|
-
}
|
|
36
|
-
for (const label of labels) {
|
|
37
|
-
if (label.length === 0) {
|
|
38
|
-
throw new Error(`ltree label must not be empty in path "${value}"`);
|
|
39
|
-
}
|
|
40
|
-
if (label.length > LTREE_MAX_LABEL_LENGTH) {
|
|
41
|
-
throw new Error(
|
|
42
|
-
`ltree label exceeds max length: got ${label.length}, max ${LTREE_MAX_LABEL_LENGTH}`,
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
if (!LABEL_PATTERN.test(label)) {
|
|
46
|
-
throw new Error(
|
|
47
|
-
`ltree label "${label}" contains invalid characters; allowed: alphanumeric, underscore, hyphen`,
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
21
|
+
export { assertValidLtree } from "./codecs-validation";
|
|
52
22
|
|
|
53
23
|
export class LtreeCodec extends CodecImpl<
|
|
54
24
|
typeof LTREE_CODEC_ID,
|
|
@@ -56,30 +26,34 @@ export class LtreeCodec extends CodecImpl<
|
|
|
56
26
|
string,
|
|
57
27
|
string
|
|
58
28
|
> {
|
|
59
|
-
|
|
29
|
+
constructor(descriptor: AnyCodecDescriptor) {
|
|
30
|
+
super(descriptor, ltreeDataType);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async toWire(value: string, _ctx: CodecCallContext): Promise<string> {
|
|
60
34
|
assertValidLtree(value);
|
|
61
35
|
return value;
|
|
62
36
|
}
|
|
63
37
|
|
|
64
|
-
async
|
|
38
|
+
async fromWire(wire: string, _ctx: CodecCallContext): Promise<string> {
|
|
65
39
|
return wire;
|
|
66
40
|
}
|
|
67
41
|
|
|
68
|
-
|
|
42
|
+
toDataTypeValue(value: string): DataTypeValue {
|
|
69
43
|
assertValidLtree(value);
|
|
70
|
-
return value;
|
|
44
|
+
return this.dataTypeValueOf(value);
|
|
71
45
|
}
|
|
72
46
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return json;
|
|
47
|
+
fromDataTypeValue(value: DataTypeValue): string {
|
|
48
|
+
return value.value as string;
|
|
76
49
|
}
|
|
77
50
|
}
|
|
78
51
|
|
|
79
52
|
export class LtreeDescriptor extends PostgresCodecDescriptor<void> {
|
|
53
|
+
override readonly jsonType = "string" as const;
|
|
80
54
|
protected override jsonProjection(expression: ProjectionExpr): ProjectionExpr {
|
|
81
|
-
//
|
|
82
|
-
return expression;
|
|
55
|
+
// JSON projections read through fromWire; cast so the wire value is text.
|
|
56
|
+
return CastExpr.as(expression, "text");
|
|
83
57
|
}
|
|
84
58
|
override readonly dataType = ltreeDataType.id;
|
|
85
59
|
override readonly codecId = LTREE_CODEC_ID;
|
|
@@ -107,38 +81,41 @@ export class LtreeArrayCodec extends CodecImpl<
|
|
|
107
81
|
readonly string[],
|
|
108
82
|
readonly string[]
|
|
109
83
|
> {
|
|
110
|
-
|
|
84
|
+
constructor(descriptor: AnyCodecDescriptor) {
|
|
85
|
+
super(descriptor, ltreeArrayDataType);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async toWire(value: readonly string[], _ctx: CodecCallContext): Promise<readonly string[]> {
|
|
111
89
|
for (const entry of value) {
|
|
112
90
|
assertValidLtree(entry);
|
|
113
91
|
}
|
|
114
92
|
return value;
|
|
115
93
|
}
|
|
116
94
|
|
|
117
|
-
async
|
|
95
|
+
async fromWire(wire: readonly string[], _ctx: CodecCallContext): Promise<readonly string[]> {
|
|
118
96
|
return wire;
|
|
119
97
|
}
|
|
120
98
|
|
|
121
|
-
|
|
99
|
+
toDataTypeValue(value: readonly string[]): DataTypeValue {
|
|
122
100
|
for (const entry of value) {
|
|
123
101
|
assertValidLtree(entry);
|
|
124
102
|
}
|
|
125
|
-
return [...value];
|
|
103
|
+
return this.dataTypeValueOf([...value]);
|
|
126
104
|
}
|
|
127
105
|
|
|
128
|
-
|
|
106
|
+
fromDataTypeValue(value: DataTypeValue): readonly string[] {
|
|
107
|
+
const json = value.value;
|
|
129
108
|
if (!Array.isArray(json)) {
|
|
130
109
|
return [];
|
|
131
110
|
}
|
|
132
|
-
return json.map((entry) =>
|
|
133
|
-
assertValidLtree(entry);
|
|
134
|
-
return String(entry);
|
|
135
|
-
});
|
|
111
|
+
return json.map((entry) => String(entry));
|
|
136
112
|
}
|
|
137
113
|
}
|
|
138
114
|
|
|
139
115
|
export class LtreeArrayDescriptor extends PostgresCodecDescriptor<void> {
|
|
116
|
+
override readonly jsonType = "array" as const;
|
|
140
117
|
protected override jsonProjection(expression: ProjectionExpr): ProjectionExpr {
|
|
141
|
-
// ltree[]
|
|
118
|
+
// ltree[] already projects as a JSON string array for fromWire.
|
|
142
119
|
return expression;
|
|
143
120
|
}
|
|
144
121
|
override readonly dataType = ltreeArrayDataType.id;
|
|
@@ -7,6 +7,17 @@ export const LTREE_ARRAY_STORAGE_TYPE = "ltreeArray" as const;
|
|
|
7
7
|
|
|
8
8
|
export const LTREE_BASELINE_MIGRATION_NAME = "20260619T2142_install_ltree" as const;
|
|
9
9
|
|
|
10
|
+
export const LTREE_DECLARE_EXTENSION_MIGRATION_NAME =
|
|
11
|
+
"20261111T1905_declare_ltree_extension" as const;
|
|
12
|
+
|
|
13
|
+
export const LTREE_CREATE_EXTENSION_MIGRATION_NAME =
|
|
14
|
+
"20261111T1904_create_ltree_extension" as const;
|
|
15
|
+
|
|
16
|
+
export const LTREE_SEARCH_PATH_MIGRATION_NAME = "20261111T1908_find_ltree_on_search_path" as const;
|
|
17
|
+
|
|
18
|
+
export const LTREE_SEARCH_PATH_INSTALL_MIGRATION_NAME =
|
|
19
|
+
"20261111T1908_install_ltree_on_search_path" as const;
|
|
20
|
+
|
|
10
21
|
export const LTREE_INVARIANTS = {
|
|
11
22
|
installLtree: "ltree:install-ltree-v1",
|
|
12
23
|
} as const;
|