@prisma/orm-mongo 8.0.0-rc.14-dev.8 → 8.0.0-rc.14-dev.10

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-mongo",
3
- "version": "8.0.0-rc.14-dev.8",
3
+ "version": "8.0.0-rc.14-dev.10",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -10,18 +10,18 @@
10
10
  "skills"
11
11
  ],
12
12
  "dependencies": {
13
- "@prisma/orm-family-mongo": "8.0.0-rc.14-dev.8",
14
- "@prisma/orm-framework": "8.0.0-rc.14-dev.8",
15
- "@prisma/orm-target-mongo": "8.0.0-rc.14-dev.8",
16
- "@prisma/orm-toolchain": "8.0.0-rc.14-dev.8",
13
+ "@prisma/orm-family-mongo": "8.0.0-rc.14-dev.10",
14
+ "@prisma/orm-framework": "8.0.0-rc.14-dev.10",
15
+ "@prisma/orm-target-mongo": "8.0.0-rc.14-dev.10",
16
+ "@prisma/orm-toolchain": "8.0.0-rc.14-dev.10",
17
17
  "mongodb-connection-string-url": "^7.0.1",
18
18
  "pathe": "^2.0.3",
19
19
  "tinyglobby": "^0.2.17"
20
20
  },
21
21
  "devDependencies": {
22
- "@internal/mongo": "8.0.0-rc.14-dev.8",
23
- "@repo/tsconfig": "8.0.0-rc.14-dev.8",
24
- "@repo/tsdown": "8.0.0-rc.14-dev.8",
22
+ "@internal/mongo": "8.0.0-rc.14-dev.10",
23
+ "@repo/tsconfig": "8.0.0-rc.14-dev.10",
24
+ "@repo/tsdown": "8.0.0-rc.14-dev.10",
25
25
  "tsdown": "0.22.14",
26
26
  "typescript": "5.9.3"
27
27
  },
@@ -15,7 +15,7 @@ description: >-
15
15
  ORM 7 or earlier (schema.prisma + @prisma/client).
16
16
  metadata:
17
17
  library: '@prisma/orm-mongo'
18
- library_version: '8.0.0-rc.14-dev.8'
18
+ library_version: '8.0.0-rc.14-dev.10'
19
19
  version: '2026-09-12'
20
20
  ---
21
21
 
@@ -359,7 +359,7 @@ On Postgres the operations are **methods on the `Migration` base class**, each t
359
359
  **Postgres** operations (representative set, all `this.<name>({...})`):
360
360
 
361
361
  - Tables: `createTable`, `dropTable`.
362
- - Columns: `addColumn` (`column: col(name, nativeType, { codecRef })`), `dropColumn`, `alterColumnType`, `setNotNull`, `dropNotNull`, `setDefault`, `dropDefault`.
362
+ - Columns: `addColumn` (`column: col(name, nativeType, { codecRef })`), `dropColumn`, `alterColumnType`, `setNotNull`, `dropNotNull`, `setDefault` (`column: col(name, nativeType, { default: lit(value) or fn(expression), codecRef })`), `dropDefault`.
363
363
  - Constraints: `addPrimaryKey`, `addForeignKey`, `addUnique`, `addCheckConstraint`, `renameCheckConstraint`, `dropCheckConstraint`, `dropConstraint`.
364
364
  - Indexes: `createIndex`, `renameIndex`, `dropIndex`.
365
365
  - Enums: `createNativeEnumType`, `addNativeEnumValue`, `dropNativeEnumType`.
@@ -236,29 +236,43 @@ For the full option surface, read the source: `packages/2-sql/5-runtime/src/midd
236
236
 
237
237
  ## Workflow — Cache middleware
238
238
 
239
- The concept: `@prisma/orm-extension-middleware-cache` ships an opt-in read cache built on the `interceptQuery` hook. On a hit the driver is never called; on a miss the rows are buffered and committed to the store when the query completes. Caching is strictly opt-in per query: only a plan annotated with `cacheAnnotation({ ttl })` is ever cached. Cache keys default to the runtime's content hash of the plan (`key` overrides), queries inside a transaction or pinned connection bypass the cache, and the default store is an in-memory LRU with TTL (`CacheStore` is the interface for a Redis-style backend).
239
+ The concept: `@prisma/orm-extension-middleware-cache` ships an opt-in read cache built on the `interceptQuery` hook. On a hit the driver is never called; on a miss the rows are buffered and stored when the query completes. Only a plan carrying `cacheAnnotation` is cached; `cacheAnnotation({ bypass: true })` skips the cache for one call. Cache keys default to the runtime's content hash of the plan (`key` overrides), and queries inside a transaction or pinned connection bypass the cache. How long an entry lives is the store's policy: the default store keeps up to 1000 entries for 60 seconds each, and `createInMemoryCacheStore({ maxEntries, ttlMs })` changes that (`ttlMs: Infinity` never expires). `CacheStore` is the interface for a Redis-style backend. The cache never sees writes: after the write commits, call `cache.invalidate({ keys })` for reads annotated with a `key`. `cacheAnnotation({ meta })` hands any value to the store with the entry, and `cache.invalidate({ meta })` hands one to its `unset`; only a custom store that indexes `meta` can act on it, and the default store throws `RUNTIME.CACHE_STORE_META_UNSUPPORTED`.
240
240
 
241
241
  ```typescript
242
- import { cacheAnnotation, createCacheMiddleware } from '@prisma/orm-extension-middleware-cache';
243
-
242
+ import {
243
+ cacheAnnotation,
244
+ createCacheMiddleware,
245
+ createInMemoryCacheStore,
246
+ } from '@prisma/orm-extension-middleware-cache';
247
+
248
+ export const cache = createCacheMiddleware({
249
+ store: createInMemoryCacheStore({ maxEntries: 1_000, ttlMs: 60_000 }),
250
+ });
244
251
  export const db = postgres<Contract>({
245
252
  contractJson,
246
253
  url: process.env['DATABASE_URL']!,
247
- middleware: [createCacheMiddleware({ maxEntries: 1_000 }), lints(), budgets({ maxRows: 10_000 })],
254
+ middleware: [cache, lints(), budgets({ maxRows: 10_000 })],
248
255
  });
249
256
 
250
- // Cached for 60s; an identical plan within the TTL is served without a driver call.
251
- const user = await db.orm.public.User.first({ id: 1 }, (meta) => meta.annotate(cacheAnnotation({ ttl: 60_000 })));
257
+ // Cached for the store's 60 s; an identical read in that window is served without a driver call.
258
+ const user = await db.orm.public.User.first({ id: 1 }, (meta) =>
259
+ meta.annotate(cacheAnnotation({ key: 'user-1' })),
260
+ );
252
261
  // Un-annotated queries always hit the database.
262
+
263
+ // After a write to user 1 has committed (outside the transaction, never inside it):
264
+ await cache.invalidate({ keys: ['user-1'] });
253
265
  ```
254
266
 
255
- **The cache key carries no identity.** The default key is the runtime's content hash of the plan — contract hash, SQL text, and bound parameters — so two callers issuing the same statement share one entry regardless of who they are. Never annotate a read whose rows depend on the caller (per-user, per-tenant, or RLS-filtered data) on the plain `postgres()` façade unless the identity is part of the key: `cacheAnnotation({ ttl, key: `user:${userId}:profile` })`, or a `where` clause that binds the identity as a parameter (the parameter is in the hash). Queries that run on a pinned connection or inside a transaction bypass the cache entirely (`ctx.scope !== 'runtime'`), which is why a Supabase `RoleBoundDb` read — executed on a connection with the role bound via `set_config` — is never served from cache; the plain façade has no such protection.
267
+ **Invalidate after the commit, not inside the transaction.** A read from another request can refill the cache with the old rows before the commit lands. A read that missed before the `invalidate` and finishes after it does not store its rows: the store moves the key's version on `unset`, and the read's `set` is conditional on the version it saw. This holds across processes that share a store.
268
+
269
+ **The cache key carries no identity.** The default key is the runtime's content hash of the plan — contract hash, SQL text, and bound parameters — so two callers issuing the same statement share one entry regardless of who they are. Never annotate a read whose rows depend on the caller (per-user, per-tenant, or RLS-filtered data) on the plain `postgres()` façade unless the identity is part of the key: `cacheAnnotation({ key: `user:${userId}:profile` })`, or a `where` clause that binds the identity as a parameter (the parameter is in the hash). Queries that run on a pinned connection or inside a transaction bypass the cache entirely (`ctx.scope !== 'runtime'`), which is why a Supabase `RoleBoundDb` read — executed on a connection with the role bound via `set_config` — is never served from cache; the plain façade has no such protection.
256
270
 
257
271
  ## Workflow — Compose multiple middleware
258
272
 
259
273
  ```typescript
260
274
  middleware: [
261
- createCacheMiddleware({ maxEntries: 1_000 }), // first — gets first claim on an interceptQuery hit
275
+ createCacheMiddleware(), // first — gets first claim on an interceptQuery hit
262
276
  lints({ severities: { noLimit: 'error' } }),
263
277
  budgets({ maxLatencyMs: 5_000 }),
264
278
  slowQueryWarning({ thresholdMs: 250 }), // afterQuery fires for cache hits too (source: 'middleware')