prisma-ltree 0.5.0 → 0.7.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.
Files changed (35) hide show
  1. package/README.md +41 -8
  2. package/dist/{codec-types-BJE-5cwk.d.mts → codec-types-B0DtEnU6.d.mts} +16 -13
  3. package/dist/codec-types-B0DtEnU6.d.mts.map +1 -0
  4. package/dist/codec-types.d.mts +1 -1
  5. package/dist/control.d.mts.map +1 -1
  6. package/dist/control.mjs +236 -16
  7. package/dist/control.mjs.map +1 -1
  8. package/dist/{descriptor-meta-2In8FI1I.mjs → descriptor-meta-DwbFei9y.mjs} +341 -34
  9. package/dist/descriptor-meta-DwbFei9y.mjs.map +1 -0
  10. package/dist/{operation-types-8su4lbK-.d.mts → operation-types-DD-KyBms.d.mts} +46 -1
  11. package/dist/{operation-types-8su4lbK-.d.mts.map → operation-types-DD-KyBms.d.mts.map} +1 -1
  12. package/dist/operation-types.d.mts +1 -1
  13. package/dist/pack.d.mts +1 -1
  14. package/dist/pack.d.mts.map +1 -1
  15. package/dist/pack.mjs +1 -1
  16. package/dist/runtime.d.mts +35 -1
  17. package/dist/runtime.d.mts.map +1 -1
  18. package/dist/runtime.mjs +34 -1
  19. package/dist/runtime.mjs.map +1 -1
  20. package/package.json +11 -10
  21. package/src/contract.d.ts +87 -20
  22. package/src/contract.json +22 -1
  23. package/src/contract.ts +21 -3
  24. package/src/core/codecs-validation.ts +31 -0
  25. package/src/core/codecs.ts +32 -55
  26. package/src/core/contract-space-constants.ts +11 -0
  27. package/src/core/data-types.ts +36 -2
  28. package/src/core/descriptor-meta.ts +64 -4
  29. package/src/core/hierarchy-collection-methods.ts +111 -0
  30. package/src/core/pattern-validation.ts +313 -0
  31. package/src/exports/control.ts +36 -1
  32. package/src/exports/runtime.ts +3 -0
  33. package/src/types/operation-types.ts +37 -0
  34. package/dist/codec-types-BJE-5cwk.d.mts.map +0 -1
  35. package/dist/descriptor-meta-2In8FI1I.mjs.map +0 -1
@@ -1,2 +1,2 @@
1
- import { t as QueryOperationTypes } from "./operation-types-8su4lbK-.mjs";
1
+ import { t as QueryOperationTypes } from "./operation-types-DD-KyBms.mjs";
2
2
  export type { QueryOperationTypes };
package/dist/pack.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as CodecTypes } from "./codec-types-BJE-5cwk.mjs";
1
+ import { t as CodecTypes } from "./codec-types-B0DtEnU6.mjs";
2
2
  //#region src/core/descriptor-meta.d.ts
3
3
  declare const ltreePackMetaBase: {
4
4
  readonly kind: "extension";
@@ -1 +1 @@
1
- {"version":3,"file":"pack.d.mts","names":[],"sources":["../src/core/descriptor-meta.ts"],"mappings":";;cA0SM,iBAAA;EAAA,SACJ,IAAA;EAAA,SACA,EAAA;EAAA,SACA,QAAA;EAAA,SACA,QAAA;EAAA,SACA,OAAA;EAAA,SACA,YAAA;IAAA,SACE,QAAA;MAAA,SACE,YAAA;IAAA;EAAA;EAAA,SAGJ,SAAA;IAAA,SACE,IAAA;MAAA;;;;;;;;;;;;;;;;;;WAEF,SAAA,4DAAS,QAAA;EAAA,SACT,KAAA;IAAA,SACE,UAAA;MAAA,SACE,gBAAA,mDAAgB,eAAA;MAAA,SAChB,MAAA;QAAA,SACE,OAAA;QAAA,SACA,KAAA;QAAA,SACA,KAAA;MAAA;MAAA,SAEF,WAAA;QAAA,SAEI,OAAA;QAAA,SACA,KAAA;QAAA,SACA,KAAA;MAAA;IAAA;IAAA,SAIN,mBAAA;MAAA,SACE,MAAA;QAAA,SACE,OAAA;QAAA,SACA,KAAA;QAAA,SACA,KAAA;MAAA;IAAA;EAAA;AAAA;AAAA,cAMK,aAAA,SAAsB,iBAAA;EAAA,SACxB,YAAA,GAAe,UAAU;AAAA"}
1
+ {"version":3,"file":"pack.d.mts","names":[],"sources":["../src/core/descriptor-meta.ts"],"mappings":";;cAsWM,iBAAA;EAAA,SACJ,IAAA;EAAA,SACA,EAAA;EAAA,SACA,QAAA;EAAA,SACA,QAAA;EAAA,SACA,OAAA;EAAA,SACA,YAAA;IAAA,SACE,QAAA;MAAA,SACE,YAAA;IAAA;EAAA;EAAA,SAGJ,SAAA;IAAA,SACE,IAAA;MAAA;;;;;;;;;;;;;;;;;;WAEF,SAAA,4DAAS,QAAA;EAAA,SACT,KAAA;IAAA,SACE,UAAA;MAAA,SACE,gBAAA,mDAAgB,eAAA;MAAA,SAChB,MAAA;QAAA,SACE,OAAA;QAAA,SACA,KAAA;QAAA,SACA,KAAA;MAAA;MAAA,SAEF,WAAA;QAAA,SAEI,OAAA;QAAA,SACA,KAAA;QAAA,SACA,KAAA;MAAA;IAAA;IAAA,SAIN,mBAAA;MAAA,SACE,MAAA;QAAA,SACE,OAAA;QAAA,SACA,KAAA;QAAA,SACA,KAAA;MAAA;IAAA;EAAA;AAAA;AAAA,cAMK,aAAA,SAAsB,iBAAA;EAAA,SACxB,YAAA,GAAe,UAAU;AAAA"}
package/dist/pack.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as ltreePackMeta } from "./descriptor-meta-2In8FI1I.mjs";
1
+ import { t as ltreePackMeta } from "./descriptor-meta-DwbFei9y.mjs";
2
2
  export { ltreePackMeta as default };
@@ -1,11 +1,45 @@
1
+ import { i as LTREE_CODEC_ID, n as Ltree } from "./codec-types-B0DtEnU6.mjs";
1
2
  import { SqlRuntimeExtensionDescriptor } from "@prisma/orm-family-sql/runtime";
2
3
  import { CodecDescriptorRegistry } from "@prisma/orm-family-sql/relational-core/query-lane-context";
4
+ import { CollectionMethodContributionType, CollectionMethodModelType } from "@prisma/orm-family-sql/relational-core/collection-methods";
3
5
 
4
6
  //#region src/core/registry.d.ts
5
7
  declare const ltreeCodecRegistry: CodecDescriptorRegistry;
6
8
  //#endregion
9
+ //#region src/core/hierarchy-collection-methods.d.ts
10
+ type LtreeFieldNames<Fields> = { [Name in keyof Fields]: Fields[Name] extends {
11
+ readonly many: object;
12
+ } ? never : Fields[Name] extends {
13
+ readonly type: {
14
+ readonly codecId: typeof LTREE_CODEC_ID;
15
+ };
16
+ } ? Name : never }[keyof Fields];
17
+ type HierarchyMethodTable<Model extends CollectionMethodModelType> = { readonly [Name in LtreeFieldNames<Model["fields"]> & string as `${Name}_descendants`]: {
18
+ readonly parameters: readonly [root: Ltree];
19
+ readonly filters: true;
20
+ readonly orders: false;
21
+ } } & { readonly [Name in LtreeFieldNames<Model["fields"]> & string as `${Name}_ancestors`]: {
22
+ readonly parameters: readonly [leaf: Ltree];
23
+ readonly filters: true;
24
+ readonly orders: false;
25
+ } };
26
+ /**
27
+ * One `{field}_descendants` / `{field}_ancestors` method per scalar `ltree`
28
+ * field. Descendants map to `isDescendantOf` (`<@`); ancestors map to
29
+ * `isAncestorOf` (`@>`). Both are inclusive of equality, matching PostgreSQL.
30
+ */
31
+ interface LtreeHierarchyMethods extends CollectionMethodContributionType {
32
+ readonly methods: HierarchyMethodTable<this["model"]>;
33
+ }
34
+ declare module "@prisma/orm-family-sql/relational-core/collection-methods" {
35
+ interface CollectionMethodRegistry {
36
+ readonly "ltree/hierarchy": LtreeHierarchyMethods;
37
+ }
38
+ }
39
+ /** The run-time half of `LtreeHierarchyMethods`. */
40
+ //#endregion
7
41
  //#region src/exports/runtime.d.ts
8
42
  declare const ltreeRuntimeDescriptor: SqlRuntimeExtensionDescriptor<"postgres">;
9
43
  //#endregion
10
- export { ltreeRuntimeDescriptor as default, ltreeCodecRegistry };
44
+ export { type LtreeHierarchyMethods, ltreeRuntimeDescriptor as default, ltreeCodecRegistry };
11
45
  //# sourceMappingURL=runtime.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/core/registry.ts","../src/exports/runtime.ts"],"mappings":";;;;cAIa,kBAAA,EAAoB,uBACe;;;cCD1C,sBAAA,EAAwB,6BAA6B"}
1
+ {"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/core/registry.ts","../src/core/hierarchy-collection-methods.ts","../src/exports/runtime.ts"],"mappings":";;;;;;cAIa,kBAAA,EAAoB,uBACe;;;KCO3C,eAAA,4BACY,MAAA,GAAS,MAAA,CAAO,IAAA;EAAA,SAAyB,IAAA;AAAA,YAEpD,MAAA,CAAO,IAAA;EAAA,SACM,IAAA;IAAA,SAAiB,OAAA,SAAgB,cAAA;EAAA;AAAA,IAE5C,IAAA,iBAEA,MAAA;AAAA,KAEH,oBAAA,eAAmC,yBAAA,wBACpB,eAAA,CAAgB,KAAA,2BAAgC,IAAA;EAAA,SACvD,UAAA,YAAsB,IAAA,EAAM,KAAA;EAAA,SAC5B,OAAA;EAAA,SACA,MAAA;AAAA,0BAGO,eAAA,CAAgB,KAAA,2BAAgC,IAAA;EAAA,SACvD,UAAA,YAAsB,IAAA,EAAM,KAAA;EAAA,SAC5B,OAAA;EAAA,SACA,MAAA;AAAA;;;;;;UASI,qBAAA,SAA8B,gCAAgC;EAAA,SACpE,OAAA,EAAS,oBAAA;AAAA;AAAA;EAAA,UAIR,wBAAA;IAAA,SACC,iBAAA,EAAmB,qBAAqB;EAAA;AAAA;;;;cC1C/C,sBAAA,EAAwB,6BAA6B"}
package/dist/runtime.mjs CHANGED
@@ -1,4 +1,36 @@
1
- import { n as ltreeQueryOperations, r as ltreeCodecRegistry, t as ltreePackMeta } from "./descriptor-meta-2In8FI1I.mjs";
1
+ import "./constants-Dfknw-h5.mjs";
2
+ import { n as ltreeQueryOperations, r as ltreeCodecRegistry, t as ltreePackMeta } from "./descriptor-meta-DwbFei9y.mjs";
3
+ import { blindCast } from "@prisma/orm-framework/utils/casts";
4
+ import { InternalError } from "@prisma/orm-framework/utils/internal-error";
5
+ //#region src/core/hierarchy-collection-methods.ts
6
+ function fieldOf(model, field) {
7
+ const accessor = blindCast(model)[field];
8
+ if (accessor === void 0) throw new InternalError(`The model accessor has no ltree field "${field}".`);
9
+ return accessor;
10
+ }
11
+ function descendantsMethod(field) {
12
+ return (collection, ...args) => {
13
+ const [root] = blindCast(args);
14
+ return collection.where((model) => fieldOf(model, field).isDescendantOf(root));
15
+ };
16
+ }
17
+ function ancestorsMethod(field) {
18
+ return (collection, ...args) => {
19
+ const [leaf] = blindCast(args);
20
+ return collection.where((model) => fieldOf(model, field).isAncestorOf(leaf));
21
+ };
22
+ }
23
+ function isScalarLtreeField(field) {
24
+ if (typeof field !== "object" || field === null) return false;
25
+ const record = field;
26
+ return record.many === void 0 && record.type?.kind === "scalar" && record.type.codecId === "pg/ltree@1";
27
+ }
28
+ /** The run-time half of `LtreeHierarchyMethods`. */
29
+ const ltreeHierarchyMethods = {
30
+ id: "ltree/hierarchy",
31
+ methodsFor: (model) => Object.fromEntries(Object.entries(model.fields).flatMap(([name, field]) => isScalarLtreeField(field) ? [[`${name}_descendants`, descendantsMethod(name)], [`${name}_ancestors`, ancestorsMethod(name)]] : []))
32
+ };
33
+ //#endregion
2
34
  //#region src/exports/runtime.ts
3
35
  const ltreeRuntimeDescriptor = {
4
36
  kind: "extension",
@@ -10,6 +42,7 @@ const ltreeRuntimeDescriptor = {
10
42
  types: { codecTypes: { codecDescriptors: Array.from(ltreeCodecRegistry.values()) } },
11
43
  codecs: () => Array.from(ltreeCodecRegistry.values()),
12
44
  queryOperations: () => ltreeQueryOperations(),
45
+ collectionMethods: () => [ltreeHierarchyMethods],
13
46
  create() {
14
47
  return {
15
48
  familyId: "sql",
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.mjs","names":[],"sources":["../src/exports/runtime.ts"],"sourcesContent":["import type { SqlRuntimeExtensionDescriptor } from \"@prisma/orm-family-sql/runtime\";\nimport { ltreePackMeta, ltreeQueryOperations } from \"../core/descriptor-meta\";\nimport { ltreeCodecRegistry } from \"../core/registry\";\n\nconst ltreeRuntimeDescriptor: SqlRuntimeExtensionDescriptor<\"postgres\"> = {\n kind: \"extension\" as const,\n id: ltreePackMeta.id,\n version: ltreePackMeta.version,\n dataTypes: ltreePackMeta.dataTypes,\n familyId: \"sql\" as const,\n targetId: \"postgres\" as const,\n types: {\n codecTypes: {\n codecDescriptors: Array.from(ltreeCodecRegistry.values()),\n },\n },\n codecs: () => Array.from(ltreeCodecRegistry.values()),\n queryOperations: () => ltreeQueryOperations(),\n create() {\n return {\n familyId: \"sql\" as const,\n targetId: \"postgres\" as const,\n };\n },\n};\n\nexport { ltreeCodecRegistry };\nexport default ltreeRuntimeDescriptor;\n"],"mappings":";;AAIA,MAAM,yBAAoE;CACxE,MAAM;CACN,IAAI,cAAc;CAClB,SAAS,cAAc;CACvB,WAAW,cAAc;CACzB,UAAU;CACV,UAAU;CACV,OAAO,EACL,YAAY,EACV,kBAAkB,MAAM,KAAK,mBAAmB,OAAO,CAAC,EAC1D,EACF;CACA,cAAc,MAAM,KAAK,mBAAmB,OAAO,CAAC;CACpD,uBAAuB,qBAAqB;CAC5C,SAAS;EACP,OAAO;GACL,UAAU;GACV,UAAU;EACZ;CACF;AACF"}
1
+ {"version":3,"file":"runtime.mjs","names":[],"sources":["../src/core/hierarchy-collection-methods.ts","../src/exports/runtime.ts"],"sourcesContent":["import type {\n CollectionMethodBody,\n CollectionMethodContribution,\n CollectionMethodContributionId,\n CollectionMethodContributionType,\n CollectionMethodModelType,\n} from \"@prisma/orm-family-sql/relational-core/collection-methods\";\nimport { blindCast } from \"@prisma/orm-framework/utils/casts\";\nimport { InternalError } from \"@prisma/orm-framework/utils/internal-error\";\nimport type { Ltree } from \"../types/codec-types\";\nimport { LTREE_CODEC_ID } from \"./constants\";\n\ntype LtreeFieldNames<Fields> = {\n [Name in keyof Fields]: Fields[Name] extends { readonly many: object }\n ? never\n : Fields[Name] extends {\n readonly type: { readonly codecId: typeof LTREE_CODEC_ID };\n }\n ? Name\n : never;\n}[keyof Fields];\n\ntype HierarchyMethodTable<Model extends CollectionMethodModelType> = {\n readonly [Name in LtreeFieldNames<Model[\"fields\"]> & string as `${Name}_descendants`]: {\n readonly parameters: readonly [root: Ltree];\n readonly filters: true;\n readonly orders: false;\n };\n} & {\n readonly [Name in LtreeFieldNames<Model[\"fields\"]> & string as `${Name}_ancestors`]: {\n readonly parameters: readonly [leaf: Ltree];\n readonly filters: true;\n readonly orders: false;\n };\n};\n\n/**\n * One `{field}_descendants` / `{field}_ancestors` method per scalar `ltree`\n * field. Descendants map to `isDescendantOf` (`<@`); ancestors map to\n * `isAncestorOf` (`@>`). Both are inclusive of equality, matching PostgreSQL.\n */\nexport interface LtreeHierarchyMethods extends CollectionMethodContributionType {\n readonly methods: HierarchyMethodTable<this[\"model\"]>;\n}\n\ndeclare module \"@prisma/orm-family-sql/relational-core/collection-methods\" {\n interface CollectionMethodRegistry {\n readonly \"ltree/hierarchy\": LtreeHierarchyMethods;\n }\n}\n\ninterface HierarchyField {\n isDescendantOf(root: Ltree): unknown;\n isAncestorOf(leaf: Ltree): unknown;\n}\n\ntype LtreeFields = Readonly<Record<string, HierarchyField>>;\n\nfunction fieldOf(model: unknown, field: string): HierarchyField {\n const accessor = blindCast<\n LtreeFields,\n \"an ltree field of the ORM model accessor has hierarchy operators\"\n >(model)[field];\n if (accessor === undefined) {\n throw new InternalError(`The model accessor has no ltree field \"${field}\".`);\n }\n return accessor;\n}\n\nfunction descendantsMethod(field: string): CollectionMethodBody {\n return (collection, ...args) => {\n const [root] = blindCast<readonly [Ltree], \"the type half declares a root path\">(args);\n return collection.where((model) => fieldOf(model, field).isDescendantOf(root));\n };\n}\n\nfunction ancestorsMethod(field: string): CollectionMethodBody {\n return (collection, ...args) => {\n const [leaf] = blindCast<readonly [Ltree], \"the type half declares a leaf path\">(args);\n return collection.where((model) => fieldOf(model, field).isAncestorOf(leaf));\n };\n}\n\nfunction isScalarLtreeField(field: unknown): boolean {\n if (typeof field !== \"object\" || field === null) return false;\n const record = field as {\n readonly many?: unknown;\n readonly type?: { readonly kind?: string; readonly codecId?: string };\n };\n return (\n record.many === undefined &&\n record.type?.kind === \"scalar\" &&\n record.type.codecId === LTREE_CODEC_ID\n );\n}\n\n/** The run-time half of `LtreeHierarchyMethods`. */\nexport const ltreeHierarchyMethods: CollectionMethodContribution = {\n id: \"ltree/hierarchy\" satisfies CollectionMethodContributionId,\n methodsFor: (model) =>\n Object.fromEntries(\n Object.entries(model.fields).flatMap(([name, field]) =>\n isScalarLtreeField(field)\n ? [\n [`${name}_descendants`, descendantsMethod(name)],\n [`${name}_ancestors`, ancestorsMethod(name)],\n ]\n : [],\n ),\n ),\n};\n","import type { SqlRuntimeExtensionDescriptor } from \"@prisma/orm-family-sql/runtime\";\nimport { ltreePackMeta, ltreeQueryOperations } from \"../core/descriptor-meta\";\nimport { ltreeHierarchyMethods } from \"../core/hierarchy-collection-methods\";\nimport { ltreeCodecRegistry } from \"../core/registry\";\n\nconst ltreeRuntimeDescriptor: SqlRuntimeExtensionDescriptor<\"postgres\"> = {\n kind: \"extension\" as const,\n id: ltreePackMeta.id,\n version: ltreePackMeta.version,\n dataTypes: ltreePackMeta.dataTypes,\n familyId: \"sql\" as const,\n targetId: \"postgres\" as const,\n types: {\n codecTypes: {\n codecDescriptors: Array.from(ltreeCodecRegistry.values()),\n },\n },\n codecs: () => Array.from(ltreeCodecRegistry.values()),\n queryOperations: () => ltreeQueryOperations(),\n collectionMethods: () => [ltreeHierarchyMethods],\n create() {\n return {\n familyId: \"sql\" as const,\n targetId: \"postgres\" as const,\n };\n },\n};\n\nexport type { LtreeHierarchyMethods } from \"../core/hierarchy-collection-methods\";\nexport { ltreeCodecRegistry };\nexport default ltreeRuntimeDescriptor;\n"],"mappings":";;;;;AA0DA,SAAS,QAAQ,OAAgB,OAA+B;CAC9D,MAAM,WAAW,UAGf,KAAK,EAAE;CACT,IAAI,aAAa,KAAA,GACf,MAAM,IAAI,cAAc,0CAA0C,MAAM,GAAG;CAE7E,OAAO;AACT;AAEA,SAAS,kBAAkB,OAAqC;CAC9D,QAAQ,YAAY,GAAG,SAAS;EAC9B,MAAM,CAAC,QAAQ,UAAkE,IAAI;EACrF,OAAO,WAAW,OAAO,UAAU,QAAQ,OAAO,KAAK,EAAE,eAAe,IAAI,CAAC;CAC/E;AACF;AAEA,SAAS,gBAAgB,OAAqC;CAC5D,QAAQ,YAAY,GAAG,SAAS;EAC9B,MAAM,CAAC,QAAQ,UAAkE,IAAI;EACrF,OAAO,WAAW,OAAO,UAAU,QAAQ,OAAO,KAAK,EAAE,aAAa,IAAI,CAAC;CAC7E;AACF;AAEA,SAAS,mBAAmB,OAAyB;CACnD,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,SAAS;CAIf,OACE,OAAO,SAAS,KAAA,KAChB,OAAO,MAAM,SAAS,YACtB,OAAO,KAAK,YAAA;AAEhB;;AAGA,MAAa,wBAAsD;CACjE,IAAI;CACJ,aAAa,UACX,OAAO,YACL,OAAO,QAAQ,MAAM,MAAM,EAAE,SAAS,CAAC,MAAM,WAC3C,mBAAmB,KAAK,IACpB,CACE,CAAC,GAAG,KAAK,eAAe,kBAAkB,IAAI,CAAC,GAC/C,CAAC,GAAG,KAAK,aAAa,gBAAgB,IAAI,CAAC,CAC7C,IACA,CAAC,CACP,CACF;AACJ;;;ACzGA,MAAM,yBAAoE;CACxE,MAAM;CACN,IAAI,cAAc;CAClB,SAAS,cAAc;CACvB,WAAW,cAAc;CACzB,UAAU;CACV,UAAU;CACV,OAAO,EACL,YAAY,EACV,kBAAkB,MAAM,KAAK,mBAAmB,OAAO,CAAC,EAC1D,EACF;CACA,cAAc,MAAM,KAAK,mBAAmB,OAAO,CAAC;CACpD,uBAAuB,qBAAqB;CAC5C,yBAAyB,CAAC,qBAAqB;CAC/C,SAAS;EACP,OAAO;GACL,UAAU;GACV,UAAU;EACZ;CACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prisma-ltree",
3
- "version": "0.5.0",
3
+ "version": "0.7.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.16",
32
- "@prisma/orm-framework": "8.0.0-rc.16",
33
- "@prisma/orm-toolchain": "8.0.0-rc.16",
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.6.3",
40
- "@prisma/orm-postgres": "8.0.0-rc.16",
41
- "@prisma/orm-target-postgres": "8.0.0-rc.16",
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.21",
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.16",
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
- Interval,
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<'5842622c2779cd02acd640ab4a5c8979fc94a2af8ed034222391fbd4f7cb3706'>;
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
- export type FieldOutputTypes = { readonly public: Record<string, never> };
251
- export type FieldInputTypes = { readonly public: Record<string, never> };
252
- export type StorageColumnTypes = { readonly public: {} };
253
- export type StorageColumnInputTypes = { readonly public: {} };
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": "5842622c2779cd02acd640ab4a5c8979fc94a2af8ed034222391fbd4f7cb3706",
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 { defineContract } from "@prisma/orm-postgres/contract-builder";
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 const contract = defineContract({}, () => ({
6
- types: {
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
+ }