@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.6",
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.6",
14
- "@prisma/orm-framework": "8.0.0-rc.17-dev.6",
15
- "@prisma/orm-target-sqlite": "8.0.0-rc.17-dev.6",
16
- "@prisma/orm-toolchain": "8.0.0-rc.17-dev.6",
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.6",
22
- "@repo/tsconfig": "8.0.0-rc.17-dev.6",
23
- "@repo/tsdown": "8.0.0-rc.17-dev.6",
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
  },
@@ -15,7 +15,7 @@ description: >-
15
15
  ORM 7 or earlier (schema.prisma + @prisma/client).
16
16
  metadata:
17
17
  library: '@prisma/orm-sqlite'
18
- library_version: '8.0.0-rc.17-dev.6'
18
+ library_version: '8.0.0-rc.17-dev.7'
19
19
  version: '2026-09-12'
20
20
  ---
21
21
 
@@ -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: "lower(email)", name: "users_email_lower")
125
- @@index([authorId], where: "(archived_at IS NULL)", name: "posts_author_active")
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: "archived_at IS NULL", name: "message_text_search_live")
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: "total > 0", name: "order_total_positive")
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: "archived_at IS NULL", name: "message_text_search_live")
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 = "\"userId\"::uuid = auth.uid()"
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 = "true"
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 = "\"userId\"::uuid = auth.uid()"
88
- withCheck = "\"userId\"::uuid = auth.uid()"
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 strings.** Quote camelCase column names inside them (`\"userId\"`), and cast where needed — `auth.uid()` returns `uuid`. Renames in your contract do not rewrite predicate bodies.
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.*`**.