@prisma-idb/client-idb 0.6.1 → 0.8.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.
- package/README.md +25 -12
- package/dist/client-auto.d.mts +20 -41
- package/dist/client-auto.d.mts.map +1 -1
- package/dist/client-auto.mjs +20 -41
- package/dist/client-auto.mjs.map +1 -1
- package/dist/client.d.mts +1 -1
- package/dist/client.mjs +1 -1
- package/dist/{idb-orm-Cupnnwum.mjs → idb-orm-C8yXJp6R.mjs} +542 -200
- package/dist/idb-orm-C8yXJp6R.mjs.map +1 -0
- package/dist/{idb-orm-zCRkkD_D.d.mts → idb-orm-MOH1S3ES.d.mts} +93 -23
- package/dist/idb-orm-MOH1S3ES.d.mts.map +1 -0
- package/dist/{managed-client-kdyHm72t.d.mts → managed-client-CJD9lBx5.d.mts} +2 -2
- package/dist/{managed-client-kdyHm72t.d.mts.map → managed-client-CJD9lBx5.d.mts.map} +1 -1
- package/dist/{managed-client-B_8JZM3h.mjs → managed-client-DofL09P8.mjs} +3 -3
- package/dist/{managed-client-B_8JZM3h.mjs.map → managed-client-DofL09P8.mjs.map} +1 -1
- package/dist/orm.d.mts +2 -2
- package/dist/orm.d.mts.map +1 -1
- package/dist/orm.mjs +2 -2
- package/package.json +9 -9
- package/dist/idb-orm-Cupnnwum.mjs.map +0 -1
- package/dist/idb-orm-zCRkkD_D.d.mts.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"idb-orm-Cupnnwum.mjs","names":["getKeyPath","_exhaustive","getKeyPath","#contract","#modelName","#executor","#storeName","#state","#newGroupingKey","#includeRefinementMode","#clone","#resolveIncludeEntry","#buildScanPlan","#executeOrRows","#applyIncludes","#projectRows","#combinedFilterExpr","getKeyPath","#materialize","#planMeta","#countTerminal"],"sources":["../src/core/types.ts","../src/core/model-accessor.ts","../src/core/store-state.ts","../src/core/query-shaping.ts","../src/core/aggregate-builder.ts","../src/core/grouped-accessor.ts","../src/core/mutation-defaults.ts","../src/core/relation-loader.ts","../src/core/mutation-scope.ts","../src/core/relation-mutator.ts","../src/core/mutation-executor.ts","../src/core/store-accessor.ts","../src/core/idb-orm.ts"],"sourcesContent":["import type { Contract, ContractModelBase, ContractReferenceRelation } from \"@prisma/orm-framework/contract/types\";\nimport { domainModelsAtDefaultNamespace } from \"@prisma/orm-framework/contract/types\";\nimport type {\n ExtractIdbFieldInputTypes,\n ExtractIdbFieldOutputTypes,\n IdbModelStorage,\n IdbStorage,\n} from \"@prisma-idb/target-idb/pack\";\n\n// Re-export for consumers who only import from client-idb\nexport type { IdbStorage };\n\n// ── Model-map extraction (v0.12.0 domain plane) ───────────────────────────────\n\n/**\n * Extract the model map from a contract by traversing the domain namespace.\n *\n * 0.14.0: `Contract` dropped the 2nd `TModels` type parameter; models are now\n * accessed via `domain.namespaces[ns].models`. For a single-namespace contract\n * (the only IDB case) this resolves to the typed model map; falls back to\n * `Record<string, ContractModelBase>` for un-typed/multi-namespace inputs.\n */\ntype ModelsOf<TContract> = TContract extends { readonly domain: { readonly namespaces: infer NS } }\n ? NS[keyof NS] extends { readonly models: infer M }\n ? M extends Record<string, ContractModelBase>\n ? M\n : Record<string, ContractModelBase>\n : Record<string, ContractModelBase>\n : Record<string, ContractModelBase>;\n\n// ── IdbContract convenience alias ─────────────────────────────────────────────\n\n/**\n * A `Contract` narrowed to the IDB storage shape. Accepts any contract whose\n * `storage` block includes an `stores` record, regardless of the model set or\n * whether type maps are attached.\n */\nexport type IdbContract = Contract<IdbStorage>;\n\n// ── Row type resolution (full type-maps path) ─────────────────────────────────\n\n/**\n * Resolve the output row type for a model from the contract's type maps.\n *\n * When `fieldOutputTypes` is parameterised (the emitted contract carries\n * `IdbContractWithTypeMaps<Base, IdbTypeMaps<Codecs, FieldOutputTypes, ...>>`),\n * each field gets the exact TypeScript type emitted by the family (e.g. `Date`\n * for `idb/date@1`).\n *\n * Falls back to `Record<string, unknown>` when type maps are absent (plain\n * `IdbContract` or when the model name is not in the type maps).\n */\n// FieldOutputTypes = { __unbound__: { User: {...} } } — union over namespace values\n// to get the flat model map, then look up ModelName.\ntype NsFieldOutputTypes<TContract> = ExtractIdbFieldOutputTypes<TContract>[keyof ExtractIdbFieldOutputTypes<TContract>];\n\ntype ResolvedOutputRow<TContract, ModelName extends string> = string extends keyof ExtractIdbFieldOutputTypes<TContract>\n ? Record<string, unknown>\n : NsFieldOutputTypes<TContract> extends Record<string, unknown>\n ? ModelName extends keyof NsFieldOutputTypes<TContract>\n ? { -readonly [K in keyof NsFieldOutputTypes<TContract>[ModelName]]: NsFieldOutputTypes<TContract>[ModelName][K] }\n : Record<string, unknown>\n : Record<string, unknown>;\n\n/**\n * Resolve the input row type for a model from the contract's type maps.\n *\n * Mirrors `ResolvedOutputRow` but uses `fieldInputTypes` — the input types\n * used for `create()`, `where()`, and mutation payloads.\n */\ntype NsFieldInputTypes<TContract> = ExtractIdbFieldInputTypes<TContract>[keyof ExtractIdbFieldInputTypes<TContract>];\n\ntype ResolvedInputRow<TContract, ModelName extends string> = string extends keyof ExtractIdbFieldInputTypes<TContract>\n ? Record<string, unknown>\n : NsFieldInputTypes<TContract> extends Record<string, unknown>\n ? ModelName extends keyof NsFieldInputTypes<TContract>\n ? { -readonly [K in keyof NsFieldInputTypes<TContract>[ModelName]]: NsFieldInputTypes<TContract>[ModelName][K] }\n : Record<string, unknown>\n : Record<string, unknown>;\n\n// ── Public row types ──────────────────────────────────────────────────────────\n\n/** The full TypeScript row shape returned by `all()`, `first()`, and `create()`. */\nexport type DefaultModelRow<TContract, ModelName extends string> = ResolvedOutputRow<TContract, ModelName>;\n\n// ── Where filter ──────────────────────────────────────────────────────────────\n\n/**\n * Partial equality filter applied as an in-memory predicate during cursor scans.\n *\n * All fields are optional — only provided fields are checked. Values use the\n * output types (from `fieldOutputTypes`) since the values are compared against\n * decoded row data.\n */\nexport type WhereFilter<TContract, ModelName extends string> = {\n readonly [K in keyof DefaultModelRow<TContract, ModelName>]?: DefaultModelRow<TContract, ModelName>[K];\n};\n\n// ── KeyPath / KeyType ─────────────────────────────────────────────────────────\n\n/**\n * The literal `keyPath` string for a model, extracted from\n * `contract.models[ModelName].storage.keyPath`.\n *\n * Used at the type level to exclude the key field from `CreateInput` and to\n * narrow the `findUnique` / `delete` key parameter type.\n */\nexport type ModelKeyPath<TContract, ModelName extends string> = ModelName extends keyof ModelsOf<TContract>\n ? ModelsOf<TContract>[ModelName] extends { storage: { keyPath: infer P } }\n ? P extends string\n ? P\n : never\n : never\n : never;\n\n/**\n * TypeScript type of the primary key field for a given model.\n *\n * When the output row type has a field matching `ModelKeyPath`, that field's\n * type is used. Otherwise falls back to `IDBValidKey` (the DOM union of valid\n * IDB key types).\n */\nexport type KeyType<TContract, ModelName extends string> =\n ModelKeyPath<TContract, ModelName> extends keyof ResolvedOutputRow<TContract, ModelName>\n ? ResolvedOutputRow<TContract, ModelName>[ModelKeyPath<TContract, ModelName>]\n : IDBValidKey;\n\n// ── Create input ──────────────────────────────────────────────────────────────\n\n/** The keyPath field when it exists in the resolved input row (may be absent for models with no typed maps). */\ntype KeyPathField<TContract, ModelName extends string> = ModelKeyPath<TContract, ModelName> &\n keyof ResolvedInputRow<TContract, ModelName>;\n\n/** The object store name for a model, extracted from `contract.domain...storage.storeName` (used to match `execution.mutations.defaults[].ref.table`). */\ntype ModelStoreName<TContract, ModelName extends string> = ModelName extends keyof ModelsOf<TContract>\n ? ModelsOf<TContract>[ModelName] extends { readonly storage: { readonly storeName: infer S } }\n ? S extends string\n ? S\n : never\n : never\n : never;\n\n/** The flattened `execution.mutations.defaults` array type, or `never` for a contract with no execution section. */\ntype ExecutionDefaultsOf<TContract> = TContract extends {\n readonly execution: { readonly mutations: { readonly defaults: infer D } };\n}\n ? D extends readonly unknown[]\n ? D[number]\n : never\n : never;\n\n/**\n * Column names with an `onCreate` execution default for this model's store —\n * e.g. `temporal.updatedAt()`/bare `@updatedAt` fields, or any\n * `@default(...)` field (literal, `now()`, `uuid()`, `cuid()`). These are\n * omittable in `create()` even though the field itself isn't nullable,\n * since the runtime fills them in (`client-idb/src/core/mutation-defaults.ts`).\n */\ntype FieldsWithCreateDefault<TContract, ModelName extends string> = Extract<\n ExecutionDefaultsOf<TContract>,\n { readonly ref: { readonly table: ModelStoreName<TContract, ModelName> }; readonly onCreate: unknown }\n>[\"ref\"][\"column\"];\n\n/** {@link FieldsWithCreateDefault}, narrowed to keys that actually exist on the resolved input row (may be absent for models with no typed maps). */\ntype DefaultedInputField<TContract, ModelName extends string> = FieldsWithCreateDefault<TContract, ModelName> &\n keyof ResolvedInputRow<TContract, ModelName>;\n\n/**\n * Input shape for `create()`: the full input row with the primary key field\n * made optional (IDB can generate keys via `autoIncrement`, or clients may\n * omit the key when using `cuid()` / `uuid()` at the application layer), and\n * every other field with an `onCreate` execution default also made optional.\n */\nexport type CreateInput<TContract, ModelName extends string> = Omit<\n ResolvedInputRow<TContract, ModelName>,\n ModelKeyPath<TContract, ModelName> | FieldsWithCreateDefault<TContract, ModelName>\n> &\n Partial<\n Pick<\n ResolvedInputRow<TContract, ModelName>,\n KeyPathField<TContract, ModelName> | DefaultedInputField<TContract, ModelName>\n >\n >;\n\n// ── Relations ─────────────────────────────────────────────────────────────────\n\n/** Extract the relations record for a model. */\ntype ModelRelations<TContract, ModelName extends string> = ModelName extends keyof ModelsOf<TContract>\n ? ModelsOf<TContract>[ModelName] extends { relations: infer R }\n ? R extends Record<string, unknown>\n ? R\n : Record<string, never>\n : Record<string, never>\n : Record<string, never>;\n\n/**\n * Union of relation keys on a model that are `ContractReferenceRelation`s\n * (i.e. cross-store joins, not embedded documents).\n *\n * Used to constrain the `include()` method's `relation` parameter to only\n * valid reference relation names.\n */\nexport type ReferenceRelKeys<TContract, ModelName extends string> = {\n [K in keyof ModelRelations<TContract, ModelName>]: ModelRelations<\n TContract,\n ModelName\n >[K] extends ContractReferenceRelation\n ? K\n : never;\n}[keyof ModelRelations<TContract, ModelName>] &\n string;\n\n/**\n * TypeScript row type for an included relation.\n *\n * - `1:N` cardinality → `RelatedRow[]`\n * - `N:1` or `1:1` cardinality → `RelatedRow | null`\n */\ntype RelationRowType<TContract, ModelName extends string, RelKey extends string> = RelKey extends keyof ModelRelations<\n TContract,\n ModelName\n>\n ? ModelRelations<TContract, ModelName>[RelKey] extends ContractReferenceRelation\n ? ModelRelations<TContract, ModelName>[RelKey] extends {\n to: { model: infer To extends string };\n cardinality: infer C;\n }\n ? C extends \"1:N\"\n ? DefaultModelRow<TContract, To>[]\n : DefaultModelRow<TContract, To> | null\n : never\n : never\n : never;\n\n/**\n * Per-relation include marker tracked at the type level.\n *\n * - `true` — the relation is loaded as rows (array for `1:N`, single/null\n * otherwise), optionally refined by a `where`/`orderBy`/`take` callback.\n * - `\"scalar\"` — the relation is reduced to a `count()` (Phase 6.5), so the\n * row field becomes a `number` instead of related rows.\n */\nexport type IncludeMarker = true | \"scalar\";\n\n/** Which relations are included in the current accessor chain. */\nexport type IncludeSpec<TContract, ModelName extends string> = Partial<\n Record<ReferenceRelKeys<TContract, ModelName>, IncludeMarker>\n>;\n\n/** Empty include spec — no relations included. */\nexport type NoIncludes = Record<never, never>;\n\n/**\n * The relation fields contributed by a set of `.include()` calls.\n *\n * A key is added only when its `TIncludes` marker is set; the field type is\n * `number` for a scalar `count()` include and the cardinality-shaped related\n * row(s) otherwise. Split out from {@link IncludedRow} so {@link SelectedRow}\n * can re-use it on top of a projected (picked) scalar base.\n */\nexport type IncludeFields<TContract, ModelName extends string, TIncludes extends IncludeSpec<TContract, ModelName>> = {\n -readonly [\n K in keyof TIncludes & string as TIncludes[K] extends IncludeMarker ? K : never\n ]: TIncludes[K] extends \"scalar\" ? number : RelationRowType<TContract, ModelName, K>;\n};\n\n/**\n * A row type that merges the base model row with any included relation fields.\n *\n * The extra fields are only added when the corresponding key in `TIncludes` is\n * set, so the type stays narrow until `.include()` is called.\n */\nexport type IncludedRow<\n TContract,\n ModelName extends string,\n TIncludes extends IncludeSpec<TContract, ModelName>,\n> = DefaultModelRow<TContract, ModelName> & IncludeFields<TContract, ModelName, TIncludes>;\n\n/**\n * The row type after an optional `.select()` projection.\n *\n * When `TSelected` is `never` (no `.select()` call) the full {@link IncludedRow}\n * is returned. Otherwise the scalar base is narrowed to the picked fields, with\n * any included relation fields preserved (mirrors the vendor `select()` which\n * keeps relations and narrows only scalar columns).\n */\nexport type SelectedRow<\n TContract,\n ModelName extends string,\n TIncludes extends IncludeSpec<TContract, ModelName>,\n TSelected extends string,\n> = [TSelected] extends [never]\n ? IncludedRow<TContract, ModelName, TIncludes>\n : Pick<DefaultModelRow<TContract, ModelName>, TSelected & keyof DefaultModelRow<TContract, ModelName>> &\n IncludeFields<TContract, ModelName, TIncludes>;\n\n// ── Patch input ───────────────────────────────────────────────────────────────\n\n/**\n * Partial update shape for `update()`, `updateAll()`, `updateCount()`, and the\n * `update` arm of `upsert()`. All fields are optional — only provided fields\n * are shallow-merged onto the existing record.\n */\nexport type PatchInput<TContract, ModelName extends string> = Partial<DefaultModelRow<TContract, ModelName>>;\n\n// ── Relation mutation types ───────────────────────────────────────────────────\n\n/** Extracts the `to` model name for a named relation on a model. */\nexport type RelatedModelOf<\n TContract,\n ModelName extends string,\n RelName extends string,\n> = ModelName extends keyof ModelsOf<TContract>\n ? ModelsOf<TContract>[ModelName] extends {\n relations: Record<RelName, { to: { model: infer To extends string } }>;\n }\n ? To\n : string\n : string;\n\n/** Nested-create descriptor: insert one or more related records. */\nexport interface RelationMutationCreate<TContract, ModelName extends string> {\n readonly kind: \"create\";\n readonly data: readonly CreateInput<TContract, ModelName>[];\n}\n\n/** Nested-connect descriptor: link existing records to the parent via FK update. */\nexport interface RelationMutationConnect {\n readonly kind: \"connect\";\n readonly criteria: readonly Record<string, unknown>[];\n}\n\n/**\n * Nested-disconnect descriptor: unlink related records by setting FK to null.\n * With no criteria, disconnects all child records from this parent.\n */\nexport interface RelationMutationDisconnect {\n readonly kind: \"disconnect\";\n readonly criteria?: readonly Record<string, unknown>[];\n}\n\n/** Discriminated union of all nested relation mutation descriptors. */\nexport type IdbRelationMutation<TContract, ModelName extends string> =\n RelationMutationCreate<TContract, ModelName> | RelationMutationConnect | RelationMutationDisconnect;\n\n/** Relation mutator object passed to the user's relation callback. */\nexport interface IdbRelationMutator<TContract, ModelName extends string> {\n create(\n data: CreateInput<TContract, ModelName> | readonly CreateInput<TContract, ModelName>[]\n ): RelationMutationCreate<TContract, ModelName>;\n connect(criteria: Record<string, unknown> | readonly Record<string, unknown>[]): RelationMutationConnect;\n disconnect(criteria?: readonly Record<string, unknown>[]): RelationMutationDisconnect;\n}\n\n/**\n * Maps each reference relation key to an optional mutation callback.\n *\n * When `ReferenceRelKeys` widens to `string` (a loosely-typed `IdbContract`\n * with no emitted type maps), a naive mapped type would become an index\n * signature `{ [k: string]: callback }` that incorrectly forces *every* field —\n * scalars included — to be a relation callback, so even `create({ name: \"x\" })`\n * would fail to type-check. The `string extends …` guard detects that case and\n * contributes no constraint (`& unknown` is identity), leaving plain scalar\n * payloads valid. Precisely-typed contracts (the emitted `contract.d.ts`)\n * resolve `ReferenceRelKeys` to a finite union and get the full callback typing.\n */\ntype RelationMutationFields<TContract, ModelName extends string> =\n string extends ReferenceRelKeys<TContract, ModelName>\n ? unknown\n : Partial<{\n [K in ReferenceRelKeys<TContract, ModelName>]: (\n mutator: IdbRelationMutator<TContract, RelatedModelOf<TContract, ModelName, K>>\n ) => IdbRelationMutation<TContract, RelatedModelOf<TContract, ModelName, K>>;\n }>;\n\n/**\n * The `localFields` of all N:1 relations on a model — the FK fields that are\n * owned by this model and can be supplied via a relation callback instead of\n * as a scalar value. Resolves to `never` for loosely-typed contracts where\n * cardinality is not preserved as a literal (e.g. `defineContract` in tests).\n *\n * Mirrors `ChildForeignKeyFieldNames` from `sql-orm-client`, simplified: instead\n * of crawling all models for relations pointing *to* this one, we look at this\n * model's own N:1 relations directly — same field set, one model.\n */\ntype N1LocalFieldNames<TContract, ModelName extends string> = {\n [K in keyof ModelRelations<TContract, ModelName>]: ModelRelations<TContract, ModelName>[K] extends {\n readonly cardinality: \"N:1\";\n readonly on: { readonly localFields: infer Fields extends readonly string[] };\n }\n ? Fields[number]\n : never;\n}[keyof ModelRelations<TContract, ModelName>] &\n string;\n\n/**\n * Like `CreateInput` but with N:1 FK fields made optional.\n *\n * An N:1 FK field (e.g. `authorId` on `Post`) can be supplied either as a\n * scalar value or via a relation callback (`author: (rel) => rel.connect({id})`).\n * Making it optional here lets callers omit it when using the callback form —\n * the executor populates it from the related record before inserting.\n *\n * Mirrors `NestedCreateInput` from `sql-orm-client`.\n */\ntype NestedCreateInput<TContract, ModelName extends string> = Omit<\n CreateInput<TContract, ModelName>,\n N1LocalFieldNames<TContract, ModelName>\n> &\n Partial<\n Pick<\n CreateInput<TContract, ModelName>,\n N1LocalFieldNames<TContract, ModelName> & keyof CreateInput<TContract, ModelName>\n >\n >;\n\n/**\n * Input shape for `create()` with optional relation callbacks.\n * N:1 FK fields (e.g. `authorId`) are optional when using a relation callback.\n * Relation fields accept a callback `(rel) => rel.create([...])` / `rel.connect(...)`.\n */\nexport type MutationCreateInput<TContract, ModelName extends string> = NestedCreateInput<TContract, ModelName> &\n RelationMutationFields<TContract, ModelName>;\n\n/**\n * Input shape for `update()` with optional relation callbacks.\n * All scalar fields are optional (shallow merge); relation fields accept\n * `connect` or `disconnect` callbacks.\n */\nexport type MutationUpdateInput<TContract, ModelName extends string> = PatchInput<TContract, ModelName> &\n RelationMutationFields<TContract, ModelName>;\n\n// ── OrderBy spec ─────────────────────────────────────────────────────────────\n\n/** Sort direction for `orderBy()`. */\nexport type SortDirection = \"asc\" | \"desc\";\n\n/** Partial sort spec: field name → direction. */\nexport type OrderBySpec<TContract, ModelName extends string> = Partial<\n Record<string & keyof DefaultModelRow<TContract, ModelName>, SortDirection>\n>;\n\n// ── Aggregate / groupBy ───────────────────────────────────────────────────────\n\n/** The five aggregation functions, matching the vendor `AggregateFn`. */\nexport type AggregateFn = \"count\" | \"sum\" | \"avg\" | \"min\" | \"max\";\n\n/**\n * Fields eligible for numeric aggregation (`sum`/`avg`/`min`/`max`).\n *\n * For an emitted (precisely-typed) contract this narrows to the fields whose\n * output type is assignable to `number`. For a loosely-typed `IdbContract`\n * (no type maps — `DefaultModelRow` is `Record<string, unknown>`) the row key\n * set widens to `string`, so we allow any field name rather than collapsing to\n * `never`. Mirrors `NumericFieldNames` from `sql-orm-client`, trait-free.\n */\nexport type NumericFieldNames<TContract, ModelName extends string> = string extends keyof DefaultModelRow<\n TContract,\n ModelName\n>\n ? string\n : {\n [K in keyof DefaultModelRow<TContract, ModelName> & string]: NonNullable<\n DefaultModelRow<TContract, ModelName>[K]\n > extends number\n ? K\n : never;\n }[keyof DefaultModelRow<TContract, ModelName> & string];\n\ndeclare const idbAggregateResultBrand: unique symbol;\n\n/**\n * A single aggregation selector produced by the {@link IdbAggregateBuilder}.\n *\n * The phantom `Result` brand carries the per-selector result type so\n * {@link IdbAggregateResult} can map each alias back to its value type.\n * Mirrors the vendor `AggregateSelector`.\n */\nexport interface IdbAggregateSelector<Result> {\n readonly kind: \"aggregate\";\n readonly fn: AggregateFn;\n readonly field?: string;\n readonly [idbAggregateResultBrand]?: Result;\n}\n\n/** A map of result aliases → aggregation selectors (the `aggregate()` spec). */\nexport type IdbAggregateSpec = Record<string, IdbAggregateSelector<unknown>>;\n\n/** The result row shape for an {@link IdbAggregateSpec}: alias → value type. */\nexport type IdbAggregateResult<Spec extends IdbAggregateSpec> = {\n [K in keyof Spec]: Spec[K] extends IdbAggregateSelector<infer Result> ? Result : never;\n};\n\n/**\n * The builder handed to an `.aggregate(agg => …)` callback. `count()` is always\n * available; the field reducers are constrained to {@link NumericFieldNames}.\n * Mirrors the vendor `AggregateBuilder`, minus the SQL column mapping.\n */\nexport interface IdbAggregateBuilder<TContract, ModelName extends string> {\n count(): IdbAggregateSelector<number>;\n sum<F extends NumericFieldNames<TContract, ModelName>>(field: F): IdbAggregateSelector<number | null>;\n avg<F extends NumericFieldNames<TContract, ModelName>>(field: F): IdbAggregateSelector<number | null>;\n min<F extends NumericFieldNames<TContract, ModelName>>(field: F): IdbAggregateSelector<number | null>;\n max<F extends NumericFieldNames<TContract, ModelName>>(field: F): IdbAggregateSelector<number | null>;\n}\n\n// ── Model storage helpers ─────────────────────────────────────────────────────\n\n/**\n * Extract the `storeName` from a model's storage metadata at runtime.\n * Falls back to the model name if `storeName` is absent.\n */\nexport function getStoreName(contract: IdbContract, modelName: string): string {\n const model = domainModelsAtDefaultNamespace(contract.domain)[modelName];\n return (model?.storage as IdbModelStorage | undefined)?.storeName ?? modelName;\n}\n\n/**\n * Extract the `keyPath` from a model's storage metadata at runtime.\n * Falls back to `\"id\"` (the invariant key name for all syncable IDB models).\n */\nexport function getKeyPath(contract: IdbContract, modelName: string): string {\n const model = domainModelsAtDefaultNamespace(contract.domain)[modelName];\n return (model?.storage as IdbModelStorage | undefined)?.keyPath ?? \"id\";\n}\n\n/**\n * Find the IDB index name for `fieldName` on the given object store, searching\n * `contract.storage.stores[storeName].indexes` by `keyPath` equality.\n *\n * Returns the index name (e.g. `\"byEmail\"`) when a single-field index whose\n * `keyPath` equals `fieldName` exists, or `undefined` otherwise.\n * Multi-entry and composite indexes (`keyPath` is an array) are skipped —\n * equality semantics on those are unsupported.\n */\nexport function getIndexForField(contract: IdbContract, storeName: string, fieldName: string): string | undefined {\n return buildFieldToIndexMap(contract, storeName)[fieldName];\n}\n\n/**\n * Build a field → indexName lookup for every single-field, non-multi-entry\n * index on `storeName`. Shared by {@link getIndexForField} (relation loader,\n * single-field lookups) and {@link IdbStoreAccessorImpl} (top-level scans,\n * which need the whole map to probe combined filter expressions).\n */\nexport function buildFieldToIndexMap(contract: IdbContract, storeName: string): Record<string, string> {\n const storeDef = contract.storage.stores[storeName];\n const result: Record<string, string> = {};\n if (storeDef?.indexes === undefined) return result;\n for (const [indexName, indexDef] of Object.entries(storeDef.indexes)) {\n if (typeof indexDef.keyPath === \"string\" && indexDef.multiEntry !== true) {\n result[indexDef.keyPath] = indexName;\n }\n }\n return result;\n}\n\n/**\n * Returns `true` when `value` is a valid {@link IDBValidKey} — i.e. a value\n * that can be passed to `IDBKeyRange.only()` without throwing a DataError.\n * Booleans, `NaN`, `BigInt`, plain objects, and `null`/`undefined` are not\n * valid IDB keys (only number/string/Date/binary/Array are, per the\n * IndexedDB spec). Arrays are validated recursively — an array containing\n * any invalid element (e.g. a nested boolean) is itself not a valid key.\n *\n * Shared by the relation loader (filtering FK values before building\n * `IDBKeyRange.only()` plans) and query-shaping (gating `eq` conditions for\n * index/PK point-range acceleration).\n */\nexport function isValidIdbKey(value: unknown): value is IDBValidKey {\n if (typeof value === \"number\") return !Number.isNaN(value);\n if (typeof value === \"string\") return true;\n if (value instanceof Date) return true;\n if (value instanceof ArrayBuffer) return true;\n if (ArrayBuffer.isView(value)) return true;\n if (Array.isArray(value)) return value.every((v) => isValidIdbKey(v));\n return false;\n}\n\n/**\n * Resolve a model's named relation to a {@link ContractReferenceRelation} at\n * runtime, or `undefined` when the relation is absent or an embedded relation\n * (no `on` join block). Used by `include()` to find the related model name and\n * cardinality before building the child-accessor refinement.\n */\nexport function getRelation(\n contract: IdbContract,\n modelName: string,\n relName: string\n): ContractReferenceRelation | undefined {\n const relation = domainModelsAtDefaultNamespace(contract.domain)[modelName]?.relations?.[relName];\n if (relation === undefined || !(\"on\" in relation)) return undefined;\n return relation as ContractReferenceRelation;\n}\n","/**\n * Proxy-based typed accessor handed to `where(fn)` callbacks.\n *\n * Mirrors `createModelAccessor()` from\n * Prisma ORM's SQL client, but without\n * the codec-trait gating — IDB stores native JS values, so every operator\n * is available on every field. The runtime accessor object is a Proxy\n * that materialises an `IdbFieldAccessor` on demand for whichever field\n * name is read; the type-level surface narrows that to the model's\n * actual field set so callbacks get autocomplete.\n */\n\nimport {\n type IdbFieldFilter,\n type IdbFilterExpr,\n type IdbNullCheckExpr,\n fieldFilter,\n nullCheckExpr,\n} from \"@prisma-idb/adapter-idb/runtime\";\nimport type { DefaultModelRow, IdbContract } from \"./types\";\n\n// ── Typed surface ─────────────────────────────────────────────────────────────\n\n/**\n * Operator surface available on every field. All return frozen AST nodes\n * — they are values, not statements, so chaining and logical combinators\n * compose naturally.\n */\nexport interface IdbFieldAccessor<T> {\n eq(value: T): IdbFieldFilter;\n neq(value: T): IdbFieldFilter;\n gt(value: T): IdbFieldFilter;\n lt(value: T): IdbFieldFilter;\n gte(value: T): IdbFieldFilter;\n lte(value: T): IdbFieldFilter;\n in(values: ReadonlyArray<T>): IdbFieldFilter;\n notIn(values: ReadonlyArray<T>): IdbFieldFilter;\n contains(sub: string): IdbFieldFilter;\n startsWith(sub: string): IdbFieldFilter;\n endsWith(sub: string): IdbFieldFilter;\n isNull(): IdbNullCheckExpr;\n isNotNull(): IdbNullCheckExpr;\n}\n\n/**\n * The accessor object handed to a `where(fn)` callback. Each key resolves\n * to an {@link IdbFieldAccessor} typed against the field's output type.\n *\n * The Proxy makes every string key resolve to an accessor at runtime; the\n * type narrows the visible surface to the model's declared fields so the\n * developer gets autocomplete.\n */\nexport type IdbModelAccessor<TContract, ModelName extends string> = {\n readonly [K in keyof DefaultModelRow<TContract, ModelName>]-?: IdbFieldAccessor<\n DefaultModelRow<TContract, ModelName>[K]\n >;\n};\n\n// ── Runtime construction ──────────────────────────────────────────────────────\n\n/**\n * Build an {@link IdbFieldAccessor} for a single field. The accessor is\n * shared via the proxy below, but each accessor instance is bound to its\n * own field name so the produced AST nodes carry the right field.\n */\nfunction createFieldAccessor(field: string): IdbFieldAccessor<unknown> {\n return {\n eq: (value) => fieldFilter(field, \"eq\", value),\n neq: (value) => fieldFilter(field, \"neq\", value),\n gt: (value) => fieldFilter(field, \"gt\", value),\n lt: (value) => fieldFilter(field, \"lt\", value),\n gte: (value) => fieldFilter(field, \"gte\", value),\n lte: (value) => fieldFilter(field, \"lte\", value),\n in: (values) => fieldFilter(field, \"in\", values),\n notIn: (values) => fieldFilter(field, \"notIn\", values),\n contains: (sub) => fieldFilter(field, \"contains\", sub),\n startsWith: (sub) => fieldFilter(field, \"startsWith\", sub),\n endsWith: (sub) => fieldFilter(field, \"endsWith\", sub),\n isNull: () => nullCheckExpr(field, true),\n isNotNull: () => nullCheckExpr(field, false),\n };\n}\n\n/**\n * Create the typed model accessor used by `where(fn)` callbacks.\n *\n * Implemented as a Proxy keyed on field names — every read returns an\n * {@link IdbFieldAccessor} bound to that field. The accessor cache means\n * `m.name.eq(...)` and `m.name.startsWith(...)` reuse the same per-field\n * accessor object across the same `where()` invocation.\n *\n * The type parameter is structural — no contract is consulted at\n * runtime, because TS already gates the visible field set at compile\n * time. (Misspelled fields surface as accessor calls on names that\n * don't exist in stored rows, which is consistent with how the\n * shorthand form behaves today.)\n */\nexport function createModelAccessor<TContract extends IdbContract, ModelName extends string>(): IdbModelAccessor<\n TContract,\n ModelName\n> {\n const cache = new Map<string, IdbFieldAccessor<unknown>>();\n return new Proxy(\n {},\n {\n get(_target, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n let acc = cache.get(prop);\n if (acc === undefined) {\n acc = createFieldAccessor(prop);\n cache.set(prop, acc);\n }\n return acc;\n },\n }\n ) as IdbModelAccessor<TContract, ModelName>;\n}\n\n// ── Re-export the AST type the callback returns ───────────────────────────────\n\nexport type { IdbFilterExpr };\n","import type { IdbFilterExpr } from \"@prisma-idb/adapter-idb/runtime\";\n\n/**\n * One entry in {@link IdbAccessorState.includes} — describes how a single\n * `.include()`d relation should be materialised.\n *\n * - `collection`: load the related rows, applying the refined `state`\n * (its `filters` / `orderBy` / `skip` / `take`) to the child scan.\n * `state` is `emptyAccessorState()` for an unrefined `.include(rel)`.\n * - `scalar`: reduce the related rows to a single number (Phase 6.5 supports\n * `count`). The `state.filters` still constrain which children are counted.\n *\n * Mirrors the `IncludeExpr` / `IncludeScalar` split from\n * Prisma ORM's SQL client, collapsed to the two shapes IDB\n * needs (no SQL column mapping, no `combine()` branches).\n */\nexport type IncludeEntry =\n | { readonly kind: \"collection\"; readonly state: IdbAccessorState }\n | { readonly kind: \"scalar\"; readonly fn: \"count\"; readonly state: IdbAccessorState };\n\n/**\n * Marker returned by the child accessor's `.count()` terminal when it is\n * called inside an `include()` refinement callback. Carries the refined\n * child `state` so the relation loader counts only the matching children.\n *\n * Detected by {@link isIncludeScalar}; mirrors `IncludeScalar` from the\n * vendor `sql-orm-client/include-descriptors.ts`.\n */\nexport interface IdbIncludeScalar {\n readonly kind: \"includeScalar\";\n readonly fn: \"count\";\n readonly state: IdbAccessorState;\n}\n\n/** Build an {@link IdbIncludeScalar} marker for a `count()` reducer. */\nexport function createIncludeScalar(state: IdbAccessorState): IdbIncludeScalar {\n return { kind: \"includeScalar\", fn: \"count\", state };\n}\n\n/** Type guard: is `value` an {@link IdbIncludeScalar} marker? */\nexport function isIncludeScalar(value: unknown): value is IdbIncludeScalar {\n if (typeof value !== \"object\" || value === null) return false;\n const candidate = value as { kind?: unknown; fn?: unknown };\n return candidate.kind === \"includeScalar\" && candidate.fn === \"count\";\n}\n\n/**\n * Immutable state carried by each {@link IdbStoreAccessorImpl} node in the\n * builder chain.\n *\n * Every mutating method (`.where()`, `.take()`, etc.) returns a cloned\n * instance with an updated state rather than mutating in place, making the\n * accessor safe to reuse across multiple query branches.\n */\nexport interface IdbAccessorState {\n /**\n * Accumulated filter expressions. Multiple `.where()` calls compose\n * with AND semantics — the planner wraps them in an `andExpr` when\n * lowering. Each entry is already either an `IdbFieldFilter`, a\n * combinator, or a `null-check` node — never raw shorthand records.\n */\n readonly filters: ReadonlyArray<IdbFilterExpr>;\n /** Sort spec: field → direction. Applied as an in-memory comparator. */\n readonly orderBy?: Record<string, \"asc\" | \"desc\">;\n /** OFFSET (number of rows to skip). */\n readonly skip?: number;\n /** LIMIT (maximum number of rows to return). */\n readonly take?: number;\n /**\n * Relations that have been `.include()`d — keys are relation names, values\n * describe how to materialise each (collection vs scalar count, plus any\n * refinement state). See {@link IncludeEntry}.\n */\n readonly includes: Record<string, IncludeEntry>;\n /**\n * Fields kept by `.select()`. `undefined` means \"all fields\". When set,\n * the materialised rows are projected down to these fields (plus any\n * included relation keys) after the scan and relation loads complete.\n */\n readonly selectedFields?: ReadonlyArray<string>;\n}\n\n/** Create a fresh, empty accessor state (no filters, no ordering, no includes). */\nexport function emptyAccessorState(): IdbAccessorState {\n return {\n filters: [],\n includes: {},\n };\n}\n\n/** Return a shallow-merged copy of `state` with the given overrides applied. */\nexport function mergeAccessorState(state: IdbAccessorState, overrides: Partial<IdbAccessorState>): IdbAccessorState {\n return { ...state, ...overrides };\n}\n","import type { IdbFilterExpr, IdbOrExpr } from \"@prisma-idb/adapter-idb/runtime\";\nimport { andExpr } from \"@prisma-idb/adapter-idb/runtime\";\nimport type { IdbRowComparator } from \"@prisma-idb/driver-idb/runtime\";\nimport { isValidIdbKey } from \"./types\";\n\n/** Describes an extractable indexed equality that can narrow a cursor scan. */\nexport interface IndexEqualityHint {\n /**\n * The IDB index name (e.g. `\"byEmail\"`), or `undefined` when the condition\n * is on the store's own primary key — a store's keyPath is always\n * point-range-queryable directly (`IDBObjectStore.openCursor(range)`),\n * without a named `IDBIndex`.\n */\n readonly indexName: string | undefined;\n /** The equality value to pass to `IDBKeyRange.only()`. */\n readonly value: unknown;\n /** The remainder of the filter after the indexed condition is peeled off. */\n readonly remainingFilter: IdbFilterExpr | undefined;\n}\n\n/**\n * Describes an OR filter where every branch can be satisfied by an indexed\n * equality lookup. Each branch maps to one `IDBKeyRange.only()` cursor scan;\n * the caller unions the results and deduplicates before applying\n * `remainingFilter`.\n */\nexport interface IndexOrHint {\n /** `indexName` is `undefined` for a branch on the store's own primary key — see {@link IndexEqualityHint}. */\n readonly branches: ReadonlyArray<{ readonly indexName: string | undefined; readonly value: unknown }>;\n /** AND conditions that wrapped the OR — applied in-memory after the union. */\n readonly remainingFilter: IdbFilterExpr | undefined;\n}\n\n/**\n * Combine accumulated filter expressions with AND.\n *\n * Returns `undefined` when no filter is present so callers can skip building a\n * row-filter closure. Shared by {@link IdbStoreAccessorImpl} (top-level scans)\n * and the relation loader (refined `include()` child scans).\n */\nexport function combineFilterExprs(filters: ReadonlyArray<IdbFilterExpr>): IdbFilterExpr | undefined {\n if (filters.length === 0) return undefined;\n if (filters.length === 1) return filters[0];\n return andExpr(filters);\n}\n\n/** Recursively flatten nested AND nodes into a single array of children. */\nfunction flattenAnd(filter: IdbFilterExpr): IdbFilterExpr[] {\n if (filter.kind !== \"and\") return [filter];\n return filter.exprs.flatMap(flattenAnd);\n}\n\n/** Fold the leftover AND children (after peeling an indexed condition) back into a single filter, or `undefined` if none remain. */\nfunction foldRemainder(rest: IdbFilterExpr[]): IdbFilterExpr | undefined {\n if (rest.length === 0) return undefined;\n if (rest.length === 1) return rest[0]!;\n return andExpr(rest);\n}\n\n/**\n * `IDBKeyRange.only()` throws `DataError` for values that aren't valid\n * IndexedDB keys (`null`/`undefined`, booleans, `NaN`, `BigInt`, plain\n * objects, or arrays containing any of those) — an `eq` condition on such a\n * value can't be served by an index point-range scan and must fall back to\n * a full scan. Delegates to the shared {@link isValidIdbKey} check.\n */\nfunction isIndexableEqValue(value: unknown): boolean {\n return isValidIdbKey(value);\n}\n\n/**\n * Scan the combined filter expression for the first `eq` field condition whose\n * field either has a matching IDB index (`fieldToIndexName[field]` is set) or\n * *is* the store's own primary key (`keyPath`) — a store's keyPath is always\n * point-range-queryable directly, no named index required.\n *\n * When found, the indexed condition is peeled off and returned as an\n * {@link IndexEqualityHint}; any remaining conditions are preserved in\n * `remainingFilter`. Returns `null` when no usable index can be found.\n *\n * Nested AND nodes are flattened before scanning, so deeply-composed filters\n * are handled correctly. Only `eq` conditions are considered — range operators\n * (`gt`, `lt`, etc.) could also use an index range but that optimization is\n * not yet implemented.\n */\nexport function extractIndexEqualityHint(\n filter: IdbFilterExpr | undefined,\n fieldToIndexName: Record<string, string>,\n keyPath: string\n): IndexEqualityHint | null {\n if (filter === undefined) return null;\n\n if (filter.kind === \"field\" && filter.op === \"eq\") {\n const indexName = fieldToIndexName[filter.field];\n if ((indexName !== undefined || filter.field === keyPath) && isIndexableEqValue(filter.value)) {\n return { indexName, value: filter.value, remainingFilter: undefined };\n }\n return null;\n }\n\n if (filter.kind === \"and\") {\n const flat = flattenAnd(filter);\n for (let i = 0; i < flat.length; i++) {\n const expr = flat[i]!;\n if (expr.kind === \"field\" && expr.op === \"eq\") {\n const indexName = fieldToIndexName[expr.field];\n if ((indexName !== undefined || expr.field === keyPath) && isIndexableEqValue(expr.value)) {\n const rest = flat.filter((_, j) => j !== i);\n return { indexName, value: expr.value, remainingFilter: foldRemainder(rest) };\n }\n }\n }\n }\n\n return null;\n}\n\n/**\n * Check whether every branch of an OR node is a single `field eq value`\n * condition whose field has a matching index. Returns an {@link IndexOrHint}\n * when the whole OR can be satisfied by N point-range cursor scans, `null`\n * otherwise.\n */\nfunction tryExtractOrBranches(\n orNode: IdbOrExpr,\n fieldToIndexName: Record<string, string>,\n keyPath: string,\n remainingFilter: IdbFilterExpr | undefined\n): IndexOrHint | null {\n if (orNode.exprs.length === 0) return null;\n const branches: { indexName: string | undefined; value: unknown }[] = [];\n for (const expr of orNode.exprs) {\n if (expr.kind !== \"field\" || expr.op !== \"eq\") return null;\n const indexName = fieldToIndexName[expr.field];\n if ((indexName === undefined && expr.field !== keyPath) || !isIndexableEqValue(expr.value)) return null;\n branches.push({ indexName, value: expr.value });\n }\n return { branches, remainingFilter };\n}\n\n/**\n * Attempt to extract an {@link IndexOrHint} from `filter`.\n *\n * Handles two shapes:\n * - Top-level `or` where every branch is `field eq value` on an indexed field.\n * - Top-level `and` (with nested ANDs flattened) that contains exactly one `or`\n * child fitting the above pattern; the remaining AND children become\n * `remainingFilter` applied in-memory after the union.\n *\n * Returns `null` when the filter cannot be accelerated via OR index scans.\n */\nexport function extractIndexOrHint(\n filter: IdbFilterExpr | undefined,\n fieldToIndexName: Record<string, string>,\n keyPath: string\n): IndexOrHint | null {\n if (filter === undefined) return null;\n\n if (filter.kind === \"or\") {\n return tryExtractOrBranches(filter, fieldToIndexName, keyPath, undefined);\n }\n\n if (filter.kind === \"and\") {\n const flat = flattenAnd(filter);\n const orIndices: number[] = [];\n for (let i = 0; i < flat.length; i++) {\n if (flat[i]!.kind === \"or\") orIndices.push(i);\n }\n if (orIndices.length !== 1) return null;\n const orIdx = orIndices[0]!;\n const orNode = flat[orIdx]! as IdbOrExpr;\n const rest = flat.filter((_, j) => j !== orIdx);\n return tryExtractOrBranches(orNode, fieldToIndexName, keyPath, foldRemainder(rest));\n }\n\n return null;\n}\n\n/**\n * Build an in-memory comparator from an `orderBy` spec (field → direction).\n *\n * Returns `undefined` when there is nothing to sort by. Compares fields in\n * declaration order; values are primitives (strings, numbers, dates) in\n * practice, so JS relational comparison is sufficient.\n */\nexport function buildRowComparator(orderBy: Record<string, \"asc\" | \"desc\"> | undefined): IdbRowComparator | undefined {\n if (orderBy === undefined) return undefined;\n return (a: Record<string, unknown>, b: Record<string, unknown>): number => {\n for (const [field, dir] of Object.entries(orderBy)) {\n const av = a[field];\n const bv = b[field];\n if (av === bv) continue;\n const cmp = (av as string | number) < (bv as string | number) ? -1 : 1;\n return dir === \"desc\" ? -cmp : cmp;\n }\n return 0;\n };\n}\n","import type { AggregateFn, IdbAggregateBuilder, IdbAggregateSelector } from \"./types\";\n\n/**\n * Build the aggregate selector factory handed to `.aggregate(agg => …)` and\n * `groupBy(...).aggregate(agg => …)`.\n *\n * Each method returns a frozen {@link IdbAggregateSelector} marker; the actual\n * reduction happens in {@link reduceAggregate} once the matching rows are\n * materialised in memory. Mirrors `createAggregateBuilder` from the vendor\n * `sql-orm-client/aggregate-builder.ts`, minus the field→column mapping (IDB\n * stores native field names).\n */\nexport function createAggregateBuilder<TContract, ModelName extends string>(): IdbAggregateBuilder<\n TContract,\n ModelName\n> {\n return {\n count: () => ({ kind: \"aggregate\", fn: \"count\" }),\n sum: (field) => ({ kind: \"aggregate\", fn: \"sum\", field: field as string }),\n avg: (field) => ({ kind: \"aggregate\", fn: \"avg\", field: field as string }),\n min: (field) => ({ kind: \"aggregate\", fn: \"min\", field: field as string }),\n max: (field) => ({ kind: \"aggregate\", fn: \"max\", field: field as string }),\n };\n}\n\n/** Type guard: is `value` an {@link IdbAggregateSelector}? */\nexport function isAggregateSelector(value: unknown): value is IdbAggregateSelector<unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const candidate = value as { kind?: unknown; fn?: unknown };\n return (\n candidate.kind === \"aggregate\" &&\n (candidate.fn === \"count\" ||\n candidate.fn === \"sum\" ||\n candidate.fn === \"avg\" ||\n candidate.fn === \"min\" ||\n candidate.fn === \"max\")\n );\n}\n\n/**\n * Reduce a set of materialised rows to a single aggregate value.\n *\n * - `count` → the number of rows (always a number, never null).\n * - `sum`/`avg`/`min`/`max` → computed over the non-null numeric values of\n * `field`; `null` when no row has a non-null value (matching Prisma's\n * \"aggregate of an empty set is null\" and the vendor `coerceAggregateValue`\n * null handling). String-encoded numbers are coerced via `Number()`.\n */\nexport function reduceAggregate(\n fn: AggregateFn,\n field: string | undefined,\n rows: readonly Record<string, unknown>[]\n): number | null {\n if (fn === \"count\") return rows.length;\n if (field === undefined) return null;\n\n const values: number[] = [];\n for (const row of rows) {\n const raw = row[field];\n if (raw === null || raw === undefined) continue;\n const n = typeof raw === \"bigint\" ? Number(raw) : Number(raw as number);\n if (!Number.isNaN(n)) values.push(n);\n }\n\n if (values.length === 0) return null;\n\n switch (fn) {\n case \"sum\":\n return values.reduce((acc, n) => acc + n, 0);\n case \"avg\":\n return values.reduce((acc, n) => acc + n, 0) / values.length;\n case \"min\":\n return Math.min(...values);\n case \"max\":\n return Math.max(...values);\n }\n}\n\n/**\n * Run every selector in an aggregate spec against `rows`, producing the\n * result object keyed by the spec's aliases.\n */\nexport function computeAggregateSpec(\n spec: Record<string, IdbAggregateSelector<unknown>>,\n rows: readonly Record<string, unknown>[]\n): Record<string, number | null> {\n const result: Record<string, number | null> = {};\n for (const [alias, selector] of Object.entries(spec)) {\n result[alias] = reduceAggregate(selector.fn, selector.field, rows);\n }\n return result;\n}\n\n/**\n * Project an aggregate spec down to the plain `{ fn, field? }` shape carried by\n * the query AST (`IdbAggregateAst.aggregates` / `IdbGroupByAst.aggregates`), so\n * middleware can observe the requested aggregations.\n */\nexport function toAggregateRequests(\n spec: Record<string, IdbAggregateSelector<unknown>>\n): Record<string, { readonly fn: string; readonly field?: string }> {\n const out: Record<string, { fn: string; field?: string }> = {};\n for (const [alias, selector] of Object.entries(spec)) {\n out[alias] = selector.field !== undefined ? { fn: selector.fn, field: selector.field } : { fn: selector.fn };\n }\n return out;\n}\n\n/**\n * Validate a user-supplied aggregate spec: it must be non-empty and every\n * value must be a real selector. Throws a descriptive error otherwise, so a\n * typo (e.g. returning a plain object) fails loudly rather than silently\n * producing `NaN`/`undefined` results.\n */\nexport function assertValidAggregateSpec(\n spec: Record<string, unknown>,\n context: \"aggregate()\" | \"groupBy().aggregate()\"\n): void {\n const entries = Object.entries(spec);\n if (entries.length === 0) {\n throw new Error(`${context} requires at least one aggregation selector`);\n }\n for (const [alias, selector] of entries) {\n if (!isAggregateSelector(selector)) {\n throw new Error(`${context} selector \"${alias}\" is invalid`);\n }\n }\n}\n","import type { IdbFilterExpr, IdbGroupByAst, IdbQueryAst } from \"@prisma-idb/adapter-idb/runtime\";\nimport {\n assertValidAggregateSpec,\n computeAggregateSpec,\n createAggregateBuilder,\n toAggregateRequests,\n} from \"./aggregate-builder\";\nimport type { DefaultModelRow, IdbAggregateBuilder, IdbAggregateResult, IdbAggregateSpec } from \"./types\";\n\n/**\n * One grouped-aggregate result row: the group-key fields picked from the model\n * row, intersected with the aggregate aliases.\n */\nexport type GroupedResultRow<\n TContract,\n ModelName extends string,\n Fields extends readonly string[],\n Spec extends IdbAggregateSpec,\n> = Pick<DefaultModelRow<TContract, ModelName>, Fields[number] & keyof DefaultModelRow<TContract, ModelName>> &\n IdbAggregateResult<Spec>;\n\n/**\n * Grouped-aggregate builder returned by `accessor.groupBy(...)`.\n *\n * Port of the vendor `GroupedCollection` (`sql-orm-client/grouped-collection.ts`),\n * but purely in-memory: there is no SQL compilation, so `aggregate()`\n * materialises the matching rows, partitions them by the group-key fields, and\n * reduces each partition with the requested selectors.\n */\nexport interface IdbGroupedAccessor<TContract, ModelName extends string, Fields extends readonly string[]> {\n /**\n * Reduce each group to one row of `{ ...groupKeyFields, ...aggregates }`.\n *\n * @example\n * ```ts\n * const byUser = await db.posts\n * .where({ published: true })\n * .groupBy(\"authorId\")\n * .aggregate((agg) => ({ count: agg.count(), totalViews: agg.sum(\"views\") }));\n * // [{ authorId: \"u1\", count: 3, totalViews: 120 }, ...]\n * ```\n */\n aggregate<Spec extends IdbAggregateSpec>(\n fn: (agg: IdbAggregateBuilder<TContract, ModelName>) => Spec\n ): Promise<Array<GroupedResultRow<TContract, ModelName, Fields, Spec>>>;\n}\n\n/** Runtime wiring handed to {@link createGroupedAccessor} by the store accessor. */\nexport interface GroupedAccessorInit {\n readonly modelName: string;\n /** Group-key fields, in declaration order. */\n readonly by: readonly string[];\n /** Combined `where` expression carried over from the source accessor, if any. */\n readonly where: IdbFilterExpr | undefined;\n /**\n * Materialise all rows matching the source filters. The store accessor owns\n * plan-building; the grouped accessor only supplies the AST it wants attached\n * (for middleware visibility) and does the in-memory grouping.\n */\n readonly materialize: (ast: IdbQueryAst) => Promise<Record<string, unknown>[]>;\n}\n\n/**\n * Build the composite group key for a row. Uses a JSON encoding of the ordered\n * key-field values so multi-field groups and primitive value types (string,\n * number, boolean, null) partition correctly.\n */\nfunction groupKeyOf(by: readonly string[], row: Record<string, unknown>): string {\n return JSON.stringify(by.map((field) => row[field] ?? null));\n}\n\nexport function createGroupedAccessor<TContract, ModelName extends string, Fields extends readonly string[]>(\n init: GroupedAccessorInit\n): IdbGroupedAccessor<TContract, ModelName, Fields> {\n return {\n async aggregate<Spec extends IdbAggregateSpec>(\n fn: (agg: IdbAggregateBuilder<TContract, ModelName>) => Spec\n ): Promise<Array<GroupedResultRow<TContract, ModelName, Fields, Spec>>> {\n const spec = fn(createAggregateBuilder<TContract, ModelName>());\n assertValidAggregateSpec(spec, \"groupBy().aggregate()\");\n\n const ast: IdbGroupByAst = {\n kind: \"groupBy\",\n modelName: init.modelName,\n by: init.by,\n aggregates: toAggregateRequests(spec),\n ...(init.where !== undefined ? { where: init.where } : {}),\n };\n\n const rows = await init.materialize(ast);\n\n // Partition rows by their composite group key, preserving first-seen order.\n const groups = new Map<string, { key: Record<string, unknown>; rows: Record<string, unknown>[] }>();\n for (const row of rows) {\n const gk = groupKeyOf(init.by, row);\n let group = groups.get(gk);\n if (group === undefined) {\n const key: Record<string, unknown> = {};\n for (const field of init.by) key[field] = row[field];\n group = { key, rows: [] };\n groups.set(gk, group);\n }\n group.rows.push(row);\n }\n\n return Array.from(groups.values()).map(\n (group) =>\n ({ ...group.key, ...computeAggregateSpec(spec, group.rows) }) as GroupedResultRow<\n TContract,\n ModelName,\n Fields,\n Spec\n >\n );\n },\n };\n}\n","/**\n * Applies `contract.execution.mutations.defaults` (ADR 158) during a\n * create/update — IDB's equivalent of the SQL family's\n * `ExecutionContext.applyMutationDefaults`.\n *\n * Semantics mirror the SQL reference implementation:\n * - a caller-provided value always wins over a default;\n * - an empty update patch skips every `onUpdate` default (no write ⇒ no\n * `@updatedAt` advance);\n * - `timestampNow`'s value is cached per call so a whole top-level mutation\n * call (e.g. a `createAll()` batch) shares one generated value across\n * every row it backs, matching its `'query'`-stability in SQL. Every other\n * generator (`literal`, `uuidv4`, `uuidv7`, `cuid2`) is deliberately *not*\n * cached — an id generator must produce a fresh, unique value per\n * resolution (both across rows in a batch and across distinct defaulted\n * fields on the same row), and a cache keyed only by generator id would\n * otherwise leak one field's/row's value onto the next.\n */\nimport type { ExecutionMutationDefault, ExecutionMutationDefaultValue } from \"@prisma/orm-framework/contract/types\";\nimport { generateId } from \"@prisma/orm-framework/ids/runtime\";\nimport type { IdbMutationDefaultGeneratorId } from \"@prisma-idb/target-idb/pack\";\n\n/** Per-top-level-mutation-call cache, keyed by generator id. Create one with {@link createMutationDefaultsCache}. */\nexport type MutationDefaultsCache = Map<string, unknown>;\n\nexport function createMutationDefaultsCache(): MutationDefaultsCache {\n return new Map();\n}\n\n/** Generator ids whose value is shared across an entire top-level call. Every other id always regenerates. */\nconst CACHEABLE_GENERATOR_IDS: ReadonlySet<IdbMutationDefaultGeneratorId> = new Set([\"timestampNow\"]);\n\nfunction computeGeneratedValue(spec: ExecutionMutationDefaultValue): unknown {\n const id = spec.id as IdbMutationDefaultGeneratorId;\n switch (id) {\n case \"timestampNow\":\n return new Date();\n case \"literal\":\n return spec.params?.[\"value\"];\n case \"uuidv4\":\n case \"uuidv7\":\n case \"cuid2\":\n return generateId(spec.params !== undefined ? { id, params: spec.params } : { id });\n default: {\n const _exhaustive: never = id;\n throw new Error(`Unknown mutation-default generator id \"${String(_exhaustive)}\"`);\n }\n }\n}\n\nfunction resolveGeneratedValue(spec: ExecutionMutationDefaultValue, cache: MutationDefaultsCache): unknown {\n const id = spec.id as IdbMutationDefaultGeneratorId;\n if (!CACHEABLE_GENERATOR_IDS.has(id)) return computeGeneratedValue(spec);\n const cached = cache.get(id);\n if (cached !== undefined) return cached;\n const value = computeGeneratedValue(spec);\n cache.set(id, value);\n return value;\n}\n\n/**\n * Fills in every column with an `onCreate` default that `data` doesn't\n * already set. Returns `data` unchanged (same reference) if there's nothing\n * to apply.\n */\nexport function applyCreateDefaults(\n defaults: readonly ExecutionMutationDefault[] | undefined,\n storeName: string,\n data: Record<string, unknown>,\n cache: MutationDefaultsCache\n): Record<string, unknown> {\n if (!defaults || defaults.length === 0) return data;\n let result = data;\n for (const d of defaults) {\n if (d.ref.table !== storeName || !d.onCreate) continue;\n if (result[d.ref.column] !== undefined) continue;\n if (result === data) result = { ...data };\n result[d.ref.column] = resolveGeneratedValue(d.onCreate, cache);\n }\n return result;\n}\n\n/**\n * Fills in every column with an `onUpdate` default that `patch` doesn't\n * already set. A patch with no defined values (empty, or every field\n * explicitly `undefined`) is returned unchanged — no write means no default\n * should fire either (matches SQL's \"empty update payloads skip onUpdate\n * defaults\" rule).\n */\nexport function applyUpdateDefaults(\n defaults: readonly ExecutionMutationDefault[] | undefined,\n storeName: string,\n patch: Record<string, unknown>,\n cache: MutationDefaultsCache\n): Record<string, unknown> {\n if (Object.values(patch).every((v) => v === undefined)) return patch;\n if (!defaults || defaults.length === 0) return patch;\n let result = patch;\n for (const d of defaults) {\n if (d.ref.table !== storeName || !d.onUpdate) continue;\n if (result[d.ref.column] !== undefined) continue;\n if (result === patch) result = { ...patch };\n result[d.ref.column] = resolveGeneratedValue(d.onUpdate, cache);\n }\n return result;\n}\n","import type { ContractReferenceRelation } from \"@prisma/orm-framework/contract/types\";\nimport { domainModelsAtDefaultNamespace } from \"@prisma/orm-framework/contract/types\";\nimport type { IdbQueryPlan } from \"@prisma-idb/adapter-idb/runtime\";\nimport { evaluateFilter } from \"@prisma-idb/adapter-idb/runtime\";\nimport type { IdbRowFilter } from \"@prisma-idb/driver-idb/runtime\";\nimport type { IdbQueryExecutor } from \"./executor\";\nimport { buildRowComparator, combineFilterExprs } from \"./query-shaping\";\nimport type { IncludeEntry } from \"./store-state\";\nimport { getIndexForField, getKeyPath, isValidIdbKey } from \"./types\";\nimport type { IdbContract } from \"./types\";\n\n/**\n * Batch-load a single named relation for all rows in `rows` and attach the\n * result to each row under the `relName` key.\n *\n * The join is done with one cursor scan over the related store (with an\n * in-memory filter), then grouped/indexed in memory — avoiding N+1 queries.\n *\n * The `entry` carries any `include()` refinement:\n *\n * - `collection` — the refined `where` further filters the child scan;\n * `orderBy` / `skip` / `take` are applied **per parent group** for `1:N`\n * relations (each parent's children are independently sorted and paginated).\n * - `scalar` — the relation field becomes the `count` of matching children\n * (to-many only; `include()` rejects scalar refinements on to-one relations).\n *\n * @param relName - The relation key to load (e.g. `\"posts\"`, `\"author\"`).\n * @param entry - How to materialise the relation (collection vs scalar + refinement state).\n * @param rows - The parent rows to attach related data to.\n * @param contract - The resolved IDB contract.\n * @param modelName - The source model name (owner of the relation).\n * @param executor - The query executor used to run the related-store scan.\n */\nexport async function loadRelation(\n relName: string,\n entry: IncludeEntry,\n rows: Record<string, unknown>[],\n contract: IdbContract,\n modelName: string,\n executor: IdbQueryExecutor,\n groupingKey: string\n): Promise<Record<string, unknown>[]> {\n if (rows.length === 0) return rows;\n\n const models = domainModelsAtDefaultNamespace(contract.domain);\n const model = models[modelName];\n if (model === undefined) return rows;\n\n const rawRelation = model.relations[relName];\n if (rawRelation === undefined) return rows;\n\n // Only handle reference relations (cross-store joins). Embed relations don't\n // have an `on` block and are stored inline — nothing to load.\n if (!(\"on\" in rawRelation)) return rows;\n\n const relation = rawRelation as ContractReferenceRelation;\n const { cardinality, on } = relation;\n // `relation.to` is a CrossReference `{ namespace, model }`.\n const relatedModelName = relation.to.model;\n\n const localField = on.localFields[0];\n const foreignField = on.targetFields[0];\n if (localField === undefined || foreignField === undefined) return rows;\n\n const relatedModel = models[relatedModelName];\n if (relatedModel === undefined) return rows;\n\n // Resolve the related object store name from the model's storage metadata.\n const relatedStoreName =\n typeof relatedModel.storage === \"object\" && relatedModel.storage !== null && \"storeName\" in relatedModel.storage\n ? String((relatedModel.storage as { storeName: unknown })[\"storeName\"])\n : relatedModelName;\n\n const isScalar = entry.kind === \"scalar\";\n\n // Collect all distinct local-field values to drive the in-memory filter.\n const localValues = new Set<unknown>();\n for (const row of rows) {\n const v = row[localField];\n if (v !== undefined && v !== null) localValues.add(v);\n }\n\n // Short-circuit: if all local values are null/undefined, attach empties.\n // (Scalar counts are 0; to-many is [], to-one is null.)\n if (localValues.size === 0) {\n return rows.map((row) => ({\n ...row,\n [relName]: isScalar ? 0 : cardinality === \"1:N\" ? [] : null,\n }));\n }\n\n const capturedForeignField = foreignField;\n const refinedWhere = combineFilterExprs(entry.state.filters);\n\n const storageHash = contract.storage.storageHash;\n const planMeta = { target: \"idb\", storageHash, lane: \"idb-orm\", annotations: { groupingKey } } as const;\n\n // When an IDB index exists on `foreignField` and IDBKeyRange is available,\n // run one IDBKeyRange.only() point-range scan per distinct FK value. Each\n // scan visits only records with that exact FK, so no membership re-check is\n // needed — only the refined `where` is applied as a row filter.\n // This is correct for any key type; the old bound-range heuristic used\n // JS lexicographic sort which produced wrong lo/hi for numeric keys.\n const fkIndexName =\n typeof IDBKeyRange !== \"undefined\" ? getIndexForField(contract, relatedStoreName, capturedForeignField) : undefined;\n\n // The related store's own primary key is never listed in its `indexes` map\n // (it doesn't need a named IDBIndex), but IDBObjectStore.openCursor(range)\n // scans the store's own keyPath directly — just as efficient as an index.\n // Without this, the very common N:1 case (e.g. `Post.author -> User.id`)\n // would miss acceleration entirely and fall back to a full store scan.\n const targetsRelatedPk =\n fkIndexName === undefined &&\n typeof IDBKeyRange !== \"undefined\" &&\n capturedForeignField === getKeyPath(contract, relatedModelName);\n\n let relatedRows: Record<string, unknown>[];\n if (fkIndexName !== undefined || targetsRelatedPk) {\n const refinedFilter: IdbRowFilter | undefined =\n refinedWhere !== undefined ? (row: Record<string, unknown>) => evaluateFilter(refinedWhere, row) : undefined;\n\n // IDBKeyRange.only() throws DataError for invalid keys (boolean, NaN,\n // plain objects, etc.). Such values cannot be stored as IndexedDB keys,\n // so no related rows can match — filter them out before building plans.\n const validValues = Array.from(localValues).filter(isValidIdbKey);\n\n // One index (or, for a PK target, store-keyspace) scan per distinct FK\n // value — independent, so run concurrently.\n const valueResults = await Promise.all(\n validValues.map(async (value) => {\n const plan: IdbQueryPlan<Record<string, unknown>> = {\n meta: planMeta,\n idbPlan: {\n meta: planMeta,\n kind: \"cursor-scan\",\n storeName: relatedStoreName,\n ...(fkIndexName !== undefined ? { indexName: fkIndexName } : {}),\n range: IDBKeyRange.only(value),\n ...(refinedFilter !== undefined ? { filter: refinedFilter } : {}),\n },\n };\n const rows: Record<string, unknown>[] = [];\n for await (const row of executor.query(plan)) {\n rows.push(row);\n }\n return rows;\n })\n );\n relatedRows = valueResults.flat();\n } else {\n relatedRows = [];\n // No index: full store scan with an in-memory FK membership + refined-where filter.\n const filter: IdbRowFilter = (row: Record<string, unknown>): boolean =>\n localValues.has(row[capturedForeignField]) && (refinedWhere === undefined || evaluateFilter(refinedWhere, row));\n const plan: IdbQueryPlan<Record<string, unknown>> = {\n meta: planMeta,\n idbPlan: { meta: planMeta, kind: \"cursor-scan\", storeName: relatedStoreName, filter },\n };\n for await (const row of executor.query(plan)) {\n relatedRows.push(row);\n }\n }\n\n // ── Merge ──────────────────────────────────────────────────────────────────\n\n if (cardinality === \"1:N\") {\n // Group related rows by their foreignField value.\n const grouped = new Map<unknown, Record<string, unknown>[]>();\n for (const rrow of relatedRows) {\n const gk = rrow[capturedForeignField];\n const group = grouped.get(gk) ?? [];\n group.push(rrow);\n grouped.set(gk, group);\n }\n\n if (isScalar) {\n // Scalar reducer (Phase 6.5: count) — attach the per-parent child count.\n return rows.map((row) => ({\n ...row,\n [relName]: (grouped.get(row[localField]) ?? []).length,\n }));\n }\n\n // Collection: apply refined orderBy / skip / take per parent group.\n const comparator = buildRowComparator(entry.state.orderBy);\n const skip = entry.state.skip ?? 0;\n const take = entry.state.take;\n return rows.map((row) => {\n let group = grouped.get(row[localField]) ?? [];\n if (comparator !== undefined) group = [...group].sort(comparator);\n if (skip > 0 || take !== undefined) {\n group = group.slice(skip, take !== undefined ? skip + take : undefined);\n }\n return { ...row, [relName]: group };\n });\n }\n\n // N:1 / 1:1: index related rows by their foreignField value, attach singles.\n // A refined `where` that excludes the related row yields `null` here.\n const indexed = new Map<unknown, Record<string, unknown>>();\n for (const rrow of relatedRows) {\n indexed.set(rrow[capturedForeignField], rrow);\n }\n return rows.map((row) => ({\n ...row,\n [relName]: indexed.get(row[localField]) ?? null,\n }));\n}\n","/**\n * Multi-store mutation scope for the IDB ORM.\n *\n * `withMutationScope` opens one IDB transaction spanning the named stores,\n * runs the callback with an `IdbTransactionScope` (raw driver-level execute),\n * then commits or rolls back depending on whether the callback throws.\n *\n * Pattern is a direct port of `withMutationScope` from\n * `sql-orm-client/mutation-executor.ts`, adapted for IDB's explicit\n * transaction scope API.\n *\n * @example\n * ```ts\n * await withMutationScope(runtime, [\"users\", \"posts\"], async (scope) => {\n * const userRow = await scope.execute({ kind: \"put\", storeName: \"users\", ... });\n * await scope.execute({ kind: \"put\", storeName: \"posts\", ... });\n * });\n * ```\n */\nimport type { IdbQueryExecutor } from \"./executor\";\nimport type { IdbTransactionScope } from \"@prisma-idb/driver-idb/runtime\";\n\n// ── Interface ─────────────────────────────────────────────────────────────────\n\n/**\n * Extends the basic {@link IdbQueryExecutor} with multi-store transaction\n * support. `IdbRuntime` satisfies this interface — `runtime.transaction()`\n * delegates to `driver.transaction()` which opens the IDB transaction.\n */\nexport interface IdbQueryExecutorWithTransaction extends IdbQueryExecutor {\n /**\n * Open a multi-store IDB transaction and return a scope object.\n *\n * The returned scope's `execute()` runs `IdbAtomicPlan`s directly inside\n * the transaction — no new transaction is opened per call, and the\n * middleware chain is bypassed. `commit()` resolves when `tx.oncomplete`\n * fires; `rollback()` calls `tx.abort()`.\n */\n transaction(storeNames: string[], mode?: IDBTransactionMode): Promise<IdbTransactionScope>;\n}\n\n// ── withMutationScope ─────────────────────────────────────────────────────────\n\n/**\n * Run a callback inside a single multi-store IDB readwrite transaction.\n *\n * Opens the transaction, passes the `IdbTransactionScope` to `run`, then:\n * - On success: awaits `scope.commit()` (waits for `tx.oncomplete`).\n * - On error: calls `scope.rollback()` and rethrows.\n *\n * The callback receives the low-level scope, not the ORM accessor.\n * Use this for multi-store atomic writes that span several object stores.\n */\nexport async function withMutationScope<T>(\n executor: IdbQueryExecutorWithTransaction,\n storeNames: string[],\n run: (scope: IdbTransactionScope) => Promise<T>\n): Promise<T> {\n const tx = await executor.transaction(storeNames, \"readwrite\");\n try {\n const result = await run(tx);\n await tx.commit();\n return result;\n } catch (err) {\n tx.rollback();\n throw err;\n }\n}\n","/**\n * IDB relation mutator factory and type guards.\n *\n * Port of `sql-orm-client/relation-mutator.ts` — same pattern, IDB types only.\n * The mutator object is passed to user-supplied relation callbacks so they can\n * express nested writes in a type-safe, intent-revealing way.\n *\n * @example\n * ```ts\n * orm.users.create({\n * id: \"u1\",\n * name: \"Alice\",\n * posts: (rel) => rel.create([{ id: \"p1\", title: \"Hello\" }]),\n * });\n * ```\n */\nimport type {\n CreateInput,\n IdbContract,\n IdbRelationMutation,\n IdbRelationMutator,\n RelationMutationConnect,\n RelationMutationCreate,\n RelationMutationDisconnect,\n} from \"./types\";\n\nexport function createRelationMutator<TContract extends IdbContract, ModelName extends string>(): IdbRelationMutator<\n TContract,\n ModelName\n> {\n return {\n create(\n data: CreateInput<TContract, ModelName> | readonly CreateInput<TContract, ModelName>[]\n ): RelationMutationCreate<TContract, ModelName> {\n const rows = Array.isArray(data) ? [...data] : [data];\n return { kind: \"create\", data: rows as readonly CreateInput<TContract, ModelName>[] };\n },\n\n connect(criteria: Record<string, unknown> | readonly Record<string, unknown>[]): RelationMutationConnect {\n const values = Array.isArray(criteria) ? [...criteria] : [criteria];\n return { kind: \"connect\", criteria: values };\n },\n\n disconnect(criteria?: readonly Record<string, unknown>[]): RelationMutationDisconnect {\n if (!criteria) return { kind: \"disconnect\" };\n return { kind: \"disconnect\", criteria: [...criteria] };\n },\n };\n}\n\nexport function isRelationMutationDescriptor(value: unknown): value is IdbRelationMutation<IdbContract, string> {\n if (!value || typeof value !== \"object\") return false;\n const candidate = value as { kind?: unknown };\n return candidate.kind === \"create\" || candidate.kind === \"connect\" || candidate.kind === \"disconnect\";\n}\n\nexport function isRelationMutationCallback(\n value: unknown\n): value is (mutator: IdbRelationMutator<IdbContract, string>) => IdbRelationMutation<IdbContract, string> {\n return typeof value === \"function\";\n}\n","/**\n * IDB nested-write executor.\n *\n * IDB adaptation of `sql-orm-client/mutation-executor.ts`. Key differences\n * from the SQL vendor:\n *\n * - No column/field mapping — IDB field names ARE the storage keys.\n * - `applyCreateDefaults`/`applyUpdateDefaults` (`mutation-defaults.ts`) fill\n * in every generator id `contract.execution.mutations.defaults` declares\n * (see `IdbMutationDefaultGeneratorId`) — IDB has no server-rendered\n * defaults, so this always runs client-side, unlike SQL's storage-plane\n * `ColumnDefault`.\n * - `insertSingleRow` → `scope.execute({ kind: \"add\", ... })`.\n * - `findRowByCriterion` / `findFirstByFilters` → `scope.execute({ kind: \"cursor-scan\", ... })`.\n * IDB allows reads inside a readwrite transaction; the transaction scope accepts\n * all `IdbAtomicPlan` types including `cursor-scan`.\n * - Child-owned `connect` → `scope.execute({ kind: \"scan-write\", write: \"put-merged\", ... })`.\n * IDB has no UPDATE SET WHERE, so we use the scan-write plan with a filter closure.\n * - `connect()` for parent-owned (N:1) relations throws if the referenced row is not\n * found — this is Phase 6.4's implicit FK validation for the connect case.\n * - Recursive nesting (nested writes inside nested writes) is not supported and throws.\n *\n * All multi-store writes are wrapped in a single `withMutationScope` call that opens\n * one IDB transaction spanning all required stores, per ADR 007.\n */\n\nimport type { PlanMeta } from \"@prisma/orm-framework/contract/types\";\nimport type { ContractReferenceRelation } from \"@prisma/orm-framework/contract/types\";\nimport { domainModelsAtDefaultNamespace } from \"@prisma/orm-framework/contract/types\";\nimport type { IdbAtomicPlan, IdbCursorScanPlan } from \"@prisma-idb/driver-idb/runtime\";\nimport { evaluateFilter, shorthandToFilterExpr } from \"@prisma-idb/adapter-idb/runtime\";\nimport type { IdbFilterExpr } from \"@prisma-idb/adapter-idb/runtime\";\nimport type { IdbReferentialAction } from \"@prisma-idb/target-idb/pack\";\nimport type { IdbQueryExecutor } from \"./executor\";\nimport {\n applyCreateDefaults,\n applyUpdateDefaults,\n createMutationDefaultsCache,\n type MutationDefaultsCache,\n} from \"./mutation-defaults\";\nimport { withMutationScope, type IdbQueryExecutorWithTransaction } from \"./mutation-scope\";\nimport { createRelationMutator, isRelationMutationCallback, isRelationMutationDescriptor } from \"./relation-mutator\";\nimport {\n type IdbContract,\n type IdbRelationMutation,\n type IdbRelationMutator,\n type MutationCreateInput,\n type MutationUpdateInput,\n getStoreName,\n} from \"./types\";\nimport type { IdbTransactionScope } from \"@prisma-idb/driver-idb/runtime\";\n\n// ── Internal types ─────────────────────────────────────────────────────────────\n\ninterface RelationDefinition {\n readonly relationName: string;\n readonly relatedModelName: string;\n readonly relatedStoreName: string;\n readonly cardinality: string | undefined;\n readonly localFields: readonly string[];\n readonly targetFields: readonly string[];\n}\n\ninterface ParsedRelationMutation {\n readonly relation: RelationDefinition;\n readonly mutation: IdbRelationMutation<IdbContract, string>;\n}\n\ninterface ParsedMutationInput {\n readonly scalarData: Record<string, unknown>;\n readonly relationMutations: readonly ParsedRelationMutation[];\n}\n\n// ── Plan meta helpers ─────────────────────────────────────────────────────────\n\nfunction makePlanMeta(contract: IdbContract): PlanMeta {\n return {\n target: \"idb\",\n storageHash: contract.storage.storageHash,\n lane: \"idb-mutation-executor\",\n annotations: { groupingKey: \"nested\" },\n };\n}\n\n// ── Relation definition resolution (cached) ──────────────────────────────────\n\nconst relationDefsCache = new WeakMap<object, Map<string, RelationDefinition[]>>();\n\nfunction getRelationDefinitions(contract: IdbContract, modelName: string): RelationDefinition[] {\n let perContract = relationDefsCache.get(contract);\n if (!perContract) {\n perContract = new Map();\n relationDefsCache.set(contract, perContract);\n }\n\n const cached = perContract.get(modelName);\n if (cached) return cached;\n\n const model = domainModelsAtDefaultNamespace(contract.domain)[modelName];\n if (!model) {\n perContract.set(modelName, []);\n return [];\n }\n\n const defs: RelationDefinition[] = [];\n for (const [relationName, rawRelation] of Object.entries(model.relations)) {\n if (!rawRelation || typeof rawRelation !== \"object\" || !(\"on\" in rawRelation)) continue;\n\n const relation = rawRelation as ContractReferenceRelation;\n // `relation.to` is a CrossReference `{ namespace, model }`.\n const relatedModelName = relation.to.model;\n const relatedStoreName = getStoreName(contract, relatedModelName);\n defs.push({\n relationName,\n relatedModelName,\n relatedStoreName,\n cardinality: relation.cardinality,\n localFields: relation.on.localFields,\n targetFields: relation.on.targetFields,\n });\n }\n\n perContract.set(modelName, defs);\n return defs;\n}\n\n// ── Public helpers ────────────────────────────────────────────────────────────\n\n/**\n * Returns true if `data` contains at least one field that is both a known\n * relation name for `modelName` and a function (a mutation callback).\n */\nexport function hasNestedMutationCallbacks(\n contract: IdbContract,\n modelName: string,\n data: Record<string, unknown>\n): boolean {\n const relationNames = new Set(getRelationDefinitions(contract, modelName).map((r) => r.relationName));\n for (const [fieldName, value] of Object.entries(data)) {\n if (relationNames.has(fieldName) && isRelationMutationCallback(value)) return true;\n }\n return false;\n}\n\n/**\n * Guards that the executor supports multi-store transactions.\n * Throws a clear error if `transaction()` is not available — the user must\n * use IdbRuntime (createIdbRuntime / createAutoMigratingIdbClient) rather than\n * a plain IdbQueryExecutor stub.\n */\nexport function requireTransactionExecutor(executor: IdbQueryExecutor): IdbQueryExecutorWithTransaction {\n if (typeof (executor as IdbQueryExecutorWithTransaction).transaction !== \"function\") {\n throw new Error(\n \"This operation requires an executor with transaction support (nested relation writes, \" +\n \"FK-validated create/update, and referential-action delete all need it). \" +\n \"Use IdbRuntime (createIdbRuntime or createAutoMigratingIdbClient) instead of a plain IdbQueryExecutor.\"\n );\n }\n return executor as IdbQueryExecutorWithTransaction;\n}\n\n// ── Entry points ──────────────────────────────────────────────────────────────\n\nexport async function executeNestedCreateMutation(options: {\n executor: IdbQueryExecutorWithTransaction;\n contract: IdbContract;\n modelName: string;\n data: MutationCreateInput<IdbContract, string>;\n}): Promise<Record<string, unknown>> {\n const { executor, contract, modelName, data } = options;\n const record = data as Record<string, unknown>;\n const storeNames = collectStoreNames(contract, modelName, record);\n const defaultsCache = createMutationDefaultsCache();\n return withMutationScope(executor, storeNames, (scope) =>\n createGraph(scope, contract, modelName, record, defaultsCache)\n );\n}\n\nexport async function executeNestedUpdateMutation(options: {\n executor: IdbQueryExecutorWithTransaction;\n contract: IdbContract;\n modelName: string;\n filters: readonly IdbFilterExpr[];\n data: MutationUpdateInput<IdbContract, string>;\n}): Promise<Record<string, unknown> | null> {\n const { executor, contract, modelName, filters, data } = options;\n const record = data as Record<string, unknown>;\n const storeNames = collectStoreNames(contract, modelName, record);\n const defaultsCache = createMutationDefaultsCache();\n return withMutationScope(executor, storeNames, (scope) =>\n updateFirstGraph(scope, contract, modelName, filters, record, defaultsCache)\n );\n}\n\n// ── Store name collection ─────────────────────────────────────────────────────\n\nfunction collectStoreNames(contract: IdbContract, modelName: string, data: Record<string, unknown>): string[] {\n const stores = new Set([getStoreName(contract, modelName)]);\n for (const def of getRelationDefinitions(contract, modelName)) {\n if (def.relationName in data && isRelationMutationCallback(data[def.relationName])) {\n stores.add(def.relatedStoreName);\n }\n }\n return [...stores];\n}\n\n// ── Graph operations ──────────────────────────────────────────────────────────\n\nasync function createGraph(\n scope: IdbTransactionScope,\n contract: IdbContract,\n modelName: string,\n input: Record<string, unknown>,\n defaultsCache: MutationDefaultsCache\n): Promise<Record<string, unknown>> {\n const parsed = parseMutationInput(contract, modelName, input);\n const { parentOwned, childOwned } = partitionByOwnership(parsed.relationMutations);\n\n const scalarData = { ...parsed.scalarData };\n\n for (const item of parentOwned) {\n if (item.mutation.kind === \"disconnect\") {\n throw new Error(\"disconnect() is only supported in update() nested mutations\");\n }\n await applyParentOwnedMutation(scope, contract, modelName, scalarData, item.relation, item.mutation, defaultsCache);\n }\n\n const parentRow = await insertSingleRow(scope, contract, modelName, scalarData, defaultsCache);\n\n for (const item of childOwned) {\n if (item.mutation.kind === \"disconnect\") {\n throw new Error(\"disconnect() is only supported in update() nested mutations\");\n }\n await applyChildOwnedMutation(scope, contract, modelName, parentRow, item.relation, item.mutation, defaultsCache);\n }\n\n return parentRow;\n}\n\nasync function updateFirstGraph(\n scope: IdbTransactionScope,\n contract: IdbContract,\n modelName: string,\n filters: readonly IdbFilterExpr[],\n input: Record<string, unknown>,\n defaultsCache: MutationDefaultsCache\n): Promise<Record<string, unknown> | null> {\n const existingRow = await findFirstByFilters(scope, contract, modelName, filters);\n if (!existingRow) return null;\n\n const parsed = parseMutationInput(contract, modelName, input);\n const { parentOwned, childOwned } = partitionByOwnership(parsed.relationMutations);\n\n const scalarData = { ...parsed.scalarData };\n\n for (const item of parentOwned) {\n await applyParentOwnedMutation(scope, contract, modelName, scalarData, item.relation, item.mutation, defaultsCache);\n }\n\n let parentRow = existingRow;\n\n if (Object.keys(scalarData).length > 0) {\n const storeName = getStoreName(contract, modelName);\n const keyPath = getKeyPath(contract, modelName);\n const key = existingRow[keyPath] as IDBValidKey;\n const meta = makePlanMeta(contract);\n const patch = applyUpdateDefaults(contract.execution?.mutations.defaults, storeName, scalarData, defaultsCache);\n const rows = await scope.execute({ meta, kind: \"update\", storeName, key, patch });\n const updated = rows[0];\n if (updated) parentRow = updated;\n }\n\n for (const item of childOwned) {\n await applyChildOwnedMutation(scope, contract, modelName, parentRow, item.relation, item.mutation, defaultsCache);\n }\n\n return parentRow;\n}\n\n// ── Input parsing ─────────────────────────────────────────────────────────────\n\nfunction parseMutationInput(\n contract: IdbContract,\n modelName: string,\n input: Record<string, unknown>\n): ParsedMutationInput {\n const scalarData: Record<string, unknown> = {};\n const relationDefs = new Map(getRelationDefinitions(contract, modelName).map((r) => [r.relationName, r]));\n const relationMutations: ParsedRelationMutation[] = [];\n\n for (const [fieldName, value] of Object.entries(input)) {\n const relation = relationDefs.get(fieldName);\n if (!relation) {\n scalarData[fieldName] = value;\n continue;\n }\n\n if (!isRelationMutationCallback(value)) {\n throw new Error(`Relation field \"${fieldName}\" on model \"${modelName}\" expects a mutator callback`);\n }\n\n const mutator = createRelationMutator<IdbContract, string>();\n const mutation = value(mutator as IdbRelationMutator<IdbContract, string>);\n if (!isRelationMutationDescriptor(mutation)) {\n throw new Error(`Relation field \"${fieldName}\" on model \"${modelName}\" returned an invalid mutation descriptor`);\n }\n\n relationMutations.push({ relation, mutation });\n }\n\n return { scalarData, relationMutations };\n}\n\n// ── Ownership partitioning ────────────────────────────────────────────────────\n\nfunction partitionByOwnership(mutations: readonly ParsedRelationMutation[]): {\n parentOwned: ParsedRelationMutation[];\n childOwned: ParsedRelationMutation[];\n} {\n const parentOwned: ParsedRelationMutation[] = [];\n const childOwned: ParsedRelationMutation[] = [];\n\n for (const item of mutations) {\n if (item.relation.cardinality === \"N:1\") {\n parentOwned.push(item);\n continue;\n }\n if (item.relation.cardinality === \"M:N\") {\n throw new Error(\"M:N nested mutations are not supported\");\n }\n childOwned.push(item);\n }\n\n return { parentOwned, childOwned };\n}\n\n// ── Parent-owned (N:1) mutations ──────────────────────────────────────────────\n\nasync function applyParentOwnedMutation(\n scope: IdbTransactionScope,\n contract: IdbContract,\n parentModelName: string,\n scalarData: Record<string, unknown>,\n relation: RelationDefinition,\n mutation: IdbRelationMutation<IdbContract, string>,\n defaultsCache: MutationDefaultsCache\n): Promise<void> {\n if (mutation.kind === \"disconnect\") {\n for (const localField of relation.localFields) {\n scalarData[localField] = null;\n }\n return;\n }\n\n if (mutation.kind === \"create\") {\n const row = mutation.data[0] as Record<string, unknown> | undefined;\n if (!row) {\n throw new Error(`create() nested mutation for relation \"${relation.relationName}\" requires data`);\n }\n // Recursive nesting is not supported in Phase 6.4 — the nested record must\n // be a plain scalar create, not itself a nested mutation.\n const relatedRow = await insertSingleRow(scope, contract, relation.relatedModelName, row, defaultsCache);\n copyRelatedValuesToParent(relation, scalarData, relatedRow, parentModelName, contract);\n return;\n }\n\n // connect()\n const criterion = mutation.criteria[0] as Record<string, unknown> | undefined;\n if (!criterion) {\n throw new Error(`connect() nested mutation for relation \"${relation.relationName}\" requires a criterion`);\n }\n const relatedRow = await findRowByCriterion(scope, contract, relation.relatedModelName, criterion);\n if (!relatedRow) {\n throw new Error(`connect() nested mutation for relation \"${relation.relationName}\" did not find a matching row`);\n }\n copyRelatedValuesToParent(relation, scalarData, relatedRow, parentModelName, contract);\n}\n\nfunction copyRelatedValuesToParent(\n relation: RelationDefinition,\n scalarData: Record<string, unknown>,\n relatedRow: Record<string, unknown>,\n _parentModelName: string,\n _contract: IdbContract\n): void {\n // localFields = parent's FK fields; targetFields = related model's PK/unique fields\n for (let i = 0; i < relation.localFields.length; i++) {\n const localField = relation.localFields[i];\n const targetField = relation.targetFields[i];\n if (!localField || !targetField) continue;\n scalarData[localField] = relatedRow[targetField];\n }\n}\n\n// ── Child-owned (1:N / 1:1) mutations ────────────────────────────────────────\n\nasync function applyChildOwnedMutation(\n scope: IdbTransactionScope,\n contract: IdbContract,\n parentModelName: string,\n parentRow: Record<string, unknown>,\n relation: RelationDefinition,\n mutation: IdbRelationMutation<IdbContract, string>,\n defaultsCache: MutationDefaultsCache\n): Promise<void> {\n // parentValues: childFkField → parentPkValue (e.g. \"authorId\" → \"u1\")\n const parentValues = readParentColumnValues(parentModelName, relation, parentRow);\n\n if (mutation.kind === \"create\") {\n for (const childInput of mutation.data) {\n const payload: Record<string, unknown> = { ...(childInput as Record<string, unknown>) };\n for (const [childField, parentValue] of parentValues.entries()) {\n payload[childField] = parentValue;\n }\n await insertSingleRow(scope, contract, relation.relatedModelName, payload, defaultsCache);\n }\n return;\n }\n\n if (mutation.kind === \"connect\") {\n for (const criterion of mutation.criteria) {\n const setValues: Record<string, unknown> = {};\n for (const [childField, parentValue] of parentValues.entries()) {\n setValues[childField] = parentValue;\n }\n const patch = applyUpdateDefaults(\n contract.execution?.mutations.defaults,\n relation.relatedStoreName,\n setValues,\n defaultsCache\n );\n const filter = buildCriterionFilter(criterion as Record<string, unknown>);\n const meta = makePlanMeta(contract);\n // scan-write + put-merged: set the FK fields on every child row matching\n // the criterion. No `take` cap — the vendor's relational connect\n // (`executeUpdateCount`) connects all matching rows; for the normal\n // unique-key criterion that is exactly one row anyway. (PLAN Issue #24.)\n await scope.execute({\n meta,\n kind: \"scan-write\",\n storeName: relation.relatedStoreName,\n write: \"put-merged\",\n patch,\n filter,\n });\n }\n return;\n }\n\n // disconnect()\n const setValues: Record<string, unknown> = {};\n for (const childField of parentValues.keys()) {\n setValues[childField] = null;\n }\n const meta = makePlanMeta(contract);\n\n if (!mutation.criteria || mutation.criteria.length === 0) {\n // Disconnect all children of this parent.\n const patch = applyUpdateDefaults(\n contract.execution?.mutations.defaults,\n relation.relatedStoreName,\n setValues,\n defaultsCache\n );\n const parentJoinFilter = buildParentJoinFilter(parentValues);\n await scope.execute({\n meta,\n kind: \"scan-write\",\n storeName: relation.relatedStoreName,\n write: \"put-merged\",\n patch,\n filter: parentJoinFilter,\n });\n return;\n }\n\n // Disconnect specific children matching each criterion AND the parent join.\n for (const criterion of mutation.criteria) {\n const patch = applyUpdateDefaults(\n contract.execution?.mutations.defaults,\n relation.relatedStoreName,\n setValues,\n defaultsCache\n );\n const criterionFilter = buildCriterionFilter(criterion as Record<string, unknown>);\n const parentJoinFilter = buildParentJoinFilter(parentValues);\n const combinedFilter = (row: Record<string, unknown>): boolean => parentJoinFilter(row) && criterionFilter(row);\n await scope.execute({\n meta,\n kind: \"scan-write\",\n storeName: relation.relatedStoreName,\n write: \"put-merged\",\n patch,\n filter: combinedFilter,\n });\n }\n}\n\nfunction readParentColumnValues(\n parentModelName: string,\n relation: RelationDefinition,\n parentRow: Record<string, unknown>\n): Map<string, unknown> {\n const values = new Map<string, unknown>();\n // For 1:N: localFields = parent PK fields; targetFields = child FK fields\n for (let i = 0; i < relation.localFields.length; i++) {\n const localField = relation.localFields[i];\n const targetField = relation.targetFields[i];\n if (!localField || !targetField) continue;\n const parentValue = parentRow[localField];\n if (parentValue === undefined) {\n throw new Error(\n `Nested mutation requires parent field \"${localField}\" to be present in \"${parentModelName}\" row`\n );\n }\n // targetField is the child's FK column name; map it to the parent's value.\n values.set(targetField, parentValue);\n }\n return values;\n}\n\n// ── Row operations ────────────────────────────────────────────────────────────\n\nasync function insertSingleRow(\n scope: IdbTransactionScope,\n contract: IdbContract,\n modelName: string,\n data: Record<string, unknown>,\n defaultsCache: MutationDefaultsCache\n): Promise<Record<string, unknown>> {\n assertNoNestedCallbacks(modelName, data);\n const storeName = getStoreName(contract, modelName);\n const meta = makePlanMeta(contract);\n const record = applyCreateDefaults(contract.execution?.mutations.defaults, storeName, data, defaultsCache);\n const rows = await scope.execute({ meta, kind: \"add\", storeName, record });\n return rows[0] ?? record;\n}\n\n/**\n * Recursive nesting (a relation callback inside an already-nested create) is\n * not supported in Phase 6.4. Without this guard the callback function would be\n * handed to `store.put(...)`, where IDB's structured-clone throws an opaque\n * `DataCloneError` (\"could not be cloned\") that gives the developer no hint\n * about the real cause. Surface a precise error instead. (PLAN Issue #22.)\n */\nfunction assertNoNestedCallbacks(modelName: string, data: Record<string, unknown>): void {\n for (const [field, value] of Object.entries(data)) {\n if (typeof value === \"function\") {\n throw new Error(\n `Recursive nested writes are not supported: field \"${field}\" on a nested \"${modelName}\" ` +\n \"record is a relation callback. Only one level of relation nesting is supported — \" +\n \"flatten the inner relation into a separate create/connect call.\"\n );\n }\n }\n}\n\nasync function findRowByCriterion(\n scope: IdbTransactionScope,\n contract: IdbContract,\n modelName: string,\n criterion: Record<string, unknown>\n): Promise<Record<string, unknown> | null> {\n const expr = shorthandToFilterExpr(criterion);\n if (!expr) {\n throw new Error(`Nested connect for model \"${modelName}\" requires a non-empty criterion`);\n }\n const filter = (row: Record<string, unknown>): boolean => evaluateFilter(expr, row);\n return scanOneRow(scope, contract, modelName, filter);\n}\n\nasync function findFirstByFilters(\n scope: IdbTransactionScope,\n contract: IdbContract,\n modelName: string,\n filters: readonly IdbFilterExpr[]\n): Promise<Record<string, unknown> | null> {\n if (filters.length === 0) return null;\n const combined = filters.length === 1 ? filters[0]! : { kind: \"and\" as const, exprs: filters };\n const filter = (row: Record<string, unknown>): boolean => evaluateFilter(combined, row);\n return scanOneRow(scope, contract, modelName, filter);\n}\n\nasync function scanOneRow(\n scope: IdbTransactionScope,\n contract: IdbContract,\n modelName: string,\n filter: (row: Record<string, unknown>) => boolean\n): Promise<Record<string, unknown> | null> {\n const storeName = getStoreName(contract, modelName);\n const meta = makePlanMeta(contract);\n const plan: IdbCursorScanPlan = { meta, kind: \"cursor-scan\", storeName, filter, take: 1 };\n const rows = await scope.execute(plan as IdbAtomicPlan);\n return rows[0] ?? null;\n}\n\n// ── Filter helpers ────────────────────────────────────────────────────────────\n\nfunction buildCriterionFilter(criterion: Record<string, unknown>): (row: Record<string, unknown>) => boolean {\n const expr = shorthandToFilterExpr(criterion);\n if (!expr) return () => true;\n return (row) => evaluateFilter(expr, row);\n}\n\nfunction buildParentJoinFilter(parentValues: Map<string, unknown>): (row: Record<string, unknown>) => boolean {\n const pairs = [...parentValues.entries()];\n return (row: Record<string, unknown>): boolean =>\n pairs.every(([childField, parentValue]) => row[childField] === parentValue);\n}\n\n// ── Key path helper ───────────────────────────────────────────────────────────\n\nfunction getKeyPath(contract: IdbContract, modelName: string): string {\n const model = domainModelsAtDefaultNamespace(contract.domain)[modelName];\n return (model?.storage as { keyPath?: string } | undefined)?.keyPath ?? \"id\";\n}\n\n// ── Referential action helpers ────────────────────────────────────────────────\n\n/**\n * Which referential-action slot to read from `IdbRelationStorage`. Shared by\n * `onDelete` enforcement (delete/deleteAll/deleteCount) and `onUpdate`\n * enforcement (update/updateAll/updateCount/upsert) — both actions are\n * declared and resolved identically, just stored under a different key.\n */\ntype ReferentialActionKind = \"onDelete\" | \"onUpdate\";\n\nfunction getStoredAction(\n contract: IdbContract,\n modelName: string,\n relationName: string,\n kind: ReferentialActionKind\n): IdbReferentialAction | undefined {\n const model = domainModelsAtDefaultNamespace(contract.domain)[modelName];\n const storage = model?.storage as\n { relations?: Record<string, { onDelete?: string; onUpdate?: string }> } | undefined;\n return storage?.relations?.[relationName]?.[kind] as IdbReferentialAction | undefined;\n}\n\nfunction sameFields(a: readonly string[], b: readonly string[]): boolean {\n return a.length === b.length && a.every((field, index) => field === b[index]);\n}\n\n/**\n * Resolves the referential action for a child-enforcement relation: prefers\n * the action stored directly on this side, falls back to the same action\n * stored on the inverse (FK-owning) side of the relation, and finally to\n * `defaultAction` when neither side declares one.\n *\n * Both branches are live, for different authoring paths. PSL only ever\n * stores the action on the `N:1` (FK-owning) side — enforcement always walks\n * from the parent (`1:N`/non-owning-`1:1`) side, which PSL leaves bare, so\n * the fallback is what actually finds it. TS-DSL relation entries are\n * self-contained (no PSL-style pairing requirement) and typically declare\n * the action directly on the side this function is called for, so the direct\n * check is what fires there — see `contract-builder.ts`'s\n * `validateNoConflictingRelationActions`, which rejects declaring the same\n * action kind on both sides so this fallback never has to arbitrate a real\n * conflict.\n */\nfunction getReferentialActionForRelation(\n contract: IdbContract,\n modelName: string,\n def: RelationDefinition,\n kind: ReferentialActionKind,\n defaultAction: IdbReferentialAction\n): IdbReferentialAction {\n const direct = getStoredAction(contract, modelName, def.relationName, kind);\n if (direct !== undefined) return direct;\n\n for (const inverse of getRelationDefinitions(contract, def.relatedModelName)) {\n if (inverse.relatedModelName !== modelName) continue;\n if (!sameFields(inverse.localFields, def.targetFields)) continue;\n if (!sameFields(inverse.targetFields, def.localFields)) continue;\n\n const inverseAction = getStoredAction(contract, def.relatedModelName, inverse.relationName, kind);\n if (inverseAction !== undefined) return inverseAction;\n }\n\n return defaultAction;\n}\n\nfunction getOnDeleteForDeleteRelation(\n contract: IdbContract,\n modelName: string,\n def: RelationDefinition\n): IdbReferentialAction {\n return getReferentialActionForRelation(contract, modelName, def, \"onDelete\", \"restrict\");\n}\n\n/**\n * `onUpdate`'s default (when neither side declares one) is `cascade`, unlike\n * `onDelete`'s `restrict` default — this matches Prisma's own documented\n * behavior: propagating a changed referenced value to children is normally\n * safe, unlike deleting the row those children point to.\n */\nfunction getOnUpdateForRelation(\n contract: IdbContract,\n modelName: string,\n def: RelationDefinition\n): IdbReferentialAction {\n return getReferentialActionForRelation(contract, modelName, def, \"onUpdate\", \"cascade\");\n}\n\nfunction isDeleteEnforcementRelation(contract: IdbContract, modelName: string, def: RelationDefinition): boolean {\n if (def.cardinality === \"1:N\") return true;\n if (def.cardinality === \"1:1\") {\n const keyPath = getKeyPath(contract, modelName);\n return def.localFields.length > 0 && def.localFields[0] === keyPath;\n }\n return false;\n}\n\n/**\n * Builds a filter matching a relation's children against one specific parent\n * row's values. Shared by `onDelete` cascade (`applyReferentialActionsForRow`)\n * and `onUpdate` cascade (`applyReferentialActionsForRowOnUpdate`).\n */\nfunction buildChildFilterFromRow(\n def: RelationDefinition,\n row: Record<string, unknown>\n): (child: Record<string, unknown>) => boolean {\n const pairs = def.localFields.map((lf, i) => ({ childField: def.targetFields[i]!, parentValue: row[lf] }));\n return (child: Record<string, unknown>): boolean =>\n pairs.every(({ childField, parentValue }) => child[childField] === parentValue);\n}\n\n/** Reads a field's literal `@default(...)` value from `IdbModelStorage.fieldDefaults`, if declared. */\nfunction getFieldDefault(contract: IdbContract, modelName: string, fieldName: string): unknown {\n const model = domainModelsAtDefaultNamespace(contract.domain)[modelName];\n const storage = model?.storage as { fieldDefaults?: Record<string, unknown> } | undefined;\n return storage?.fieldDefaults?.[fieldName];\n}\n\n/**\n * Builds the patch for a `setDefault` referential action: each of the\n * relation's `targetFields` (the child's FK fields) reset to its own\n * declared literal default — not the parent's. Throws when any target field\n * has no declared default; `setDefault` is only meaningful when every FK\n * field it resets has somewhere to reset to.\n */\nfunction buildSetDefaultPatch(contract: IdbContract, def: RelationDefinition): Record<string, unknown> {\n const patch: Record<string, unknown> = {};\n for (const targetField of def.targetFields) {\n const value = getFieldDefault(contract, def.relatedModelName, targetField);\n if (value === undefined) {\n throw new Error(\n `setDefault referential action on relation '${def.relationName}' requires field ` +\n `'${def.relatedModelName}.${targetField}' to declare a literal @default(...) value — ` +\n \"no default is registered for that field.\"\n );\n }\n patch[targetField] = value;\n }\n return patch;\n}\n\n/**\n * Validates that a `setDefault` patch actually references a real row before\n * it's written — without this, `setDefault` would silently reintroduce the\n * exact dangling-FK problem the rest of this file exists to prevent. A real\n * SQL database only makes `SET DEFAULT` safe because its FK constraint\n * re-checks the new value transactionally at write time; IDB has no such\n * engine to delegate to, so this check is IDB's equivalent.\n *\n * Checks against `modelName`'s own store (the parent being deleted/updated)\n * using `def.localFields` — the relation's own semantics (\"child.targetField\n * references parent.localField\") mean that's exactly what a default value\n * written to the child's FK field must match. That store is always already\n * part of the transaction (it's the model literally being written), so no\n * store-list changes are needed to call this.\n *\n * Refuses (throws) rather than validates incorrectly for compound (multi-\n * field) relations, for the same reason `validateScalarFks` does: each\n * field's default is resolved independently, so there's no guarantee the\n * combination corresponds to a single real row.\n *\n * `excludeKey`, when given, excludes the parent row currently being\n * deleted/updated from the existence scan. That row is still physically\n * present in the store at this point (its own write/delete hasn't happened\n * yet — this check runs first, before the enforcement loop's caller applies\n * it), so without the exclusion, a default value equal to that row's *old*\n * `localField` value would false-positive: the scan would find the row about\n * to disappear (or change away from that value) and wrongly conclude the\n * default references a real row, when after the transaction nothing will.\n */\nasync function validateSetDefaultPatch(\n scope: IdbTransactionScope,\n contract: IdbContract,\n modelName: string,\n def: RelationDefinition,\n patch: Record<string, unknown>,\n excludeKey?: IDBValidKey\n): Promise<void> {\n if (def.localFields.length > 1) {\n throw new Error(\n `setDefault referential action on relation '${def.relationName}' cannot validate a compound (multi-field) ` +\n \"default: each field's default is resolved independently, so there is no guarantee the combination \" +\n \"corresponds to a single real row.\"\n );\n }\n\n const meta = makePlanMeta(contract);\n const parentStoreName = getStoreName(contract, modelName);\n const parentKeyPath = getKeyPath(contract, modelName);\n const localField = def.localFields[0]!;\n const targetField = def.targetFields[0]!;\n const value = patch[targetField];\n const filter = (row: Record<string, unknown>): boolean =>\n row[localField] === value && (excludeKey === undefined || row[parentKeyPath] !== excludeKey);\n const found = await scope.execute({\n meta,\n kind: \"cursor-scan\",\n storeName: parentStoreName,\n filter,\n take: 1,\n } as IdbAtomicPlan);\n if (found.length === 0) {\n throw new Error(\n `setDefault referential action on relation '${def.relationName}' would set ` +\n `'${def.relatedModelName}.${targetField}' to '${String(value)}', but no ${modelName} with ` +\n `${localField}='${String(value)}' exists — the declared default does not reference a real row.`\n );\n }\n}\n\n// ── Update referential action enforcement ─────────────────────────────────────\n\n/**\n * Collects every store an `onUpdate`-enforced write to `modelName` might\n * touch: the model's own store, plus the related store of any 1:N/1:1-\n * parent-side relation whose `localFields` appear in the raw patch —\n * pessimistic (checks field *presence*, not whether the resolved value will\n * actually change, since the current row isn't read yet when this runs).\n * Once a `cascade` edge is entered, the walk continues transitively (mirrors\n * `collectDeleteStoreNames`'s cascade-only recursion), since a propagated\n * value change may itself need to cascade further.\n *\n * Returns `enforces: false` when no `onUpdate` enforcement can apply to this\n * write — callers use that to keep the existing fast blind-write path\n * instead of paying for a read-before-write. This is tracked as an explicit\n * flag rather than inferred from `storeNames.length > 1`: for a\n * self-referential relation, `def.relatedStoreName` equals `modelName`'s own\n * store (already the seed of the `Set`), so the store count alone can't tell\n * \"no enforcement\" apart from \"enforces, but only against this same store\".\n */\nexport function collectOnUpdateEnforcementStoreNames(\n contract: IdbContract,\n modelName: string,\n data: Record<string, unknown>\n): { storeNames: string[]; enforces: boolean } {\n const stores = new Set([getStoreName(contract, modelName)]);\n const visitedModels = new Set<string>();\n let enforces = false;\n\n function walkCascadeChain(mName: string): void {\n if (visitedModels.has(mName)) return;\n visitedModels.add(mName);\n for (const def of getRelationDefinitions(contract, mName)) {\n if (!isDeleteEnforcementRelation(contract, mName, def)) continue;\n const action = getOnUpdateForRelation(contract, mName, def);\n if (action === \"noAction\") continue;\n stores.add(def.relatedStoreName);\n if (action === \"cascade\") walkCascadeChain(def.relatedModelName);\n }\n }\n\n visitedModels.add(modelName);\n for (const def of getRelationDefinitions(contract, modelName)) {\n if (!isDeleteEnforcementRelation(contract, modelName, def)) continue;\n if (!def.localFields.some((f) => f in data)) continue;\n const action = getOnUpdateForRelation(contract, modelName, def);\n if (action === \"noAction\") continue;\n enforces = true;\n stores.add(def.relatedStoreName);\n if (action === \"cascade\") walkCascadeChain(def.relatedModelName);\n }\n\n return { storeNames: [...stores], enforces };\n}\n\n/**\n * Enforces every `onUpdate` action declared on `modelName`'s child relations\n * against one specific `oldRow` about to be patched with `patch`. Only\n * relations whose `localFields` are both present in `patch` and differ from\n * `oldRow`'s current value are enforced — a patch that sets a field to its\n * existing value, or never touches a locally-referenced field, is a no-op\n * here. Children are matched against `oldRow`'s pre-change values.\n *\n * `cascade` propagates the new value(s) onto the matched children's FK\n * fields and recurses into each child's own `onUpdate` relations before\n * writing (the propagated change may itself need to cascade further) —\n * mirrors `applyReferentialActionsForRow`'s recursive shape, including the\n * `visited` row-level cycle guard (see that function's doc comment for the\n * fresh-per-top-level-row / shared-across-one-row's-descent contract).\n * `setNull`/`setDefault` are leaf actions: the child's FK field changes but\n * its own key doesn't, so nothing below it needs re-enforcement.\n *\n * Unlike `validateScalarFks`'s compound-FK restriction, a compound (multi-\n * field) relation is safe to cascade here: both `localFields` values come\n * from the same `oldRow`/`patch`, so there's no risk of assembling a value\n * from two unrelated rows the way independently-validated FK-existence\n * checks could.\n */\nexport async function applyReferentialActionsForRowOnUpdate(\n scope: IdbTransactionScope,\n contract: IdbContract,\n modelName: string,\n oldRow: Record<string, unknown>,\n patch: Record<string, unknown>,\n visited: Set<string> = new Set()\n): Promise<void> {\n const keyPath = getKeyPath(contract, modelName);\n const rowKey = `${getStoreName(contract, modelName)}::${String(oldRow[keyPath])}`;\n if (visited.has(rowKey)) return;\n visited.add(rowKey);\n\n const meta = makePlanMeta(contract);\n for (const def of getRelationDefinitions(contract, modelName)) {\n if (!isDeleteEnforcementRelation(contract, modelName, def)) continue;\n const changedFields = def.localFields.filter((f) => f in patch && patch[f] !== oldRow[f]);\n if (changedFields.length === 0) continue;\n\n const action = getOnUpdateForRelation(contract, modelName, def);\n if (action === \"noAction\") continue;\n\n const childFilter = buildChildFilterFromRow(def, oldRow);\n\n if (action === \"restrict\") {\n const found = await scope.execute({\n meta,\n kind: \"cursor-scan\",\n storeName: def.relatedStoreName,\n filter: childFilter,\n take: 1,\n } as IdbAtomicPlan);\n if (found.length > 0) {\n throw new Error(\n `Cannot update ${modelName} '${String(oldRow[keyPath])}': changing field(s) ${changedFields.join(\", \")} ` +\n `would orphan child records on relation '${def.relationName}'. ` +\n \"Use onUpdate: 'cascade', 'setNull', 'setDefault', or 'noAction'.\"\n );\n }\n continue;\n }\n\n if (action === \"cascade\") {\n const childPatch: Record<string, unknown> = {};\n for (let i = 0; i < def.localFields.length; i++) {\n const lf = def.localFields[i]!;\n const tf = def.targetFields[i]!;\n if (changedFields.includes(lf)) childPatch[tf] = patch[lf];\n }\n const children = await scope.execute({\n meta,\n kind: \"cursor-scan\",\n storeName: def.relatedStoreName,\n filter: childFilter,\n } as IdbAtomicPlan);\n for (const child of children) {\n await applyReferentialActionsForRowOnUpdate(scope, contract, def.relatedModelName, child, childPatch, visited);\n }\n await scope.execute({\n meta,\n kind: \"scan-write\",\n storeName: def.relatedStoreName,\n write: \"put-merged\",\n patch: childPatch,\n filter: childFilter,\n } as IdbAtomicPlan);\n continue;\n }\n\n if (action === \"setNull\") {\n const childPatch: Record<string, unknown> = {};\n for (const targetField of def.targetFields) childPatch[targetField] = null;\n await scope.execute({\n meta,\n kind: \"scan-write\",\n storeName: def.relatedStoreName,\n write: \"put-merged\",\n patch: childPatch,\n filter: childFilter,\n } as IdbAtomicPlan);\n continue;\n }\n\n if (action === \"setDefault\") {\n const childPatch = buildSetDefaultPatch(contract, def);\n await validateSetDefaultPatch(scope, contract, modelName, def, childPatch, oldRow[keyPath] as IDBValidKey);\n await scope.execute({\n meta,\n kind: \"scan-write\",\n storeName: def.relatedStoreName,\n write: \"put-merged\",\n patch: childPatch,\n filter: childFilter,\n } as IdbAtomicPlan);\n continue;\n }\n }\n}\n\n// ── Scalar FK validation ──────────────────────────────────────────────────────\n\n/**\n * Returns true if `data` contains at least one non-null value for a localField\n * of a N:1 relation — indicating scalar FK fields that need existence validation.\n */\nexport function hasScalarFkFields(contract: IdbContract, modelName: string, data: Record<string, unknown>): boolean {\n for (const def of getRelationDefinitions(contract, modelName)) {\n if (def.cardinality !== \"N:1\") continue;\n for (const localField of def.localFields) {\n if (localField in data && data[localField] !== null && data[localField] !== undefined) return true;\n }\n }\n return false;\n}\n\nfunction collectScalarFkStoreNames(contract: IdbContract, modelName: string, data: Record<string, unknown>): string[] {\n const stores = new Set([getStoreName(contract, modelName)]);\n for (const def of getRelationDefinitions(contract, modelName)) {\n if (def.cardinality !== \"N:1\") continue;\n const hasFkField = def.localFields.some((f) => f in data && data[f] !== null && data[f] !== undefined);\n if (hasFkField) stores.add(def.relatedStoreName);\n }\n return [...stores];\n}\n\nasync function validateScalarFks(\n scope: IdbTransactionScope,\n contract: IdbContract,\n modelName: string,\n data: Record<string, unknown>\n): Promise<void> {\n const meta = makePlanMeta(contract);\n for (const def of getRelationDefinitions(contract, modelName)) {\n if (def.cardinality !== \"N:1\") continue;\n const touched = def.localFields.some((f) => f in data && data[f] !== null && data[f] !== undefined);\n if (!touched) continue;\n\n if (def.localFields.length > 1) {\n // Validating each field of a compound FK independently would check\n // \"does *some* row have this orgId\" and \"does *some* row have this\n // userId\" as two separate queries — both can pass even when no single\n // parent row satisfies the full tuple, silently persisting a value\n // assembled from two different parent rows. Refuse outright rather\n // than validate incorrectly: a correct fix also needs the row's other,\n // untouched FK fields (not available here on a partial update patch)\n // to know the intended full tuple.\n throw new Error(\n `FK violation on relation '${def.relationName}': compound (multi-field) scalar FK validation is not supported`\n );\n }\n\n const localField = def.localFields[0]!;\n const targetField = def.targetFields[0]!;\n const value = data[localField];\n const filter = (row: Record<string, unknown>): boolean => row[targetField] === value;\n const plan: IdbCursorScanPlan = {\n meta,\n kind: \"cursor-scan\",\n storeName: def.relatedStoreName,\n filter,\n take: 1,\n };\n const rows = await scope.execute(plan as IdbAtomicPlan);\n if (rows.length === 0) {\n throw new Error(\n `FK violation on relation '${def.relationName}': no ${def.relatedModelName} with ${targetField}='${String(value)}'`\n );\n }\n }\n}\n\nexport async function executeScalarCreateWithFkValidation(options: {\n executor: IdbQueryExecutorWithTransaction;\n contract: IdbContract;\n modelName: string;\n data: Record<string, unknown>;\n}): Promise<Record<string, unknown>> {\n const { executor, contract, modelName, data } = options;\n const storeNames = collectScalarFkStoreNames(contract, modelName, data);\n return withMutationScope(executor, storeNames, async (scope) => {\n await validateScalarFks(scope, contract, modelName, data);\n return insertSingleRow(scope, contract, modelName, data, createMutationDefaultsCache());\n });\n}\n\n/**\n * Combines FK-existence store scope (this model's own N:1 relations) with\n * `onUpdate` enforcement store scope (this model's child relations) for a\n * single write. Returns the union alongside whether `onUpdate` enforcement\n * actually applies (i.e. the `onUpdate` collector found more than just the\n * model's own store) — callers use that flag to choose between the existing\n * fast blind-write path and the read-before-write enforcement path.\n */\nfunction collectUpdateStoreNames(\n contract: IdbContract,\n modelName: string,\n data: Record<string, unknown>\n): { storeNames: string[]; enforcesOnUpdate: boolean } {\n const fkStoreNames = collectScalarFkStoreNames(contract, modelName, data);\n const { storeNames: onUpdateStoreNames, enforces } = collectOnUpdateEnforcementStoreNames(contract, modelName, data);\n return {\n storeNames: [...new Set([...fkStoreNames, ...onUpdateStoreNames])],\n enforcesOnUpdate: enforces,\n };\n}\n\nexport async function executeScalarUpdateWithFkValidation(options: {\n executor: IdbQueryExecutorWithTransaction;\n contract: IdbContract;\n modelName: string;\n filters: readonly IdbFilterExpr[];\n data: Record<string, unknown>;\n}): Promise<Record<string, unknown> | null> {\n const { executor, contract, modelName, filters, data } = options;\n const { storeNames, enforcesOnUpdate } = collectUpdateStoreNames(contract, modelName, data);\n return withMutationScope(executor, storeNames, async (scope) => {\n await validateScalarFks(scope, contract, modelName, data);\n const storeName = getStoreName(contract, modelName);\n const meta = makePlanMeta(contract);\n const combined =\n filters.length === 0 ? undefined : filters.length === 1 ? filters[0]! : { kind: \"and\" as const, exprs: filters };\n const filter =\n combined !== undefined ? (row: Record<string, unknown>): boolean => evaluateFilter(combined, row) : undefined;\n const patch = applyUpdateDefaults(\n contract.execution?.mutations.defaults,\n storeName,\n data,\n createMutationDefaultsCache()\n );\n\n if (!enforcesOnUpdate) {\n const rows = await scope.execute({\n meta,\n kind: \"scan-write\",\n storeName,\n write: \"put-merged\",\n patch,\n take: 1,\n ...(filter !== undefined ? { filter } : {}),\n } as IdbAtomicPlan);\n return rows[0] ?? null;\n }\n\n // Read-before-write: onUpdate enforcement needs the pre-image to know\n // whether a locally-referenced field's value is actually changing.\n const oldRows = await scope.execute({\n meta,\n kind: \"cursor-scan\",\n storeName,\n take: 1,\n ...(filter !== undefined ? { filter } : {}),\n } as IdbAtomicPlan);\n const oldRow = oldRows[0];\n if (!oldRow) return null;\n await applyReferentialActionsForRowOnUpdate(scope, contract, modelName, oldRow, patch);\n const keyPath = getKeyPath(contract, modelName);\n const key = oldRow[keyPath] as IDBValidKey;\n const rows = await scope.execute({ meta, kind: \"update\", storeName, key, patch } as IdbAtomicPlan);\n return rows[0] ?? null;\n });\n}\n\n/**\n * Bulk counterpart to {@link executeScalarUpdateWithFkValidation}: same FK\n * validation and `onUpdate` enforcement, but applies the patch to every row\n * the filter matches (no `take: 1`) and returns all of them.\n *\n * Always goes through the transaction scope — unlike single-row `update()`,\n * which only needs one when there's a scalar FK field or `onUpdate`\n * enforcement to apply. A bulk scan-write's affected row SET isn't knowable\n * until it actually runs, and observing that result INSIDE the same\n * transaction is exactly what the sync interceptor needs to track the write\n * correctly: its transaction-scope hook (`SyncInterceptingTransactionScope#maybeTrack`'s\n * `scan-write`/`update` cases) writes one outbox event per row it's handed,\n * atomically with the write itself. The plan-level path `update()` falls\n * back to for a non-enforced single row has no equivalent hook — a plan is\n * extended with outbox ops BEFORE it runs, which only works when the\n * affected key is knowable up front.\n */\nexport async function executeBulkUpdateWithFkValidation(options: {\n executor: IdbQueryExecutorWithTransaction;\n contract: IdbContract;\n modelName: string;\n filters: readonly IdbFilterExpr[];\n data: Record<string, unknown>;\n}): Promise<Record<string, unknown>[]> {\n const { executor, contract, modelName, filters, data } = options;\n const { storeNames, enforcesOnUpdate } = collectUpdateStoreNames(contract, modelName, data);\n return withMutationScope(executor, storeNames, async (scope) => {\n await validateScalarFks(scope, contract, modelName, data);\n const storeName = getStoreName(contract, modelName);\n const meta = makePlanMeta(contract);\n const combined =\n filters.length === 0 ? undefined : filters.length === 1 ? filters[0]! : { kind: \"and\" as const, exprs: filters };\n const filter =\n combined !== undefined ? (row: Record<string, unknown>): boolean => evaluateFilter(combined, row) : undefined;\n const patch = applyUpdateDefaults(\n contract.execution?.mutations.defaults,\n storeName,\n data,\n createMutationDefaultsCache()\n );\n\n if (!enforcesOnUpdate) {\n return scope.execute({\n meta,\n kind: \"scan-write\",\n storeName,\n write: \"put-merged\",\n patch,\n ...(filter !== undefined ? { filter } : {}),\n } as IdbAtomicPlan);\n }\n\n const oldRows = await scope.execute({\n meta,\n kind: \"cursor-scan\",\n storeName,\n ...(filter !== undefined ? { filter } : {}),\n } as IdbAtomicPlan);\n const keyPath = getKeyPath(contract, modelName);\n const results: Record<string, unknown>[] = [];\n for (const oldRow of oldRows) {\n await applyReferentialActionsForRowOnUpdate(scope, contract, modelName, oldRow, patch);\n const key = oldRow[keyPath] as IDBValidKey;\n const rows = await scope.execute({ meta, kind: \"update\", storeName, key, patch } as IdbAtomicPlan);\n const updated = rows[0];\n if (updated) results.push(updated);\n }\n return results;\n });\n}\n\n// ── Delete referential action enforcement ─────────────────────────────────────\n\n/**\n * Returns true if the model has at least one child relation (1:N or parent-side\n * 1:1) whose `onDelete` action requires enforcement (anything except `noAction`).\n * Since the default is `restrict`, any model with 1:N/1:1 relations that do not\n * explicitly set `noAction` returns true.\n */\nexport function hasEnforceableChildRelations(contract: IdbContract, modelName: string): boolean {\n for (const def of getRelationDefinitions(contract, modelName)) {\n if (!isDeleteEnforcementRelation(contract, modelName, def)) continue;\n if (getOnDeleteForDeleteRelation(contract, modelName, def) !== \"noAction\") return true;\n }\n return false;\n}\n\n/**\n * Transitively walks the `onDelete` cascade graph from `modelName`, collecting\n * every store a recursive delete might touch. `cascade` edges are walked\n * further (a cascaded child's own children may themselves cascade);\n * `restrict`/`setNull`/`setDefault` edges still need their store added (each\n * is read or written once) but don't recurse further, since none of them\n * delete the child row. Guarded by a model-level visited set — required\n * because IDB must declare every store a transaction might touch before it\n * opens, so this static walk must terminate even on a self-referential model\n * or a cycle of mutually-cascading models.\n */\nexport function collectDeleteStoreNames(contract: IdbContract, modelName: string): string[] {\n const stores = new Set<string>();\n const visitedModels = new Set<string>();\n\n function walk(mName: string): void {\n if (visitedModels.has(mName)) return;\n visitedModels.add(mName);\n stores.add(getStoreName(contract, mName));\n for (const def of getRelationDefinitions(contract, mName)) {\n if (!isDeleteEnforcementRelation(contract, mName, def)) continue;\n const action = getOnDeleteForDeleteRelation(contract, mName, def);\n if (action === \"noAction\") continue;\n stores.add(def.relatedStoreName);\n if (action === \"cascade\") walk(def.relatedModelName);\n }\n }\n\n walk(modelName);\n return [...stores];\n}\n\n/**\n * Enforces every `onDelete` action declared on `modelName`'s child relations\n * against one specific `row` about to be deleted. `cascade` recurses into\n * each matched child's own `onDelete` relations *before* deleting it — so a\n * multi-hop chain (`User --cascade--> Post --cascade--> Comment`) is fully\n * torn down, and a `restrict` several hops deep still aborts the whole\n * transaction (recursing before deleting means the delete never happens if a\n * deeper hop throws). `setNull`/`setDefault` are leaf actions: the child row\n * survives, so recursion never continues past them.\n *\n * `visited` (keyed by `storeName::key`) guards against row-level cycles — two\n * specific rows whose FKs point at each other through a self-referential or\n * mutually-cascading relation graph. Callers should leave it at its default\n * (a fresh `Set` per top-level call) so independent rows deleted in the same\n * `deleteAll()` batch don't cross-suppress each other's cascades; it's only\n * ever passed explicitly by this function's own recursive calls, to keep one\n * shared guard across a single row's full recursive descent.\n */\nexport async function applyReferentialActionsForRow(\n scope: IdbTransactionScope,\n contract: IdbContract,\n modelName: string,\n row: Record<string, unknown>,\n visited: Set<string> = new Set()\n): Promise<void> {\n const keyPath = getKeyPath(contract, modelName);\n const rowKey = `${getStoreName(contract, modelName)}::${String(row[keyPath])}`;\n if (visited.has(rowKey)) return;\n visited.add(rowKey);\n\n const meta = makePlanMeta(contract);\n for (const def of getRelationDefinitions(contract, modelName)) {\n if (!isDeleteEnforcementRelation(contract, modelName, def)) continue;\n const action = getOnDeleteForDeleteRelation(contract, modelName, def);\n if (action === \"noAction\") continue;\n\n const childFilter = buildChildFilterFromRow(def, row);\n\n if (action === \"restrict\") {\n const found = await scope.execute({\n meta,\n kind: \"cursor-scan\",\n storeName: def.relatedStoreName,\n filter: childFilter,\n take: 1,\n } as IdbAtomicPlan);\n if (found.length > 0) {\n throw new Error(\n `Cannot delete ${modelName} '${String(row[keyPath])}': child records exist on relation '${def.relationName}'. ` +\n \"Use onDelete: 'cascade', 'setNull', or 'noAction'.\"\n );\n }\n continue;\n }\n\n if (action === \"cascade\") {\n const childKeyPath = getKeyPath(contract, def.relatedModelName);\n const children = await scope.execute({\n meta,\n kind: \"cursor-scan\",\n storeName: def.relatedStoreName,\n filter: childFilter,\n } as IdbAtomicPlan);\n for (const child of children) {\n await applyReferentialActionsForRow(scope, contract, def.relatedModelName, child, visited);\n await scope.execute({\n meta,\n kind: \"delete\",\n storeName: def.relatedStoreName,\n key: child[childKeyPath] as IDBValidKey,\n } as IdbAtomicPlan);\n }\n continue;\n }\n\n if (action === \"setNull\") {\n const patch: Record<string, unknown> = {};\n for (const targetField of def.targetFields) patch[targetField] = null;\n await scope.execute({\n meta,\n kind: \"scan-write\",\n storeName: def.relatedStoreName,\n write: \"put-merged\",\n patch,\n filter: childFilter,\n } as IdbAtomicPlan);\n continue;\n }\n\n if (action === \"setDefault\") {\n const patch = buildSetDefaultPatch(contract, def);\n await validateSetDefaultPatch(scope, contract, modelName, def, patch, row[keyPath] as IDBValidKey);\n await scope.execute({\n meta,\n kind: \"scan-write\",\n storeName: def.relatedStoreName,\n write: \"put-merged\",\n patch,\n filter: childFilter,\n } as IdbAtomicPlan);\n continue;\n }\n }\n}\n\nexport async function executeDeleteWithReferentialActions(options: {\n executor: IdbQueryExecutorWithTransaction;\n contract: IdbContract;\n modelName: string;\n key: IDBValidKey;\n}): Promise<void> {\n const { executor, contract, modelName, key } = options;\n const storeNames = collectDeleteStoreNames(contract, modelName);\n await withMutationScope(executor, storeNames, async (scope) => {\n const storeName = getStoreName(contract, modelName);\n const meta = makePlanMeta(contract);\n const rows = await scope.execute({ meta, kind: \"key-get\", storeName, key } as IdbAtomicPlan);\n const row = rows[0];\n if (!row) return [];\n await applyReferentialActionsForRow(scope, contract, modelName, row);\n await scope.execute({ meta, kind: \"delete\", storeName, key } as IdbAtomicPlan);\n return [];\n });\n}\n\nexport async function executeDeleteAllWithReferentialActions(options: {\n executor: IdbQueryExecutorWithTransaction;\n contract: IdbContract;\n modelName: string;\n filter?: (row: Record<string, unknown>) => boolean;\n}): Promise<Record<string, unknown>[]> {\n const { executor, contract, modelName, filter } = options;\n const storeNames = collectDeleteStoreNames(contract, modelName);\n return withMutationScope(executor, storeNames, async (scope) => {\n const storeName = getStoreName(contract, modelName);\n const meta = makePlanMeta(contract);\n const keyPath = getKeyPath(contract, modelName);\n const rows = await scope.execute({\n meta,\n kind: \"cursor-scan\",\n storeName,\n ...(filter !== undefined ? { filter } : {}),\n } as IdbAtomicPlan);\n for (const row of rows) {\n await applyReferentialActionsForRow(scope, contract, modelName, row);\n const key = row[keyPath] as IDBValidKey;\n await scope.execute({ meta, kind: \"delete\", storeName, key } as IdbAtomicPlan);\n }\n return rows;\n });\n}\n","import { AsyncIterableResult } from \"@prisma/orm-framework/components/runtime\";\nimport type { PlanMeta } from \"@prisma/orm-framework/contract/types\";\nimport type { IdbFilterExpr, IdbQueryPlan } from \"@prisma-idb/adapter-idb/runtime\";\nimport type {\n IdbAggregateAst,\n IdbCountAst,\n IdbCreateAst,\n IdbCreateAllAst,\n IdbDeleteAst,\n IdbFindManyAst,\n IdbFindUniqueAst,\n IdbQueryAst,\n} from \"@prisma-idb/adapter-idb/runtime\";\nimport { evaluateFilter, shorthandToFilterExpr } from \"@prisma-idb/adapter-idb/runtime\";\nimport {\n type CreateInput,\n type DefaultModelRow,\n type IdbAggregateBuilder,\n type IdbAggregateResult,\n type IdbAggregateSpec,\n type IdbContract,\n type IncludeSpec,\n type KeyType,\n type MutationCreateInput,\n type MutationUpdateInput,\n type NoIncludes,\n type OrderBySpec,\n type PatchInput,\n type ReferenceRelKeys,\n type RelatedModelOf,\n type SelectedRow,\n type WhereFilter,\n buildFieldToIndexMap,\n getKeyPath,\n getRelation,\n getStoreName,\n} from \"./types\";\nimport { createModelAccessor, type IdbModelAccessor } from \"./model-accessor\";\nimport {\n type IdbAccessorState,\n type IdbIncludeScalar,\n type IncludeEntry,\n createIncludeScalar,\n emptyAccessorState,\n isIncludeScalar,\n mergeAccessorState,\n} from \"./store-state\";\nimport {\n buildRowComparator,\n combineFilterExprs,\n extractIndexEqualityHint,\n extractIndexOrHint,\n type IndexOrHint,\n} from \"./query-shaping\";\nimport {\n assertValidAggregateSpec,\n computeAggregateSpec,\n createAggregateBuilder,\n toAggregateRequests,\n} from \"./aggregate-builder\";\nimport { type IdbGroupedAccessor, createGroupedAccessor } from \"./grouped-accessor\";\nimport type { IdbQueryExecutor } from \"./executor\";\nimport { applyCreateDefaults, applyUpdateDefaults, createMutationDefaultsCache } from \"./mutation-defaults\";\nimport { loadRelation } from \"./relation-loader\";\nimport {\n applyReferentialActionsForRowOnUpdate,\n collectOnUpdateEnforcementStoreNames,\n executeBulkUpdateWithFkValidation,\n executeDeleteAllWithReferentialActions,\n executeDeleteWithReferentialActions,\n executeNestedCreateMutation,\n executeNestedUpdateMutation,\n executeScalarCreateWithFkValidation,\n executeScalarUpdateWithFkValidation,\n hasEnforceableChildRelations,\n hasNestedMutationCallbacks,\n hasScalarFkFields,\n requireTransactionExecutor,\n} from \"./mutation-executor\";\nimport { withMutationScope } from \"./mutation-scope\";\n\n/** Callback form of `.where(fn)` — receives the typed model accessor proxy. */\nexport type WhereCallback<TContract, ModelName extends string> = (\n m: IdbModelAccessor<TContract, ModelName>\n) => IdbFilterExpr;\n\n/** Tuple of one-or-more field names of a model (for `select()` / `groupBy()`). */\ntype FieldTuple<TContract, ModelName extends string> = readonly [\n keyof DefaultModelRow<TContract, ModelName> & string,\n ...(keyof DefaultModelRow<TContract, ModelName> & string)[],\n];\n\n/**\n * The child accessor handed to an `include()` refinement callback.\n *\n * Exposes the chainable narrowing methods (`where` / `orderBy` / `take` /\n * `skip`) plus the scalar `count()` reducer. Mirrors the vendor\n * `IncludeRefinementCollection`: chainable methods return the same refinement\n * surface so `count()` stays reachable after a `where()`, and `count()` returns\n * an {@link IdbIncludeScalar} marker rather than the async terminal `count()`\n * found on the top-level accessor.\n */\nexport interface IdbIncludeRefinementAccessor<TContract, ModelName extends string> {\n where(\n filter: WhereFilter<TContract, ModelName> | WhereCallback<TContract, ModelName>\n ): IdbIncludeRefinementAccessor<TContract, ModelName>;\n orderBy(spec: OrderBySpec<TContract, ModelName>): IdbIncludeRefinementAccessor<TContract, ModelName>;\n take(n: number): IdbIncludeRefinementAccessor<TContract, ModelName>;\n skip(n: number): IdbIncludeRefinementAccessor<TContract, ModelName>;\n count(): IdbIncludeScalar;\n}\n\n/** Refinement callback type for a given relation key `K`. */\ntype IncludeRefineFn<TContract, ModelName extends string, K extends string, R> = (\n collection: IdbIncludeRefinementAccessor<TContract, RelatedModelOf<TContract, ModelName, K>>\n) => R;\n\n// ── Interface ─────────────────────────────────────────────────────────────────\n\n/**\n * Immutable query-builder for a single IDB object store.\n *\n * Each method that narrows the query (`.where()`, `.take()`, etc.) returns a\n * new, independent accessor instance — the original is never mutated. This\n * mirrors the `MongoCollection` pattern from Prisma ORM's Mongo family.\n *\n * @template TContract - The full IDB contract (with or without type maps).\n * @template ModelName - The model (store) this accessor targets.\n * @template TIncludes - Tracks which relations have been included via\n * `.include()` calls, so the return type widens progressively.\n * @template TSelected - Field names kept by `.select()`. `never` (the\n * default) means \"all fields\"; otherwise the row narrows to these fields\n * (plus any included relations).\n */\nexport interface IdbStoreAccessor<\n TContract,\n ModelName extends string,\n TIncludes extends IncludeSpec<TContract, ModelName> = NoIncludes,\n TSelected extends string = never,\n> {\n /**\n * Add a filter (ANDed with any previous `.where()` calls).\n *\n * Two forms:\n *\n * - **Shorthand**: `where({ field: value })` — multi-key shorthand\n * objects compose as AND. `null` values become null-checks rather\n * than literal-null equalities so absent fields match.\n * - **Callback**: `where((m) => m.field.op(value))` — receives the\n * typed model accessor proxy and returns an `IdbFilterExpr` built\n * via the operator surface. Combinators (`and`, `or`, `not` from\n * `@prisma-idb/client-idb/orm`) compose nodes.\n */\n where(\n filter: WhereFilter<TContract, ModelName> | WhereCallback<TContract, ModelName>\n ): IdbStoreAccessor<TContract, ModelName, TIncludes, TSelected>;\n\n /** Set the sort order. Replaces any previous `.orderBy()` call. */\n orderBy(spec: OrderBySpec<TContract, ModelName>): IdbStoreAccessor<TContract, ModelName, TIncludes, TSelected>;\n\n /** Limit the number of rows returned. */\n take(n: number): IdbStoreAccessor<TContract, ModelName, TIncludes, TSelected>;\n\n /** Skip the first `n` rows (OFFSET). */\n skip(n: number): IdbStoreAccessor<TContract, ModelName, TIncludes, TSelected>;\n\n /**\n * Include a reference relation in the returned rows.\n *\n * The relation is loaded via a single batch cursor scan after the main\n * query — O(1) round trips to IDB per included relation regardless of\n * the number of parent rows. The return type gains the relation field\n * automatically.\n *\n * An optional refinement callback narrows the loaded relation:\n *\n * - return the (chained) collection to apply `where` / `orderBy` /\n * `take` / `skip` to the related rows (per-parent for `1:N`);\n * - return `collection.count()` to reduce a to-many relation to the\n * number of matching children (the field becomes a `number`).\n *\n * @example\n * ```ts\n * db.users.include(\"posts\", (posts) => posts.where({ published: true }).take(5))\n * db.users.include(\"posts\", (posts) => posts.count())\n * ```\n */\n include<K extends ReferenceRelKeys<TContract, ModelName>>(\n relation: K,\n refineFn?: IncludeRefineFn<\n TContract,\n ModelName,\n K,\n IdbIncludeRefinementAccessor<TContract, RelatedModelOf<TContract, ModelName, K>>\n >\n ): IdbStoreAccessor<TContract, ModelName, TIncludes & Record<K, true>, TSelected>;\n include<K extends ReferenceRelKeys<TContract, ModelName>>(\n relation: K,\n refineFn: IncludeRefineFn<TContract, ModelName, K, IdbIncludeScalar>\n ): IdbStoreAccessor<TContract, ModelName, TIncludes & Record<K, \"scalar\">, TSelected>;\n\n /**\n * Project the row down to a subset of scalar fields. Any previously\n * `.include()`d relations are preserved on the result; only the scalar\n * fields are narrowed.\n *\n * @example\n * ```ts\n * const summaries = await db.users.select(\"id\", \"email\").all();\n * // typeof summaries[number] === { id: string; email: string }\n * ```\n */\n select<Fields extends FieldTuple<TContract, ModelName>>(\n ...fields: Fields\n ): IdbStoreAccessor<TContract, ModelName, TIncludes, Fields[number]>;\n\n /** Return all matching rows as an async iterable (also awaitable as `Row[]`). */\n all(): AsyncIterableResult<SelectedRow<TContract, ModelName, TIncludes, TSelected>>;\n\n /** Return the first matching row, or `null` if none match. */\n first(): Promise<SelectedRow<TContract, ModelName, TIncludes, TSelected> | null>;\n\n /**\n * Run an in-memory aggregate (count/sum/avg/min/max) over the rows matching\n * the accumulated `.where()` filter. Returns one result object keyed by the\n * aliases supplied in the spec.\n *\n * @example\n * ```ts\n * const stats = await db.posts.where({ published: true }).aggregate((agg) => ({\n * total: agg.count(),\n * avgViews: agg.avg(\"views\"),\n * }));\n * ```\n */\n aggregate<Spec extends IdbAggregateSpec>(\n fn: (agg: IdbAggregateBuilder<TContract, ModelName>) => Spec\n ): Promise<IdbAggregateResult<Spec>>;\n\n /**\n * Switch to grouped-aggregate mode. The returned {@link IdbGroupedAccessor}'s\n * `.aggregate(...)` terminal produces one row per group with the chosen key\n * fields plus the requested aggregates.\n *\n * @example\n * ```ts\n * const byUser = await db.posts\n * .where({ published: true })\n * .groupBy(\"authorId\")\n * .aggregate((agg) => ({ count: agg.count(), totalViews: agg.sum(\"views\") }));\n * ```\n */\n groupBy<Fields extends FieldTuple<TContract, ModelName>>(\n ...fields: Fields\n ): IdbGroupedAccessor<TContract, ModelName, Fields>;\n\n /**\n * Insert a record into the store and return the stored row.\n *\n * The primary key field is optional in `data` — pass it to use a\n * client-generated ID (`cuid`, `uuid`) or omit it for auto-increment stores.\n *\n * Relation fields accept a mutation callback:\n * `posts: (rel) => rel.create([...])` or `author: (rel) => rel.connect({ id })`.\n * When any relation callback is present, all writes are wrapped in a single\n * multi-store IDB transaction (requires IdbRuntime, not a plain executor).\n */\n create(data: MutationCreateInput<TContract, ModelName>): Promise<DefaultModelRow<TContract, ModelName>>;\n\n /** Look up a single row by primary key. Returns `null` if not found. */\n findUnique(key: KeyType<TContract, ModelName>): Promise<DefaultModelRow<TContract, ModelName> | null>;\n\n /** Delete the row with the given primary key. */\n delete(key: KeyType<TContract, ModelName>): Promise<void>;\n\n /**\n * Update the first row matching the accumulated `.where()` filter.\n * Returns the merged row, or `null` if no row matches.\n *\n * Relation fields accept `connect` or `disconnect` callbacks. When any\n * relation callback is present, all writes run in a single multi-store\n * IDB transaction (requires IdbRuntime).\n */\n update(patch: MutationUpdateInput<TContract, ModelName>): Promise<DefaultModelRow<TContract, ModelName> | null>;\n\n /**\n * Update all rows matching the accumulated `.where()` filter and return\n * them as an `AsyncIterableResult` (also awaitable as `Row[]`).\n */\n updateAll(patch: PatchInput<TContract, ModelName>): AsyncIterableResult<DefaultModelRow<TContract, ModelName>>;\n\n /**\n * Update all rows matching the accumulated `.where()` filter.\n * Returns the count of updated rows.\n */\n updateCount(patch: PatchInput<TContract, ModelName>): Promise<number>;\n\n /**\n * Insert or update a single record.\n *\n * - If a row matching `where` exists: shallow-merge `update` onto it and\n * return the merged row.\n * - If no matching row exists: insert `create` and return it.\n */\n upsert(args: {\n create: CreateInput<TContract, ModelName>;\n update: PatchInput<TContract, ModelName>;\n where: WhereFilter<TContract, ModelName>;\n }): Promise<DefaultModelRow<TContract, ModelName>>;\n\n /**\n * Insert multiple records in a single atomic transaction.\n * Returns all inserted rows as an `AsyncIterableResult`.\n */\n createAll(data: CreateInput<TContract, ModelName>[]): AsyncIterableResult<DefaultModelRow<TContract, ModelName>>;\n\n /**\n * Insert multiple records in a single atomic transaction.\n * Returns the count of inserted rows.\n */\n createCount(data: CreateInput<TContract, ModelName>[]): Promise<number>;\n\n /**\n * Delete all rows matching the accumulated `.where()` filter.\n * Returns the deleted rows as an `AsyncIterableResult`.\n */\n deleteAll(): AsyncIterableResult<DefaultModelRow<TContract, ModelName>>;\n\n /**\n * Delete all rows matching the accumulated `.where()` filter.\n * Returns the count of deleted rows.\n */\n deleteCount(): Promise<number>;\n\n /**\n * Count all rows matching the accumulated `.where()` filter.\n * With no filter, counts all rows in the store.\n *\n * **Note — `skip`/`take` are respected**: unlike Prisma's SQL `count()`,\n * which ignores pagination, this implementation reuses the same cursor-scan\n * plan as `all()`. That means `where(...).take(5).count()` returns at most 5,\n * not the total number of matching rows. Use `where(...).count()` without\n * `take`/`skip` when you need an unbounded total.\n */\n count(): Promise<number>;\n}\n\n// ── Implementation ────────────────────────────────────────────────────────────\n\n/**\n * Concrete immutable query builder.\n *\n * Internal details:\n * - All state is in `#state` (filters, orderBy, skip, take, includes, selectedFields).\n * - Builder methods clone via `#clone()` — O(1) copies since state is\n * structurally shared.\n * - `all()` materialises the main rows first, then batch-loads each included\n * relation, then applies any `.select()` projection before yielding.\n * - `#includeRefinementMode` flips `count()` from an async terminal to an\n * {@link IdbIncludeScalar} marker so it can be used inside `include()`.\n */\nexport class IdbStoreAccessorImpl<\n TContract extends IdbContract,\n ModelName extends string,\n TIncludes extends IncludeSpec<TContract, ModelName> = NoIncludes,\n TSelected extends string = never,\n> implements IdbStoreAccessor<TContract, ModelName, TIncludes, TSelected> {\n readonly #contract: TContract;\n readonly #modelName: ModelName;\n readonly #executor: IdbQueryExecutor;\n readonly #storeName: string;\n readonly #state: IdbAccessorState;\n readonly #newGroupingKey: () => string;\n readonly #includeRefinementMode: boolean;\n\n constructor(\n contract: TContract,\n modelName: ModelName,\n executor: IdbQueryExecutor,\n state?: IdbAccessorState,\n newGroupingKey?: () => string,\n includeRefinementMode = false\n ) {\n this.#contract = contract;\n this.#modelName = modelName;\n this.#executor = executor;\n this.#storeName = getStoreName(contract, modelName);\n this.#state = state ?? emptyAccessorState();\n // Default: per-instance counter (single client; avoids module-level interleaving).\n let _key = 0;\n this.#newGroupingKey = newGroupingKey ?? (() => `idb-op-${++_key}`);\n this.#includeRefinementMode = includeRefinementMode;\n }\n\n // ── Builder methods ───────────────────────────────────────────────────────\n\n where(\n filter: WhereFilter<TContract, ModelName> | WhereCallback<TContract, ModelName>\n ): IdbStoreAccessor<TContract, ModelName, TIncludes, TSelected> {\n const expr =\n typeof filter === \"function\"\n ? filter(createModelAccessor<TContract, ModelName>())\n : shorthandToFilterExpr(filter as Record<string, unknown>);\n // An empty shorthand object (or one with only undefined values) lifts\n // to `undefined` — keep the existing filter list untouched so chained\n // `.where({})` calls don't produce noisy AND nodes.\n if (expr === undefined) return this.#clone({});\n return this.#clone({ filters: [...this.#state.filters, expr] });\n }\n\n orderBy(spec: OrderBySpec<TContract, ModelName>): IdbStoreAccessor<TContract, ModelName, TIncludes, TSelected> {\n return this.#clone({ orderBy: spec as Record<string, \"asc\" | \"desc\"> });\n }\n\n take(n: number): IdbStoreAccessor<TContract, ModelName, TIncludes, TSelected> {\n return this.#clone({ take: n });\n }\n\n skip(n: number): IdbStoreAccessor<TContract, ModelName, TIncludes, TSelected> {\n return this.#clone({ skip: n });\n }\n\n include<K extends ReferenceRelKeys<TContract, ModelName>>(\n relation: K,\n refineFn?: IncludeRefineFn<\n TContract,\n ModelName,\n K,\n IdbIncludeRefinementAccessor<TContract, RelatedModelOf<TContract, ModelName, K>>\n >\n ): IdbStoreAccessor<TContract, ModelName, TIncludes & Record<K, true>, TSelected>;\n include<K extends ReferenceRelKeys<TContract, ModelName>>(\n relation: K,\n refineFn: IncludeRefineFn<TContract, ModelName, K, IdbIncludeScalar>\n ): IdbStoreAccessor<TContract, ModelName, TIncludes & Record<K, \"scalar\">, TSelected>;\n include<K extends ReferenceRelKeys<TContract, ModelName>>(\n relation: K,\n refineFn?: IncludeRefineFn<\n TContract,\n ModelName,\n K,\n IdbIncludeRefinementAccessor<TContract, RelatedModelOf<TContract, ModelName, K>> | IdbIncludeScalar\n >\n ): IdbStoreAccessor<TContract, ModelName, IncludeSpec<TContract, ModelName>, TSelected> {\n const entry = this.#resolveIncludeEntry(relation, refineFn);\n const newState = mergeAccessorState(this.#state, {\n includes: { ...this.#state.includes, [relation]: entry },\n });\n // The new instance is identical at runtime; the narrowed TIncludes type is\n // only a compile-time distinction — so an `as unknown as` cast is safe.\n return new IdbStoreAccessorImpl(\n this.#contract,\n this.#modelName,\n this.#executor,\n newState,\n this.#newGroupingKey,\n this.#includeRefinementMode\n ) as unknown as IdbStoreAccessor<TContract, ModelName, IncludeSpec<TContract, ModelName>, TSelected>;\n }\n\n select<Fields extends FieldTuple<TContract, ModelName>>(\n ...fields: Fields\n ): IdbStoreAccessor<TContract, ModelName, TIncludes, Fields[number]> {\n // Runtime is identical; only TSelected narrows. Cast bridges the type-level\n // projection (the clone preserves TIncludes / contract / executor).\n return this.#clone({ selectedFields: fields as readonly string[] }) as unknown as IdbStoreAccessor<\n TContract,\n ModelName,\n TIncludes,\n Fields[number]\n >;\n }\n\n // ── Execution methods ─────────────────────────────────────────────────────\n\n all(): AsyncIterableResult<SelectedRow<TContract, ModelName, TIncludes, TSelected>> {\n const groupingKey = this.#newGroupingKey();\n // Capture the private fields needed inside the generator. Private names\n // must be accessed on `this`, so we bind the methods to keep them callable\n // without aliasing `this` (no-this-alias).\n const buildScanPlan = this.#buildScanPlan.bind(this);\n const executeOrRows = this.#executeOrRows.bind(this);\n const executorQuery = this.#executor.query.bind(this.#executor);\n const applyIncludes = this.#applyIncludes.bind(this);\n const projectRows = this.#projectRows.bind(this);\n const combined = this.#combinedFilterExpr();\n const fieldToIndexMap =\n typeof IDBKeyRange !== \"undefined\" ? buildFieldToIndexMap(this.#contract, this.#storeName) : undefined;\n const keyPath = getKeyPath(this.#contract, this.#modelName);\n const comparator = buildRowComparator(this.#state.orderBy);\n const skip = this.#state.skip;\n const take = this.#state.take;\n return new AsyncIterableResult(\n (async function* (): AsyncGenerator<SelectedRow<TContract, ModelName, TIncludes, TSelected>, void, unknown> {\n let rows: Record<string, unknown>[];\n\n // OR multi-scan path: union N index point-range scans, deduplicate,\n // re-apply orderBy (the union has no overall ordering), then apply\n // skip/take in-memory (pagination must happen after the union).\n const orHint = fieldToIndexMap !== undefined ? extractIndexOrHint(combined, fieldToIndexMap, keyPath) : null;\n if (orHint !== null) {\n rows = await executeOrRows(orHint, groupingKey, combined);\n if (comparator !== undefined) rows.sort(comparator);\n if (skip !== undefined) rows = rows.slice(skip);\n if (take !== undefined) rows = rows.slice(0, take);\n } else {\n // AND single-index path (or full scan — decided inside buildScanPlan).\n const scanPlan = buildScanPlan<Record<string, unknown>>(groupingKey, fieldToIndexMap);\n rows = [];\n for await (const row of executorQuery(scanPlan)) {\n rows.push(row);\n }\n }\n\n // Batch-load any included relations (uses full rows — FK fields intact).\n const withIncludes = await applyIncludes(rows, groupingKey);\n\n // Apply any `.select()` projection, then yield.\n for (const row of projectRows(withIncludes)) {\n yield row as SelectedRow<TContract, ModelName, TIncludes, TSelected>;\n }\n })()\n );\n }\n\n async first(): Promise<SelectedRow<TContract, ModelName, TIncludes, TSelected> | null> {\n return this.take(1).all().first();\n }\n\n async aggregate<Spec extends IdbAggregateSpec>(\n fn: (agg: IdbAggregateBuilder<TContract, ModelName>) => Spec\n ): Promise<IdbAggregateResult<Spec>> {\n const spec = fn(createAggregateBuilder<TContract, ModelName>());\n assertValidAggregateSpec(spec, \"aggregate()\");\n const combined = this.#combinedFilterExpr();\n const ast: IdbAggregateAst = {\n kind: \"aggregate\",\n modelName: this.#modelName,\n aggregates: toAggregateRequests(spec),\n ...(combined !== undefined ? { where: combined } : {}),\n };\n const rows = await this.#materialize(this.#newGroupingKey(), ast);\n return computeAggregateSpec(spec, rows) as IdbAggregateResult<Spec>;\n }\n\n groupBy<Fields extends FieldTuple<TContract, ModelName>>(\n ...fields: Fields\n ): IdbGroupedAccessor<TContract, ModelName, Fields> {\n const combined = this.#combinedFilterExpr();\n const materialize = (ast: IdbQueryAst): Promise<Record<string, unknown>[]> =>\n this.#materialize(this.#newGroupingKey(), ast);\n return createGroupedAccessor<TContract, ModelName, Fields>({\n modelName: this.#modelName,\n by: fields as readonly string[],\n where: combined,\n materialize,\n });\n }\n\n async create(data: MutationCreateInput<TContract, ModelName>): Promise<DefaultModelRow<TContract, ModelName>> {\n const record = data as Record<string, unknown>;\n\n if (hasNestedMutationCallbacks(this.#contract, this.#modelName, record)) {\n const row = await executeNestedCreateMutation({\n executor: requireTransactionExecutor(this.#executor),\n contract: this.#contract,\n modelName: this.#modelName,\n data: record,\n });\n return row as DefaultModelRow<TContract, ModelName>;\n }\n\n if (hasScalarFkFields(this.#contract, this.#modelName, record)) {\n const row = await executeScalarCreateWithFkValidation({\n executor: requireTransactionExecutor(this.#executor),\n contract: this.#contract,\n modelName: this.#modelName,\n data: record,\n });\n return row as DefaultModelRow<TContract, ModelName>;\n }\n\n const groupingKey = this.#newGroupingKey();\n const meta = this.#planMeta(groupingKey);\n const withDefaults = applyCreateDefaults(\n this.#contract.execution?.mutations.defaults,\n this.#storeName,\n record,\n createMutationDefaultsCache()\n );\n const ast: IdbCreateAst = { kind: \"create\", modelName: this.#modelName, data: withDefaults };\n const plan: IdbQueryPlan<Record<string, unknown>> = {\n meta,\n ast,\n idbPlan: { meta, kind: \"add\", storeName: this.#storeName, record: withDefaults },\n };\n // The IDB driver echoes the stored record back as the single result row.\n for await (const row of this.#executor.query(plan)) {\n return row as DefaultModelRow<TContract, ModelName>;\n }\n return withDefaults as DefaultModelRow<TContract, ModelName>;\n }\n\n async findUnique(key: KeyType<TContract, ModelName>): Promise<DefaultModelRow<TContract, ModelName> | null> {\n const groupingKey = this.#newGroupingKey();\n const meta = this.#planMeta(groupingKey);\n const ast: IdbFindUniqueAst = { kind: \"findUnique\", modelName: this.#modelName, key };\n const plan: IdbQueryPlan<Record<string, unknown>> = {\n meta,\n ast,\n idbPlan: { meta, kind: \"key-get\", storeName: this.#storeName, key: key as IDBValidKey },\n };\n for await (const row of this.#executor.query(plan)) {\n return row as DefaultModelRow<TContract, ModelName>;\n }\n return null;\n }\n\n async delete(key: KeyType<TContract, ModelName>): Promise<void> {\n if (hasEnforceableChildRelations(this.#contract, this.#modelName)) {\n await executeDeleteWithReferentialActions({\n executor: requireTransactionExecutor(this.#executor),\n contract: this.#contract,\n modelName: this.#modelName,\n key: key as IDBValidKey,\n });\n return;\n }\n const groupingKey = this.#newGroupingKey();\n const meta = this.#planMeta(groupingKey);\n const ast: IdbDeleteAst = { kind: \"delete\", modelName: this.#modelName, key };\n const plan: IdbQueryPlan<Record<string, unknown>> = {\n meta,\n ast,\n idbPlan: { meta, kind: \"delete\", storeName: this.#storeName, key: key as IDBValidKey },\n };\n // The driver echoes the deleted row, but this API returns void — drain\n // via toArray() just to execute the plan and discard the result.\n await this.#executor.query(plan).toArray();\n }\n\n async update(\n patch: MutationUpdateInput<TContract, ModelName>\n ): Promise<DefaultModelRow<TContract, ModelName> | null> {\n const patchRecord = patch as Record<string, unknown>;\n\n if (hasNestedMutationCallbacks(this.#contract, this.#modelName, patchRecord)) {\n const row = await executeNestedUpdateMutation({\n executor: requireTransactionExecutor(this.#executor),\n contract: this.#contract,\n modelName: this.#modelName,\n filters: this.#state.filters,\n data: patchRecord,\n });\n return row as DefaultModelRow<TContract, ModelName> | null;\n }\n\n // Always routes through the transaction scope, whether or not the patch\n // touches a scalar FK field — same reasoning as `updateAll()` below: the\n // matched row isn't known until the scan-write actually runs (`.where()`\n // filters on ANY field, not just the primary key), and only the\n // transaction-scope path lets the sync interceptor observe that REAL row\n // and key it correctly (`SyncInterceptingTransactionScope#maybeTrack`'s\n // `update`/`scan-write` cases), atomically with the write itself.\n //\n // The previous plan-level fallback here (for patches with no FK field)\n // tried to recover the key by statically inspecting the filter AST\n // instead — which only worked for the narrow case of an equality filter\n // directly on the primary key (`.where({ id })`). Any other filter\n // (`.where({ name: \"...\" })`, a range, an OR) left the key unresolved,\n // and the outbox event synced with a raw filter tree the server\n // couldn't apply — or, after an earlier fix, was rejected outright with\n // `Unsupported update: filter does not pin \"id\" by equality`. Routing\n // through the transaction scope unconditionally removes the whole\n // category: the row (and therefore its key) comes from what actually\n // matched, not from re-deriving it from the filter that found it.\n const row = await executeScalarUpdateWithFkValidation({\n executor: requireTransactionExecutor(this.#executor),\n contract: this.#contract,\n modelName: this.#modelName,\n filters: this.#state.filters,\n data: patchRecord,\n });\n return row as DefaultModelRow<TContract, ModelName> | null;\n }\n\n /**\n * Always routes through the transaction scope (`executeBulkUpdateWithFkValidation`),\n * unlike single-row `update()`'s plan-level fallback for the no-FK-field\n * case. A bulk scan-write's affected row set isn't knowable until it\n * actually runs — going through the transaction scope is what lets the\n * sync interceptor observe the real affected rows and write one outbox\n * event per row (see `SyncInterceptingTransactionScope#maybeTrack`'s\n * `scan-write` case), atomically with the write itself, instead of one\n * event for the whole batch with no way to recover which rows it covered.\n */\n updateAll(patch: PatchInput<TContract, ModelName>): AsyncIterableResult<DefaultModelRow<TContract, ModelName>> {\n const contract = this.#contract;\n const modelName = this.#modelName;\n const filters = this.#state.filters;\n const patchRecord = patch as Record<string, unknown>;\n const executor = requireTransactionExecutor(this.#executor);\n return new AsyncIterableResult(\n (async function* (): AsyncGenerator<DefaultModelRow<TContract, ModelName>, void, unknown> {\n const rows = await executeBulkUpdateWithFkValidation({\n executor,\n contract,\n modelName,\n filters,\n data: patchRecord,\n });\n for (const row of rows) yield row as DefaultModelRow<TContract, ModelName>;\n })()\n );\n }\n\n async updateCount(patch: PatchInput<TContract, ModelName>): Promise<number> {\n return (await this.updateAll(patch).toArray()).length;\n }\n\n async upsert(args: {\n create: CreateInput<TContract, ModelName>;\n update: PatchInput<TContract, ModelName>;\n where: WhereFilter<TContract, ModelName>;\n }): Promise<DefaultModelRow<TContract, ModelName>> {\n const keyPath = getKeyPath(this.#contract, this.#modelName);\n const whereExpr = shorthandToFilterExpr(args.where as Record<string, unknown>);\n const matches = (row: Record<string, unknown>): boolean =>\n whereExpr === undefined || evaluateFilter(whereExpr, row);\n const meta = this.#planMeta(this.#newGroupingKey());\n const createRecord = args.create as Record<string, unknown>;\n const patchRecord = args.update as Record<string, unknown>;\n const storeName = this.#storeName;\n const executionDefaults = this.#contract.execution?.mutations.defaults;\n\n // Runs the find-then-write in a single readwrite transaction so there is\n // no check-then-act race window — atomicity is needed both for that and\n // for `onUpdate` referential-action enforcement (a multi-store read +\n // write) on the update branch. Mirrors the vendor's single-statement\n // upsert.\n const exec = requireTransactionExecutor(this.#executor);\n // Defaults are applied here, before store-name collection, rather than\n // inside the transaction: `collectOnUpdateEnforcementStoreNames` only\n // sees fields present in the patch it's given, and an `onUpdate` mutation\n // default can add a field that wasn't in the caller's raw patch — if that\n // field also happens to be a relation's local field, collecting stores\n // from the raw patch would under-declare the transaction's store list.\n // Applying defaults first (a pure function of the patch + static contract\n // config, no row read needed) and reusing the same result throughout\n // keeps enforcement, store collection, and the actual write looking at\n // one consistent effective patch.\n const effectivePatch = applyUpdateDefaults(\n executionDefaults,\n storeName,\n patchRecord,\n createMutationDefaultsCache()\n );\n const { storeNames: onUpdateStoreNames } = collectOnUpdateEnforcementStoreNames(\n this.#contract,\n this.#modelName,\n effectivePatch\n );\n const storeNames = [...new Set([storeName, ...onUpdateStoreNames])];\n return withMutationScope(exec, storeNames, async (scope) => {\n const found = await scope.execute({ meta, kind: \"cursor-scan\", storeName, filter: matches, take: 1 });\n const existing = found[0];\n if (existing === undefined) {\n const record = applyCreateDefaults(executionDefaults, storeName, createRecord, createMutationDefaultsCache());\n const rows = await scope.execute({ meta, kind: \"add\", storeName, record });\n return (rows[0] ?? record) as DefaultModelRow<TContract, ModelName>;\n }\n const key = existing[keyPath] as IDBValidKey;\n await applyReferentialActionsForRowOnUpdate(scope, this.#contract, this.#modelName, existing, effectivePatch);\n const rows = await scope.execute({ meta, kind: \"update\", storeName, key, patch: effectivePatch });\n return (rows[0] ?? existing) as DefaultModelRow<TContract, ModelName>;\n });\n }\n\n createAll(data: CreateInput<TContract, ModelName>[]): AsyncIterableResult<DefaultModelRow<TContract, ModelName>> {\n const groupingKey = this.#newGroupingKey();\n const meta = this.#planMeta(groupingKey);\n // One shared cache for the whole batch — every row in a single createAll()\n // call gets the same generated `temporal.updatedAt()` timestamp, matching\n // SQL's 'query'-stability semantics for the same generator.\n const defaultsCache = createMutationDefaultsCache();\n const executionDefaults = this.#contract.execution?.mutations.defaults;\n const records = data.map((d) =>\n applyCreateDefaults(executionDefaults, this.#storeName, d as Record<string, unknown>, defaultsCache)\n );\n const ast: IdbCreateAllAst = { kind: \"createAll\", modelName: this.#modelName, data: records };\n const plan: IdbQueryPlan<Record<string, unknown>> = {\n meta,\n ast,\n idbPlan: {\n meta,\n kind: \"batch\",\n storeNames: [this.#storeName],\n ops: records.map((record) => ({ meta, kind: \"add\" as const, storeName: this.#storeName, record })),\n },\n };\n const executorQuery = this.#executor.query.bind(this.#executor);\n return new AsyncIterableResult(\n (async function* (): AsyncGenerator<DefaultModelRow<TContract, ModelName>, void, unknown> {\n for await (const row of executorQuery(plan)) {\n yield row as DefaultModelRow<TContract, ModelName>;\n }\n })()\n );\n }\n\n async createCount(data: CreateInput<TContract, ModelName>[]): Promise<number> {\n return (await this.createAll(data).toArray()).length;\n }\n\n /**\n * Always routes through the transaction scope (`executeDeleteAllWithReferentialActions`),\n * not just when there are enforceable child relations to cascade — that\n * function already handles the no-relations case correctly (an empty\n * relation list is a no-op loop), and going through it unconditionally is\n * what lets the sync interceptor's transaction-scope tracking write one\n * outbox event per actually-deleted row instead of one lump event for\n * the whole batch with no way to know which rows it covered. See\n * `updateAll()`'s doc comment for the same reasoning.\n */\n deleteAll(): AsyncIterableResult<DefaultModelRow<TContract, ModelName>> {\n const combined = this.#combinedFilterExpr();\n const filter = combined !== undefined ? (row: Record<string, unknown>) => evaluateFilter(combined, row) : undefined;\n const contract = this.#contract;\n const modelName = this.#modelName;\n const executor = requireTransactionExecutor(this.#executor);\n return new AsyncIterableResult(\n (async function* (): AsyncGenerator<DefaultModelRow<TContract, ModelName>, void, unknown> {\n const rows = await executeDeleteAllWithReferentialActions({\n executor,\n contract,\n modelName,\n ...(filter !== undefined ? { filter } : {}),\n });\n for (const row of rows) yield row as DefaultModelRow<TContract, ModelName>;\n })()\n );\n }\n\n async deleteCount(): Promise<number> {\n return (await this.deleteAll().toArray()).length;\n }\n\n count(): Promise<number> {\n if (this.#includeRefinementMode) {\n // Inside an include() refinement, count() is a scalar-include marker that\n // include() consumes synchronously — not the async terminal below. The\n // IdbIncludeRefinementAccessor type surfaces the IdbIncludeScalar return;\n // this cast bridges count()'s dual runtime role.\n return createIncludeScalar(this.#state) as unknown as Promise<number>;\n }\n return this.#countTerminal();\n }\n\n // ── Private helpers ───────────────────────────────────────────────────────\n\n async #countTerminal(): Promise<number> {\n const groupingKey = this.#newGroupingKey();\n const combined = this.#combinedFilterExpr();\n const fieldToIndexMap =\n typeof IDBKeyRange !== \"undefined\" ? buildFieldToIndexMap(this.#contract, this.#storeName) : undefined;\n\n // OR multi-scan path: count the deduped+filtered union, applying\n // skip/take pagination so count() is consistent with the non-OR path.\n if (fieldToIndexMap !== undefined) {\n const keyPath = getKeyPath(this.#contract, this.#modelName);\n const orHint = extractIndexOrHint(combined, fieldToIndexMap, keyPath);\n if (orHint !== null) {\n const rows = await this.#executeOrRows(orHint, groupingKey, combined);\n let n = rows.length;\n if (this.#state.skip !== undefined) n = Math.max(0, n - this.#state.skip);\n if (this.#state.take !== undefined) n = Math.min(this.#state.take, n);\n return n;\n }\n }\n\n const scanPlan = this.#buildScanPlan<Record<string, unknown>>(groupingKey, fieldToIndexMap);\n // Override the AST kind for middleware introspection — the idbPlan stays cursor-scan.\n const scanAst = scanPlan.ast;\n const ast: IdbCountAst = {\n kind: \"count\",\n modelName: this.#modelName,\n ...(scanAst?.kind === \"findMany\" && scanAst.where !== undefined ? { where: scanAst.where } : {}),\n };\n const plan: IdbQueryPlan<Record<string, unknown>> = { ...scanPlan, ast };\n let n = 0;\n for await (const _ of this.#executor.query(plan)) {\n n++;\n }\n return n;\n }\n\n /**\n * Resolve an `include()` argument pair into an {@link IncludeEntry}: run the\n * optional refinement against a fresh refinement-mode child accessor, then\n * classify the result as a scalar count or a refined collection.\n */\n #resolveIncludeEntry(relation: string, refineFn: ((collection: never) => unknown) | undefined): IncludeEntry {\n if (refineFn === undefined) {\n return { kind: \"collection\", state: emptyAccessorState() };\n }\n\n const rel = getRelation(this.#contract, this.#modelName, relation);\n // v0.12.0: `relation.to` is a CrossReference `{ namespace, model }`.\n const relatedModelName = rel?.to.model ?? relation;\n const child = new IdbStoreAccessorImpl(\n this.#contract,\n relatedModelName,\n this.#executor,\n emptyAccessorState(),\n this.#newGroupingKey,\n /* includeRefinementMode */ true\n );\n\n const refined = (refineFn as (c: unknown) => unknown)(child);\n\n if (isIncludeScalar(refined)) {\n if (rel !== undefined && rel.cardinality !== \"1:N\") {\n throw new Error(`include('${relation}'): count() is only supported for to-many (1:N) relations`);\n }\n return { kind: \"scalar\", fn: refined.fn, state: refined.state };\n }\n\n // Cross-instance private access is allowed within the class body.\n if (refined instanceof IdbStoreAccessorImpl) {\n return { kind: \"collection\", state: refined.#state };\n }\n\n throw new Error(\n `include('${relation}') refinement must return the collection (for where/orderBy/take/skip) or a count() selector`\n );\n }\n\n /**\n * Materialise all rows matching the accumulated filters with no pagination —\n * used by `aggregate()` / `groupBy()`. The supplied `ast` is attached to the\n * scan plan so middleware can observe the aggregate intent.\n */\n async #materialize(groupingKey: string, ast: IdbQueryAst): Promise<Record<string, unknown>[]> {\n const combined = this.#combinedFilterExpr();\n const filter = combined !== undefined ? (row: Record<string, unknown>) => evaluateFilter(combined, row) : undefined;\n const meta = this.#planMeta(groupingKey);\n const plan: IdbQueryPlan<Record<string, unknown>> = {\n meta,\n ast,\n idbPlan: {\n meta,\n kind: \"cursor-scan\",\n storeName: this.#storeName,\n ...(filter !== undefined ? { filter } : {}),\n },\n };\n const rows: Record<string, unknown>[] = [];\n for await (const row of this.#executor.query(plan)) {\n rows.push(row);\n }\n return rows;\n }\n\n #buildScanPlan<Row>(groupingKey: string, fieldToIndexMap?: Record<string, string>): IdbQueryPlan<Row> {\n const combined = this.#combinedFilterExpr();\n const comparator = buildRowComparator(this.#state.orderBy);\n const meta = this.#planMeta(groupingKey);\n const ast: IdbFindManyAst = {\n kind: \"findMany\",\n modelName: this.#modelName,\n ...(combined !== undefined ? { where: combined } : {}),\n ...(this.#state.orderBy !== undefined ? { orderBy: this.#state.orderBy as Record<string, \"asc\" | \"desc\"> } : {}),\n ...(this.#state.skip !== undefined ? { skip: this.#state.skip } : {}),\n ...(this.#state.take !== undefined ? { take: this.#state.take } : {}),\n };\n\n // Attempt to peel an indexed equality condition from the combined filter\n // and use a cursor-scan over the index with a point range. This avoids\n // a full store scan when IDBKeyRange is available (browser / fake-indexeddb).\n if (typeof IDBKeyRange !== \"undefined\") {\n const fieldToIndexName = fieldToIndexMap ?? buildFieldToIndexMap(this.#contract, this.#storeName);\n const keyPath = getKeyPath(this.#contract, this.#modelName);\n const hint = extractIndexEqualityHint(combined, fieldToIndexName, keyPath);\n if (hint !== null) {\n const { indexName, value, remainingFilter } = hint;\n const filter =\n remainingFilter !== undefined\n ? (row: Record<string, unknown>) => evaluateFilter(remainingFilter, row)\n : undefined;\n return {\n meta,\n ast,\n idbPlan: {\n meta,\n kind: \"cursor-scan\" as const,\n storeName: this.#storeName,\n ...(indexName !== undefined ? { indexName } : {}),\n range: IDBKeyRange.only(value as IDBValidKey),\n ...(filter !== undefined ? { filter } : {}),\n ...(comparator !== undefined ? { comparator } : {}),\n ...(this.#state.skip !== undefined ? { skip: this.#state.skip } : {}),\n ...(this.#state.take !== undefined ? { take: this.#state.take } : {}),\n },\n } as IdbQueryPlan<Row>;\n }\n }\n\n // Fallback: full cursor scan.\n const filter = combined !== undefined ? (row: Record<string, unknown>) => evaluateFilter(combined, row) : undefined;\n // exactOptionalPropertyTypes: spread conditionally to avoid `undefined`\n // values in optional fields.\n return {\n meta,\n ast,\n idbPlan: {\n meta,\n kind: \"cursor-scan\" as const,\n storeName: this.#storeName,\n ...(filter !== undefined ? { filter } : {}),\n ...(comparator !== undefined ? { comparator } : {}),\n ...(this.#state.skip !== undefined ? { skip: this.#state.skip } : {}),\n ...(this.#state.take !== undefined ? { take: this.#state.take } : {}),\n },\n } as IdbQueryPlan<Row>;\n }\n\n /**\n * Execute one cursor-scan per OR branch, union the results, deduplicate by\n * primary key, and apply `hint.remainingFilter` in-memory. Skip/take are\n * NOT applied here — the caller slices the array after union so pagination\n * is correct across branches.\n */\n async #executeOrRows(\n hint: IndexOrHint,\n groupingKey: string,\n combined: IdbFilterExpr | undefined\n ): Promise<Record<string, unknown>[]> {\n const meta = this.#planMeta(groupingKey);\n const storeName = this.#storeName;\n const keyPath = getKeyPath(this.#contract, this.#modelName);\n const seen = new Set<unknown>();\n const rows: Record<string, unknown>[] = [];\n const ast: IdbFindManyAst = {\n kind: \"findMany\",\n modelName: this.#modelName,\n ...(combined !== undefined ? { where: combined } : {}),\n };\n\n // Branches are independent index scans — run them concurrently, then\n // merge/dedupe sequentially (first-branch-wins) so results stay\n // deterministic regardless of completion order.\n const branchResults = await Promise.all(\n hint.branches.map(async (branch) => {\n const plan: IdbQueryPlan<Record<string, unknown>> = {\n meta,\n ast,\n idbPlan: {\n meta,\n kind: \"cursor-scan\" as const,\n storeName,\n ...(branch.indexName !== undefined ? { indexName: branch.indexName } : {}),\n range: IDBKeyRange.only(branch.value as IDBValidKey),\n },\n };\n const branchRows: Record<string, unknown>[] = [];\n for await (const row of this.#executor.query(plan)) {\n branchRows.push(row);\n }\n return branchRows;\n })\n );\n for (const branchRows of branchResults) {\n for (const row of branchRows) {\n const pk = row[keyPath];\n if (!seen.has(pk)) {\n seen.add(pk);\n rows.push(row);\n }\n }\n }\n\n if (hint.remainingFilter === undefined) return rows;\n const { remainingFilter } = hint;\n return rows.filter((row) => evaluateFilter(remainingFilter, row));\n }\n\n /**\n * Combine all accumulated filter expressions with AND.\n *\n * Returns `undefined` when no filter has been installed so the driver can\n * skip building a row filter closure (a small perf and readability win on\n * `.all()` paths). Delegates to the shared {@link combineFilterExprs}.\n */\n #combinedFilterExpr(): IdbFilterExpr | undefined {\n return combineFilterExprs(this.#state.filters);\n }\n\n async #applyIncludes(rows: Record<string, unknown>[], groupingKey: string): Promise<Record<string, unknown>[]> {\n const relNames = Object.keys(this.#state.includes);\n if (relNames.length === 0) return rows;\n let result = rows;\n for (const relName of relNames) {\n const entry = this.#state.includes[relName]!;\n result = await loadRelation(relName, entry, result, this.#contract, this.#modelName, this.#executor, groupingKey);\n }\n return result;\n }\n\n /**\n * Apply a `.select()` projection (if any) to materialised rows. Keeps the\n * selected scalar fields plus every included relation key (which `include()`\n * attached during {@link #applyIncludes}); a no-op when nothing is selected.\n */\n #projectRows(rows: Record<string, unknown>[]): Record<string, unknown>[] {\n const selected = this.#state.selectedFields;\n if (selected === undefined) return rows;\n const keep = [...selected, ...Object.keys(this.#state.includes)];\n return rows.map((row) => {\n const out: Record<string, unknown> = {};\n for (const field of keep) {\n if (field in row) out[field] = row[field];\n }\n return out;\n });\n }\n\n #planMeta(groupingKey: string): PlanMeta {\n return {\n target: \"idb\",\n storageHash: this.#contract.storage.storageHash,\n lane: \"idb-orm\",\n annotations: { groupingKey },\n };\n }\n\n #clone(overrides: Partial<IdbAccessorState>): IdbStoreAccessorImpl<TContract, ModelName, TIncludes, TSelected> {\n return new IdbStoreAccessorImpl(\n this.#contract,\n this.#modelName,\n this.#executor,\n mergeAccessorState(this.#state, overrides),\n this.#newGroupingKey,\n this.#includeRefinementMode\n );\n }\n}\n","import type { Contract } from \"@prisma/orm-framework/contract/types\";\nimport type { IdbContract, IdbStorage } from \"./types\";\nimport type { IdbQueryExecutor } from \"./executor\";\nimport { type IdbStoreAccessor, IdbStoreAccessorImpl } from \"./store-accessor\";\n\n// ── Public types ──────────────────────────────────────────────────────────────\n\n/**\n * The ORM client object returned by {@link idbOrm}.\n *\n * Keys are the root keys from `contract.roots` (e.g. `\"users\"`, `\"posts\"`).\n * Each value is an {@link IdbStoreAccessor} targeting the corresponding model.\n *\n * @example\n * ```ts\n * const db = idbOrm({ contract, executor: runtime });\n * const users = await db.users.all(); // IdbStoreAccessor<..., \"User\">\n * ```\n */\nexport type IdbOrmClient<TContract extends Contract<IdbStorage>> = {\n // v0.12.0: `roots` values are CrossReference `{ namespace, model }`, so the\n // target model name is `roots[K].model` (was a bare model-name string).\n readonly [K in string & keyof TContract[\"roots\"]]: TContract[\"roots\"][K] extends {\n model: infer ModelName extends string;\n }\n ? IdbStoreAccessor<TContract, ModelName>\n : never;\n};\n\n/**\n * Options for {@link idbOrm}.\n */\nexport interface IdbOrmOptions<TContract extends IdbContract> {\n /** The resolved IDB contract (with or without attached type maps). */\n readonly contract: TContract;\n /**\n * The query executor.\n *\n * Any object with a compatible `query()` signature satisfies this —\n * most commonly an `IdbRuntime` created via `createIdbRuntime()`.\n */\n readonly executor: IdbQueryExecutor;\n}\n\n// ── Factory function ──────────────────────────────────────────────────────────\n\n/**\n * Create a typed IDB ORM client from a contract and executor.\n *\n * The client exposes one `IdbStoreAccessor` per entry in `contract.roots`.\n * Only roots-declared stores are accessible at the top level — other stores\n * can be reached via `.include()` on any accessor.\n *\n * @example\n * ```ts\n * import { idbOrm } from \"@prisma-idb/client-idb/orm\";\n * import { createIdbRuntime } from \"@prisma-idb/runtime-idb/runtime\";\n * import contract from \"./prisma/idb-contract\";\n *\n * const runtime = createIdbRuntime({ adapter, driver });\n * const db = idbOrm({ contract, executor: runtime });\n *\n * // Typed query builder:\n * const alice = await db.users.where({ email: \"alice@example.com\" }).first();\n * const postsWithAuthor = await db.posts.include(\"author\").all();\n * ```\n */\nexport function idbOrm<TContract extends IdbContract>(options: IdbOrmOptions<TContract>): IdbOrmClient<TContract> {\n const { contract, executor } = options;\n\n // One counter per idbOrm() call — two clients in the same realm get\n // independent key sequences and can't interleave (ADR 160).\n let _key = 0;\n const newGroupingKey = () => `idb-op-${++_key}`;\n\n const client: Record<string, IdbStoreAccessor<TContract, string>> = {};\n for (const [rootKey, ref] of Object.entries(contract.roots)) {\n // v0.12.0: `roots` values are CrossReference `{ namespace, model }`.\n client[rootKey] = new IdbStoreAccessorImpl(contract, ref.model, executor, undefined, newGroupingKey);\n }\n\n return client as unknown as IdbOrmClient<TContract>;\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"idb-orm-zCRkkD_D.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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"}
|