@prisma/orm-sqlite 8.0.0-rc.17-dev.6 → 8.0.0-rc.17-dev.7
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/orm-sqlite",
|
|
3
|
-
"version": "8.0.0-rc.17-dev.
|
|
3
|
+
"version": "8.0.0-rc.17-dev.7",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -10,17 +10,17 @@
|
|
|
10
10
|
"skills"
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@prisma/orm-family-sql": "8.0.0-rc.17-dev.
|
|
14
|
-
"@prisma/orm-framework": "8.0.0-rc.17-dev.
|
|
15
|
-
"@prisma/orm-target-sqlite": "8.0.0-rc.17-dev.
|
|
16
|
-
"@prisma/orm-toolchain": "8.0.0-rc.17-dev.
|
|
13
|
+
"@prisma/orm-family-sql": "8.0.0-rc.17-dev.7",
|
|
14
|
+
"@prisma/orm-framework": "8.0.0-rc.17-dev.7",
|
|
15
|
+
"@prisma/orm-target-sqlite": "8.0.0-rc.17-dev.7",
|
|
16
|
+
"@prisma/orm-toolchain": "8.0.0-rc.17-dev.7",
|
|
17
17
|
"pathe": "^2.0.3",
|
|
18
18
|
"tinyglobby": "^0.2.17"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@internal/sqlite": "8.0.0-rc.17-dev.
|
|
22
|
-
"@repo/tsconfig": "8.0.0-rc.17-dev.
|
|
23
|
-
"@repo/tsdown": "8.0.0-rc.17-dev.
|
|
21
|
+
"@internal/sqlite": "8.0.0-rc.17-dev.7",
|
|
22
|
+
"@repo/tsconfig": "8.0.0-rc.17-dev.7",
|
|
23
|
+
"@repo/tsdown": "8.0.0-rc.17-dev.7",
|
|
24
24
|
"tsdown": "0.22.14",
|
|
25
25
|
"typescript": "5.9.3"
|
|
26
26
|
},
|
package/skills/prisma-8/SKILL.md
CHANGED
|
@@ -118,11 +118,11 @@ Then run `pnpm prisma contract emit` (or rely on the Vite plugin — see `refere
|
|
|
118
118
|
|
|
119
119
|
**Temporal columns.** On PostgreSQL, `Date`, `Timestamp(p)`, `Timestamptz(p)` and `Time(p)` read and write `Temporal` values (`Temporal.PlainDate`, `PlainDateTime`, `Instant`, `PlainTime`), never JavaScript `Date`. They need a global `Temporal` at query time: Node.js 26.8.2 and later ship `globalThis.Temporal`; 26.8.1 and earlier — including every 22 and 24 release — do not, and the first read or write of such a column throws `RUNTIME.TEMPORAL_UNAVAILABLE`. On those runtimes either `import 'temporal-polyfill/full/global'` before the first query (add `temporal-polyfill` as a dependency) or author the column as `DateString` / `TimestampString(p)` / `TimestamptzString(p)` / `TimeString(p)`, which carry PostgreSQL's own text and need no `Temporal`. `prisma contract emit`, `prisma db init` and the other commands need no global `Temporal`: the Postgres target loads `temporal-polyfill` as a fallback `Temporal` for the control plane, and sets no global. `temporal-polyfill` is a required peer dependency of `@prisma/orm-postgres`. npm, pnpm and bun install it automatically. With Yarn, add `temporal-polyfill` (`^1.0.4`) to the project's dependencies, or the commands fail because Node.js cannot find the package. That fallback is held once per process. An application that loads control-plane code in its own process, such as server code under `vite dev` with the Prisma Vite plugin or a script that calls the control client, decodes dates without its own `Temporal`, and then fails in production. An application that uses the Temporal codecs must load its own `Temporal`. A TypeScript contract file that constructs a `Temporal` value must load an implementation too.
|
|
120
120
|
|
|
121
|
-
`@@index` also accepts `expression:` (instead of a fields list), `where:` (partial-index predicate), `unique:`, `type:`/`options:` (target-registered access method), and `name:` xor `map
|
|
121
|
+
`@@index` also accepts `expression:` (instead of a fields list), `where:` (partial-index predicate), `unique:`, `type:`/`options:` (target-registered access method), and `name:` xor `map:`. Raw SQL in `expression:` and `where:` is a `sql` literal; a quoted string is refused with `PSL_VALUE_TYPE_INCOMPATIBLE`, whose message gives the rewrite:
|
|
122
122
|
|
|
123
123
|
```prisma
|
|
124
|
-
@@index(expression:
|
|
125
|
-
@@index([authorId], where:
|
|
124
|
+
@@index(expression: sql`lower(email)`, name: "users_email_lower")
|
|
125
|
+
@@index([authorId], where: sql`(archived_at IS NULL)`, name: "posts_author_active")
|
|
126
126
|
```
|
|
127
127
|
|
|
128
128
|
`name:` declares a wire-named index (physical name `<name>_<8-hex hash>`, renames plan as `ALTER INDEX … RENAME`); `map:` adopts an exact physical name verbatim (for infer-captured objects — combining it with a SQL body warns, because drift detection byte-compares the authored text against Postgres's reprint). An `expression:` requires `name:` or `map:`. The TS builder mirrors this via `constraints.index([cols.x], {...})` / `constraints.index({ expression, ... })` — see `packages/2-sql/2-authoring/contract-ts/README.md`.
|
|
@@ -132,7 +132,7 @@ Then run `pnpm prisma contract emit` (or rely on the Vite plugin — see `refere
|
|
|
132
132
|
```prisma
|
|
133
133
|
@@fullTextIndex([text], name: "message_text_search")
|
|
134
134
|
@@fullTextIndex([summary], language: "german", name: "message_summary_search_de")
|
|
135
|
-
@@fullTextIndex([text], where:
|
|
135
|
+
@@fullTextIndex([text], where: sql`archived_at IS NULL`, name: "message_text_search_live")
|
|
136
136
|
@@fullTextIndex([[title, subtitle], body], name: "post_search")
|
|
137
137
|
```
|
|
138
138
|
|
|
@@ -326,11 +326,11 @@ model Order {
|
|
|
326
326
|
total Decimal
|
|
327
327
|
|
|
328
328
|
// name: is a prefix — the physical constraint becomes order_total_positive_<8-hex hash>.
|
|
329
|
-
@@check(expression:
|
|
329
|
+
@@check(expression: sql`total > 0`, name: "order_total_positive")
|
|
330
330
|
}
|
|
331
331
|
```
|
|
332
332
|
|
|
333
|
-
`expression` is the raw predicate — the text that goes inside `CHECK (...)` — and it is never parsed, so get it right; Prisma 8 does not validate SQL syntax. Exactly one of `name:` or `map:` is required, and they're mutually exclusive:
|
|
333
|
+
`expression` is the raw predicate — the text that goes inside `CHECK (...)`, written as a `sql` literal (a quoted string is refused) — and it is never parsed, so get it right; Prisma 8 does not validate SQL syntax. Exactly one of `name:` or `map:` is required, and they're mutually exclusive:
|
|
334
334
|
|
|
335
335
|
- **`name:`** — declaring a new rule. Prisma 8 picks the physical constraint name and future plans compare by that name, so Postgres's own reprint of your predicate (which rarely matches what you typed byte-for-byte) never causes false drift.
|
|
336
336
|
- **`map:`** — adopting a rule that already exists. Give the constraint's exact physical name and Prisma 8 compares the predicate byte-for-byte against what's live. This is the form `contract infer` writes for you (see *Workflow — Brownfield introspection* below) when it finds a hand-written check in the database. Every `map:` body warns at emit time (`PN_EXACT_NAME_BODY_COMPARISON`) — the warning fires on the text, not on who wrote it, so the check `contract infer` just wrote warns again on your next `contract emit` too. That is expected, not a defect: the comparison is still sound because both sides are Postgres's own reprint. Prefer `name:` for anything you're authoring fresh: your text and Postgres's reprint of it rarely match character-for-character, and a byte comparison reports that as drift even when both mean exactly the same thing. Reserve `map:` for adopting what's already there, where both sides are the database's own reprint and so do match.
|
|
@@ -104,7 +104,7 @@ Without an index Postgres recomputes `to_tsvector` for every row, and it only us
|
|
|
104
104
|
|
|
105
105
|
```prisma
|
|
106
106
|
@@fullTextIndex([text], name: "message_text_search")
|
|
107
|
-
@@fullTextIndex([text], where:
|
|
107
|
+
@@fullTextIndex([text], where: sql`archived_at IS NULL`, name: "message_text_search_live")
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
Give the index and the operation the same `language`: a mismatch raises no error, the query silently falls back to a sequential scan.
|
|
@@ -69,14 +69,14 @@ namespace public {
|
|
|
69
69
|
policy_select profile_owner_read {
|
|
70
70
|
target = Profile
|
|
71
71
|
roles = [authenticated]
|
|
72
|
-
using = "
|
|
72
|
+
using = sql`"userId"::uuid = auth.uid()`
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
// anon may read every profile (a public directory listing).
|
|
76
76
|
policy_select profile_public_read {
|
|
77
77
|
target = Profile
|
|
78
78
|
roles = [anon]
|
|
79
|
-
using =
|
|
79
|
+
using = sql`true`
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// authenticated may update only their own profile, and may not
|
|
@@ -84,8 +84,8 @@ namespace public {
|
|
|
84
84
|
policy_update profile_owner_write {
|
|
85
85
|
target = Profile
|
|
86
86
|
roles = [authenticated]
|
|
87
|
-
using = "
|
|
88
|
-
withCheck = "
|
|
87
|
+
using = sql`"userId"::uuid = auth.uid()`
|
|
88
|
+
withCheck = sql`"userId"::uuid = auth.uid()`
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
```
|
|
@@ -94,9 +94,9 @@ The `Uuid` constructor selects native UUID storage in type position. The legacy
|
|
|
94
94
|
|
|
95
95
|
The pieces:
|
|
96
96
|
|
|
97
|
-
- **Per-operation policy blocks**: `policy_select`, `policy_insert`, `policy_update`, `policy_delete`, `policy_all`. Body is `key = value`: `target` (a model in this namespace), `roles` (resolve against the composed contract — the pack supplies `anon` / `authenticated` / `service_role`), `using`, and (for write operations) `withCheck`. Multiple permissive policies per `(target, operation)` are valid — Postgres ORs them. A block may also carry `@@map("physical name")` to adopt an existing live policy under its exact name (no wire-name hash; drift detection then byte-compares the body against Postgres's reprint, so keep the text as captured — hand-authoring it warns).
|
|
97
|
+
- **Per-operation policy blocks**: `policy_select`, `policy_insert`, `policy_update`, `policy_delete`, `policy_all`. Body is `key = value`: `target` (a model in this namespace), `roles` (resolve against the composed contract — the pack supplies `anon` / `authenticated` / `service_role`), `using`, and (for write operations) `withCheck`. `using` and `withCheck` are `sql` literals, as in `` using = sql`"userId"::uuid = auth.uid()` ``; a quoted string is refused, and the error message gives the rewrite. Multiple permissive policies per `(target, operation)` are valid — Postgres ORs them. A block may also carry `@@map("physical name")` to adopt an existing live policy under its exact name (no wire-name hash; drift detection then byte-compares the body against Postgres's reprint, so keep the text as captured — hand-authoring it warns).
|
|
98
98
|
- **`@@rls` is required on policy targets.** A `policy_*` block whose target model lacks `@@rls` fails emit with `PSL_EXTENSION_TARGET_MODEL_MISSING_ATTRIBUTE`. A model with `@@rls` and *no* policies is also meaningful: RLS enabled, deny-all.
|
|
99
|
-
- **Predicates are verbatim SQL
|
|
99
|
+
- **Predicates are `sql` literals holding verbatim SQL.** Quote camelCase column names inside them with ordinary double quotes (`"userId"`; inside a backtick `sql` literal the only escapes are `` \` `` and `\\`), and cast where needed — `auth.uid()` returns `uuid`. Renames in your contract do not rewrite predicate bodies.
|
|
100
100
|
- **TS-builder parity exists.** `@internal/postgres/contract-builder` exports `policySelect` / `policyInsert` / `policyUpdate` / `policyDelete` / `policyAll`, `rlsEnabled(Model)`, and `role('anon')` — mirroring the PSL lowering key-for-key (identical emitted wire names). PSL is the canonical path shown here.
|
|
101
101
|
|
|
102
102
|
Emit + migrate as usual (`prisma contract emit`, then `references/migrations.md`). The plan creates your table, its FK, `ENABLE ROW LEVEL SECURITY`, and the `CREATE POLICY` statements — and **no DDL for `auth.*`**.
|