import { dV as SqlFragment, aZ as Cardinality, N as NodeInsertClaim, m as InsertEdgeParams, E as EdgeConvergenceMatch, l as SchemaWriteFenceParams, ek as UpsertFulltextParams, bG as DeleteFulltextParams, ej as UpsertFulltextBatchParams, bF as DeleteFulltextBatchParams, cw as FulltextSearchParams, cL as HybridSearchParams, j as InsertNodeParams, dc as ManagedNodeCreatePlan, ed as UpdateNodeParams, b8 as CompareAndSetNodeParams, ee as UpdateNodeSetParams, dI as ResolvedNodeUpdateBatchParams, bH as DeleteNodeParams, cG as HardDeleteNodeParams, o as ClaimEdgeCardinalityParams, ec as UpdateEdgeParams, bC as DeleteEdgeParams, bD as DeleteEdgesBatchParams, cF as HardDeleteEdgeParams, bt as CountEdgesFromParams, bW as EdgeExistsBetweenParams, cq as FindEdgesConnectedToParams, cr as FindNodesByKindParams, bu as CountNodesByKindParams, cp as FindEdgesByKindParams, aO as FindEdgesByEndpointSetParams, co as FindEdgesByHeterogeneousEndpointSetParams, bs as CountEdgesByKindParams, cZ as InsertUniqueParams, bI as DeleteUniqueParams, cI as HardDeleteUniquesByNodeIdsParams, cH as HardDeleteUniquesByConcreteKindParams, b2 as CheckUniqueParams, b1 as CheckUniqueBatchParams, dn as PurgeEdgeClaimsParams, F as FenceSql, cY as InsertSchemaParams, dt as RecordContributionMaterializationParams, bi as ContributionMaterializationIdentity, s as SqlDialect, d as FulltextStrategy, V as VectorStrategy, hN as WriteFenceTarget, hO as SchemaWriteTransactionBackend, b9 as CompiledRowsSql, W as WriteFencePlan, f as SchemaVersionRow, ab as SerializedSchema, e1 as TableContribution, du as RecordIndexMaterializationParams, dv as RecordKindRemovalParams, dJ as ResolvedSqlTableNames, a2 as BackendCapabilities, S as SchemaProvisioning, aT as BackendCatalogProbes, d5 as LineageMembers, bZ as EngineRecordedTimeMembers } from './types-BynPp5kU.js'; import { SQL, AnyColumn } from 'drizzle-orm'; import { C as CompiledAtomicSqlStatement, a as AtomicSqlBatchExecutor, Z as AtomicNodePostimageEntry, x as AtomicNodeBatchEntry, k as AtomicEdgeConvergenceEntry, K as AtomicNodeProjectionFamily, R as AtomicNodeResolvedUpdateEntry, D as AtomicNodeBatchResultMode, N as AtomicNodeReplacementEntry, H as AtomicNodeDeleteBatchInput, v as AtomicEdgeResolvedUpdateEntry, p as AtomicEdgeDeleteBatchInput } from './atomic-mutation-program-BhP75Qn0.js'; /** * A relation plus the names its PRIMARY KEY constraint can carry — how far a * duplicate-key classification is allowed to reach on an engine that reports the * violated constraint by name. See {@link isDuplicatePrimaryKeyError}. */ type PrimaryKeyRelation = Readonly<{ table: string; constraintNames: readonly string[]; /** SQLite/libSQL's remote protocol reports the violated key by columns. */ sqliteColumns: readonly string[]; }>; /** * What we know about the connection a backend's statements land on. * * `independent` is a POSITIVE verdict — a factory looked and found statements * that can run on independent connections. It is not the same runtime state as * a backend nobody audited, which carries no record at all. */ type BackendResourceAudit = Readonly<{ kind: "serialized"; resource: object; }> | Readonly<{ kind: "independent"; /** Stable key for the SQLite identity arm of an explicit declaration. */ identityLeaseResource?: object; }>; /** * Declare the connection this backend serializes on, when TypeGraph cannot * detect it (Bun `SQL`, `expo-sqlite`, `op-sqlite`, `sqlite-proxy`, `pg-proxy`, * a postgres-js pool capped through a string the driver does not coerce — the * KNOWN GAPS in this module's inventory). Two wrappers that pass the same * object are treated as one serialized resource, exactly as two wrappers over a * detected client are. * * - `"detect"` (the default, and the same behavior as omitting the option): * whatever the factory's driver predicates find, and nothing else. * - `"shared"`: the given object IS the serialized resource. Refused with a * {@link ConfigurationError} when the factory detected a DIFFERENT resource — * silently overriding would let two wrappers over one handle be given two * different sentinels and quietly de-serialize a pair that really does share. * - `"independent"`: statements can run on independent connections. The * documented escape hatch for a mis-detection, so a user surprised by a * refusal is never stuck. * * SCOPE — read this before using `"independent"`: this option controls the * SHARED-RESOURCE arm of {@link snapshotExportContention} only. It cannot lift * the object-identity arm, under which ONE SQLite backend object exporting into * ITSELF is refused with `same-sqlite-backend`. That arm is a driver fact (one * handle, one open snapshot transaction), not a claim about connection * topology, so no declaration can make it false. * * That surviving arm is SQLITE-ONLY, deliberately: it is gated on * `dialect === "sqlite"`, so on Postgres a backend declared `"independent"` * exporting into ITSELF is not refused either — a Postgres client that hands * out independent connections is exactly what the declaration claims, and the * snapshot and the writes it contends with land on different ones. */ type SerializedResourceDeclaration = Readonly<{ mode: "detect"; }> | Readonly<{ mode: "shared"; resource: object; }> | Readonly<{ mode: "independent"; }>; /** * Exact durable contribution marker required by one atomic SQL program. * * The signature is resolved locally from the active strategy declaration. The * program proves this complete identity against durable database state inside * the same atomic submission as the projection write, so a cold backend does * not need a separate marker-read round trip before dispatch. */ type AtomicContributionEvidence = Readonly<{ graphId: string; logicalName: string; owner: string; tableName: string; signature: string; }>; /** * Shared building blocks for the * `typegraph_contribution_materializations` durable-marker table on * both SQLite and Postgres backends (#135). * * Independent sibling of `index-materializations.ts`. It deliberately * mirrors that module's shape — dialect timestamp adapter, raw-row * mapper, insert/upsert value builders, the `materialized_at` COALESCE * preservation rule for failed re-attempts — but stays a separate * module because the two status tables have different identities: * declared indexes key on a database-global physical index name, * #129 contributions key on `(graph_id, logical_name, owner, * table_name)`. The declared-index path is untouched by #135; a future * PR may migrate it onto this contribution model. */ /** * Raw shape Drizzle returns for one row of * `typegraph_contribution_materializations`. The caller has already * narrowed via the typed table query; this just spells out the * dialect-shared field set so `mapContributionMaterializationRow` can * decode it. */ type RawContributionMaterializationRow = Readonly<{ graphId: string; logicalName: string; owner: string; tableName: string; signature: string; materializedAt: unknown; lastAttemptedAt: unknown; lastError: string | null; }>; type ExecutableSql = SQL | SqlFragment; type CompiledSqlQuery = CompiledAtomicSqlStatement; /** * A driver-native, all-or-nothing group of compiled statements. * * This is intentionally an optional execution surface. Most SQL drivers only * expose one-statement execution through Drizzle; drivers with a native batch * primitive can provide it without making callers guess whether a sequence is * actually transactional. The static name is deliberate: this hook submits a * complete batch to a native primitive and is not an interactive transaction * runner. */ type PreparedSqlStatement = Readonly<{ execute: (params: readonly unknown[]) => Promise; }>; type SqlExecutionAdapter = Readonly<{ compile: (query: ExecutableSql) => CompiledSqlQuery; execute: (query: ExecutableSql) => Promise; executeCompiled?: (compiledQuery: CompiledSqlQuery) => Promise; /** Executes all statements atomically when the native driver supports it. */ executeAtomicBatch?: AtomicSqlBatchExecutor; prepare?: (sqlText: string) => PreparedSqlStatement; /** * Runs `critical` with exclusive use of the connection: no statement from * anywhere else can interleave with the ones it issues. * * Statement-at-a-time serialization is not enough for a *sequence* that must * be atomic. `SET LOCAL` around a query is the motivating case — snapshot, * set, select, restore. Two searches whose statements merely take turns can * still interleave as `A snapshot → B snapshot → A set → B set → A select`, * and `A` then runs under `B`'s settings. * * `critical` is handed the unqueued adapter, so it must not attempt to * re-enter the queue. Present only on transaction-scoped (serialized) * adapters; a pooled adapter needs no exclusion because every statement gets * its own connection. */ runExclusive?: (critical: (connection: SqlExecutionAdapter) => Promise) => Promise; /** * Recognizes this engine's own commit-conflict shape when it is not * PostgreSQL's `40001`/`40P01` SQLSTATE (or the fixed message fallback for * a driver that drops the code). `createSqlBackend` registers this * classifier against the exact backend object it returns; `isSerializationFailure` * (`src/utils/sql-errors.ts`) consults it before falling back to its own * SQLSTATE/message rules, so there remains ONE predicate every retry owner * calls, never a second inline check for engines this covers. */ serializationFailure?: (error: unknown) => boolean; }>; /** * Edge claims — what an edge write reserves on a declared cardinality axis. * * A declared cardinality is a predicate over `(kind, from)` or * `(kind, from, to)`, and the edges relation's only uniqueness is its * `(graph_id, id)` primary key, so nothing in the schema re-decides at write * time what the probe decided at read time. This module is the reservation that * does: one row per `(graph_id, axis, key)` in `typegraph_edge_claims`, whose * primary key refuses a second concurrent claimant. * * The claim needs no release path. A claim whose holder is no longer live (or, * for `oneActive`, no longer active) fails the liveness predicate the takeover * statement carries and is taken over in place, so the fence never depends on * any delete path having run. `purgeEdgeClaims` exists to bound table growth, * not to make the fence correct. */ /** A cardinality that declares something — `many` declares nothing. */ type ConstrainedCardinality = Exclude; /** One node batch member, carrying its stable ordinal into claim SQL. */ type AtomicNodeClaimEntry = Readonly<{ memberOrdinal: number; claimOrdinal: number; entry: TEntry; claim: NodeInsertClaim; }>; type ClearGraphStatement = Readonly<{ query: ExecutableSql; ignoreMissingTable?: boolean; requiredTableName?: string; }>; /** * Inputs for the dialect-specific edge convergence statement. * * `matchOn` is deliberately a call-level key: it is validated against the * edge schema by the store before it reaches this backend seam. The statement * still treats absent properties distinctly from JSON `null`, matching the * store's own-property comparison. */ type ConvergeEdgeCreateParams = Readonly<{ params: InsertEdgeParams; match: EdgeConvergenceMatch; timestamp: string; schemaFence?: SchemaWriteFenceParams; schemaLockClause?: SQL; }>; type AtomicConvergeEdgesParams = Readonly<{ entries: readonly AtomicEdgeConvergenceEntry[]; timestamp: string; schemaFence: SchemaWriteFenceParams; schemaLockClause: SQL; }>; type CommonOperationStrategy = Readonly<{ atomicNodeProjectionFamilies: readonly AtomicNodeProjectionFamily[]; /** Terminal NOT NULL sentinel shared by resolved mutation-set programs. */ /** * The exact NOT NULL sentinels emitted by the closed edge-batch program. * Derive them from the same table definitions as the SQL so error * classification cannot drift when a physical column is renamed. */ atomicEdgeRefusalConstraints: Readonly<{ cardinality: Readonly<{ table: string; column: string; }>; deleteIdentity: Readonly<{ table: string; column: string; }>; durableIdentity: Readonly<{ table: string; column: string; }>; endpoint: Readonly<{ table: string; column: string; }>; mutationPostimage: Readonly<{ table: string; column: string; }>; tombstoneConvergence: Readonly<{ table: string; column: string; }>; }>; atomicNodeRefusalConstraints: Readonly<{ deleteRestricted: Readonly<{ table: string; column: string; }>; liveIdentity: Readonly<{ table: string; column: string; }>; mutationPostimage: Readonly<{ table: string; column: string; }>; projectionEvidence: Readonly<{ table: string; column: string; }>; }>; /** * The nodes and edges PRIMARY KEY constraints, as the engine names them — the * only scope in which a driver duplicate-key failure means "this identity is * already taken" rather than "these values collide with another row's". * * Data rather than SQL, and a member of this interface rather than a lookup at * the classification site, so it is derived once from the same `tables` the * insert builders render and every dialect is forced by the type checker to * supply it. */ primaryKeyConstraints: Readonly<{ nodes: PrimaryKeyRelation; edges: PrimaryKeyRelation; }>; buildUpsertFulltext: (params: UpsertFulltextParams, timestamp: string) => readonly SQL[]; buildDeleteFulltext: (params: DeleteFulltextParams) => readonly SQL[]; buildDeleteFulltextByNode: (graphId: string, nodeKind: string, nodeId: string) => readonly SQL[]; buildUpsertFulltextBatch: (params: UpsertFulltextBatchParams, timestamp: string) => readonly SQL[]; buildDeleteFulltextBatch: (params: DeleteFulltextBatchParams) => readonly SQL[]; buildFulltextSearch: (params: FulltextSearchParams) => SQL; /** * Composes the single-statement hybrid search: the caller supplies the * vector source SQL (strategy-owned); this member builds the fulltext * source over the same candidate set and fuses both via * {@link buildHybridSearchStatement}. */ buildHybridSearch: (params: HybridSearchParams, vectorSql: SQL, vectorScoreDescending: boolean) => SQL; buildInsertNode: (params: InsertNodeParams, timestamp: string) => SQL; buildInsertNodeIfAbsent: (params: InsertNodeParams, timestamp: string) => SQL; buildInsertNodeIfAbsentWithSchemaFence: (params: InsertNodeParams, timestamp: string, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildInsertNodeWithSchemaFence: (params: InsertNodeParams, timestamp: string, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildInsertNodeWithProjections?: (params: InsertNodeParams, plan: ManagedNodeCreatePlan, timestamp: string, schemaLockClause?: SQL) => SQL | undefined; buildAtomicNodeProjectionStatements: (creates: readonly AtomicNodePostimageEntry[], updates: readonly AtomicNodeResolvedUpdateEntry[], timestamp: string, chunkSize: number) => readonly SQL[] | undefined; buildInsertNodeNoReturn: (params: InsertNodeParams, timestamp: string) => SQL; buildInsertNodesBatch: (params: readonly InsertNodeParams[], timestamp: string) => SQL; buildInsertNodesBatchReturning: (params: readonly InsertNodeParams[], timestamp: string) => SQL; buildInsertNodesBatchWithSchemaFence: (params: readonly InsertNodeParams[], timestamp: string, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildAtomicNodeBatchWithSchemaFence: (entries: readonly AtomicNodeBatchEntry[], timestamp: string, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL, resultMode: AtomicNodeBatchResultMode, writeGate?: SQL) => SQL; buildAtomicNodeReplacementBatchWithSchemaFence: (entries: readonly AtomicNodeReplacementEntry[], timestamp: string, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL, writeGate?: SQL) => SQL; buildAtomicNodeClaimUpsertWithSchemaFence: (entries: readonly AtomicNodeClaimEntry[], schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildAtomicNodeClaimGatePredicateWithSchemaFence: (entries: readonly AtomicNodeClaimEntry[], schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildAtomicNodeClaimCleanupWithSchemaFence: (entries: readonly AtomicNodeClaimEntry[], schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildAtomicDeletedNodeClaimReleaseWithSchemaFence: (input: Readonly<{ graphId: string; kind: string; ids: readonly string[]; timestamp: string; }>, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildAtomicNodeReplacementClaimReleaseWithSchemaFence: (input: Readonly<{ graphId: string; kind: string; ids: readonly string[]; timestamp: string; }>, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildGetNode: (graphId: string, kind: string, id: string) => SQL; buildGetNodes: (graphId: string, kind: string, ids: readonly string[]) => SQL; buildUpdateNode: (params: UpdateNodeParams, timestamp: string) => SQL; buildAtomicNodeResolvedUpdateBatch: (entries: readonly AtomicNodeResolvedUpdateEntry[], timestamp: string, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildAssertAtomicNodeMutationPostimages: (creates: readonly AtomicNodePostimageEntry[], updates: readonly AtomicNodeResolvedUpdateEntry[], timestamp: string, schemaFence: SchemaWriteFenceParams) => SQL; buildAssertAtomicNodeProjectionEvidence: (timestamp: string, evidence: readonly AtomicContributionEvidence[]) => SQL; buildReadAtomicNodeMutationPostimages: (graphId: string, kind: string, ids: readonly string[], schemaFence: SchemaWriteFenceParams) => SQL; buildUpdateNodeSet: (params: CompareAndSetNodeParams | UpdateNodeSetParams, timestamp: string) => SQL; buildResolvedNodeUpdateBatch: (params: ResolvedNodeUpdateBatchParams, timestamp: string) => SQL; buildDeleteNode: (params: DeleteNodeParams, timestamp: string) => SQL; buildAtomicNodeDeleteBatchWithSchemaFence: (input: AtomicNodeDeleteBatchInput, timestamp: string, schemaLockClause: SQL) => SQL; buildSchemaFenceProbe: (params: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildHardDeleteNode: (params: HardDeleteNodeParams) => SQL; buildInsertEdge: (params: InsertEdgeParams, timestamp: string) => SQL; buildInsertEdgeIfEndpointsLive: (params: InsertEdgeParams, timestamp: string) => SQL; buildInsertEdgeIfEndpointsLiveWithSchemaFence: (params: InsertEdgeParams, timestamp: string, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; /** Single-statement match-key convergence. */ buildConvergeEdgeCreate?: (params: ConvergeEdgeCreateParams) => SQL; /** Closed-program durable convergence and its tombstone revival leg. */ buildAtomicConvergeEdges?: (params: AtomicConvergeEdgesParams) => SQL; buildAtomicConvergeEdgesTombstoneRefusal?: (params: Omit) => SQL; /** PostgreSQL transaction-only claim + endpoint + edge write. */ buildInsertEdgeIfEndpointsLiveWithCardinalityClaim?: (params: InsertEdgeParams, claim: ClaimEdgeCardinalityParams, timestamp: string) => SQL; /** * One statement per cardinality group in the chunk — see * `buildDeleteStaleAtomicEdgeClaims`. A chunk of one edge kind, the ordinary * case, renders exactly one. */ buildDeleteStaleAtomicEdgeClaims: (entries: readonly ClaimEdgeCardinalityParams[], schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => readonly SQL[]; buildAcquireAtomicEdgeClaims: (entries: readonly ClaimEdgeCardinalityParams[], timestamp: string, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => readonly SQL[]; buildAssertAtomicEdgeClaimsOwned: (entries: readonly ClaimEdgeCardinalityParams[], timestamp: string, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => readonly SQL[]; buildInsertEdgeNoReturn: (params: InsertEdgeParams, timestamp: string) => SQL; buildInsertEdgesBatch: (params: readonly InsertEdgeParams[], timestamp: string) => SQL; buildInsertEdgesBatchReturning: (params: readonly InsertEdgeParams[], timestamp: string) => SQL; buildInsertEdgesBatchWithSchemaFence: (params: readonly InsertEdgeParams[], timestamp: string, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildInsertEdgesBatchReturningWithSchemaFence: (params: readonly InsertEdgeParams[], timestamp: string, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildInsertEdgesDurableBatchReturning: (params: readonly InsertEdgeParams[], timestamp: string) => SQL; buildGetEdge: (graphId: string, id: string) => SQL; buildGetEdges: (graphId: string, ids: readonly string[]) => SQL; buildUpdateEdge: (params: UpdateEdgeParams, timestamp: string) => SQL; buildAtomicEdgeResolvedUpdateBatch: (entries: readonly AtomicEdgeResolvedUpdateEntry[], timestamp: string, schemaFence: SchemaWriteFenceParams, schemaLockClause: SQL) => SQL; buildAssertAtomicEdgeMutationPostimages: (creates: readonly InsertEdgeParams[], updates: readonly AtomicEdgeResolvedUpdateEntry[], timestamp: string, schemaFence: SchemaWriteFenceParams) => SQL; buildReadAtomicEdgeMutationPostimages: (graphId: string, ids: readonly string[], schemaFence: SchemaWriteFenceParams) => SQL; buildDeleteEdge: (params: DeleteEdgeParams, timestamp: string) => SQL; buildDeleteEdgesBatch: (params: DeleteEdgesBatchParams, timestamp: string) => SQL; buildAtomicEdgeDeleteBatchWithSchemaFence: (input: AtomicEdgeDeleteBatchInput, timestamp: string, schemaLockClause: SQL) => SQL; buildHardDeleteEdge: (params: HardDeleteEdgeParams) => SQL; buildHardDeleteEdgesBatch: (params: DeleteEdgesBatchParams) => SQL; buildHardDeleteEdgesByNode: (graphId: string, nodeKind: string, nodeId: string) => SQL; buildCountEdgesFrom: (params: CountEdgesFromParams) => SQL; buildEdgeExistsBetween: (params: EdgeExistsBetweenParams) => SQL; buildFindEdgesConnectedTo: (params: FindEdgesConnectedToParams) => SQL; buildFindNodesByKind: (params: FindNodesByKindParams) => SQL; buildCountNodesByKind: (params: CountNodesByKindParams) => SQL; buildFindEdgesByKind: (params: FindEdgesByKindParams) => SQL; /** * Interface member rather than an optional one: every dialect must supply * an endpoint-set read, so the operation can never be silently skipped by a * dialect that forgot it. Both bundled dialects get it from the shared * builder. */ buildFindEdgesByEndpointSet: (params: FindEdgesByEndpointSetParams, endpointIds: readonly string[]) => SQL; buildFindEdgesByHeterogeneousEndpointSet: (params: FindEdgesByHeterogeneousEndpointSetParams, endpoints: FindEdgesByHeterogeneousEndpointSetParams["endpoints"], edgeKinds: readonly string[]) => SQL; buildCountEdgesByKind: (params: CountEdgesByKindParams) => SQL; buildInsertUnique: (params: InsertUniqueParams) => SQL; buildInsertUniqueBatch: (entries: readonly InsertUniqueParams[]) => SQL; buildDeleteUnique: (params: DeleteUniqueParams, timestamp: string) => SQL; buildHardDeleteUniquesByNode: (graphId: string, concreteKind: string, nodeId: string) => SQL; buildHardDeleteUniquesByNodeIds: (params: HardDeleteUniquesByNodeIdsParams) => SQL; /** * Dialect-independent by construction — the fragment names only the * relation and two columns, so the store-side kind-removal cleanup compiles * the identical predicate through its own execution path. */ buildHardDeleteUniquesByConcreteKind: (params: HardDeleteUniquesByConcreteKindParams) => SqlFragment; buildCheckUnique: (params: CheckUniqueParams) => SQL; buildCheckUniqueBatch: (params: CheckUniqueBatchParams) => SQL; /** * The two edge-claim statements, in the order the driver issues them: the * decision-free lock that reports the committed holder, then — only for a * foreign holder — the conditional takeover. Members of this interface rather * than dialect helpers, so the type checker forces both dialects to have them. */ buildLockEdgeClaims: (entries: readonly ClaimEdgeCardinalityParams[], timestamp: string) => SQL; buildLockEdgeClaimGuarded: (params: ClaimEdgeCardinalityParams, timestamp: string) => SQL; buildTakeOverEdgeClaim: (params: ClaimEdgeCardinalityParams, timestamp: string) => SQL; buildTakeOverEdgeClaimGuarded: (params: ClaimEdgeCardinalityParams, timestamp: string) => SQL; buildPurgeEdgeClaims: (params: PurgeEdgeClaimsParams) => SQL; /** * The three read-only fence-audit statements, one per constraint family. * Members of this interface for the same reason the claim statements are: * the type checker forces both dialects to have them, so a family cannot be * audited on one backend and silently skipped on the other. */ buildContendedUniqueRowAudit: (graphId: string, constraintNames: readonly string[]) => SQL; buildContendedEdgeRowAudit: (graphId: string, cardinality: ConstrainedCardinality, edgeKinds: readonly string[]) => SQL; buildDisjointOverlapAudit: (graphId: string, kinds: readonly [string, string]) => SQL; buildGetActiveSchema: (graphId: string) => SQL; /** * PostgreSQL-only dependent schema-row + graph-advisory fence. `fenceSql` * is the resolved fence target's own spelling — never spelled by this * builder itself — so the fused statement and the portable lock sites a * derived profile's `FenceSql` override backs always exclude on the same * key. */ buildLockSchemaVersionAndGraphWrite?: (params: SchemaWriteFenceParams, advisoryLockNamespace: string, fenceSql: FenceSql) => SQL; buildInsertSchema: (params: InsertSchemaParams, timestamp: string) => SQL; buildGetSchemaVersion: (graphId: string, version: number) => SQL; buildSetActiveSchema: (graphId: string, version: number) => Readonly<{ activateVersion: SQL; deactivateAll: SQL; }>; /** * Write one contribution marker row outright (no conflict clause), for * the transaction-scoped stamp a destructive rebuild commits alongside * the DDL that produced it. */ buildInsertContributionMaterialization: (params: RecordContributionMaterializationParams) => SQL; buildDeleteContributionMaterialization: (identity: ContributionMaterializationIdentity) => SQL; buildTableExists: (tableName: string) => SQL; buildClearGraph: (graphId: string) => readonly ClearGraphStatement[]; }>; declare const ENGINE_ASSEMBLY_BRAND: unique symbol; /** * An opaque handle for one dialect's `buildOperations`/`lateMembers` pair. * {@link assembleEngine} is the only constructor, called once by each * bundled builder (`buildSqliteEngineProfile`, `buildPostgresEngineProfile`) * on its own closures; {@link resolveEngineAssembly} is the only way to read * one back out. No other operation on this type is public — an author * deriving a profile carries the base's `assembly` forward by reference * (`deriveEngineProfile`) rather than constructing a new one. */ type EngineAssembly = Readonly<{ readonly [ENGINE_ASSEMBLY_BRAND]: (transaction: TTx) => TTx; }>; type CreateBaseSchemaMembersDeps = Readonly<{ /** Idempotent `CREATE TABLE ...` for the base-schema-version marker table, rendered once by the caller from its own dialect's table-DDL generator. */ baseSchemaVersionsTableDdl: string; /** Runs one idempotent CREATE-shaped DDL statement — the same closure the profile's own `EngineProvisioning.ensureTable` uses. */ ensureTable: (ddl: string) => Promise; /** Runs one DDL statement with no concurrency handling — the profile's own `EngineProvisioning.executeDdl`, exposed here verbatim as the `GraphBackend` member of the same name. */ executeDdl: (ddl: string) => Promise; /** The full set of base-schema DDL statements for a fresh bootstrap — the profile's own `EngineProvisioning.generateDdl`. */ generateDdl: () => readonly string[]; /** * Reads the installed base-schema-version marker, or `undefined` when * none is installed yet. Dialect-owned: it selects through Drizzle's * typed table API directly, and `PgTable`/`SQLiteTable` share no common * supertype. */ readVersion: () => Promise; /** * Monotonically stamps `version` and returns the version observed * afterward. Dialect-owned for the same reason as `readVersion`, and * because the marker row's timestamp column type differs (a `Date` for * PostgreSQL, an ISO-8601 string for SQLite). */ writeVersion: (version: number) => Promise; /** The graph-templates table's own idempotent CREATE, the version-1 adoption step's other half — `graph-template-members.ts`'s `ensureGraphTemplatesTable`. */ ensureGraphTemplatesTable: () => Promise; /** * Idempotent `CREATE TABLE ...` for the write-fence rows relation, the * version-2 adoption step — rendered once by the caller from its own * dialect's table-DDL generator, the same way `baseSchemaVersionsTableDdl` * is. A brand-new relation needs no ALTER-shaped migration, so this step's * `bootstrap` is `"covered-by-generated-ddl"`; `adopt()` still ensures it * for the OFFLINE adoption path, which never calls `generateDdl()`. */ fencesTableDdl: string; /** * Ensures the edge table's match-identity columns, check constraint, and * unique index exist. Dialect-owned: PostgreSQL introspects * `pg_attribute`/`pg_constraint` and runs an additive migration; SQLite * re-reads `PRAGMA table_info` under a duplicate-column retry loop, since * it has no `ADD COLUMN IF NOT EXISTS`. Neither body goes through * `execution.execAll`/`execGet`/`execRun` or `EngineProvisioning`. */ ensureEdgeMatchIdentityStorage: () => Promise; /** * DDL for version-3 adoption: ensure recorded node, edge, and identity-assertion * storage and its structural indexes before creating the changed-since indexes. * Older installations can lack these relations even with a version-1 or * version-2 marker: they originally shipped only in bootstrap DDL. * Dialect factories generate their table and index DDL from the same schema * definitions as bootstrap, then append `sinceIndexAdoptionDdl` for the * `(recordedNodes, recordedEdges, recordedIdentityAssertions)` since indexes. * Fresh bootstrap already creates all of this storage, so the statements * are only exercised by offline `adopt()`. */ sinceIndexDdl: readonly string[]; }>; /** * Contribution-marker bookkeeping: the durable-marker CRUD, the * `ContributionMaterializer` wiring, and the adapter-facing members it * backs — shared verbatim by every SQL engine profile. * * Every marker-table statement goes through one of two seams the caller * supplies rather than through Drizzle's typed table API directly: a * `ContributionMarkerRowAccess` / `ReconciliationMarkerRowAccess` pair for * the two tables' SELECT/INSERT..ON CONFLICT/DELETE, and `ensureTable` / * `execute` for DDL and the catalog probe. Drizzle's own `.from()` / * `.insert()` / `.delete()` builders are typed against each dialect's own * table class (`PgTable` vs `SQLiteTable`) with no common supertype, so one * shared implementation cannot call them directly on a generic table * parameter — the identity-matching, row-decoding, and upsert-shaping logic * lives here instead, and each dialect binds the three-line access closures * to its own `db` and table objects. `ensureTable` and `execute` carry no * such restriction: `EngineProvisioning.ensureTable` and the root execution * adapter's `execute` are already uniform across dialects (SQLite's queue * bypass and PostgreSQL's concurrent-create retry live inside the closures * the caller passes in, unchanged). */ /** The contribution-marker table's identity columns, as generic Drizzle columns. */ type ContributionMarkerColumns = Readonly<{ graphId: AnyColumn; logicalName: AnyColumn; owner: AnyColumn; tableName: AnyColumn; }>; /** * The three statements the contribution-marker table needs, bound to one * dialect's `db` and table object by the caller. `upsert` takes the same * domain params `recordContributionMaterialization` does, rather than a * pre-shaped Drizzle payload: shaping the insert values and the * ON CONFLICT `set` clause (via `buildContributionInsertValues` / * `buildContributionOnConflictSet`) stays inside the per-dialect binding, * where the table's own typed columns are in scope, so Drizzle keeps * checking the payload against the table instead of the call being widened * to `never` to paper over the two dialects' distinct table types. */ type ContributionMarkerRowAccess = Readonly<{ selectWhere: (condition: SQL) => Promise; upsert: (params: RecordContributionMaterializationParams) => Promise; deleteWhere: (condition: SQL) => Promise; }>; /** The reconciliation-marker table's one identity column. */ type ReconciliationMarkerColumns = Readonly<{ graphId: AnyColumn; }>; /** The two statements the reconciliation-marker table needs. See {@link ContributionMarkerRowAccess}. */ type ReconciliationMarkerRowAccess = Readonly<{ selectWhere: (condition: SQL) => Promise[]>; upsert: (graphId: string, version: number) => Promise; }>; type CreateContributionMembersDeps = Readonly<{ dialect: SqlDialect; /** Absent when this backend has no fulltext support (`fulltext: false`). */ fulltextStrategy: FulltextStrategy | undefined; fulltextTableName: string; vectorStrategy: VectorStrategy | undefined; /** ONE fence target the materializer's two lock sites resolve, shared with every other lock this backend can take. */ fenceTarget: WriteFenceTarget; /** Idempotent `CREATE TABLE ...` for the contribution-marker table, rendered once by the caller from its own dialect's table-DDL generator. */ contributionTableDdl: string; /** Idempotent `CREATE TABLE ...` for the reconciliation-marker table. */ reconciliationMarkersTableDdl: string; /** Runs one idempotent CREATE-shaped DDL statement — the same closure the profile's own `EngineProvisioning.ensureTable` uses. */ ensureTable: (ddl: string) => Promise; /** The root execution adapter's raw statement runner, for the uncached catalog probe backing `verifyContributions`. */ execute: (query: ExecutableSql) => Promise; operationStrategy: Pick; /** * Decodes the dialect's timestamp column representation to a canonical * ISO-8601 string. The reverse direction (`encode`) is not a dep here: * shaping the insert payload happens inside `contributionMarkerRows.upsert`, * in the per-dialect binding. */ timestamps: Readonly<{ decode: (value: unknown) => string | undefined; }>; contributionMarkerColumns: ContributionMarkerColumns; contributionMarkerRows: ContributionMarkerRowAccess; reconciliationMarkerColumns: ReconciliationMarkerColumns; reconciliationMarkerRows: ReconciliationMarkerRowAccess; /** * Runs an administrative callback under the same per-graph fence as a * schema commit. Absent on a backend with no transactional schema fence, * which declines the destructive rebuild rather than running it unfenced. */ schemaWriteTransaction?: (graphId: string, fn: (tx: SchemaWriteTransactionBackend) => Promise) => Promise; }>; type InstantiateGraphTemplateSqlParams = Readonly<{ graphId: string; schemaHash: string; schemaVersionsTableName: string; templatesTableName: string; contributionMaterializationsTableName: string; templateId: string; templateSchemaHash: string; }>; type CopyGraphTemplateContributionMarkersSqlParams = Readonly<{ graphId: string; schemaHash: string; schemaVersionsTableName: string; templatesTableName: string; contributionMaterializationsTableName: string; templateId: string; templateSchemaHash: string; }>; /** * Parameters for `registerGraphTemplate`, matching the inline shape on * {@link GraphBackend.registerGraphTemplate} field for field. Kept local * (not exported) so this extraction leaves the public `GraphBackend` * declaration surface untouched; structural typing makes this type * assignable to that member's inline parameter type. */ type RegisterGraphTemplateParams = Readonly<{ templateId: string; schemaHash: string; schemaDoc: SerializedSchema; }>; /** A raw graph-template row, already normalized to canonical strings by the dialect binding. */ type RawGraphTemplateRow = Readonly<{ templateId: string; schemaHash: string; schemaDoc: string; createdAt: string; }>; /** * The two statements graph-template registration needs, bound to one * dialect's `db` and table object by the caller. `insertIgnoringConflict` * carries its own timestamp stamping (`new Date()` for PostgreSQL, `nowIso()` * for SQLite) and its own JSON-document encoding, so those stay inside the * per-dialect binding rather than re-spelled here. */ type GraphTemplateRowAccess = Readonly<{ insertIgnoringConflict: (params: RegisterGraphTemplateParams) => Promise; selectByTemplateId: (templateId: string) => Promise; }>; /** The table names `instantiateStatement` compiles its statement against. */ type GraphTemplateTableNames = Readonly<{ schemaVersions: string; graphTemplates: string; contributionMaterializations: string; }>; /** Runs a compiled statement through the operation-backend layer's row-returning execution path. */ type GraphTemplateExecute = (query: CompiledRowsSql) => Promise; type CreateGraphTemplateMembersDeps = Readonly<{ /** Idempotent `CREATE TABLE ...` for the graph-templates table, rendered once by the caller from its own dialect's table-DDL generator. */ graphTemplatesTableDdl: string; /** Runs one idempotent CREATE-shaped DDL statement — the same closure the profile's own `EngineProvisioning.ensureTable` uses. */ ensureTable: (ddl: string) => Promise; execute: GraphTemplateExecute; tableNames: GraphTemplateTableNames; /** * The resolved write-fence plan `createSqlBackend` closes over once at * construction — the SAME plan every other lock site reads. Read only by * the PostgreSQL binding, to decide whether its schema-row instantiation * needs a preceding fence-row acquisition; SQLite's binding never * consults it. */ fencePlan: WriteFencePlan; /** * The SAME fence target `createSqlBackend` built and registered its * profile-declared serialization classifier against (see * `create-sql-backend.ts`) — read only by the PostgreSQL binding, as the * `target` it hands `runRetriedUnit` when it replays its row-mechanism * instantiation branch under the `"optimistic-retry"` tier. SQLite's * binding never consults it. */ fenceTarget: WriteFenceTarget; /** * Runs this profile's schema-row instantiation and returns its raw driver * rows. SQLite's binding runs the bare `INSERT ... SELECT ... RETURNING` * `graph-template-sql.ts` builds through the `execute` dep unchanged. The * PostgreSQL binding does the same under every fence-plan kind except * `"row"` (see the module doc comment for what it does instead there). */ instantiateStatement: (params: InstantiateGraphTemplateSqlParams, execute: GraphTemplateExecute, fencePlan: WriteFencePlan, fenceTarget: WriteFenceTarget) => Promise[]>; /** Decodes a raw driver row into a `SchemaVersionRow` — the same mapper `OperationBackendRowMappers.toSchemaVersionRow` is. */ toSchemaVersionRow: (row: Record) => SchemaVersionRow; rowAccess: GraphTemplateRowAccess; /** * SQLite's second DML statement copying contribution markers after the * schema row is confirmed (see the module doc comment). Absent on a * dialect whose `instantiateStatement` already folds the marker copy into * its own statement (PostgreSQL). Receives this same group's own * `execute` dep as its first argument rather than closing over one: the * profile head builds this closure before the operation layer exists, so * it cannot capture `execute` directly, and by the time * `instantiateGraphTemplate` actually invokes it below, this function's * own `execute` parameter is already the resolved one. */ copyContributionMarkers?: (execute: GraphTemplateExecute, params: CopyGraphTemplateContributionMarkersSqlParams) => Promise; }>; type CreateIdentityMembersDeps = Readonly<{ /** Idempotent `CREATE TABLE ...` for the revision-origins table, rendered once by the caller from its own dialect's table-DDL generator. */ revisionOriginsTableDdl: string; /** Runs one idempotent CREATE-shaped DDL statement — the same closure the profile's own `EngineProvisioning.ensureTable` uses. */ ensureTable: (ddl: string) => Promise; /** Whether the given physical table name currently exists — the same catalog probe `createContributionMembers` builds. */ contributionTableExists: (tableName: string) => Promise; /** * This dialect's authoritative `TableContribution` set for a * caller-supplied physical-name override — i.e. `xContributions(buildXTables(overrides), fulltextStrategy)`. * Pure: builds Drizzle table objects and walks them, issuing no SQL. The * one seam a shared implementation cannot call directly, for the same * reason `contribution-members.ts` cannot call `.from()` / `.insert()` * on a generic table parameter. */ contributionsForTableNames: (overrides: Readonly>) => readonly TableContribution[]; /** * Names a recorded relation's PRIMARY KEY constraint from its resolved * physical table name (PostgreSQL: `_pkey`, the name the server * derives for the unnamed inline `PRIMARY KEY (…)` both dialects emit). * Absent on a dialect that does not name PRIMARY KEY constraints * separately (SQLite) — `recordedTableDdl` then omits the field entirely * rather than setting it to `undefined`. */ primaryKeyConstraintNameFor?: (tableName: string) => string; }>; /** * Shared building blocks for the `typegraph_index_materializations` * status-table operations on both SQLite and Postgres backends. * * The two dialect adapters used to carry near-identical implementations * of `getIndexMaterialization` and `recordIndexMaterialization`. They * differ only in (a) how timestamps cross the Drizzle boundary — * SQLite stores ISO strings in TEXT columns, Postgres stores `Date` * objects in TIMESTAMPTZ columns — and (b) the raw-DDL exec call used * to bootstrap the table. Everything else (the row shape, the * `onConflictDoUpdate` set clause, the `materializedAt` COALESCE * preservation rule for failed re-attempts) is dialect-agnostic and * lives here. */ /** * Raw shape returned by Drizzle for one row of the * `typegraph_index_materializations` table. The caller has already * narrowed via the typed table query; this type just spells out the * dialect-shared field set so `mapMaterializationRow` can decode it. * Exported so `engine/members/index-materialization-members.ts` can type * the row-access closures each dialect binds to its own table object. */ type RawIndexMaterializationRow = Readonly<{ indexName: string; graphId: string; entity: string; kind: string; signature: string; schemaVersion: number; materializedAt: unknown; lastAttemptedAt: unknown; lastError: string | null; }>; /** * The `typegraph_index_materializations` status-table CRUD: ensuring the * table exists, reading one or many rows, and the `materializedAt`-preserving * upsert — shared verbatim by every SQL engine profile. * * `ensureIndexMaterializationsTable` is not a full mirror: PostgreSQL runs an * additive-column migration (`ADD COLUMN IF NOT EXISTS`) for the build-claim * columns right after the `CREATE TABLE`, for a table created before those * columns existed — a fresh install already has them from the `CREATE` * itself. SQLite has no such migration to run. That asymmetry is threaded * through as the optional `ensureIndexMaterializationColumns` dep, the same * shape `EngineProvisioning` exposes it as, rather than re-spelled here. * * The three row-shaped statements (SELECT one, SELECT many by name, upsert) * go through `rowAccess` rather than Drizzle's typed table API directly, for * the same reason `contribution-members.ts`'s module doc comment gives: * `PgTable` and `SQLiteTable` share no common supertype, so one shared body * cannot call `.from()` / `.insert()` on a generic table parameter. Each * dialect binds the three-line access closures to its own `db` and table * object; the row-shaping and decoding logic (`mapMaterializationRow`, * `buildMaterializationInsertValues`, `buildMaterializationOnConflictSet`) * already lived in `index-materializations.ts` before this extraction and is * unchanged. */ /** * The three statements the index-materializations table needs, bound to one * dialect's `db` and table object by the caller. `upsert` takes the same * domain params `recordIndexMaterialization` does, rather than a pre-shaped * Drizzle payload, so the timestamp encoding and the ON CONFLICT `set` clause * stay inside the per-dialect binding, where the table's own typed columns * are in scope. */ type IndexMaterializationRowAccess = Readonly<{ selectByIndexName: (indexName: string) => Promise; selectByIndexNames: (indexNames: readonly string[]) => Promise; upsert: (params: RecordIndexMaterializationParams) => Promise; }>; type CreateIndexMaterializationMembersDeps = Readonly<{ /** Idempotent `CREATE TABLE ...` for the index-materializations table, rendered once by the caller from its own dialect's table-DDL generator. */ indexMaterializationsTableDdl: string; /** Runs one idempotent CREATE-shaped DDL statement — the same closure the profile's own `EngineProvisioning.ensureTable` uses. */ ensureTable: (ddl: string) => Promise; /** * PostgreSQL's additive-column migration for a table created before the * build-claim columns existed — the same optional hook * `EngineProvisioning.ensureIndexMaterializationColumns` exposes. Absent on * a dialect with no such migration to run (SQLite). */ ensureIndexMaterializationColumns?: (tableName: string) => Promise; /** The index-materializations table's resolved physical name, passed to `ensureIndexMaterializationColumns`. */ tableName: string; /** Decodes the dialect's timestamp column representation to a canonical ISO-8601 string. */ timestamps: Readonly<{ decode: (value: unknown) => string | undefined; }>; rowAccess: IndexMaterializationRowAccess; }>; /** * Shared building blocks for the `typegraph_kind_removals` status-table * operations on both SQLite and Postgres backends. * * Same shape as `index-materializations.ts`: the dialects differ only * in (a) timestamp encoding (SQLite TEXT vs Postgres TIMESTAMPTZ) and * (b) the raw-DDL exec call used to bootstrap the table. The row * mapper, the `onConflictDoUpdate` set clause, and the * `removed_at` COALESCE-on-failure preservation rule are dialect- * agnostic and live here. Two near-identical adapter copies in * `sqlite.ts` / `postgres.ts` collapse to ~15 lines each. */ /** * Raw shape returned by Drizzle for one row of the * `typegraph_kind_removals` table. */ type RawKindRemovalRow = Readonly<{ graphId: string; kindName: string; entity: string; schemaVersion: number; removedAt: unknown; lastAttemptedAt: unknown; lastError: string | null; }>; /** * The `typegraph_kind_removals` status-table CRUD: ensuring the table * exists, reading a graph's pending or all removal rows, and the * `removed_at`-preserving upsert — shared verbatim by every SQL engine * profile. Unlike `index-materialization-members.ts`'s table, this one is a * full mirror: neither dialect runs a migration beyond the initial CREATE. * * The three row-shaped statements (select pending, select all, upsert) go * through `rowAccess` rather than Drizzle's typed table API directly, for * the same reason `index-materialization-members.ts`'s module doc comment * gives: `PgTable` and `SQLiteTable` share no common supertype, so one * shared body cannot call `.from()` / `.insert()` on a generic table * parameter. Each dialect binds the three-line access closures to its own * `db` and table object; the row-shaping and decoding logic * (`mapKindRemovalRow`, `buildKindRemovalInsertValues`, * `buildKindRemovalOnConflictSet`) already lived in `kind-removals.ts` * before this extraction and is unchanged. */ /** * The three statements the kind-removals table needs, bound to one * dialect's `db` and table object by the caller. `upsert` takes the same * domain params `recordKindRemoval` does, rather than a pre-shaped Drizzle * payload, so the timestamp encoding and the ON CONFLICT `set` clause stay * inside the per-dialect binding, where the table's own typed columns are * in scope. */ type KindRemovalRowAccess = Readonly<{ selectPending: (graphId: string) => Promise; selectAll: (graphId: string) => Promise; upsert: (params: RecordKindRemovalParams) => Promise; }>; type CreateKindRemovalMembersDeps = Readonly<{ /** Idempotent `CREATE TABLE ...` for the kind-removals table, rendered once by the caller from its own dialect's table-DDL generator. */ kindRemovalsTableDdl: string; /** Runs one idempotent CREATE-shaped DDL statement — the same closure the profile's own `EngineProvisioning.ensureTable` uses. */ ensureTable: (ddl: string) => Promise; /** Decodes the dialect's timestamp column representation to a canonical ISO-8601 string. */ timestamps: Readonly<{ decode: (value: unknown) => string | undefined; }>; rowAccess: KindRemovalRowAccess; }>; /** Resolved physical table names, uniform across dialects. */ type EngineTableNames = ResolvedSqlTableNames; /** * The DDL primitives a profile owns. Every DDL statement any member group * emits goes through one of these rather than a bare `db.execute` / * `db.run`, so each dialect's wrinkle stays in one place: SQLite's DDL * bypasses its serialized queue on purpose, and PostgreSQL's `ensureTable` * carries a concurrent-create retry because two replicas can boot against * the same database at once. */ type EngineProvisioning = Readonly<{ /** * Runs ONE DDL statement with no concurrency handling — the semantics of * the adapter's own `executeDdl` member. Never use it for a create that * two booting processes can race; that is what `ensureTable` is for. */ executeDdl: (ddl: string) => Promise; /** * Runs one already-rendered `CREATE ...` statement idempotently, carrying * the dialect's concurrent-create retry where the engine needs one * (PostgreSQL). Every bootstrap and `ensure*` path that creates a relation * must use this arm, not `executeDdl`. */ ensureTable: (ddl: string) => Promise; /** The full set of base-schema DDL statements for a fresh bootstrap. */ generateDdl: () => readonly string[]; /** * PostgreSQL's additive-column migration for an index-materializations * table created before the build-claim columns existed. Absent on * dialects with no such migration to run. */ ensureIndexMaterializationColumns?: (tableName: string) => Promise; /** * The physical-schema introspection surface `createSqlBackend` forwards * onto the assembled backend's `catalog` member unchanged. Optional: a * profile that omits it produces a backend with no `catalog`, exactly * like any other optional `GraphBackend` member. */ catalog?: BackendCatalogProbes; /** * The engine-revision and change-delta surface `createSqlBackend` * forwards onto the assembled backend's `lineage` member unchanged. * Optional: a profile that omits it produces a backend with no * `lineage`, exactly like any other optional `GraphBackend` member — * neither bundled Drizzle profile supplies one today, so a store's own * recorded-relations lineage (when history is on) is what backs the * capability instead. */ lineage?: LineageMembers; /** * The engine-native recorded-time source and revision clock * `createSqlBackend` forwards onto the assembled backend's * `recordedTime` member unchanged. Optional: a profile that omits it * produces a backend with no `recordedTime`, exactly like any other * optional `GraphBackend` member — neither bundled Drizzle profile * supplies one today, so `history`/`revisionTracking` always allocate * TypeGraph's own recorded clock and relations instead. A profile that * declares this must also declare `lineage`; `createSqlBackend` refuses * one that declares only `recordedTime`. */ recordedTime?: EngineRecordedTimeMembers; }>; /** * What a profile supplies `createSqlBackend` to build the contribution * member group, beyond what the profile's own head already carries * (`dialect`, `fulltext`, `vector`) and what `createSqlBackend` derives * itself (`fenceTarget` from the finalized capabilities; * `ensureTable`/`execute`/`operationStrategy` from * `provisioning`/`execution`/`strategy`; and `schemaWriteTransaction` from * the fence's own late member, once it exists). See * `members/contribution-members.ts` for what each field does. */ type ContributionRuntime = Omit; /** * What a profile supplies `createSqlBackend` to build the identity/ * recorded-relation member group, beyond `ensureTable` (from `provisioning`) * and `contributionTableExists` (from the contribution member group * `createSqlBackend` builds first). See `members/identity-members.ts`. */ type IdentityRuntime = Omit; /** * What a profile supplies `createSqlBackend` to build the graph-template * member group, beyond `ensureTable` (from `provisioning`), `execute` (the * operation layer's own `execute`, once `createSqlBackend` has built it), * and `fencePlan`/`fenceTarget` (resolved and built once by `createSqlBackend` * before it builds this member group — the same pair every other member * group shares). See `members/graph-template-members.ts`. */ type GraphTemplateRuntime = Omit; /** * What a profile supplies `createSqlBackend` to build the base-schema * lifecycle member group, beyond `ensureTable`/`executeDdl`/`generateDdl` * (from `provisioning`) and `ensureGraphTemplatesTable` (from the * graph-template member group `createSqlBackend` builds first). See * `members/base-schema-members.ts`. */ type BaseSchemaRuntime = Omit; /** * What a profile supplies `createSqlBackend` to build the index- * materializations member group, beyond `ensureTable` / * `ensureIndexMaterializationColumns` (both from `provisioning`). See * `members/index-materialization-members.ts`. */ type IndexMaterializationRuntime = Omit; /** * What a profile supplies `createSqlBackend` to build the kind-removals * member group, beyond `ensureTable` (from `provisioning`). See * `members/kind-removal-members.ts`. */ type KindRemovalRuntime = Omit; /** * Everything one SQL engine contributes to `createSqlBackend`: a HEAD of * data and dialect closures that exist before any backend object does, * including the opaque `assembly` that wraps the operation-backend builder * and the late-member factory for the members that need the assembled * pipeline (see the module doc comment for why the split exists). * * First-party standing — `resolveWriteFencePlan`'s dialect-derivation * fallback (sound only for the two bundled dialects) and the lazy * schema-fence lease `store/operations/write-transaction.ts` takes out * under `isFirstPartyFactory` — is not a field on this type. It is bound to * the exact object `buildSqliteEngineProfile` / `buildPostgresEngineProfile` * returned, via `isFirstPartyProfile` (`../../capabilities/write-fence`), an * identity check `createSqlBackend` runs on the `profile` argument it * receives. A copy, spread, or otherwise derived profile is a new object * that check has never seen, so it never carries this standing forward — * no field could grant it the way a spread grants every other key. */ type SqlEngineProfile = Readonly<{ /** * The dialect this profile is for. `createSqlBackend` threads it through * unexamined — into the write-fence declaration line, the fence-target * marker, and the profile-refusal error — never branches on it itself. */ dialect: SqlDialect; tableNames: EngineTableNames; /** * Every statement any shared member group issues goes through this * adapter's `execAll`/`execGet`/`execRun`, which is where a dialect * serializes its own SQL over its own driver. */ execution: SqlExecutionAdapter; /** * The dialect's SQL-fragment strategy (table/column resolution, JSON and * locking-clause construction) the operation-backend layer assembles * its writes and reads against. */ strategy: CommonOperationStrategy; /** * The dialect's full-text search strategy, or `undefined` when this * backend has no fulltext support (`fulltext: false`). Feeds capability * derivation and search compilation. */ fulltext: FulltextStrategy | undefined; /** The dialect's vector-search strategy, or `undefined` when this connection has no vector extension loaded. */ vector: VectorStrategy | undefined; /** The dialect's declared capabilities, before its capability tail runs. */ declaredCapabilities: BackendCapabilities; /** Adapter policy for provisioning inside caller-owned schema transactions. */ schemaProvisioning: SchemaProvisioning; /** * The serialized-resource verdict {@link createSqlBackend} records once, * before the backend object escapes (see `../../transaction-resource.ts`). */ resourceAudit: BackendResourceAudit; /** * Declares whether a single statement outside an explicit transaction has * this engine's full durability and atomicity. `createSqlBackend` marks * the backend's bundled root autocommit-eligible on this word alone — a * profile that gets it wrong makes callers trust a write that is not yet * durable. */ autocommit: Readonly<{ singleStatementDurable: boolean; }>; provisioning: EngineProvisioning; /** * The lock-statement spelling this engine's fence plan carries when it * resolves to `lock`: `createSqlBackend` folds it into the one fence * target it builds, and the backend advertises it as `fenceSql`. Absent * on an engine whose fence is `engine-serialized`. */ fenceSql?: FenceSql; /** Deps for the contribution-marker member group; see {@link ContributionRuntime}. */ contributionRuntime: ContributionRuntime; /** Deps for the identity/recorded-relation member group; see {@link IdentityRuntime}. */ identityRuntime: IdentityRuntime; /** Deps for the graph-template member group; see {@link GraphTemplateRuntime}. */ graphTemplateRuntime: GraphTemplateRuntime; /** Deps for the base-schema lifecycle member group; see {@link BaseSchemaRuntime}. */ baseSchemaRuntime: BaseSchemaRuntime; /** Deps for the index-materializations member group; see {@link IndexMaterializationRuntime}. */ indexMaterializationRuntime: IndexMaterializationRuntime; /** Deps for the kind-removals member group; see {@link KindRemovalRuntime}. */ kindRemovalRuntime: KindRemovalRuntime; /** The `GraphBackend` member of the same name. */ close: () => Promise; /** * This dialect's operation-backend builder and late-member factory, * wrapped opaquely — see {@link EngineAssembly} (`./assembly`) for what it * hides and why. Bundled-only: the two builders are the only callers of * `assembleEngine`, `createSqlBackend` resolves it once via * `resolveEngineAssembly`, and `deriveEngineProfile` carries a base * profile's `assembly` forward by reference rather than building its own. */ assembly: EngineAssembly; }>; export type { BackendResourceAudit as B, ContributionRuntime as C, EngineAssembly as E, GraphTemplateRuntime as G, IdentityRuntime as I, KindRemovalRuntime as K, SerializedResourceDeclaration as S, SqlEngineProfile as a, BaseSchemaRuntime as b, EngineProvisioning as c, EngineTableNames as d, IndexMaterializationRuntime as e };