@prisma-next/target-sqlite 0.14.0-dev.6 → 0.14.0-dev.60

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.
Files changed (72) hide show
  1. package/dist/contract-free.mjs +1 -1
  2. package/dist/control.d.mts +3 -4
  3. package/dist/control.d.mts.map +1 -1
  4. package/dist/control.mjs +16 -27
  5. package/dist/control.mjs.map +1 -1
  6. package/dist/{descriptor-meta-DxmEeTJ-.mjs → descriptor-meta-D1fap-5t.mjs} +4 -11
  7. package/dist/descriptor-meta-D1fap-5t.mjs.map +1 -0
  8. package/dist/descriptor-meta-runtime-BkXK3OjD.mjs +12 -0
  9. package/dist/descriptor-meta-runtime-BkXK3OjD.mjs.map +1 -0
  10. package/dist/migration.d.mts +2 -2
  11. package/dist/migration.mjs +2 -2
  12. package/dist/native-type-normalizer.mjs +13 -1
  13. package/dist/native-type-normalizer.mjs.map +1 -0
  14. package/dist/{op-factory-call-DmdfD1yd.mjs → op-factory-call-Do03QgD9.mjs} +134 -117
  15. package/dist/op-factory-call-Do03QgD9.mjs.map +1 -0
  16. package/dist/op-factory-call.d.mts +2 -2
  17. package/dist/op-factory-call.d.mts.map +1 -1
  18. package/dist/op-factory-call.mjs +1 -1
  19. package/dist/pack.mjs +1 -1
  20. package/dist/planner-DGhzXuGh.mjs +848 -0
  21. package/dist/planner-DGhzXuGh.mjs.map +1 -0
  22. package/dist/{planner-produced-sqlite-migration-0xPEm3R1.mjs → planner-produced-sqlite-migration-BDzhFAoW.mjs} +46 -17
  23. package/dist/planner-produced-sqlite-migration-BDzhFAoW.mjs.map +1 -0
  24. package/dist/{planner-produced-sqlite-migration-CpgsY-M9.d.mts → planner-produced-sqlite-migration-o1qUzwLk.d.mts} +3 -3
  25. package/dist/{planner-produced-sqlite-migration-CpgsY-M9.d.mts.map → planner-produced-sqlite-migration-o1qUzwLk.d.mts.map} +1 -1
  26. package/dist/planner-produced-sqlite-migration.d.mts +1 -1
  27. package/dist/planner-produced-sqlite-migration.mjs +1 -1
  28. package/dist/planner.d.mts +47 -11
  29. package/dist/planner.d.mts.map +1 -1
  30. package/dist/planner.mjs +1 -1
  31. package/dist/runtime.d.mts +6 -4
  32. package/dist/runtime.d.mts.map +1 -1
  33. package/dist/runtime.mjs +3 -3
  34. package/dist/{shared-Dhc8mLK1.d.mts → shared-C6sM-wel.d.mts} +2 -2
  35. package/dist/{shared-Dhc8mLK1.d.mts.map → shared-C6sM-wel.d.mts.map} +1 -1
  36. package/dist/{sqlite-contract-serializer--iaDgC8e.mjs → sqlite-contract-view-BEwi0mUC.mjs} +34 -9
  37. package/dist/sqlite-contract-view-BEwi0mUC.mjs.map +1 -0
  38. package/dist/sqlite-contract-view-J32K82Gi.d.mts +29 -0
  39. package/dist/sqlite-contract-view-J32K82Gi.d.mts.map +1 -0
  40. package/dist/sqlite-migration-BNiSiP0z.mjs +123 -0
  41. package/dist/sqlite-migration-BNiSiP0z.mjs.map +1 -0
  42. package/dist/{sqlite-migration-DVfhQwN_.d.mts → sqlite-migration-BYbzskpE.d.mts} +35 -6
  43. package/dist/sqlite-migration-BYbzskpE.d.mts.map +1 -0
  44. package/package.json +18 -18
  45. package/src/core/control-target.ts +13 -18
  46. package/src/core/errors.ts +14 -12
  47. package/src/core/migrations/column-ddl-rendering.ts +177 -0
  48. package/src/core/migrations/diff-database-schema.ts +230 -0
  49. package/src/core/migrations/issue-planner.ts +361 -488
  50. package/src/core/migrations/op-factory-call.ts +5 -0
  51. package/src/core/migrations/operations/tables.ts +107 -68
  52. package/src/core/migrations/planner-strategies.ts +118 -137
  53. package/src/core/migrations/planner.ts +117 -30
  54. package/src/core/migrations/render-typescript.ts +42 -15
  55. package/src/core/migrations/runner.ts +4 -10
  56. package/src/core/migrations/sqlite-migration.ts +69 -31
  57. package/src/core/sqlite-contract-serializer.ts +29 -14
  58. package/src/core/sqlite-contract-view.ts +41 -0
  59. package/src/core/sqlite-schema-verifier.ts +6 -3
  60. package/src/core/sqlite-unbound-database.ts +8 -8
  61. package/src/exports/runtime.ts +1 -0
  62. package/dist/descriptor-meta-DxmEeTJ-.mjs.map +0 -1
  63. package/dist/native-type-normalizer-CiSyVmMP.mjs +0 -14
  64. package/dist/native-type-normalizer-CiSyVmMP.mjs.map +0 -1
  65. package/dist/op-factory-call-DmdfD1yd.mjs.map +0 -1
  66. package/dist/planner-Ciq8p_dL.mjs +0 -622
  67. package/dist/planner-Ciq8p_dL.mjs.map +0 -1
  68. package/dist/planner-produced-sqlite-migration-0xPEm3R1.mjs.map +0 -1
  69. package/dist/sqlite-contract-serializer--iaDgC8e.mjs.map +0 -1
  70. package/dist/sqlite-migration-A0rwqPOG.mjs +0 -92
  71. package/dist/sqlite-migration-A0rwqPOG.mjs.map +0 -1
  72. package/dist/sqlite-migration-DVfhQwN_.d.mts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner-DGhzXuGh.mjs","names":["exhaustive","#lowerer"],"sources":["../src/core/migrations/diff-database-schema.ts","../src/core/migrations/column-ddl-rendering.ts","../src/core/migrations/planner-strategies.ts","../src/core/migrations/issue-planner.ts","../src/core/migrations/planner.ts"],"sourcesContent":["import type { ColumnDefault, Contract, ControlPolicy } from '@prisma-next/contract/types';\nimport type { NativeTypeExpander, SqlSchemaDiffResult } from '@prisma-next/family-sql/control';\nimport { buildNativeTypeExpander, contractToSchemaIR } from '@prisma-next/family-sql/control';\nimport { verifySqlSchemaByDiff } from '@prisma-next/family-sql/diff';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n SchemaDiffIssue,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport { diffSchemas } from '@prisma-next/framework-components/control';\nimport { entityAt } from '@prisma-next/framework-components/ir';\nimport type { SqlStorage, StorageColumn, StorageTable } from '@prisma-next/sql-contract/types';\nimport type {\n SqlColumnIRInput,\n SqlSchemaIRInput,\n SqlSchemaIRNode,\n SqlTableIRInput,\n} from '@prisma-next/sql-schema-ir/types';\nimport { relationalNodeGranularity, SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { renderDefaultLiteral } from './planner-ddl-builders';\n\ninterface SqliteDiffDatabaseSchemaInput {\n readonly contract: Contract<SqlStorage>;\n readonly actualSchema: SqlSchemaIRNode;\n readonly strict: boolean;\n readonly typeMetadataRegistry: ReadonlyMap<string, { readonly nativeType?: string }>;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;\n}\n\n/** Renders a column default for the SQLite dialect. */\nexport function sqliteRenderDefault(def: ColumnDefault, _column: StorageColumn): string {\n if (def.kind === 'function') {\n if (def.expression === 'now()') {\n return \"datetime('now')\";\n }\n return def.expression;\n }\n return renderDefaultLiteral(def.value);\n}\n\n/**\n * The SQLite expected-side projection: contract → flat relational schema IR.\n *\n * `extras` thread the plan-time derivation input: the native-type expander,\n * so the expected side carries resolved native types (like the verify\n * side). Every expected column also carries its `codecRef` unconditionally\n * (Decision 5) — the planner's op-builders resolve DDL rendering from it at\n * plan time, so no separate render stamper is threaded here.\n */\nexport function sqliteContractToSchema(\n contract: Contract<SqlStorage> | null,\n extras?: {\n readonly expandNativeType?: NativeTypeExpander;\n },\n): SqlSchemaIR {\n // SQLite is single-schema: every contract FK targets the unbound namespace\n // node, so derivation stamps no referenced namespace — the same absence\n // flat introspection produces — and the derived expected FK pairs with its\n // introspected counterpart by construction. No pre-diff pass, no flag.\n return contractToSchemaIR(contract, {\n annotationNamespace: 'sqlite',\n renderDefault: sqliteRenderDefault,\n ...ifDefined('expandNativeType', extras?.expandNativeType),\n });\n}\n\n/**\n * The SQLite schema verify: the full-tree node-diff verdict wrapped in the\n * issue-based result envelope. Used by the runner's post-apply check; the\n * family `verifySchema` runs the same composition via the descriptor hook.\n */\nexport function verifySqliteDatabaseSchema(\n input: SqliteDiffDatabaseSchemaInput,\n): VerifyDatabaseSchemaResult {\n return verifySqlSchemaByDiff({\n contract: input.contract,\n schema: input.actualSchema,\n strict: input.strict,\n frameworkComponents: input.frameworkComponents,\n diffSchema: diffSqliteSchema,\n granularityOf: relationalNodeGranularity,\n });\n}\n\n/**\n * Resolves a verdict-diff issue's subject table's declared control policy\n * directly from the contract. SQLite's expected tree is flat, so the issue\n * path carries no namespace segment — `path[1]` is the table name (`path[0]`\n * is the tree root's own id); every contract namespace is searched for that\n * table name (table names are globally unique in the flat tree — duplicates\n * across namespaces are rejected earlier, at `contractToSchemaIR`).\n */\nfunction resolveControlPolicy(\n issue: SchemaDiffIssue,\n contract: Contract<SqlStorage>,\n): ControlPolicy | undefined {\n const tableName = issue.path[1];\n if (tableName === undefined) return undefined;\n for (const namespaceId of Object.keys(contract.storage.namespaces)) {\n const table = entityAt<StorageTable>(contract.storage, {\n namespaceId,\n entityKind: 'table',\n entityName: tableName,\n });\n if (table !== undefined) return table.control;\n }\n return undefined;\n}\n\n/**\n * The SQLite full-tree node diff for the family verify verdict: derive the\n * expected flat tree with resolved leaf values (expander threaded so\n * parameterized types compare expanded; FK nodes born with the flat empty\n * `resolvedReferencedNamespace`), and run the generic differ over the trees\n * as derived. Flat targets need no ownership scoping. The codec `verifyType`\n * hooks run once per contract namespace with tables, each against the sole\n * flat actual root — exactly the legacy per-namespace pairing.\n */\nexport function diffSqliteSchema(input: {\n readonly contract: Contract<SqlStorage>;\n readonly schema: SqlSchemaIRNode;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;\n}): SqlSchemaDiffResult {\n const expandNativeType = buildNativeTypeExpander(input.frameworkComponents);\n const expected = sqliteContractToSchema(input.contract, {\n ...ifDefined('expandNativeType', expandNativeType),\n });\n const actual =\n input.schema instanceof SqlSchemaIR\n ? input.schema\n : blindCast<\n SqlSchemaIR,\n 'the SQLite introspection adapter always produces a flat SqlSchemaIR root'\n >(input.schema);\n const issues = diffSchemas(expected, actual);\n const namespacesWithTables = Object.values(input.contract.storage.namespaces).filter(\n (ns) => Object.keys(ns.entries.table ?? {}).length > 0,\n );\n return {\n issues,\n resolveControlPolicy: (issue) => resolveControlPolicy(issue, input.contract),\n namespacePairs: namespacesWithTables.map(() => ({ actual })),\n };\n}\n\nexport interface SqlitePlanDiff {\n /** The desired (\"end\") tree — resolved leaf values, incl. `codecRef`, on every column. */\n readonly expected: SqlSchemaIR;\n /** The live (\"start\") tree. */\n readonly actual: SqlSchemaIR;\n readonly issues: readonly SchemaDiffIssue[];\n}\n\n/**\n * The SQLite planner's diff input: the same tree-building\n * `diffSqliteSchema` uses (expander threaded, FK nodes born flat). One differ\n * drives both verify and plan over the trees as derived; this is the plan-side\n * derivation — column DDL resolves from each expected column's `codecRef` at\n * plan time (`column-ddl-rendering.ts`), so no separate render stamping happens here.\n */\nexport function buildSqlitePlanDiff(input: {\n readonly contract: Contract<SqlStorage>;\n readonly actualSchema: SqlSchemaIRNode;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;\n}): SqlitePlanDiff {\n const expandNativeType = buildNativeTypeExpander(input.frameworkComponents);\n const expected = sqliteContractToSchema(input.contract, {\n ...ifDefined('expandNativeType', expandNativeType),\n });\n // The differ dispatches polymorphically (`.isEqualTo()` / `.children()`), so\n // the actual tree must be genuine `SqlSchemaIR`/`SqlTableIR`/`SqlColumnIR`\n // instances, not plain data shaped like them. `new SqlSchemaIR(...)`\n // normalizes either input uniformly (an already-real tree passes through\n // untouched — its nested values are already instances) and is a no-op\n // rebuild in the common (real-instance) case, so this is always safe to run.\n const actual = new SqlSchemaIR(withRecordKeyNames(input.actualSchema));\n const issues = diffSchemas(expected, actual);\n return { expected, actual, issues };\n}\n\n/**\n * Every schema-tree builder in this codebase derives a table's / column's\n * `name` from the record key it's stored under (`contractToSchemaIR`,\n * the SQLite introspection adapter) rather than trusting a redundant\n * embedded field — the record key IS the identity. Mirrors that discipline\n * for the actual/live tree before construction, so `SqlTableIR.id` /\n * `SqlColumnIR.id` (both derived from `.name`) are always correct without\n * requiring every caller to duplicate the key onto the value. A no-op for a\n * tree that already carries matching names (the real introspection adapter\n * always does).\n */\nfunction withRecordKeyNames(actualSchema: SqlSchemaIRNode): SqlSchemaIRInput {\n const raw = blindCast<\n { readonly tables?: Readonly<Record<string, unknown>> },\n 'the SQLite introspection adapter always produces a flat, tables-keyed root'\n >(actualSchema);\n const tables: Record<string, SqlTableIRInput> = {};\n for (const [tableName, table] of Object.entries(raw.tables ?? {})) {\n const rawTable = blindCast<\n Omit<SqlTableIRInput, 'name' | 'columns'>,\n 'every table value in a tables record is SqlTableIR(Input)-shaped'\n >(table);\n const columns: Record<string, SqlColumnIRInput> = {};\n for (const [columnName, column] of Object.entries(\n blindCast<\n { readonly columns?: Readonly<Record<string, unknown>> },\n 'every SqlTableIR(Input) carries a columns record keyed by column name'\n >(table).columns ?? {},\n )) {\n columns[columnName] = {\n ...blindCast<\n SqlColumnIRInput,\n 'every column value in a columns record is SqlColumnIR(Input)-shaped'\n >(column),\n name: columnName,\n };\n }\n tables[tableName] = {\n ...rawTable,\n name: tableName,\n columns,\n foreignKeys: rawTable.foreignKeys ?? [],\n uniques: rawTable.uniques ?? [],\n indexes: rawTable.indexes ?? [],\n };\n }\n return { tables };\n}\n","import type { StorageColumn } from '@prisma-next/sql-contract/types';\nimport {\n DdlColumn,\n type DdlTableConstraint,\n ForeignKeyConstraint,\n FunctionColumnDefault,\n LiteralColumnDefault,\n PrimaryKeyConstraint,\n UniqueConstraint,\n} from '@prisma-next/sql-relational-core/ast';\nimport type { SqlColumnIR, SqlTableIR } from '@prisma-next/sql-schema-ir/types';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport type { SqliteColumnSpec } from './operations/shared';\nimport { buildColumnDefaultSql, buildColumnTypeSql } from './planner-ddl-builders';\n\n/**\n * Reconstructs the `StorageColumn`-shaped fields `buildColumnTypeSql` /\n * `buildColumnDefaultSql` expect, from a column node's own stamped codec\n * identity (`codecRef` / `codecBaseNativeType`, Decision 5) — never the\n * contract. SQLite's type renderer only uppercases the resolved base type\n * (no parameterized expansion, no named-type quoting), so `typeRef` is\n * deliberately left unset here: setting it would send `buildColumnTypeSql`\n * back through a live `storageTypes` lookup the node's fields have already\n * resolved past, which throws for an unrecognized reference (unlike\n * Postgres's lenient fallback).\n */\nfunction columnLike(\n column: SqlColumnIR,\n): Pick<StorageColumn, 'nativeType' | 'codecId' | 'nullable' | 'many' | 'typeParams' | 'default'> {\n if (column.codecRef === undefined || column.codecBaseNativeType === undefined) {\n throw new Error(\n `columnLike: expected column \"${column.name}\" carries no codec identity — the expected tree must be derived via contractToSchemaIR for planning`,\n );\n }\n return {\n nativeType: column.codecBaseNativeType,\n codecId: column.codecRef.codecId,\n nullable: column.nullable,\n // `column.many` is unset on contract-derived columns (array-ness rides\n // on the `nativeType` `[]` suffix there instead) — `codecRef.many`\n // carries it. Hand-built/introspected columns set `column.many` directly.\n ...((column.many ?? column.codecRef.many) !== undefined\n ? { many: column.many ?? column.codecRef.many }\n : {}),\n ...(column.codecRef.typeParams !== undefined\n ? {\n typeParams: blindCast<\n Record<string, unknown>,\n 'CodecRef.typeParams is JsonValue-shaped; the DDL builders only ever read it as the Record the contract column originally carried'\n >(column.codecRef.typeParams),\n }\n : {}),\n ...(column.resolvedDefault !== undefined ? { default: column.resolvedDefault } : {}),\n };\n}\n\nfunction sqliteDefaultToDdlColumnDefault(\n columnDefault: StorageColumn['default'],\n): DdlColumn['default'] {\n if (!columnDefault) return undefined;\n switch (columnDefault.kind) {\n case 'literal':\n return new LiteralColumnDefault(columnDefault.value);\n case 'function':\n // `autoincrement()` is not a DEFAULT clause — SQLite encodes it as\n // `INTEGER PRIMARY KEY AUTOINCREMENT` inline on the column. Skip it\n // here; the renderer also has a defensive guard for the same case.\n if (columnDefault.expression === 'autoincrement()') return undefined;\n return new FunctionColumnDefault(columnDefault.expression);\n default: {\n const exhaustive: never = columnDefault;\n throw new Error(\n `sqliteDefaultToDdlColumnDefault: unhandled kind \"${blindCast<{ kind: string }, 'exhaustiveness: surface the unhandled default kind'>(exhaustive).kind}\"`,\n );\n }\n }\n}\n\n/**\n * True when the column is rendered inline as `INTEGER PRIMARY KEY\n * AUTOINCREMENT` — the sole member of the table's primary key with an\n * `autoincrement()` default. Node-based sibling of the retired\n * `isInlineAutoincrementPrimaryKey` (which read the raw `StorageTable`);\n * reads the table/column nodes instead.\n */\nexport function isInlineAutoincrementPrimaryKeyNode(\n table: SqlTableIR,\n column: SqlColumnIR,\n): boolean {\n if (table.primaryKey?.columns.length !== 1) return false;\n if (table.primaryKey.columns[0] !== column.name) return false;\n return (\n column.resolvedDefault?.kind === 'function' &&\n column.resolvedDefault.expression === 'autoincrement()'\n );\n}\n\n/**\n * Builds the flat `SqliteColumnSpec` `AddColumnCall` / `RecreateTableCall`\n * need, resolved from the column node's codec identity — the same builders\n * the pre-`plan(start, end)` op-path called, so the output is\n * byte-identical.\n */\nexport function columnSpecFromNode(column: SqlColumnIR, inline: boolean): SqliteColumnSpec {\n const like = columnLike(column);\n const typeSql = buildColumnTypeSql(like, {});\n const defaultSql = buildColumnDefaultSql(like.default);\n return {\n name: column.name,\n typeSql,\n defaultSql,\n nullable: column.nullable,\n ...(inline ? { inlineAutoincrementPrimaryKey: true } : {}),\n };\n}\n\n/**\n * Builds the `DdlColumn` the `CreateTableCall` path needs, resolved from the\n * column node's codec identity.\n */\nexport function ddlColumnFromNode(column: SqlColumnIR, inline: boolean): DdlColumn {\n const like = columnLike(column);\n const typeSql = buildColumnTypeSql(like, {});\n if (inline) {\n // `DdlColumn` has no SQLite-specific autoincrement flag, so the full\n // `PRIMARY KEY AUTOINCREMENT` clause is embedded in the `type` string.\n // The DDL renderer (`ddl-renderer.ts`) substring-detects `AUTOINCREMENT`\n // to suppress the normal NOT NULL / PRIMARY KEY / DEFAULT clause rendering\n // and emit the entire type string verbatim. Both sites must stay in sync.\n // The structural fix (a SQLite-specific column option) is tracked in TML-2866.\n return new DdlColumn({ name: column.name, type: `${typeSql} PRIMARY KEY AUTOINCREMENT` });\n }\n const colDefault = sqliteDefaultToDdlColumnDefault(like.default);\n return new DdlColumn({\n name: column.name,\n type: typeSql,\n ...(!column.nullable ? { notNull: true } : {}),\n ...(colDefault !== undefined ? { default: colDefault } : {}),\n ...(column.codecRef !== undefined ? { codecRef: column.codecRef } : {}),\n });\n}\n\n/**\n * Builds the table-level constraints (PK / unique / FK) for a `CreateTable`\n * path from the table node — the node-sourced sibling of the retired\n * contract-based `tableToDdlParts`'s constraint half.\n */\nexport function tableConstraintsFromNode(\n table: SqlTableIR,\n hasInlinePk: boolean,\n): DdlTableConstraint[] {\n const constraints: DdlTableConstraint[] = [];\n if (table.primaryKey && !hasInlinePk) {\n constraints.push(new PrimaryKeyConstraint({ columns: table.primaryKey.columns }));\n }\n for (const u of table.uniques) {\n constraints.push(\n new UniqueConstraint({\n columns: u.columns,\n ...(u.name !== undefined ? { name: u.name } : {}),\n }),\n );\n }\n for (const fk of table.foreignKeys) {\n constraints.push(\n new ForeignKeyConstraint({\n columns: fk.columns,\n refTable: fk.referencedTable,\n refColumns: fk.referencedColumns,\n ...(fk.name !== undefined ? { name: fk.name } : {}),\n ...(fk.onDelete !== undefined ? { onDelete: fk.onDelete } : {}),\n ...(fk.onUpdate !== undefined ? { onUpdate: fk.onUpdate } : {}),\n }),\n );\n }\n return constraints;\n}\n","/**\n * SQLite migration strategies.\n *\n * Each strategy examines the node-typed issue list, consumes issues it\n * handles, and returns the `SqliteOpFactoryCall[]` to address them. The issue\n * planner runs each strategy in order and routes whatever's left through\n * `mapNodeIssueToCall`.\n *\n * SQLite has no enums, no data-safe backfill, and no component-declared\n * database dependencies. The only recipe that needs strategy-level\n * multi-issue consumption is `recreateTable`, which absorbs\n * type/nullability/default/constraint mismatches for a given table into a\n * single recreate operation.\n */\n\nimport type {\n MigrationOperationClass,\n MigrationOperationPolicy,\n} from '@prisma-next/family-sql/control';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type { SchemaDiffIssue } from '@prisma-next/framework-components/control';\nimport { defaultIndexName } from '@prisma-next/sql-schema-ir/naming';\nimport {\n RelationalSchemaNodeKind,\n type SqlColumnIR,\n type SqlSchemaIR,\n} from '@prisma-next/sql-schema-ir/types';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { columnTypeChanged, tableSpecFromNode } from './issue-planner';\nimport { DataTransformCall, RecreateTableCall, type SqliteOpFactoryCall } from './op-factory-call';\nimport type { SqliteIndexSpec } from './operations/shared';\nimport { buildRecreatePostchecks, buildRecreateSummary } from './operations/tables';\n\nexport interface StrategyContext {\n /** The desired (\"end\") tree — resolved leaf values, incl. `codecRef`. */\n readonly expected: SqlSchemaIR;\n /** The live (\"start\") tree. */\n readonly actual: SqlSchemaIR;\n readonly policy: MigrationOperationPolicy;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;\n}\n\nexport type CallMigrationStrategy = (\n issues: readonly SchemaDiffIssue[],\n context: StrategyContext,\n) =>\n | {\n kind: 'match';\n issues: readonly SchemaDiffIssue[];\n calls: readonly SqliteOpFactoryCall[];\n recipe?: boolean;\n }\n | { kind: 'no_match' };\n\n// ============================================================================\n// Recreate-table strategy\n// ============================================================================\n\n/**\n * Classifies a node issue into the operation class a recreate absorbing it\n * would need, or `null` when the strategy doesn't handle this node/reason at\n * all (table/column not-found-or-not-expected, and index issues — those are\n * standalone ops, never folded into a recreate).\n *\n * Column drift is a single `not-equal` issue now (type AND nullability\n * compared together by `SqlColumnIR.isEqualTo`), so this reads both fields\n * off the node pair directly rather than trusting a separate issue kind per\n * attribute: a type change is always destructive; a pure nullability change\n * is destructive when tightening (NOT NULL required) and widening when\n * relaxing.\n */\nfunction classifyNodeIssue(issue: SchemaDiffIssue): 'widening' | 'destructive' | null {\n const node = issue.expected ?? issue.actual;\n if (node === undefined) return null;\n const nodeKind = blindCast<\n { readonly nodeKind: string },\n 'every diff-tree node declares nodeKind'\n >(node).nodeKind;\n switch (nodeKind) {\n case RelationalSchemaNodeKind.column: {\n if (issue.reason !== 'not-equal') return null;\n const expected = blindCast<SqlColumnIR, 'a not-equal column issue carries the expected node'>(\n issue.expected,\n );\n const actual = blindCast<SqlColumnIR, 'a not-equal column issue carries the actual node'>(\n issue.actual,\n );\n if (columnTypeChanged(expected, actual)) return 'destructive';\n // Type is unchanged, so `not-equal` here means only nullability\n // differs: relaxing (NOT NULL → nullable) is safe; tightening is not.\n return expected.nullable ? 'widening' : 'destructive';\n }\n case RelationalSchemaNodeKind.columnDefault:\n return issue.reason === 'not-expected' ? 'destructive' : 'widening';\n case RelationalSchemaNodeKind.primaryKey:\n case RelationalSchemaNodeKind.foreignKey:\n case RelationalSchemaNodeKind.unique:\n return 'destructive';\n default:\n return null;\n }\n}\n\n/**\n * Groups recreate-eligible issues by table, decides per-table operation class\n * (destructive wins over widening), and emits one `RecreateTableCall` per\n * table. Returns unchanged-or-smaller issue list — issues the strategy\n * consumed are removed so `mapNodeIssueToCall` doesn't double-handle them.\n *\n * The full desired/live table shapes come from `ctx.expected`/`ctx.actual`\n * directly (keyed by table name — SQLite is a flat, single-namespace target)\n * rather than from any individual issue, since a single drifted attribute's\n * issue only carries that attribute's own node, never the whole table.\n */\nexport const recreateTableStrategy: CallMigrationStrategy = (issues, ctx) => {\n const byTable = new Map<string, { issues: SchemaDiffIssue[]; hasDestructive: boolean }>();\n const consumed = new Set<SchemaDiffIssue>();\n\n for (const issue of issues) {\n const cls = classifyNodeIssue(issue);\n if (!cls) continue;\n const tableName = issue.path[1];\n if (tableName === undefined) continue;\n const entry = byTable.get(tableName);\n if (entry) {\n entry.issues.push(issue);\n if (cls === 'destructive') entry.hasDestructive = true;\n } else {\n byTable.set(tableName, { issues: [issue], hasDestructive: cls === 'destructive' });\n }\n consumed.add(issue);\n }\n\n if (byTable.size === 0) return { kind: 'no_match' };\n\n const calls: SqliteOpFactoryCall[] = [];\n for (const [tableName, entry] of byTable) {\n const expectedTable = ctx.expected.tables[tableName];\n const actualTable = ctx.actual.tables[tableName];\n if (!expectedTable || !actualTable) continue;\n const operationClass: MigrationOperationClass = entry.hasDestructive\n ? 'destructive'\n : 'widening';\n\n // Flatten the expected table node to a self-contained spec — the Call\n // holds pre-rendered SQL fragments only, no schema-IR node.\n const tableSpec = tableSpecFromNode(expectedTable);\n\n // Indexes (declared + FK-backing) are already merged and deduped by\n // column-set at derivation (`contractToSchemaIR`'s `convertTable`).\n const indexes: SqliteIndexSpec[] = expectedTable.indexes.map((idx) => ({\n name: idx.name ?? defaultIndexName(tableName, idx.columns),\n columns: idx.columns,\n }));\n\n calls.push(\n new RecreateTableCall({\n tableName,\n contractTable: tableSpec,\n schemaColumnNames: Object.keys(actualTable.columns),\n indexes,\n summary: buildRecreateSummary(tableName, entry.issues),\n postchecks: buildRecreatePostchecks(tableName, entry.issues, tableSpec),\n operationClass,\n }),\n );\n }\n\n return {\n kind: 'match',\n issues: issues.filter((i) => !consumed.has(i)),\n calls,\n recipe: true,\n };\n};\n\n// ============================================================================\n// Nullability-tightening backfill strategy\n// ============================================================================\n\n/**\n * When the policy allows `'data'` and the expected tree tightens one or more\n * columns from nullable to NOT NULL, emit a `DataTransformCall` stub per\n * tightened column. The user fills the backfill `UPDATE` in the rendered\n * `migration.ts` before the subsequent `RecreateTableCall` copies data into\n * the tightened schema (whose `INSERT INTO temp SELECT … FROM old` would\n * otherwise fail at runtime if any `NULL`s remain).\n *\n * Does NOT consume the tightening issue — `recreateTableStrategy` still\n * needs it to produce the actual recreate that enforces the NOT NULL at\n * the schema level. The backfill op and the recreate op end up in the\n * recipe slot in strategy order (backfill first, recreate second), which\n * matches the required execution order.\n *\n * Mirrors Postgres's `nullableTighteningCallStrategy` / `'data'`-class\n * gating. When `'data'` is not in the policy (the default `db update` /\n * `db init` path), the strategy short-circuits and the recreate alone\n * runs with its current destructive-class gating — preserving today's\n * behavior where a tightening blows up at runtime if NULLs are present.\n */\nexport const nullabilityTighteningBackfillStrategy: CallMigrationStrategy = (issues, ctx) => {\n if (!ctx.policy.allowedOperationClasses.includes('data')) {\n return { kind: 'no_match' };\n }\n\n const calls: SqliteOpFactoryCall[] = [];\n for (const issue of issues) {\n if (\n issue.reason !== 'not-equal' ||\n issue.expected === undefined ||\n issue.actual === undefined\n ) {\n continue;\n }\n const expected = blindCast<\n { readonly nodeKind: string },\n 'every diff-tree node declares nodeKind'\n >(issue.expected).nodeKind;\n if (expected !== RelationalSchemaNodeKind.column) continue;\n\n const expectedColumn = blindCast<\n SqlColumnIR,\n 'a not-equal column issue carries the expected node'\n >(issue.expected);\n const actualColumn = blindCast<SqlColumnIR, 'a not-equal column issue carries the actual node'>(\n issue.actual,\n );\n if (expectedColumn.nullable === actualColumn.nullable) continue; // not a nullability change\n if (expectedColumn.nullable) continue; // relaxing — no backfill needed\n\n const tableName = issue.path[1];\n if (tableName === undefined) continue;\n\n calls.push(\n new DataTransformCall(\n `data_migration.backfill-${tableName}-${expectedColumn.name}`,\n `Backfill NULLs in \"${tableName}\".\"${expectedColumn.name}\" before NOT NULL tightening`,\n tableName,\n expectedColumn.name,\n ),\n );\n }\n\n if (calls.length === 0) return { kind: 'no_match' };\n\n return {\n kind: 'match',\n issues,\n calls,\n recipe: true,\n };\n};\n\nexport const sqlitePlannerStrategies: readonly CallMigrationStrategy[] = [\n nullabilityTighteningBackfillStrategy,\n recreateTableStrategy,\n];\n","/**\n * SQLite migration issue planner.\n *\n * Takes node-typed schema-diff issues (from the one differ — see\n * `buildSqlitePlanDiff` in `diff-database-schema.ts`) and emits migration IR\n * (`SqliteOpFactoryCall[]`). Strategies consume issues they recognize and\n * produce specialized call sequences (e.g. `recreateTableStrategy` absorbs\n * type/nullability/default/constraint mismatches into a single recreate op);\n * remaining issues flow through `mapNodeIssueToCall` for the default case.\n *\n * Every branch reads the diff node the issue carries (`issue.expected` /\n * `issue.actual`) — never the contract, never `storageTypes`, never codec\n * hooks. Column DDL resolves from the column node's `codecRef`\n * (`column-ddl-rendering.ts`), never a recomputation against the contract.\n */\n\nimport type {\n MigrationOperationPolicy,\n SqlPlannerConflict,\n SqlPlannerConflictLocation,\n} from '@prisma-next/family-sql/control';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type { SchemaDiffIssue } from '@prisma-next/framework-components/control';\nimport { defaultIndexName } from '@prisma-next/sql-schema-ir/naming';\nimport {\n RelationalSchemaNodeKind,\n type SqlColumnIR,\n type SqlIndexIR,\n SqlSchemaIR,\n type SqlSchemaIRNode,\n type SqlTableIR,\n} from '@prisma-next/sql-schema-ir/types';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport type { Result } from '@prisma-next/utils/result';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport { CONTROL_TABLE_NAMES } from '../control-tables';\nimport {\n columnSpecFromNode,\n ddlColumnFromNode,\n isInlineAutoincrementPrimaryKeyNode,\n tableConstraintsFromNode,\n} from './column-ddl-rendering';\nimport {\n AddColumnCall,\n CreateIndexCall,\n CreateTableCall,\n DropColumnCall,\n DropIndexCall,\n DropTableCall,\n type SqliteOpFactoryCall,\n} from './op-factory-call';\nimport type {\n SqliteColumnSpec,\n SqliteForeignKeySpec,\n SqliteTableSpec,\n SqliteUniqueSpec,\n} from './operations/shared';\nimport {\n type CallMigrationStrategy,\n type StrategyContext,\n sqlitePlannerStrategies,\n} from './planner-strategies';\n\nexport type { CallMigrationStrategy, StrategyContext };\n\n// ============================================================================\n// Node-keyed issue ordering (dependency order)\n// ============================================================================\n\n/**\n * Re-keys the legacy `ISSUE_KIND_ORDER` (kind string → priority number) on\n * `(nodeKind, reason)`. Numbers are preserved from the legacy table so the\n * dependency intent stays legible; the final emission order is actually\n * fixed downstream by category bucketing (create-table → add-column →\n * create-index → recreate → drop-column → drop-index → drop-table), so this\n * only breaks ties within a single bucket.\n */\nexport function nodeIssueOrder(issue: SchemaDiffIssue): number {\n const node = issueNode(issue);\n if (node === undefined) return 99;\n switch (node.nodeKind) {\n case RelationalSchemaNodeKind.foreignKey:\n return issue.reason === 'not-expected' ? 10 : 60;\n case RelationalSchemaNodeKind.unique:\n return issue.reason === 'not-expected' ? 11 : 51;\n case RelationalSchemaNodeKind.primaryKey:\n return issue.reason === 'not-expected' ? 12 : 50;\n case RelationalSchemaNodeKind.index:\n return issue.reason === 'not-expected' ? 13 : 52;\n case RelationalSchemaNodeKind.columnDefault:\n if (issue.reason === 'not-expected') return 14;\n return issue.reason === 'not-found' ? 42 : 43;\n case RelationalSchemaNodeKind.column:\n if (issue.reason === 'not-expected') return 15;\n return issue.reason === 'not-found' ? 30 : 40;\n case RelationalSchemaNodeKind.table:\n return issue.reason === 'not-expected' ? 16 : 20;\n case RelationalSchemaNodeKind.check:\n if (issue.reason === 'not-found') return 53;\n return issue.reason === 'not-expected' ? 54 : 55;\n default:\n return 99;\n }\n}\n\n/** Deterministic tiebreak within an order bucket: the diff path itself already encodes table → child → grandchild. */\nexport function nodeIssueKey(issue: SchemaDiffIssue): string {\n return issue.path.join(' ');\n}\n\n// ============================================================================\n// Subtree coalescing — the planner's responsibility per the differ's contract\n// ============================================================================\n\n/**\n * The generic differ is total: a missing/extra table (or column) emits an\n * issue for itself AND for every node in its subtree (columns, defaults,\n * constraints, indexes). `CreateTableCall`/`DropTableCall` and\n * `AddColumnCall`/`DropColumnCall` already account for the whole subtree\n * (reading it directly off the table/column node), so the nested issues are\n * redundant — coalescing them is \"the planner's responsibility\" the differ's\n * own contract assigns (`schema-diff.ts`). Drops any issue whose path is a\n * strict descendant of a `not-found`/`not-expected` issue's path.\n */\nexport function coalesceSubtreeIssues(\n issues: readonly SchemaDiffIssue[],\n): readonly SchemaDiffIssue[] {\n const collapsingPaths = issues\n .filter((issue) => issue.reason === 'not-found' || issue.reason === 'not-expected')\n .map((issue) => issue.path);\n if (collapsingPaths.length === 0) return issues;\n return issues.filter(\n (issue) => !collapsingPaths.some((ancestor) => isStrictDescendantPath(issue.path, ancestor)),\n );\n}\n\nfunction isStrictDescendantPath(path: readonly string[], ancestor: readonly string[]): boolean {\n if (path.length <= ancestor.length) return false;\n for (let i = 0; i < ancestor.length; i += 1) {\n if (path[i] !== ancestor[i]) return false;\n }\n return true;\n}\n\n// ============================================================================\n// Node helpers\n// ============================================================================\n\nexport function issueNode(issue: SchemaDiffIssue): SqlSchemaIRNode | undefined {\n const node = issue.expected ?? issue.actual;\n if (node === undefined) return undefined;\n return blindCast<\n SqlSchemaIRNode,\n 'every node in a SQL schema diff tree is a SqlSchemaIRNode; nodeKind is its required discriminant'\n >(node);\n}\n\n/** Whether the expected/actual native type (resolved, or raw+many fallback) differs — mirrors `SqlColumnIR.isEqualTo`'s type comparison. */\nexport function columnTypeChanged(expected: SqlColumnIR, actual: SqlColumnIR): boolean {\n if (expected.resolvedNativeType !== undefined && actual.resolvedNativeType !== undefined) {\n return expected.resolvedNativeType !== actual.resolvedNativeType;\n }\n return (\n expected.nativeType !== actual.nativeType || Boolean(expected.many) !== Boolean(actual.many)\n );\n}\n\n/**\n * Builds the flat `SqliteTableSpec` `RecreateTableCall` needs from the\n * expected table node — the node-sourced equivalent of the retired\n * `toTableSpec` (which read a raw contract `StorageTable`). Every column's\n * spec is resolved from its `codecRef` via `columnSpecFromNode`.\n */\nexport function tableSpecFromNode(table: SqlTableIR): SqliteTableSpec {\n const columns: SqliteColumnSpec[] = Object.values(table.columns).map((c) =>\n columnSpecFromNode(c, isInlineAutoincrementPrimaryKeyNode(table, c)),\n );\n const uniques: SqliteUniqueSpec[] = table.uniques.map((u) => ({\n columns: u.columns,\n ...(u.name !== undefined ? { name: u.name } : {}),\n }));\n // Every FK node on the expected tree is constraint-bearing by construction\n // (contractToSchemaIR filters `constraint: false` FKs out before they ever\n // become nodes — those only ever contribute an index, never an FK node).\n const foreignKeys: SqliteForeignKeySpec[] = table.foreignKeys.map((fk) => ({\n columns: fk.columns,\n references: { table: fk.referencedTable, columns: fk.referencedColumns },\n constraint: true,\n ...(fk.name !== undefined ? { name: fk.name } : {}),\n ...(fk.onDelete !== undefined ? { onDelete: fk.onDelete } : {}),\n ...(fk.onUpdate !== undefined ? { onUpdate: fk.onUpdate } : {}),\n }));\n return {\n columns,\n ...(table.primaryKey ? { primaryKey: { columns: table.primaryKey.columns } } : {}),\n uniques,\n foreignKeys,\n };\n}\n\n// ============================================================================\n// Conflict helpers\n// ============================================================================\n\nfunction issueConflict(\n kind: SqlPlannerConflict['kind'],\n summary: string,\n location?: SqlPlannerConflict['location'],\n): SqlPlannerConflict {\n return {\n kind,\n summary,\n why: 'Use `migration new` to author a custom migration for this change.',\n ...(location ? { location } : {}),\n };\n}\n\nfunction issueLocation(tableName: string, columnName?: string): SqlPlannerConflictLocation {\n return columnName !== undefined ? { table: tableName, column: columnName } : { table: tableName };\n}\n\n/**\n * Conflict kind for a node kind that `recreateTableStrategy` absorbs for\n * every reachable production issue. Reaching `mapNodeIssueToCall` for one of\n * these means the recreate strategy didn't run — mirrors the legacy\n * `conflictKindForIssue` per-kind categorization.\n */\nfunction absorbedConflictKind(nodeKind: string): SqlPlannerConflict['kind'] {\n switch (nodeKind) {\n case RelationalSchemaNodeKind.primaryKey:\n case RelationalSchemaNodeKind.unique:\n return 'indexIncompatible';\n case RelationalSchemaNodeKind.foreignKey:\n return 'foreignKeyConflict';\n default:\n return 'missingButNonAdditive';\n }\n}\n\n// ============================================================================\n// StorageTable / StorageColumn → flat SqliteTableSpec / DdlColumn helpers\n// ============================================================================\n\n/**\n * Builds the `CreateTableCall` + per-index `CreateIndexCall`s for a\n * newly-expected table. Reads only the table node's own children — indexes\n * (declared + FK-backing, deduped) are already merged and ordered at\n * derivation (`contractToSchemaIR`'s `convertTable`).\n */\nfunction buildCreateTableCalls(table: SqlTableIR): SqliteOpFactoryCall[] {\n const columns = Object.values(table.columns).map((c) =>\n ddlColumnFromNode(c, isInlineAutoincrementPrimaryKeyNode(table, c)),\n );\n const hasInlinePk = Object.values(table.columns).some((c) =>\n isInlineAutoincrementPrimaryKeyNode(table, c),\n );\n const constraints = tableConstraintsFromNode(table, hasInlinePk);\n const calls: SqliteOpFactoryCall[] = [\n new CreateTableCall(table.name, columns, constraints.length > 0 ? constraints : undefined),\n ];\n for (const index of table.indexes) {\n const indexName = index.name ?? defaultIndexName(table.name, index.columns);\n calls.push(new CreateIndexCall(table.name, indexName, index.columns));\n }\n return calls;\n}\n\n// ============================================================================\n// Issue → Call mapping (per-issue default path)\n// ============================================================================\n\nfunction mapTableIssue(\n issue: SchemaDiffIssue,\n): Result<readonly SqliteOpFactoryCall[], SqlPlannerConflict> {\n if (issue.reason === 'not-found') {\n const table = blindCast<\n SqlTableIR,\n 'a not-found table issue always carries the expected table node'\n >(issue.expected);\n return ok(buildCreateTableCalls(table));\n }\n if (issue.reason === 'not-expected') {\n const table = blindCast<\n SqlTableIR,\n 'a not-expected table issue always carries the actual table node'\n >(issue.actual);\n // Runner-owned control tables must never be dropped.\n if (CONTROL_TABLE_NAMES.has(table.name)) return ok([]);\n return ok([new DropTableCall(table.name)]);\n }\n // Unreachable: SqlTableIR.isEqualTo is identity, so a paired table can\n // never mismatch — kept for exhaustiveness against a future node change.\n return notOk(\n issueConflict('unsupportedOperation', `Unexpected table drift: ${issue.path.join('/')}`),\n );\n}\n\nfunction mapColumnIssue(\n issue: SchemaDiffIssue,\n ctx: StrategyContext,\n): Result<readonly SqliteOpFactoryCall[], SqlPlannerConflict> {\n const tableName = issue.path[1];\n if (tableName === undefined) {\n return notOk(\n issueConflict(\n 'unsupportedOperation',\n `Column issue has no table in its path: ${issue.path.join('/')}`,\n ),\n );\n }\n if (issue.reason === 'not-found') {\n const column = blindCast<\n SqlColumnIR,\n 'a not-found column issue always carries the expected column node'\n >(issue.expected);\n // A sole-autoincrement-PK column is always part of the table's own\n // CREATE (never a bare ADD COLUMN — PK changes go through\n // `recreateTableStrategy`), but the check is cheap and keeps this path\n // honest against the table node rather than assuming it.\n const table = ctx.expected.tables[tableName];\n const inline = table !== undefined && isInlineAutoincrementPrimaryKeyNode(table, column);\n return ok([new AddColumnCall(tableName, columnSpecFromNode(column, inline))]);\n }\n if (issue.reason === 'not-expected') {\n const column = blindCast<\n SqlColumnIR,\n 'a not-expected column issue always carries the actual column node'\n >(issue.actual);\n return ok([new DropColumnCall(tableName, column.name)]);\n }\n // not-equal: absorbed by recreateTableStrategy for every reachable\n // production issue (SQLite can't ALTER a column type/nullability in\n // place). Reaching here means the strategy didn't run — conflict.\n const expected = blindCast<\n SqlColumnIR,\n 'a not-equal column issue always carries the expected column node'\n >(issue.expected);\n const actual = blindCast<\n SqlColumnIR,\n 'a not-equal column issue always carries the actual column node'\n >(issue.actual);\n const kind = columnTypeChanged(expected, actual) ? 'typeMismatch' : 'nullabilityConflict';\n return notOk(issueConflict(kind, issue.path.join('/'), issueLocation(tableName, expected.name)));\n}\n\nfunction mapIndexIssue(\n issue: SchemaDiffIssue,\n): Result<readonly SqliteOpFactoryCall[], SqlPlannerConflict> {\n const tableName = issue.path[1];\n if (tableName === undefined) {\n return notOk(\n issueConflict(\n 'unsupportedOperation',\n `Index issue has no table in its path: ${issue.path.join('/')}`,\n ),\n );\n }\n if (issue.reason === 'not-found') {\n const index = blindCast<\n SqlIndexIR,\n 'a not-found index issue always carries the expected index node'\n >(issue.expected);\n const indexName = index.name ?? defaultIndexName(tableName, index.columns);\n return ok([new CreateIndexCall(tableName, indexName, index.columns)]);\n }\n if (issue.reason === 'not-expected') {\n const index = blindCast<\n SqlIndexIR,\n 'a not-expected index issue always carries the actual index node'\n >(issue.actual);\n const indexName = index.name ?? defaultIndexName(tableName, index.columns);\n return ok([new DropIndexCall(tableName, indexName)]);\n }\n // not-equal: index type/options/uniqueness drift. SQLite can't ALTER an\n // index in place and the legacy planner never absorbed this into a\n // recreate either — surfaces as a conflict, matching `index_mismatch`.\n return notOk(issueConflict('indexIncompatible', issue.path.join('/'), issueLocation(tableName)));\n}\n\nexport function mapNodeIssueToCall(\n issue: SchemaDiffIssue,\n ctx: StrategyContext,\n): Result<readonly SqliteOpFactoryCall[], SqlPlannerConflict> {\n const node = issueNode(issue);\n if (node === undefined) {\n return notOk(\n issueConflict(\n 'unsupportedOperation',\n `Issue carries neither an expected nor an actual node: ${issue.path.join('/')}`,\n ),\n );\n }\n switch (node.nodeKind) {\n case RelationalSchemaNodeKind.table:\n return mapTableIssue(issue);\n case RelationalSchemaNodeKind.column:\n return mapColumnIssue(issue, ctx);\n case RelationalSchemaNodeKind.index:\n return mapIndexIssue(issue);\n case RelationalSchemaNodeKind.columnDefault:\n case RelationalSchemaNodeKind.primaryKey:\n case RelationalSchemaNodeKind.foreignKey:\n case RelationalSchemaNodeKind.unique:\n return notOk(issueConflict(absorbedConflictKind(node.nodeKind), issue.path.join('/')));\n case RelationalSchemaNodeKind.check:\n return notOk(\n issueConflict(\n 'unsupportedOperation',\n `SQLite does not support CHECK constraint DDL: ${issue.path.join('/')}`,\n ),\n );\n default:\n return notOk(issueConflict('unsupportedOperation', `Unhandled node kind: ${node.nodeKind}`));\n }\n}\n\n// ============================================================================\n// Call categorization for final emission order\n// ============================================================================\n\ntype CallCategory =\n | 'drop-column'\n | 'drop-index'\n | 'drop-table'\n | 'create-table'\n | 'add-column'\n | 'create-index';\n\nfunction classifyCall(call: SqliteOpFactoryCall): CallCategory | null {\n switch (call.factoryName) {\n case 'createTable':\n return 'create-table';\n case 'addColumn':\n return 'add-column';\n case 'createIndex':\n return 'create-index';\n case 'dropColumn':\n return 'drop-column';\n case 'dropIndex':\n return 'drop-index';\n case 'dropTable':\n return 'drop-table';\n // recreateTable goes into the recipe slot; return null for bucketable.\n case 'recreateTable':\n return null;\n default:\n return null;\n }\n}\n\n// ============================================================================\n// Top-level planIssues\n// ============================================================================\n\nexport interface IssuePlannerOptions {\n readonly issues: readonly SchemaDiffIssue[];\n /** The desired (\"end\") tree — resolved leaf values, incl. `codecRef`. */\n readonly expected?: SqlSchemaIR;\n /** The live (\"start\") tree. */\n readonly actual?: SqlSchemaIR;\n readonly policy?: MigrationOperationPolicy;\n readonly frameworkComponents?: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;\n readonly strategies?: readonly CallMigrationStrategy[];\n}\n\nexport interface IssuePlannerValue {\n readonly calls: readonly SqliteOpFactoryCall[];\n}\n\nconst DEFAULT_POLICY: MigrationOperationPolicy = {\n allowedOperationClasses: ['additive', 'widening', 'destructive', 'data'],\n};\n\nexport function planIssues(\n options: IssuePlannerOptions,\n): Result<IssuePlannerValue, readonly SqlPlannerConflict[]> {\n const policyProvided = options.policy !== undefined;\n const policy = options.policy ?? DEFAULT_POLICY;\n const frameworkComponents = options.frameworkComponents ?? [];\n\n const context: StrategyContext = {\n expected: options.expected ?? emptySchemaIR(),\n actual: options.actual ?? emptySchemaIR(),\n policy,\n frameworkComponents,\n };\n\n const strategies = options.strategies ?? sqlitePlannerStrategies;\n\n let remaining = options.issues;\n const recipeCalls: SqliteOpFactoryCall[] = [];\n const bucketableCalls: SqliteOpFactoryCall[] = [];\n\n for (const strategy of strategies) {\n const result = strategy(remaining, context);\n if (result.kind === 'match') {\n remaining = result.issues;\n if (result.recipe) {\n recipeCalls.push(...result.calls);\n } else {\n bucketableCalls.push(...result.calls);\n }\n }\n }\n\n const sorted = [...remaining].sort((a, b) => {\n const kindDelta = nodeIssueOrder(a) - nodeIssueOrder(b);\n if (kindDelta !== 0) return kindDelta;\n const keyA = nodeIssueKey(a);\n const keyB = nodeIssueKey(b);\n return keyA < keyB ? -1 : keyA > keyB ? 1 : 0;\n });\n\n const defaultCalls: SqliteOpFactoryCall[] = [];\n const conflicts: SqlPlannerConflict[] = [];\n\n for (const issue of sorted) {\n const result = mapNodeIssueToCall(issue, context);\n if (result.ok) {\n defaultCalls.push(...result.value);\n } else {\n conflicts.push(result.failure);\n }\n }\n\n // Policy gating for recipe + bucketable. Default-mapped calls for disallowed\n // classes never get here (they're surfaced as per-issue conflicts above).\n const allowed = policy.allowedOperationClasses;\n let gatedRecipe = recipeCalls;\n let gatedBucketable = bucketableCalls;\n let gatedDefault = defaultCalls;\n if (policyProvided) {\n const sink = (acc: SqliteOpFactoryCall[]) => (call: SqliteOpFactoryCall) => {\n if (allowed.includes(call.operationClass)) {\n acc.push(call);\n return;\n }\n conflicts.push(conflictForDisallowedCall(call, allowed));\n };\n const gatedRecipeBucket: SqliteOpFactoryCall[] = [];\n const gatedBucketableBucket: SqliteOpFactoryCall[] = [];\n const gatedDefaultBucket: SqliteOpFactoryCall[] = [];\n recipeCalls.forEach(sink(gatedRecipeBucket));\n bucketableCalls.forEach(sink(gatedBucketableBucket));\n defaultCalls.forEach(sink(gatedDefaultBucket));\n gatedRecipe = gatedRecipeBucket;\n gatedBucketable = gatedBucketableBucket;\n gatedDefault = gatedDefaultBucket;\n }\n\n if (conflicts.length > 0) {\n return notOk(conflicts);\n }\n\n // Final emission order matches the current monolithic planner:\n // create-table → add-column → create-index → recreate → drop-column → drop-index → drop-table\n const combined = [...gatedDefault, ...gatedBucketable];\n const byCategory = (cat: CallCategory) => combined.filter((c) => classifyCall(c) === cat);\n\n const calls: SqliteOpFactoryCall[] = [\n ...byCategory('create-table'),\n ...byCategory('add-column'),\n ...byCategory('create-index'),\n ...gatedRecipe,\n ...byCategory('drop-column'),\n ...byCategory('drop-index'),\n ...byCategory('drop-table'),\n ];\n\n return ok({ calls });\n}\n\nfunction emptySchemaIR(): SqlSchemaIR {\n return new SqlSchemaIR({ tables: {} });\n}\n\nfunction conflictForDisallowedCall(\n call: SqliteOpFactoryCall,\n allowed: readonly string[],\n): SqlPlannerConflict {\n const summary = `Operation \"${call.label}\" requires class \"${call.operationClass}\", but policy allows only: ${allowed.join(', ')}`;\n const location = locationForCall(call);\n return {\n kind: conflictKindForCall(call),\n summary,\n why: 'Use `migration new` to author a custom migration for this change.',\n ...(location ? { location } : {}),\n };\n}\n\nfunction conflictKindForCall(call: SqliteOpFactoryCall): SqlPlannerConflict['kind'] {\n switch (call.factoryName) {\n case 'createIndex':\n case 'dropIndex':\n return 'indexIncompatible';\n default:\n return 'missingButNonAdditive';\n }\n}\n\nfunction locationForCall(call: SqliteOpFactoryCall): SqlPlannerConflictLocation | undefined {\n const location: { table?: string; column?: string; index?: string } = {};\n if ('tableName' in call) location.table = call.tableName;\n if ('columnName' in call) location.column = call.columnName;\n if ('indexName' in call) location.index = call.indexName;\n return Object.keys(location).length > 0 ? (location as SqlPlannerConflictLocation) : undefined;\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type {\n MigrationOperationPolicy,\n SqlMigrationPlanner,\n SqlMigrationPlannerPlanOptions,\n SqlPlannerFailureResult,\n} from '@prisma-next/family-sql/control';\nimport {\n extractCodecControlHooks,\n planFieldEventOperations,\n plannerFailure,\n} from '@prisma-next/family-sql/control';\nimport type { ExecuteRequestLowerer } from '@prisma-next/family-sql/control-adapter';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n MigrationPlanner,\n MigrationScaffoldContext,\n SchemaDiffIssue,\n SchemaOwnership,\n} from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport { RelationalSchemaNodeKind, type SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { buildSqlitePlanDiff } from './diff-database-schema';\nimport { coalesceSubtreeIssues, issueNode, planIssues } from './issue-planner';\nimport {\n type SqliteMigrationDestinationInfo,\n TypeScriptRenderableSqliteMigration,\n} from './planner-produced-sqlite-migration';\nimport { sqlitePlannerStrategies } from './planner-strategies';\nimport type { SqlitePlanTargetDetails } from './planner-target-details';\n\nexport function createSqliteMigrationPlanner(\n lowerer: ExecuteRequestLowerer,\n): SqliteMigrationPlanner {\n return new SqliteMigrationPlanner(lowerer);\n}\n\nexport type SqlitePlanResult =\n | { readonly kind: 'success'; readonly plan: TypeScriptRenderableSqliteMigration }\n | SqlPlannerFailureResult;\n\n/**\n * SQLite migration planner — a thin wrapper over `planIssues`.\n *\n * `plan()` diffs the live schema against the target contract via the one\n * differ (`buildSqlitePlanDiff`, producing node-typed `SchemaDiffIssue[]`)\n * and delegates to `planIssues` with the registered strategies. Strategies\n * absorb groups of related issues into composite recipes (e.g. recreating a\n * table to apply type/nullability/default/constraint changes at once);\n * anything not absorbed by a strategy flows through `mapNodeIssueToCall` in\n * the issue planner as a one-off call.\n *\n * FK-backing indexes are already merged into the expected table node's\n * `indexes` at derivation (`contractToSchemaIR`'s `convertTable`), so\n * `mapNodeIssueToCall` handles them uniformly alongside user-declared\n * indexes — no separate expansion step in the planner.\n */\nexport class SqliteMigrationPlanner\n implements SqlMigrationPlanner<SqlitePlanTargetDetails>, MigrationPlanner<'sql', 'sqlite'>\n{\n readonly #lowerer: ExecuteRequestLowerer;\n\n constructor(lowerer: ExecuteRequestLowerer) {\n this.#lowerer = lowerer;\n }\n\n plan(options: {\n readonly contract: unknown;\n readonly schema: unknown;\n readonly policy: MigrationOperationPolicy;\n /**\n * The \"from\" contract (state the planner assumes the database starts at),\n * or `null` for reconciliation flows.\n *\n * Typed as the framework `Contract | null` to satisfy the\n * `MigrationPlanner` interface contract; `planSql` narrows to the SQL\n * shape via `SqlMigrationPlannerPlanOptions`. Used to populate\n * `describe().from` on the produced plan as\n * `fromContract?.storage.storageHash ?? null`.\n */\n readonly fromContract: Contract | null;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;\n /**\n * Contract space this plan applies to. Stamped onto the produced\n * {@link TypeScriptRenderableSqliteMigration.spaceId} so the runner keys\n * the marker row by the right space.\n */\n readonly spaceId: string;\n /**\n * Ownership oracle over the contract-space composition — see\n * {@link SqlMigrationPlannerPlanOptions.ownership}.\n */\n readonly ownership?: SchemaOwnership;\n }): SqlitePlanResult {\n return this.planSql(options as SqlMigrationPlannerPlanOptions);\n }\n\n emptyMigration(\n context: MigrationScaffoldContext,\n spaceId: string,\n ): TypeScriptRenderableSqliteMigration {\n return new TypeScriptRenderableSqliteMigration(\n [],\n {\n from: context.fromHash,\n to: context.toHash,\n },\n spaceId,\n undefined,\n this.#lowerer,\n );\n }\n\n private planSql(options: SqlMigrationPlannerPlanOptions): SqlitePlanResult {\n const policyResult = this.ensureAdditivePolicy(options.policy);\n if (policyResult) return policyResult;\n\n const { expected, actual, issues } = this.collectSchemaIssues(options);\n const codecHooks = extractCodecControlHooks(options.frameworkComponents);\n\n const result = planIssues({\n issues,\n expected,\n actual,\n policy: options.policy,\n frameworkComponents: options.frameworkComponents,\n strategies: sqlitePlannerStrategies,\n });\n\n if (!result.ok) {\n return plannerFailure(result.failure);\n }\n\n // Codec lifecycle hook (T2.2): inline `onFieldEvent`-emitted ops after\n // structural DDL. Sub-spec § 5 fixes the ordering as\n // `structural → added → dropped → altered`, with within-group sorting by\n // `(tableName, fieldName)` deterministic for byte-stable re-emits.\n // Hook fires only at the application emitter — extension-space planning\n // (M2 R2) never reaches this helper.\n const fieldEventOps = planFieldEventOperations({\n priorContract: options.fromContract,\n newContract: options.contract,\n codecHooks,\n });\n // Codec-emitted calls already conform to `OpFactoryCall` — render +\n // toOp + importRequirements ride directly through the same emit path\n // as structural ops, no `RawSqlCall` wrap.\n const calls = [...result.value.calls, ...fieldEventOps];\n\n const destination: SqliteMigrationDestinationInfo = {\n storageHash: options.contract.storage.storageHash,\n ...(options.contract.profileHash !== undefined\n ? { profileHash: options.contract.profileHash }\n : {}),\n };\n\n return {\n kind: 'success' as const,\n plan: new TypeScriptRenderableSqliteMigration(\n calls,\n {\n from: options.fromContract?.storage.storageHash ?? null,\n to: options.contract.storage.storageHash,\n },\n options.spaceId,\n destination,\n this.#lowerer,\n ),\n };\n }\n\n private ensureAdditivePolicy(policy: MigrationOperationPolicy): SqlPlannerFailureResult | null {\n if (!policy.allowedOperationClasses.includes('additive')) {\n return plannerFailure([\n {\n kind: 'unsupportedOperation',\n summary: 'Migration planner requires additive operations be allowed',\n why: 'The planner requires the \"additive\" operation class to be allowed in the policy.',\n },\n ]);\n }\n return null;\n }\n\n /**\n * Diffs the target contract against the live schema via the one differ\n * (the same tree-building `diffSqliteSchema` uses, plus the\n * op-render stamper) and prepares the issue list `planIssues` consumes.\n *\n * Three passes, in order:\n * 1. Subtree coalescing — the differ is total (a missing/extra table also\n * emits an issue for every column/constraint under it); those nested\n * issues are redundant once the table-level `CreateTable`/`DropTable`\n * call already accounts for the whole subtree. Runs FIRST, over the\n * complete diff: a sibling-owned extra table's column issues must\n * collapse into its one table-level issue before the ownership pass,\n * because a bare column node carries no table reference — if coalescing\n * ran after ownership dropped the table-level issue, the orphaned column\n * issues would survive and the planner would emit drops against a\n * sibling space's table.\n * 2. Ownership — a live extra is only this plan's to drop when no contract\n * space owns it. The differ ran against THIS space's contract, so a\n * table a sibling owns surfaces here as `not-expected`; the planner asks\n * the ownership oracle (the passive aggregate) whether any space declares\n * it and, if so, leaves it alone. A table no space owns stays a genuine\n * extra. Ownership lives in the aggregate; the planner only asks. No\n * oracle (single-space) keeps every extra.\n * 3. Strict-mode extras gating — `not-expected` (extra table/column/\n * constraint) issues are dropped entirely outside strict mode, mirroring\n * the retired coordinate walk's `if (strict) { ...extra_* } }` guards:\n * an additive-only plan must never even consider dropping an unclaimed\n * object, not just refuse to emit the drop.\n */\n private collectSchemaIssues(options: SqlMigrationPlannerPlanOptions): {\n readonly expected: SqlSchemaIR;\n readonly actual: SqlSchemaIR;\n readonly issues: readonly SchemaDiffIssue[];\n } {\n const allowed = options.policy.allowedOperationClasses;\n const strict = allowed.includes('widening') || allowed.includes('destructive');\n const {\n expected,\n actual,\n issues: rawIssues,\n } = buildSqlitePlanDiff({\n contract: options.contract,\n actualSchema: options.schema,\n frameworkComponents: options.frameworkComponents,\n });\n const coalesced = coalesceSubtreeIssues(rawIssues);\n const owned = retainUnownedExtras(coalesced, options.ownership);\n const issues = strict ? owned : owned.filter((issue) => issue.reason !== 'not-expected');\n return { expected, actual, issues };\n }\n}\n\n/**\n * Drops a `not-expected` issue when it is a whole extra TABLE that some\n * contract space owns, asking the ownership oracle per node.\n *\n * The consultation applies ONLY to table-level extras — a live table this\n * space's contract lacks — identified by asking the issue's own node\n * (`nodeKind === table`), never by counting path segments. SQLite is a\n * single-namespace target, so every coordinate is qualified with the shared\n * `UNBOUND_NAMESPACE_ID` sentinel (the same one the aggregate's declared\n * entities carry for this target). `entityKind` is the literal `'table'`:\n * this function only ever asks about a node already confirmed to be\n * `RelationalSchemaNodeKind.table` (checked just above), and that's a\n * diff-tree `nodeKind` spelling (`'sql-table'`) distinct from the storage\n * `entries` vocabulary `elementCoordinates` walks (`'table'`) — the literal\n * is that storage-entries spelling. `declaresEntity` answers over the whole\n * composition (self included), so a positive answer on such a table means\n * another space owns it (a table this space owned would be in its expected\n * tree, never an extra): leave it. A negative answer means no space owns\n * it — a genuine orphan to drop.\n *\n * A DEEPER extra (an extra column/constraint on a table this space DOES own —\n * only the child drifted, so the table is in the expected tree) is this\n * space's own drift and is always kept for dropping; asking the oracle there\n * would wrongly suppress it, because the owned table answers `true`. No oracle\n * ⇒ every extra is kept (single-space plan).\n */\nfunction retainUnownedExtras(\n issues: readonly SchemaDiffIssue[],\n ownership: SchemaOwnership | undefined,\n): readonly SchemaDiffIssue[] {\n if (ownership === undefined) return issues;\n return issues.filter((issue) => {\n if (issue.reason !== 'not-expected') return true;\n const node = issueNode(issue);\n if (node === undefined || node.nodeKind !== RelationalSchemaNodeKind.table) return true;\n const tableName = issue.path[1];\n return (\n tableName === undefined ||\n !ownership.declaresEntity({\n namespaceId: UNBOUND_NAMESPACE_ID,\n entityKind: 'table',\n entityName: tableName,\n })\n );\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgCA,SAAgB,oBAAoB,KAAoB,SAAgC;CACtF,IAAI,IAAI,SAAS,YAAY;EAC3B,IAAI,IAAI,eAAe,SACrB,OAAO;EAET,OAAO,IAAI;CACb;CACA,OAAO,qBAAqB,IAAI,KAAK;AACvC;;;;;;;;;;AAWA,SAAgB,uBACd,UACA,QAGa;CAKb,OAAO,mBAAmB,UAAU;EAClC,qBAAqB;EACrB,eAAe;EACf,GAAG,UAAU,oBAAoB,QAAQ,gBAAgB;CAC3D,CAAC;AACH;;;;;;AAOA,SAAgB,2BACd,OAC4B;CAC5B,OAAO,sBAAsB;EAC3B,UAAU,MAAM;EAChB,QAAQ,MAAM;EACd,QAAQ,MAAM;EACd,qBAAqB,MAAM;EAC3B,YAAY;EACZ,eAAe;CACjB,CAAC;AACH;;;;;;;;;AAUA,SAAS,qBACP,OACA,UAC2B;CAC3B,MAAM,YAAY,MAAM,KAAK;CAC7B,IAAI,cAAc,KAAA,GAAW,OAAO,KAAA;CACpC,KAAK,MAAM,eAAe,OAAO,KAAK,SAAS,QAAQ,UAAU,GAAG;EAClE,MAAM,QAAQ,SAAuB,SAAS,SAAS;GACrD;GACA,YAAY;GACZ,YAAY;EACd,CAAC;EACD,IAAI,UAAU,KAAA,GAAW,OAAO,MAAM;CACxC;AAEF;;;;;;;;;;AAWA,SAAgB,iBAAiB,OAIT;CACtB,MAAM,mBAAmB,wBAAwB,MAAM,mBAAmB;CAC1E,MAAM,WAAW,uBAAuB,MAAM,UAAU,EACtD,GAAG,UAAU,oBAAoB,gBAAgB,EACnD,CAAC;CACD,MAAM,SACJ,MAAM,kBAAkB,cACpB,MAAM,SACN,UAGE,MAAM,MAAM;CAKpB,OAAO;EACL,QALa,YAAY,UAAU,MAK9B;EACL,uBAAuB,UAAU,qBAAqB,OAAO,MAAM,QAAQ;EAC3E,gBAN2B,OAAO,OAAO,MAAM,SAAS,QAAQ,UAAU,CAAC,CAAC,QAC3E,OAAO,OAAO,KAAK,GAAG,QAAQ,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAKlB,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE;CAC7D;AACF;;;;;;;;AAiBA,SAAgB,oBAAoB,OAIjB;CACjB,MAAM,mBAAmB,wBAAwB,MAAM,mBAAmB;CAC1E,MAAM,WAAW,uBAAuB,MAAM,UAAU,EACtD,GAAG,UAAU,oBAAoB,gBAAgB,EACnD,CAAC;CAOD,MAAM,SAAS,IAAI,YAAY,mBAAmB,MAAM,YAAY,CAAC;CAErE,OAAO;EAAE;EAAU;EAAQ,QADZ,YAAY,UAAU,MACL;CAAE;AACpC;;;;;;;;;;;;AAaA,SAAS,mBAAmB,cAAiD;CAC3E,MAAM,MAAM,UAGV,YAAY;CACd,MAAM,SAA0C,CAAC;CACjD,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,IAAI,UAAU,CAAC,CAAC,GAAG;EACjE,MAAM,WAAW,UAGf,KAAK;EACP,MAAM,UAA4C,CAAC;EACnD,KAAK,MAAM,CAAC,YAAY,WAAW,OAAO,QACxC,UAGE,KAAK,CAAC,CAAC,WAAW,CAAC,CACvB,GACE,QAAQ,cAAc;GACpB,GAAG,UAGD,MAAM;GACR,MAAM;EACR;EAEF,OAAO,aAAa;GAClB,GAAG;GACH,MAAM;GACN;GACA,aAAa,SAAS,eAAe,CAAC;GACtC,SAAS,SAAS,WAAW,CAAC;GAC9B,SAAS,SAAS,WAAW,CAAC;EAChC;CACF;CACA,OAAO,EAAE,OAAO;AAClB;;;;;;;;;;;;;;AC3MA,SAAS,WACP,QACgG;CAChG,IAAI,OAAO,aAAa,KAAA,KAAa,OAAO,wBAAwB,KAAA,GAClE,MAAM,IAAI,MACR,gCAAgC,OAAO,KAAK,oGAC9C;CAEF,OAAO;EACL,YAAY,OAAO;EACnB,SAAS,OAAO,SAAS;EACzB,UAAU,OAAO;EAIjB,IAAK,OAAO,QAAQ,OAAO,SAAS,UAAU,KAAA,IAC1C,EAAE,MAAM,OAAO,QAAQ,OAAO,SAAS,KAAK,IAC5C,CAAC;EACL,GAAI,OAAO,SAAS,eAAe,KAAA,IAC/B,EACE,YAAY,UAGV,OAAO,SAAS,UAAU,EAC9B,IACA,CAAC;EACL,GAAI,OAAO,oBAAoB,KAAA,IAAY,EAAE,SAAS,OAAO,gBAAgB,IAAI,CAAC;CACpF;AACF;AAEA,SAAS,gCACP,eACsB;CACtB,IAAI,CAAC,eAAe,OAAO,KAAA;CAC3B,QAAQ,cAAc,MAAtB;EACE,KAAK,WACH,OAAO,IAAI,qBAAqB,cAAc,KAAK;EACrD,KAAK;GAIH,IAAI,cAAc,eAAe,mBAAmB,OAAO,KAAA;GAC3D,OAAO,IAAI,sBAAsB,cAAc,UAAU;EAC3D,SAEE,MAAM,IAAI,MACR,oDAAoD,UAAkFA,aAAU,CAAC,CAAC,KAAK,EACzJ;CAEJ;AACF;;;;;;;;AASA,SAAgB,oCACd,OACA,QACS;CACT,IAAI,MAAM,YAAY,QAAQ,WAAW,GAAG,OAAO;CACnD,IAAI,MAAM,WAAW,QAAQ,OAAO,OAAO,MAAM,OAAO;CACxD,OACE,OAAO,iBAAiB,SAAS,cACjC,OAAO,gBAAgB,eAAe;AAE1C;;;;;;;AAQA,SAAgB,mBAAmB,QAAqB,QAAmC;CACzF,MAAM,OAAO,WAAW,MAAM;CAC9B,MAAM,UAAU,mBAAmB,MAAM,CAAC,CAAC;CAC3C,MAAM,aAAa,sBAAsB,KAAK,OAAO;CACrD,OAAO;EACL,MAAM,OAAO;EACb;EACA;EACA,UAAU,OAAO;EACjB,GAAI,SAAS,EAAE,+BAA+B,KAAK,IAAI,CAAC;CAC1D;AACF;;;;;AAMA,SAAgB,kBAAkB,QAAqB,QAA4B;CACjF,MAAM,OAAO,WAAW,MAAM;CAC9B,MAAM,UAAU,mBAAmB,MAAM,CAAC,CAAC;CAC3C,IAAI,QAOF,OAAO,IAAI,UAAU;EAAE,MAAM,OAAO;EAAM,MAAM,GAAG,QAAQ;CAA4B,CAAC;CAE1F,MAAM,aAAa,gCAAgC,KAAK,OAAO;CAC/D,OAAO,IAAI,UAAU;EACnB,MAAM,OAAO;EACb,MAAM;EACN,GAAI,CAAC,OAAO,WAAW,EAAE,SAAS,KAAK,IAAI,CAAC;EAC5C,GAAI,eAAe,KAAA,IAAY,EAAE,SAAS,WAAW,IAAI,CAAC;EAC1D,GAAI,OAAO,aAAa,KAAA,IAAY,EAAE,UAAU,OAAO,SAAS,IAAI,CAAC;CACvE,CAAC;AACH;;;;;;AAOA,SAAgB,yBACd,OACA,aACsB;CACtB,MAAM,cAAoC,CAAC;CAC3C,IAAI,MAAM,cAAc,CAAC,aACvB,YAAY,KAAK,IAAI,qBAAqB,EAAE,SAAS,MAAM,WAAW,QAAQ,CAAC,CAAC;CAElF,KAAK,MAAM,KAAK,MAAM,SACpB,YAAY,KACV,IAAI,iBAAiB;EACnB,SAAS,EAAE;EACX,GAAI,EAAE,SAAS,KAAA,IAAY,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACjD,CAAC,CACH;CAEF,KAAK,MAAM,MAAM,MAAM,aACrB,YAAY,KACV,IAAI,qBAAqB;EACvB,SAAS,GAAG;EACZ,UAAU,GAAG;EACb,YAAY,GAAG;EACf,GAAI,GAAG,SAAS,KAAA,IAAY,EAAE,MAAM,GAAG,KAAK,IAAI,CAAC;EACjD,GAAI,GAAG,aAAa,KAAA,IAAY,EAAE,UAAU,GAAG,SAAS,IAAI,CAAC;EAC7D,GAAI,GAAG,aAAa,KAAA,IAAY,EAAE,UAAU,GAAG,SAAS,IAAI,CAAC;CAC/D,CAAC,CACH;CAEF,OAAO;AACT;;;;;;;;;;;;;;;;ACzGA,SAAS,kBAAkB,OAA2D;CACpF,MAAM,OAAO,MAAM,YAAY,MAAM;CACrC,IAAI,SAAS,KAAA,GAAW,OAAO;CAK/B,QAJiB,UAGf,IAAI,CAAC,CAAC,UACR;EACE,KAAK,yBAAyB,QAAQ;GACpC,IAAI,MAAM,WAAW,aAAa,OAAO;GACzC,MAAM,WAAW,UACf,MAAM,QACR;GAIA,IAAI,kBAAkB,UAHP,UACb,MAAM,MAE6B,CAAC,GAAG,OAAO;GAGhD,OAAO,SAAS,WAAW,aAAa;EAC1C;EACA,KAAK,yBAAyB,eAC5B,OAAO,MAAM,WAAW,iBAAiB,gBAAgB;EAC3D,KAAK,yBAAyB;EAC9B,KAAK,yBAAyB;EAC9B,KAAK,yBAAyB,QAC5B,OAAO;EACT,SACE,OAAO;CACX;AACF;;;;;;;;;;;;AAaA,MAAa,yBAAgD,QAAQ,QAAQ;CAC3E,MAAM,0BAAU,IAAI,IAAoE;CACxF,MAAM,2BAAW,IAAI,IAAqB;CAE1C,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,MAAM,kBAAkB,KAAK;EACnC,IAAI,CAAC,KAAK;EACV,MAAM,YAAY,MAAM,KAAK;EAC7B,IAAI,cAAc,KAAA,GAAW;EAC7B,MAAM,QAAQ,QAAQ,IAAI,SAAS;EACnC,IAAI,OAAO;GACT,MAAM,OAAO,KAAK,KAAK;GACvB,IAAI,QAAQ,eAAe,MAAM,iBAAiB;EACpD,OACE,QAAQ,IAAI,WAAW;GAAE,QAAQ,CAAC,KAAK;GAAG,gBAAgB,QAAQ;EAAc,CAAC;EAEnF,SAAS,IAAI,KAAK;CACpB;CAEA,IAAI,QAAQ,SAAS,GAAG,OAAO,EAAE,MAAM,WAAW;CAElD,MAAM,QAA+B,CAAC;CACtC,KAAK,MAAM,CAAC,WAAW,UAAU,SAAS;EACxC,MAAM,gBAAgB,IAAI,SAAS,OAAO;EAC1C,MAAM,cAAc,IAAI,OAAO,OAAO;EACtC,IAAI,CAAC,iBAAiB,CAAC,aAAa;EACpC,MAAM,iBAA0C,MAAM,iBAClD,gBACA;EAIJ,MAAM,YAAY,kBAAkB,aAAa;EAIjD,MAAM,UAA6B,cAAc,QAAQ,KAAK,SAAS;GACrE,MAAM,IAAI,QAAQ,iBAAiB,WAAW,IAAI,OAAO;GACzD,SAAS,IAAI;EACf,EAAE;EAEF,MAAM,KACJ,IAAI,kBAAkB;GACpB;GACA,eAAe;GACf,mBAAmB,OAAO,KAAK,YAAY,OAAO;GAClD;GACA,SAAS,qBAAqB,WAAW,MAAM,MAAM;GACrD,YAAY,wBAAwB,WAAW,MAAM,QAAQ,SAAS;GACtE;EACF,CAAC,CACH;CACF;CAEA,OAAO;EACL,MAAM;EACN,QAAQ,OAAO,QAAQ,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;EAC7C;EACA,QAAQ;CACV;AACF;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAa,yCAAgE,QAAQ,QAAQ;CAC3F,IAAI,CAAC,IAAI,OAAO,wBAAwB,SAAS,MAAM,GACrD,OAAO,EAAE,MAAM,WAAW;CAG5B,MAAM,QAA+B,CAAC;CACtC,KAAK,MAAM,SAAS,QAAQ;EAC1B,IACE,MAAM,WAAW,eACjB,MAAM,aAAa,KAAA,KACnB,MAAM,WAAW,KAAA,GAEjB;EAMF,IAJiB,UAGf,MAAM,QAAQ,CAAC,CAAC,aACD,yBAAyB,QAAQ;EAElD,MAAM,iBAAiB,UAGrB,MAAM,QAAQ;EAChB,MAAM,eAAe,UACnB,MAAM,MACR;EACA,IAAI,eAAe,aAAa,aAAa,UAAU;EACvD,IAAI,eAAe,UAAU;EAE7B,MAAM,YAAY,MAAM,KAAK;EAC7B,IAAI,cAAc,KAAA,GAAW;EAE7B,MAAM,KACJ,IAAI,kBACF,2BAA2B,UAAU,GAAG,eAAe,QACvD,sBAAsB,UAAU,KAAK,eAAe,KAAK,+BACzD,WACA,eAAe,IACjB,CACF;CACF;CAEA,IAAI,MAAM,WAAW,GAAG,OAAO,EAAE,MAAM,WAAW;CAElD,OAAO;EACL,MAAM;EACN;EACA;EACA,QAAQ;CACV;AACF;AAEA,MAAa,0BAA4D,CACvE,uCACA,qBACF;;;;;;;;;;;ACnLA,SAAgB,eAAe,OAAgC;CAC7D,MAAM,OAAO,UAAU,KAAK;CAC5B,IAAI,SAAS,KAAA,GAAW,OAAO;CAC/B,QAAQ,KAAK,UAAb;EACE,KAAK,yBAAyB,YAC5B,OAAO,MAAM,WAAW,iBAAiB,KAAK;EAChD,KAAK,yBAAyB,QAC5B,OAAO,MAAM,WAAW,iBAAiB,KAAK;EAChD,KAAK,yBAAyB,YAC5B,OAAO,MAAM,WAAW,iBAAiB,KAAK;EAChD,KAAK,yBAAyB,OAC5B,OAAO,MAAM,WAAW,iBAAiB,KAAK;EAChD,KAAK,yBAAyB;GAC5B,IAAI,MAAM,WAAW,gBAAgB,OAAO;GAC5C,OAAO,MAAM,WAAW,cAAc,KAAK;EAC7C,KAAK,yBAAyB;GAC5B,IAAI,MAAM,WAAW,gBAAgB,OAAO;GAC5C,OAAO,MAAM,WAAW,cAAc,KAAK;EAC7C,KAAK,yBAAyB,OAC5B,OAAO,MAAM,WAAW,iBAAiB,KAAK;EAChD,KAAK,yBAAyB;GAC5B,IAAI,MAAM,WAAW,aAAa,OAAO;GACzC,OAAO,MAAM,WAAW,iBAAiB,KAAK;EAChD,SACE,OAAO;CACX;AACF;;AAGA,SAAgB,aAAa,OAAgC;CAC3D,OAAO,MAAM,KAAK,KAAK,GAAG;AAC5B;;;;;;;;;;;AAgBA,SAAgB,sBACd,QAC4B;CAC5B,MAAM,kBAAkB,OACrB,QAAQ,UAAU,MAAM,WAAW,eAAe,MAAM,WAAW,cAAc,CAAC,CAClF,KAAK,UAAU,MAAM,IAAI;CAC5B,IAAI,gBAAgB,WAAW,GAAG,OAAO;CACzC,OAAO,OAAO,QACX,UAAU,CAAC,gBAAgB,MAAM,aAAa,uBAAuB,MAAM,MAAM,QAAQ,CAAC,CAC7F;AACF;AAEA,SAAS,uBAAuB,MAAyB,UAAsC;CAC7F,IAAI,KAAK,UAAU,SAAS,QAAQ,OAAO;CAC3C,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,GACxC,IAAI,KAAK,OAAO,SAAS,IAAI,OAAO;CAEtC,OAAO;AACT;AAMA,SAAgB,UAAU,OAAqD;CAC7E,MAAM,OAAO,MAAM,YAAY,MAAM;CACrC,IAAI,SAAS,KAAA,GAAW,OAAO,KAAA;CAC/B,OAAO,UAGL,IAAI;AACR;;AAGA,SAAgB,kBAAkB,UAAuB,QAA8B;CACrF,IAAI,SAAS,uBAAuB,KAAA,KAAa,OAAO,uBAAuB,KAAA,GAC7E,OAAO,SAAS,uBAAuB,OAAO;CAEhD,OACE,SAAS,eAAe,OAAO,cAAc,QAAQ,SAAS,IAAI,MAAM,QAAQ,OAAO,IAAI;AAE/F;;;;;;;AAQA,SAAgB,kBAAkB,OAAoC;CACpE,MAAM,UAA8B,OAAO,OAAO,MAAM,OAAO,CAAC,CAAC,KAAK,MACpE,mBAAmB,GAAG,oCAAoC,OAAO,CAAC,CAAC,CACrE;CACA,MAAM,UAA8B,MAAM,QAAQ,KAAK,OAAO;EAC5D,SAAS,EAAE;EACX,GAAI,EAAE,SAAS,KAAA,IAAY,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACjD,EAAE;CAIF,MAAM,cAAsC,MAAM,YAAY,KAAK,QAAQ;EACzE,SAAS,GAAG;EACZ,YAAY;GAAE,OAAO,GAAG;GAAiB,SAAS,GAAG;EAAkB;EACvE,YAAY;EACZ,GAAI,GAAG,SAAS,KAAA,IAAY,EAAE,MAAM,GAAG,KAAK,IAAI,CAAC;EACjD,GAAI,GAAG,aAAa,KAAA,IAAY,EAAE,UAAU,GAAG,SAAS,IAAI,CAAC;EAC7D,GAAI,GAAG,aAAa,KAAA,IAAY,EAAE,UAAU,GAAG,SAAS,IAAI,CAAC;CAC/D,EAAE;CACF,OAAO;EACL;EACA,GAAI,MAAM,aAAa,EAAE,YAAY,EAAE,SAAS,MAAM,WAAW,QAAQ,EAAE,IAAI,CAAC;EAChF;EACA;CACF;AACF;AAMA,SAAS,cACP,MACA,SACA,UACoB;CACpB,OAAO;EACL;EACA;EACA,KAAK;EACL,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;CACjC;AACF;AAEA,SAAS,cAAc,WAAmB,YAAiD;CACzF,OAAO,eAAe,KAAA,IAAY;EAAE,OAAO;EAAW,QAAQ;CAAW,IAAI,EAAE,OAAO,UAAU;AAClG;;;;;;;AAQA,SAAS,qBAAqB,UAA8C;CAC1E,QAAQ,UAAR;EACE,KAAK,yBAAyB;EAC9B,KAAK,yBAAyB,QAC5B,OAAO;EACT,KAAK,yBAAyB,YAC5B,OAAO;EACT,SACE,OAAO;CACX;AACF;;;;;;;AAYA,SAAS,sBAAsB,OAA0C;CACvE,MAAM,UAAU,OAAO,OAAO,MAAM,OAAO,CAAC,CAAC,KAAK,MAChD,kBAAkB,GAAG,oCAAoC,OAAO,CAAC,CAAC,CACpE;CAIA,MAAM,cAAc,yBAAyB,OAHzB,OAAO,OAAO,MAAM,OAAO,CAAC,CAAC,MAAM,MACrD,oCAAoC,OAAO,CAAC,CAEgB,CAAC;CAC/D,MAAM,QAA+B,CACnC,IAAI,gBAAgB,MAAM,MAAM,SAAS,YAAY,SAAS,IAAI,cAAc,KAAA,CAAS,CAC3F;CACA,KAAK,MAAM,SAAS,MAAM,SAAS;EACjC,MAAM,YAAY,MAAM,QAAQ,iBAAiB,MAAM,MAAM,MAAM,OAAO;EAC1E,MAAM,KAAK,IAAI,gBAAgB,MAAM,MAAM,WAAW,MAAM,OAAO,CAAC;CACtE;CACA,OAAO;AACT;AAMA,SAAS,cACP,OAC4D;CAC5D,IAAI,MAAM,WAAW,aAKnB,OAAO,GAAG,sBAJI,UAGZ,MAAM,QAC4B,CAAC,CAAC;CAExC,IAAI,MAAM,WAAW,gBAAgB;EACnC,MAAM,QAAQ,UAGZ,MAAM,MAAM;EAEd,IAAI,oBAAoB,IAAI,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,CAAC;EACrD,OAAO,GAAG,CAAC,IAAI,cAAc,MAAM,IAAI,CAAC,CAAC;CAC3C;CAGA,OAAO,MACL,cAAc,wBAAwB,2BAA2B,MAAM,KAAK,KAAK,GAAG,GAAG,CACzF;AACF;AAEA,SAAS,eACP,OACA,KAC4D;CAC5D,MAAM,YAAY,MAAM,KAAK;CAC7B,IAAI,cAAc,KAAA,GAChB,OAAO,MACL,cACE,wBACA,0CAA0C,MAAM,KAAK,KAAK,GAAG,GAC/D,CACF;CAEF,IAAI,MAAM,WAAW,aAAa;EAChC,MAAM,SAAS,UAGb,MAAM,QAAQ;EAKhB,MAAM,QAAQ,IAAI,SAAS,OAAO;EAElC,OAAO,GAAG,CAAC,IAAI,cAAc,WAAW,mBAAmB,QAD5C,UAAU,KAAA,KAAa,oCAAoC,OAAO,MAAM,CACd,CAAC,CAAC,CAAC;CAC9E;CACA,IAAI,MAAM,WAAW,gBAKnB,OAAO,GAAG,CAAC,IAAI,eAAe,WAJf,UAGb,MAAM,MACsC,CAAC,CAAC,IAAI,CAAC,CAAC;CAKxD,MAAM,WAAW,UAGf,MAAM,QAAQ;CAMhB,OAAO,MAAM,cADA,kBAAkB,UAJhB,UAGb,MAAM,MACsC,CAAC,IAAI,iBAAiB,uBACnC,MAAM,KAAK,KAAK,GAAG,GAAG,cAAc,WAAW,SAAS,IAAI,CAAC,CAAC;AACjG;AAEA,SAAS,cACP,OAC4D;CAC5D,MAAM,YAAY,MAAM,KAAK;CAC7B,IAAI,cAAc,KAAA,GAChB,OAAO,MACL,cACE,wBACA,yCAAyC,MAAM,KAAK,KAAK,GAAG,GAC9D,CACF;CAEF,IAAI,MAAM,WAAW,aAAa;EAChC,MAAM,QAAQ,UAGZ,MAAM,QAAQ;EAEhB,OAAO,GAAG,CAAC,IAAI,gBAAgB,WADb,MAAM,QAAQ,iBAAiB,WAAW,MAAM,OAAO,GACpB,MAAM,OAAO,CAAC,CAAC;CACtE;CACA,IAAI,MAAM,WAAW,gBAAgB;EACnC,MAAM,QAAQ,UAGZ,MAAM,MAAM;EAEd,OAAO,GAAG,CAAC,IAAI,cAAc,WADX,MAAM,QAAQ,iBAAiB,WAAW,MAAM,OAAO,CACxB,CAAC,CAAC;CACrD;CAIA,OAAO,MAAM,cAAc,qBAAqB,MAAM,KAAK,KAAK,GAAG,GAAG,cAAc,SAAS,CAAC,CAAC;AACjG;AAEA,SAAgB,mBACd,OACA,KAC4D;CAC5D,MAAM,OAAO,UAAU,KAAK;CAC5B,IAAI,SAAS,KAAA,GACX,OAAO,MACL,cACE,wBACA,yDAAyD,MAAM,KAAK,KAAK,GAAG,GAC9E,CACF;CAEF,QAAQ,KAAK,UAAb;EACE,KAAK,yBAAyB,OAC5B,OAAO,cAAc,KAAK;EAC5B,KAAK,yBAAyB,QAC5B,OAAO,eAAe,OAAO,GAAG;EAClC,KAAK,yBAAyB,OAC5B,OAAO,cAAc,KAAK;EAC5B,KAAK,yBAAyB;EAC9B,KAAK,yBAAyB;EAC9B,KAAK,yBAAyB;EAC9B,KAAK,yBAAyB,QAC5B,OAAO,MAAM,cAAc,qBAAqB,KAAK,QAAQ,GAAG,MAAM,KAAK,KAAK,GAAG,CAAC,CAAC;EACvF,KAAK,yBAAyB,OAC5B,OAAO,MACL,cACE,wBACA,iDAAiD,MAAM,KAAK,KAAK,GAAG,GACtE,CACF;EACF,SACE,OAAO,MAAM,cAAc,wBAAwB,wBAAwB,KAAK,UAAU,CAAC;CAC/F;AACF;AAcA,SAAS,aAAa,MAAgD;CACpE,QAAQ,KAAK,aAAb;EACE,KAAK,eACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,eACH,OAAO;EACT,KAAK,cACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,aACH,OAAO;EAET,KAAK,iBACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAqBA,MAAM,iBAA2C,EAC/C,yBAAyB;CAAC;CAAY;CAAY;CAAe;AAAM,EACzE;AAEA,SAAgB,WACd,SAC0D;CAC1D,MAAM,iBAAiB,QAAQ,WAAW,KAAA;CAC1C,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,sBAAsB,QAAQ,uBAAuB,CAAC;CAE5D,MAAM,UAA2B;EAC/B,UAAU,QAAQ,YAAY,cAAc;EAC5C,QAAQ,QAAQ,UAAU,cAAc;EACxC;EACA;CACF;CAEA,MAAM,aAAa,QAAQ,cAAc;CAEzC,IAAI,YAAY,QAAQ;CACxB,MAAM,cAAqC,CAAC;CAC5C,MAAM,kBAAyC,CAAC;CAEhD,KAAK,MAAM,YAAY,YAAY;EACjC,MAAM,SAAS,SAAS,WAAW,OAAO;EAC1C,IAAI,OAAO,SAAS,SAAS;GAC3B,YAAY,OAAO;GACnB,IAAI,OAAO,QACT,YAAY,KAAK,GAAG,OAAO,KAAK;QAEhC,gBAAgB,KAAK,GAAG,OAAO,KAAK;EAExC;CACF;CAEA,MAAM,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC,MAAM,GAAG,MAAM;EAC3C,MAAM,YAAY,eAAe,CAAC,IAAI,eAAe,CAAC;EACtD,IAAI,cAAc,GAAG,OAAO;EAC5B,MAAM,OAAO,aAAa,CAAC;EAC3B,MAAM,OAAO,aAAa,CAAC;EAC3B,OAAO,OAAO,OAAO,KAAK,OAAO,OAAO,IAAI;CAC9C,CAAC;CAED,MAAM,eAAsC,CAAC;CAC7C,MAAM,YAAkC,CAAC;CAEzC,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,SAAS,mBAAmB,OAAO,OAAO;EAChD,IAAI,OAAO,IACT,aAAa,KAAK,GAAG,OAAO,KAAK;OAEjC,UAAU,KAAK,OAAO,OAAO;CAEjC;CAIA,MAAM,UAAU,OAAO;CACvB,IAAI,cAAc;CAClB,IAAI,kBAAkB;CACtB,IAAI,eAAe;CACnB,IAAI,gBAAgB;EAClB,MAAM,QAAQ,SAAgC,SAA8B;GAC1E,IAAI,QAAQ,SAAS,KAAK,cAAc,GAAG;IACzC,IAAI,KAAK,IAAI;IACb;GACF;GACA,UAAU,KAAK,0BAA0B,MAAM,OAAO,CAAC;EACzD;EACA,MAAM,oBAA2C,CAAC;EAClD,MAAM,wBAA+C,CAAC;EACtD,MAAM,qBAA4C,CAAC;EACnD,YAAY,QAAQ,KAAK,iBAAiB,CAAC;EAC3C,gBAAgB,QAAQ,KAAK,qBAAqB,CAAC;EACnD,aAAa,QAAQ,KAAK,kBAAkB,CAAC;EAC7C,cAAc;EACd,kBAAkB;EAClB,eAAe;CACjB;CAEA,IAAI,UAAU,SAAS,GACrB,OAAO,MAAM,SAAS;CAKxB,MAAM,WAAW,CAAC,GAAG,cAAc,GAAG,eAAe;CACrD,MAAM,cAAc,QAAsB,SAAS,QAAQ,MAAM,aAAa,CAAC,MAAM,GAAG;CAYxF,OAAO,GAAG,EAAE,OAAA;EATV,GAAG,WAAW,cAAc;EAC5B,GAAG,WAAW,YAAY;EAC1B,GAAG,WAAW,cAAc;EAC5B,GAAG;EACH,GAAG,WAAW,aAAa;EAC3B,GAAG,WAAW,YAAY;EAC1B,GAAG,WAAW,YAAY;CAGZ,EAAE,CAAC;AACrB;AAEA,SAAS,gBAA6B;CACpC,OAAO,IAAI,YAAY,EAAE,QAAQ,CAAC,EAAE,CAAC;AACvC;AAEA,SAAS,0BACP,MACA,SACoB;CACpB,MAAM,UAAU,cAAc,KAAK,MAAM,oBAAoB,KAAK,eAAe,6BAA6B,QAAQ,KAAK,IAAI;CAC/H,MAAM,WAAW,gBAAgB,IAAI;CACrC,OAAO;EACL,MAAM,oBAAoB,IAAI;EAC9B;EACA,KAAK;EACL,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;CACjC;AACF;AAEA,SAAS,oBAAoB,MAAuD;CAClF,QAAQ,KAAK,aAAb;EACE,KAAK;EACL,KAAK,aACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAEA,SAAS,gBAAgB,MAAmE;CAC1F,MAAM,WAAgE,CAAC;CACvE,IAAI,eAAe,MAAM,SAAS,QAAQ,KAAK;CAC/C,IAAI,gBAAgB,MAAM,SAAS,SAAS,KAAK;CACjD,IAAI,eAAe,MAAM,SAAS,QAAQ,KAAK;CAC/C,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,SAAS,IAAK,WAA0C,KAAA;AACvF;;;AC/jBA,SAAgB,6BACd,SACwB;CACxB,OAAO,IAAI,uBAAuB,OAAO;AAC3C;;;;;;;;;;;;;;;;;AAsBA,IAAa,yBAAb,MAEA;CACE;CAEA,YAAY,SAAgC;EAC1C,KAAKC,WAAW;CAClB;CAEA,KAAK,SA2BgB;EACnB,OAAO,KAAK,QAAQ,OAAyC;CAC/D;CAEA,eACE,SACA,SACqC;EACrC,OAAO,IAAI,oCACT,CAAC,GACD;GACE,MAAM,QAAQ;GACd,IAAI,QAAQ;EACd,GACA,SACA,KAAA,GACA,KAAKA,QACP;CACF;CAEA,QAAgB,SAA2D;EACzE,MAAM,eAAe,KAAK,qBAAqB,QAAQ,MAAM;EAC7D,IAAI,cAAc,OAAO;EAEzB,MAAM,EAAE,UAAU,QAAQ,WAAW,KAAK,oBAAoB,OAAO;EACrE,MAAM,aAAa,yBAAyB,QAAQ,mBAAmB;EAEvE,MAAM,SAAS,WAAW;GACxB;GACA;GACA;GACA,QAAQ,QAAQ;GAChB,qBAAqB,QAAQ;GAC7B,YAAY;EACd,CAAC;EAED,IAAI,CAAC,OAAO,IACV,OAAO,eAAe,OAAO,OAAO;EAStC,MAAM,gBAAgB,yBAAyB;GAC7C,eAAe,QAAQ;GACvB,aAAa,QAAQ;GACrB;EACF,CAAC;EAID,MAAM,QAAQ,CAAC,GAAG,OAAO,MAAM,OAAO,GAAG,aAAa;EAEtD,MAAM,cAA8C;GAClD,aAAa,QAAQ,SAAS,QAAQ;GACtC,GAAI,QAAQ,SAAS,gBAAgB,KAAA,IACjC,EAAE,aAAa,QAAQ,SAAS,YAAY,IAC5C,CAAC;EACP;EAEA,OAAO;GACL,MAAM;GACN,MAAM,IAAI,oCACR,OACA;IACE,MAAM,QAAQ,cAAc,QAAQ,eAAe;IACnD,IAAI,QAAQ,SAAS,QAAQ;GAC/B,GACA,QAAQ,SACR,aACA,KAAKA,QACP;EACF;CACF;CAEA,qBAA6B,QAAkE;EAC7F,IAAI,CAAC,OAAO,wBAAwB,SAAS,UAAU,GACrD,OAAO,eAAe,CACpB;GACE,MAAM;GACN,SAAS;GACT,KAAK;EACP,CACF,CAAC;EAEH,OAAO;CACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BA,oBAA4B,SAI1B;EACA,MAAM,UAAU,QAAQ,OAAO;EAC/B,MAAM,SAAS,QAAQ,SAAS,UAAU,KAAK,QAAQ,SAAS,aAAa;EAC7E,MAAM,EACJ,UACA,QACA,QAAQ,cACN,oBAAoB;GACtB,UAAU,QAAQ;GAClB,cAAc,QAAQ;GACtB,qBAAqB,QAAQ;EAC/B,CAAC;EAED,MAAM,QAAQ,oBADI,sBAAsB,SACE,GAAG,QAAQ,SAAS;EAE9D,OAAO;GAAE;GAAU;GAAQ,QADZ,SAAS,QAAQ,MAAM,QAAQ,UAAU,MAAM,WAAW,cAAc;EACrD;CACpC;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAS,oBACP,QACA,WAC4B;CAC5B,IAAI,cAAc,KAAA,GAAW,OAAO;CACpC,OAAO,OAAO,QAAQ,UAAU;EAC9B,IAAI,MAAM,WAAW,gBAAgB,OAAO;EAC5C,MAAM,OAAO,UAAU,KAAK;EAC5B,IAAI,SAAS,KAAA,KAAa,KAAK,aAAa,yBAAyB,OAAO,OAAO;EACnF,MAAM,YAAY,MAAM,KAAK;EAC7B,OACE,cAAc,KAAA,KACd,CAAC,UAAU,eAAe;GACxB,aAAa;GACb,YAAY;GACZ,YAAY;EACd,CAAC;CAEL,CAAC;AACH"}
@@ -1,5 +1,5 @@
1
1
  import { t as renderOps } from "./render-ops-BDW2tUeR.mjs";
2
- import { t as SqliteMigration } from "./sqlite-migration-A0rwqPOG.mjs";
2
+ import { t as SqliteMigration } from "./sqlite-migration-BNiSiP0z.mjs";
3
3
  import { renderImports } from "@prisma-next/ts-render";
4
4
  import { detectScaffoldRuntime, shebangLineFor } from "@prisma-next/migration-tools/migration-ts";
5
5
  //#region src/core/migrations/render-typescript.ts
@@ -24,14 +24,18 @@ const BASE_IMPORTS = [{
24
24
  symbol: "MigrationCLI"
25
25
  }];
26
26
  function renderCallsToTypeScript(calls, meta) {
27
- const imports = buildImports(calls);
27
+ const imports = buildImports(calls, meta);
28
28
  const operationsBody = calls.map((c) => c.renderTypeScript()).join(",\n");
29
+ const hasStart = meta.from !== null;
30
+ const startField = hasStart ? [" override readonly startContractJson = startContract;"] : [];
29
31
  return [
30
32
  shebangLineFor(detectScaffoldRuntime()),
31
33
  imports,
32
34
  "",
33
- "export default class M extends Migration {",
34
- buildDescribeMethod(meta),
35
+ `export default class M extends Migration<${hasStart ? "Start" : "never"}, End> {`,
36
+ ...startField,
37
+ " override readonly endContractJson = endContract;",
38
+ "",
35
39
  " override get operations() {",
36
40
  " return [",
37
41
  indent(operationsBody, 6),
@@ -43,21 +47,46 @@ function renderCallsToTypeScript(calls, meta) {
43
47
  ""
44
48
  ].join("\n");
45
49
  }
46
- function buildImports(calls) {
47
- const requirements = [...BASE_IMPORTS];
50
+ function buildImports(calls, meta) {
51
+ const requirements = [...BASE_IMPORTS, ...contractImports(meta)];
48
52
  for (const call of calls) for (const req of call.importRequirements()) requirements.push(req);
49
53
  return renderImports(requirements);
50
54
  }
51
- function buildDescribeMethod(meta) {
52
- const lines = [];
53
- lines.push(" override describe() {");
54
- lines.push(" return {");
55
- lines.push(` from: ${JSON.stringify(meta.from)},`);
56
- lines.push(` to: ${JSON.stringify(meta.to)},`);
57
- lines.push(" };");
58
- lines.push(" }");
59
- lines.push("");
60
- return lines.join("\n");
55
+ /**
56
+ * The committed contract-JSON imports the scaffold reads its from/to identity
57
+ * from. `end-contract.json` is always present; `start-contract.json` is added
58
+ * only for a non-baseline migration (`meta.from !== null`). The matching
59
+ * `Contract` type imports (aliased `Start`/`End`) feed the
60
+ * `Migration<Start, End>` generics. Baseline emits `Migration<never, End>` with
61
+ * no start imports — `never` is the honest "no prior contract" Start.
62
+ */
63
+ function contractImports(meta) {
64
+ const reqs = [{
65
+ moduleSpecifier: "./end-contract.json",
66
+ symbol: "endContract",
67
+ kind: "default",
68
+ attributes: { type: "json" }
69
+ }, {
70
+ moduleSpecifier: "./end-contract",
71
+ symbol: "Contract",
72
+ alias: "End",
73
+ typeOnly: true
74
+ }];
75
+ if (meta.from !== null) {
76
+ reqs.push({
77
+ moduleSpecifier: "./start-contract.json",
78
+ symbol: "startContract",
79
+ kind: "default",
80
+ attributes: { type: "json" }
81
+ });
82
+ reqs.push({
83
+ moduleSpecifier: "./start-contract",
84
+ symbol: "Contract",
85
+ alias: "Start",
86
+ typeOnly: true
87
+ });
88
+ }
89
+ return reqs;
61
90
  }
62
91
  function indent(text, spaces) {
63
92
  const pad = " ".repeat(spaces);
@@ -108,4 +137,4 @@ var TypeScriptRenderableSqliteMigration = class extends SqliteMigration {
108
137
  //#endregion
109
138
  export { TypeScriptRenderableSqliteMigration as t };
110
139
 
111
- //# sourceMappingURL=planner-produced-sqlite-migration-0xPEm3R1.mjs.map
140
+ //# sourceMappingURL=planner-produced-sqlite-migration-BDzhFAoW.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner-produced-sqlite-migration-BDzhFAoW.mjs","names":["#calls","#meta","#destination","#spaceId","#lowerer","#operationsCache"],"sources":["../src/core/migrations/render-typescript.ts","../src/core/migrations/planner-produced-sqlite-migration.ts"],"sourcesContent":["/**\n * Polymorphic TypeScript emitter for the SQLite migration IR. Mirrors the\n * Postgres `render-typescript.ts` — different base-class + factory module\n * specifier, same overall shape.\n */\n\nimport type { OpFactoryCall } from '@prisma-next/framework-components/control';\nimport { detectScaffoldRuntime, shebangLineFor } from '@prisma-next/migration-tools/migration-ts';\nimport { type ImportRequirement, renderImports } from '@prisma-next/ts-render';\n\nexport interface RenderMigrationMeta {\n readonly from: string | null;\n readonly to: string;\n}\n\n/**\n * Always-present base imports for the rendered scaffold. Both come from\n * `@prisma-next/sqlite/migration` so an authored SQLite\n * `migration.ts` only needs a single dependency for its base class and\n * its CLI entrypoint. Mirrors Postgres's `BASE_IMPORTS`.\n *\n * - `Migration` — the facade re-export fixes the `SqlMigration`\n * generic to `SqlitePlanTargetDetails` and the abstract `targetId` to\n * `'sqlite'`.\n * - `MigrationCLI` — the migration-file CLI entrypoint, re-exported from\n * `@prisma-next/cli/migration-cli`. Loads `prisma-next.config.ts`,\n * assembles a `ControlStack`, and instantiates the migration class.\n */\nconst BASE_IMPORTS: readonly ImportRequirement[] = [\n { moduleSpecifier: '@prisma-next/sqlite/migration', symbol: 'Migration' },\n { moduleSpecifier: '@prisma-next/sqlite/migration', symbol: 'MigrationCLI' },\n];\n\nexport function renderCallsToTypeScript(\n calls: ReadonlyArray<OpFactoryCall>,\n meta: RenderMigrationMeta,\n): string {\n const imports = buildImports(calls, meta);\n const operationsBody = calls.map((c) => c.renderTypeScript()).join(',\\n');\n const hasStart = meta.from !== null;\n const startField = hasStart ? [' override readonly startContractJson = startContract;'] : [];\n\n return [\n shebangLineFor(detectScaffoldRuntime()),\n imports,\n '',\n `export default class M extends Migration<${hasStart ? 'Start' : 'never'}, End> {`,\n ...startField,\n ' override readonly endContractJson = endContract;',\n '',\n ' override get operations() {',\n ' return [',\n indent(operationsBody, 6),\n ' ];',\n ' }',\n '}',\n '',\n 'MigrationCLI.run(import.meta.url, M);',\n '',\n ].join('\\n');\n}\n\nfunction buildImports(calls: ReadonlyArray<OpFactoryCall>, meta: RenderMigrationMeta): string {\n const requirements: ImportRequirement[] = [...BASE_IMPORTS, ...contractImports(meta)];\n for (const call of calls) {\n for (const req of call.importRequirements()) {\n requirements.push(req);\n }\n }\n return renderImports(requirements);\n}\n\n/**\n * The committed contract-JSON imports the scaffold reads its from/to identity\n * from. `end-contract.json` is always present; `start-contract.json` is added\n * only for a non-baseline migration (`meta.from !== null`). The matching\n * `Contract` type imports (aliased `Start`/`End`) feed the\n * `Migration<Start, End>` generics. Baseline emits `Migration<never, End>` with\n * no start imports — `never` is the honest \"no prior contract\" Start.\n */\nfunction contractImports(meta: RenderMigrationMeta): readonly ImportRequirement[] {\n const reqs: ImportRequirement[] = [\n {\n moduleSpecifier: './end-contract.json',\n symbol: 'endContract',\n kind: 'default',\n attributes: { type: 'json' },\n },\n { moduleSpecifier: './end-contract', symbol: 'Contract', alias: 'End', typeOnly: true },\n ];\n if (meta.from !== null) {\n reqs.push({\n moduleSpecifier: './start-contract.json',\n symbol: 'startContract',\n kind: 'default',\n attributes: { type: 'json' },\n });\n reqs.push({\n moduleSpecifier: './start-contract',\n symbol: 'Contract',\n alias: 'Start',\n typeOnly: true,\n });\n }\n return reqs;\n}\n\nfunction indent(text: string, spaces: number): string {\n const pad = ' '.repeat(spaces);\n return text\n .split('\\n')\n .map((line) => (line.trim() ? `${pad}${line}` : line))\n .join('\\n');\n}\n","import type { SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';\nimport type { ExecuteRequestLowerer } from '@prisma-next/family-sql/control-adapter';\nimport type {\n MigrationPlanWithAuthoringSurface,\n OpFactoryCall,\n} from '@prisma-next/framework-components/control';\nimport type { MigrationMeta } from '@prisma-next/migration-tools/migration';\nimport type { SqlitePlanTargetDetails } from './planner-target-details';\nimport { renderOps } from './render-ops';\nimport { renderCallsToTypeScript } from './render-typescript';\nimport { SqliteMigration } from './sqlite-migration';\n\ntype Op = SqlMigrationPlanOperation<SqlitePlanTargetDetails>;\n\nexport interface SqliteMigrationDestinationInfo {\n readonly storageHash: string;\n readonly profileHash?: string;\n}\n\nexport class TypeScriptRenderableSqliteMigration\n extends SqliteMigration\n implements MigrationPlanWithAuthoringSurface\n{\n readonly #calls: readonly OpFactoryCall[];\n readonly #meta: MigrationMeta;\n readonly #destination: SqliteMigrationDestinationInfo;\n readonly #spaceId: string;\n readonly #lowerer: ExecuteRequestLowerer | undefined;\n #operationsCache: readonly (Op | Promise<Op>)[] | undefined;\n\n constructor(\n calls: readonly OpFactoryCall[],\n meta: MigrationMeta,\n spaceId: string,\n destination?: SqliteMigrationDestinationInfo,\n lowerer?: ExecuteRequestLowerer,\n ) {\n super();\n this.#calls = calls;\n this.#meta = meta;\n this.#spaceId = spaceId;\n this.#destination = destination ?? { storageHash: meta.to };\n this.#lowerer = lowerer;\n }\n\n override get operations(): readonly (Op | Promise<Op>)[] {\n this.#operationsCache ??= renderOps(this.#calls, this.#lowerer);\n return this.#operationsCache;\n }\n\n override describe(): MigrationMeta {\n return this.#meta;\n }\n\n override get destination(): SqliteMigrationDestinationInfo {\n return this.#destination;\n }\n\n /**\n * Contract space this planner-produced plan applies to. Threaded\n * from {@link SqlMigrationPlannerPlanOptions.spaceId} so the runner\n * keys the marker row by the right space when executing the plan.\n */\n get spaceId(): string {\n return this.#spaceId;\n }\n\n renderTypeScript(): string {\n return renderCallsToTypeScript(this.#calls, {\n from: this.#meta.from,\n to: this.#meta.to,\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4BA,MAAM,eAA6C,CACjD;CAAE,iBAAiB;CAAiC,QAAQ;AAAY,GACxE;CAAE,iBAAiB;CAAiC,QAAQ;AAAe,CAC7E;AAEA,SAAgB,wBACd,OACA,MACQ;CACR,MAAM,UAAU,aAAa,OAAO,IAAI;CACxC,MAAM,iBAAiB,MAAM,KAAK,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,KAAK;CACxE,MAAM,WAAW,KAAK,SAAS;CAC/B,MAAM,aAAa,WAAW,CAAC,wDAAwD,IAAI,CAAC;CAE5F,OAAO;EACL,eAAe,sBAAsB,CAAC;EACtC;EACA;EACA,4CAA4C,WAAW,UAAU,QAAQ;EACzE,GAAG;EACH;EACA;EACA;EACA;EACA,OAAO,gBAAgB,CAAC;EACxB;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,IAAI;AACb;AAEA,SAAS,aAAa,OAAqC,MAAmC;CAC5F,MAAM,eAAoC,CAAC,GAAG,cAAc,GAAG,gBAAgB,IAAI,CAAC;CACpF,KAAK,MAAM,QAAQ,OACjB,KAAK,MAAM,OAAO,KAAK,mBAAmB,GACxC,aAAa,KAAK,GAAG;CAGzB,OAAO,cAAc,YAAY;AACnC;;;;;;;;;AAUA,SAAS,gBAAgB,MAAyD;CAChF,MAAM,OAA4B,CAChC;EACE,iBAAiB;EACjB,QAAQ;EACR,MAAM;EACN,YAAY,EAAE,MAAM,OAAO;CAC7B,GACA;EAAE,iBAAiB;EAAkB,QAAQ;EAAY,OAAO;EAAO,UAAU;CAAK,CACxF;CACA,IAAI,KAAK,SAAS,MAAM;EACtB,KAAK,KAAK;GACR,iBAAiB;GACjB,QAAQ;GACR,MAAM;GACN,YAAY,EAAE,MAAM,OAAO;EAC7B,CAAC;EACD,KAAK,KAAK;GACR,iBAAiB;GACjB,QAAQ;GACR,OAAO;GACP,UAAU;EACZ,CAAC;CACH;CACA,OAAO;AACT;AAEA,SAAS,OAAO,MAAc,QAAwB;CACpD,MAAM,MAAM,IAAI,OAAO,MAAM;CAC7B,OAAO,KACJ,MAAM,IAAI,CAAC,CACX,KAAK,SAAU,KAAK,KAAK,IAAI,GAAG,MAAM,SAAS,IAAK,CAAC,CACrD,KAAK,IAAI;AACd;;;AC9FA,IAAa,sCAAb,cACU,gBAEV;CACE;CACA;CACA;CACA;CACA;CACA;CAEA,YACE,OACA,MACA,SACA,aACA,SACA;EACA,MAAM;EACN,KAAKA,SAAS;EACd,KAAKC,QAAQ;EACb,KAAKE,WAAW;EAChB,KAAKD,eAAe,eAAe,EAAE,aAAa,KAAK,GAAG;EAC1D,KAAKE,WAAW;CAClB;CAEA,IAAa,aAA4C;EACvD,KAAKC,qBAAqB,UAAU,KAAKL,QAAQ,KAAKI,QAAQ;EAC9D,OAAO,KAAKC;CACd;CAEA,WAAmC;EACjC,OAAO,KAAKJ;CACd;CAEA,IAAa,cAA8C;EACzD,OAAO,KAAKC;CACd;;;;;;CAOA,IAAI,UAAkB;EACpB,OAAO,KAAKC;CACd;CAEA,mBAA2B;EACzB,OAAO,wBAAwB,KAAKH,QAAQ;GAC1C,MAAM,KAAKC,MAAM;GACjB,IAAI,KAAKA,MAAM;EACjB,CAAC;CACH;AACF"}
@@ -1,9 +1,9 @@
1
1
  import { t as SqlitePlanTargetDetails } from "./planner-target-details-xR6UfIcz.mjs";
2
- import { t as SqliteMigration } from "./sqlite-migration-DVfhQwN_.mjs";
2
+ import { t as SqliteMigration } from "./sqlite-migration-BYbzskpE.mjs";
3
3
  import { SqlMigrationPlanOperation } from "@prisma-next/family-sql/control";
4
4
  import { MigrationPlanWithAuthoringSurface, OpFactoryCall } from "@prisma-next/framework-components/control";
5
- import { ExecuteRequestLowerer } from "@prisma-next/family-sql/control-adapter";
6
5
  import { MigrationMeta } from "@prisma-next/migration-tools/migration";
6
+ import { ExecuteRequestLowerer } from "@prisma-next/family-sql/control-adapter";
7
7
 
8
8
  //#region src/core/migrations/planner-produced-sqlite-migration.d.ts
9
9
  type Op = SqlMigrationPlanOperation<SqlitePlanTargetDetails>;
@@ -27,4 +27,4 @@ declare class TypeScriptRenderableSqliteMigration extends SqliteMigration implem
27
27
  }
28
28
  //#endregion
29
29
  export { TypeScriptRenderableSqliteMigration as n, SqliteMigrationDestinationInfo as t };
30
- //# sourceMappingURL=planner-produced-sqlite-migration-CpgsY-M9.d.mts.map
30
+ //# sourceMappingURL=planner-produced-sqlite-migration-o1qUzwLk.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"planner-produced-sqlite-migration-CpgsY-M9.d.mts","names":[],"sources":["../src/core/migrations/planner-produced-sqlite-migration.ts"],"mappings":";;;;;;;;KAYK,EAAA,GAAK,yBAAyB,CAAC,uBAAA;AAAA,UAEnB,8BAAA;EAAA,SACN,WAAA;EAAA,SACA,WAAW;AAAA;AAAA,cAGT,mCAAA,SACH,eAAA,YACG,iCAAA;EAAA;cAUT,KAAA,WAAgB,aAAA,IAChB,IAAA,EAAM,aAAA,EACN,OAAA,UACA,WAAA,GAAc,8BAAA,EACd,OAAA,GAAU,qBAAA;EAAA,IAUC,UAAA,cAAwB,EAAA,GAAK,OAAA,CAAQ,EAAA;EAKzC,QAAA,IAAY,aAAA;EAAA,IAIR,WAAA,IAAe,8BAAA;EAtCR;AAGtB;;;;EAHsB,IA+ChB,OAAA;EAIJ,gBAAA;AAAA"}
1
+ {"version":3,"file":"planner-produced-sqlite-migration-o1qUzwLk.d.mts","names":[],"sources":["../src/core/migrations/planner-produced-sqlite-migration.ts"],"mappings":";;;;;;;;KAYK,EAAA,GAAK,yBAAyB,CAAC,uBAAA;AAAA,UAEnB,8BAAA;EAAA,SACN,WAAA;EAAA,SACA,WAAW;AAAA;AAAA,cAGT,mCAAA,SACH,eAAA,YACG,iCAAA;EAAA;cAUT,KAAA,WAAgB,aAAA,IAChB,IAAA,EAAM,aAAA,EACN,OAAA,UACA,WAAA,GAAc,8BAAA,EACd,OAAA,GAAU,qBAAA;EAAA,IAUC,UAAA,cAAwB,EAAA,GAAK,OAAA,CAAQ,EAAA;EAKzC,QAAA,IAAY,aAAA;EAAA,IAIR,WAAA,IAAe,8BAAA;EAtCR;AAGtB;;;;EAHsB,IA+ChB,OAAA;EAIJ,gBAAA;AAAA"}
@@ -1,2 +1,2 @@
1
- import { n as TypeScriptRenderableSqliteMigration, t as SqliteMigrationDestinationInfo } from "./planner-produced-sqlite-migration-CpgsY-M9.mjs";
1
+ import { n as TypeScriptRenderableSqliteMigration, t as SqliteMigrationDestinationInfo } from "./planner-produced-sqlite-migration-o1qUzwLk.mjs";
2
2
  export { type SqliteMigrationDestinationInfo, TypeScriptRenderableSqliteMigration };
@@ -1,2 +1,2 @@
1
- import { t as TypeScriptRenderableSqliteMigration } from "./planner-produced-sqlite-migration-0xPEm3R1.mjs";
1
+ import { t as TypeScriptRenderableSqliteMigration } from "./planner-produced-sqlite-migration-BDzhFAoW.mjs";
2
2
  export { TypeScriptRenderableSqliteMigration };
@@ -1,7 +1,7 @@
1
1
  import { t as SqlitePlanTargetDetails } from "./planner-target-details-xR6UfIcz.mjs";
2
- import { n as TypeScriptRenderableSqliteMigration } from "./planner-produced-sqlite-migration-CpgsY-M9.mjs";
2
+ import { n as TypeScriptRenderableSqliteMigration } from "./planner-produced-sqlite-migration-o1qUzwLk.mjs";
3
3
  import { MigrationOperationPolicy, SqlMigrationPlanner, SqlPlannerFailureResult } from "@prisma-next/family-sql/control";
4
- import { MigrationPlanner, MigrationScaffoldContext } from "@prisma-next/framework-components/control";
4
+ import { MigrationPlanner, MigrationScaffoldContext, SchemaOwnership } from "@prisma-next/framework-components/control";
5
5
  import { Contract } from "@prisma-next/contract/types";
6
6
  import { ExecuteRequestLowerer } from "@prisma-next/family-sql/control-adapter";
7
7
  import { TargetBoundComponentDescriptor } from "@prisma-next/framework-components/components";
@@ -15,16 +15,18 @@ type SqlitePlanResult = {
15
15
  /**
16
16
  * SQLite migration planner — a thin wrapper over `planIssues`.
17
17
  *
18
- * `plan()` verifies the live schema against the target contract (producing
19
- * `SchemaIssue[]`) and delegates to `planIssues` with the registered
20
- * strategies. Strategies absorb groups of related issues into composite
21
- * recipes (e.g. recreating a table to apply type/nullability/default/
22
- * constraint changes at once); anything not absorbed by a strategy flows
23
- * through `mapIssueToCall` in the issue planner as a one-off call.
18
+ * `plan()` diffs the live schema against the target contract via the one
19
+ * differ (`buildSqlitePlanDiff`, producing node-typed `SchemaDiffIssue[]`)
20
+ * and delegates to `planIssues` with the registered strategies. Strategies
21
+ * absorb groups of related issues into composite recipes (e.g. recreating a
22
+ * table to apply type/nullability/default/constraint changes at once);
23
+ * anything not absorbed by a strategy flows through `mapNodeIssueToCall` in
24
+ * the issue planner as a one-off call.
24
25
  *
25
- * FK-backing indexes are surfaced by `verifySqlSchema`'s index expansion
26
- * (see `verify-sql-schema.ts:459-469`), so `mapIssueToCall` handles them
27
- * uniformly alongside user-declared indexes.
26
+ * FK-backing indexes are already merged into the expected table node's
27
+ * `indexes` at derivation (`contractToSchemaIR`'s `convertTable`), so
28
+ * `mapNodeIssueToCall` handles them uniformly alongside user-declared
29
+ * indexes — no separate expansion step in the planner.
28
30
  */
29
31
  declare class SqliteMigrationPlanner implements SqlMigrationPlanner<SqlitePlanTargetDetails>, MigrationPlanner<'sql', 'sqlite'> {
30
32
  #private;
@@ -51,10 +53,44 @@ declare class SqliteMigrationPlanner implements SqlMigrationPlanner<SqlitePlanTa
51
53
  * the marker row by the right space.
52
54
  */
53
55
  readonly spaceId: string;
56
+ /**
57
+ * Ownership oracle over the contract-space composition — see
58
+ * {@link SqlMigrationPlannerPlanOptions.ownership}.
59
+ */
60
+ readonly ownership?: SchemaOwnership;
54
61
  }): SqlitePlanResult;
55
62
  emptyMigration(context: MigrationScaffoldContext, spaceId: string): TypeScriptRenderableSqliteMigration;
56
63
  private planSql;
57
64
  private ensureAdditivePolicy;
65
+ /**
66
+ * Diffs the target contract against the live schema via the one differ
67
+ * (the same tree-building `diffSqliteSchema` uses, plus the
68
+ * op-render stamper) and prepares the issue list `planIssues` consumes.
69
+ *
70
+ * Three passes, in order:
71
+ * 1. Subtree coalescing — the differ is total (a missing/extra table also
72
+ * emits an issue for every column/constraint under it); those nested
73
+ * issues are redundant once the table-level `CreateTable`/`DropTable`
74
+ * call already accounts for the whole subtree. Runs FIRST, over the
75
+ * complete diff: a sibling-owned extra table's column issues must
76
+ * collapse into its one table-level issue before the ownership pass,
77
+ * because a bare column node carries no table reference — if coalescing
78
+ * ran after ownership dropped the table-level issue, the orphaned column
79
+ * issues would survive and the planner would emit drops against a
80
+ * sibling space's table.
81
+ * 2. Ownership — a live extra is only this plan's to drop when no contract
82
+ * space owns it. The differ ran against THIS space's contract, so a
83
+ * table a sibling owns surfaces here as `not-expected`; the planner asks
84
+ * the ownership oracle (the passive aggregate) whether any space declares
85
+ * it and, if so, leaves it alone. A table no space owns stays a genuine
86
+ * extra. Ownership lives in the aggregate; the planner only asks. No
87
+ * oracle (single-space) keeps every extra.
88
+ * 3. Strict-mode extras gating — `not-expected` (extra table/column/
89
+ * constraint) issues are dropped entirely outside strict mode, mirroring
90
+ * the retired coordinate walk's `if (strict) { ...extra_* } }` guards:
91
+ * an additive-only plan must never even consider dropping an unclaimed
92
+ * object, not just refuse to emit the drop.
93
+ */
58
94
  private collectSchemaIssues;
59
95
  }
60
96
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"planner.d.mts","names":[],"sources":["../src/core/migrations/planner.ts"],"mappings":";;;;;;;;;iBA8BgB,4BAAA,CACd,OAAA,EAAS,qBAAA,GACR,sBAAsB;AAAA,KAIb,gBAAA;EAAA,SACG,IAAA;EAAA,SAA0B,IAAA,EAAM,mCAAA;AAAA,IAC3C,uBAAuB;;;;;;AANF;AAIzB;;;;;;;;cAkBa,sBAAA,YACA,mBAAA,CAAoB,uBAAA,GAA0B,gBAAA;EAAA;cAI7C,OAAA,EAAS,qBAAA;EAIrB,IAAA,CAAK,OAAA;IAAA,SACM,QAAA;IAAA,SACA,MAAA;IAAA,SACA,MAAA,EAAQ,wBAAA;IAAA;;;;;;;;;;IAAA,SAWR,YAAA,EAAc,QAAA;IAAA,SACd,mBAAA,EAAqB,aAAA,CAAc,8BAAA;IAvBf;;;;;IAAA,SA6BpB,OAAA;EAAA,IACP,gBAAA;EAIJ,cAAA,CACE,OAAA,EAAS,wBAAA,EACT,OAAA,WACC,mCAAA;EAAA,QAaK,OAAA;EAAA,QA8DA,oBAAA;EAAA,QAaA,mBAAA;AAAA"}
1
+ {"version":3,"file":"planner.d.mts","names":[],"sources":["../src/core/migrations/planner.ts"],"mappings":";;;;;;;;;iBA+BgB,4BAAA,CACd,OAAA,EAAS,qBAAA,GACR,sBAAsB;AAAA,KAIb,gBAAA;EAAA,SACG,IAAA;EAAA,SAA0B,IAAA,EAAM,mCAAA;AAAA,IAC3C,uBAAuB;;;;;;AANF;AAIzB;;;;;;;;;AAE2B;cAkBd,sBAAA,YACA,mBAAA,CAAoB,uBAAA,GAA0B,gBAAA;EAAA;cAI7C,OAAA,EAAS,qBAAA;EAIrB,IAAA,CAAK,OAAA;IAAA,SACM,QAAA;IAAA,SACA,MAAA;IAAA,SACA,MAAA,EAAQ,wBAAA;IAY2B;;;;;;;;;;IAAA,SADnC,YAAA,EAAc,QAAA;IAAA,SACd,mBAAA,EAAqB,aAAA,CAAc,8BAAA;IAvBW;;;;;IAAA,SA6B9C,OAAA;IApBA;;;;IAAA,SAyBA,SAAA,GAAY,eAAA;EAAA,IACnB,gBAAA;EAIJ,cAAA,CACE,OAAA,EAAS,wBAAA,EACT,OAAA,WACC,mCAAA;EAAA,QAaK,OAAA;EAAA,QA0DA,oBAAA;EApFG;;;;;;;;;;;;;;AA8HgB;;;;;;;;;;;;;;;EA9HhB,QA8HH,mBAAA;AAAA"}
package/dist/planner.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as createSqliteMigrationPlanner, t as SqliteMigrationPlanner } from "./planner-Ciq8p_dL.mjs";
1
+ import { n as createSqliteMigrationPlanner, t as SqliteMigrationPlanner } from "./planner-DGhzXuGh.mjs";
2
2
  export { SqliteMigrationPlanner, createSqliteMigrationPlanner };
@@ -1,9 +1,11 @@
1
- import { SqlNamespaceTablesInput, SqlStorage } from "@prisma-next/sql-contract/types";
1
+ import { t as SqliteContractView } from "./sqlite-contract-view-J32K82Gi.mjs";
2
+ import { SqlNamespaceInput, SqlStorage } from "@prisma-next/sql-contract/types";
2
3
  import { Namespace } from "@prisma-next/framework-components/ir";
3
4
  import { SqlContractSerializerBase } from "@prisma-next/family-sql/ir";
4
5
  import { Contract } from "@prisma-next/contract/types";
5
6
  import { RuntimeTargetInstance } from "@prisma-next/framework-components/execution";
6
7
  import { SqlRuntimeTargetDescriptor } from "@prisma-next/sql-runtime";
8
+ import { JsonObject } from "@prisma-next/utils/json";
7
9
 
8
10
  //#region src/core/runtime-target.d.ts
9
11
  interface SqliteRuntimeTargetInstance extends RuntimeTargetInstance<'sql', 'sqlite'> {}
@@ -18,9 +20,9 @@ declare const sqliteRuntimeTargetDescriptor: SqlRuntimeTargetDescriptor<'sqlite'
18
20
  */
19
21
  declare class SqliteContractSerializer extends SqlContractSerializerBase<Contract<SqlStorage>> {
20
22
  constructor();
21
- protected get defaultNamespaceId(): string;
22
- protected hydrateSqlNamespaceEntry(nsId: string, raw: Namespace | Record<string, unknown>): Namespace | SqlNamespaceTablesInput;
23
+ protected hydrateSqlNamespaceEntry(nsId: string, raw: Record<string, unknown>): Namespace | SqlNamespaceInput;
24
+ serializeContract(contract: Contract<SqlStorage>): JsonObject;
23
25
  }
24
26
  //#endregion
25
- export { SqliteContractSerializer, type SqliteRuntimeTargetInstance, sqliteRuntimeTargetDescriptor as default };
27
+ export { SqliteContractSerializer, SqliteContractView, type SqliteRuntimeTargetInstance, sqliteRuntimeTargetDescriptor as default };
26
28
  //# sourceMappingURL=runtime.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/core/runtime-target.ts","../src/core/sqlite-contract-serializer.ts"],"mappings":";;;;;;;;UAIiB,2BAAA,SAAoC,qBAAqB;AAAA,cAEpE,6BAAA,EAA+B,0BAA0B,WAE7D,2BAAA;;;;;;;AAJF;;cCUa,wBAAA,SAAiC,yBAAA,CAA0B,QAAA,CAAS,UAAA;;gBAKxD,kBAAA;EAAA,UAIJ,wBAAA,CACjB,IAAA,UACA,GAAA,EAAK,SAAA,GAAY,MAAA,oBAChB,SAAA,GAAY,uBAAA;AAAA"}
1
+ {"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/core/runtime-target.ts","../src/core/sqlite-contract-serializer.ts"],"mappings":";;;;;;;;;;UAIiB,2BAAA,SAAoC,qBAAqB;AAAA,cAEpE,6BAAA,EAA+B,0BAA0B,WAE7D,2BAAA;;;;;;;;AAJF;cCUa,wBAAA,SAAiC,yBAAA,CAA0B,QAAA,CAAS,UAAA;;YAK5D,wBAAA,CACjB,IAAA,UACA,GAAA,EAAK,MAAA,oBACJ,SAAA,GAAY,iBAAA;EAQN,iBAAA,CAAkB,QAAA,EAAU,QAAA,CAAS,UAAA,IAAc,UAAA;AAAA"}
package/dist/runtime.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { n as sqliteTargetDescriptorMetaRuntime } from "./descriptor-meta-DxmEeTJ-.mjs";
2
- import { t as SqliteContractSerializer } from "./sqlite-contract-serializer--iaDgC8e.mjs";
1
+ import { t as sqliteTargetDescriptorMetaRuntime } from "./descriptor-meta-runtime-BkXK3OjD.mjs";
2
+ import { n as SqliteContractSerializer, t as SqliteContractView } from "./sqlite-contract-view-BEwi0mUC.mjs";
3
3
  //#region src/core/runtime-target.ts
4
4
  const sqliteRuntimeTargetDescriptor = {
5
5
  ...sqliteTargetDescriptorMetaRuntime,
@@ -12,6 +12,6 @@ const sqliteRuntimeTargetDescriptor = {
12
12
  }
13
13
  };
14
14
  //#endregion
15
- export { SqliteContractSerializer, sqliteRuntimeTargetDescriptor as default };
15
+ export { SqliteContractSerializer, SqliteContractView, sqliteRuntimeTargetDescriptor as default };
16
16
 
17
17
  //# sourceMappingURL=runtime.mjs.map
@@ -1,6 +1,6 @@
1
1
  import { t as SqlitePlanTargetDetails } from "./planner-target-details-xR6UfIcz.mjs";
2
- import { SqlMigrationPlanOperation } from "@prisma-next/family-sql/control";
3
2
  import { ReferentialAction } from "@prisma-next/sql-contract/types";
3
+ import { SqlMigrationPlanOperation } from "@prisma-next/family-sql/control";
4
4
 
5
5
  //#region src/core/migrations/operations/shared.d.ts
6
6
  type Op = SqlMigrationPlanOperation<SqlitePlanTargetDetails>;
@@ -66,4 +66,4 @@ interface SqliteIndexSpec {
66
66
  }
67
67
  //#endregion
68
68
  export { SqliteTableSpec as i, SqliteColumnSpec as n, SqliteIndexSpec as r, Op as t };
69
- //# sourceMappingURL=shared-Dhc8mLK1.d.mts.map
69
+ //# sourceMappingURL=shared-C6sM-wel.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared-Dhc8mLK1.d.mts","names":[],"sources":["../src/core/migrations/operations/shared.ts"],"mappings":";;;;;KAUY,EAAA,GAAK,yBAAyB,CAAC,uBAAA;AAA3C;;;;AAAkE;AA0BlE;;;;;;;;;;AAKwC;AA/BxC,UA0BiB,gBAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA;EAAA,SACA,QAAA;EAAA,SACA,6BAAA;AAAA;AAAA,UAGM,oBAAA;EAAA,SACN,OAAO;AAAA;AAAA,UAGD,gBAAA;EAAA,SACN,OAAA;EAAA,SACA,IAAI;AAAA;AAAA,UAGE,oBAAA;EAAA,SACN,OAAA;EAAA,SACA,UAAA;IAAA,SACE,KAAA;IAAA,SACA,OAAA;EAAA;EAAA,SAEF,IAAA;EAAA,SACA,QAAA,GAAW,iBAAA;EAAA,SACX,QAAA,GAAW,iBAAiB;EAAA,SAC5B,UAAA;AAAA;AAAU;AAOrB;;;AAPqB,UAOJ,eAAA;EAAA,SACN,OAAA,WAAkB,gBAAA;EAAA,SAClB,UAAA,GAAa,oBAAA;EAAA,SACb,OAAA,YAAmB,gBAAA;EAAA,SACnB,WAAA,YAAuB,oBAAA;AAAA;;;;;;UAQjB,eAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAO;AAAA"}
1
+ {"version":3,"file":"shared-C6sM-wel.d.mts","names":[],"sources":["../src/core/migrations/operations/shared.ts"],"mappings":";;;;;KAUY,EAAA,GAAK,yBAAyB,CAAC,uBAAA;AAA3C;;;;AAAkE;AA0BlE;;;;;;;;;;AAKwC;AA/BxC,UA0BiB,gBAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA;EAAA,SACA,QAAA;EAAA,SACA,6BAAA;AAAA;AAAA,UAGM,oBAAA;EAAA,SACN,OAAO;AAAA;AAAA,UAGD,gBAAA;EAAA,SACN,OAAA;EAAA,SACA,IAAI;AAAA;AAAA,UAGE,oBAAA;EAAA,SACN,OAAA;EAAA,SACA,UAAA;IAAA,SACE,KAAA;IAAA,SACA,OAAA;EAAA;EAAA,SAEF,IAAA;EAAA,SACA,QAAA,GAAW,iBAAA;EAAA,SACX,QAAA,GAAW,iBAAiB;EAAA,SAC5B,UAAA;AAAA;AAAU;AAOrB;;;AAPqB,UAOJ,eAAA;EAAA,SACN,OAAA,WAAkB,gBAAA;EAAA,SAClB,UAAA,GAAa,oBAAA;EAAA,SACb,OAAA,YAAmB,gBAAA;EAAA,SACnB,WAAA,YAAuB,oBAAA;AAAA;;;;;;UAQjB,eAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAO;AAAA"}
@@ -1,6 +1,7 @@
1
- import { t as sqliteTargetDescriptorMeta } from "./descriptor-meta-DxmEeTJ-.mjs";
2
- import { NamespaceBase, UNBOUND_NAMESPACE_ID, freezeNode, hydrateNamespaceEntities } from "@prisma-next/framework-components/ir";
1
+ import { SqlNamespaceBase } from "@prisma-next/sql-contract/types";
2
+ import { UNBOUND_NAMESPACE_ID, freezeNode, hydrateNamespaceEntities } from "@prisma-next/framework-components/ir";
3
3
  import { blindCast } from "@prisma-next/utils/casts";
4
+ import { buildSqlSingleNamespaceView } from "@prisma-next/sql-contract/contract-view";
4
5
  import { SqlContractSerializerBase } from "@prisma-next/family-sql/ir";
5
6
  import { tableEntityKind } from "@prisma-next/sql-contract/entity-kinds";
6
7
  //#region src/core/sqlite-unbound-database.ts
@@ -10,7 +11,7 @@ const SQLITE_NAMESPACE_KIND = "sqlite-namespace";
10
11
  * `entries.table` and unqualified `qualifyTable()` emission for runtime
11
12
  * SQL rendering.
12
13
  */
13
- var SqliteDatabase = class extends NamespaceBase {
14
+ var SqliteDatabase = class extends SqlNamespaceBase {
14
15
  id;
15
16
  entries;
16
17
  constructor(input) {
@@ -98,15 +99,39 @@ var SqliteContractSerializer = class extends SqlContractSerializerBase {
98
99
  constructor() {
99
100
  super(/* @__PURE__ */ new Map());
100
101
  }
101
- get defaultNamespaceId() {
102
- return sqliteTargetDescriptorMeta.defaultNamespaceId;
103
- }
104
102
  hydrateSqlNamespaceEntry(nsId, raw) {
105
- if (raw instanceof NamespaceBase) return raw;
106
103
  return buildSqliteNamespace(blindCast(super.hydrateSqlNamespaceEntry(nsId, raw)));
107
104
  }
105
+ serializeContract(contract) {
106
+ const { storage, ...rest } = contract;
107
+ const namespacesJson = {};
108
+ for (const [nsId, ns] of Object.entries(storage.namespaces)) namespacesJson[nsId] = {
109
+ id: ns.id,
110
+ entries: this.serializeNamespaceEntries(ns.entries)
111
+ };
112
+ return blindCast({
113
+ ...rest,
114
+ storage: {
115
+ storageHash: String(storage.storageHash),
116
+ namespaces: namespacesJson,
117
+ ...storage.types !== void 0 ? { types: this.serializeJsonObject(storage.types) } : {}
118
+ }
119
+ });
120
+ }
121
+ };
122
+ //#endregion
123
+ //#region src/core/sqlite-contract-view.ts
124
+ const SqliteContractView = {
125
+ /** Wrap an already-deserialized SQLite contract in a view. */
126
+ from(contract) {
127
+ return buildSqlSingleNamespaceView(contract);
128
+ },
129
+ /** Deserialize a SQLite contract JSON envelope and wrap it in a view. */
130
+ fromJson(json) {
131
+ return buildSqlSingleNamespaceView(new SqliteContractSerializer().deserializeContract(json));
132
+ }
108
133
  };
109
134
  //#endregion
110
- export { SqliteUnboundDatabase as n, sqliteCreateNamespace as r, SqliteContractSerializer as t };
135
+ export { sqliteCreateNamespace as i, SqliteContractSerializer as n, SqliteUnboundDatabase as r, SqliteContractView as t };
111
136
 
112
- //# sourceMappingURL=sqlite-contract-serializer--iaDgC8e.mjs.map
137
+ //# sourceMappingURL=sqlite-contract-view-BEwi0mUC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-contract-view-BEwi0mUC.mjs","names":[],"sources":["../src/core/sqlite-unbound-database.ts","../src/core/sqlite-contract-serializer.ts","../src/core/sqlite-contract-view.ts"],"sourcesContent":["import {\n freezeNode,\n hydrateNamespaceEntities,\n UNBOUND_NAMESPACE_ID,\n} from '@prisma-next/framework-components/ir';\nimport { tableEntityKind } from '@prisma-next/sql-contract/entity-kinds';\nimport {\n SqlNamespaceBase,\n type SqlNamespaceEntries,\n type SqlNamespaceInput,\n type StorageTable,\n} from '@prisma-next/sql-contract/types';\nimport { blindCast } from '@prisma-next/utils/casts';\n\nexport type SqliteDatabaseInput = {\n readonly id: string;\n readonly entries: SqlNamespaceEntries;\n};\n\nconst SQLITE_NAMESPACE_KIND = 'sqlite-namespace' as const;\n\n/**\n * SQLite namespace concretion carrying table metadata under\n * `entries.table` and unqualified `qualifyTable()` emission for runtime\n * SQL rendering.\n */\nexport class SqliteDatabase extends SqlNamespaceBase {\n declare readonly kind: string;\n\n readonly id: string;\n readonly entries: SqlNamespaceEntries;\n\n constructor(input: SqliteDatabaseInput) {\n super();\n this.id = input.id;\n\n const dispatched = hydrateNamespaceEntities(\n input.entries,\n new Map([['table', tableEntityKind]]),\n 'carry',\n );\n\n this.entries = Object.freeze(\n blindCast<\n SqlNamespaceEntries,\n \"SQLite's table-only descriptor map hydrates table→StorageTable and carries every other kind raw, so this open-dict result satisfies SqlNamespaceEntries; the descriptor Map erases the per-kind Node type from the return.\"\n >(dispatched),\n );\n Object.defineProperty(this, 'kind', {\n value: SQLITE_NAMESPACE_KIND,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n freezeNode(this);\n }\n\n get table(): Readonly<Record<string, StorageTable>> {\n return this.entries.table ?? Object.freeze({});\n }\n\n qualifier(): string {\n return '';\n }\n\n qualifyTable(tableName: string): string {\n return `\"${tableName}\"`;\n }\n}\n\n/**\n * SQLite target `Namespace` concretion. SQLite has no schema or\n * database-namespacing concept at the SQL level — there is exactly one\n * effective namespace per connection, so the target ships a single\n * singleton bound to the framework's `UNBOUND_NAMESPACE_ID` slot.\n *\n * Qualifier emission elides the prefix entirely: rendered DDL and\n * queries look unqualified (`CREATE TABLE \"users\" (...)`), matching\n * SQLite's native dialect. Call sites stay polymorphic — they ask the\n * namespace for its qualifier and consume the empty/unqualified result\n * the same way Postgres consumes a `\"schema\"` prefix.\n *\n * The SQLite PSL interpreter rejects every explicit `namespace { … }`\n * block with a diagnostic naming SQLite; only the implicit\n * `__unspecified__` AST bucket reaches the SQLite interpreter, which\n * lowers it to this singleton.\n */\nexport class SqliteUnboundDatabase extends SqliteDatabase {\n static readonly instance: SqliteUnboundDatabase = new SqliteUnboundDatabase();\n\n private constructor() {\n super({ id: UNBOUND_NAMESPACE_ID, entries: { table: {} } });\n }\n}\n\nexport function buildSqliteNamespace(\n input: SqlNamespaceInput,\n): SqliteDatabase | SqliteUnboundDatabase {\n if (input.id !== UNBOUND_NAMESPACE_ID) {\n throw new Error(\n `buildSqliteNamespace: SQLite has no schema concept; the only valid namespace id is \"${UNBOUND_NAMESPACE_ID}\" (received \"${input.id}\").`,\n );\n }\n const tableKind = input.entries['table'];\n const tableCount = tableKind !== undefined ? Object.keys(tableKind).length : 0;\n const hasUnknownKinds = Object.keys(input.entries).some((kind) => kind !== 'table');\n if (tableCount === 0 && !hasUnknownKinds) {\n return SqliteUnboundDatabase.instance;\n }\n return new SqliteDatabase({ id: input.id, entries: input.entries });\n}\n\n/**\n * Target-supplied `Namespace` factory the SQLite target plumbs through\n * `defineContract({ createNamespace })`. SQLite has only one\n * effective namespace slot — the framework `UNBOUND_NAMESPACE_ID`\n * sentinel — so the factory always returns the singleton or a fresh\n * `SqliteDatabase` for the unbound slot with tables. The SQL family's\n * defensive validation in `defineContract` already rejects\n * user-declared SQLite namespaces, so this throw is a structural\n * safety net rather than a user-facing surface.\n */\nexport function sqliteCreateNamespace(\n input: SqlNamespaceInput,\n): SqliteDatabase | SqliteUnboundDatabase {\n return buildSqliteNamespace(input);\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport { SqlContractSerializerBase } from '@prisma-next/family-sql/ir';\nimport type { Namespace } from '@prisma-next/framework-components/ir';\nimport type { SqlNamespaceInput, SqlStorage } from '@prisma-next/sql-contract/types';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport type { JsonObject } from '@prisma-next/utils/json';\nimport { buildSqliteNamespace } from './sqlite-unbound-database';\n\n/**\n * SQLite target `ContractSerializer` concretion. Mirrors the Postgres\n * shape: inherits the full SQL-family deserialization pipeline and\n * materialises namespace entries as SQLite database concretions that\n * expose `qualifyTable()` for runtime SQL rendering.\n */\nexport class SqliteContractSerializer extends SqlContractSerializerBase<Contract<SqlStorage>> {\n constructor() {\n super(new Map());\n }\n\n protected override hydrateSqlNamespaceEntry(\n nsId: string,\n raw: Record<string, unknown>,\n ): Namespace | SqlNamespaceInput {\n const hydrated = blindCast<\n SqlNamespaceInput,\n 'raw is always plain JSON, so super.hydrateSqlNamespaceEntry returns SqlNamespaceInput'\n >(super.hydrateSqlNamespaceEntry(nsId, raw));\n return buildSqliteNamespace(hydrated);\n }\n\n override serializeContract(contract: Contract<SqlStorage>): JsonObject {\n const { storage, ...rest } = contract;\n const namespacesJson: Record<string, JsonObject> = {};\n for (const [nsId, ns] of Object.entries(storage.namespaces)) {\n namespacesJson[nsId] = {\n id: ns.id,\n entries: this.serializeNamespaceEntries(ns.entries),\n };\n }\n return blindCast<\n JsonObject,\n 'rest + storage are serialized plain values; spread preserves JSON-clean contract envelope'\n >({\n ...rest,\n storage: {\n storageHash: String(storage.storageHash),\n namespaces: namespacesJson,\n ...(storage.types !== undefined ? { types: this.serializeJsonObject(storage.types) } : {}),\n },\n });\n }\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport {\n buildSqlSingleNamespaceView,\n type SqlSingleNamespaceView,\n} from '@prisma-next/sql-contract/contract-view';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport { SqliteContractSerializer } from './sqlite-contract-serializer';\n\n/**\n * A SQLite contract view: the deserialized contract intersected with by-name\n * accessors. It is substitutable for `Contract` (carries `storage`, `domain`,\n * …) and also exposes the single default namespace unwrapped with the SQL\n * built-in kinds promoted:\n *\n * ```ts\n * const view = SqliteContractView.fromJson<Contract>(contractJson);\n * view.table.users // typed table leaf\n * view.entries.policy.X // pack-contributed kind (singular key)\n * view.storage // the full contract is still present\n * ```\n *\n * SQLite has `sql.enums: false`, so it never emits `valueSet` entries; the\n * `valueSet` slot is therefore an empty map.\n */\nexport type SqliteContractView<TContract extends Contract<SqlStorage> = Contract<SqlStorage>> =\n SqlSingleNamespaceView<TContract>;\n\nexport const SqliteContractView = {\n /** Wrap an already-deserialized SQLite contract in a view. */\n from<TContract extends Contract<SqlStorage>>(contract: TContract): SqliteContractView<TContract> {\n return buildSqlSingleNamespaceView(contract);\n },\n\n /** Deserialize a SQLite contract JSON envelope and wrap it in a view. */\n fromJson<TContract extends Contract<SqlStorage> = Contract<SqlStorage>>(\n json: unknown,\n ): SqliteContractView<TContract> {\n const contract = new SqliteContractSerializer().deserializeContract<TContract>(json);\n return buildSqlSingleNamespaceView(contract);\n },\n};\n"],"mappings":";;;;;;;AAmBA,MAAM,wBAAwB;;;;;;AAO9B,IAAa,iBAAb,cAAoC,iBAAiB;CAGnD;CACA;CAEA,YAAY,OAA4B;EACtC,MAAM;EACN,KAAK,KAAK,MAAM;EAEhB,MAAM,aAAa,yBACjB,MAAM,SACN,IAAI,IAAI,CAAC,CAAC,SAAS,eAAe,CAAC,CAAC,GACpC,OACF;EAEA,KAAK,UAAU,OAAO,OACpB,UAGE,UAAU,CACd;EACA,OAAO,eAAe,MAAM,QAAQ;GAClC,OAAO;GACP,UAAU;GACV,YAAY;GACZ,cAAc;EAChB,CAAC;EACD,WAAW,IAAI;CACjB;CAEA,IAAI,QAAgD;EAClD,OAAO,KAAK,QAAQ,SAAS,OAAO,OAAO,CAAC,CAAC;CAC/C;CAEA,YAAoB;EAClB,OAAO;CACT;CAEA,aAAa,WAA2B;EACtC,OAAO,IAAI,UAAU;CACvB;AACF;;;;;;;;;;;;;;;;;;AAmBA,IAAa,wBAAb,MAAa,8BAA8B,eAAe;CACxD,OAAgB,WAAkC,IAAI,sBAAsB;CAE5E,cAAsB;EACpB,MAAM;GAAE,IAAI;GAAsB,SAAS,EAAE,OAAO,CAAC,EAAE;EAAE,CAAC;CAC5D;AACF;AAEA,SAAgB,qBACd,OACwC;CACxC,IAAI,MAAM,OAAO,sBACf,MAAM,IAAI,MACR,uFAAuF,qBAAqB,eAAe,MAAM,GAAG,IACtI;CAEF,MAAM,YAAY,MAAM,QAAQ;CAChC,MAAM,aAAa,cAAc,KAAA,IAAY,OAAO,KAAK,SAAS,CAAC,CAAC,SAAS;CAC7E,MAAM,kBAAkB,OAAO,KAAK,MAAM,OAAO,CAAC,CAAC,MAAM,SAAS,SAAS,OAAO;CAClF,IAAI,eAAe,KAAK,CAAC,iBACvB,OAAO,sBAAsB;CAE/B,OAAO,IAAI,eAAe;EAAE,IAAI,MAAM;EAAI,SAAS,MAAM;CAAQ,CAAC;AACpE;;;;;;;;;;;AAYA,SAAgB,sBACd,OACwC;CACxC,OAAO,qBAAqB,KAAK;AACnC;;;;;;;;;AChHA,IAAa,2BAAb,cAA8C,0BAAgD;CAC5F,cAAc;EACZ,sBAAM,IAAI,IAAI,CAAC;CACjB;CAEA,yBACE,MACA,KAC+B;EAK/B,OAAO,qBAJU,UAGf,MAAM,yBAAyB,MAAM,GAAG,CACP,CAAC;CACtC;CAEA,kBAA2B,UAA4C;EACrE,MAAM,EAAE,SAAS,GAAG,SAAS;EAC7B,MAAM,iBAA6C,CAAC;EACpD,KAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,QAAQ,UAAU,GACxD,eAAe,QAAQ;GACrB,IAAI,GAAG;GACP,SAAS,KAAK,0BAA0B,GAAG,OAAO;EACpD;EAEF,OAAO,UAGL;GACA,GAAG;GACH,SAAS;IACP,aAAa,OAAO,QAAQ,WAAW;IACvC,YAAY;IACZ,GAAI,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,KAAK,oBAAoB,QAAQ,KAAK,EAAE,IAAI,CAAC;GAC1F;EACF,CAAC;CACH;AACF;;;ACxBA,MAAa,qBAAqB;;CAEhC,KAA6C,UAAoD;EAC/F,OAAO,4BAA4B,QAAQ;CAC7C;;CAGA,SACE,MAC+B;EAE/B,OAAO,4BADU,IAAI,yBAAyB,CAAC,CAAC,oBAA+B,IACrC,CAAC;CAC7C;AACF"}