@prisma-next/target-postgres 0.1.0-pr.48.2 → 0.1.0-pr.49.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,36 +4,74 @@ Postgres target pack for Prisma Next.
4
4
 
5
5
  ## Package Classification
6
6
 
7
- - **Domain**: extensions
7
+ - **Domain**: targets
8
8
  - **Layer**: targets
9
9
  - **Plane**: multi-plane (migration, runtime)
10
10
 
11
11
  ## Purpose
12
12
 
13
- Provides the Postgres target descriptor (`TargetDescriptor`) for CLI config. The target descriptor includes the target manifest with capabilities and type information.
13
+ Provides the Postgres target descriptor (`SqlControlTargetDescriptor`) for CLI config. The target descriptor includes the target manifest with capabilities and type information, as well as factories for creating migration planners and runners.
14
14
 
15
15
  ## Responsibilities
16
16
 
17
- - **Target Descriptor Export**: Exports the Postgres `TargetDescriptor` for use in CLI configuration files
17
+ - **Target Descriptor Export**: Exports the Postgres `SqlControlTargetDescriptor` for use in CLI configuration files
18
18
  - **Manifest Loading**: Loads the Postgres target manifest from `packs/manifest.json` with capabilities and type information
19
- - **Multi-Plane Support**: Provides both migration-plane (CLI) and runtime-plane entry points for the Postgres target
19
+ - **Multi-Plane Support**: Provides both migration-plane (control) and runtime-plane entry points for the Postgres target
20
+ - **Planner Factory**: Implements `createPlanner()` to create Postgres-specific migration planners
21
+ - **Runner Factory**: Implements `createRunner()` to create Postgres-specific migration runners
20
22
 
21
23
  This package spans multiple planes:
22
- - **Migration plane** (`src/exports/cli.ts`): CLI entry point that exports `TargetDescriptor` for config files
24
+ - **Migration plane** (`src/exports/control.ts`): Control plane entry point that exports `SqlControlTargetDescriptor` for config files
23
25
  - **Runtime plane** (`src/exports/runtime.ts`): Runtime entry point for target-specific runtime code (future)
24
26
 
25
27
  ## Usage
26
28
 
27
- ### Migration Plane (CLI)
29
+ ### Control Plane (CLI)
28
30
 
29
31
  ```typescript
30
32
  import postgres from '@prisma-next/target-postgres/control';
33
+ import sqlFamilyDescriptor from '@prisma-next/family-sql/control';
34
+ import postgresAdapter from '@prisma-next/adapter-postgres/control';
35
+ import postgresDriver from '@prisma-next/driver-postgres/control';
31
36
 
32
- // postgres is a TargetDescriptor with:
37
+ // postgres is a SqlControlTargetDescriptor with:
33
38
  // - kind: 'target'
39
+ // - familyId: 'sql'
40
+ // - targetId: 'postgres'
34
41
  // - id: 'postgres'
35
- // - family: 'sql'
36
42
  // - manifest: ExtensionPackManifest
43
+ // - createPlanner(): creates a Postgres migration planner
44
+ // - createRunner(): creates a Postgres migration runner
45
+
46
+ // Create family instance with target, adapter, and driver
47
+ const family = sqlFamilyDescriptor.create({
48
+ target: postgres,
49
+ adapter: postgresAdapter,
50
+ driver: postgresDriver,
51
+ extensions: [],
52
+ });
53
+
54
+ // Create planner and runner from target descriptor
55
+ const planner = postgres.createPlanner(family);
56
+ const runner = postgres.createRunner(family);
57
+
58
+ // Plan and execute migrations
59
+ const planResult = planner.plan({ contract, schema, policy });
60
+ if (planResult.kind === 'success') {
61
+ const executeResult = await runner.execute({
62
+ plan: planResult.plan,
63
+ driver,
64
+ destinationContract: contract,
65
+ policy,
66
+ });
67
+ if (!executeResult.ok) {
68
+ // Handle structured failure (e.g., EXECUTION_FAILED, PRECHECK_FAILED)
69
+ console.error(executeResult.failure.code, executeResult.failure.summary);
70
+ }
71
+ } else {
72
+ // Handle planner failure (e.g., unsupportedExtension, unsupportedOperation)
73
+ console.error(planResult.conflicts);
74
+ }
37
75
  ```
38
76
 
39
77
  ### Runtime Plane
@@ -45,11 +83,29 @@ import { ... } from '@prisma-next/target-postgres/runtime';
45
83
 
46
84
  ## Architecture
47
85
 
48
- This package provides both CLI and runtime entry points for the Postgres target. The CLI entry point loads the target manifest from `packs/manifest.json` and exports it as a `TargetDescriptor`. The runtime entry point will provide target-specific runtime functionality in the future.
86
+ This package provides both control and runtime entry points for the Postgres target. The control entry point loads the target manifest from `packs/manifest.json` and exports it as a `SqlControlTargetDescriptor`. The runtime entry point will provide target-specific runtime functionality in the future.
87
+
88
+ ## Error Handling
89
+
90
+ Both the planner and runner return structured results instead of throwing:
91
+
92
+ **Planner** returns `PlannerResult` with either:
93
+ - `kind: 'success'` with a `MigrationPlan`
94
+ - `kind: 'failure'` with a list of `PlannerConflict` objects (e.g., `unsupportedExtension`, `unsupportedOperation`)
95
+
96
+ **Runner** returns `MigrationRunnerResult` (`Result<MigrationRunnerSuccessValue, MigrationRunnerFailure>`) with either:
97
+ - `ok: true` with operation counts
98
+ - `ok: false` with a `MigrationRunnerFailure` containing error code, summary, and metadata
99
+
100
+ Runner error codes include: `EXECUTION_FAILED`, `PRECHECK_FAILED`, `POSTCHECK_FAILED`, `SCHEMA_VERIFY_FAILED`, `POLICY_VIOLATION`, `MARKER_ORIGIN_MISMATCH`, `DESTINATION_CONTRACT_MISMATCH`.
101
+
102
+ See `@prisma-next/family-sql/control` README for full error code documentation.
49
103
 
50
104
  ## Dependencies
51
105
 
52
- - **`@prisma-next/cli`**: CLI descriptor types (`TargetDescriptor`, `ExtensionPackManifest`)
106
+ - **`@prisma-next/family-sql`**: SQL family types (`SqlControlTargetDescriptor`, `SqlControlFamilyInstance`)
107
+ - **`@prisma-next/core-control-plane`**: Control plane types (`ControlTargetInstance`)
108
+ - **`@prisma-next/contract`**: Manifest types (`ExtensionPackManifest`)
53
109
  - **`arktype`**: Runtime validation
54
110
 
55
111
  **Dependents:**
@@ -57,6 +113,18 @@ This package provides both CLI and runtime entry points for the Postgres target.
57
113
 
58
114
  ## Exports
59
115
 
60
- - `./cli`: Migration entry point for `TargetDescriptor`
116
+ - `./control`: Control plane entry point for `SqlControlTargetDescriptor`
61
117
  - `./runtime`: Runtime entry point for target-specific runtime code (future)
62
118
 
119
+ ## Tests
120
+
121
+ This package ships a mix of fast planner unit tests and slower runner integration tests that require a dev Postgres instance (via `@prisma/dev`).
122
+
123
+ - **Default (`pnpm --filter @prisma-next/target-postgres test`)**: runs all tests including integration tests
124
+ - **Test files**:
125
+ - `test/migrations/planner.case1.test.ts`: Planner unit tests
126
+ - `test/migrations/runner.*.integration.test.ts`: Runner integration tests (basic, errors, idempotency, policy)
127
+
128
+ ```bash
129
+ pnpm --filter @prisma-next/target-postgres test
130
+ ```
@@ -1,8 +1,16 @@
1
- import { ControlTargetDescriptor, ControlTargetInstance } from '@prisma-next/core-control-plane/types';
1
+ import { SqlControlTargetDescriptor } from '@prisma-next/family-sql/control';
2
+
3
+ type OperationClass = 'extension' | 'table' | 'unique' | 'index' | 'foreignKey';
4
+ interface PostgresPlanTargetDetails {
5
+ readonly schema: string;
6
+ readonly objectType: OperationClass;
7
+ readonly name: string;
8
+ readonly table?: string;
9
+ }
2
10
 
3
11
  /**
4
12
  * Postgres target descriptor for CLI config.
5
13
  */
6
- declare const postgresTargetDescriptor: ControlTargetDescriptor<'sql', 'postgres', ControlTargetInstance<'sql', 'postgres'>>;
14
+ declare const postgresTargetDescriptor: SqlControlTargetDescriptor<'postgres', PostgresPlanTargetDetails>;
7
15
 
8
16
  export { postgresTargetDescriptor as default };
@@ -3,6 +3,898 @@ import { readFileSync } from "fs";
3
3
  import { dirname, join } from "path";
4
4
  import { fileURLToPath } from "url";
5
5
  import { type } from "arktype";
6
+
7
+ // src/core/migrations/planner.ts
8
+ import {
9
+ createMigrationPlan,
10
+ plannerFailure,
11
+ plannerSuccess
12
+ } from "@prisma-next/family-sql/control";
13
+ var DEFAULT_PLANNER_CONFIG = {
14
+ defaultSchema: "public"
15
+ };
16
+ var PG_EXTENSION_SQL = {
17
+ pgvector: "CREATE EXTENSION IF NOT EXISTS vector"
18
+ };
19
+ var ADAPTER_LEVEL_EXTENSIONS = /* @__PURE__ */ new Set(["pg", "postgres"]);
20
+ function createPostgresMigrationPlanner(config = {}) {
21
+ return new PostgresMigrationPlanner({
22
+ ...DEFAULT_PLANNER_CONFIG,
23
+ ...config
24
+ });
25
+ }
26
+ var PostgresMigrationPlanner = class {
27
+ constructor(config) {
28
+ this.config = config;
29
+ }
30
+ plan(options) {
31
+ const schemaName = options.schemaName ?? this.config.defaultSchema;
32
+ const policyResult = this.ensureAdditivePolicy(options.policy);
33
+ if (policyResult) {
34
+ return policyResult;
35
+ }
36
+ const existingTables = Object.keys(options.schema.tables);
37
+ if (existingTables.length > 0) {
38
+ const tableList = existingTables.sort().join(", ");
39
+ return plannerFailure([
40
+ {
41
+ kind: "unsupportedOperation",
42
+ summary: `The Postgres migration planner currently supports only empty databases. Found ${existingTables.length} existing table(s): ${tableList}`,
43
+ why: "Remove existing tables or use a future planner mode that handles subsets/supersets."
44
+ }
45
+ ]);
46
+ }
47
+ const extensionResult = this.validateExtensions(options.contract);
48
+ if (extensionResult) {
49
+ return extensionResult;
50
+ }
51
+ const operations = [];
52
+ operations.push(
53
+ ...this.buildExtensionOperations(options.contract, schemaName),
54
+ ...this.buildTableOperations(options.contract.storage.tables, schemaName),
55
+ ...this.buildUniqueOperations(options.contract.storage.tables, schemaName),
56
+ ...this.buildIndexOperations(options.contract.storage.tables, schemaName),
57
+ ...this.buildForeignKeyOperations(options.contract.storage.tables, schemaName)
58
+ );
59
+ const plan = createMigrationPlan({
60
+ targetId: "postgres",
61
+ origin: null,
62
+ destination: {
63
+ coreHash: options.contract.coreHash,
64
+ ...options.contract.profileHash ? { profileHash: options.contract.profileHash } : {}
65
+ },
66
+ operations
67
+ });
68
+ return plannerSuccess(plan);
69
+ }
70
+ validateExtensions(contract) {
71
+ const extensions = contract.extensions ?? {};
72
+ const extensionNames = Object.keys(extensions);
73
+ const databaseExtensions = extensionNames.filter(
74
+ (extensionName) => !ADAPTER_LEVEL_EXTENSIONS.has(extensionName)
75
+ );
76
+ const unsupportedExtensions = databaseExtensions.filter(
77
+ (extensionName) => !PG_EXTENSION_SQL[extensionName]
78
+ );
79
+ if (unsupportedExtensions.length > 0) {
80
+ const supportedExtensions = Object.keys(PG_EXTENSION_SQL).join(", ");
81
+ const unsupportedList = unsupportedExtensions.join(", ");
82
+ return plannerFailure([
83
+ {
84
+ kind: "unsupportedExtension",
85
+ summary: `Unsupported PostgreSQL extensions in contract: ${unsupportedList}`,
86
+ why: `The Postgres migration planner currently only supports: ${supportedExtensions}. Extensions are defined in contract.extensions.`,
87
+ location: { extension: unsupportedList }
88
+ }
89
+ ]);
90
+ }
91
+ return null;
92
+ }
93
+ ensureAdditivePolicy(policy) {
94
+ if (!policy.allowedOperationClasses.includes("additive")) {
95
+ return plannerFailure([
96
+ {
97
+ kind: "unsupportedOperation",
98
+ summary: "Init planner requires additive operations be allowed",
99
+ why: 'The init planner only emits additive operations. Update the policy to include "additive".'
100
+ }
101
+ ]);
102
+ }
103
+ return null;
104
+ }
105
+ buildExtensionOperations(contract, schema) {
106
+ const extensions = contract.extensions ?? {};
107
+ const extensionNames = Object.keys(extensions);
108
+ const operations = [];
109
+ for (const extensionName of extensionNames) {
110
+ if (ADAPTER_LEVEL_EXTENSIONS.has(extensionName)) {
111
+ continue;
112
+ }
113
+ const sql = PG_EXTENSION_SQL[extensionName];
114
+ if (!sql) {
115
+ throw new Error(`Extension SQL not found for ${extensionName}`);
116
+ }
117
+ const details = this.buildTargetDetails("extension", extensionName, schema);
118
+ operations.push({
119
+ id: `extension.${extensionName}`,
120
+ label: `Enable extension "${extensionName}"`,
121
+ summary: `Ensures the ${extensionName} extension is available`,
122
+ operationClass: "additive",
123
+ target: { id: "postgres", details },
124
+ precheck: [
125
+ {
126
+ description: `verify extension "${extensionName}" is not already enabled`,
127
+ sql: `SELECT NOT EXISTS (SELECT 1 FROM pg_extension WHERE extname = '${escapeLiteral(
128
+ this.extensionDatabaseName(extensionName)
129
+ )}')`
130
+ }
131
+ ],
132
+ execute: [
133
+ {
134
+ description: `create extension "${extensionName}"`,
135
+ sql
136
+ }
137
+ ],
138
+ postcheck: [
139
+ {
140
+ description: `confirm extension "${extensionName}" is enabled`,
141
+ sql: `SELECT EXISTS (SELECT 1 FROM pg_extension WHERE extname = '${escapeLiteral(
142
+ this.extensionDatabaseName(extensionName)
143
+ )}')`
144
+ }
145
+ ]
146
+ });
147
+ }
148
+ return operations;
149
+ }
150
+ extensionDatabaseName(extensionName) {
151
+ if (extensionName === "pgvector") {
152
+ return "vector";
153
+ }
154
+ return extensionName;
155
+ }
156
+ buildTableOperations(tables, schema) {
157
+ const operations = [];
158
+ for (const [tableName, table] of sortedEntries(tables)) {
159
+ const qualified = qualifyTableName(schema, tableName);
160
+ operations.push({
161
+ id: `table.${tableName}`,
162
+ label: `Create table ${tableName}`,
163
+ summary: `Creates table ${tableName} with required columns`,
164
+ operationClass: "additive",
165
+ target: {
166
+ id: "postgres",
167
+ details: this.buildTargetDetails("table", tableName, schema)
168
+ },
169
+ precheck: [
170
+ {
171
+ description: `ensure table "${tableName}" does not exist`,
172
+ sql: `SELECT to_regclass(${toRegclassLiteral(schema, tableName)}) IS NULL`
173
+ }
174
+ ],
175
+ execute: [
176
+ {
177
+ description: `create table "${tableName}"`,
178
+ sql: buildCreateTableSql(qualified, table)
179
+ }
180
+ ],
181
+ postcheck: [
182
+ {
183
+ description: `verify table "${tableName}" exists`,
184
+ sql: `SELECT to_regclass(${toRegclassLiteral(schema, tableName)}) IS NOT NULL`
185
+ }
186
+ ]
187
+ });
188
+ }
189
+ return operations;
190
+ }
191
+ buildUniqueOperations(tables, schema) {
192
+ const operations = [];
193
+ for (const [tableName, table] of sortedEntries(tables)) {
194
+ for (const unique of table.uniques) {
195
+ const constraintName = unique.name ?? `${tableName}_${unique.columns.join("_")}_key`;
196
+ operations.push({
197
+ id: `unique.${tableName}.${constraintName}`,
198
+ label: `Add unique constraint ${constraintName} on ${tableName}`,
199
+ summary: `Adds unique constraint ${constraintName} on ${tableName}`,
200
+ operationClass: "additive",
201
+ target: {
202
+ id: "postgres",
203
+ details: this.buildTargetDetails("unique", constraintName, schema, tableName)
204
+ },
205
+ precheck: [
206
+ {
207
+ description: `ensure unique constraint "${constraintName}" is missing`,
208
+ sql: constraintExistsCheck({ constraintName, schema, exists: false })
209
+ }
210
+ ],
211
+ execute: [
212
+ {
213
+ description: `add unique constraint "${constraintName}"`,
214
+ sql: `ALTER TABLE ${qualifyTableName(schema, tableName)}
215
+ ADD CONSTRAINT ${quoteIdentifier(constraintName)}
216
+ UNIQUE (${unique.columns.map(quoteIdentifier).join(", ")})`
217
+ }
218
+ ],
219
+ postcheck: [
220
+ {
221
+ description: `verify unique constraint "${constraintName}" exists`,
222
+ sql: constraintExistsCheck({ constraintName, schema })
223
+ }
224
+ ]
225
+ });
226
+ }
227
+ }
228
+ return operations;
229
+ }
230
+ buildIndexOperations(tables, schema) {
231
+ const operations = [];
232
+ for (const [tableName, table] of sortedEntries(tables)) {
233
+ for (const index of table.indexes) {
234
+ const indexName = index.name ?? `${tableName}_${index.columns.join("_")}_idx`;
235
+ operations.push({
236
+ id: `index.${tableName}.${indexName}`,
237
+ label: `Create index ${indexName} on ${tableName}`,
238
+ summary: `Creates index ${indexName} on ${tableName}`,
239
+ operationClass: "additive",
240
+ target: {
241
+ id: "postgres",
242
+ details: this.buildTargetDetails("index", indexName, schema, tableName)
243
+ },
244
+ precheck: [
245
+ {
246
+ description: `ensure index "${indexName}" is missing`,
247
+ sql: `SELECT to_regclass(${toRegclassLiteral(schema, indexName)}) IS NULL`
248
+ }
249
+ ],
250
+ execute: [
251
+ {
252
+ description: `create index "${indexName}"`,
253
+ sql: `CREATE INDEX ${quoteIdentifier(indexName)} ON ${qualifyTableName(
254
+ schema,
255
+ tableName
256
+ )} (${index.columns.map(quoteIdentifier).join(", ")})`
257
+ }
258
+ ],
259
+ postcheck: [
260
+ {
261
+ description: `verify index "${indexName}" exists`,
262
+ sql: `SELECT to_regclass(${toRegclassLiteral(schema, indexName)}) IS NOT NULL`
263
+ }
264
+ ]
265
+ });
266
+ }
267
+ }
268
+ return operations;
269
+ }
270
+ buildForeignKeyOperations(tables, schema) {
271
+ const operations = [];
272
+ for (const [tableName, table] of sortedEntries(tables)) {
273
+ for (const foreignKey of table.foreignKeys) {
274
+ const fkName = foreignKey.name ?? `${tableName}_${foreignKey.columns.join("_")}_fkey`;
275
+ operations.push({
276
+ id: `foreignKey.${tableName}.${fkName}`,
277
+ label: `Add foreign key ${fkName} on ${tableName}`,
278
+ summary: `Adds foreign key ${fkName} referencing ${foreignKey.references.table}`,
279
+ operationClass: "additive",
280
+ target: {
281
+ id: "postgres",
282
+ details: this.buildTargetDetails("foreignKey", fkName, schema, tableName)
283
+ },
284
+ precheck: [
285
+ {
286
+ description: `ensure foreign key "${fkName}" is missing`,
287
+ sql: constraintExistsCheck({ constraintName: fkName, schema, exists: false })
288
+ }
289
+ ],
290
+ execute: [
291
+ {
292
+ description: `add foreign key "${fkName}"`,
293
+ sql: `ALTER TABLE ${qualifyTableName(schema, tableName)}
294
+ ADD CONSTRAINT ${quoteIdentifier(fkName)}
295
+ FOREIGN KEY (${foreignKey.columns.map(quoteIdentifier).join(", ")})
296
+ REFERENCES ${qualifyTableName(schema, foreignKey.references.table)} (${foreignKey.references.columns.map(quoteIdentifier).join(", ")})`
297
+ }
298
+ ],
299
+ postcheck: [
300
+ {
301
+ description: `verify foreign key "${fkName}" exists`,
302
+ sql: constraintExistsCheck({ constraintName: fkName, schema })
303
+ }
304
+ ]
305
+ });
306
+ }
307
+ }
308
+ return operations;
309
+ }
310
+ buildTargetDetails(objectType, name, schema, table) {
311
+ return {
312
+ schema,
313
+ objectType,
314
+ name,
315
+ ...table ? { table } : {}
316
+ };
317
+ }
318
+ };
319
+ function buildCreateTableSql(qualifiedTableName, table) {
320
+ const columnDefinitions = Object.entries(table.columns).map(
321
+ ([columnName, column]) => {
322
+ const parts = [
323
+ quoteIdentifier(columnName),
324
+ column.nativeType,
325
+ column.nullable ? "" : "NOT NULL"
326
+ ].filter(Boolean);
327
+ return parts.join(" ");
328
+ }
329
+ );
330
+ const constraintDefinitions = [];
331
+ if (table.primaryKey) {
332
+ constraintDefinitions.push(
333
+ `PRIMARY KEY (${table.primaryKey.columns.map(quoteIdentifier).join(", ")})`
334
+ );
335
+ }
336
+ const allDefinitions = [...columnDefinitions, ...constraintDefinitions];
337
+ return `CREATE TABLE ${qualifiedTableName} (
338
+ ${allDefinitions.join(",\n ")}
339
+ )`;
340
+ }
341
+ function qualifyTableName(schema, table) {
342
+ return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
343
+ }
344
+ function toRegclassLiteral(schema, name) {
345
+ const regclass = `${quoteIdentifier(schema)}.${quoteIdentifier(name)}`;
346
+ return `'${escapeLiteral(regclass)}'`;
347
+ }
348
+ function quoteIdentifier(identifier) {
349
+ return `"${identifier.replace(/"/g, '""')}"`;
350
+ }
351
+ function escapeLiteral(value) {
352
+ return value.replace(/'/g, "''");
353
+ }
354
+ function sortedEntries(record) {
355
+ return Object.entries(record).sort(([a], [b]) => a.localeCompare(b));
356
+ }
357
+ function constraintExistsCheck({
358
+ constraintName,
359
+ schema,
360
+ exists = true
361
+ }) {
362
+ const existsClause = exists ? "EXISTS" : "NOT EXISTS";
363
+ return `SELECT ${existsClause} (
364
+ SELECT 1 FROM pg_constraint c
365
+ JOIN pg_namespace n ON c.connamespace = n.oid
366
+ WHERE c.conname = '${escapeLiteral(constraintName)}'
367
+ AND n.nspname = '${escapeLiteral(schema)}'
368
+ )`;
369
+ }
370
+
371
+ // src/core/migrations/runner.ts
372
+ import { runnerFailure, runnerSuccess } from "@prisma-next/family-sql/control";
373
+ import { verifySqlSchema } from "@prisma-next/family-sql/schema-verify";
374
+ import { readMarker } from "@prisma-next/family-sql/verify";
375
+ import { ok, okVoid } from "@prisma-next/utils/result";
376
+
377
+ // src/core/migrations/statement-builders.ts
378
+ var ensurePrismaContractSchemaStatement = {
379
+ sql: "create schema if not exists prisma_contract",
380
+ params: []
381
+ };
382
+ var ensureMarkerTableStatement = {
383
+ sql: `create table if not exists prisma_contract.marker (
384
+ id smallint primary key default 1,
385
+ core_hash text not null,
386
+ profile_hash text not null,
387
+ contract_json jsonb,
388
+ canonical_version int,
389
+ updated_at timestamptz not null default now(),
390
+ app_tag text,
391
+ meta jsonb not null default '{}'
392
+ )`,
393
+ params: []
394
+ };
395
+ var ensureLedgerTableStatement = {
396
+ sql: `create table if not exists prisma_contract.ledger (
397
+ id bigserial primary key,
398
+ created_at timestamptz not null default now(),
399
+ origin_core_hash text,
400
+ origin_profile_hash text,
401
+ destination_core_hash text not null,
402
+ destination_profile_hash text,
403
+ contract_json_before jsonb,
404
+ contract_json_after jsonb,
405
+ operations jsonb not null
406
+ )`,
407
+ params: []
408
+ };
409
+ function buildWriteMarkerStatements(input) {
410
+ const params = [
411
+ 1,
412
+ input.coreHash,
413
+ input.profileHash,
414
+ jsonParam(input.contractJson),
415
+ input.canonicalVersion ?? null,
416
+ input.appTag ?? null,
417
+ jsonParam(input.meta ?? {})
418
+ ];
419
+ return {
420
+ insert: {
421
+ sql: `insert into prisma_contract.marker (
422
+ id,
423
+ core_hash,
424
+ profile_hash,
425
+ contract_json,
426
+ canonical_version,
427
+ updated_at,
428
+ app_tag,
429
+ meta
430
+ ) values (
431
+ $1,
432
+ $2,
433
+ $3,
434
+ $4::jsonb,
435
+ $5,
436
+ now(),
437
+ $6,
438
+ $7::jsonb
439
+ )`,
440
+ params
441
+ },
442
+ update: {
443
+ sql: `update prisma_contract.marker set
444
+ core_hash = $2,
445
+ profile_hash = $3,
446
+ contract_json = $4::jsonb,
447
+ canonical_version = $5,
448
+ updated_at = now(),
449
+ app_tag = $6,
450
+ meta = $7::jsonb
451
+ where id = $1`,
452
+ params
453
+ }
454
+ };
455
+ }
456
+ function buildLedgerInsertStatement(input) {
457
+ return {
458
+ sql: `insert into prisma_contract.ledger (
459
+ origin_core_hash,
460
+ origin_profile_hash,
461
+ destination_core_hash,
462
+ destination_profile_hash,
463
+ contract_json_before,
464
+ contract_json_after,
465
+ operations
466
+ ) values (
467
+ $1,
468
+ $2,
469
+ $3,
470
+ $4,
471
+ $5::jsonb,
472
+ $6::jsonb,
473
+ $7::jsonb
474
+ )`,
475
+ params: [
476
+ input.originCoreHash ?? null,
477
+ input.originProfileHash ?? null,
478
+ input.destinationCoreHash,
479
+ input.destinationProfileHash ?? null,
480
+ jsonParam(input.contractJsonBefore),
481
+ jsonParam(input.contractJsonAfter),
482
+ jsonParam(input.operations)
483
+ ]
484
+ };
485
+ }
486
+ function jsonParam(value) {
487
+ return JSON.stringify(value ?? null);
488
+ }
489
+
490
+ // src/core/migrations/runner.ts
491
+ var DEFAULT_CONFIG = {
492
+ defaultSchema: "public"
493
+ };
494
+ var LOCK_DOMAIN = "prisma_next.contract.marker";
495
+ function cloneAndFreezeRecord(value) {
496
+ const cloned = {};
497
+ for (const [key, val] of Object.entries(value)) {
498
+ if (val === null || val === void 0) {
499
+ cloned[key] = val;
500
+ } else if (Array.isArray(val)) {
501
+ cloned[key] = Object.freeze([...val]);
502
+ } else if (typeof val === "object") {
503
+ cloned[key] = cloneAndFreezeRecord(val);
504
+ } else {
505
+ cloned[key] = val;
506
+ }
507
+ }
508
+ return Object.freeze(cloned);
509
+ }
510
+ function createPostgresMigrationRunner(family, config = {}) {
511
+ return new PostgresMigrationRunner(family, { ...DEFAULT_CONFIG, ...config });
512
+ }
513
+ var PostgresMigrationRunner = class {
514
+ constructor(family, config) {
515
+ this.family = family;
516
+ this.config = config;
517
+ }
518
+ async execute(options) {
519
+ const schema = options.schemaName ?? this.config.defaultSchema;
520
+ const driver = options.driver;
521
+ const lockKey = `${LOCK_DOMAIN}:${schema}`;
522
+ const destinationCheck = this.ensurePlanMatchesDestinationContract(
523
+ options.plan.destination,
524
+ options.destinationContract
525
+ );
526
+ if (!destinationCheck.ok) {
527
+ return destinationCheck;
528
+ }
529
+ const policyCheck = this.enforcePolicyCompatibility(options.policy, options.plan.operations);
530
+ if (!policyCheck.ok) {
531
+ return policyCheck;
532
+ }
533
+ await this.beginTransaction(driver);
534
+ let committed = false;
535
+ try {
536
+ await this.acquireLock(driver, lockKey);
537
+ await this.ensureControlTables(driver);
538
+ const existingMarker = await readMarker(driver);
539
+ const markerCheck = this.ensureMarkerCompatibility(existingMarker, options.plan);
540
+ if (!markerCheck.ok) {
541
+ return markerCheck;
542
+ }
543
+ const markerAtDestination = this.markerMatchesDestination(existingMarker, options.plan);
544
+ let applyValue;
545
+ if (markerAtDestination) {
546
+ applyValue = { operationsExecuted: 0, executedOperations: [] };
547
+ } else {
548
+ const applyResult = await this.applyPlan(driver, options);
549
+ if (!applyResult.ok) {
550
+ return applyResult;
551
+ }
552
+ applyValue = applyResult.value;
553
+ }
554
+ const schemaIR = await this.family.introspect({
555
+ driver,
556
+ contractIR: options.destinationContract
557
+ });
558
+ const schemaVerifyResult = verifySqlSchema({
559
+ contract: options.destinationContract,
560
+ schema: schemaIR,
561
+ strict: options.strictVerification ?? true,
562
+ context: options.context ?? {},
563
+ typeMetadataRegistry: this.family.typeMetadataRegistry
564
+ });
565
+ if (!schemaVerifyResult.ok) {
566
+ return runnerFailure("SCHEMA_VERIFY_FAILED", schemaVerifyResult.summary, {
567
+ why: "The resulting database schema does not satisfy the destination contract.",
568
+ meta: {
569
+ issues: schemaVerifyResult.schema.issues
570
+ }
571
+ });
572
+ }
573
+ await this.upsertMarker(driver, options, existingMarker);
574
+ await this.recordLedgerEntry(driver, options, existingMarker, applyValue.executedOperations);
575
+ await this.commitTransaction(driver);
576
+ committed = true;
577
+ return runnerSuccess({
578
+ operationsPlanned: options.plan.operations.length,
579
+ operationsExecuted: applyValue.operationsExecuted
580
+ });
581
+ } finally {
582
+ if (!committed) {
583
+ await this.rollbackTransaction(driver);
584
+ }
585
+ }
586
+ }
587
+ async applyPlan(driver, options) {
588
+ let operationsExecuted = 0;
589
+ const executedOperations = [];
590
+ for (const operation of options.plan.operations) {
591
+ options.callbacks?.onOperationStart?.(operation);
592
+ try {
593
+ const postcheckAlreadySatisfied = await this.expectationsAreSatisfied(
594
+ driver,
595
+ operation.postcheck
596
+ );
597
+ if (postcheckAlreadySatisfied) {
598
+ executedOperations.push(this.createPostcheckPreSatisfiedSkipRecord(operation));
599
+ continue;
600
+ }
601
+ const precheckResult = await this.runExpectationSteps(
602
+ driver,
603
+ operation.precheck,
604
+ operation,
605
+ "precheck"
606
+ );
607
+ if (!precheckResult.ok) {
608
+ return precheckResult;
609
+ }
610
+ const executeResult = await this.runExecuteSteps(driver, operation.execute, operation);
611
+ if (!executeResult.ok) {
612
+ return executeResult;
613
+ }
614
+ const postcheckResult = await this.runExpectationSteps(
615
+ driver,
616
+ operation.postcheck,
617
+ operation,
618
+ "postcheck"
619
+ );
620
+ if (!postcheckResult.ok) {
621
+ return postcheckResult;
622
+ }
623
+ executedOperations.push(operation);
624
+ operationsExecuted += 1;
625
+ } finally {
626
+ options.callbacks?.onOperationComplete?.(operation);
627
+ }
628
+ }
629
+ return ok({ operationsExecuted, executedOperations });
630
+ }
631
+ async ensureControlTables(driver) {
632
+ await this.executeStatement(driver, ensurePrismaContractSchemaStatement);
633
+ await this.executeStatement(driver, ensureMarkerTableStatement);
634
+ await this.executeStatement(driver, ensureLedgerTableStatement);
635
+ }
636
+ async runExpectationSteps(driver, steps, operation, phase) {
637
+ for (const step of steps) {
638
+ const result = await driver.query(step.sql);
639
+ if (!this.stepResultIsTrue(result.rows)) {
640
+ const code = phase === "precheck" ? "PRECHECK_FAILED" : "POSTCHECK_FAILED";
641
+ return runnerFailure(
642
+ code,
643
+ `Operation ${operation.id} failed during ${phase}: ${step.description}`,
644
+ {
645
+ meta: {
646
+ operationId: operation.id,
647
+ phase,
648
+ stepDescription: step.description
649
+ }
650
+ }
651
+ );
652
+ }
653
+ }
654
+ return okVoid();
655
+ }
656
+ async runExecuteSteps(driver, steps, operation) {
657
+ for (const step of steps) {
658
+ try {
659
+ await driver.query(step.sql);
660
+ } catch (error) {
661
+ return runnerFailure(
662
+ "EXECUTION_FAILED",
663
+ `Operation ${operation.id} failed during execution: ${step.description}`,
664
+ {
665
+ why: error instanceof Error ? error.message : String(error),
666
+ meta: {
667
+ operationId: operation.id,
668
+ stepDescription: step.description,
669
+ sql: step.sql
670
+ }
671
+ }
672
+ );
673
+ }
674
+ }
675
+ return okVoid();
676
+ }
677
+ stepResultIsTrue(rows) {
678
+ if (!rows || rows.length === 0) {
679
+ return false;
680
+ }
681
+ const firstRow = rows[0];
682
+ const firstValue = firstRow ? Object.values(firstRow)[0] : void 0;
683
+ if (typeof firstValue === "boolean") {
684
+ return firstValue;
685
+ }
686
+ if (typeof firstValue === "number") {
687
+ return firstValue !== 0;
688
+ }
689
+ if (typeof firstValue === "string") {
690
+ const lower = firstValue.toLowerCase();
691
+ if (lower === "t" || lower === "true" || lower === "1") {
692
+ return true;
693
+ }
694
+ if (lower === "f" || lower === "false" || lower === "0") {
695
+ return false;
696
+ }
697
+ return firstValue.length > 0;
698
+ }
699
+ return Boolean(firstValue);
700
+ }
701
+ async expectationsAreSatisfied(driver, steps) {
702
+ if (steps.length === 0) {
703
+ return false;
704
+ }
705
+ for (const step of steps) {
706
+ const result = await driver.query(step.sql);
707
+ if (!this.stepResultIsTrue(result.rows)) {
708
+ return false;
709
+ }
710
+ }
711
+ return true;
712
+ }
713
+ createPostcheckPreSatisfiedSkipRecord(operation) {
714
+ const clonedMeta = operation.meta ? cloneAndFreezeRecord(operation.meta) : void 0;
715
+ const runnerMeta = Object.freeze({
716
+ skipped: true,
717
+ reason: "postcheck_pre_satisfied"
718
+ });
719
+ const mergedMeta = Object.freeze({
720
+ ...clonedMeta ?? {},
721
+ runner: runnerMeta
722
+ });
723
+ const frozenPostcheck = Object.freeze([...operation.postcheck]);
724
+ return Object.freeze({
725
+ id: operation.id,
726
+ label: operation.label,
727
+ ...operation.summary ? { summary: operation.summary } : {},
728
+ operationClass: operation.operationClass,
729
+ target: operation.target,
730
+ // Already frozen from plan creation
731
+ precheck: Object.freeze([]),
732
+ execute: Object.freeze([]),
733
+ postcheck: frozenPostcheck,
734
+ ...operation.meta || mergedMeta ? { meta: mergedMeta } : {}
735
+ });
736
+ }
737
+ markerMatchesDestination(marker, plan) {
738
+ if (!marker) {
739
+ return false;
740
+ }
741
+ if (marker.coreHash !== plan.destination.coreHash) {
742
+ return false;
743
+ }
744
+ if (plan.destination.profileHash && marker.profileHash !== plan.destination.profileHash) {
745
+ return false;
746
+ }
747
+ return true;
748
+ }
749
+ enforcePolicyCompatibility(policy, operations) {
750
+ const allowedClasses = new Set(policy.allowedOperationClasses);
751
+ for (const operation of operations) {
752
+ if (!allowedClasses.has(operation.operationClass)) {
753
+ return runnerFailure(
754
+ "POLICY_VIOLATION",
755
+ `Operation ${operation.id} has class "${operation.operationClass}" which is not allowed by policy.`,
756
+ {
757
+ why: `Policy only allows: ${policy.allowedOperationClasses.join(", ")}.`,
758
+ meta: {
759
+ operationId: operation.id,
760
+ operationClass: operation.operationClass,
761
+ allowedClasses: policy.allowedOperationClasses
762
+ }
763
+ }
764
+ );
765
+ }
766
+ }
767
+ return okVoid();
768
+ }
769
+ ensureMarkerCompatibility(marker, plan) {
770
+ const origin = plan.origin ?? null;
771
+ if (!origin) {
772
+ if (!marker) {
773
+ return okVoid();
774
+ }
775
+ if (this.markerMatchesDestination(marker, plan)) {
776
+ return okVoid();
777
+ }
778
+ return runnerFailure(
779
+ "MARKER_ORIGIN_MISMATCH",
780
+ `Existing contract marker (${marker.coreHash}) does not match plan origin (no marker expected).`,
781
+ {
782
+ meta: {
783
+ markerCoreHash: marker.coreHash,
784
+ expectedOrigin: null
785
+ }
786
+ }
787
+ );
788
+ }
789
+ if (!marker) {
790
+ return runnerFailure(
791
+ "MARKER_ORIGIN_MISMATCH",
792
+ `Missing contract marker: expected origin core hash ${origin.coreHash}.`,
793
+ {
794
+ meta: {
795
+ expectedOriginCoreHash: origin.coreHash
796
+ }
797
+ }
798
+ );
799
+ }
800
+ if (marker.coreHash !== origin.coreHash) {
801
+ return runnerFailure(
802
+ "MARKER_ORIGIN_MISMATCH",
803
+ `Existing contract marker (${marker.coreHash}) does not match plan origin (${origin.coreHash}).`,
804
+ {
805
+ meta: {
806
+ markerCoreHash: marker.coreHash,
807
+ expectedOriginCoreHash: origin.coreHash
808
+ }
809
+ }
810
+ );
811
+ }
812
+ if (origin.profileHash && marker.profileHash !== origin.profileHash) {
813
+ return runnerFailure(
814
+ "MARKER_ORIGIN_MISMATCH",
815
+ `Existing contract marker profile hash (${marker.profileHash}) does not match plan origin profile hash (${origin.profileHash}).`,
816
+ {
817
+ meta: {
818
+ markerProfileHash: marker.profileHash,
819
+ expectedOriginProfileHash: origin.profileHash
820
+ }
821
+ }
822
+ );
823
+ }
824
+ return okVoid();
825
+ }
826
+ ensurePlanMatchesDestinationContract(destination, contract) {
827
+ if (destination.coreHash !== contract.coreHash) {
828
+ return runnerFailure(
829
+ "DESTINATION_CONTRACT_MISMATCH",
830
+ `Plan destination core hash (${destination.coreHash}) does not match provided contract core hash (${contract.coreHash}).`,
831
+ {
832
+ meta: {
833
+ planCoreHash: destination.coreHash,
834
+ contractCoreHash: contract.coreHash
835
+ }
836
+ }
837
+ );
838
+ }
839
+ if (destination.profileHash && contract.profileHash && destination.profileHash !== contract.profileHash) {
840
+ return runnerFailure(
841
+ "DESTINATION_CONTRACT_MISMATCH",
842
+ `Plan destination profile hash (${destination.profileHash}) does not match provided contract profile hash (${contract.profileHash}).`,
843
+ {
844
+ meta: {
845
+ planProfileHash: destination.profileHash,
846
+ contractProfileHash: contract.profileHash
847
+ }
848
+ }
849
+ );
850
+ }
851
+ return okVoid();
852
+ }
853
+ async upsertMarker(driver, options, existingMarker) {
854
+ const writeStatements = buildWriteMarkerStatements({
855
+ coreHash: options.plan.destination.coreHash,
856
+ profileHash: options.plan.destination.profileHash ?? options.destinationContract.profileHash ?? options.plan.destination.coreHash,
857
+ contractJson: options.destinationContract,
858
+ canonicalVersion: null,
859
+ meta: {}
860
+ });
861
+ const statement = existingMarker ? writeStatements.update : writeStatements.insert;
862
+ await this.executeStatement(driver, statement);
863
+ }
864
+ async recordLedgerEntry(driver, options, existingMarker, executedOperations) {
865
+ const ledgerStatement = buildLedgerInsertStatement({
866
+ originCoreHash: existingMarker?.coreHash ?? null,
867
+ originProfileHash: existingMarker?.profileHash ?? null,
868
+ destinationCoreHash: options.plan.destination.coreHash,
869
+ destinationProfileHash: options.plan.destination.profileHash ?? options.destinationContract.profileHash ?? options.plan.destination.coreHash,
870
+ contractJsonBefore: existingMarker?.contractJson ?? null,
871
+ contractJsonAfter: options.destinationContract,
872
+ operations: executedOperations
873
+ });
874
+ await this.executeStatement(driver, ledgerStatement);
875
+ }
876
+ async acquireLock(driver, key) {
877
+ await driver.query("select pg_advisory_xact_lock(hashtext($1))", [key]);
878
+ }
879
+ async beginTransaction(driver) {
880
+ await driver.query("BEGIN");
881
+ }
882
+ async commitTransaction(driver) {
883
+ await driver.query("COMMIT");
884
+ }
885
+ async rollbackTransaction(driver) {
886
+ await driver.query("ROLLBACK");
887
+ }
888
+ async executeStatement(driver, statement) {
889
+ if (statement.params.length > 0) {
890
+ await driver.query(statement.sql, statement.params);
891
+ return;
892
+ }
893
+ await driver.query(statement.sql);
894
+ }
895
+ };
896
+
897
+ // src/exports/control.ts
6
898
  var __filename = fileURLToPath(import.meta.url);
7
899
  var __dirname = dirname(__filename);
8
900
  var TypesImportSpecSchema = type({
@@ -46,6 +938,12 @@ var postgresTargetDescriptor = {
46
938
  familyId: "sql",
47
939
  targetId: "postgres"
48
940
  };
941
+ },
942
+ createPlanner(_family) {
943
+ return createPostgresMigrationPlanner();
944
+ },
945
+ createRunner(family) {
946
+ return createPostgresMigrationRunner(family);
49
947
  }
50
948
  };
51
949
  var control_default = postgresTargetDescriptor;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/exports/control.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { ExtensionPackManifest } from '@prisma-next/contract/pack-manifest-types';\nimport type {\n ControlTargetDescriptor,\n ControlTargetInstance,\n} from '@prisma-next/core-control-plane/types';\nimport { type } from 'arktype';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst TypesImportSpecSchema = type({\n package: 'string',\n named: 'string',\n alias: 'string',\n});\n\nconst ExtensionPackManifestSchema = type({\n id: 'string',\n version: 'string',\n 'targets?': type({ '[string]': type({ 'minVersion?': 'string' }) }),\n 'capabilities?': 'Record<string, unknown>',\n 'types?': type({\n 'codecTypes?': type({\n import: TypesImportSpecSchema,\n }),\n 'operationTypes?': type({\n import: TypesImportSpecSchema,\n }),\n }),\n 'operations?': 'unknown[]',\n});\n\n/**\n * Loads the target manifest from packs/manifest.json.\n */\nfunction loadTargetManifest(): ExtensionPackManifest {\n const manifestPath = join(__dirname, '../../packs/manifest.json');\n const manifestJson = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n\n const result = ExtensionPackManifestSchema(manifestJson);\n if (result instanceof type.errors) {\n const messages = result.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Invalid target manifest structure at ${manifestPath}: ${messages}`);\n }\n\n return result as ExtensionPackManifest;\n}\n\n/**\n * Postgres target descriptor for CLI config.\n */\nconst postgresTargetDescriptor: ControlTargetDescriptor<\n 'sql',\n 'postgres',\n ControlTargetInstance<'sql', 'postgres'>\n> = {\n kind: 'target',\n familyId: 'sql',\n targetId: 'postgres',\n id: 'postgres',\n manifest: loadTargetManifest(),\n create(): ControlTargetInstance<'sql', 'postgres'> {\n return {\n familyId: 'sql',\n targetId: 'postgres',\n };\n },\n};\n\nexport default postgresTargetDescriptor;\n"],"mappings":";AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAM9B,SAAS,YAAY;AAErB,IAAM,aAAa,cAAc,YAAY,GAAG;AAChD,IAAM,YAAY,QAAQ,UAAU;AAEpC,IAAM,wBAAwB,KAAK;AAAA,EACjC,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AACT,CAAC;AAED,IAAM,8BAA8B,KAAK;AAAA,EACvC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,YAAY,KAAK,EAAE,YAAY,KAAK,EAAE,eAAe,SAAS,CAAC,EAAE,CAAC;AAAA,EAClE,iBAAiB;AAAA,EACjB,UAAU,KAAK;AAAA,IACb,eAAe,KAAK;AAAA,MAClB,QAAQ;AAAA,IACV,CAAC;AAAA,IACD,mBAAmB,KAAK;AAAA,MACtB,QAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AAAA,EACD,eAAe;AACjB,CAAC;AAKD,SAAS,qBAA4C;AACnD,QAAM,eAAe,KAAK,WAAW,2BAA2B;AAChE,QAAM,eAAe,KAAK,MAAM,aAAa,cAAc,OAAO,CAAC;AAEnE,QAAM,SAAS,4BAA4B,YAAY;AACvD,MAAI,kBAAkB,KAAK,QAAQ;AACjC,UAAM,WAAW,OAAO,IAAI,CAAC,MAA2B,EAAE,OAAO,EAAE,KAAK,IAAI;AAC5E,UAAM,IAAI,MAAM,wCAAwC,YAAY,KAAK,QAAQ,EAAE;AAAA,EACrF;AAEA,SAAO;AACT;AAKA,IAAM,2BAIF;AAAA,EACF,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,IAAI;AAAA,EACJ,UAAU,mBAAmB;AAAA,EAC7B,SAAmD;AACjD,WAAO;AAAA,MACL,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAO,kBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../src/exports/control.ts","../../src/core/migrations/planner.ts","../../src/core/migrations/runner.ts","../../src/core/migrations/statement-builders.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { ExtensionPackManifest } from '@prisma-next/contract/pack-manifest-types';\nimport type { ControlTargetInstance } from '@prisma-next/core-control-plane/types';\nimport type {\n SqlControlFamilyInstance,\n SqlControlTargetDescriptor,\n} from '@prisma-next/family-sql/control';\nimport { type } from 'arktype';\nimport type { PostgresPlanTargetDetails } from '../core/migrations/planner';\nimport { createPostgresMigrationPlanner } from '../core/migrations/planner';\nimport { createPostgresMigrationRunner } from '../core/migrations/runner';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst TypesImportSpecSchema = type({\n package: 'string',\n named: 'string',\n alias: 'string',\n});\n\nconst ExtensionPackManifestSchema = type({\n id: 'string',\n version: 'string',\n 'targets?': type({ '[string]': type({ 'minVersion?': 'string' }) }),\n 'capabilities?': 'Record<string, unknown>',\n 'types?': type({\n 'codecTypes?': type({\n import: TypesImportSpecSchema,\n }),\n 'operationTypes?': type({\n import: TypesImportSpecSchema,\n }),\n }),\n 'operations?': 'unknown[]',\n});\n\n/**\n * Loads the target manifest from packs/manifest.json.\n */\nfunction loadTargetManifest(): ExtensionPackManifest {\n const manifestPath = join(__dirname, '../../packs/manifest.json');\n const manifestJson = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n\n const result = ExtensionPackManifestSchema(manifestJson);\n if (result instanceof type.errors) {\n const messages = result.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Invalid target manifest structure at ${manifestPath}: ${messages}`);\n }\n\n return result as ExtensionPackManifest;\n}\n\n/**\n * Postgres target descriptor for CLI config.\n */\nconst postgresTargetDescriptor: SqlControlTargetDescriptor<'postgres', PostgresPlanTargetDetails> =\n {\n kind: 'target',\n familyId: 'sql',\n targetId: 'postgres',\n id: 'postgres',\n manifest: loadTargetManifest(),\n create(): ControlTargetInstance<'sql', 'postgres'> {\n return {\n familyId: 'sql',\n targetId: 'postgres',\n };\n },\n createPlanner(_family: SqlControlFamilyInstance) {\n return createPostgresMigrationPlanner();\n },\n createRunner(family) {\n return createPostgresMigrationRunner(family);\n },\n };\n\nexport default postgresTargetDescriptor;\n","import type {\n MigrationOperationPolicy,\n MigrationPlanner,\n MigrationPlannerPlanOptions,\n MigrationPlanOperation,\n} from '@prisma-next/family-sql/control';\nimport {\n createMigrationPlan,\n plannerFailure,\n plannerSuccess,\n} from '@prisma-next/family-sql/control';\nimport type {\n SqlContract,\n SqlStorage,\n StorageColumn,\n StorageTable,\n} from '@prisma-next/sql-contract/types';\n\ntype OperationClass = 'extension' | 'table' | 'unique' | 'index' | 'foreignKey';\n\nexport interface PostgresPlanTargetDetails {\n readonly schema: string;\n readonly objectType: OperationClass;\n readonly name: string;\n readonly table?: string;\n}\n\ninterface PlannerConfig {\n readonly defaultSchema: string;\n}\n\nconst DEFAULT_PLANNER_CONFIG: PlannerConfig = {\n defaultSchema: 'public',\n};\n\nconst PG_EXTENSION_SQL: Record<string, string> = {\n pgvector: 'CREATE EXTENSION IF NOT EXISTS vector',\n};\n\n/**\n * Adapter-level extensions that are NOT PostgreSQL database extensions.\n * These are metadata namespaces used by adapters for codec IDs (e.g., 'pg/int4@1').\n * The planner should skip these when validating extensions.\n */\nconst ADAPTER_LEVEL_EXTENSIONS = new Set(['pg', 'postgres']);\n\nexport function createPostgresMigrationPlanner(\n config: Partial<PlannerConfig> = {},\n): MigrationPlanner<PostgresPlanTargetDetails> {\n return new PostgresMigrationPlanner({\n ...DEFAULT_PLANNER_CONFIG,\n ...config,\n });\n}\n\nclass PostgresMigrationPlanner implements MigrationPlanner<PostgresPlanTargetDetails> {\n constructor(private readonly config: PlannerConfig) {}\n\n plan(options: MigrationPlannerPlanOptions) {\n const schemaName = options.schemaName ?? this.config.defaultSchema;\n const policyResult = this.ensureAdditivePolicy(options.policy);\n if (policyResult) {\n return policyResult;\n }\n\n const existingTables = Object.keys(options.schema.tables);\n if (existingTables.length > 0) {\n const tableList = existingTables.sort().join(', ');\n return plannerFailure([\n {\n kind: 'unsupportedOperation',\n summary: `The Postgres migration planner currently supports only empty databases. Found ${existingTables.length} existing table(s): ${tableList}`,\n why: 'Remove existing tables or use a future planner mode that handles subsets/supersets.',\n },\n ]);\n }\n\n const extensionResult = this.validateExtensions(options.contract);\n if (extensionResult) {\n return extensionResult;\n }\n\n const operations: MigrationPlanOperation<PostgresPlanTargetDetails>[] = [];\n\n operations.push(\n ...this.buildExtensionOperations(options.contract, schemaName),\n ...this.buildTableOperations(options.contract.storage.tables, schemaName),\n ...this.buildUniqueOperations(options.contract.storage.tables, schemaName),\n ...this.buildIndexOperations(options.contract.storage.tables, schemaName),\n ...this.buildForeignKeyOperations(options.contract.storage.tables, schemaName),\n );\n\n const plan = createMigrationPlan<PostgresPlanTargetDetails>({\n targetId: 'postgres',\n origin: null,\n destination: {\n coreHash: options.contract.coreHash,\n ...(options.contract.profileHash ? { profileHash: options.contract.profileHash } : {}),\n },\n operations,\n });\n\n return plannerSuccess(plan);\n }\n\n private validateExtensions(contract: SqlContract<SqlStorage>) {\n const extensions = contract.extensions ?? {};\n const extensionNames = Object.keys(extensions);\n // Filter out adapter-level extensions (like 'pg', 'postgres') which are metadata namespaces\n // used by adapters for codec IDs, not PostgreSQL database extensions\n const databaseExtensions = extensionNames.filter(\n (extensionName) => !ADAPTER_LEVEL_EXTENSIONS.has(extensionName),\n );\n const unsupportedExtensions = databaseExtensions.filter(\n (extensionName) => !PG_EXTENSION_SQL[extensionName],\n );\n if (unsupportedExtensions.length > 0) {\n const supportedExtensions = Object.keys(PG_EXTENSION_SQL).join(', ');\n const unsupportedList = unsupportedExtensions.join(', ');\n return plannerFailure([\n {\n kind: 'unsupportedExtension' as const,\n summary: `Unsupported PostgreSQL extensions in contract: ${unsupportedList}`,\n why: `The Postgres migration planner currently only supports: ${supportedExtensions}. Extensions are defined in contract.extensions.`,\n location: { extension: unsupportedList },\n },\n ]);\n }\n return null;\n }\n\n private ensureAdditivePolicy(policy: MigrationOperationPolicy) {\n if (!policy.allowedOperationClasses.includes('additive')) {\n return plannerFailure([\n {\n kind: 'unsupportedOperation',\n summary: 'Init planner requires additive operations be allowed',\n why: 'The init planner only emits additive operations. Update the policy to include \"additive\".',\n },\n ]);\n }\n return null;\n }\n\n private buildExtensionOperations(\n contract: SqlContract<SqlStorage>,\n schema: string,\n ): readonly MigrationPlanOperation<PostgresPlanTargetDetails>[] {\n const extensions = contract.extensions ?? {};\n const extensionNames = Object.keys(extensions);\n const operations: MigrationPlanOperation<PostgresPlanTargetDetails>[] = [];\n\n // Extensions are validated in validateExtensions() before this method is called\n for (const extensionName of extensionNames) {\n // Skip adapter-level extensions (metadata namespaces, not database extensions)\n if (ADAPTER_LEVEL_EXTENSIONS.has(extensionName)) {\n continue;\n }\n const sql = PG_EXTENSION_SQL[extensionName];\n if (!sql) {\n // This should never happen since we validate extensions in validateExtensions(), but TypeScript requires this check\n throw new Error(`Extension SQL not found for ${extensionName}`);\n }\n const details = this.buildTargetDetails('extension', extensionName, schema);\n operations.push({\n id: `extension.${extensionName}`,\n label: `Enable extension \"${extensionName}\"`,\n summary: `Ensures the ${extensionName} extension is available`,\n operationClass: 'additive',\n target: { id: 'postgres', details },\n precheck: [\n {\n description: `verify extension \"${extensionName}\" is not already enabled`,\n sql: `SELECT NOT EXISTS (SELECT 1 FROM pg_extension WHERE extname = '${escapeLiteral(\n this.extensionDatabaseName(extensionName),\n )}')`,\n },\n ],\n execute: [\n {\n description: `create extension \"${extensionName}\"`,\n sql,\n },\n ],\n postcheck: [\n {\n description: `confirm extension \"${extensionName}\" is enabled`,\n sql: `SELECT EXISTS (SELECT 1 FROM pg_extension WHERE extname = '${escapeLiteral(\n this.extensionDatabaseName(extensionName),\n )}')`,\n },\n ],\n });\n }\n\n return operations;\n }\n\n private extensionDatabaseName(extensionName: string): string {\n if (extensionName === 'pgvector') {\n return 'vector';\n }\n return extensionName;\n }\n\n private buildTableOperations(\n tables: SqlContract<SqlStorage>['storage']['tables'],\n schema: string,\n ): readonly MigrationPlanOperation<PostgresPlanTargetDetails>[] {\n const operations: MigrationPlanOperation<PostgresPlanTargetDetails>[] = [];\n for (const [tableName, table] of sortedEntries(tables)) {\n const qualified = qualifyTableName(schema, tableName);\n operations.push({\n id: `table.${tableName}`,\n label: `Create table ${tableName}`,\n summary: `Creates table ${tableName} with required columns`,\n operationClass: 'additive',\n target: {\n id: 'postgres',\n details: this.buildTargetDetails('table', tableName, schema),\n },\n precheck: [\n {\n description: `ensure table \"${tableName}\" does not exist`,\n sql: `SELECT to_regclass(${toRegclassLiteral(schema, tableName)}) IS NULL`,\n },\n ],\n execute: [\n {\n description: `create table \"${tableName}\"`,\n sql: buildCreateTableSql(qualified, table),\n },\n ],\n postcheck: [\n {\n description: `verify table \"${tableName}\" exists`,\n sql: `SELECT to_regclass(${toRegclassLiteral(schema, tableName)}) IS NOT NULL`,\n },\n ],\n });\n }\n return operations;\n }\n\n private buildUniqueOperations(\n tables: SqlContract<SqlStorage>['storage']['tables'],\n schema: string,\n ): readonly MigrationPlanOperation<PostgresPlanTargetDetails>[] {\n const operations: MigrationPlanOperation<PostgresPlanTargetDetails>[] = [];\n for (const [tableName, table] of sortedEntries(tables)) {\n for (const unique of table.uniques) {\n const constraintName = unique.name ?? `${tableName}_${unique.columns.join('_')}_key`;\n operations.push({\n id: `unique.${tableName}.${constraintName}`,\n label: `Add unique constraint ${constraintName} on ${tableName}`,\n summary: `Adds unique constraint ${constraintName} on ${tableName}`,\n operationClass: 'additive',\n target: {\n id: 'postgres',\n details: this.buildTargetDetails('unique', constraintName, schema, tableName),\n },\n precheck: [\n {\n description: `ensure unique constraint \"${constraintName}\" is missing`,\n sql: constraintExistsCheck({ constraintName, schema, exists: false }),\n },\n ],\n execute: [\n {\n description: `add unique constraint \"${constraintName}\"`,\n sql: `ALTER TABLE ${qualifyTableName(schema, tableName)}\nADD CONSTRAINT ${quoteIdentifier(constraintName)}\nUNIQUE (${unique.columns.map(quoteIdentifier).join(', ')})`,\n },\n ],\n postcheck: [\n {\n description: `verify unique constraint \"${constraintName}\" exists`,\n sql: constraintExistsCheck({ constraintName, schema }),\n },\n ],\n });\n }\n }\n return operations;\n }\n\n private buildIndexOperations(\n tables: SqlContract<SqlStorage>['storage']['tables'],\n schema: string,\n ): readonly MigrationPlanOperation<PostgresPlanTargetDetails>[] {\n const operations: MigrationPlanOperation<PostgresPlanTargetDetails>[] = [];\n for (const [tableName, table] of sortedEntries(tables)) {\n for (const index of table.indexes) {\n const indexName = index.name ?? `${tableName}_${index.columns.join('_')}_idx`;\n operations.push({\n id: `index.${tableName}.${indexName}`,\n label: `Create index ${indexName} on ${tableName}`,\n summary: `Creates index ${indexName} on ${tableName}`,\n operationClass: 'additive',\n target: {\n id: 'postgres',\n details: this.buildTargetDetails('index', indexName, schema, tableName),\n },\n precheck: [\n {\n description: `ensure index \"${indexName}\" is missing`,\n sql: `SELECT to_regclass(${toRegclassLiteral(schema, indexName)}) IS NULL`,\n },\n ],\n execute: [\n {\n description: `create index \"${indexName}\"`,\n sql: `CREATE INDEX ${quoteIdentifier(indexName)} ON ${qualifyTableName(\n schema,\n tableName,\n )} (${index.columns.map(quoteIdentifier).join(', ')})`,\n },\n ],\n postcheck: [\n {\n description: `verify index \"${indexName}\" exists`,\n sql: `SELECT to_regclass(${toRegclassLiteral(schema, indexName)}) IS NOT NULL`,\n },\n ],\n });\n }\n }\n return operations;\n }\n\n private buildForeignKeyOperations(\n tables: SqlContract<SqlStorage>['storage']['tables'],\n schema: string,\n ): readonly MigrationPlanOperation<PostgresPlanTargetDetails>[] {\n const operations: MigrationPlanOperation<PostgresPlanTargetDetails>[] = [];\n for (const [tableName, table] of sortedEntries(tables)) {\n for (const foreignKey of table.foreignKeys) {\n const fkName = foreignKey.name ?? `${tableName}_${foreignKey.columns.join('_')}_fkey`;\n operations.push({\n id: `foreignKey.${tableName}.${fkName}`,\n label: `Add foreign key ${fkName} on ${tableName}`,\n summary: `Adds foreign key ${fkName} referencing ${foreignKey.references.table}`,\n operationClass: 'additive',\n target: {\n id: 'postgres',\n details: this.buildTargetDetails('foreignKey', fkName, schema, tableName),\n },\n precheck: [\n {\n description: `ensure foreign key \"${fkName}\" is missing`,\n sql: constraintExistsCheck({ constraintName: fkName, schema, exists: false }),\n },\n ],\n execute: [\n {\n description: `add foreign key \"${fkName}\"`,\n sql: `ALTER TABLE ${qualifyTableName(schema, tableName)}\nADD CONSTRAINT ${quoteIdentifier(fkName)}\nFOREIGN KEY (${foreignKey.columns.map(quoteIdentifier).join(', ')})\nREFERENCES ${qualifyTableName(schema, foreignKey.references.table)} (${foreignKey.references.columns\n .map(quoteIdentifier)\n .join(', ')})`,\n },\n ],\n postcheck: [\n {\n description: `verify foreign key \"${fkName}\" exists`,\n sql: constraintExistsCheck({ constraintName: fkName, schema }),\n },\n ],\n });\n }\n }\n return operations;\n }\n\n private buildTargetDetails(\n objectType: OperationClass,\n name: string,\n schema: string,\n table?: string,\n ): PostgresPlanTargetDetails {\n return {\n schema,\n objectType,\n name,\n ...(table ? { table } : {}),\n };\n }\n}\n\nfunction buildCreateTableSql(qualifiedTableName: string, table: StorageTable): string {\n const columnDefinitions = Object.entries(table.columns).map(\n ([columnName, column]: [string, StorageColumn]) => {\n const parts = [\n quoteIdentifier(columnName),\n column.nativeType,\n column.nullable ? '' : 'NOT NULL',\n ].filter(Boolean);\n return parts.join(' ');\n },\n );\n\n const constraintDefinitions: string[] = [];\n if (table.primaryKey) {\n constraintDefinitions.push(\n `PRIMARY KEY (${table.primaryKey.columns.map(quoteIdentifier).join(', ')})`,\n );\n }\n\n const allDefinitions = [...columnDefinitions, ...constraintDefinitions];\n return `CREATE TABLE ${qualifiedTableName} (\\n ${allDefinitions.join(',\\n ')}\\n)`;\n}\n\nfunction qualifyTableName(schema: string, table: string): string {\n return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;\n}\n\nfunction toRegclassLiteral(schema: string, name: string): string {\n const regclass = `${quoteIdentifier(schema)}.${quoteIdentifier(name)}`;\n return `'${escapeLiteral(regclass)}'`;\n}\n\nfunction quoteIdentifier(identifier: string): string {\n return `\"${identifier.replace(/\"/g, '\"\"')}\"`;\n}\n\nfunction escapeLiteral(value: string): string {\n return value.replace(/'/g, \"''\");\n}\n\nfunction sortedEntries<V>(record: Readonly<Record<string, V>>): Array<[string, V]> {\n return Object.entries(record).sort(([a], [b]) => a.localeCompare(b)) as Array<[string, V]>;\n}\n\nfunction constraintExistsCheck({\n constraintName,\n schema,\n exists = true,\n}: {\n constraintName: string;\n schema: string;\n exists?: boolean;\n}): string {\n const existsClause = exists ? 'EXISTS' : 'NOT EXISTS';\n return `SELECT ${existsClause} (\n SELECT 1 FROM pg_constraint c\n JOIN pg_namespace n ON c.connamespace = n.oid\n WHERE c.conname = '${escapeLiteral(constraintName)}'\n AND n.nspname = '${escapeLiteral(schema)}'\n)`;\n}\n","import type { ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type {\n MigrationOperationPolicy,\n MigrationPlanContractInfo,\n MigrationPlanOperation,\n MigrationPlanOperationStep,\n MigrationRunner,\n MigrationRunnerExecuteOptions,\n MigrationRunnerFailure,\n MigrationRunnerResult,\n SqlControlFamilyInstance,\n} from '@prisma-next/family-sql/control';\nimport { runnerFailure, runnerSuccess } from '@prisma-next/family-sql/control';\nimport { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';\nimport { readMarker } from '@prisma-next/family-sql/verify';\nimport type { Result } from '@prisma-next/utils/result';\nimport { ok, okVoid } from '@prisma-next/utils/result';\nimport type { PostgresPlanTargetDetails } from './planner';\nimport {\n buildLedgerInsertStatement,\n buildWriteMarkerStatements,\n ensureLedgerTableStatement,\n ensureMarkerTableStatement,\n ensurePrismaContractSchemaStatement,\n type SqlStatement,\n} from './statement-builders';\n\ninterface RunnerConfig {\n readonly defaultSchema: string;\n}\n\ninterface ApplyPlanSuccessValue {\n readonly operationsExecuted: number;\n readonly executedOperations: readonly MigrationPlanOperation<PostgresPlanTargetDetails>[];\n}\n\nconst DEFAULT_CONFIG: RunnerConfig = {\n defaultSchema: 'public',\n};\n\nconst LOCK_DOMAIN = 'prisma_next.contract.marker';\n\n/**\n * Deep clones and freezes a record object to prevent mutation.\n * Recursively clones nested objects and arrays to ensure complete isolation.\n */\nfunction cloneAndFreezeRecord<T extends Record<string, unknown>>(value: T): T {\n const cloned: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (val === null || val === undefined) {\n cloned[key] = val;\n } else if (Array.isArray(val)) {\n // Clone array (shallow clone of array elements)\n cloned[key] = Object.freeze([...val]);\n } else if (typeof val === 'object') {\n // Recursively clone nested objects\n cloned[key] = cloneAndFreezeRecord(val as Record<string, unknown>);\n } else {\n // Primitives are copied as-is\n cloned[key] = val;\n }\n }\n return Object.freeze(cloned) as T;\n}\n\nexport function createPostgresMigrationRunner(\n family: SqlControlFamilyInstance,\n config: Partial<RunnerConfig> = {},\n): MigrationRunner<PostgresPlanTargetDetails> {\n return new PostgresMigrationRunner(family, { ...DEFAULT_CONFIG, ...config });\n}\n\nclass PostgresMigrationRunner implements MigrationRunner<PostgresPlanTargetDetails> {\n constructor(\n private readonly family: SqlControlFamilyInstance,\n private readonly config: RunnerConfig,\n ) {}\n\n async execute(\n options: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,\n ): Promise<MigrationRunnerResult> {\n const schema = options.schemaName ?? this.config.defaultSchema;\n const driver = options.driver;\n const lockKey = `${LOCK_DOMAIN}:${schema}`;\n\n // Static checks - fail fast before transaction\n const destinationCheck = this.ensurePlanMatchesDestinationContract(\n options.plan.destination,\n options.destinationContract,\n );\n if (!destinationCheck.ok) {\n return destinationCheck;\n }\n\n const policyCheck = this.enforcePolicyCompatibility(options.policy, options.plan.operations);\n if (!policyCheck.ok) {\n return policyCheck;\n }\n\n // Begin transaction for DB operations\n await this.beginTransaction(driver);\n let committed = false;\n try {\n await this.acquireLock(driver, lockKey);\n await this.ensureControlTables(driver);\n const existingMarker = await readMarker(driver);\n\n // Validate plan origin matches existing marker (needs marker from DB)\n const markerCheck = this.ensureMarkerCompatibility(existingMarker, options.plan);\n if (!markerCheck.ok) {\n return markerCheck;\n }\n\n // Apply plan operations or skip if marker already at destination\n const markerAtDestination = this.markerMatchesDestination(existingMarker, options.plan);\n let applyValue: ApplyPlanSuccessValue;\n\n if (markerAtDestination) {\n applyValue = { operationsExecuted: 0, executedOperations: [] };\n } else {\n const applyResult = await this.applyPlan(driver, options);\n if (!applyResult.ok) {\n return applyResult;\n }\n applyValue = applyResult.value;\n }\n\n // Verify resulting schema matches contract\n // Step 1: Introspect live schema (DB I/O, family-owned)\n const schemaIR = await this.family.introspect({\n driver,\n contractIR: options.destinationContract,\n });\n\n // Step 2: Pure verification (no DB I/O)\n const schemaVerifyResult = verifySqlSchema({\n contract: options.destinationContract,\n schema: schemaIR,\n strict: options.strictVerification ?? true,\n context: options.context ?? {},\n typeMetadataRegistry: this.family.typeMetadataRegistry,\n });\n if (!schemaVerifyResult.ok) {\n return runnerFailure('SCHEMA_VERIFY_FAILED', schemaVerifyResult.summary, {\n why: 'The resulting database schema does not satisfy the destination contract.',\n meta: {\n issues: schemaVerifyResult.schema.issues,\n },\n });\n }\n\n // Record marker and ledger entries\n await this.upsertMarker(driver, options, existingMarker);\n await this.recordLedgerEntry(driver, options, existingMarker, applyValue.executedOperations);\n\n await this.commitTransaction(driver);\n committed = true;\n return runnerSuccess({\n operationsPlanned: options.plan.operations.length,\n operationsExecuted: applyValue.operationsExecuted,\n });\n } finally {\n if (!committed) {\n await this.rollbackTransaction(driver);\n }\n }\n }\n\n private async applyPlan(\n driver: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n options: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,\n ): Promise<Result<ApplyPlanSuccessValue, MigrationRunnerFailure>> {\n let operationsExecuted = 0;\n const executedOperations: Array<MigrationPlanOperation<PostgresPlanTargetDetails>> = [];\n for (const operation of options.plan.operations) {\n options.callbacks?.onOperationStart?.(operation);\n try {\n const postcheckAlreadySatisfied = await this.expectationsAreSatisfied(\n driver,\n operation.postcheck,\n );\n if (postcheckAlreadySatisfied) {\n executedOperations.push(this.createPostcheckPreSatisfiedSkipRecord(operation));\n continue;\n }\n\n const precheckResult = await this.runExpectationSteps(\n driver,\n operation.precheck,\n operation,\n 'precheck',\n );\n if (!precheckResult.ok) {\n return precheckResult;\n }\n\n const executeResult = await this.runExecuteSteps(driver, operation.execute, operation);\n if (!executeResult.ok) {\n return executeResult;\n }\n\n const postcheckResult = await this.runExpectationSteps(\n driver,\n operation.postcheck,\n operation,\n 'postcheck',\n );\n if (!postcheckResult.ok) {\n return postcheckResult;\n }\n\n executedOperations.push(operation);\n operationsExecuted += 1;\n } finally {\n options.callbacks?.onOperationComplete?.(operation);\n }\n }\n return ok({ operationsExecuted, executedOperations });\n }\n\n private async ensureControlTables(\n driver: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n ): Promise<void> {\n await this.executeStatement(driver, ensurePrismaContractSchemaStatement);\n await this.executeStatement(driver, ensureMarkerTableStatement);\n await this.executeStatement(driver, ensureLedgerTableStatement);\n }\n\n private async runExpectationSteps(\n driver: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n steps: readonly MigrationPlanOperationStep[],\n operation: MigrationPlanOperation<PostgresPlanTargetDetails>,\n phase: 'precheck' | 'postcheck',\n ): Promise<Result<void, MigrationRunnerFailure>> {\n for (const step of steps) {\n const result = await driver.query(step.sql);\n if (!this.stepResultIsTrue(result.rows)) {\n const code = phase === 'precheck' ? 'PRECHECK_FAILED' : 'POSTCHECK_FAILED';\n return runnerFailure(\n code,\n `Operation ${operation.id} failed during ${phase}: ${step.description}`,\n {\n meta: {\n operationId: operation.id,\n phase,\n stepDescription: step.description,\n },\n },\n );\n }\n }\n return okVoid();\n }\n\n private async runExecuteSteps(\n driver: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n steps: readonly MigrationPlanOperationStep[],\n operation: MigrationPlanOperation<PostgresPlanTargetDetails>,\n ): Promise<Result<void, MigrationRunnerFailure>> {\n for (const step of steps) {\n try {\n await driver.query(step.sql);\n } catch (error) {\n return runnerFailure(\n 'EXECUTION_FAILED',\n `Operation ${operation.id} failed during execution: ${step.description}`,\n {\n why: error instanceof Error ? error.message : String(error),\n meta: {\n operationId: operation.id,\n stepDescription: step.description,\n sql: step.sql,\n },\n },\n );\n }\n }\n return okVoid();\n }\n\n private stepResultIsTrue(rows: readonly Record<string, unknown>[]): boolean {\n if (!rows || rows.length === 0) {\n return false;\n }\n const firstRow = rows[0];\n const firstValue = firstRow ? Object.values(firstRow)[0] : undefined;\n if (typeof firstValue === 'boolean') {\n return firstValue;\n }\n if (typeof firstValue === 'number') {\n return firstValue !== 0;\n }\n if (typeof firstValue === 'string') {\n const lower = firstValue.toLowerCase();\n // PostgreSQL boolean representations: 't'/'f', 'true'/'false', '1'/'0'\n if (lower === 't' || lower === 'true' || lower === '1') {\n return true;\n }\n if (lower === 'f' || lower === 'false' || lower === '0') {\n return false;\n }\n // For other strings, non-empty is truthy (though this case shouldn't occur for boolean checks)\n return firstValue.length > 0;\n }\n return Boolean(firstValue);\n }\n\n private async expectationsAreSatisfied(\n driver: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n steps: readonly MigrationPlanOperationStep[],\n ): Promise<boolean> {\n if (steps.length === 0) {\n return false;\n }\n for (const step of steps) {\n const result = await driver.query(step.sql);\n if (!this.stepResultIsTrue(result.rows)) {\n return false;\n }\n }\n return true;\n }\n\n private createPostcheckPreSatisfiedSkipRecord(\n operation: MigrationPlanOperation<PostgresPlanTargetDetails>,\n ): MigrationPlanOperation<PostgresPlanTargetDetails> {\n // Clone and freeze existing meta if present\n const clonedMeta = operation.meta ? cloneAndFreezeRecord(operation.meta) : undefined;\n\n // Create frozen runner metadata\n const runnerMeta = Object.freeze({\n skipped: true,\n reason: 'postcheck_pre_satisfied',\n });\n\n // Merge and freeze the combined meta\n const mergedMeta = Object.freeze({\n ...(clonedMeta ?? {}),\n runner: runnerMeta,\n });\n\n // Clone and freeze arrays to prevent mutation\n const frozenPostcheck = Object.freeze([...operation.postcheck]);\n\n return Object.freeze({\n id: operation.id,\n label: operation.label,\n ...(operation.summary ? { summary: operation.summary } : {}),\n operationClass: operation.operationClass,\n target: operation.target, // Already frozen from plan creation\n precheck: Object.freeze([]),\n execute: Object.freeze([]),\n postcheck: frozenPostcheck,\n ...(operation.meta || mergedMeta ? { meta: mergedMeta } : {}),\n });\n }\n\n private markerMatchesDestination(\n marker: ContractMarkerRecord | null,\n plan: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['plan'],\n ): boolean {\n if (!marker) {\n return false;\n }\n if (marker.coreHash !== plan.destination.coreHash) {\n return false;\n }\n if (plan.destination.profileHash && marker.profileHash !== plan.destination.profileHash) {\n return false;\n }\n return true;\n }\n\n private enforcePolicyCompatibility(\n policy: MigrationOperationPolicy,\n operations: readonly MigrationPlanOperation<PostgresPlanTargetDetails>[],\n ): Result<void, MigrationRunnerFailure> {\n const allowedClasses = new Set(policy.allowedOperationClasses);\n for (const operation of operations) {\n if (!allowedClasses.has(operation.operationClass)) {\n return runnerFailure(\n 'POLICY_VIOLATION',\n `Operation ${operation.id} has class \"${operation.operationClass}\" which is not allowed by policy.`,\n {\n why: `Policy only allows: ${policy.allowedOperationClasses.join(', ')}.`,\n meta: {\n operationId: operation.id,\n operationClass: operation.operationClass,\n allowedClasses: policy.allowedOperationClasses,\n },\n },\n );\n }\n }\n return okVoid();\n }\n\n private ensureMarkerCompatibility(\n marker: ContractMarkerRecord | null,\n plan: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['plan'],\n ): Result<void, MigrationRunnerFailure> {\n const origin = plan.origin ?? null;\n if (!origin) {\n if (!marker) {\n return okVoid();\n }\n if (this.markerMatchesDestination(marker, plan)) {\n return okVoid();\n }\n return runnerFailure(\n 'MARKER_ORIGIN_MISMATCH',\n `Existing contract marker (${marker.coreHash}) does not match plan origin (no marker expected).`,\n {\n meta: {\n markerCoreHash: marker.coreHash,\n expectedOrigin: null,\n },\n },\n );\n }\n\n if (!marker) {\n return runnerFailure(\n 'MARKER_ORIGIN_MISMATCH',\n `Missing contract marker: expected origin core hash ${origin.coreHash}.`,\n {\n meta: {\n expectedOriginCoreHash: origin.coreHash,\n },\n },\n );\n }\n if (marker.coreHash !== origin.coreHash) {\n return runnerFailure(\n 'MARKER_ORIGIN_MISMATCH',\n `Existing contract marker (${marker.coreHash}) does not match plan origin (${origin.coreHash}).`,\n {\n meta: {\n markerCoreHash: marker.coreHash,\n expectedOriginCoreHash: origin.coreHash,\n },\n },\n );\n }\n if (origin.profileHash && marker.profileHash !== origin.profileHash) {\n return runnerFailure(\n 'MARKER_ORIGIN_MISMATCH',\n `Existing contract marker profile hash (${marker.profileHash}) does not match plan origin profile hash (${origin.profileHash}).`,\n {\n meta: {\n markerProfileHash: marker.profileHash,\n expectedOriginProfileHash: origin.profileHash,\n },\n },\n );\n }\n return okVoid();\n }\n\n private ensurePlanMatchesDestinationContract(\n destination: MigrationPlanContractInfo,\n contract: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['destinationContract'],\n ): Result<void, MigrationRunnerFailure> {\n if (destination.coreHash !== contract.coreHash) {\n return runnerFailure(\n 'DESTINATION_CONTRACT_MISMATCH',\n `Plan destination core hash (${destination.coreHash}) does not match provided contract core hash (${contract.coreHash}).`,\n {\n meta: {\n planCoreHash: destination.coreHash,\n contractCoreHash: contract.coreHash,\n },\n },\n );\n }\n if (\n destination.profileHash &&\n contract.profileHash &&\n destination.profileHash !== contract.profileHash\n ) {\n return runnerFailure(\n 'DESTINATION_CONTRACT_MISMATCH',\n `Plan destination profile hash (${destination.profileHash}) does not match provided contract profile hash (${contract.profileHash}).`,\n {\n meta: {\n planProfileHash: destination.profileHash,\n contractProfileHash: contract.profileHash,\n },\n },\n );\n }\n return okVoid();\n }\n\n private async upsertMarker(\n driver: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n options: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,\n existingMarker: ContractMarkerRecord | null,\n ): Promise<void> {\n const writeStatements = buildWriteMarkerStatements({\n coreHash: options.plan.destination.coreHash,\n profileHash:\n options.plan.destination.profileHash ??\n options.destinationContract.profileHash ??\n options.plan.destination.coreHash,\n contractJson: options.destinationContract,\n canonicalVersion: null,\n meta: {},\n });\n const statement = existingMarker ? writeStatements.update : writeStatements.insert;\n await this.executeStatement(driver, statement);\n }\n\n private async recordLedgerEntry(\n driver: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n options: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,\n existingMarker: ContractMarkerRecord | null,\n executedOperations: readonly MigrationPlanOperation<PostgresPlanTargetDetails>[],\n ): Promise<void> {\n const ledgerStatement = buildLedgerInsertStatement({\n originCoreHash: existingMarker?.coreHash ?? null,\n originProfileHash: existingMarker?.profileHash ?? null,\n destinationCoreHash: options.plan.destination.coreHash,\n destinationProfileHash:\n options.plan.destination.profileHash ??\n options.destinationContract.profileHash ??\n options.plan.destination.coreHash,\n contractJsonBefore: existingMarker?.contractJson ?? null,\n contractJsonAfter: options.destinationContract,\n operations: executedOperations,\n });\n await this.executeStatement(driver, ledgerStatement);\n }\n\n private async acquireLock(\n driver: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n key: string,\n ): Promise<void> {\n await driver.query('select pg_advisory_xact_lock(hashtext($1))', [key]);\n }\n\n private async beginTransaction(\n driver: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n ): Promise<void> {\n await driver.query('BEGIN');\n }\n\n private async commitTransaction(\n driver: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n ): Promise<void> {\n await driver.query('COMMIT');\n }\n\n private async rollbackTransaction(\n driver: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n ): Promise<void> {\n await driver.query('ROLLBACK');\n }\n\n private async executeStatement(\n driver: MigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n statement: SqlStatement,\n ): Promise<void> {\n if (statement.params.length > 0) {\n await driver.query(statement.sql, statement.params);\n return;\n }\n await driver.query(statement.sql);\n }\n}\n","export interface SqlStatement {\n readonly sql: string;\n readonly params: readonly unknown[];\n}\n\nexport const ensurePrismaContractSchemaStatement: SqlStatement = {\n sql: 'create schema if not exists prisma_contract',\n params: [],\n};\n\nexport const ensureMarkerTableStatement: SqlStatement = {\n sql: `create table if not exists prisma_contract.marker (\n id smallint primary key default 1,\n core_hash text not null,\n profile_hash text not null,\n contract_json jsonb,\n canonical_version int,\n updated_at timestamptz not null default now(),\n app_tag text,\n meta jsonb not null default '{}'\n )`,\n params: [],\n};\n\nexport const ensureLedgerTableStatement: SqlStatement = {\n sql: `create table if not exists prisma_contract.ledger (\n id bigserial primary key,\n created_at timestamptz not null default now(),\n origin_core_hash text,\n origin_profile_hash text,\n destination_core_hash text not null,\n destination_profile_hash text,\n contract_json_before jsonb,\n contract_json_after jsonb,\n operations jsonb not null\n )`,\n params: [],\n};\n\nexport interface WriteMarkerInput {\n readonly coreHash: string;\n readonly profileHash: string;\n readonly contractJson?: unknown;\n readonly canonicalVersion?: number | null;\n readonly appTag?: string | null;\n readonly meta?: Record<string, unknown>;\n}\n\nexport function buildWriteMarkerStatements(input: WriteMarkerInput): {\n readonly insert: SqlStatement;\n readonly update: SqlStatement;\n} {\n const params: readonly unknown[] = [\n 1,\n input.coreHash,\n input.profileHash,\n jsonParam(input.contractJson),\n input.canonicalVersion ?? null,\n input.appTag ?? null,\n jsonParam(input.meta ?? {}),\n ];\n\n return {\n insert: {\n sql: `insert into prisma_contract.marker (\n id,\n core_hash,\n profile_hash,\n contract_json,\n canonical_version,\n updated_at,\n app_tag,\n meta\n ) values (\n $1,\n $2,\n $3,\n $4::jsonb,\n $5,\n now(),\n $6,\n $7::jsonb\n )`,\n params,\n },\n update: {\n sql: `update prisma_contract.marker set\n core_hash = $2,\n profile_hash = $3,\n contract_json = $4::jsonb,\n canonical_version = $5,\n updated_at = now(),\n app_tag = $6,\n meta = $7::jsonb\n where id = $1`,\n params,\n },\n };\n}\n\nexport interface LedgerInsertInput {\n readonly originCoreHash?: string | null;\n readonly originProfileHash?: string | null;\n readonly destinationCoreHash: string;\n readonly destinationProfileHash?: string | null;\n readonly contractJsonBefore?: unknown;\n readonly contractJsonAfter?: unknown;\n readonly operations: unknown;\n}\n\nexport function buildLedgerInsertStatement(input: LedgerInsertInput): SqlStatement {\n return {\n sql: `insert into prisma_contract.ledger (\n origin_core_hash,\n origin_profile_hash,\n destination_core_hash,\n destination_profile_hash,\n contract_json_before,\n contract_json_after,\n operations\n ) values (\n $1,\n $2,\n $3,\n $4,\n $5::jsonb,\n $6::jsonb,\n $7::jsonb\n )`,\n params: [\n input.originCoreHash ?? null,\n input.originProfileHash ?? null,\n input.destinationCoreHash,\n input.destinationProfileHash ?? null,\n jsonParam(input.contractJsonBefore),\n jsonParam(input.contractJsonAfter),\n jsonParam(input.operations),\n ],\n };\n}\n\nfunction jsonParam(value: unknown): string {\n return JSON.stringify(value ?? null);\n}\n"],"mappings":";AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAO9B,SAAS,YAAY;;;ACHrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAqBP,IAAM,yBAAwC;AAAA,EAC5C,eAAe;AACjB;AAEA,IAAM,mBAA2C;AAAA,EAC/C,UAAU;AACZ;AAOA,IAAM,2BAA2B,oBAAI,IAAI,CAAC,MAAM,UAAU,CAAC;AAEpD,SAAS,+BACd,SAAiC,CAAC,GACW;AAC7C,SAAO,IAAI,yBAAyB;AAAA,IAClC,GAAG;AAAA,IACH,GAAG;AAAA,EACL,CAAC;AACH;AAEA,IAAM,2BAAN,MAAsF;AAAA,EACpF,YAA6B,QAAuB;AAAvB;AAAA,EAAwB;AAAA,EAErD,KAAK,SAAsC;AACzC,UAAM,aAAa,QAAQ,cAAc,KAAK,OAAO;AACrD,UAAM,eAAe,KAAK,qBAAqB,QAAQ,MAAM;AAC7D,QAAI,cAAc;AAChB,aAAO;AAAA,IACT;AAEA,UAAM,iBAAiB,OAAO,KAAK,QAAQ,OAAO,MAAM;AACxD,QAAI,eAAe,SAAS,GAAG;AAC7B,YAAM,YAAY,eAAe,KAAK,EAAE,KAAK,IAAI;AACjD,aAAO,eAAe;AAAA,QACpB;AAAA,UACE,MAAM;AAAA,UACN,SAAS,iFAAiF,eAAe,MAAM,uBAAuB,SAAS;AAAA,UAC/I,KAAK;AAAA,QACP;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,kBAAkB,KAAK,mBAAmB,QAAQ,QAAQ;AAChE,QAAI,iBAAiB;AACnB,aAAO;AAAA,IACT;AAEA,UAAM,aAAkE,CAAC;AAEzE,eAAW;AAAA,MACT,GAAG,KAAK,yBAAyB,QAAQ,UAAU,UAAU;AAAA,MAC7D,GAAG,KAAK,qBAAqB,QAAQ,SAAS,QAAQ,QAAQ,UAAU;AAAA,MACxE,GAAG,KAAK,sBAAsB,QAAQ,SAAS,QAAQ,QAAQ,UAAU;AAAA,MACzE,GAAG,KAAK,qBAAqB,QAAQ,SAAS,QAAQ,QAAQ,UAAU;AAAA,MACxE,GAAG,KAAK,0BAA0B,QAAQ,SAAS,QAAQ,QAAQ,UAAU;AAAA,IAC/E;AAEA,UAAM,OAAO,oBAA+C;AAAA,MAC1D,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,UAAU,QAAQ,SAAS;AAAA,QAC3B,GAAI,QAAQ,SAAS,cAAc,EAAE,aAAa,QAAQ,SAAS,YAAY,IAAI,CAAC;AAAA,MACtF;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO,eAAe,IAAI;AAAA,EAC5B;AAAA,EAEQ,mBAAmB,UAAmC;AAC5D,UAAM,aAAa,SAAS,cAAc,CAAC;AAC3C,UAAM,iBAAiB,OAAO,KAAK,UAAU;AAG7C,UAAM,qBAAqB,eAAe;AAAA,MACxC,CAAC,kBAAkB,CAAC,yBAAyB,IAAI,aAAa;AAAA,IAChE;AACA,UAAM,wBAAwB,mBAAmB;AAAA,MAC/C,CAAC,kBAAkB,CAAC,iBAAiB,aAAa;AAAA,IACpD;AACA,QAAI,sBAAsB,SAAS,GAAG;AACpC,YAAM,sBAAsB,OAAO,KAAK,gBAAgB,EAAE,KAAK,IAAI;AACnE,YAAM,kBAAkB,sBAAsB,KAAK,IAAI;AACvD,aAAO,eAAe;AAAA,QACpB;AAAA,UACE,MAAM;AAAA,UACN,SAAS,kDAAkD,eAAe;AAAA,UAC1E,KAAK,2DAA2D,mBAAmB;AAAA,UACnF,UAAU,EAAE,WAAW,gBAAgB;AAAA,QACzC;AAAA,MACF,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,qBAAqB,QAAkC;AAC7D,QAAI,CAAC,OAAO,wBAAwB,SAAS,UAAU,GAAG;AACxD,aAAO,eAAe;AAAA,QACpB;AAAA,UACE,MAAM;AAAA,UACN,SAAS;AAAA,UACT,KAAK;AAAA,QACP;AAAA,MACF,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,yBACN,UACA,QAC8D;AAC9D,UAAM,aAAa,SAAS,cAAc,CAAC;AAC3C,UAAM,iBAAiB,OAAO,KAAK,UAAU;AAC7C,UAAM,aAAkE,CAAC;AAGzE,eAAW,iBAAiB,gBAAgB;AAE1C,UAAI,yBAAyB,IAAI,aAAa,GAAG;AAC/C;AAAA,MACF;AACA,YAAM,MAAM,iBAAiB,aAAa;AAC1C,UAAI,CAAC,KAAK;AAER,cAAM,IAAI,MAAM,+BAA+B,aAAa,EAAE;AAAA,MAChE;AACA,YAAM,UAAU,KAAK,mBAAmB,aAAa,eAAe,MAAM;AAC1E,iBAAW,KAAK;AAAA,QACd,IAAI,aAAa,aAAa;AAAA,QAC9B,OAAO,qBAAqB,aAAa;AAAA,QACzC,SAAS,eAAe,aAAa;AAAA,QACrC,gBAAgB;AAAA,QAChB,QAAQ,EAAE,IAAI,YAAY,QAAQ;AAAA,QAClC,UAAU;AAAA,UACR;AAAA,YACE,aAAa,qBAAqB,aAAa;AAAA,YAC/C,KAAK,kEAAkE;AAAA,cACrE,KAAK,sBAAsB,aAAa;AAAA,YAC1C,CAAC;AAAA,UACH;AAAA,QACF;AAAA,QACA,SAAS;AAAA,UACP;AAAA,YACE,aAAa,qBAAqB,aAAa;AAAA,YAC/C;AAAA,UACF;AAAA,QACF;AAAA,QACA,WAAW;AAAA,UACT;AAAA,YACE,aAAa,sBAAsB,aAAa;AAAA,YAChD,KAAK,8DAA8D;AAAA,cACjE,KAAK,sBAAsB,aAAa;AAAA,YAC1C,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,sBAAsB,eAA+B;AAC3D,QAAI,kBAAkB,YAAY;AAChC,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,qBACN,QACA,QAC8D;AAC9D,UAAM,aAAkE,CAAC;AACzE,eAAW,CAAC,WAAW,KAAK,KAAK,cAAc,MAAM,GAAG;AACtD,YAAM,YAAY,iBAAiB,QAAQ,SAAS;AACpD,iBAAW,KAAK;AAAA,QACd,IAAI,SAAS,SAAS;AAAA,QACtB,OAAO,gBAAgB,SAAS;AAAA,QAChC,SAAS,iBAAiB,SAAS;AAAA,QACnC,gBAAgB;AAAA,QAChB,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ,SAAS,KAAK,mBAAmB,SAAS,WAAW,MAAM;AAAA,QAC7D;AAAA,QACA,UAAU;AAAA,UACR;AAAA,YACE,aAAa,iBAAiB,SAAS;AAAA,YACvC,KAAK,sBAAsB,kBAAkB,QAAQ,SAAS,CAAC;AAAA,UACjE;AAAA,QACF;AAAA,QACA,SAAS;AAAA,UACP;AAAA,YACE,aAAa,iBAAiB,SAAS;AAAA,YACvC,KAAK,oBAAoB,WAAW,KAAK;AAAA,UAC3C;AAAA,QACF;AAAA,QACA,WAAW;AAAA,UACT;AAAA,YACE,aAAa,iBAAiB,SAAS;AAAA,YACvC,KAAK,sBAAsB,kBAAkB,QAAQ,SAAS,CAAC;AAAA,UACjE;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,sBACN,QACA,QAC8D;AAC9D,UAAM,aAAkE,CAAC;AACzE,eAAW,CAAC,WAAW,KAAK,KAAK,cAAc,MAAM,GAAG;AACtD,iBAAW,UAAU,MAAM,SAAS;AAClC,cAAM,iBAAiB,OAAO,QAAQ,GAAG,SAAS,IAAI,OAAO,QAAQ,KAAK,GAAG,CAAC;AAC9E,mBAAW,KAAK;AAAA,UACd,IAAI,UAAU,SAAS,IAAI,cAAc;AAAA,UACzC,OAAO,yBAAyB,cAAc,OAAO,SAAS;AAAA,UAC9D,SAAS,0BAA0B,cAAc,OAAO,SAAS;AAAA,UACjE,gBAAgB;AAAA,UAChB,QAAQ;AAAA,YACN,IAAI;AAAA,YACJ,SAAS,KAAK,mBAAmB,UAAU,gBAAgB,QAAQ,SAAS;AAAA,UAC9E;AAAA,UACA,UAAU;AAAA,YACR;AAAA,cACE,aAAa,6BAA6B,cAAc;AAAA,cACxD,KAAK,sBAAsB,EAAE,gBAAgB,QAAQ,QAAQ,MAAM,CAAC;AAAA,YACtE;AAAA,UACF;AAAA,UACA,SAAS;AAAA,YACP;AAAA,cACE,aAAa,0BAA0B,cAAc;AAAA,cACrD,KAAK,eAAe,iBAAiB,QAAQ,SAAS,CAAC;AAAA,iBACpD,gBAAgB,cAAc,CAAC;AAAA,UACtC,OAAO,QAAQ,IAAI,eAAe,EAAE,KAAK,IAAI,CAAC;AAAA,YAC5C;AAAA,UACF;AAAA,UACA,WAAW;AAAA,YACT;AAAA,cACE,aAAa,6BAA6B,cAAc;AAAA,cACxD,KAAK,sBAAsB,EAAE,gBAAgB,OAAO,CAAC;AAAA,YACvD;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,qBACN,QACA,QAC8D;AAC9D,UAAM,aAAkE,CAAC;AACzE,eAAW,CAAC,WAAW,KAAK,KAAK,cAAc,MAAM,GAAG;AACtD,iBAAW,SAAS,MAAM,SAAS;AACjC,cAAM,YAAY,MAAM,QAAQ,GAAG,SAAS,IAAI,MAAM,QAAQ,KAAK,GAAG,CAAC;AACvE,mBAAW,KAAK;AAAA,UACd,IAAI,SAAS,SAAS,IAAI,SAAS;AAAA,UACnC,OAAO,gBAAgB,SAAS,OAAO,SAAS;AAAA,UAChD,SAAS,iBAAiB,SAAS,OAAO,SAAS;AAAA,UACnD,gBAAgB;AAAA,UAChB,QAAQ;AAAA,YACN,IAAI;AAAA,YACJ,SAAS,KAAK,mBAAmB,SAAS,WAAW,QAAQ,SAAS;AAAA,UACxE;AAAA,UACA,UAAU;AAAA,YACR;AAAA,cACE,aAAa,iBAAiB,SAAS;AAAA,cACvC,KAAK,sBAAsB,kBAAkB,QAAQ,SAAS,CAAC;AAAA,YACjE;AAAA,UACF;AAAA,UACA,SAAS;AAAA,YACP;AAAA,cACE,aAAa,iBAAiB,SAAS;AAAA,cACvC,KAAK,gBAAgB,gBAAgB,SAAS,CAAC,OAAO;AAAA,gBACpD;AAAA,gBACA;AAAA,cACF,CAAC,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,KAAK,IAAI,CAAC;AAAA,YACrD;AAAA,UACF;AAAA,UACA,WAAW;AAAA,YACT;AAAA,cACE,aAAa,iBAAiB,SAAS;AAAA,cACvC,KAAK,sBAAsB,kBAAkB,QAAQ,SAAS,CAAC;AAAA,YACjE;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,0BACN,QACA,QAC8D;AAC9D,UAAM,aAAkE,CAAC;AACzE,eAAW,CAAC,WAAW,KAAK,KAAK,cAAc,MAAM,GAAG;AACtD,iBAAW,cAAc,MAAM,aAAa;AAC1C,cAAM,SAAS,WAAW,QAAQ,GAAG,SAAS,IAAI,WAAW,QAAQ,KAAK,GAAG,CAAC;AAC9E,mBAAW,KAAK;AAAA,UACd,IAAI,cAAc,SAAS,IAAI,MAAM;AAAA,UACrC,OAAO,mBAAmB,MAAM,OAAO,SAAS;AAAA,UAChD,SAAS,oBAAoB,MAAM,gBAAgB,WAAW,WAAW,KAAK;AAAA,UAC9E,gBAAgB;AAAA,UAChB,QAAQ;AAAA,YACN,IAAI;AAAA,YACJ,SAAS,KAAK,mBAAmB,cAAc,QAAQ,QAAQ,SAAS;AAAA,UAC1E;AAAA,UACA,UAAU;AAAA,YACR;AAAA,cACE,aAAa,uBAAuB,MAAM;AAAA,cAC1C,KAAK,sBAAsB,EAAE,gBAAgB,QAAQ,QAAQ,QAAQ,MAAM,CAAC;AAAA,YAC9E;AAAA,UACF;AAAA,UACA,SAAS;AAAA,YACP;AAAA,cACE,aAAa,oBAAoB,MAAM;AAAA,cACvC,KAAK,eAAe,iBAAiB,QAAQ,SAAS,CAAC;AAAA,iBACpD,gBAAgB,MAAM,CAAC;AAAA,eACzB,WAAW,QAAQ,IAAI,eAAe,EAAE,KAAK,IAAI,CAAC;AAAA,aACpD,iBAAiB,QAAQ,WAAW,WAAW,KAAK,CAAC,KAAK,WAAW,WAAW,QAC5E,IAAI,eAAe,EACnB,KAAK,IAAI,CAAC;AAAA,YACf;AAAA,UACF;AAAA,UACA,WAAW;AAAA,YACT;AAAA,cACE,aAAa,uBAAuB,MAAM;AAAA,cAC1C,KAAK,sBAAsB,EAAE,gBAAgB,QAAQ,OAAO,CAAC;AAAA,YAC/D;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,mBACN,YACA,MACA,QACA,OAC2B;AAC3B,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,IAC3B;AAAA,EACF;AACF;AAEA,SAAS,oBAAoB,oBAA4B,OAA6B;AACpF,QAAM,oBAAoB,OAAO,QAAQ,MAAM,OAAO,EAAE;AAAA,IACtD,CAAC,CAAC,YAAY,MAAM,MAA+B;AACjD,YAAM,QAAQ;AAAA,QACZ,gBAAgB,UAAU;AAAA,QAC1B,OAAO;AAAA,QACP,OAAO,WAAW,KAAK;AAAA,MACzB,EAAE,OAAO,OAAO;AAChB,aAAO,MAAM,KAAK,GAAG;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,wBAAkC,CAAC;AACzC,MAAI,MAAM,YAAY;AACpB,0BAAsB;AAAA,MACpB,gBAAgB,MAAM,WAAW,QAAQ,IAAI,eAAe,EAAE,KAAK,IAAI,CAAC;AAAA,IAC1E;AAAA,EACF;AAEA,QAAM,iBAAiB,CAAC,GAAG,mBAAmB,GAAG,qBAAqB;AACtE,SAAO,gBAAgB,kBAAkB;AAAA,IAAS,eAAe,KAAK,OAAO,CAAC;AAAA;AAChF;AAEA,SAAS,iBAAiB,QAAgB,OAAuB;AAC/D,SAAO,GAAG,gBAAgB,MAAM,CAAC,IAAI,gBAAgB,KAAK,CAAC;AAC7D;AAEA,SAAS,kBAAkB,QAAgB,MAAsB;AAC/D,QAAM,WAAW,GAAG,gBAAgB,MAAM,CAAC,IAAI,gBAAgB,IAAI,CAAC;AACpE,SAAO,IAAI,cAAc,QAAQ,CAAC;AACpC;AAEA,SAAS,gBAAgB,YAA4B;AACnD,SAAO,IAAI,WAAW,QAAQ,MAAM,IAAI,CAAC;AAC3C;AAEA,SAAS,cAAc,OAAuB;AAC5C,SAAO,MAAM,QAAQ,MAAM,IAAI;AACjC;AAEA,SAAS,cAAiB,QAAyD;AACjF,SAAO,OAAO,QAAQ,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AACrE;AAEA,SAAS,sBAAsB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA,SAAS;AACX,GAIW;AACT,QAAM,eAAe,SAAS,WAAW;AACzC,SAAO,UAAU,YAAY;AAAA;AAAA;AAAA,uBAGR,cAAc,cAAc,CAAC;AAAA,qBAC/B,cAAc,MAAM,CAAC;AAAA;AAE1C;;;ACxbA,SAAS,eAAe,qBAAqB;AAC7C,SAAS,uBAAuB;AAChC,SAAS,kBAAkB;AAE3B,SAAS,IAAI,cAAc;;;ACXpB,IAAM,sCAAoD;AAAA,EAC/D,KAAK;AAAA,EACL,QAAQ,CAAC;AACX;AAEO,IAAM,6BAA2C;AAAA,EACtD,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUL,QAAQ,CAAC;AACX;AAEO,IAAM,6BAA2C;AAAA,EACtD,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWL,QAAQ,CAAC;AACX;AAWO,SAAS,2BAA2B,OAGzC;AACA,QAAM,SAA6B;AAAA,IACjC;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,UAAU,MAAM,YAAY;AAAA,IAC5B,MAAM,oBAAoB;AAAA,IAC1B,MAAM,UAAU;AAAA,IAChB,UAAU,MAAM,QAAQ,CAAC,CAAC;AAAA,EAC5B;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAmBL;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASL;AAAA,IACF;AAAA,EACF;AACF;AAYO,SAAS,2BAA2B,OAAwC;AACjF,SAAO;AAAA,IACL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAiBL,QAAQ;AAAA,MACN,MAAM,kBAAkB;AAAA,MACxB,MAAM,qBAAqB;AAAA,MAC3B,MAAM;AAAA,MACN,MAAM,0BAA0B;AAAA,MAChC,UAAU,MAAM,kBAAkB;AAAA,MAClC,UAAU,MAAM,iBAAiB;AAAA,MACjC,UAAU,MAAM,UAAU;AAAA,IAC5B;AAAA,EACF;AACF;AAEA,SAAS,UAAU,OAAwB;AACzC,SAAO,KAAK,UAAU,SAAS,IAAI;AACrC;;;AD3GA,IAAM,iBAA+B;AAAA,EACnC,eAAe;AACjB;AAEA,IAAM,cAAc;AAMpB,SAAS,qBAAwD,OAAa;AAC5E,QAAM,SAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC9C,QAAI,QAAQ,QAAQ,QAAQ,QAAW;AACrC,aAAO,GAAG,IAAI;AAAA,IAChB,WAAW,MAAM,QAAQ,GAAG,GAAG;AAE7B,aAAO,GAAG,IAAI,OAAO,OAAO,CAAC,GAAG,GAAG,CAAC;AAAA,IACtC,WAAW,OAAO,QAAQ,UAAU;AAElC,aAAO,GAAG,IAAI,qBAAqB,GAA8B;AAAA,IACnE,OAAO;AAEL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AACA,SAAO,OAAO,OAAO,MAAM;AAC7B;AAEO,SAAS,8BACd,QACA,SAAgC,CAAC,GACW;AAC5C,SAAO,IAAI,wBAAwB,QAAQ,EAAE,GAAG,gBAAgB,GAAG,OAAO,CAAC;AAC7E;AAEA,IAAM,0BAAN,MAAoF;AAAA,EAClF,YACmB,QACA,QACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAEH,MAAM,QACJ,SACgC;AAChC,UAAM,SAAS,QAAQ,cAAc,KAAK,OAAO;AACjD,UAAM,SAAS,QAAQ;AACvB,UAAM,UAAU,GAAG,WAAW,IAAI,MAAM;AAGxC,UAAM,mBAAmB,KAAK;AAAA,MAC5B,QAAQ,KAAK;AAAA,MACb,QAAQ;AAAA,IACV;AACA,QAAI,CAAC,iBAAiB,IAAI;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,KAAK,2BAA2B,QAAQ,QAAQ,QAAQ,KAAK,UAAU;AAC3F,QAAI,CAAC,YAAY,IAAI;AACnB,aAAO;AAAA,IACT;AAGA,UAAM,KAAK,iBAAiB,MAAM;AAClC,QAAI,YAAY;AAChB,QAAI;AACF,YAAM,KAAK,YAAY,QAAQ,OAAO;AACtC,YAAM,KAAK,oBAAoB,MAAM;AACrC,YAAM,iBAAiB,MAAM,WAAW,MAAM;AAG9C,YAAM,cAAc,KAAK,0BAA0B,gBAAgB,QAAQ,IAAI;AAC/E,UAAI,CAAC,YAAY,IAAI;AACnB,eAAO;AAAA,MACT;AAGA,YAAM,sBAAsB,KAAK,yBAAyB,gBAAgB,QAAQ,IAAI;AACtF,UAAI;AAEJ,UAAI,qBAAqB;AACvB,qBAAa,EAAE,oBAAoB,GAAG,oBAAoB,CAAC,EAAE;AAAA,MAC/D,OAAO;AACL,cAAM,cAAc,MAAM,KAAK,UAAU,QAAQ,OAAO;AACxD,YAAI,CAAC,YAAY,IAAI;AACnB,iBAAO;AAAA,QACT;AACA,qBAAa,YAAY;AAAA,MAC3B;AAIA,YAAM,WAAW,MAAM,KAAK,OAAO,WAAW;AAAA,QAC5C;AAAA,QACA,YAAY,QAAQ;AAAA,MACtB,CAAC;AAGD,YAAM,qBAAqB,gBAAgB;AAAA,QACzC,UAAU,QAAQ;AAAA,QAClB,QAAQ;AAAA,QACR,QAAQ,QAAQ,sBAAsB;AAAA,QACtC,SAAS,QAAQ,WAAW,CAAC;AAAA,QAC7B,sBAAsB,KAAK,OAAO;AAAA,MACpC,CAAC;AACD,UAAI,CAAC,mBAAmB,IAAI;AAC1B,eAAO,cAAc,wBAAwB,mBAAmB,SAAS;AAAA,UACvE,KAAK;AAAA,UACL,MAAM;AAAA,YACJ,QAAQ,mBAAmB,OAAO;AAAA,UACpC;AAAA,QACF,CAAC;AAAA,MACH;AAGA,YAAM,KAAK,aAAa,QAAQ,SAAS,cAAc;AACvD,YAAM,KAAK,kBAAkB,QAAQ,SAAS,gBAAgB,WAAW,kBAAkB;AAE3F,YAAM,KAAK,kBAAkB,MAAM;AACnC,kBAAY;AACZ,aAAO,cAAc;AAAA,QACnB,mBAAmB,QAAQ,KAAK,WAAW;AAAA,QAC3C,oBAAoB,WAAW;AAAA,MACjC,CAAC;AAAA,IACH,UAAE;AACA,UAAI,CAAC,WAAW;AACd,cAAM,KAAK,oBAAoB,MAAM;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,UACZ,QACA,SACgE;AAChE,QAAI,qBAAqB;AACzB,UAAM,qBAA+E,CAAC;AACtF,eAAW,aAAa,QAAQ,KAAK,YAAY;AAC/C,cAAQ,WAAW,mBAAmB,SAAS;AAC/C,UAAI;AACF,cAAM,4BAA4B,MAAM,KAAK;AAAA,UAC3C;AAAA,UACA,UAAU;AAAA,QACZ;AACA,YAAI,2BAA2B;AAC7B,6BAAmB,KAAK,KAAK,sCAAsC,SAAS,CAAC;AAC7E;AAAA,QACF;AAEA,cAAM,iBAAiB,MAAM,KAAK;AAAA,UAChC;AAAA,UACA,UAAU;AAAA,UACV;AAAA,UACA;AAAA,QACF;AACA,YAAI,CAAC,eAAe,IAAI;AACtB,iBAAO;AAAA,QACT;AAEA,cAAM,gBAAgB,MAAM,KAAK,gBAAgB,QAAQ,UAAU,SAAS,SAAS;AACrF,YAAI,CAAC,cAAc,IAAI;AACrB,iBAAO;AAAA,QACT;AAEA,cAAM,kBAAkB,MAAM,KAAK;AAAA,UACjC;AAAA,UACA,UAAU;AAAA,UACV;AAAA,UACA;AAAA,QACF;AACA,YAAI,CAAC,gBAAgB,IAAI;AACvB,iBAAO;AAAA,QACT;AAEA,2BAAmB,KAAK,SAAS;AACjC,8BAAsB;AAAA,MACxB,UAAE;AACA,gBAAQ,WAAW,sBAAsB,SAAS;AAAA,MACpD;AAAA,IACF;AACA,WAAO,GAAG,EAAE,oBAAoB,mBAAmB,CAAC;AAAA,EACtD;AAAA,EAEA,MAAc,oBACZ,QACe;AACf,UAAM,KAAK,iBAAiB,QAAQ,mCAAmC;AACvE,UAAM,KAAK,iBAAiB,QAAQ,0BAA0B;AAC9D,UAAM,KAAK,iBAAiB,QAAQ,0BAA0B;AAAA,EAChE;AAAA,EAEA,MAAc,oBACZ,QACA,OACA,WACA,OAC+C;AAC/C,eAAW,QAAQ,OAAO;AACxB,YAAM,SAAS,MAAM,OAAO,MAAM,KAAK,GAAG;AAC1C,UAAI,CAAC,KAAK,iBAAiB,OAAO,IAAI,GAAG;AACvC,cAAM,OAAO,UAAU,aAAa,oBAAoB;AACxD,eAAO;AAAA,UACL;AAAA,UACA,aAAa,UAAU,EAAE,kBAAkB,KAAK,KAAK,KAAK,WAAW;AAAA,UACrE;AAAA,YACE,MAAM;AAAA,cACJ,aAAa,UAAU;AAAA,cACvB;AAAA,cACA,iBAAiB,KAAK;AAAA,YACxB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAc,gBACZ,QACA,OACA,WAC+C;AAC/C,eAAW,QAAQ,OAAO;AACxB,UAAI;AACF,cAAM,OAAO,MAAM,KAAK,GAAG;AAAA,MAC7B,SAAS,OAAO;AACd,eAAO;AAAA,UACL;AAAA,UACA,aAAa,UAAU,EAAE,6BAA6B,KAAK,WAAW;AAAA,UACtE;AAAA,YACE,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,YAC1D,MAAM;AAAA,cACJ,aAAa,UAAU;AAAA,cACvB,iBAAiB,KAAK;AAAA,cACtB,KAAK,KAAK;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO,OAAO;AAAA,EAChB;AAAA,EAEQ,iBAAiB,MAAmD;AAC1E,QAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,aAAO;AAAA,IACT;AACA,UAAM,WAAW,KAAK,CAAC;AACvB,UAAM,aAAa,WAAW,OAAO,OAAO,QAAQ,EAAE,CAAC,IAAI;AAC3D,QAAI,OAAO,eAAe,WAAW;AACnC,aAAO;AAAA,IACT;AACA,QAAI,OAAO,eAAe,UAAU;AAClC,aAAO,eAAe;AAAA,IACxB;AACA,QAAI,OAAO,eAAe,UAAU;AAClC,YAAM,QAAQ,WAAW,YAAY;AAErC,UAAI,UAAU,OAAO,UAAU,UAAU,UAAU,KAAK;AACtD,eAAO;AAAA,MACT;AACA,UAAI,UAAU,OAAO,UAAU,WAAW,UAAU,KAAK;AACvD,eAAO;AAAA,MACT;AAEA,aAAO,WAAW,SAAS;AAAA,IAC7B;AACA,WAAO,QAAQ,UAAU;AAAA,EAC3B;AAAA,EAEA,MAAc,yBACZ,QACA,OACkB;AAClB,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO;AAAA,IACT;AACA,eAAW,QAAQ,OAAO;AACxB,YAAM,SAAS,MAAM,OAAO,MAAM,KAAK,GAAG;AAC1C,UAAI,CAAC,KAAK,iBAAiB,OAAO,IAAI,GAAG;AACvC,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,sCACN,WACmD;AAEnD,UAAM,aAAa,UAAU,OAAO,qBAAqB,UAAU,IAAI,IAAI;AAG3E,UAAM,aAAa,OAAO,OAAO;AAAA,MAC/B,SAAS;AAAA,MACT,QAAQ;AAAA,IACV,CAAC;AAGD,UAAM,aAAa,OAAO,OAAO;AAAA,MAC/B,GAAI,cAAc,CAAC;AAAA,MACnB,QAAQ;AAAA,IACV,CAAC;AAGD,UAAM,kBAAkB,OAAO,OAAO,CAAC,GAAG,UAAU,SAAS,CAAC;AAE9D,WAAO,OAAO,OAAO;AAAA,MACnB,IAAI,UAAU;AAAA,MACd,OAAO,UAAU;AAAA,MACjB,GAAI,UAAU,UAAU,EAAE,SAAS,UAAU,QAAQ,IAAI,CAAC;AAAA,MAC1D,gBAAgB,UAAU;AAAA,MAC1B,QAAQ,UAAU;AAAA;AAAA,MAClB,UAAU,OAAO,OAAO,CAAC,CAAC;AAAA,MAC1B,SAAS,OAAO,OAAO,CAAC,CAAC;AAAA,MACzB,WAAW;AAAA,MACX,GAAI,UAAU,QAAQ,aAAa,EAAE,MAAM,WAAW,IAAI,CAAC;AAAA,IAC7D,CAAC;AAAA,EACH;AAAA,EAEQ,yBACN,QACA,MACS;AACT,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AACA,QAAI,OAAO,aAAa,KAAK,YAAY,UAAU;AACjD,aAAO;AAAA,IACT;AACA,QAAI,KAAK,YAAY,eAAe,OAAO,gBAAgB,KAAK,YAAY,aAAa;AACvF,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,2BACN,QACA,YACsC;AACtC,UAAM,iBAAiB,IAAI,IAAI,OAAO,uBAAuB;AAC7D,eAAW,aAAa,YAAY;AAClC,UAAI,CAAC,eAAe,IAAI,UAAU,cAAc,GAAG;AACjD,eAAO;AAAA,UACL;AAAA,UACA,aAAa,UAAU,EAAE,eAAe,UAAU,cAAc;AAAA,UAChE;AAAA,YACE,KAAK,uBAAuB,OAAO,wBAAwB,KAAK,IAAI,CAAC;AAAA,YACrE,MAAM;AAAA,cACJ,aAAa,UAAU;AAAA,cACvB,gBAAgB,UAAU;AAAA,cAC1B,gBAAgB,OAAO;AAAA,YACzB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO,OAAO;AAAA,EAChB;AAAA,EAEQ,0BACN,QACA,MACsC;AACtC,UAAM,SAAS,KAAK,UAAU;AAC9B,QAAI,CAAC,QAAQ;AACX,UAAI,CAAC,QAAQ;AACX,eAAO,OAAO;AAAA,MAChB;AACA,UAAI,KAAK,yBAAyB,QAAQ,IAAI,GAAG;AAC/C,eAAO,OAAO;AAAA,MAChB;AACA,aAAO;AAAA,QACL;AAAA,QACA,6BAA6B,OAAO,QAAQ;AAAA,QAC5C;AAAA,UACE,MAAM;AAAA,YACJ,gBAAgB,OAAO;AAAA,YACvB,gBAAgB;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL;AAAA,QACA,sDAAsD,OAAO,QAAQ;AAAA,QACrE;AAAA,UACE,MAAM;AAAA,YACJ,wBAAwB,OAAO;AAAA,UACjC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,QAAI,OAAO,aAAa,OAAO,UAAU;AACvC,aAAO;AAAA,QACL;AAAA,QACA,6BAA6B,OAAO,QAAQ,iCAAiC,OAAO,QAAQ;AAAA,QAC5F;AAAA,UACE,MAAM;AAAA,YACJ,gBAAgB,OAAO;AAAA,YACvB,wBAAwB,OAAO;AAAA,UACjC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,QAAI,OAAO,eAAe,OAAO,gBAAgB,OAAO,aAAa;AACnE,aAAO;AAAA,QACL;AAAA,QACA,0CAA0C,OAAO,WAAW,8CAA8C,OAAO,WAAW;AAAA,QAC5H;AAAA,UACE,MAAM;AAAA,YACJ,mBAAmB,OAAO;AAAA,YAC1B,2BAA2B,OAAO;AAAA,UACpC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO,OAAO;AAAA,EAChB;AAAA,EAEQ,qCACN,aACA,UACsC;AACtC,QAAI,YAAY,aAAa,SAAS,UAAU;AAC9C,aAAO;AAAA,QACL;AAAA,QACA,+BAA+B,YAAY,QAAQ,iDAAiD,SAAS,QAAQ;AAAA,QACrH;AAAA,UACE,MAAM;AAAA,YACJ,cAAc,YAAY;AAAA,YAC1B,kBAAkB,SAAS;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,QACE,YAAY,eACZ,SAAS,eACT,YAAY,gBAAgB,SAAS,aACrC;AACA,aAAO;AAAA,QACL;AAAA,QACA,kCAAkC,YAAY,WAAW,oDAAoD,SAAS,WAAW;AAAA,QACjI;AAAA,UACE,MAAM;AAAA,YACJ,iBAAiB,YAAY;AAAA,YAC7B,qBAAqB,SAAS;AAAA,UAChC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAc,aACZ,QACA,SACA,gBACe;AACf,UAAM,kBAAkB,2BAA2B;AAAA,MACjD,UAAU,QAAQ,KAAK,YAAY;AAAA,MACnC,aACE,QAAQ,KAAK,YAAY,eACzB,QAAQ,oBAAoB,eAC5B,QAAQ,KAAK,YAAY;AAAA,MAC3B,cAAc,QAAQ;AAAA,MACtB,kBAAkB;AAAA,MAClB,MAAM,CAAC;AAAA,IACT,CAAC;AACD,UAAM,YAAY,iBAAiB,gBAAgB,SAAS,gBAAgB;AAC5E,UAAM,KAAK,iBAAiB,QAAQ,SAAS;AAAA,EAC/C;AAAA,EAEA,MAAc,kBACZ,QACA,SACA,gBACA,oBACe;AACf,UAAM,kBAAkB,2BAA2B;AAAA,MACjD,gBAAgB,gBAAgB,YAAY;AAAA,MAC5C,mBAAmB,gBAAgB,eAAe;AAAA,MAClD,qBAAqB,QAAQ,KAAK,YAAY;AAAA,MAC9C,wBACE,QAAQ,KAAK,YAAY,eACzB,QAAQ,oBAAoB,eAC5B,QAAQ,KAAK,YAAY;AAAA,MAC3B,oBAAoB,gBAAgB,gBAAgB;AAAA,MACpD,mBAAmB,QAAQ;AAAA,MAC3B,YAAY;AAAA,IACd,CAAC;AACD,UAAM,KAAK,iBAAiB,QAAQ,eAAe;AAAA,EACrD;AAAA,EAEA,MAAc,YACZ,QACA,KACe;AACf,UAAM,OAAO,MAAM,8CAA8C,CAAC,GAAG,CAAC;AAAA,EACxE;AAAA,EAEA,MAAc,iBACZ,QACe;AACf,UAAM,OAAO,MAAM,OAAO;AAAA,EAC5B;AAAA,EAEA,MAAc,kBACZ,QACe;AACf,UAAM,OAAO,MAAM,QAAQ;AAAA,EAC7B;AAAA,EAEA,MAAc,oBACZ,QACe;AACf,UAAM,OAAO,MAAM,UAAU;AAAA,EAC/B;AAAA,EAEA,MAAc,iBACZ,QACA,WACe;AACf,QAAI,UAAU,OAAO,SAAS,GAAG;AAC/B,YAAM,OAAO,MAAM,UAAU,KAAK,UAAU,MAAM;AAClD;AAAA,IACF;AACA,UAAM,OAAO,MAAM,UAAU,GAAG;AAAA,EAClC;AACF;;;AF3iBA,IAAM,aAAa,cAAc,YAAY,GAAG;AAChD,IAAM,YAAY,QAAQ,UAAU;AAEpC,IAAM,wBAAwB,KAAK;AAAA,EACjC,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AACT,CAAC;AAED,IAAM,8BAA8B,KAAK;AAAA,EACvC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,YAAY,KAAK,EAAE,YAAY,KAAK,EAAE,eAAe,SAAS,CAAC,EAAE,CAAC;AAAA,EAClE,iBAAiB;AAAA,EACjB,UAAU,KAAK;AAAA,IACb,eAAe,KAAK;AAAA,MAClB,QAAQ;AAAA,IACV,CAAC;AAAA,IACD,mBAAmB,KAAK;AAAA,MACtB,QAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AAAA,EACD,eAAe;AACjB,CAAC;AAKD,SAAS,qBAA4C;AACnD,QAAM,eAAe,KAAK,WAAW,2BAA2B;AAChE,QAAM,eAAe,KAAK,MAAM,aAAa,cAAc,OAAO,CAAC;AAEnE,QAAM,SAAS,4BAA4B,YAAY;AACvD,MAAI,kBAAkB,KAAK,QAAQ;AACjC,UAAM,WAAW,OAAO,IAAI,CAAC,MAA2B,EAAE,OAAO,EAAE,KAAK,IAAI;AAC5E,UAAM,IAAI,MAAM,wCAAwC,YAAY,KAAK,QAAQ,EAAE;AAAA,EACrF;AAEA,SAAO;AACT;AAKA,IAAM,2BACJ;AAAA,EACE,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,IAAI;AAAA,EACJ,UAAU,mBAAmB;AAAA,EAC7B,SAAmD;AACjD,WAAO;AAAA,MACL,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA,cAAc,SAAmC;AAC/C,WAAO,+BAA+B;AAAA,EACxC;AAAA,EACA,aAAa,QAAQ;AACnB,WAAO,8BAA8B,MAAM;AAAA,EAC7C;AACF;AAEF,IAAO,kBAAQ;","names":[]}
package/package.json CHANGED
@@ -1,20 +1,27 @@
1
1
  {
2
2
  "name": "@prisma-next/target-postgres",
3
- "version": "0.1.0-pr.48.2",
3
+ "version": "0.1.0-pr.49.2",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Postgres target pack for Prisma Next",
7
7
  "dependencies": {
8
8
  "arktype": "^2.0.0",
9
- "@prisma-next/cli": "0.1.0-pr.48.2",
10
- "@prisma-next/contract": "0.1.0-pr.48.2",
11
- "@prisma-next/core-control-plane": "0.1.0-pr.48.2",
12
- "@prisma-next/core-execution-plane": "0.1.0-pr.48.2"
9
+ "@prisma-next/family-sql": "0.1.0-pr.49.2",
10
+ "@prisma-next/cli": "0.1.0-pr.49.2",
11
+ "@prisma-next/contract": "0.1.0-pr.49.2",
12
+ "@prisma-next/sql-contract": "0.1.0-pr.49.2",
13
+ "@prisma-next/sql-schema-ir": "0.1.0-pr.49.2",
14
+ "@prisma-next/core-control-plane": "0.1.0-pr.49.2",
15
+ "@prisma-next/core-execution-plane": "0.1.0-pr.49.2",
16
+ "@prisma-next/utils": "0.1.0-pr.49.2"
13
17
  },
14
18
  "devDependencies": {
19
+ "vite-tsconfig-paths": "^5.1.4",
15
20
  "tsup": "^8.3.0",
16
21
  "typescript": "^5.9.3",
17
22
  "vitest": "^2.1.1",
23
+ "@prisma-next/adapter-postgres": "0.1.0-pr.49.2",
24
+ "@prisma-next/driver-postgres": "0.1.0-pr.49.2",
18
25
  "@prisma-next/test-utils": "0.0.1"
19
26
  },
20
27
  "files": [