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.
- package/README.md +41 -8
- package/dist/{codec-types-BJE-5cwk.d.mts → codec-types-B0DtEnU6.d.mts} +16 -13
- package/dist/codec-types-B0DtEnU6.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-DwbFei9y.mjs} +341 -34
- package/dist/descriptor-meta-DwbFei9y.mjs.map +1 -0
- package/dist/{operation-types-8su4lbK-.d.mts → operation-types-DD-KyBms.d.mts} +46 -1
- package/dist/{operation-types-8su4lbK-.d.mts.map → operation-types-DD-KyBms.d.mts.map} +1 -1
- package/dist/operation-types.d.mts +1 -1
- package/dist/pack.d.mts +1 -1
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/runtime.d.mts +35 -1
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +34 -1
- package/dist/runtime.mjs.map +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/core/descriptor-meta.ts +64 -4
- package/src/core/hierarchy-collection-methods.ts +111 -0
- package/src/core/pattern-validation.ts +313 -0
- package/src/exports/control.ts +36 -1
- package/src/exports/runtime.ts +3 -0
- package/src/types/operation-types.ts +37 -0
- package/dist/codec-types-BJE-5cwk.d.mts.map +0 -1
- package/dist/descriptor-meta-2In8FI1I.mjs.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as QueryOperationTypes } from "./operation-types-
|
|
1
|
+
import { t as QueryOperationTypes } from "./operation-types-DD-KyBms.mjs";
|
|
2
2
|
export type { QueryOperationTypes };
|
package/dist/pack.d.mts
CHANGED
package/dist/pack.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack.d.mts","names":[],"sources":["../src/core/descriptor-meta.ts"],"mappings":";;
|
|
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-
|
|
1
|
+
import { t as ltreePackMeta } from "./descriptor-meta-DwbFei9y.mjs";
|
|
2
2
|
export { ltreePackMeta as default };
|
package/dist/runtime.d.mts
CHANGED
|
@@ -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
|
package/dist/runtime.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/core/registry.ts","../src/exports/runtime.ts"],"mappings":"
|
|
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
|
|
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",
|
package/dist/runtime.mjs.map
CHANGED
|
@@ -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":";;
|
|
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.
|
|
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.
|
|
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
|
+
}
|