@prisma-next/target-sqlite 0.15.0 → 0.16.0-dev.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/dist/{codec-ids-BfPkjMmk.d.mts → codec-ids-Dof8fZfe.d.mts} +1 -2
- package/dist/codec-ids-Dof8fZfe.d.mts.map +1 -0
- package/dist/codec-ids.d.mts +1 -1
- package/dist/{codec-types-izdPhp_9.d.mts → codec-types-CcFkbJ3o.d.mts} +3 -4
- package/dist/codec-types-CcFkbJ3o.d.mts.map +1 -0
- package/dist/codec-types.d.mts +2 -2
- package/dist/{codecs-BGeJavlQ.d.mts → codecs-DGgo--O0.d.mts} +2 -3
- package/dist/codecs-DGgo--O0.d.mts.map +1 -0
- package/dist/codecs.d.mts +1 -1
- package/dist/contract-free.d.mts +1 -2
- package/dist/contract-free.d.mts.map +1 -1
- package/dist/control-tables.d.mts.map +1 -1
- package/dist/control.d.mts +0 -1
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +14 -14
- package/dist/control.mjs.map +1 -1
- package/dist/ddl.d.mts +1 -1
- package/dist/default-normalizer.d.mts +0 -1
- package/dist/default-normalizer.d.mts.map +1 -1
- package/dist/{descriptor-meta-D1fap-5t.mjs → descriptor-meta-BPrgV878.mjs} +12 -6
- package/dist/descriptor-meta-BPrgV878.mjs.map +1 -0
- package/dist/migration.d.mts +2 -3
- package/dist/migration.d.mts.map +1 -1
- package/dist/migration.mjs +2 -2
- package/dist/native-type-normalizer.d.mts.map +1 -1
- package/dist/{nodes-VzaaeUTb.d.mts → nodes-COZjF41I.d.mts} +1 -2
- package/dist/nodes-COZjF41I.d.mts.map +1 -0
- package/dist/{op-factory-call-Do03QgD9.mjs → op-factory-call-8pTnIHhR.mjs} +8 -8
- package/dist/op-factory-call-8pTnIHhR.mjs.map +1 -0
- package/dist/op-factory-call.d.mts +2 -3
- package/dist/op-factory-call.d.mts.map +1 -1
- package/dist/op-factory-call.mjs +1 -1
- package/dist/pack.d.mts +41 -2
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/{planner-D2hMk3oC.mjs → planner-D4B8Rugz.mjs} +17 -57
- package/dist/planner-D4B8Rugz.mjs.map +1 -0
- package/dist/{planner-produced-sqlite-migration-o1qUzwLk.d.mts → planner-produced-sqlite-migration-C9k0q8Il.d.mts} +2 -3
- package/dist/planner-produced-sqlite-migration-C9k0q8Il.d.mts.map +1 -0
- package/dist/{planner-produced-sqlite-migration-CeGjNfd2.mjs → planner-produced-sqlite-migration-hyDa7QK-.mjs} +2 -2
- package/dist/{planner-produced-sqlite-migration-CeGjNfd2.mjs.map → planner-produced-sqlite-migration-hyDa7QK-.mjs.map} +1 -1
- package/dist/planner-produced-sqlite-migration.d.mts +1 -1
- package/dist/planner-produced-sqlite-migration.mjs +1 -1
- package/dist/planner-target-details-xR6UfIcz.d.mts.map +1 -1
- package/dist/planner.d.mts +1 -2
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +1 -1
- package/dist/render-ops.d.mts +0 -1
- package/dist/render-ops.d.mts.map +1 -1
- package/dist/runtime.d.mts +1 -2
- package/dist/runtime.d.mts.map +1 -1
- package/dist/{shared-C6sM-wel.d.mts → shared-DLUM4Ae2.d.mts} +1 -3
- package/dist/shared-DLUM4Ae2.d.mts.map +1 -0
- package/dist/sql-utils.d.mts.map +1 -1
- package/dist/{sqlite-contract-view-J32K82Gi.d.mts → sqlite-contract-view-CMgE0L4W.d.mts} +4 -3
- package/dist/sqlite-contract-view-CMgE0L4W.d.mts.map +1 -0
- package/dist/{sqlite-migration-BYbzskpE.d.mts → sqlite-migration-BbSrmBAa.d.mts} +5 -6
- package/dist/sqlite-migration-BbSrmBAa.d.mts.map +1 -0
- package/dist/{sqlite-migration-C9bD6XDl.mjs → sqlite-migration-BcFf2OFa.mjs} +8 -8
- package/dist/sqlite-migration-BcFf2OFa.mjs.map +1 -0
- package/package.json +19 -19
- package/src/core/authoring.ts +11 -5
- package/src/core/errors.ts +12 -8
- package/src/core/migrations/issue-planner.ts +18 -62
- package/src/core/migrations/op-factory-call.ts +1 -1
- package/src/core/migrations/operations/shared.ts +3 -5
- package/src/core/migrations/operations/tables.ts +3 -2
- package/src/core/migrations/planner-strategies.ts +4 -3
- package/src/core/migrations/planner.ts +3 -2
- package/src/core/migrations/runner.ts +13 -12
- package/src/core/migrations/sqlite-migration.ts +2 -2
- package/dist/codec-ids-BfPkjMmk.d.mts.map +0 -1
- package/dist/codec-types-izdPhp_9.d.mts.map +0 -1
- package/dist/codecs-BGeJavlQ.d.mts.map +0 -1
- package/dist/descriptor-meta-D1fap-5t.mjs.map +0 -1
- package/dist/nodes-VzaaeUTb.d.mts.map +0 -1
- package/dist/op-factory-call-Do03QgD9.mjs.map +0 -1
- package/dist/planner-D2hMk3oC.mjs.map +0 -1
- package/dist/planner-produced-sqlite-migration-o1qUzwLk.d.mts.map +0 -1
- package/dist/shared-C6sM-wel.d.mts.map +0 -1
- package/dist/sqlite-contract-view-J32K82Gi.d.mts.map +0 -1
- package/dist/sqlite-migration-BYbzskpE.d.mts.map +0 -1
- package/dist/sqlite-migration-C9bD6XDl.mjs.map +0 -1
package/src/core/authoring.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { temporalAuthoringPresets } from '@prisma-next/family-sql/control';
|
|
1
|
+
import { temporalAuthoringPresets, temporalCodecPreset } from '@prisma-next/family-sql/control';
|
|
2
2
|
import type { AuthoringFieldNamespace } from '@prisma-next/framework-components/authoring';
|
|
3
3
|
|
|
4
4
|
export const sqliteAuthoringFieldPresets = {
|
|
5
|
-
temporal:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
temporal: {
|
|
6
|
+
.../* @__PURE__ */ temporalAuthoringPresets({
|
|
7
|
+
codecId: 'sqlite/datetime@1',
|
|
8
|
+
nativeType: 'text',
|
|
9
|
+
}),
|
|
10
|
+
datetime: /* @__PURE__ */ temporalCodecPreset({
|
|
11
|
+
codecId: 'sqlite/datetime@1',
|
|
12
|
+
nativeType: 'text',
|
|
13
|
+
}),
|
|
14
|
+
},
|
|
9
15
|
} as const satisfies AuthoringFieldNamespace;
|
package/src/core/errors.ts
CHANGED
|
@@ -12,8 +12,9 @@ import { CliStructuredError } from '@prisma-next/errors/control';
|
|
|
12
12
|
* The `operation` argument is required so every throw site names the operation
|
|
13
13
|
* that actually failed; a new operation cannot inherit a misattributed message.
|
|
14
14
|
*
|
|
15
|
-
* Distinct from `
|
|
16
|
-
* input is the stack itself, not the per-operation
|
|
15
|
+
* Distinct from `MIGRATION.UNFILLED_PLACEHOLDER` (placeholder not filled)
|
|
16
|
+
* because the missing input is the stack itself, not the per-operation
|
|
17
|
+
* contract.
|
|
17
18
|
*
|
|
18
19
|
* Lives in `@prisma-next/target-sqlite/errors` rather than the shared
|
|
19
20
|
* framework migration errors module because the failure is target-specific:
|
|
@@ -21,10 +22,13 @@ import { CliStructuredError } from '@prisma-next/errors/control';
|
|
|
21
22
|
* adapter, the SQLite-target stack) only exists in this package.
|
|
22
23
|
*/
|
|
23
24
|
export function errorSqliteMigrationStackMissing(operation: string): CliStructuredError {
|
|
24
|
-
return new CliStructuredError(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
return new CliStructuredError(
|
|
26
|
+
'MIGRATION.SQLITE_CONTROL_STACK_MISSING',
|
|
27
|
+
`SqliteMigration.${operation} requires a control adapter`,
|
|
28
|
+
{
|
|
29
|
+
why: `SqliteMigration.${operation} was invoked on an instance constructed without a ControlStack, so the stored controlAdapter is undefined and the operation cannot lower its DDL node.`,
|
|
30
|
+
fix: 'Construct the migration via the migration CLI entrypoint (which assembles a ControlStack from the loaded prisma-next.config.ts), or pass a ControlStack containing a SQLite adapter to the migration constructor in test fixtures.',
|
|
31
|
+
meta: { operation },
|
|
32
|
+
},
|
|
33
|
+
);
|
|
30
34
|
}
|
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
} from '@prisma-next/family-sql/control';
|
|
22
22
|
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
23
23
|
import type { SchemaDiffIssue } from '@prisma-next/framework-components/control';
|
|
24
|
+
import { issueOutcome, orderIssuesByDependencies } from '@prisma-next/framework-components/control';
|
|
24
25
|
import { defaultIndexName } from '@prisma-next/sql-schema-ir/naming';
|
|
25
26
|
import {
|
|
26
27
|
RelationalSchemaNodeKind,
|
|
@@ -63,51 +64,6 @@ import {
|
|
|
63
64
|
|
|
64
65
|
export type { CallMigrationStrategy, StrategyContext };
|
|
65
66
|
|
|
66
|
-
// ============================================================================
|
|
67
|
-
// Node-keyed issue ordering (dependency order)
|
|
68
|
-
// ============================================================================
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Re-keys the legacy `ISSUE_KIND_ORDER` (kind string → priority number) on
|
|
72
|
-
* `(nodeKind, reason)`. Numbers are preserved from the legacy table so the
|
|
73
|
-
* dependency intent stays legible; the final emission order is actually
|
|
74
|
-
* fixed downstream by category bucketing (create-table → add-column →
|
|
75
|
-
* create-index → recreate → drop-column → drop-index → drop-table), so this
|
|
76
|
-
* only breaks ties within a single bucket.
|
|
77
|
-
*/
|
|
78
|
-
export function nodeIssueOrder(issue: SchemaDiffIssue): number {
|
|
79
|
-
const node = issueNode(issue);
|
|
80
|
-
if (node === undefined) return 99;
|
|
81
|
-
switch (node.nodeKind) {
|
|
82
|
-
case RelationalSchemaNodeKind.foreignKey:
|
|
83
|
-
return issue.reason === 'not-expected' ? 10 : 60;
|
|
84
|
-
case RelationalSchemaNodeKind.unique:
|
|
85
|
-
return issue.reason === 'not-expected' ? 11 : 51;
|
|
86
|
-
case RelationalSchemaNodeKind.primaryKey:
|
|
87
|
-
return issue.reason === 'not-expected' ? 12 : 50;
|
|
88
|
-
case RelationalSchemaNodeKind.index:
|
|
89
|
-
return issue.reason === 'not-expected' ? 13 : 52;
|
|
90
|
-
case RelationalSchemaNodeKind.columnDefault:
|
|
91
|
-
if (issue.reason === 'not-expected') return 14;
|
|
92
|
-
return issue.reason === 'not-found' ? 42 : 43;
|
|
93
|
-
case RelationalSchemaNodeKind.column:
|
|
94
|
-
if (issue.reason === 'not-expected') return 15;
|
|
95
|
-
return issue.reason === 'not-found' ? 30 : 40;
|
|
96
|
-
case RelationalSchemaNodeKind.table:
|
|
97
|
-
return issue.reason === 'not-expected' ? 16 : 20;
|
|
98
|
-
case RelationalSchemaNodeKind.check:
|
|
99
|
-
if (issue.reason === 'not-found') return 53;
|
|
100
|
-
return issue.reason === 'not-expected' ? 54 : 55;
|
|
101
|
-
default:
|
|
102
|
-
return 99;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/** Deterministic tiebreak within an order bucket: the diff path itself already encodes table → child → grandchild. */
|
|
107
|
-
export function nodeIssueKey(issue: SchemaDiffIssue): string {
|
|
108
|
-
return issue.path.join(' ');
|
|
109
|
-
}
|
|
110
|
-
|
|
111
67
|
// ============================================================================
|
|
112
68
|
// Subtree coalescing — the planner's responsibility per the differ's contract
|
|
113
69
|
// ============================================================================
|
|
@@ -126,7 +82,9 @@ export function coalesceSubtreeIssues(
|
|
|
126
82
|
issues: readonly SchemaDiffIssue[],
|
|
127
83
|
): readonly SchemaDiffIssue[] {
|
|
128
84
|
const collapsingPaths = issues
|
|
129
|
-
.filter(
|
|
85
|
+
.filter(
|
|
86
|
+
(issue) => issueOutcome(issue) === 'not-found' || issueOutcome(issue) === 'not-expected',
|
|
87
|
+
)
|
|
130
88
|
.map((issue) => issue.path);
|
|
131
89
|
if (collapsingPaths.length === 0) return issues;
|
|
132
90
|
return issues.filter(
|
|
@@ -180,12 +138,11 @@ export function tableSpecFromNode(table: SqlTableIR): SqliteTableSpec {
|
|
|
180
138
|
...(u.name !== undefined ? { name: u.name } : {}),
|
|
181
139
|
}));
|
|
182
140
|
// Every FK node on the expected tree is constraint-bearing by construction
|
|
183
|
-
// (
|
|
184
|
-
//
|
|
141
|
+
// (a persisted `foreignKeys[]` entry is a constraint; a non-constraint FK
|
|
142
|
+
// contributes only a backing index, never an FK node).
|
|
185
143
|
const foreignKeys: SqliteForeignKeySpec[] = table.foreignKeys.map((fk) => ({
|
|
186
144
|
columns: fk.columns,
|
|
187
145
|
references: { table: fk.referencedTable, columns: fk.referencedColumns },
|
|
188
|
-
constraint: true,
|
|
189
146
|
...(fk.name !== undefined ? { name: fk.name } : {}),
|
|
190
147
|
...(fk.onDelete !== undefined ? { onDelete: fk.onDelete } : {}),
|
|
191
148
|
...(fk.onUpdate !== undefined ? { onUpdate: fk.onUpdate } : {}),
|
|
@@ -274,14 +231,14 @@ function buildCreateTableCalls(table: SqlTableIR): SqliteOpFactoryCall[] {
|
|
|
274
231
|
function mapTableIssue(
|
|
275
232
|
issue: SchemaDiffIssue,
|
|
276
233
|
): Result<readonly SqliteOpFactoryCall[], SqlPlannerConflict> {
|
|
277
|
-
if (issue
|
|
234
|
+
if (issueOutcome(issue) === 'not-found') {
|
|
278
235
|
const table = blindCast<
|
|
279
236
|
SqlTableIR,
|
|
280
237
|
'a not-found table issue always carries the expected table node'
|
|
281
238
|
>(issue.expected);
|
|
282
239
|
return ok(buildCreateTableCalls(table));
|
|
283
240
|
}
|
|
284
|
-
if (issue
|
|
241
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
285
242
|
const table = blindCast<
|
|
286
243
|
SqlTableIR,
|
|
287
244
|
'a not-expected table issue always carries the actual table node'
|
|
@@ -310,7 +267,7 @@ function mapColumnIssue(
|
|
|
310
267
|
),
|
|
311
268
|
);
|
|
312
269
|
}
|
|
313
|
-
if (issue
|
|
270
|
+
if (issueOutcome(issue) === 'not-found') {
|
|
314
271
|
const column = blindCast<
|
|
315
272
|
SqlColumnIR,
|
|
316
273
|
'a not-found column issue always carries the expected column node'
|
|
@@ -323,7 +280,7 @@ function mapColumnIssue(
|
|
|
323
280
|
const inline = table !== undefined && isInlineAutoincrementPrimaryKeyNode(table, column);
|
|
324
281
|
return ok([new AddColumnCall(tableName, columnSpecFromNode(column, inline))]);
|
|
325
282
|
}
|
|
326
|
-
if (issue
|
|
283
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
327
284
|
const column = blindCast<
|
|
328
285
|
SqlColumnIR,
|
|
329
286
|
'a not-expected column issue always carries the actual column node'
|
|
@@ -357,7 +314,7 @@ function mapIndexIssue(
|
|
|
357
314
|
),
|
|
358
315
|
);
|
|
359
316
|
}
|
|
360
|
-
if (issue
|
|
317
|
+
if (issueOutcome(issue) === 'not-found') {
|
|
361
318
|
const index = blindCast<
|
|
362
319
|
SqlIndexIR,
|
|
363
320
|
'a not-found index issue always carries the expected index node'
|
|
@@ -365,7 +322,7 @@ function mapIndexIssue(
|
|
|
365
322
|
const indexName = index.name ?? defaultIndexName(tableName, index.columns);
|
|
366
323
|
return ok([new CreateIndexCall(tableName, indexName, index.columns)]);
|
|
367
324
|
}
|
|
368
|
-
if (issue
|
|
325
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
369
326
|
const index = blindCast<
|
|
370
327
|
SqlIndexIR,
|
|
371
328
|
'a not-expected index issue always carries the actual index node'
|
|
@@ -505,13 +462,12 @@ export function planIssues(
|
|
|
505
462
|
}
|
|
506
463
|
}
|
|
507
464
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
});
|
|
465
|
+
// Dependency-graph order: a topological sort over the issues' `dependsOn`
|
|
466
|
+
// cross-links and containment edges (edge direction from the ordering law's
|
|
467
|
+
// presence rule), path-tiebroken for determinism. `classifyCall` bucketing
|
|
468
|
+
// downstream fixes the coarse create/recreate/drop sequence; this settles
|
|
469
|
+
// the order within each bucket.
|
|
470
|
+
const sorted = orderIssuesByDependencies(remaining);
|
|
515
471
|
|
|
516
472
|
const defaultCalls: SqliteOpFactoryCall[] = [];
|
|
517
473
|
const conflicts: SqlPlannerConflict[] = [];
|
|
@@ -563,7 +563,7 @@ export class DropIndexCall extends SqliteOpFactoryCallNode {
|
|
|
563
563
|
* any future strategy that needs a placeholder data step can construct one
|
|
564
564
|
* with its own id/label.
|
|
565
565
|
*
|
|
566
|
-
* `toOp()` always throws `
|
|
566
|
+
* `toOp()` always throws `MIGRATION.UNFILLED_PLACEHOLDER`: the planner cannot lower a stubbed
|
|
567
567
|
* transform to a runtime op — the user must edit the rendered
|
|
568
568
|
* `migration.ts` and re-emit.
|
|
569
569
|
*/
|
|
@@ -60,7 +60,6 @@ export interface SqliteForeignKeySpec {
|
|
|
60
60
|
readonly name?: string;
|
|
61
61
|
readonly onDelete?: ReferentialAction;
|
|
62
62
|
readonly onUpdate?: ReferentialAction;
|
|
63
|
-
readonly constraint: boolean;
|
|
64
63
|
}
|
|
65
64
|
|
|
66
65
|
/**
|
|
@@ -103,12 +102,11 @@ export function renderColumnDefinition(column: SqliteColumnSpec): string {
|
|
|
103
102
|
|
|
104
103
|
/**
|
|
105
104
|
* Renders an inline FOREIGN KEY constraint clause for a `CREATE TABLE`
|
|
106
|
-
* body.
|
|
107
|
-
*
|
|
108
|
-
*
|
|
105
|
+
* body. Every `SqliteForeignKeySpec` is constraint-bearing by construction
|
|
106
|
+
* (`tableSpecFromNode` only ever builds specs from schema-IR FK nodes, which
|
|
107
|
+
* are themselves constraint-only — a non-constraint FK contributes no node).
|
|
109
108
|
*/
|
|
110
109
|
export function renderForeignKeyClause(fk: SqliteForeignKeySpec): string {
|
|
111
|
-
if (!fk.constraint) return '';
|
|
112
110
|
const name = fk.name ? `CONSTRAINT ${quoteIdentifier(fk.name)} ` : '';
|
|
113
111
|
let sql = `${name}FOREIGN KEY (${fk.columns.map(quoteIdentifier).join(', ')}) REFERENCES ${quoteIdentifier(fk.references.table)} (${fk.references.columns.map(quoteIdentifier).join(', ')})`;
|
|
114
112
|
if (fk.onDelete !== undefined) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { MigrationOperationClass } from '@prisma-next/family-sql/control';
|
|
2
2
|
import type { ExecuteRequestLowerer } from '@prisma-next/family-sql/control-adapter';
|
|
3
3
|
import type { SchemaDiffIssue } from '@prisma-next/framework-components/control';
|
|
4
|
+
import { issueOutcome } from '@prisma-next/framework-components/control';
|
|
4
5
|
import { RelationalSchemaNodeKind, type SqlColumnIR } from '@prisma-next/sql-schema-ir/types';
|
|
5
6
|
import { blindCast } from '@prisma-next/utils/casts';
|
|
6
7
|
import { tableExistsAst } from '../../../contract-free/checks';
|
|
@@ -294,7 +295,7 @@ export function buildRecreatePostchecks(
|
|
|
294
295
|
|
|
295
296
|
for (const issue of issues) {
|
|
296
297
|
const nodeKind = nodeKindOf(issue);
|
|
297
|
-
if (nodeKind === RelationalSchemaNodeKind.column && issue
|
|
298
|
+
if (nodeKind === RelationalSchemaNodeKind.column && issueOutcome(issue) === 'not-equal') {
|
|
298
299
|
const columnName = columnNameFromNode(issue);
|
|
299
300
|
if (columnName === undefined) continue;
|
|
300
301
|
const c = escapeLiteral(columnName);
|
|
@@ -325,7 +326,7 @@ export function buildRecreatePostchecks(
|
|
|
325
326
|
const columnName = columnNameFromDefaultIssuePath(issue);
|
|
326
327
|
if (columnName === undefined) continue;
|
|
327
328
|
const c = escapeLiteral(columnName);
|
|
328
|
-
if (issue
|
|
329
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
329
330
|
checks.push({
|
|
330
331
|
description: `verify "${columnName}" has no default on "${tableName}"`,
|
|
331
332
|
sql: `SELECT COUNT(*) > 0 FROM pragma_table_info('${t}') WHERE name = '${c}' AND dflt_value IS NULL`,
|
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
} from '@prisma-next/family-sql/control';
|
|
20
20
|
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
21
21
|
import type { SchemaDiffIssue } from '@prisma-next/framework-components/control';
|
|
22
|
+
import { issueOutcome } from '@prisma-next/framework-components/control';
|
|
22
23
|
import { defaultIndexName } from '@prisma-next/sql-schema-ir/naming';
|
|
23
24
|
import {
|
|
24
25
|
RelationalSchemaNodeKind,
|
|
@@ -78,7 +79,7 @@ function classifyNodeIssue(issue: SchemaDiffIssue): 'widening' | 'destructive' |
|
|
|
78
79
|
>(node).nodeKind;
|
|
79
80
|
switch (nodeKind) {
|
|
80
81
|
case RelationalSchemaNodeKind.column: {
|
|
81
|
-
if (issue
|
|
82
|
+
if (issueOutcome(issue) !== 'not-equal') return null;
|
|
82
83
|
const expected = blindCast<SqlColumnIR, 'a not-equal column issue carries the expected node'>(
|
|
83
84
|
issue.expected,
|
|
84
85
|
);
|
|
@@ -91,7 +92,7 @@ function classifyNodeIssue(issue: SchemaDiffIssue): 'widening' | 'destructive' |
|
|
|
91
92
|
return expected.nullable ? 'widening' : 'destructive';
|
|
92
93
|
}
|
|
93
94
|
case RelationalSchemaNodeKind.columnDefault:
|
|
94
|
-
return issue
|
|
95
|
+
return issueOutcome(issue) === 'not-expected' ? 'destructive' : 'widening';
|
|
95
96
|
case RelationalSchemaNodeKind.primaryKey:
|
|
96
97
|
case RelationalSchemaNodeKind.foreignKey:
|
|
97
98
|
case RelationalSchemaNodeKind.unique:
|
|
@@ -206,7 +207,7 @@ export const nullabilityTighteningBackfillStrategy: CallMigrationStrategy = (iss
|
|
|
206
207
|
const calls: SqliteOpFactoryCall[] = [];
|
|
207
208
|
for (const issue of issues) {
|
|
208
209
|
if (
|
|
209
|
-
issue
|
|
210
|
+
issueOutcome(issue) !== 'not-equal' ||
|
|
210
211
|
issue.expected === undefined ||
|
|
211
212
|
issue.actual === undefined
|
|
212
213
|
) {
|
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
SchemaDiffIssue,
|
|
19
19
|
SchemaOwnership,
|
|
20
20
|
} from '@prisma-next/framework-components/control';
|
|
21
|
+
import { issueOutcome } from '@prisma-next/framework-components/control';
|
|
21
22
|
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
22
23
|
import { RelationalSchemaNodeKind, type SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
|
|
23
24
|
import { buildSqlitePlanDiff } from './diff-database-schema';
|
|
@@ -229,7 +230,7 @@ export class SqliteMigrationPlanner
|
|
|
229
230
|
});
|
|
230
231
|
const coalesced = coalesceSubtreeIssues(rawIssues);
|
|
231
232
|
const owned = retainUnownedExtras(coalesced, options.ownership);
|
|
232
|
-
const issues = strict ? owned : owned.filter((issue) => issue
|
|
233
|
+
const issues = strict ? owned : owned.filter((issue) => issueOutcome(issue) !== 'not-expected');
|
|
233
234
|
return { expected, actual, issues };
|
|
234
235
|
}
|
|
235
236
|
}
|
|
@@ -266,7 +267,7 @@ function retainUnownedExtras(
|
|
|
266
267
|
): readonly SchemaDiffIssue[] {
|
|
267
268
|
if (ownership === undefined) return issues;
|
|
268
269
|
return issues.filter((issue) => {
|
|
269
|
-
if (issue
|
|
270
|
+
if (issueOutcome(issue) !== 'not-expected') return true;
|
|
270
271
|
const node = issueNode(issue);
|
|
271
272
|
if (node === undefined || node.nodeKind !== RelationalSchemaNodeKind.table) return true;
|
|
272
273
|
const tableName = issue.path[1];
|
|
@@ -102,7 +102,7 @@ class SqliteMigrationRunner implements SqlMigrationRunner<SqlitePlanTargetDetail
|
|
|
102
102
|
frameworkComponents: options.frameworkComponents,
|
|
103
103
|
});
|
|
104
104
|
if (!schemaVerifyResult.ok) {
|
|
105
|
-
return runnerFailure('SCHEMA_VERIFY_FAILED', schemaVerifyResult.summary, {
|
|
105
|
+
return runnerFailure('MIGRATION.SCHEMA_VERIFY_FAILED', schemaVerifyResult.summary, {
|
|
106
106
|
why: 'The resulting database schema does not satisfy the destination contract.',
|
|
107
107
|
meta: { issues: schemaVerifyResult.schema.issues },
|
|
108
108
|
});
|
|
@@ -215,7 +215,7 @@ class SqliteMigrationRunner implements SqlMigrationRunner<SqlitePlanTargetDetail
|
|
|
215
215
|
return okVoid();
|
|
216
216
|
}
|
|
217
217
|
return runnerFailure(
|
|
218
|
-
'FOREIGN_KEY_VIOLATION',
|
|
218
|
+
'MIGRATION.FOREIGN_KEY_VIOLATION',
|
|
219
219
|
`Foreign key integrity check failed after migration: ${result.rows.length} violation(s).`,
|
|
220
220
|
{
|
|
221
221
|
why: 'PRAGMA foreign_key_check reported violations after applying recreate-table operations.',
|
|
@@ -326,7 +326,7 @@ class SqliteMigrationRunner implements SqlMigrationRunner<SqlitePlanTargetDetail
|
|
|
326
326
|
return okVoid();
|
|
327
327
|
}
|
|
328
328
|
return runnerFailure(
|
|
329
|
-
'LEGACY_MARKER_SHAPE',
|
|
329
|
+
'MIGRATION.LEGACY_MARKER_SHAPE',
|
|
330
330
|
`Legacy marker-table shape detected on ${MARKER_TABLE_NAME} (no \`space\` column). ` +
|
|
331
331
|
'Prisma Next is in pre-1.0; the previous transitional auto-migration to the per-space-row schema has been removed. ' +
|
|
332
332
|
`Drop \`${MARKER_TABLE_NAME}\` and re-run \`dbInit\` to reinitialise from a clean baseline.`,
|
|
@@ -348,7 +348,8 @@ class SqliteMigrationRunner implements SqlMigrationRunner<SqlitePlanTargetDetail
|
|
|
348
348
|
for (const step of steps) {
|
|
349
349
|
const result = await driver.query(step.sql, step.params ?? []);
|
|
350
350
|
if (!this.stepResultIsTrue(result.rows)) {
|
|
351
|
-
const code =
|
|
351
|
+
const code =
|
|
352
|
+
phase === 'precheck' ? 'MIGRATION.PRECHECK_FAILED' : 'MIGRATION.POSTCHECK_FAILED';
|
|
352
353
|
return runnerFailure(
|
|
353
354
|
code,
|
|
354
355
|
`Operation ${operation.id} failed during ${phase}: ${step.description}`,
|
|
@@ -376,7 +377,7 @@ class SqliteMigrationRunner implements SqlMigrationRunner<SqlitePlanTargetDetail
|
|
|
376
377
|
} catch (error: unknown) {
|
|
377
378
|
const message = error instanceof Error ? error.message : String(error);
|
|
378
379
|
return runnerFailure(
|
|
379
|
-
'EXECUTION_FAILED',
|
|
380
|
+
'MIGRATION.EXECUTION_FAILED',
|
|
380
381
|
`Operation ${operation.id} failed during execution: ${step.description}`,
|
|
381
382
|
{
|
|
382
383
|
why: message,
|
|
@@ -468,7 +469,7 @@ class SqliteMigrationRunner implements SqlMigrationRunner<SqlitePlanTargetDetail
|
|
|
468
469
|
for (const operation of operations) {
|
|
469
470
|
if (!allowedClasses.has(operation.operationClass)) {
|
|
470
471
|
return runnerFailure(
|
|
471
|
-
'POLICY_VIOLATION',
|
|
472
|
+
'MIGRATION.POLICY_VIOLATION',
|
|
472
473
|
`Operation ${operation.id} has class "${operation.operationClass}" which is not allowed by policy.`,
|
|
473
474
|
{
|
|
474
475
|
why: `Policy only allows: ${policy.allowedOperationClasses.join(', ')}.`,
|
|
@@ -494,14 +495,14 @@ class SqliteMigrationRunner implements SqlMigrationRunner<SqlitePlanTargetDetail
|
|
|
494
495
|
}
|
|
495
496
|
if (!marker) {
|
|
496
497
|
return runnerFailure(
|
|
497
|
-
'MARKER_ORIGIN_MISMATCH',
|
|
498
|
+
'MIGRATION.MARKER_ORIGIN_MISMATCH',
|
|
498
499
|
`Missing contract marker: expected origin storage hash ${origin.storageHash}.`,
|
|
499
500
|
{ meta: { expectedOriginStorageHash: origin.storageHash } },
|
|
500
501
|
);
|
|
501
502
|
}
|
|
502
503
|
if (marker.storageHash !== origin.storageHash) {
|
|
503
504
|
return runnerFailure(
|
|
504
|
-
'MARKER_ORIGIN_MISMATCH',
|
|
505
|
+
'MIGRATION.MARKER_ORIGIN_MISMATCH',
|
|
505
506
|
`Existing contract marker (${marker.storageHash}) does not match plan origin (${origin.storageHash}).`,
|
|
506
507
|
{
|
|
507
508
|
meta: {
|
|
@@ -513,7 +514,7 @@ class SqliteMigrationRunner implements SqlMigrationRunner<SqlitePlanTargetDetail
|
|
|
513
514
|
}
|
|
514
515
|
if (origin.profileHash && marker.profileHash !== origin.profileHash) {
|
|
515
516
|
return runnerFailure(
|
|
516
|
-
'MARKER_ORIGIN_MISMATCH',
|
|
517
|
+
'MIGRATION.MARKER_ORIGIN_MISMATCH',
|
|
517
518
|
`Existing contract marker profile hash (${marker.profileHash}) does not match plan origin profile hash (${origin.profileHash}).`,
|
|
518
519
|
{
|
|
519
520
|
meta: {
|
|
@@ -532,7 +533,7 @@ class SqliteMigrationRunner implements SqlMigrationRunner<SqlitePlanTargetDetail
|
|
|
532
533
|
): Result<void, SqlMigrationRunnerFailure> {
|
|
533
534
|
if (destination.storageHash !== contract.storage.storageHash) {
|
|
534
535
|
return runnerFailure(
|
|
535
|
-
'DESTINATION_CONTRACT_MISMATCH',
|
|
536
|
+
'MIGRATION.DESTINATION_CONTRACT_MISMATCH',
|
|
536
537
|
`Plan destination storage hash (${destination.storageHash}) does not match provided contract storage hash (${contract.storage.storageHash}).`,
|
|
537
538
|
{
|
|
538
539
|
meta: {
|
|
@@ -548,7 +549,7 @@ class SqliteMigrationRunner implements SqlMigrationRunner<SqlitePlanTargetDetail
|
|
|
548
549
|
destination.profileHash !== contract.profileHash
|
|
549
550
|
) {
|
|
550
551
|
return runnerFailure(
|
|
551
|
-
'DESTINATION_CONTRACT_MISMATCH',
|
|
552
|
+
'MIGRATION.DESTINATION_CONTRACT_MISMATCH',
|
|
552
553
|
`Plan destination profile hash (${destination.profileHash}) does not match provided contract profile hash (${contract.profileHash}).`,
|
|
553
554
|
{
|
|
554
555
|
meta: {
|
|
@@ -591,7 +592,7 @@ class SqliteMigrationRunner implements SqlMigrationRunner<SqlitePlanTargetDetail
|
|
|
591
592
|
});
|
|
592
593
|
if (!updated) {
|
|
593
594
|
return runnerFailure(
|
|
594
|
-
'MARKER_CAS_FAILURE',
|
|
595
|
+
'MIGRATION.MARKER_CAS_FAILURE',
|
|
595
596
|
'Marker was modified by another process during migration execution.',
|
|
596
597
|
{
|
|
597
598
|
meta: {
|
|
@@ -57,7 +57,7 @@ export abstract class SqliteMigration<
|
|
|
57
57
|
* Materialized SQLite control adapter, created once per migration
|
|
58
58
|
* instance from the injected stack. `undefined` only when the migration
|
|
59
59
|
* was instantiated without a stack (test fixtures); `controlAdapterFor`
|
|
60
|
-
* throws a
|
|
60
|
+
* throws a MIGRATION.SQLITE_CONTROL_STACK_MISSING in that case to surface the misuse.
|
|
61
61
|
*/
|
|
62
62
|
protected readonly controlAdapter: SqlControlAdapter<'sqlite'> | undefined;
|
|
63
63
|
|
|
@@ -81,7 +81,7 @@ export abstract class SqliteMigration<
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* Returns the materialized control adapter, or throws a
|
|
84
|
+
* Returns the materialized control adapter, or throws a MIGRATION.SQLITE_CONTROL_STACK_MISSING naming
|
|
85
85
|
* `operation` when the migration was constructed without a `ControlStack`.
|
|
86
86
|
* Single home for the null-check that every DDL/DML method shares.
|
|
87
87
|
*/
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codec-ids-BfPkjMmk.d.mts","names":[],"sources":["../src/core/codec-ids.ts"],"mappings":";;;cAMa,oBAAA;AAAA,cACA,uBAAA;AAAA,cACA,oBAAA;AAAA,cACA,oBAAA;AAAA,cACA,wBAAA;AAAA,cACA,oBAAA;AAAA,cACA,sBAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codec-types-izdPhp_9.d.mts","names":[],"sources":["../src/exports/codec-types.ts"],"mappings":";;;;cAwBM,kBAAA;EAAA;;;;iBAYI,oBAAA;EAAA;;;;;;;KAEL,OAAA,6BAAoC,CAAA,0BAA2B,CAAA,CAAE,CAAA,IAAK,CAAA,CAAE,CAAA,EAAG,CAAA;AAAA,KAEpE,UAAA,GAAa,OAAA,CAAQ,iBAAA,QAAyB,kBAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codecs-BGeJavlQ.d.mts","names":[],"sources":["../src/core/codec-helpers.ts","../src/core/codecs.ts","../src/core/registry.ts"],"mappings":";;;;;;;;;KAIY,WAAA;EAAA,UAKI,GAAA,WAAc,WAAA;AAAA,aACjB,WAAS;;;cC+BT,eAAA,SAAwB,SAAA,QAC5B,oBAAA;EAKD,MAAA,CAAO,KAAA,UAAe,IAAA,EAAM,gBAAA,GAAmB,OAAA;EAG/C,MAAA,CAAO,IAAA,UAAc,IAAA,EAAM,gBAAA,GAAmB,OAAA;EAGpD,UAAA,CAAW,KAAA,WAAgB,SAAA;EAG3B,UAAA,CAAW,IAAA,EAAM,SAAA;AAAA;AAAA,cAKN,oBAAA,SAA6B,mBAAA;EAAA,SACtB,OAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,YAAA,kCAAY,gBAAA;EACrB,OAAA,KAAY,GAAA,EAAK,oBAAA,KAAyB,eAAA;AAAA;AAAA,cAOxC,gBAAA,0DAAgB,UAAA,CAAA,eAAA;AAAA,cAMhB,kBAAA,SAA2B,SAAA,QAC/B,uBAAA;EAKD,MAAA,CAAO,KAAA,UAAe,IAAA,EAAM,gBAAA,GAAmB,OAAA;EAG/C,MAAA,CAAO,IAAA,UAAc,IAAA,EAAM,gBAAA,GAAmB,OAAA;EAGpD,UAAA,CAAW,KAAA,WAAgB,SAAA;EAG3B,UAAA,CAAW,IAAA,EAAM,SAAA;AAAA;AAAA,cAKN,uBAAA,SAAgC,mBAAA;EAAA,SACzB,OAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,YAAA,kCAAY,gBAAA;EACrB,OAAA,KAAY,GAAA,EAAK,oBAAA,KAAyB,kBAAA;AAAA;AAAA,cAOxC,mBAAA,0DAAmB,UAAA,CAAA,kBAAA;AAAA,cAMnB,eAAA,SAAwB,SAAA,QAC5B,oBAAA;EAKD,MAAA,CAAO,KAAA,UAAe,IAAA,EAAM,gBAAA,GAAmB,OAAA;EAG/C,MAAA,CAAO,IAAA,UAAc,IAAA,EAAM,gBAAA,GAAmB,OAAA;EAGpD,UAAA,CAAW,KAAA,WAAgB,SAAA;EAG3B,UAAA,CAAW,IAAA,EAAM,SAAA;AAAA;AAAA,cAKN,oBAAA,SAA6B,mBAAA;EAAA,SACtB,OAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,YAAA,kCAAY,gBAAA;EACrB,OAAA,KAAY,GAAA,EAAK,oBAAA,KAAyB,eAAA;AAAA;AAAA,cAOxC,gBAAA,0DAAgB,UAAA,CAAA,eAAA;AAAA,cAMhB,eAAA,SAAwB,SAAA,QAC5B,oBAAA,yBAEP,UAAA,EACA,UAAA;EAEM,MAAA,CAAO,KAAA,EAAO,UAAA,EAAY,IAAA,EAAM,gBAAA,GAAmB,OAAA,CAAQ,UAAA;EAG3D,MAAA,CAAO,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,gBAAA,GAAmB,OAAA,CAAQ,UAAA;EAGhE,UAAA,CAAW,KAAA,EAAO,UAAA,GAAa,SAAA;EAG/B,UAAA,CAAW,IAAA,EAAM,SAAA,GAAY,UAAA;AAAA;AAAA,cAQlB,oBAAA,SAA6B,mBAAA;EAAA,SACtB,OAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,YAAA,kCAAY,gBAAA;EACrB,OAAA,KAAY,GAAA,EAAK,oBAAA,KAAyB,eAAA;AAAA;AAAA,cAOxC,gBAAA,0DAAgB,UAAA,CAAA,eAAA;AAAA,cAMhB,mBAAA,SAA4B,SAAA,QAChC,wBAAA,0CAGP,IAAA;EAAA,QAGQ,SAAA;EAOF,MAAA,CAAO,KAAA,EAAO,IAAA,EAAM,IAAA,EAAM,gBAAA,GAAmB,OAAA;EAG7C,MAAA,CAAO,IAAA,UAAc,IAAA,EAAM,gBAAA,GAAmB,OAAA,CAAQ,IAAA;EAG5D,UAAA,CAAW,KAAA,EAAO,IAAA,GAAO,SAAA;EAGzB,UAAA,CAAW,IAAA,EAAM,SAAA,GAAY,IAAA;AAAA;AAAA,cAQlB,wBAAA,SAAiC,mBAAA;EAAA,SAC1B,OAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,YAAA,kCAAY,gBAAA;EACrB,OAAA,KAAY,GAAA,EAAK,oBAAA,KAAyB,mBAAA;AAAA;AAAA,cAOxC,oBAAA,0DAAoB,UAAA,CAAA,mBAAA;AAAA,cAMpB,eAAA,SAAwB,SAAA,QAC5B,oBAAA,kCAEE,SAAA,EACT,SAAA;EAEM,MAAA,CAAO,KAAA,EAAO,SAAA,EAAW,IAAA,EAAM,gBAAA,GAAmB,OAAA;EAGlD,MAAA,CAAO,IAAA,WAAe,SAAA,EAAW,IAAA,EAAM,gBAAA,GAAmB,OAAA,CAAQ,SAAA;EAGxE,UAAA,CAAW,KAAA,EAAO,SAAA,GAAY,SAAA;EAG9B,UAAA,CAAW,IAAA,EAAM,SAAA,GAAY,SAAA;AAAA;AAAA,cAKlB,oBAAA,SAA6B,mBAAA;EAAA,SACtB,OAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,YAAA,kCAAY,gBAAA;EACrB,OAAA,KAAY,GAAA,EAAK,oBAAA,KAAyB,eAAA;AAAA;AAAA,cAOxC,gBAAA,0DAAgB,UAAA,CAAA,eAAA;AAAA,cAMhB,iBAAA,SAA0B,SAAA,QAC9B,sBAAA;EAKD,MAAA,CAAO,KAAA,UAAe,IAAA,EAAM,gBAAA,GAAmB,OAAA;EAG/C,MAAA,CAAO,IAAA,mBAAuB,IAAA,EAAM,gBAAA,GAAmB,OAAA;EAG7D,UAAA,CAAW,KAAA,WAAgB,SAAA;EAO3B,UAAA,CAAW,IAAA,EAAM,SAAA;AAAA;AAAA,cAWN,sBAAA,SAA+B,mBAAA;EAAA,SACxB,OAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,YAAA,kCAAY,gBAAA;EACrB,OAAA,KAAY,GAAA,EAAK,oBAAA,KAAyB,iBAAA;AAAA;AAAA,cAOxC,kBAAA,0DAAkB,UAAA,CAAA,iBAAA;;;;;;;;cC5TlB,mBAAA,EAAqB,uBACc"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"descriptor-meta-D1fap-5t.mjs","names":[],"sources":["../src/core/authoring.ts","../src/core/descriptor-meta.ts"],"sourcesContent":["import { temporalAuthoringPresets } from '@prisma-next/family-sql/control';\nimport type { AuthoringFieldNamespace } from '@prisma-next/framework-components/authoring';\n\nexport const sqliteAuthoringFieldPresets = {\n temporal: /* @__PURE__ */ temporalAuthoringPresets({\n codecId: 'sqlite/datetime@1',\n nativeType: 'text',\n }),\n} as const satisfies AuthoringFieldNamespace;\n","import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { CodecTypes } from '../exports/codec-types';\nimport { sqliteAuthoringFieldPresets } from './authoring';\nimport { sqliteTargetDescriptorMetaRuntime } from './descriptor-meta-runtime';\n\nconst sqliteTargetDescriptorMetaBase = {\n ...sqliteTargetDescriptorMetaRuntime,\n defaultNamespaceId: UNBOUND_NAMESPACE_ID,\n authoring: {\n field: sqliteAuthoringFieldPresets,\n },\n} as const;\n\nexport const sqliteTargetDescriptorMeta: typeof sqliteTargetDescriptorMetaBase & {\n readonly __codecTypes?: CodecTypes;\n} = sqliteTargetDescriptorMetaBase;\n"],"mappings":";;;;AAGA,MAAa,8BAA8B,EACzC,UAA0B,yCAAyB;CACjD,SAAS;CACT,YAAY;AACd,CAAC,EACH;ACKA,MAAa,6BAET;CATF,GAAG;CACH,oBAAoB;CACpB,WAAW,EACT,OAAO,4BACT;AAKE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nodes-VzaaeUTb.d.mts","names":[],"sources":["../src/core/ddl/nodes.ts"],"mappings":";;;UAMiB,gBAAA;EACf,WAAA,CAAY,IAAA,EAAM,iBAAA,GAAoB,CAAC;AAAA;AAAA,uBAGnB,aAAA,SAAsB,OAAA;EAAA,SACjC,MAAA,IAAU,OAAA,EAAS,gBAAA,CAAiB,CAAA,IAAK,CAAA;AAAA;AAAA,cAavC,iBAAA,SAA0B,aAAA;EAAA,SAC5B,IAAA;EAAA,SACA,KAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,OAAA,EAAS,aAAA,CAAc,SAAA;EAAA,SACvB,WAAA,EAAa,aAAA,CAAc,kBAAA;cAExB,OAAA;IAAA,SACD,KAAA;IAAA,SACA,MAAA;IAAA,SACA,WAAA;IAAA,SACA,OAAA,WAAkB,SAAA;IAAA,SAClB,WAAA,YAAuB,kBAAA;EAAA;EAWzB,MAAA,IAAU,OAAA,EAAS,gBAAA,CAAiB,CAAA,IAAK,CAAA;AAAA;AAAA,KAKxC,gBAAA,GAAmB,iBAAiB"}
|