prisma-ltree 0.1.0 → 0.2.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 (2) hide show
  1. package/README.md +73 -59
  2. package/package.json +14 -15
package/README.md CHANGED
@@ -8,25 +8,19 @@ them with type-safe, prisma-native operators — ancestor/descendant checks, `lq
8
8
  pattern matching, path manipulation, and lowest-common-ancestor computation — without dropping to
9
9
  raw SQL.
10
10
 
11
- ## Overview
12
-
13
- This extension pack provides:
14
-
15
- - **`pg/ltree@1` codec** — `string ↔ string` with label-syntax + length validation (traits
16
- `['equality', 'order']`).
17
- - **`pg/ltree-array@1` codec** — `string[] ↔ string[]` with per-element validation, for the
18
- `ltree[]` first-match operators (see [ADR-003](../../docs/decisions/ADR-003-array-receiver.md)).
19
- - **`ltree()` / `ltreeArray()` column helpers** — non-parameterized columns with `nativeType`
20
- `'ltree'` / `'ltree[]'`.
21
- - **Query operators** — hierarchy, pattern-match, scalar functions, concatenation, conversion, and
22
- array first-match operators (full list under [Operations](#operations)).
11
+ ## Features
12
+
13
+ - **`ltree` and `ltree[]` columns** — `ltree()` / `ltreeArray()` column helpers
14
+ - **Hierarchy operators** — ancestor and descendant checks
15
+ - **Pattern matching** — `lquery`, `lquery[]`, and `ltxtquery`
16
+ - **Scalar functions** — depth, subpaths, label index, lowest common ancestor
17
+ - **Concatenation & conversion** — path building and `ltree` ↔ `text` conversion
18
+ - **Array first-match** — find the first matching path in an `ltree[]` column
23
19
  - **Baseline migration** — installs the Postgres extension via
24
- `CREATE EXTENSION IF NOT EXISTS ltree` (invariantId `ltree:install-ltree-v1`).
25
- - **Multi-plane entrypoints** — `/control`, `/runtime`, `/column-types`, `/codec-types`,
26
- `/operation-types`, `/pack`.
20
+ `CREATE EXTENSION IF NOT EXISTS ltree` when the pack is composed
27
21
 
28
- The single source of truth for what is supported, planned, or out-of-scope is
29
- [`docs/feature-support.md`](../../docs/feature-support.md).
22
+ See the [feature support matrix](https://github.com/slovakian/prisma-ltree/blob/main/docs/feature-support.md)
23
+ for what is supported, planned, or out of scope.
30
24
 
31
25
  ## Installation
32
26
 
@@ -34,9 +28,19 @@ The single source of truth for what is supported, planned, or out-of-scope is
34
28
  pnpm add prisma-ltree
35
29
  ```
36
30
 
37
- Requires Node `>=24` and `@prisma-next/*@0.14.0`.
31
+ Requires Node `>=24` and `@prisma-next/*@0.14.0` (exact pin — see
32
+ [versioning & compatibility](https://github.com/slovakian/prisma-ltree/blob/main/docs/prisma-next/versioning-and-compatibility.md)).
38
33
 
39
- ## Database Setup
34
+ ### Agent skills (optional)
35
+
36
+ Agent skills for adoption and query patterns ship in the repo under
37
+ [`skills/`](https://github.com/slovakian/prisma-ltree/tree/main/skills):
38
+
39
+ ```bash
40
+ pnpm dlx skills add slovakian/prisma-ltree --all
41
+ ```
42
+
43
+ ## Database setup
40
44
 
41
45
  The extension ships an on-disk baseline migration that installs `ltree` when the pack is composed
42
46
  into an application. `prisma-next db init` / `db update` apply it automatically. The equivalent
@@ -67,7 +71,35 @@ export default defineConfig({
67
71
 
68
72
  ## Usage
69
73
 
70
- ### Contract Definition
74
+ ### Contract definition
75
+
76
+ Author ltree columns in either lane — `contract.prisma` (PSL) or `contract.ts`
77
+ (TypeScript). Both emit a byte-identical compiled contract.
78
+
79
+ **PSL lane** — reference the `ltree` namespace constructors (parens required) and compose
80
+ `ltree` into `extensions` in `prisma-next.config.ts`:
81
+
82
+ ```prisma
83
+ // contract.prisma — use prisma-next
84
+
85
+ types {
86
+ Path = ltree.Ltree() // → pg/ltree@1 / ltree
87
+ Paths = ltree.LtreeArray() // → pg/ltree-array@1 / ltree[]
88
+ }
89
+
90
+ model Page {
91
+ id String @id @default(uuid())
92
+ path Path
93
+ breadcrumbs Paths
94
+
95
+ @@map("page")
96
+ }
97
+ ```
98
+
99
+ `@db.Ltree` is not available — `@db.*` is a closed core table with no extension hook; the
100
+ namespace constructor is the sanctioned surface (the same one pgvector and postgis use).
101
+
102
+ **TypeScript lane**:
71
103
 
72
104
  ```typescript
73
105
  import { int4Column, textColumn } from "@prisma-next/adapter-postgres/column-types";
@@ -93,7 +125,7 @@ export const contract = defineContract({
93
125
  });
94
126
  ```
95
127
 
96
- ### Runtime Setup
128
+ ### Runtime setup
97
129
 
98
130
  ```typescript
99
131
  import { instantiateExecutionStack } from "@prisma-next/framework-components/execution";
@@ -111,7 +143,7 @@ const context = createExecutionContext({ contract, stack });
111
143
  const stackInstance = instantiateExecutionStack(stack);
112
144
  ```
113
145
 
114
- ### Query Usage
146
+ ### Query usage
115
147
 
116
148
  ```typescript
117
149
  import { sql, tables } from "../prisma/query";
@@ -130,9 +162,6 @@ const plan = sql
130
162
 
131
163
  ## Operations
132
164
 
133
- All boolean operators return `pg/bool@1`. See
134
- [`docs/feature-support.md`](../../docs/feature-support.md) for the authoritative matrix.
135
-
136
165
  ### Hierarchy (→ boolean)
137
166
 
138
167
  | Method | SQL |
@@ -150,30 +179,28 @@ All boolean operators return `pg/bool@1`. See
150
179
 
151
180
  ### Scalar functions
152
181
 
153
- | Method | SQL | Returns |
154
- | ---------------------------- | ----------------------------- | ------------ |
155
- | `path.nlevel()` | `nlevel(ltree)` | `pg/int4@1` |
156
- | `path.subltree(start, end)` | `subltree(ltree, start, end)` | `pg/ltree@1` |
157
- | `path.subpath(offset, len?)` | `subpath(ltree, offset, len)` | `pg/ltree@1` |
158
- | `path.indexOf(other, off?)` | `index(ltree, ltree, off)` | `pg/int4@1` |
159
- | `path.lca(other, ...rest)` | `lca(ltree, ltree, ...)` | `pg/ltree@1` |
182
+ | Method | SQL | Returns |
183
+ | ---------------------------- | ----------------------------- | ------- |
184
+ | `path.nlevel()` | `nlevel(ltree)` | `int` |
185
+ | `path.subltree(start, end)` | `subltree(ltree, start, end)` | `ltree` |
186
+ | `path.subpath(offset, len?)` | `subpath(ltree, offset, len)` | `ltree` |
187
+ | `path.indexOf(other, off?)` | `index(ltree, ltree, off)` | `int` |
188
+ | `path.lca(other, ...rest)` | `lca(ltree, ltree, ...)` | `ltree` |
160
189
 
161
- `lca` is a variadic method requiring **≥2 paths** and returns the proper (strictly shorter) lowest
162
- common ancestor (see [ADR-001](../../docs/decisions/ADR-001-lca-api-shape.md)).
190
+ `lca` requires **≥2 paths** and returns the proper (strictly shorter) lowest common ancestor.
163
191
 
164
192
  ### Concatenation (→ ltree) & conversion
165
193
 
166
- | Method | SQL | Returns |
167
- | ------------------------- | ------------------- | ------------ |
168
- | `path.concat(rhs)` | `ltree \|\| ltree` | `pg/ltree@1` |
169
- | `path.concatText(label)` | `ltree \|\| text` | `pg/ltree@1` |
170
- | `path.prependText(label)` | `text \|\| ltree` | `pg/ltree@1` |
171
- | `path.toText()` | `ltree2text(ltree)` | `pg/text@1` |
172
- | `text.toLtree()` | `text2ltree(text)` | `pg/ltree@1` |
194
+ | Method | SQL | Returns |
195
+ | ------------------------- | ------------------- | ------- |
196
+ | `path.concat(rhs)` | `ltree \|\| ltree` | `ltree` |
197
+ | `path.concatText(label)` | `ltree \|\| text` | `ltree` |
198
+ | `path.prependText(label)` | `text \|\| ltree` | `ltree` |
199
+ | `path.toText()` | `ltree2text(ltree)` | `text` |
200
+ | `text.toLtree()` | `text2ltree(text)` | `ltree` |
173
201
 
174
- `prependText` keeps the ltree column as the receiver even though it is the right operand, and
175
- `toLtree` is rooted on a text column (see
176
- [ADR-002](../../docs/decisions/ADR-002-free-function-lowering.md)).
202
+ `prependText` keeps the ltree column as the receiver even though it is the right SQL operand.
203
+ `toLtree` is called on a text column.
177
204
 
178
205
  ### Array first-match (→ ltree, receiver `ltree[]`)
179
206
 
@@ -184,6 +211,8 @@ common ancestor (see [ADR-001](../../docs/decisions/ADR-001-lca-api-shape.md)).
184
211
  | `paths.firstMatchLquery(pattern)` | `ltree[] ?~ lquery` |
185
212
  | `paths.firstMatchLtxtquery(query)` | `ltree[] ?@ ltxtquery` |
186
213
 
214
+ Use `ltreeArray()` for `ltree[]` columns that expose these methods.
215
+
187
216
  ## Types
188
217
 
189
218
  ```typescript
@@ -194,21 +223,6 @@ import type { QueryOperationTypes } from "prisma-ltree/operation-types";
194
223
  // CodecTypes['pg/ltree-array@1']['output'] = readonly string[]
195
224
  ```
196
225
 
197
- ## Development
198
-
199
- This package is built with [Vite+](https://viteplus.dev/):
200
-
201
- ```bash
202
- vp install # install dependencies
203
- vp check # format, lint, typecheck
204
- vp test # run unit + integration + type-level tests
205
- vp test --coverage # enforce the 95% coverage threshold
206
- vp run build # build dist/
207
- ```
208
-
209
- Integration tests run against [PGlite](https://pglite.dev/) with the `ltree` contrib extension —
210
- every operator is lowered through a composed Postgres runtime adapter and executed for real.
211
-
212
226
  ## License
213
227
 
214
228
  Apache-2.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prisma-ltree",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Prisma Next extension pack for PostgreSQL's ltree hierarchical tree data type.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -26,15 +26,6 @@
26
26
  "publishConfig": {
27
27
  "access": "public"
28
28
  },
29
- "scripts": {
30
- "build": "vp pack",
31
- "dev": "vp pack --watch",
32
- "test": "vp test",
33
- "check": "vp check",
34
- "build:contract-space": "prisma-next contract emit",
35
- "check-pins": "prisma-next-check-pins",
36
- "prepublishOnly": "vp run build"
37
- },
38
29
  "dependencies": {
39
30
  "@prisma-next/contract": "0.14.0",
40
31
  "@prisma-next/contract-authoring": "0.14.0",
@@ -50,7 +41,7 @@
50
41
  "arktype": "^2.2.0"
51
42
  },
52
43
  "devDependencies": {
53
- "@electric-sql/pglite": "catalog:",
44
+ "@electric-sql/pglite": "^0.5.3",
54
45
  "@prisma-next/adapter-postgres": "0.14.0",
55
46
  "@prisma-next/cli": "0.14.0",
56
47
  "@prisma-next/extension-author-tools": "0.14.0",
@@ -58,11 +49,11 @@
58
49
  "@prisma-next/postgres": "0.14.0",
59
50
  "@prisma-next/sql-contract-ts": "0.14.0",
60
51
  "@prisma-next/target-postgres": "0.14.0",
61
- "@types/node": "catalog:",
52
+ "@types/node": "^24",
62
53
  "@typescript/native-preview": "7.0.0-dev.20260509.2",
63
54
  "@vitest/coverage-v8": "4.1.8",
64
- "typescript": "catalog:",
65
- "vite-plus": "catalog:"
55
+ "typescript": "^5",
56
+ "vite-plus": "0.1.24"
66
57
  },
67
58
  "peerDependencies": {
68
59
  "@prisma-next/adapter-postgres": "0.14.0",
@@ -85,5 +76,13 @@
85
76
  "postgres"
86
77
  ],
87
78
  "type": "extension-pack"
79
+ },
80
+ "scripts": {
81
+ "build": "vp pack",
82
+ "dev": "vp pack --watch",
83
+ "test": "vp test",
84
+ "check": "vp check",
85
+ "build:contract-space": "prisma-next contract emit",
86
+ "check-pins": "prisma-next-check-pins"
88
87
  }
89
- }
88
+ }