@prisma-idb/client-idb 0.0.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.
@@ -1,7 +1,8 @@
1
1
  import { AsyncIterableResult } from "@prisma/orm-framework/components/runtime";
2
2
  import { IdbFieldFilter, IdbFilterExpr, IdbNullCheckExpr, IdbQueryPlan } from "@prisma-idb/adapter-idb/runtime";
3
3
  import { Contract, ContractModelBase, ContractReferenceRelation } from "@prisma/orm-framework/contract/types";
4
- import { ExtractIdbFieldInputTypes, ExtractIdbFieldOutputTypes, IdbStorage } from "@prisma-idb/target-idb/pack";
4
+ import { keyEquals, keyToken } from "@prisma-idb/target-idb/runtime";
5
+ import { ExtractIdbFieldInputTypes, ExtractIdbFieldOutputTypes, IdbKeyPath, IdbStorage } from "@prisma-idb/target-idb/pack";
5
6
  //#region src/core/types.d.ts
6
7
  /**
7
8
  * Extract the model map from a contract by traversing the domain namespace.
@@ -56,33 +57,87 @@ type DefaultModelRow<TContract, ModelName extends string> = ResolvedOutputRow<TC
56
57
  */
57
58
  type WhereFilter<TContract, ModelName extends string> = { readonly [K in keyof DefaultModelRow<TContract, ModelName>]?: DefaultModelRow<TContract, ModelName>[K]; };
58
59
  /**
59
- * The literal `keyPath` string for a model, extracted from
60
- * `contract.models[ModelName].storage.keyPath`.
60
+ * The union of a model's `keyPath` field name(s), extracted from
61
+ * `contract.models[ModelName].storage.keyPath`. For a single-field key this
62
+ * is just that field name; for a compound key it's the union of every member
63
+ * field name (NOT an ordered tuple — see {@link ModelKeyPathOrdered} for the
64
+ * order-preserving form `KeyType` needs).
61
65
  *
62
- * Used at the type level to exclude the key field from `CreateInput` and to
63
- * narrow the `findUnique` / `delete` key parameter type.
66
+ * A plain union is what `Omit`/`Pick` need, where order doesn't matter.
64
67
  */
65
68
  type ModelKeyPath<TContract, ModelName extends string> = ModelName extends keyof ModelsOf<TContract> ? ModelsOf<TContract>[ModelName] extends {
66
69
  storage: {
67
70
  keyPath: infer P;
68
71
  };
69
- } ? P extends string ? P : never : never : never;
72
+ } ? P extends string ? P : P extends readonly string[] ? P[number] : never : never : never;
70
73
  /**
71
- * TypeScript type of the primary key field for a given model.
72
- *
73
- * When the output row type has a field matching `ModelKeyPath`, that field's
74
- * type is used. Otherwise falls back to `IDBValidKey` (the DOM union of valid
75
- * IDB key types).
74
+ * Like {@link ModelKeyPath}, but preserves declaration order as a tuple
75
+ * (`readonly ["a", "b"]`, not the unioned `"a" | "b"`). A single-field key is
76
+ * normalized to a 1-tuple (`readonly ["id"]`) so `KeyType` below can branch
77
+ * on tuple shape uniformly. Needed because `findUnique`/`delete` accept the
78
+ * key as a positional array for compound-key models (mirroring the
79
+ * `IDBValidKey` array form IDB itself expects — see ADR-tracked decision in
80
+ * Phase 9.1), which requires order, unlike `ModelKeyPath`'s Omit/Pick usage.
76
81
  */
77
- type KeyType<TContract, ModelName extends string> = ModelKeyPath<TContract, ModelName> extends keyof ResolvedOutputRow<TContract, ModelName> ? ResolvedOutputRow<TContract, ModelName>[ModelKeyPath<TContract, ModelName>] : IDBValidKey;
78
- /** The keyPath field when it exists in the resolved input row (may be absent for models with no typed maps). */
79
- type KeyPathField<TContract, ModelName extends string> = ModelKeyPath<TContract, ModelName> & keyof ResolvedInputRow<TContract, ModelName>;
82
+ type ModelKeyPathOrdered<TContract, ModelName extends string> = ModelName extends keyof ModelsOf<TContract> ? ModelsOf<TContract>[ModelName] extends {
83
+ storage: {
84
+ keyPath: infer P;
85
+ };
86
+ } ? P extends string ? readonly [P] : P extends readonly string[] ? P : never : never : never;
87
+ /** Maps an ordered tuple of key field names to their resolved output types, preserving position. */
88
+ type KeyTupleType<TContract, ModelName extends string, Fields extends readonly string[]> = { [I in keyof Fields]: Fields[I] extends keyof ResolvedOutputRow<TContract, ModelName> ? ResolvedOutputRow<TContract, ModelName>[Fields[I] & keyof ResolvedOutputRow<TContract, ModelName>] : IDBValidKey; };
89
+ /**
90
+ * `true` only when `T` is exactly `never` — the tuple-wrap defeats
91
+ * conditional-type distributivity (without it, `never extends never ? A : B`
92
+ * called with a naked, union-distributing `T` short-circuits to `never`
93
+ * itself rather than evaluating `A`/`B`). Needed because `never` is also a
94
+ * structural subtype of every other concrete type (including a 2+-element
95
+ * tuple type), so a plain `ModelKeyPathOrdered<...> extends readonly
96
+ * [string, string, ...string[]]` check would incorrectly match `never`
97
+ * (the loosely-typed/no-type-maps contract case) as if it were a real
98
+ * compound key.
99
+ */
100
+ type IsNever<T> = [T] extends [never] ? true : false;
101
+ /**
102
+ * TypeScript type of the primary key parameter for `findUnique()`/`delete()`.
103
+ *
104
+ * Single-field-key models keep today's scalar shape (e.g. `string`) — no
105
+ * change for the common case, and untyped/loosely-typed contracts (no
106
+ * emitted type maps — `ModelKeyPathOrdered` resolves to `never`) fall
107
+ * through to the exact same `IDBValidKey` fallback `KeyType` always used
108
+ * before compound keys existed. Compound-key models get an ordered tuple
109
+ * type (e.g. `[string, Date]` for `@@id([orgId, effectiveFrom])`), matching
110
+ * the `IDBValidKey` array IDB itself expects for a compound key-get — the
111
+ * same value passes straight through to the driver with zero runtime
112
+ * conversion.
113
+ */
114
+ type KeyType<TContract, ModelName extends string> = IsNever<ModelKeyPathOrdered<TContract, ModelName>> extends true ? ModelKeyPath<TContract, ModelName> extends keyof ResolvedOutputRow<TContract, ModelName> ? ResolvedOutputRow<TContract, ModelName>[ModelKeyPath<TContract, ModelName>] : IDBValidKey : ModelKeyPathOrdered<TContract, ModelName> extends readonly [infer Single extends string] ? Single extends keyof ResolvedOutputRow<TContract, ModelName> ? ResolvedOutputRow<TContract, ModelName>[Single] : IDBValidKey : KeyTupleType<TContract, ModelName, ModelKeyPathOrdered<TContract, ModelName>>;
80
115
  /** The object store name for a model, extracted from `contract.domain...storage.storeName` (used to match `execution.mutations.defaults[].ref.table`). */
81
116
  type ModelStoreName<TContract, ModelName extends string> = ModelName extends keyof ModelsOf<TContract> ? ModelsOf<TContract>[ModelName] extends {
82
117
  readonly storage: {
83
118
  readonly storeName: infer S;
84
119
  };
85
120
  } ? S extends string ? S : never : never : never;
121
+ /** Whether the model's object store has `autoIncrement: true` in `contract.storage.stores` (set by `@default(autoincrement())`). */
122
+ type IsAutoIncrementStore<TContract, ModelName extends string> = TContract extends {
123
+ readonly storage: {
124
+ readonly stores: infer Stores;
125
+ };
126
+ } ? ModelStoreName<TContract, ModelName> extends keyof Stores ? Stores[ModelStoreName<TContract, ModelName>] extends {
127
+ readonly autoIncrement: true;
128
+ } ? true : false : false : false;
129
+ /**
130
+ * The primary key field `create()` may omit because IDB generates it: the
131
+ * key of a *single-field*-key model whose store has `autoIncrement: true`.
132
+ * IDB's key generator is numeric-only and never runs without
133
+ * `autoIncrement` — an absent key then makes `add()` throw `DataError` —
134
+ * and it can't fill a compound key (`autoIncrement` + array `keyPath` is
135
+ * rejected). App-generated keys (`uuid()`/`cuid()`) are covered separately
136
+ * by {@link FieldsWithCreateDefault}; any other key must be supplied.
137
+ */
138
+ type OptionalKeyPathField<TContract, ModelName extends string> = IsAutoIncrementStore<TContract, ModelName> extends true ? ModelKeyPathOrdered<TContract, ModelName> extends readonly [infer Single extends string] ? Single : never : never;
139
+ /** {@link OptionalKeyPathField}, narrowed to a key that actually exists on the resolved input row (may be absent for models with no typed maps). */
140
+ type KeyPathField<TContract, ModelName extends string> = OptionalKeyPathField<TContract, ModelName> & keyof ResolvedInputRow<TContract, ModelName>;
86
141
  /** The flattened `execution.mutations.defaults` array type, or `never` for a contract with no execution section. */
87
142
  type ExecutionDefaultsOf<TContract> = TContract extends {
88
143
  readonly execution: {
@@ -107,12 +162,12 @@ type FieldsWithCreateDefault<TContract, ModelName extends string> = Extract<Exec
107
162
  /** {@link FieldsWithCreateDefault}, narrowed to keys that actually exist on the resolved input row (may be absent for models with no typed maps). */
108
163
  type DefaultedInputField<TContract, ModelName extends string> = FieldsWithCreateDefault<TContract, ModelName> & keyof ResolvedInputRow<TContract, ModelName>;
109
164
  /**
110
- * Input shape for `create()`: the full input row with the primary key field
111
- * made optional (IDB can generate keys via `autoIncrement`, or clients may
112
- * omit the key when using `cuid()` / `uuid()` at the application layer), and
113
- * every other field with an `onCreate` execution default also made optional.
165
+ * Input shape for `create()`: the full input row with an `autoIncrement`
166
+ * primary key made optional (see {@link OptionalKeyPathField}), and every
167
+ * field with an `onCreate` execution default — including a `uuid()`/`cuid()`
168
+ * key — also made optional. Any other key field stays required.
114
169
  */
115
- type CreateInput<TContract, ModelName extends string> = Omit<ResolvedInputRow<TContract, ModelName>, ModelKeyPath<TContract, ModelName> | FieldsWithCreateDefault<TContract, ModelName>> & Partial<Pick<ResolvedInputRow<TContract, ModelName>, KeyPathField<TContract, ModelName> | DefaultedInputField<TContract, ModelName>>>;
170
+ type CreateInput<TContract, ModelName extends string> = Omit<ResolvedInputRow<TContract, ModelName>, OptionalKeyPathField<TContract, ModelName> | FieldsWithCreateDefault<TContract, ModelName>> & Partial<Pick<ResolvedInputRow<TContract, ModelName>, KeyPathField<TContract, ModelName> | DefaultedInputField<TContract, ModelName>>>;
116
171
  /** Extract the relations record for a model. */
117
172
  type ModelRelations<TContract, ModelName extends string> = ModelName extends keyof ModelsOf<TContract> ? ModelsOf<TContract>[ModelName] extends {
118
173
  relations: infer R;
@@ -320,9 +375,24 @@ interface IdbAggregateBuilder<TContract, ModelName extends string> {
320
375
  declare function getStoreName(contract: IdbContract, modelName: string): string;
321
376
  /**
322
377
  * Extract the `keyPath` from a model's storage metadata at runtime.
323
- * Falls back to `"id"` (the invariant key name for all syncable IDB models).
378
+ * A single field name for the common case; an ordered array of field names
379
+ * for a compound primary key.
380
+ *
381
+ * @throws if the model is unknown or its storage has no `keyPath` — a
382
+ * validated contract always has one, so this only fires on a malformed or
383
+ * hand-built contract, where guessing a key name would silently read/write
384
+ * the wrong key.
385
+ */
386
+ declare function getKeyPath(contract: IdbContract, modelName: string): IdbKeyPath;
387
+ /**
388
+ * Extracts a row's primary key as an {@link IDBValidKey} — the scalar value
389
+ * at `row[keyPath]` for a single-field key, or an ordered array of the
390
+ * compound key's member field values (matching the array form IDB itself
391
+ * expects for a compound `keyPath`). The one construction site every
392
+ * key-get/put/delete/update call should route through, so compound-key field
393
+ * order stays consistent everywhere.
324
394
  */
325
- declare function getKeyPath(contract: IdbContract, modelName: string): string;
395
+ declare function extractKeyFromRow(row: Record<string, unknown>, keyPath: IdbKeyPath): IDBValidKey;
326
396
  //#endregion
327
397
  //#region src/core/executor.d.ts
328
398
  /**
@@ -742,5 +812,5 @@ interface IdbOrmOptions<TContract extends IdbContract> {
742
812
  */
743
813
  declare function idbOrm<TContract extends IdbContract>(options: IdbOrmOptions<TContract>): IdbOrmClient<TContract>;
744
814
  //#endregion
745
- export { MutationUpdateInput as A, SelectedRow as B, IncludeFields as C, KeyType as D, IncludedRow as E, ReferenceRelKeys as F, WhereFilter as H, RelatedModelOf as I, RelationMutationConnect as L, NumericFieldNames as M, OrderBySpec as N, ModelKeyPath as O, PatchInput as P, RelationMutationCreate as R, IdbRelationMutator as S, IncludeSpec as T, getKeyPath as U, SortDirection as V, getStoreName as W, IdbAggregateResult as _, IdbStoreAccessor as a, IdbContract as b, IdbGroupedAccessor as c, IdbModelAccessor as d, IdbQueryExecutor as f, IdbAggregateBuilder as g, DefaultModelRow as h, IdbIncludeRefinementAccessor as i, NoIncludes as j, MutationCreateInput as k, IdbIncludeScalar as l, CreateInput as m, IdbOrmOptions as n, WhereCallback as o, AggregateFn as p, idbOrm as r, GroupedResultRow as s, IdbOrmClient as t, IdbFieldAccessor as u, IdbAggregateSelector as v, IncludeMarker as w, IdbRelationMutation as x, IdbAggregateSpec as y, RelationMutationDisconnect as z };
746
- //# sourceMappingURL=idb-orm-zCRkkD_D.d.mts.map
815
+ export { ModelKeyPathOrdered as A, RelationMutationCreate as B, IdbRelationMutator as C, IncludedRow as D, IncludeSpec as E, OrderBySpec as F, extractKeyFromRow as G, SelectedRow as H, PatchInput as I, keyEquals as J, getKeyPath as K, ReferenceRelKeys as L, MutationUpdateInput as M, NoIncludes as N, KeyType as O, NumericFieldNames as P, RelatedModelOf as R, IdbRelationMutation as S, IncludeMarker as T, SortDirection as U, RelationMutationDisconnect as V, WhereFilter as W, keyToken as Y, IdbAggregateResult as _, IdbStoreAccessor as a, IdbContract as b, IdbGroupedAccessor as c, IdbModelAccessor as d, IdbQueryExecutor as f, IdbAggregateBuilder as g, DefaultModelRow as h, IdbIncludeRefinementAccessor as i, MutationCreateInput as j, ModelKeyPath as k, IdbIncludeScalar as l, CreateInput as m, IdbOrmOptions as n, WhereCallback as o, AggregateFn as p, getStoreName as q, idbOrm as r, GroupedResultRow as s, IdbOrmClient as t, IdbFieldAccessor as u, IdbAggregateSelector as v, IncludeFields as w, IdbKeyPath as x, IdbAggregateSpec as y, RelationMutationConnect as z };
816
+ //# sourceMappingURL=idb-orm-MOH1S3ES.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idb-orm-MOH1S3ES.d.mts","names":[],"sources":["../src/core/types.ts","../src/core/executor.ts","../src/core/model-accessor.ts","../src/core/store-state.ts","../src/core/grouped-accessor.ts","../src/core/store-accessor.ts","../src/core/idb-orm.ts"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
- import { c as withMutationScope, t as idbOrm } from "./idb-orm-Cupnnwum.mjs";
1
+ import { c as withMutationScope, t as idbOrm } from "./idb-orm-JBg6si7u.mjs";
2
2
  import { IdbAdapter } from "@prisma-idb/adapter-idb/runtime";
3
+ import { idbCodecLookup } from "@prisma-idb/target-idb/runtime";
3
4
  import { createIDBRuntimeDriver } from "@prisma-idb/driver-idb/runtime";
4
5
  import { createIdbRuntime } from "@prisma-idb/runtime-idb/runtime";
5
- import { idbCodecLookup } from "@prisma-idb/target-idb/runtime";
6
6
  //#region src/core/idb-client.ts
7
7
  /**
8
8
  * Creates a typed IDB client from a contract and a database name.
@@ -119,4 +119,4 @@ function createManagedIdbClient(open, options) {
119
119
  //#endregion
120
120
  export { createIdbClient as n, createManagedIdbClient as t };
121
121
 
122
- //# sourceMappingURL=managed-client-B_8JZM3h.mjs.map
122
+ //# sourceMappingURL=managed-client-BLdCyxUi.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"managed-client-B_8JZM3h.mjs","names":[],"sources":["../src/core/idb-client.ts","../src/core/managed-client.ts"],"sourcesContent":["import { IdbAdapter } from \"@prisma-idb/adapter-idb/runtime\";\nimport { createIDBRuntimeDriver } from \"@prisma-idb/driver-idb/runtime\";\nimport type { IdbTransactionScope } from \"@prisma-idb/driver-idb/runtime\";\nimport type { IdbMiddleware } from \"@prisma-idb/runtime-idb/runtime\";\nimport { createIdbRuntime } from \"@prisma-idb/runtime-idb/runtime\";\nimport { idbCodecLookup } from \"@prisma-idb/target-idb/runtime\";\nimport { withMutationScope } from \"./mutation-scope\";\nimport { idbOrm } from \"./idb-orm\";\nimport type { IdbOrmClient } from \"./idb-orm\";\nimport type { IdbContract } from \"./types\";\n\nexport interface IdbClientOptions<TContract extends IdbContract> {\n readonly contract: TContract;\n readonly dbName: string;\n // No version — the migration runner owns the IDB version integer (ADR 001).\n /** IDB factory override — primarily for tests and custom browser realms. */\n readonly factory?: IDBFactory;\n readonly middleware?: readonly IdbMiddleware[];\n}\n\nexport interface IdbClient<TContract extends IdbContract> {\n readonly orm: IdbOrmClient<TContract>;\n /**\n * Run `fn` inside a single multi-store readwrite IDB transaction.\n *\n * Opens the transaction, passes an `IdbTransactionScope` to `fn`, then\n * commits on success or rolls back on error. Equivalent to calling\n * `withMutationScope(runtime, storeNames, fn)`.\n *\n * Useful from test harnesses and from any caller that has an `IdbClient`\n * but not the raw runtime reference.\n */\n withTransaction<T>(storeNames: string[], fn: (scope: IdbTransactionScope) => Promise<T>): Promise<T>;\n verifyMarker(): Promise<boolean>;\n close(): Promise<void>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\n/**\n * Creates a typed IDB client from a contract and a database name.\n *\n * Assembles the full runtime stack (driver → adapter → runtime → ORM) internally.\n * Equivalent to `postgres({ contract, url })` in `@prisma/orm-postgres/runtime`.\n *\n * The IDB database version is not exposed — it is managed by the migration runner\n * per ADR 001. The driver opens at the current database version, which is correct\n * for a runtime that only reads/writes (no DDL).\n *\n * @example\n * ```ts\n * import { createIdbClient } from '@prisma-idb/client-idb/client';\n * import contract from './contract';\n *\n * export const db = createIdbClient({ contract, dbName: 'my-app' });\n *\n * // Later:\n * const users = await db.orm.users.all().toArray();\n * ```\n */\nexport function createIdbClient<TContract extends IdbContract>(\n options: IdbClientOptions<TContract>\n): IdbClient<TContract> {\n const driver = createIDBRuntimeDriver(\n options.dbName,\n undefined,\n options.factory !== undefined ? { factory: options.factory } : undefined\n ).create();\n const adapter = new IdbAdapter(idbCodecLookup);\n const runtime = createIdbRuntime({\n adapter,\n driver,\n contract: options.contract as Record<string, unknown>,\n ...(options.middleware !== undefined && options.middleware.length > 0 ? { middleware: options.middleware } : {}),\n });\n const orm = idbOrm({ contract: options.contract, executor: runtime });\n\n return {\n orm,\n withTransaction: <T>(storeNames: string[], fn: (scope: IdbTransactionScope) => Promise<T>) =>\n withMutationScope(runtime, storeNames, fn),\n verifyMarker: () => runtime.verifyMarker(),\n async close() {\n await runtime.close();\n },\n [Symbol.asyncDispose]() {\n return this.close();\n },\n };\n}\n","/**\n * `createManagedIdbClient` — a singleton, race-safe wrapper around any IDB\n * client factory (`createIdbClient`, `createAutoMigratingIdbClient`, or a\n * sync-extension factory like `createAutoMigratingSyncIdbClient` — anything\n * returning a `close(): Promise<void>`-shaped client).\n *\n * Every consumer of this package that wants a module-level singleton client\n * plus a \"wipe local data\" reset (e.g. on logout) needs the same race-safety:\n * `reset()` must never call `indexedDB.deleteDatabase` while a `get()` open\n * is still in flight, since a still-opening connection would block (or worse,\n * leave a stale handle once that open resolves after the delete). This was\n * previously hand-rolled per app with diverging correctness; see ADR-less\n * discussion in the kanban example's `db.ts` history.\n */\n\nexport interface ManagedIdbClientOptions {\n /** IDB database name — passed to `indexedDB.deleteDatabase` on `reset()`. */\n readonly dbName: string;\n /** IDB factory override — primarily for tests. Defaults to `indexedDB`. */\n readonly idbFactory?: IDBFactory;\n}\n\nexport interface ManagedIdbClient<TClient> {\n /** Opens the client on first call and caches it; concurrent calls share one open. */\n get(): Promise<TClient>;\n /** Closes the cached client, if any. Safe to call when nothing is open. */\n close(): Promise<void>;\n /**\n * Closes and deletes the database — waits out any `get()` open already in\n * flight first. `onblocked` (another tab still has the DB open) is NOT\n * terminal — per spec, the delete request stays pending, and still fires\n * `onsuccess` once every blocking connection closes — so this promise\n * stays pending through it too, settling only once `deleteDatabase`\n * actually reaches `onsuccess` or `onerror`. Neither resolving early\n * (claims success before the old data is actually gone) nor rejecting\n * early (reports failure on a delete that may still succeed) would be\n * accurate.\n */\n reset(): Promise<void>;\n}\n\n/**\n * Wraps `open` (a client factory, e.g. `() => createAutoMigratingIdbClient({...})`)\n * with a module-scoped singleton: `get()` opens once and caches the result,\n * `close()` releases it, `reset()` closes and wipes the underlying database.\n *\n * @example\n * ```ts\n * import { createManagedIdbClient } from '@prisma-idb/client-idb/client';\n *\n * const db = createManagedIdbClient(\n * () => createAutoMigratingIdbClient({ contractSpace, dbName: 'my-app' }),\n * { dbName: 'my-app' }\n * );\n *\n * const client = await db.get();\n * // ... on logout:\n * await db.reset();\n * ```\n */\nexport function createManagedIdbClient<TClient extends { close(): Promise<void> }>(\n open: () => Promise<TClient>,\n options: ManagedIdbClientOptions\n): ManagedIdbClient<TClient> {\n const { dbName, idbFactory = indexedDB } = options;\n\n let client: TClient | null = null;\n let clientPromise: Promise<TClient> | null = null;\n // Gate between get() and reset() — set synchronously (no `await` before\n // either reads/writes it) so the two never interleave: see module doc comment.\n let resetPromise: Promise<void> | null = null;\n\n async function get(): Promise<TClient> {\n if (resetPromise) await resetPromise;\n if (client) return client;\n clientPromise ??= open().catch((err: unknown) => {\n // Clear on rejection so a later get() call retries instead of\n // re-awaiting the same rejected promise forever.\n clientPromise = null;\n throw err;\n });\n\n const fresh = await clientPromise;\n client = fresh;\n return fresh;\n }\n\n async function close(): Promise<void> {\n if (!client) return;\n await client.close();\n client = null;\n clientPromise = null;\n }\n\n async function reset(): Promise<void> {\n if (resetPromise) return resetPromise;\n resetPromise = (async () => {\n if (clientPromise) await clientPromise.catch(() => {});\n await close();\n await new Promise<void>((resolve, reject) => {\n const req = idbFactory.deleteDatabase(dbName);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error as Error);\n // Deliberately no-op: `onblocked` only means the request is waiting\n // on another open connection, not that it failed — `onsuccess` (or\n // `onerror`) still fires later once that connection closes. Settling\n // here either way would misreport the outcome; see the `reset()`\n // doc comment above.\n req.onblocked = () => {};\n });\n })();\n try {\n await resetPromise;\n } finally {\n resetPromise = null;\n }\n }\n\n return { get, close, reset };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DA,SAAgB,gBACd,SACsB;CACtB,MAAM,SAAS,uBACb,QAAQ,QACR,KAAA,GACA,QAAQ,YAAY,KAAA,IAAY,EAAE,SAAS,QAAQ,QAAQ,IAAI,KAAA,CACjE,CAAC,CAAC,OAAO;CACT,MAAM,UAAU,IAAI,WAAW,cAAc;CAC7C,MAAM,UAAU,iBAAiB;EAC/B;EACA;EACA,UAAU,QAAQ;EAClB,GAAI,QAAQ,eAAe,KAAA,KAAa,QAAQ,WAAW,SAAS,IAAI,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;CAChH,CAAC;CAGD,OAAO;EACL,KAHU,OAAO;GAAE,UAAU,QAAQ;GAAU,UAAU;EAAQ,CAG/D;EACF,kBAAqB,YAAsB,OACzC,kBAAkB,SAAS,YAAY,EAAE;EAC3C,oBAAoB,QAAQ,aAAa;EACzC,MAAM,QAAQ;GACZ,MAAM,QAAQ,MAAM;EACtB;EACA,CAAC,OAAO,gBAAgB;GACtB,OAAO,KAAK,MAAM;EACpB;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;AC5BA,SAAgB,uBACd,MACA,SAC2B;CAC3B,MAAM,EAAE,QAAQ,aAAa,cAAc;CAE3C,IAAI,SAAyB;CAC7B,IAAI,gBAAyC;CAG7C,IAAI,eAAqC;CAEzC,eAAe,MAAwB;EACrC,IAAI,cAAc,MAAM;EACxB,IAAI,QAAQ,OAAO;EACnB,kBAAkB,KAAK,CAAC,CAAC,OAAO,QAAiB;GAG/C,gBAAgB;GAChB,MAAM;EACR,CAAC;EAED,MAAM,QAAQ,MAAM;EACpB,SAAS;EACT,OAAO;CACT;CAEA,eAAe,QAAuB;EACpC,IAAI,CAAC,QAAQ;EACb,MAAM,OAAO,MAAM;EACnB,SAAS;EACT,gBAAgB;CAClB;CAEA,eAAe,QAAuB;EACpC,IAAI,cAAc,OAAO;EACzB,gBAAgB,YAAY;GAC1B,IAAI,eAAe,MAAM,cAAc,YAAY,CAAC,CAAC;GACrD,MAAM,MAAM;GACZ,MAAM,IAAI,SAAe,SAAS,WAAW;IAC3C,MAAM,MAAM,WAAW,eAAe,MAAM;IAC5C,IAAI,kBAAkB,QAAQ;IAC9B,IAAI,gBAAgB,OAAO,IAAI,KAAc;IAM7C,IAAI,kBAAkB,CAAC;GACzB,CAAC;EACH,EAAA,CAAG;EACH,IAAI;GACF,MAAM;EACR,UAAU;GACR,eAAe;EACjB;CACF;CAEA,OAAO;EAAE;EAAK;EAAO;CAAM;AAC7B"}
1
+ {"version":3,"file":"managed-client-BLdCyxUi.mjs","names":[],"sources":["../src/core/idb-client.ts","../src/core/managed-client.ts"],"sourcesContent":["import { IdbAdapter } from \"@prisma-idb/adapter-idb/runtime\";\nimport { createIDBRuntimeDriver } from \"@prisma-idb/driver-idb/runtime\";\nimport type { IdbTransactionScope } from \"@prisma-idb/driver-idb/runtime\";\nimport type { IdbMiddleware } from \"@prisma-idb/runtime-idb/runtime\";\nimport { createIdbRuntime } from \"@prisma-idb/runtime-idb/runtime\";\nimport { idbCodecLookup } from \"@prisma-idb/target-idb/runtime\";\nimport { withMutationScope } from \"./mutation-scope\";\nimport { idbOrm } from \"./idb-orm\";\nimport type { IdbOrmClient } from \"./idb-orm\";\nimport type { IdbContract } from \"./types\";\n\nexport interface IdbClientOptions<TContract extends IdbContract> {\n readonly contract: TContract;\n readonly dbName: string;\n // No version — the migration runner owns the IDB version integer (ADR 001).\n /** IDB factory override — primarily for tests and custom browser realms. */\n readonly factory?: IDBFactory;\n readonly middleware?: readonly IdbMiddleware[];\n}\n\nexport interface IdbClient<TContract extends IdbContract> {\n readonly orm: IdbOrmClient<TContract>;\n /**\n * Run `fn` inside a single multi-store readwrite IDB transaction.\n *\n * Opens the transaction, passes an `IdbTransactionScope` to `fn`, then\n * commits on success or rolls back on error. Equivalent to calling\n * `withMutationScope(runtime, storeNames, fn)`.\n *\n * Useful from test harnesses and from any caller that has an `IdbClient`\n * but not the raw runtime reference.\n */\n withTransaction<T>(storeNames: string[], fn: (scope: IdbTransactionScope) => Promise<T>): Promise<T>;\n verifyMarker(): Promise<boolean>;\n close(): Promise<void>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\n/**\n * Creates a typed IDB client from a contract and a database name.\n *\n * Assembles the full runtime stack (driver → adapter → runtime → ORM) internally.\n * Equivalent to `postgres({ contract, url })` in `@prisma/orm-postgres/runtime`.\n *\n * The IDB database version is not exposed — it is managed by the migration runner\n * per ADR 001. The driver opens at the current database version, which is correct\n * for a runtime that only reads/writes (no DDL).\n *\n * @example\n * ```ts\n * import { createIdbClient } from '@prisma-idb/client-idb/client';\n * import contract from './contract';\n *\n * export const db = createIdbClient({ contract, dbName: 'my-app' });\n *\n * // Later:\n * const users = await db.orm.users.all().toArray();\n * ```\n */\nexport function createIdbClient<TContract extends IdbContract>(\n options: IdbClientOptions<TContract>\n): IdbClient<TContract> {\n const driver = createIDBRuntimeDriver(\n options.dbName,\n undefined,\n options.factory !== undefined ? { factory: options.factory } : undefined\n ).create();\n const adapter = new IdbAdapter(idbCodecLookup);\n const runtime = createIdbRuntime({\n adapter,\n driver,\n contract: options.contract as Record<string, unknown>,\n ...(options.middleware !== undefined && options.middleware.length > 0 ? { middleware: options.middleware } : {}),\n });\n const orm = idbOrm({ contract: options.contract, executor: runtime });\n\n return {\n orm,\n withTransaction: <T>(storeNames: string[], fn: (scope: IdbTransactionScope) => Promise<T>) =>\n withMutationScope(runtime, storeNames, fn),\n verifyMarker: () => runtime.verifyMarker(),\n async close() {\n await runtime.close();\n },\n [Symbol.asyncDispose]() {\n return this.close();\n },\n };\n}\n","/**\n * `createManagedIdbClient` — a singleton, race-safe wrapper around any IDB\n * client factory (`createIdbClient`, `createAutoMigratingIdbClient`, or a\n * sync-extension factory like `createAutoMigratingSyncIdbClient` — anything\n * returning a `close(): Promise<void>`-shaped client).\n *\n * Every consumer of this package that wants a module-level singleton client\n * plus a \"wipe local data\" reset (e.g. on logout) needs the same race-safety:\n * `reset()` must never call `indexedDB.deleteDatabase` while a `get()` open\n * is still in flight, since a still-opening connection would block (or worse,\n * leave a stale handle once that open resolves after the delete). This was\n * previously hand-rolled per app with diverging correctness; see ADR-less\n * discussion in the kanban example's `db.ts` history.\n */\n\nexport interface ManagedIdbClientOptions {\n /** IDB database name — passed to `indexedDB.deleteDatabase` on `reset()`. */\n readonly dbName: string;\n /** IDB factory override — primarily for tests. Defaults to `indexedDB`. */\n readonly idbFactory?: IDBFactory;\n}\n\nexport interface ManagedIdbClient<TClient> {\n /** Opens the client on first call and caches it; concurrent calls share one open. */\n get(): Promise<TClient>;\n /** Closes the cached client, if any. Safe to call when nothing is open. */\n close(): Promise<void>;\n /**\n * Closes and deletes the database — waits out any `get()` open already in\n * flight first. `onblocked` (another tab still has the DB open) is NOT\n * terminal — per spec, the delete request stays pending, and still fires\n * `onsuccess` once every blocking connection closes — so this promise\n * stays pending through it too, settling only once `deleteDatabase`\n * actually reaches `onsuccess` or `onerror`. Neither resolving early\n * (claims success before the old data is actually gone) nor rejecting\n * early (reports failure on a delete that may still succeed) would be\n * accurate.\n */\n reset(): Promise<void>;\n}\n\n/**\n * Wraps `open` (a client factory, e.g. `() => createAutoMigratingIdbClient({...})`)\n * with a module-scoped singleton: `get()` opens once and caches the result,\n * `close()` releases it, `reset()` closes and wipes the underlying database.\n *\n * @example\n * ```ts\n * import { createManagedIdbClient } from '@prisma-idb/client-idb/client';\n *\n * const db = createManagedIdbClient(\n * () => createAutoMigratingIdbClient({ contractSpace, dbName: 'my-app' }),\n * { dbName: 'my-app' }\n * );\n *\n * const client = await db.get();\n * // ... on logout:\n * await db.reset();\n * ```\n */\nexport function createManagedIdbClient<TClient extends { close(): Promise<void> }>(\n open: () => Promise<TClient>,\n options: ManagedIdbClientOptions\n): ManagedIdbClient<TClient> {\n const { dbName, idbFactory = indexedDB } = options;\n\n let client: TClient | null = null;\n let clientPromise: Promise<TClient> | null = null;\n // Gate between get() and reset() — set synchronously (no `await` before\n // either reads/writes it) so the two never interleave: see module doc comment.\n let resetPromise: Promise<void> | null = null;\n\n async function get(): Promise<TClient> {\n if (resetPromise) await resetPromise;\n if (client) return client;\n clientPromise ??= open().catch((err: unknown) => {\n // Clear on rejection so a later get() call retries instead of\n // re-awaiting the same rejected promise forever.\n clientPromise = null;\n throw err;\n });\n\n const fresh = await clientPromise;\n client = fresh;\n return fresh;\n }\n\n async function close(): Promise<void> {\n if (!client) return;\n await client.close();\n client = null;\n clientPromise = null;\n }\n\n async function reset(): Promise<void> {\n if (resetPromise) return resetPromise;\n resetPromise = (async () => {\n if (clientPromise) await clientPromise.catch(() => {});\n await close();\n await new Promise<void>((resolve, reject) => {\n const req = idbFactory.deleteDatabase(dbName);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error as Error);\n // Deliberately no-op: `onblocked` only means the request is waiting\n // on another open connection, not that it failed — `onsuccess` (or\n // `onerror`) still fires later once that connection closes. Settling\n // here either way would misreport the outcome; see the `reset()`\n // doc comment above.\n req.onblocked = () => {};\n });\n })();\n try {\n await resetPromise;\n } finally {\n resetPromise = null;\n }\n }\n\n return { get, close, reset };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DA,SAAgB,gBACd,SACsB;CACtB,MAAM,SAAS,uBACb,QAAQ,QACR,KAAA,GACA,QAAQ,YAAY,KAAA,IAAY,EAAE,SAAS,QAAQ,QAAQ,IAAI,KAAA,CACjE,CAAC,CAAC,OAAO;CACT,MAAM,UAAU,IAAI,WAAW,cAAc;CAC7C,MAAM,UAAU,iBAAiB;EAC/B;EACA;EACA,UAAU,QAAQ;EAClB,GAAI,QAAQ,eAAe,KAAA,KAAa,QAAQ,WAAW,SAAS,IAAI,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;CAChH,CAAC;CAGD,OAAO;EACL,KAHU,OAAO;GAAE,UAAU,QAAQ;GAAU,UAAU;EAAQ,CAG/D;EACF,kBAAqB,YAAsB,OACzC,kBAAkB,SAAS,YAAY,EAAE;EAC3C,oBAAoB,QAAQ,aAAa;EACzC,MAAM,QAAQ;GACZ,MAAM,QAAQ,MAAM;EACtB;EACA,CAAC,OAAO,gBAAgB;GACtB,OAAO,KAAK,MAAM;EACpB;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;AC5BA,SAAgB,uBACd,MACA,SAC2B;CAC3B,MAAM,EAAE,QAAQ,aAAa,cAAc;CAE3C,IAAI,SAAyB;CAC7B,IAAI,gBAAyC;CAG7C,IAAI,eAAqC;CAEzC,eAAe,MAAwB;EACrC,IAAI,cAAc,MAAM;EACxB,IAAI,QAAQ,OAAO;EACnB,kBAAkB,KAAK,CAAC,CAAC,OAAO,QAAiB;GAG/C,gBAAgB;GAChB,MAAM;EACR,CAAC;EAED,MAAM,QAAQ,MAAM;EACpB,SAAS;EACT,OAAO;CACT;CAEA,eAAe,QAAuB;EACpC,IAAI,CAAC,QAAQ;EACb,MAAM,OAAO,MAAM;EACnB,SAAS;EACT,gBAAgB;CAClB;CAEA,eAAe,QAAuB;EACpC,IAAI,cAAc,OAAO;EACzB,gBAAgB,YAAY;GAC1B,IAAI,eAAe,MAAM,cAAc,YAAY,CAAC,CAAC;GACrD,MAAM,MAAM;GACZ,MAAM,IAAI,SAAe,SAAS,WAAW;IAC3C,MAAM,MAAM,WAAW,eAAe,MAAM;IAC5C,IAAI,kBAAkB,QAAQ;IAC9B,IAAI,gBAAgB,OAAO,IAAI,KAAc;IAM7C,IAAI,kBAAkB,CAAC;GACzB,CAAC;EACH,EAAA,CAAG;EACH,IAAI;GACF,MAAM;EACR,UAAU;GACR,eAAe;EACjB;CACF;CAEA,OAAO;EAAE;EAAK;EAAO;CAAM;AAC7B"}
@@ -1,4 +1,4 @@
1
- import { b as IdbContract, t as IdbOrmClient } from "./idb-orm-zCRkkD_D.mjs";
1
+ import { b as IdbContract, t as IdbOrmClient } from "./idb-orm-MOH1S3ES.mjs";
2
2
  import { IdbTransactionScope } from "@prisma-idb/driver-idb/runtime";
3
3
  import { IdbMiddleware } from "@prisma-idb/runtime-idb/runtime";
4
4
  //#region src/core/idb-client.d.ts
@@ -112,4 +112,4 @@ declare function createManagedIdbClient<TClient extends {
112
112
  }>(open: () => Promise<TClient>, options: ManagedIdbClientOptions): ManagedIdbClient<TClient>;
113
113
  //#endregion
114
114
  export { IdbClientOptions as a, IdbClient as i, ManagedIdbClientOptions as n, createIdbClient as o, createManagedIdbClient as r, ManagedIdbClient as t };
115
- //# sourceMappingURL=managed-client-kdyHm72t.d.mts.map
115
+ //# sourceMappingURL=managed-client-CJD9lBx5.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"managed-client-kdyHm72t.d.mts","names":[],"sources":["../src/core/idb-client.ts","../src/core/managed-client.ts"],"mappings":";;;;UAWiB,iBAAiB,kBAAkB;WACzC,UAAU;WACV;;WAGA,UAAU;WACV,sBAAsB;;UAGhB,UAAU,kBAAkB;WAClC,KAAK,aAAa;;;;;;;;;;;EAW3B,gBAAgB,GAAG,sBAAsB,KAAK,OAAO,wBAAwB,QAAQ,KAAK,QAAQ;EAClG,gBAAgB;EAChB,SAAS;GACR,OAAO,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;iBAwBX,gBAAgB,kBAAkB,aAChD,SAAS,iBAAiB,aACzB,UAAU;;;;;;;;;;;;;;;;;UC9CI;;WAEN;;WAEA,aAAa;;UAGP,iBAAiB;;EAEhC,OAAO,QAAQ;;EAEf,SAAS;;;;;;;;;;;;EAYT,SAAS;;;;;;;;;;;;;;;;;;;;;iBAsBK,uBAAuB;EAAkB,SAAS;GAChE,YAAY,QAAQ,UACpB,SAAS,0BACR,iBAAiB"}
1
+ {"version":3,"file":"managed-client-CJD9lBx5.d.mts","names":[],"sources":["../src/core/idb-client.ts","../src/core/managed-client.ts"],"mappings":";;;;UAWiB,iBAAiB,kBAAkB;WACzC,UAAU;WACV;;WAGA,UAAU;WACV,sBAAsB;;UAGhB,UAAU,kBAAkB;WAClC,KAAK,aAAa;;;;;;;;;;;EAW3B,gBAAgB,GAAG,sBAAsB,KAAK,OAAO,wBAAwB,QAAQ,KAAK,QAAQ;EAClG,gBAAgB;EAChB,SAAS;GACR,OAAO,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;iBAwBX,gBAAgB,kBAAkB,aAChD,SAAS,iBAAiB,aACzB,UAAU;;;;;;;;;;;;;;;;;UC9CI;;WAEN;;WAEA,aAAa;;UAGP,iBAAiB;;EAEhC,OAAO,QAAQ;;EAEf,SAAS;;;;;;;;;;;;EAYT,SAAS;;;;;;;;;;;;;;;;;;;;;iBAsBK,uBAAuB;EAAkB,SAAS;GAChE,YAAY,QAAQ,UACpB,SAAS,0BACR,iBAAiB"}
package/dist/orm.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as MutationUpdateInput, B as SelectedRow, C as IncludeFields, D as KeyType, E as IncludedRow, F as ReferenceRelKeys, H as WhereFilter, I as RelatedModelOf, L as RelationMutationConnect, M as NumericFieldNames, N as OrderBySpec, O as ModelKeyPath, P as PatchInput, R as RelationMutationCreate, S as IdbRelationMutator, T as IncludeSpec, U as getKeyPath, V as SortDirection, W as getStoreName, _ as IdbAggregateResult, a as IdbStoreAccessor, b as IdbContract, c as IdbGroupedAccessor, d as IdbModelAccessor, f as IdbQueryExecutor, g as IdbAggregateBuilder, h as DefaultModelRow, i as IdbIncludeRefinementAccessor, j as NoIncludes, k as MutationCreateInput, l as IdbIncludeScalar, m as CreateInput, n as IdbOrmOptions, o as WhereCallback, p as AggregateFn, r as idbOrm, s as GroupedResultRow, t as IdbOrmClient, u as IdbFieldAccessor, v as IdbAggregateSelector, w as IncludeMarker, x as IdbRelationMutation, y as IdbAggregateSpec, z as RelationMutationDisconnect } from "./idb-orm-zCRkkD_D.mjs";
1
+ import { A as ModelKeyPathOrdered, B as RelationMutationCreate, C as IdbRelationMutator, D as IncludedRow, E as IncludeSpec, F as OrderBySpec, G as extractKeyFromRow, H as SelectedRow, I as PatchInput, J as keyEquals, K as getKeyPath, L as ReferenceRelKeys, M as MutationUpdateInput, N as NoIncludes, O as KeyType, P as NumericFieldNames, R as RelatedModelOf, S as IdbRelationMutation, T as IncludeMarker, U as SortDirection, V as RelationMutationDisconnect, W as WhereFilter, Y as keyToken, _ as IdbAggregateResult, a as IdbStoreAccessor, b as IdbContract, c as IdbGroupedAccessor, d as IdbModelAccessor, f as IdbQueryExecutor, g as IdbAggregateBuilder, h as DefaultModelRow, i as IdbIncludeRefinementAccessor, j as MutationCreateInput, k as ModelKeyPath, l as IdbIncludeScalar, m as CreateInput, n as IdbOrmOptions, o as WhereCallback, p as AggregateFn, q as getStoreName, r as idbOrm, s as GroupedResultRow, t as IdbOrmClient, u as IdbFieldAccessor, v as IdbAggregateSelector, w as IncludeFields, x as IdbKeyPath, y as IdbAggregateSpec, z as RelationMutationConnect } from "./idb-orm-MOH1S3ES.mjs";
2
2
  import { IdbAndExpr, IdbAndExpr as IdbAndExpr$1, IdbFieldFilter, IdbFilterExpr, IdbFilterExpr as IdbFilterExpr$1, IdbFilterOp, IdbNotExpr, IdbNotExpr as IdbNotExpr$1, IdbNullCheckExpr, IdbOrExpr, IdbOrExpr as IdbOrExpr$1 } from "@prisma-idb/adapter-idb/runtime";
3
3
  import { IdbTransactionScope } from "@prisma-idb/driver-idb/runtime";
4
4
  //#region src/core/filters.d.ts
@@ -81,5 +81,5 @@ declare function collectDeleteStoreNames(contract: IdbContract, modelName: strin
81
81
  */
82
82
  declare function applyReferentialActionsForRow(scope: IdbTransactionScope, contract: IdbContract, modelName: string, row: Record<string, unknown>, visited?: Set<string>): Promise<void>;
83
83
  //#endregion
84
- export { type AggregateFn, type CreateInput, type DefaultModelRow, type GroupedResultRow, type IdbAggregateBuilder, type IdbAggregateResult, type IdbAggregateSelector, type IdbAggregateSpec, type IdbAndExpr, type IdbContract, type IdbFieldAccessor, type IdbFieldFilter, type IdbFilterExpr, type IdbFilterOp, type IdbGroupedAccessor, type IdbIncludeRefinementAccessor, type IdbIncludeScalar, type IdbModelAccessor, type IdbNotExpr, type IdbNullCheckExpr, type IdbOrExpr, type IdbOrmClient, type IdbOrmOptions, type IdbQueryExecutor, type IdbQueryExecutorWithTransaction, type IdbRelationMutation, type IdbRelationMutator, type IdbStoreAccessor, type IncludeFields, type IncludeMarker, type IncludeSpec, type IncludedRow, type KeyType, type ModelKeyPath, type MutationCreateInput, type MutationUpdateInput, type NoIncludes, type NumericFieldNames, type OrderBySpec, type PatchInput, type ReferenceRelKeys, type RelatedModelOf, type RelationMutationConnect, type RelationMutationCreate, type RelationMutationDisconnect, type SelectedRow, type SortDirection, type WhereCallback, type WhereFilter, and, applyReferentialActionsForRow, collectDeleteStoreNames, createRelationMutator, getKeyPath, getStoreName, hasNestedMutationCallbacks, idbOrm, isRelationMutationCallback, isRelationMutationDescriptor, not, or, withMutationScope };
84
+ export { type AggregateFn, type CreateInput, type DefaultModelRow, type GroupedResultRow, type IdbAggregateBuilder, type IdbAggregateResult, type IdbAggregateSelector, type IdbAggregateSpec, type IdbAndExpr, type IdbContract, type IdbFieldAccessor, type IdbFieldFilter, type IdbFilterExpr, type IdbFilterOp, type IdbGroupedAccessor, type IdbIncludeRefinementAccessor, type IdbIncludeScalar, type IdbKeyPath, type IdbModelAccessor, type IdbNotExpr, type IdbNullCheckExpr, type IdbOrExpr, type IdbOrmClient, type IdbOrmOptions, type IdbQueryExecutor, type IdbQueryExecutorWithTransaction, type IdbRelationMutation, type IdbRelationMutator, type IdbStoreAccessor, type IncludeFields, type IncludeMarker, type IncludeSpec, type IncludedRow, type KeyType, type ModelKeyPath, type ModelKeyPathOrdered, type MutationCreateInput, type MutationUpdateInput, type NoIncludes, type NumericFieldNames, type OrderBySpec, type PatchInput, type ReferenceRelKeys, type RelatedModelOf, type RelationMutationConnect, type RelationMutationCreate, type RelationMutationDisconnect, type SelectedRow, type SortDirection, type WhereCallback, type WhereFilter, and, applyReferentialActionsForRow, collectDeleteStoreNames, createRelationMutator, extractKeyFromRow, getKeyPath, getStoreName, hasNestedMutationCallbacks, idbOrm, isRelationMutationCallback, isRelationMutationDescriptor, keyEquals, keyToken, not, or, withMutationScope };
85
85
  //# sourceMappingURL=orm.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"orm.d.mts","names":[],"sources":["../src/core/filters.ts","../src/core/mutation-scope.ts","../src/core/relation-mutator.ts","../src/core/mutation-executor.ts"],"mappings":";;;;;iBAqBgB,OAAO,OAAO,cAAc,mBAAiB;;iBAK7C,MAAM,OAAO,cAAc,mBAAiB;;iBAK5C,IAAI,MAAM,kBAAgB;;;;;;;;UCFzB,wCAAwC;;;;;;;;;EASvD,YAAY,sBAAsB,OAAO,qBAAqB,QAAQ;;;;;;;;;;;;iBAelD,kBAAkB,GACtC,UAAU,iCACV,sBACA,MAAM,OAAO,wBAAwB,QAAQ,KAC5C,QAAQ;;;iBC/BK,sBAAsB,kBAAkB,aAAa,6BAA6B,mBAChG,WACA;iBAsBc,6BAA6B,iBAAiB,SAAS,oBAAoB;iBAM3E,2BACd,iBACC,UAAU,SAAS,mBAAmB,yBAAyB,oBAAoB;;;;;;;iBC0EtE,2BACd,UAAU,aACV,mBACA,MAAM;;;;;;;;;;;;iBAymCQ,wBAAwB,UAAU,aAAa;;;;;;;;;;;;;;;;;;;iBAuCzC,8BACpB,OAAO,qBACP,UAAU,aACV,mBACA,KAAK,yBACL,UAAS,cACR"}
1
+ {"version":3,"file":"orm.d.mts","names":[],"sources":["../src/core/filters.ts","../src/core/mutation-scope.ts","../src/core/relation-mutator.ts","../src/core/mutation-executor.ts"],"mappings":";;;;;iBAqBgB,OAAO,OAAO,cAAc,mBAAiB;;iBAK7C,MAAM,OAAO,cAAc,mBAAiB;;iBAK5C,IAAI,MAAM,kBAAgB;;;;;;;;UCFzB,wCAAwC;;;;;;;;;EASvD,YAAY,sBAAsB,OAAO,qBAAqB,QAAQ;;;;;;;;;;;;iBAelD,kBAAkB,GACtC,UAAU,iCACV,sBACA,MAAM,OAAO,wBAAwB,QAAQ,KAC5C,QAAQ;;;iBC/BK,sBAAsB,kBAAkB,aAAa,6BAA6B,mBAChG,WACA;iBAsBc,6BAA6B,iBAAiB,SAAS,oBAAoB;iBAM3E,2BACd,iBACC,UAAU,SAAS,mBAAmB,yBAAyB,oBAAoB;;;;;;;iBCiFtE,2BACd,UAAU,aACV,mBACA,MAAM;;;;;;;;;;;;iBA4yCQ,wBAAwB,UAAU,aAAa;;;;;;;;;;;;;;;;;;;iBAsCzC,8BACpB,OAAO,qBACP,UAAU,aACV,mBACA,KAAK,yBACL,UAAS,cACR"}
package/dist/orm.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as createRelationMutator, c as withMutationScope, i as hasNestedMutationCallbacks, l as getKeyPath, n as applyReferentialActionsForRow, o as isRelationMutationCallback, r as collectDeleteStoreNames, s as isRelationMutationDescriptor, t as idbOrm, u as getStoreName } from "./idb-orm-Cupnnwum.mjs";
1
+ import { a as createRelationMutator, c as withMutationScope, d as getStoreName, f as keyEquals, i as hasNestedMutationCallbacks, l as extractKeyFromRow, n as applyReferentialActionsForRow, o as isRelationMutationCallback, p as keyToken, r as collectDeleteStoreNames, s as isRelationMutationDescriptor, t as idbOrm, u as getKeyPath } from "./idb-orm-JBg6si7u.mjs";
2
2
  import { andExpr, notExpr, orExpr } from "@prisma-idb/adapter-idb/runtime";
3
3
  //#region src/core/filters.ts
4
4
  /**
@@ -23,6 +23,6 @@ function not(expr) {
23
23
  return notExpr(expr);
24
24
  }
25
25
  //#endregion
26
- export { and, applyReferentialActionsForRow, collectDeleteStoreNames, createRelationMutator, getKeyPath, getStoreName, hasNestedMutationCallbacks, idbOrm, isRelationMutationCallback, isRelationMutationDescriptor, not, or, withMutationScope };
26
+ export { and, applyReferentialActionsForRow, collectDeleteStoreNames, createRelationMutator, extractKeyFromRow, getKeyPath, getStoreName, hasNestedMutationCallbacks, idbOrm, isRelationMutationCallback, isRelationMutationDescriptor, keyEquals, keyToken, not, or, withMutationScope };
27
27
 
28
28
  //# sourceMappingURL=orm.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma-idb/client-idb",
3
- "version": "0.0.0",
3
+ "version": "0.7.0",
4
4
  "description": "Prisma 8 IDB family — ORM client (idbOrm typed query builder)",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -31,20 +31,20 @@
31
31
  "./package.json": "./package.json"
32
32
  },
33
33
  "dependencies": {
34
- "@prisma/orm-framework": "8.0.0-rc.5",
35
- "@prisma-idb/adapter-idb": "0.0.0",
36
- "@prisma-idb/runtime-idb": "0.0.0",
37
- "@prisma-idb/target-idb": "0.0.0",
38
- "@prisma-idb/driver-idb": "0.0.0"
34
+ "@prisma-idb/adapter-idb": "0.7.0",
35
+ "@prisma-idb/driver-idb": "0.7.0",
36
+ "@prisma-idb/runtime-idb": "0.7.0",
37
+ "@prisma-idb/target-idb": "0.7.0",
38
+ "@prisma/orm-framework": "8.0.0-rc.5"
39
39
  },
40
40
  "devDependencies": {
41
+ "@prisma-idb/family-idb": "0.7.0",
41
42
  "@prisma/cli-engine": "0.2.0",
42
43
  "@prisma/orm-toolchain": "8.0.0-rc.5",
43
44
  "fake-indexeddb": "^6.2.5",
44
45
  "tsdown": "^0.22.14",
45
46
  "typescript": "^6.0.3",
46
- "vitest": "^4.1.10",
47
- "@prisma-idb/family-idb": "0.0.0"
47
+ "vitest": "^4.1.11"
48
48
  },
49
49
  "publishConfig": {
50
50
  "access": "public"