@dbsp/types 4.0.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{adapter-B057_WKR.d.ts → adapter-DXjfHEAf.d.ts} +39 -23
- package/dist/adapter-sdk.d.ts +1 -1
- package/dist/{chunk-CKQRFBMA.js → chunk-X5OQYLAK.js} +106 -1
- package/dist/chunk-X5OQYLAK.js.map +1 -0
- package/dist/index.d.ts +56 -4
- package/dist/index.js +7 -1
- package/dist/internal.d.ts +3 -3
- package/dist/internal.js +7 -1
- package/dist/internal.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-CKQRFBMA.js.map +0 -1
|
@@ -202,6 +202,10 @@ interface ColumnIR {
|
|
|
202
202
|
* Foreign key constraint
|
|
203
203
|
*/
|
|
204
204
|
interface ForeignKeyIR {
|
|
205
|
+
/** Physical PostgreSQL constraint name when the model has been physicalized. */
|
|
206
|
+
readonly name?: string;
|
|
207
|
+
/** Physical PostgreSQL name of the automatic single-column FK index. */
|
|
208
|
+
readonly autoIndexName?: string;
|
|
205
209
|
/** Local columns that form the FK */
|
|
206
210
|
readonly columns: readonly string[];
|
|
207
211
|
/** Referenced table and columns; schema is the referenced table's schema and defaults to the FK's own/migration schema when absent */
|
|
@@ -231,6 +235,8 @@ interface ForeignKeyIR {
|
|
|
231
235
|
interface SequenceIR {
|
|
232
236
|
/** Sequence name */
|
|
233
237
|
readonly name: string;
|
|
238
|
+
/** Explicitly bring this existing standalone sequence under managed state. Adoption is never inferred. */
|
|
239
|
+
readonly adopt?: true;
|
|
234
240
|
/** Start value */
|
|
235
241
|
readonly startWith?: number | string;
|
|
236
242
|
/** Increment step */
|
|
@@ -245,7 +251,13 @@ interface SequenceIR {
|
|
|
245
251
|
readonly schema?: string;
|
|
246
252
|
}
|
|
247
253
|
interface EnumIR {
|
|
248
|
-
/**
|
|
254
|
+
/**
|
|
255
|
+
* Raw PostgreSQL catalog type name (`pg_type.typname`): no identifier
|
|
256
|
+
* quotes, schema, modifiers or array suffix. It is physical: `dbCasing`
|
|
257
|
+
* never maps it. A column refers to it through the rendered spelling in
|
|
258
|
+
* `originalDbType` (`status`, `"Status"`, `status[]`), with the schema in
|
|
259
|
+
* `originalDbTypeSchema`. Its `ModelIR.enums` key must be this same string.
|
|
260
|
+
*/
|
|
249
261
|
readonly name: string;
|
|
250
262
|
/** Ordered list of enum values */
|
|
251
263
|
readonly values: readonly string[];
|
|
@@ -254,6 +266,7 @@ interface EnumIR {
|
|
|
254
266
|
}
|
|
255
267
|
interface RequiredEnumLabelIR {
|
|
256
268
|
readonly schema?: string;
|
|
269
|
+
/** Physical enum type name, as in `EnumIR.name`; `dbCasing` never maps it. */
|
|
257
270
|
readonly type: string;
|
|
258
271
|
readonly label: string;
|
|
259
272
|
}
|
|
@@ -368,6 +381,8 @@ interface TableIR {
|
|
|
368
381
|
readonly columns: readonly ColumnIR[];
|
|
369
382
|
/** Primary key (single column or composite); omitted for junction tables without explicit PK */
|
|
370
383
|
readonly primaryKey?: string | readonly string[];
|
|
384
|
+
/** Physical PostgreSQL primary-key constraint name when known. */
|
|
385
|
+
readonly primaryKeyName?: string;
|
|
371
386
|
/** Foreign key constraints */
|
|
372
387
|
readonly foreignKeys: readonly ForeignKeyIR[];
|
|
373
388
|
/** Index definitions */
|
|
@@ -481,7 +496,10 @@ interface ModelIR {
|
|
|
481
496
|
readonly externalTables?: ReadonlySet<string>;
|
|
482
497
|
/** Relation definitions indexed by "source.name" */
|
|
483
498
|
readonly relations: ReadonlyMap<string, RelationIR>;
|
|
484
|
-
/**
|
|
499
|
+
/**
|
|
500
|
+
* ENUM type definitions keyed by `EnumIR.name`, the physical type name. A key
|
|
501
|
+
* that differs from its value's `name` is refused wherever enums are handled.
|
|
502
|
+
*/
|
|
485
503
|
readonly enums?: ReadonlyMap<string, EnumIR>;
|
|
486
504
|
/** Extension names to ensure (CREATE EXTENSION IF NOT EXISTS) */
|
|
487
505
|
readonly extensions?: readonly string[];
|
|
@@ -1271,11 +1289,20 @@ interface ColumnAliasIntent {
|
|
|
1271
1289
|
}
|
|
1272
1290
|
/**
|
|
1273
1291
|
* Relation column expression: select a column from a related table
|
|
1274
|
-
*
|
|
1275
|
-
*
|
|
1276
|
-
*
|
|
1277
|
-
*
|
|
1278
|
-
*
|
|
1292
|
+
* The query must already emit the named relation's JOIN, through `.join()` or
|
|
1293
|
+
* an include with an explicit outer join. Without one, compilation reports
|
|
1294
|
+
* `relation column "<relation>"."<column>" has no emitted alias in this query`.
|
|
1295
|
+
* A bare include aggregates the relation instead, and the column lands inside
|
|
1296
|
+
* `<relation>_json` rather than under its own alias (#793).
|
|
1297
|
+
* @example orm.select('products').join('category').columns([
|
|
1298
|
+
* relationColumn('category', 'name', 'categoryName'),
|
|
1299
|
+
* ])
|
|
1300
|
+
* @example orm.select('products').include('category', { join: 'left' }).columns([
|
|
1301
|
+
* relationColumn('category', 'name', 'categoryName'),
|
|
1302
|
+
* ])
|
|
1303
|
+
*
|
|
1304
|
+
* Deriving a join would choose join type, null behavior, and row multiplication
|
|
1305
|
+
* on the caller's behalf; that is a separate feature.
|
|
1279
1306
|
*/
|
|
1280
1307
|
interface RelationColumnIntent {
|
|
1281
1308
|
readonly kind: 'relationColumn';
|
|
@@ -2604,6 +2631,8 @@ type OutputReadHandling = {
|
|
|
2604
2631
|
readonly table: string;
|
|
2605
2632
|
readonly column: string;
|
|
2606
2633
|
readonly js: ColumnJsReadType;
|
|
2634
|
+
/** Emitted nested JSON key; absent metadata keeps legacy column lookup. */
|
|
2635
|
+
readonly outputKey?: string;
|
|
2607
2636
|
} | {
|
|
2608
2637
|
readonly kind: 'none';
|
|
2609
2638
|
};
|
|
@@ -3462,25 +3491,12 @@ interface TableDDLGeneratorAdapter {
|
|
|
3462
3491
|
*/
|
|
3463
3492
|
storageSize?(table: string, schema?: string): Promise<number>;
|
|
3464
3493
|
}
|
|
3465
|
-
/**
|
|
3466
|
-
* DDL-generating adapter - can generate DDL (CREATE TABLE statements) from a schema.
|
|
3467
|
-
*/
|
|
3468
|
-
interface DDLGeneratingAdapter extends BaseAdapter {
|
|
3469
|
-
/**
|
|
3470
|
-
* Generate DDL statements from a schema.
|
|
3471
|
-
*
|
|
3472
|
-
* @param schema - The ModelIR schema to generate DDL from
|
|
3473
|
-
* @param options - Optional adapter-specific options (e.g., includeDropStatements)
|
|
3474
|
-
* @returns Array of DDL statements (CREATE TABLE, CREATE INDEX, etc.)
|
|
3475
|
-
*/
|
|
3476
|
-
generateDDL(schema: ModelIR, options?: Record<string, unknown>): string[];
|
|
3477
|
-
}
|
|
3478
3494
|
/**
|
|
3479
3495
|
* Database adapter interface - full adapter with all capabilities.
|
|
3480
3496
|
*
|
|
3481
3497
|
* @typeParam DB - Database schema type for type inference
|
|
3482
3498
|
*/
|
|
3483
|
-
interface Adapter<DB = unknown> extends CompilingAdapter, ExecutingAdapter, StreamingAdapter, IntrospectingAdapter, TransactionalAdapter<DB>, RawSqlAdapter,
|
|
3499
|
+
interface Adapter<DB = unknown> extends CompilingAdapter, ExecutingAdapter, StreamingAdapter, IntrospectingAdapter, TransactionalAdapter<DB>, RawSqlAdapter, TableDDLGeneratorAdapter {
|
|
3484
3500
|
/**
|
|
3485
3501
|
* Naming convention used by this adapter.
|
|
3486
3502
|
*
|
|
@@ -3499,7 +3515,7 @@ interface Adapter<DB = unknown> extends CompilingAdapter, ExecutingAdapter, Stre
|
|
|
3499
3515
|
* @deprecated Existing `CompileOnlyAdapter` annotations remain valid. Use
|
|
3500
3516
|
* `Adapter` when direct execution calls are needed.
|
|
3501
3517
|
*/
|
|
3502
|
-
type CompileOnlyAdapter<DB = unknown> = CompilingAdapter &
|
|
3518
|
+
type CompileOnlyAdapter<DB = unknown> = CompilingAdapter & TableDDLGeneratorAdapter & {
|
|
3503
3519
|
/** Naming convention used by this adapter. */
|
|
3504
3520
|
readonly dbCasing: DbCasing;
|
|
3505
3521
|
/** Create a schema-scoped compile-only adapter. */
|
|
@@ -3581,4 +3597,4 @@ interface TranslationContext {
|
|
|
3581
3597
|
readonly dialectCapabilities: DialectCapabilities;
|
|
3582
3598
|
}
|
|
3583
3599
|
|
|
3584
|
-
export { type CustomOpExpressionIntent as $, type Adapter as A, type BaseAdapter as B, type CompiledQuery as C, type CastExpressionIntent as D, type CheckConstraintIR as E, type CoalesceExpressionIntent as F, type ColumnAliasIntent as G, type ColumnExpressionIntent as H, type ColumnIR as I, type ColumnJsReadType as J, type ColumnListInput as K, type ColumnType as L, type CommonColumnType as M, type NqlBindingRelationType as N, type ComparisonExpressionIntent as O, type PlanReport as P, type ComparisonOperator as Q, type CompileOnlyAdapter as R, type CompileOptions as S, type CompileOptionsBase as T, type CompileResultWithIncludes as U, type CompiledNqlQuery as V, type CompilingAdapter as W, type ConnectionAvailability as X, type CreateIndexOptions as Y, type CteQueryIntent as Z, type CustomFnExpressionIntent as _, type CompiledColumnMetadata as a, type
|
|
3600
|
+
export { type CustomOpExpressionIntent as $, type Adapter as A, type BaseAdapter as B, type CompiledQuery as C, type CastExpressionIntent as D, type CheckConstraintIR as E, type CoalesceExpressionIntent as F, type ColumnAliasIntent as G, type ColumnExpressionIntent as H, type ColumnIR as I, type ColumnJsReadType as J, type ColumnListInput as K, type ColumnType as L, type CommonColumnType as M, type NqlBindingRelationType as N, type ComparisonExpressionIntent as O, type PlanReport as P, type ComparisonOperator as Q, type CompileOnlyAdapter as R, type CompileOptions as S, type CompileOptionsBase as T, type CompileResultWithIncludes as U, type CompiledNqlQuery as V, type CompilingAdapter as W, type ConnectionAvailability as X, type CreateIndexOptions as Y, type CteQueryIntent as Z, type CustomFnExpressionIntent as _, type CompiledColumnMetadata as a, type NqlBindingColumnTypeInfo as a$, type CustomTraversal as a0, type DDLFeature as a1, type DDLFeatureElementMap as a2, type DDLFeatureVersionRange as a3, type DbCasing as a4, type DecisionType as a5, type DeleteIntent as a6, type DialectCapabilities as a7, type DialectName as a8, type DiffSummary as a9, type InsertIntent as aA, type IntrospectingAdapter as aB, type IntrospectionOptions as aC, type IntrospectionResult as aD, type IsTypeSupported as aE, type JoinDefault as aF, type JoinIntent as aG, type JsonAggOrderByEntry as aH, type JsonContainsIntent as aI, type JsonExistsIntent as aJ, type JsonExtractIntent as aK, type JsonPathExtractIntent as aL, type LiteralExpressionIntent as aM, type LockIntent as aN, type LockStrength as aO, type LockWaitPolicy as aP, type LogicalIdentity as aQ, type LogicalIdentityCarrier as aR, type LogicalOperator as aS, type MSSQLColumnType as aT, type ModelIR as aU, type MutationIntent as aV, type MutationReturningItem as aW, type MySQLColumnType as aX, type NamedArgExpressionIntent as aY, type NestedOutputReadHandling as aZ, type NqlBindingColumnLineage as a_, type DropIndexOptions as aa, type DuckDBColumnType as ab, type Dump as ac, type DumpMeta as ad, type DumpSequenceStep as ae, type EdgeTableTraversal as af, type EmitJoinClause as ag, type EnumIR as ah, type ExecutingAdapter as ai, type ExpressionIntent as aj, type FeatureBehaviorConfig as ak, type FeatureTranslator as al, type FeatureWarning as am, type FieldRef as an, type FilterStrategy as ao, type ForeignKeyIR as ap, type FunctionExpressionIntent as aq, type HierarchyIR as ar, type IncludeIntent as as, type IncludeRecursiveOptions as at, type IncludeStrategy as au, type IndexColumnDef as av, type IndexIR as aw, type IndexInfo as ax, type IndexMethod as ay, type InsertFromIntent as az, type AdapterCapabilities as b, type RelationType as b$, type NqlBindingColumnUntypeableReason as b0, type NqlBindingOutputSchema as b1, type NqlBindingRelationFilterMetadata as b2, type NqlBindingVirtualRelation as b3, type NqlBindingVirtualRelationHop as b4, type NqlBindingVirtualRelationRecursive as b5, type NqlProgramSequenceStep as b6, type NqlRuntimeBinding as b7, type NullOperator as b8, type NullsPosition as b9, type PseudoColumnTraversal as bA, type QueryIntent as bB, type RangeOperand as bC, type RangeOperator as bD, type RangeValue as bE, type RankingWindowFunction as bF, type RankingWindowIntent as bG, type RawCteIntent as bH, type RawExpressionIntent as bI, type RawSqlAdapter as bJ, type RecursiveAdvancedOptions as bK, type RecursiveDedupe as bL, type RecursiveDirection as bM, type RecursiveEmitOptions as bN, type RecursiveExistsOptions as bO, type RecursiveIntent as bP, type RecursiveMetadata as bQ, type RecursiveNodeIdExpr as bR, type RecursivePlanOptions as bS, type RecursivePlanReport as bT, type RecursiveTrackOptions as bU, type RecursiveTraversal as bV, type RefExpressionIntent as bW, type RelationColumnIntent as bX, type RelationIR as bY, type RelationKind as bZ, type RelationOperator as b_, type OffsetWindowFunction as ba, type OffsetWindowIntent as bb, type OnDeleteAction as bc, type OperationKindRef as bd, type Optionality as be, type OrderByExpressionIntent as bf, type OrderByFieldIntent as bg, type OrderByIntent as bh, type OutputDescriptor as bi, type OutputReadHandling as bj, type OutputSource as bk, type OutputValueShape as bl, type ParamExpressionIntent as bm, type ParamIntent as bn, type PartitionIR as bo, type PinnedConnectionOptions as bp, type PlanDecision as bq, type PlanOptions as br, type PlanWarning as bs, type PlanWarningCode as bt, type PolicyIR as bu, type PostgresColumnType as bv, type PostgresOnlyColumnType as bw, type PredicateOperator as bx, type PseudoColumnExpressionIntent as by, type PseudoColumnMetadata as bz, type AdapterLogger as c, type WhereRelationFilterIntent as c$, type RequiredEnumLabelIR as c0, type ResolvedIncludeStrategy as c1, type SQLiteColumnType as c2, type SchemaChange as c3, type SchemaDiff as c4, type SelectAggregateIntent as c5, type SelectAllIntent as c6, type SelectFieldsIntent as c7, type SelectIntent as c8, type SelectWithExpressionsIntent as c9, type UnnestCteIntent as cA, type UnsupportedFeatureBehavior as cB, type UpdateIntent as cC, type UpsertConflictAction as cD, type UpsertConflictTarget as cE, type UpsertFromIntent as cF, type UpsertIntent as cG, type VacuumOptions as cH, type WhereAndIntent as cI, type WhereAnyIntent as cJ, type WhereComparisonIntent as cK, type WhereExistsIntent as cL, type WhereExpressionIntent as cM, type WhereInIntent as cN, type WhereInSubqueryIntent as cO, type WhereInValueIntent as cP, type WhereIntent as cQ, type WhereJsonContainsIntent as cR, type WhereJsonExistsIntent as cS, type WhereLikeIntent as cT, type WhereNotExistsIntent as cU, type WhereNotIntent as cV, type WhereNullIntent as cW, type WhereOrIntent as cX, type WhereRangeIntent as cY, type WhereRawExistsIntent as cZ, type WhereRawNotExistsIntent as c_, type SemanticArtifactId as ca, type SemanticArtifactRef as cb, type SequenceIR as cc, type SetOperationIntent as cd, type SetOperationType as ce, type SimpleCteIntent as cf, type SortDirection as cg, type StandaloneWhereExpressionIntent as ch, type StarExpressionIntent as ci, type StreamingAdapter as cj, type StringOperator as ck, type SubqueryExpressionIntent as cl, type SubqueryIncludeInfo as cm, type SubqueryRefIntent as cn, type SupportedColumnTypes as co, type TableDDLGeneratorAdapter as cp, type TableIR as cq, type TableReaddressAddress as cr, type TableReaddressDeclaration as cs, type TransactionBeginOptions as ct, type TransactionOptions as cu, type TransactionalAdapter as cv, type TranslationContext as cw, type TruncateOptions as cx, type TrustRoot as cy, type UnaryExpressionIntent as cz, type AdapterStreamOptions as d, type WhereSubqueryIntent as d0, type WindowFunction as d1, type WindowIntent as d2, type WindowOrderBy as d3, getNodeIdAlias as d4, isFieldRef as d5, isParamIntent as d6, resolveOutputReadHandling as d7, toColumnList as d8, type AdjacencyTraversal as e, type AggOrderByArg as f, type AggregateCountIntent as g, type AggregateExpressionIntent as h, type AggregateFieldIntent as i, type AggregateFunction as j, type AggregateIntent as k, type AggregateWindowFunction as l, type AggregateWindowIntent as m, type AliasIncludedColumnsMode as n, type AlterColumnOptions as o, type AmbiguityCheckResult as p, type ArithmeticExpressionIntent as q, type ArrayExpressionIntent as r, type ArrayOperator as s, type AuthorAttestedNativeDefault as t, type AuthorAttester as u, type BatchUpdateIntent as v, type BatchValuesJoinPayload as w, type CTEDefinition as x, type Cardinality as y, type CaseExpressionIntent as z };
|
package/dist/adapter-sdk.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as CompiledQuery, a as CompiledColumnMetadata, P as PlanReport } from './adapter-
|
|
1
|
+
import { C as CompiledQuery, a as CompiledColumnMetadata, P as PlanReport } from './adapter-DXjfHEAf.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Stable SPI for implementing the `Adapter` port. Only stable helpers required to construct/validate a
|
|
@@ -334,6 +334,108 @@ function resolveOutputReadHandling(descriptor) {
|
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
336
|
|
|
337
|
+
// src/physical-name-inventory.ts
|
|
338
|
+
var PhysicalNameInventoryDuplicateError = class extends Error {
|
|
339
|
+
constructor(scope, first, second) {
|
|
340
|
+
super(
|
|
341
|
+
`Duplicate physical-name inventory ${scope}: "${first.physical}" is claimed by ${addressText(first.logical)} and ${addressText(second.logical)}.`
|
|
342
|
+
);
|
|
343
|
+
this.scope = scope;
|
|
344
|
+
this.first = first;
|
|
345
|
+
this.second = second;
|
|
346
|
+
this.name = "PhysicalNameInventoryDuplicateError";
|
|
347
|
+
}
|
|
348
|
+
scope;
|
|
349
|
+
first;
|
|
350
|
+
second;
|
|
351
|
+
};
|
|
352
|
+
function createPhysicalNameInventory(entries) {
|
|
353
|
+
const byAddress = /* @__PURE__ */ new Map();
|
|
354
|
+
const tables = /* @__PURE__ */ new Map();
|
|
355
|
+
const columns = /* @__PURE__ */ new Map();
|
|
356
|
+
const copied = entries.map(
|
|
357
|
+
(entry) => Object.freeze({
|
|
358
|
+
logical: Object.freeze({ ...entry.logical }),
|
|
359
|
+
physical: entry.physical,
|
|
360
|
+
...entry.sequenceProvenance === void 0 ? {} : { sequenceProvenance: entry.sequenceProvenance }
|
|
361
|
+
})
|
|
362
|
+
);
|
|
363
|
+
const physicalTables = /* @__PURE__ */ new Map();
|
|
364
|
+
for (const entry of copied) {
|
|
365
|
+
if (entry.logical.kind === "table")
|
|
366
|
+
physicalTables.set(
|
|
367
|
+
`${entry.logical.schema}\0${entry.logical.name}`,
|
|
368
|
+
entry.physical
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
for (const entry of copied) {
|
|
372
|
+
const key = addressKey(entry.logical);
|
|
373
|
+
const firstAddress = byAddress.get(key);
|
|
374
|
+
if (firstAddress)
|
|
375
|
+
throw new PhysicalNameInventoryDuplicateError(
|
|
376
|
+
"logical-address",
|
|
377
|
+
firstAddress,
|
|
378
|
+
entry
|
|
379
|
+
);
|
|
380
|
+
byAddress.set(key, entry);
|
|
381
|
+
if (entry.logical.kind === "table") {
|
|
382
|
+
const tableKey = `${entry.logical.schema}\0${entry.physical}`;
|
|
383
|
+
const firstTable = tables.get(tableKey);
|
|
384
|
+
if (firstTable)
|
|
385
|
+
throw new PhysicalNameInventoryDuplicateError(
|
|
386
|
+
"table",
|
|
387
|
+
firstTable,
|
|
388
|
+
entry
|
|
389
|
+
);
|
|
390
|
+
tables.set(tableKey, entry);
|
|
391
|
+
}
|
|
392
|
+
if (entry.logical.kind === "column") {
|
|
393
|
+
const physicalTable = physicalTables.get(
|
|
394
|
+
`${entry.logical.schema}\0${entry.logical.table}`
|
|
395
|
+
) ?? entry.logical.table;
|
|
396
|
+
const columnKey = `${entry.logical.schema}\0${physicalTable}\0${entry.physical}`;
|
|
397
|
+
const firstColumn = columns.get(columnKey);
|
|
398
|
+
if (firstColumn)
|
|
399
|
+
throw new PhysicalNameInventoryDuplicateError(
|
|
400
|
+
"column",
|
|
401
|
+
firstColumn,
|
|
402
|
+
entry
|
|
403
|
+
);
|
|
404
|
+
columns.set(columnKey, entry);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
const sorted = Object.freeze(
|
|
408
|
+
[...copied].sort(
|
|
409
|
+
(left, right) => addressKey(left.logical) < addressKey(right.logical) ? -1 : addressKey(left.logical) > addressKey(right.logical) ? 1 : 0
|
|
410
|
+
)
|
|
411
|
+
);
|
|
412
|
+
return Object.freeze({
|
|
413
|
+
entries: sorted,
|
|
414
|
+
has(address) {
|
|
415
|
+
return byAddress.has(addressKey(address));
|
|
416
|
+
},
|
|
417
|
+
get(address) {
|
|
418
|
+
const entry = byAddress.get(addressKey(address));
|
|
419
|
+
if (!entry) throw new PhysicalNameInventoryMissingError(address);
|
|
420
|
+
return entry.physical;
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
var PhysicalNameInventoryMissingError = class extends Error {
|
|
425
|
+
constructor(address) {
|
|
426
|
+
super(`Physical name inventory has no entry for ${addressText(address)}.`);
|
|
427
|
+
this.address = address;
|
|
428
|
+
this.name = "PhysicalNameInventoryMissingError";
|
|
429
|
+
}
|
|
430
|
+
address;
|
|
431
|
+
};
|
|
432
|
+
function addressKey(address) {
|
|
433
|
+
return "table" in address ? `${address.kind}\0${address.schema}\0${address.table}\0${address.name}` : `${address.kind}\0${address.schema}\0${address.name}`;
|
|
434
|
+
}
|
|
435
|
+
function addressText(address) {
|
|
436
|
+
return "table" in address ? `${address.kind} ${address.schema}.${address.table}.${address.name}` : `${address.kind} ${address.schema}.${address.name}`;
|
|
437
|
+
}
|
|
438
|
+
|
|
337
439
|
// src/relation-key-fields.ts
|
|
338
440
|
var DEFAULT_REFERENCED_COLUMN = "id";
|
|
339
441
|
function columnListValue(columns, shape) {
|
|
@@ -572,6 +674,9 @@ export {
|
|
|
572
674
|
resolveJsonAggOrderKey,
|
|
573
675
|
isValidSchema,
|
|
574
676
|
resolveOutputReadHandling,
|
|
677
|
+
PhysicalNameInventoryDuplicateError,
|
|
678
|
+
createPhysicalNameInventory,
|
|
679
|
+
PhysicalNameInventoryMissingError,
|
|
575
680
|
buildRelationKeyFields,
|
|
576
681
|
EXECUTION_CONTRACT_VERSION,
|
|
577
682
|
LEDGER_EVENT_KINDS,
|
|
@@ -583,4 +688,4 @@ export {
|
|
|
583
688
|
refusalFor,
|
|
584
689
|
sameControllerIdentity
|
|
585
690
|
};
|
|
586
|
-
//# sourceMappingURL=chunk-
|
|
691
|
+
//# sourceMappingURL=chunk-X5OQYLAK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bigint-js-read.ts","../src/column-list.ts","../src/intent/expression-intent.ts","../src/intent/recursive-intent.ts","../src/intent/select-function-allowlist.ts","../src/intent/type-guards.ts","../src/intent/where-intent.ts","../src/json-agg-order-key.ts","../src/loaded-schema.ts","../src/output-provenance.ts","../src/physical-name-inventory.ts","../src/relation-key-fields.ts","../src/transition/execution-contract.ts","../src/transition/ledger.ts","../src/transition/refusal.ts","../src/transition/resource.ts"],"sourcesContent":["import type { ColumnJsReadType } from './model-ir.js';\n\nexport interface BigintJsReadConversionContext {\n\treadonly table: string;\n\treadonly column: string;\n\treadonly outputKey: string;\n}\n\nconst MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);\nconst MIN_SAFE_BIGINT = BigInt(Number.MIN_SAFE_INTEGER);\nconst INTEGER_STRING_RE = /^[+-]?\\d+$/;\n\nfunction formatValue(value: unknown): string {\n\tif (typeof value === 'string') return `\"${value}\"`;\n\tif (typeof value === 'bigint') return `${value.toString()}n`;\n\tif (typeof value === 'number' || typeof value === 'boolean') {\n\t\treturn String(value);\n\t}\n\tif (value === null) return 'null';\n\tif (value === undefined) return 'undefined';\n\ttry {\n\t\treturn JSON.stringify(value) ?? String(value);\n\t} catch {\n\t\treturn String(value);\n\t}\n}\n\nfunction conversionError(\n\tvalue: unknown,\n\ttarget: Exclude<ColumnJsReadType, 'string'>,\n\tctx: BigintJsReadConversionContext,\n\treason: string,\n): RangeError {\n\treturn new RangeError(\n\t\t`Cannot convert PostgreSQL bigint column \"${ctx.table}.${ctx.column}\" output key \"${ctx.outputKey}\" value ${formatValue(value)} to ${target}: ${reason}.`,\n\t);\n}\n\nfunction toStrictBigInt(\n\tvalue: unknown,\n\ttarget: Exclude<ColumnJsReadType, 'string'>,\n\tctx: BigintJsReadConversionContext,\n): bigint {\n\tif (typeof value === 'bigint') return value;\n\tif (typeof value === 'string') {\n\t\tconst trimmed = value.trim();\n\t\tif (!INTEGER_STRING_RE.test(trimmed)) {\n\t\t\tthrow conversionError(\n\t\t\t\tvalue,\n\t\t\t\ttarget,\n\t\t\t\tctx,\n\t\t\t\t'expected an integer string, bigint, or safe integer number',\n\t\t\t);\n\t\t}\n\t\treturn BigInt(trimmed);\n\t}\n\tif (typeof value === 'number') {\n\t\tif (!Number.isSafeInteger(value)) {\n\t\t\tthrow conversionError(\n\t\t\t\tvalue,\n\t\t\t\ttarget,\n\t\t\t\tctx,\n\t\t\t\t'expected a safe integer number',\n\t\t\t);\n\t\t}\n\t\treturn BigInt(value);\n\t}\n\tthrow conversionError(\n\t\tvalue,\n\t\ttarget,\n\t\tctx,\n\t\t'expected an integer string, bigint, or safe integer number',\n\t);\n}\n\nexport function convertBigintJsReadValue(\n\tvalue: unknown,\n\tjs: ColumnJsReadType,\n\tctx: BigintJsReadConversionContext,\n): unknown {\n\tif (value === null || value === undefined) return value;\n\n\tswitch (js) {\n\t\tcase 'string':\n\t\t\treturn value;\n\t\tcase 'bigint':\n\t\t\treturn toStrictBigInt(value, 'bigint', ctx);\n\t\tcase 'number': {\n\t\t\tconst bigintValue = toStrictBigInt(value, 'number', ctx);\n\t\t\tif (bigintValue > MAX_SAFE_BIGINT || bigintValue < MIN_SAFE_BIGINT) {\n\t\t\t\tthrow conversionError(\n\t\t\t\t\tvalue,\n\t\t\t\t\t'number',\n\t\t\t\t\tctx,\n\t\t\t\t\t\"outside Number.MAX_SAFE_INTEGER; use js:'bigint' or omit js\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn Number(bigintValue);\n\t\t}\n\t\tdefault:\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid bigint js read type '${String(js)}' for PostgreSQL bigint column \"${ctx.table}.${ctx.column}\".`,\n\t\t\t);\n\t}\n}\n","/**\n * Shared relation-key normalizer.\n *\n * Relation metadata accepts either a single column or a composite column list.\n * Readers should normalize once and keep the full list instead of degrading to\n * the first column.\n */\nexport type ColumnListInput = string | readonly string[] | undefined;\n\nexport function toColumnList(key: ColumnListInput): readonly string[] {\n\tif (key === undefined) return [];\n\treturn typeof key === 'string' ? [key] : key;\n}\n","/**\n * @module intent/expression-intent\n * Expression intent types for computed/derived values in SELECT.\n */\n\nimport type { QueryIntent } from './query-intent.js';\nimport type { AggregateFunction } from './select-intent.js';\nimport type { WhereIntent } from './where-intent.js';\n\n// ============================================================================\n// Expression Intents - Computed/Derived Values\n// ============================================================================\n\n/**\n * COALESCE expression: returns first non-null value from a list of fields\n * @example { kind: 'coalesce', fields: ['name_fr', 'name_en'], as: 'display_name' }\n * → COALESCE(name_fr, name_en) AS display_name\n */\nexport interface CoalesceExpressionIntent {\n\treadonly kind: 'coalesce';\n\t/** Fields to check in order (first non-null wins) */\n\treadonly fields: readonly string[];\n\t/** Required alias for the result column */\n\treadonly as: string;\n}\n\n/**\n * Raw SQL expression (escape hatch for advanced use cases)\n * @example { kind: 'raw', sql: 'NOW()', as: 'current_time' }\n * → NOW() AS current_time\n * @warning Use sparingly - bypasses type safety and SQL injection protection\n */\nexport interface RawExpressionIntent {\n\treadonly kind: 'raw';\n\t/** Raw SQL fragment (must be safe, no user input!) */\n\treadonly sql: string;\n\t/** Required alias for the result column */\n\treadonly as: string;\n}\n\n/**\n * Simple column expression: just a column reference, optionally aliased\n * Used by NQL when a column is selected without modification\n * @example { kind: 'column', column: 'name' }\n * → SELECT \"name\"\n * @example { kind: 'column', column: 'name', as: 'userName' }\n * → SELECT \"name\" AS \"userName\"\n */\nexport interface ColumnExpressionIntent {\n\treadonly kind: 'column';\n\t/** Column name to select */\n\treadonly column: string;\n\t/** Optional alias for the result column */\n\treadonly as?: string;\n}\n\n/**\n * Column alias expression: simple column reference with alias\n * Represents an aliased column as structured intent for dialect compilers\n * @example { kind: 'columnAlias', column: 'name', alias: 'userName' }\n * → SELECT \"name\" AS \"userName\"\n */\nexport interface ColumnAliasIntent {\n\treadonly kind: 'columnAlias';\n\t/** Column name to select */\n\treadonly column: string;\n\t/** Alias for the result column */\n\treadonly alias: string;\n}\n\n/**\n * Relation column expression: select a column from a related table\n * The query must already emit the named relation's JOIN, through `.join()` or\n * an include with an explicit outer join. Without one, compilation reports\n * `relation column \"<relation>\".\"<column>\" has no emitted alias in this query`.\n * A bare include aggregates the relation instead, and the column lands inside\n * `<relation>_json` rather than under its own alias (#793).\n * @example orm.select('products').join('category').columns([\n * relationColumn('category', 'name', 'categoryName'),\n * ])\n * @example orm.select('products').include('category', { join: 'left' }).columns([\n * relationColumn('category', 'name', 'categoryName'),\n * ])\n *\n * Deriving a join would choose join type, null behavior, and row multiplication\n * on the caller's behalf; that is a separate feature.\n */\nexport interface RelationColumnIntent {\n\treadonly kind: 'relationColumn';\n\t/** Relation path to traverse (dot-separated for multi-level) */\n\treadonly relation: string;\n\t/** Column name to select from the target relation */\n\treadonly column: string;\n\t/** Alias for the result column */\n\treadonly as: string;\n}\n\n/**\n * Aggregate expression intent for SELECT expressions\n * @example { kind: 'aggregate', function: 'count', as: 'total' } → COUNT(*) AS total\n * @example { kind: 'aggregate', function: 'sum', field: 'price', as: 'total_price' } → SUM(price) AS total_price\n * @example { kind: 'aggregate', function: 'count', field: 'id', distinct: true, as: 'unique_count' }\n * → COUNT(DISTINCT id) AS unique_count\n */\nexport interface AggregateExpressionIntent {\n\treadonly kind: 'aggregate';\n\t/** Aggregate function */\n\treadonly function: AggregateFunction;\n\t/** Field to aggregate (or '*' for count) */\n\treadonly field: string | '*';\n\t/** Alias for result column */\n\treadonly as?: string | undefined;\n\t/** Whether to apply DISTINCT to the aggregate */\n\treadonly distinct?: boolean | undefined;\n\t/** Extra arguments for multi-arg aggregates like string_agg(field, separator) */\n\treadonly extraArgs?: readonly unknown[] | undefined;\n\t/** FILTER (WHERE ...) clause for conditional aggregation */\n\treadonly filter?: WhereIntent | undefined;\n}\n\n/**\n * Pseudo-column traversal keyword for self-referential relations.\n * Used by NQL to traverse hierarchical/tree structures.\n *\n * Default keywords: 'parent', 'child', 'ascendant', 'descendant'.\n * Custom keywords are supported via schema configuration\n * (e.g., 'manager', 'managee' via parentRole/childRole).\n */\nexport type PseudoColumnTraversal = string;\n\n/**\n * Pseudo-column expression intent for self-referential traversal.\n * Enables access to columns on related rows in hierarchical structures.\n *\n * @example { kind: 'pseudoColumn', traversal: 'parent', targetColumn: 'name', as: 'parent.name' }\n * → SELECT parent_row.name AS \"parent.name\" via CTE join\n * @example { kind: 'pseudoColumn', traversal: 'ascendant', targetColumn: 'title', as: 'ancestor_title' }\n * → Recursive CTE to find all ancestors, return their title column\n */\nexport interface PseudoColumnExpressionIntent {\n\treadonly kind: 'pseudoColumn';\n\t/** Traversal type: single-hop (parent/child) or recursive (ascendant/descendant) */\n\treadonly traversal: PseudoColumnTraversal;\n\t/** The column to access on the target row(s) */\n\treadonly targetColumn: string;\n\t/** Alias for result column (required) */\n\treadonly as: string;\n\t/** Optional bounded depth for ascendant[N] / descendant[N] syntax */\n\treadonly depth?: number;\n\t/** Custom role name for multi-FK tables (e.g., 'manager' in manager.ascendant) */\n\treadonly role?: string;\n\t/**\n\t * Chained traversals for multi-hop navigation (e.g., parent.parent.name → ['parent', 'parent']).\n\t * When present, overrides single `traversal` field. Each element generates a successive self-join.\n\t */\n\treadonly traversals?: readonly PseudoColumnTraversal[];\n}\n\n/**\n * Generic function expression (e.g., now(), upper(name), coalesce(a, b)).\n * Used for SQL functions that are not aggregates.\n */\nexport interface FunctionExpressionIntent {\n\treadonly kind: 'function';\n\t/** Function name (e.g., 'upper', 'now', 'coalesce') */\n\treadonly name: string;\n\t/** Function arguments */\n\treadonly args: readonly unknown[];\n\t/** Alias for result column */\n\treadonly as?: string | undefined;\n}\n\n/**\n * Scalar subquery in SELECT clause.\n * Produces a single value from a nested query.\n */\nexport interface SubqueryExpressionIntent {\n\treadonly kind: 'subquery';\n\t/** The nested query */\n\treadonly query: QueryIntent;\n\t/** Alias for result column */\n\treadonly as?: string | undefined;\n}\n\n/**\n * Arithmetic expression (e.g., price * quantity).\n * Binary operation with left operand, operator, and right operand.\n */\nexport interface ArithmeticExpressionIntent {\n\treadonly kind: 'arithmetic';\n\t/** Left operand (column name or value) */\n\treadonly left: string | number | unknown;\n\t/** Arithmetic operator */\n\treadonly operator: '+' | '-' | '*' | '/' | '%';\n\t/** Right operand (column name or value) */\n\treadonly right: string | number | unknown;\n\t/** Alias for result column */\n\treadonly as?: string | undefined;\n}\n\n/**\n * Literal value expression: string, number, boolean, or null.\n * Used in CASE THEN/ELSE clauses for constant values.\n */\nexport interface LiteralExpressionIntent {\n\treadonly kind: 'literal';\n\t/** The literal value */\n\treadonly value: string | number | boolean | null;\n\t/** Optional alias */\n\treadonly as?: string | undefined;\n}\n\n/**\n * Comparison expression: left operator right.\n * Used in CASE WHEN conditions.\n */\nexport interface ComparisonExpressionIntent {\n\treadonly kind: 'comparison';\n\t/** Left side column reference */\n\treadonly column: string;\n\t/** Comparison operator */\n\treadonly operator: '=' | '!=' | '<' | '>' | '<=' | '>=' | 'like';\n\t/** Right side value */\n\treadonly value: unknown;\n}\n\n/**\n * CASE expression: conditional logic in SELECT.\n * CASE WHEN condition THEN result [WHEN ...] [ELSE default] END\n */\nexport interface CaseExpressionIntent {\n\treadonly kind: 'case';\n\t/** Array of WHEN-THEN pairs */\n\treadonly when: ReadonlyArray<{\n\t\treadonly condition: WhereIntent;\n\t\treadonly result: ExpressionIntent;\n\t}>;\n\t/** Optional ELSE clause */\n\treadonly else?: ExpressionIntent | undefined;\n\t/** Alias for result column */\n\treadonly as?: string | undefined;\n}\n\n// ============================================================================\n// JSON/JSONB Operators (E13)\n// ============================================================================\n\n/**\n * JSON path extraction: col->'key' or col->>'key' (chained paths supported).\n * Also used for function notation: json_extract(col, 'key'), json_extract_text(col, 'key').\n */\nexport interface JsonExtractIntent {\n\treadonly kind: 'jsonExtract';\n\treadonly field: string;\n\treadonly path: readonly (string | ParamIntent)[];\n\t/** 'json' = returns JSON value (->), 'text' = returns text (->>) */\n\treadonly mode: 'json' | 'text';\n\treadonly as?: string | undefined;\n}\n\n/**\n * JSON containment: col @> value (contains) or col <@ value (contained by).\n */\nexport interface JsonContainsIntent {\n\treadonly kind: 'jsonContains';\n\treadonly field: string;\n\treadonly value: unknown;\n\t/** true = <@ (contained by), false = @> (contains) */\n\treadonly reversed: boolean;\n}\n\n/**\n * JSON key existence: col ? 'key'.\n */\nexport interface JsonExistsIntent {\n\treadonly kind: 'jsonExists';\n\treadonly field: string;\n\treadonly key: string;\n}\n\n/**\n * JSON path extraction with array path: col #> '{a,b}' or col #>> '{a,b}'.\n */\nexport interface JsonPathExtractIntent {\n\treadonly kind: 'jsonPathExtract';\n\treadonly field: string;\n\t/** PostgreSQL JSON path segments. Bound as one text[] parameter by adapters. */\n\treadonly path: readonly (string | ParamIntent)[];\n\t/** 'json' = returns JSON (#>), 'text' = returns text (#>>) */\n\treadonly mode: 'json' | 'text';\n\treadonly as?: string | undefined;\n}\n\n/**\n * Operators whose result is a SQL predicate.\n *\n * This is deliberately closed: `op()` only brands these literal operators as\n * predicates. Arbitrary operator strings remain ordinary expressions unless a\n * caller explicitly opts into `unsafeAsPredicate()`.\n */\nexport type PredicateOperator =\n\t| '='\n\t| '!='\n\t| '<>'\n\t| '<'\n\t| '<='\n\t| '>'\n\t| '>='\n\t| 'AND'\n\t| 'OR'\n\t| 'NOT'\n\t| '@@'\n\t| '@@@'\n\t| '&&'\n\t| '<@'\n\t| '@>';\n\n/** Custom binary operator expression (e.g., <=> for pgvector) */\nexport interface CustomOpExpressionIntent {\n\treadonly kind: 'customOp';\n\treadonly operator: string;\n\treadonly left: ExpressionIntent;\n\treadonly right: ExpressionIntent;\n\treadonly as?: string;\n}\n\n/** Custom function call (e.g., paradedb.score) */\n/** Represents a single ORDER BY entry inside an aggregate function. */\nexport interface AggOrderByArg {\n\t/** Discriminator to distinguish from regular expression args. */\n\treadonly __aggOrderBy: true;\n\treadonly field: string;\n\treadonly direction: 'asc' | 'desc';\n}\n\nexport interface CustomFnExpressionIntent {\n\treadonly kind: 'customFn';\n\treadonly name: string;\n\treadonly args: readonly ExpressionIntent[];\n\treadonly as?: string;\n\t/** Apply DISTINCT to the call's arguments (e.g. count(DISTINCT id)) */\n\treadonly distinct?: boolean;\n\t/** FILTER (WHERE ...) clause for conditional aggregation */\n\treadonly filter?: WhereIntent | undefined;\n\t/** ORDER BY clause for ordered aggregates (e.g. array_agg(x ORDER BY y)) */\n\treadonly aggOrderBy?: readonly AggOrderByArg[] | undefined;\n}\n\n/** Column reference in custom expressions */\nexport interface RefExpressionIntent {\n\treadonly kind: 'ref';\n\treadonly column: string;\n}\n\n/**\n * Public bound-parameter node.\n *\n * A value that originated from an NQL named parameter or template binding is\n * represented explicitly in the public IntentAST. The inner value is opaque:\n * consumers must bind it as a value and must not inspect its shape to decide\n * whether it is query structure.\n *\n * @public\n */\nexport interface ParamExpressionIntent {\n\treadonly kind: 'param';\n\treadonly value: unknown;\n\t/** Optional alias when used as a SELECT expression. */\n\treadonly as?: string | undefined;\n}\n\n/** @public */\nexport type ParamIntent = ParamExpressionIntent;\n\n/** Single-level only — never recurse into .value; the inner bound value is opaque user data. @public */\nexport function isParamIntent(value: unknown): value is ParamIntent {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t(value as Record<string, unknown>).kind === 'param' &&\n\t\t'value' in (value as Record<string, unknown>)\n\t);\n}\n\n/** Type cast expression */\nexport interface CastExpressionIntent {\n\treadonly kind: 'cast';\n\treadonly expr: ExpressionIntent;\n\treadonly typeName: string;\n}\n\n/** Named argument in a function call: name => value */\nexport interface NamedArgExpressionIntent {\n\treadonly kind: 'namedArg';\n\treadonly name: string;\n\treadonly value: ExpressionIntent;\n}\n\n/** Star/wildcard expression (*) — used in COUNT(*), SELECT *, etc. */\nexport interface StarExpressionIntent {\n\treadonly kind: 'star';\n}\n\n/** PostgreSQL ARRAY constructor: ARRAY[item1, item2, ...] */\nexport interface ArrayExpressionIntent {\n\treadonly kind: 'array';\n\treadonly elements: readonly ExpressionIntent[];\n\treadonly as?: string;\n}\n\n/** Unary operator expression (e.g., NOT, -, ~) */\nexport interface UnaryExpressionIntent {\n\treadonly kind: 'unary';\n\treadonly operator: string;\n\treadonly operand: ExpressionIntent;\n\treadonly as?: string;\n}\n\n/**\n * Expression intent union type - computed/derived values in SELECT\n * Extensible for future expression types\n */\nexport type ExpressionIntent =\n\t| ColumnExpressionIntent\n\t| CoalesceExpressionIntent\n\t| RawExpressionIntent\n\t| ColumnAliasIntent\n\t| RelationColumnIntent\n\t| WindowIntent\n\t| AggregateExpressionIntent\n\t| PseudoColumnExpressionIntent\n\t| FunctionExpressionIntent\n\t| SubqueryExpressionIntent\n\t| ArithmeticExpressionIntent\n\t| LiteralExpressionIntent\n\t| ComparisonExpressionIntent\n\t| CaseExpressionIntent\n\t| JsonExtractIntent\n\t| JsonContainsIntent\n\t| JsonExistsIntent\n\t| JsonPathExtractIntent\n\t| CustomOpExpressionIntent\n\t| CustomFnExpressionIntent\n\t| RefExpressionIntent\n\t| ParamExpressionIntent\n\t| CastExpressionIntent\n\t| UnaryExpressionIntent\n\t| NamedArgExpressionIntent\n\t| StarExpressionIntent\n\t| ArrayExpressionIntent;\n\n/**\n * Expression intents that the standalone `WHERE` expression compiler accepts.\n *\n * This deliberately excludes SELECT-only and planner-only expression kinds.\n * A standalone expression is used only when a local predicate wrapper derives\n * `{ kind: 'expression', expr }` for `WHERE`.\n */\nexport type StandaloneWhereExpressionIntent =\n\t| CustomOpExpressionIntent\n\t| CustomFnExpressionIntent\n\t| RefExpressionIntent\n\t| ParamExpressionIntent\n\t| CastExpressionIntent\n\t| LiteralExpressionIntent\n\t| UnaryExpressionIntent\n\t| NamedArgExpressionIntent\n\t| StarExpressionIntent\n\t| ArrayExpressionIntent\n\t| SubqueryExpressionIntent\n\t| RelationColumnIntent\n\t| CaseExpressionIntent;\n\n// ============================================================================\n// Window Functions (P3-A)\n// ============================================================================\n\n/**\n * Window function types for OVER clause analytics.\n * - Ranking: row_number, rank, dense_rank (no field required)\n * - Aggregate: sum, avg, count, min, max (field required)\n * - Offset: lag, lead (field required, offset/default deferred to P3+)\n */\nexport type WindowFunction =\n\t| 'row_number'\n\t| 'rank'\n\t| 'dense_rank'\n\t| 'sum'\n\t| 'avg'\n\t| 'count'\n\t| 'min'\n\t| 'max'\n\t| 'lag'\n\t| 'lead';\n\n/**\n * Order specification for window OVER clause.\n */\nexport interface WindowOrderBy {\n\treadonly field: string;\n\treadonly direction?: 'asc' | 'desc';\n}\n\n/**\n * Window function intent for analytics over partitions.\n * Produces SQL like: ROW_NUMBER() OVER (PARTITION BY x ORDER BY y) AS alias\n *\n * @example Row numbering\n * {\n * kind: 'window',\n * function: 'row_number',\n * alias: 'rn',\n * over: { orderBy: [{ field: 'created_at', direction: 'desc' }] }\n * }\n *\n * @example Running total\n * {\n * kind: 'window',\n * function: 'sum',\n * field: 'amount',\n * alias: 'running_total',\n * over: { partitionBy: ['account_id'], orderBy: [{ field: 'date' }] }\n * }\n */\n/**\n * Window function intent (ranking branch): ROW_NUMBER / RANK / DENSE_RANK — no field required.\n *\n * @example\n * { kind: 'window', function: 'row_number', alias: 'rn', over: { orderBy: [{ field: 'created_at', direction: 'desc' }] } }\n */\nexport interface RankingWindowIntent {\n\treadonly kind: 'window';\n\treadonly function: RankingWindowFunction;\n\treadonly field?: never;\n\t/** Result column alias (required) */\n\treadonly alias: string;\n\treadonly offset?: never;\n\treadonly defaultValue?: never;\n\t/** OVER clause specification */\n\treadonly over: {\n\t\treadonly partitionBy?: readonly string[] | undefined;\n\t\treadonly orderBy?: readonly WindowOrderBy[] | undefined;\n\t};\n}\n\n/**\n * Window function intent (aggregate branch): SUM / AVG / COUNT / MIN / MAX — field required.\n *\n * @example\n * { kind: 'window', function: 'sum', field: 'amount', alias: 'running_total', over: { partitionBy: ['account_id'] } }\n */\n/**\n * Window function intent (aggregate branch): SUM / AVG / COUNT / MIN / MAX.\n * Field is required for sum/avg/min/max; COUNT omits field to produce COUNT(*) OVER (...).\n *\n * @example SUM with field\n * { kind: 'window', function: 'sum', field: 'amount', alias: 'running_total', over: { partitionBy: ['account_id'] } }\n * @example COUNT(*)\n * { kind: 'window', function: 'count', alias: 'total', over: {} }\n */\nexport interface AggregateWindowIntent {\n\treadonly kind: 'window';\n\treadonly function: AggregateWindowFunction;\n\t/**\n\t * Field to aggregate over.\n\t * Required for sum/avg/min/max. Omit (or undefined) for COUNT(*) OVER (...).\n\t */\n\treadonly field?: string | undefined;\n\t/** Result column alias (required) */\n\treadonly alias: string;\n\treadonly offset?: never;\n\treadonly defaultValue?: never;\n\t/** OVER clause specification */\n\treadonly over: {\n\t\treadonly partitionBy?: readonly string[] | undefined;\n\t\treadonly orderBy?: readonly WindowOrderBy[] | undefined;\n\t};\n}\n\n/**\n * Window function intent (offset branch): LAG / LEAD — field required, offset optional.\n *\n * @example\n * { kind: 'window', function: 'lag', field: 'salary', alias: 'prev_salary', over: { orderBy: [{ field: 'date', direction: 'asc' }] } }\n */\nexport interface OffsetWindowIntent {\n\treadonly kind: 'window';\n\treadonly function: OffsetWindowFunction;\n\t/** Field to access from the offset row (required for lag/lead) */\n\treadonly field: string;\n\t/** Result column alias (required) */\n\treadonly alias: string;\n\t/** Offset for lag/lead (default: 1 in PostgreSQL) */\n\treadonly offset?: number | undefined;\n\t/** Default value for lag/lead when row doesn't exist */\n\treadonly defaultValue?: unknown;\n\t/** OVER clause specification */\n\treadonly over: {\n\t\treadonly partitionBy?: readonly string[] | undefined;\n\t\treadonly orderBy?: readonly WindowOrderBy[] | undefined;\n\t};\n}\n\n/**\n * Window function intent for analytics over partitions.\n * Discriminated by function group:\n * - RankingWindowIntent: row_number / rank / dense_rank (no field)\n * - AggregateWindowIntent: sum / avg / count / min / max (field required)\n * - OffsetWindowIntent: lag / lead (field required, offset optional)\n */\nexport type WindowIntent =\n\t| RankingWindowIntent\n\t| AggregateWindowIntent\n\t| OffsetWindowIntent;\n\n/**\n * Ranking window functions (no field required)\n */\nexport type RankingWindowFunction = 'row_number' | 'rank' | 'dense_rank';\n\n/**\n * Aggregate window functions (field required)\n */\nexport type AggregateWindowFunction = 'sum' | 'avg' | 'count' | 'min' | 'max';\n\n/**\n * Offset window functions (field required, offset/default deferred)\n */\nexport type OffsetWindowFunction = 'lag' | 'lead';\n","/**\n * @module intent/recursive-intent\n * Recursive CTE intent types for hierarchical data traversal (RFC-001).\n */\n\nimport type { OrderByIntent } from './include-intent.js';\nimport type { WhereIntent } from './where-intent.js';\n\n// ============================================================================\n// Recursive CTE Intent - Hierarchical Data Traversal (RFC-001)\n// ============================================================================\n\n/**\n * Node ID expression for recursive CTE anchor.\n * Used to define the join key for recursive traversal.\n */\nexport type RecursiveNodeIdExpr =\n\t| { readonly kind: 'column'; readonly name: string; readonly as?: string }\n\t| {\n\t\t\treadonly kind: 'literal';\n\t\t\treadonly value: unknown;\n\t\t\treadonly as?: string;\n\t }\n\t| {\n\t\t\treadonly kind: 'binary';\n\t\t\treadonly left: RecursiveNodeIdExpr;\n\t\t\treadonly op: string;\n\t\t\treadonly right: RecursiveNodeIdExpr;\n\t\t\treadonly as?: string;\n\t };\n\n/**\n * Get the alias for a node ID expression.\n * Used by both planner and compiler for consistent CTE column naming.\n *\n * @param expr - The node ID expression\n * @returns The alias to use (explicit alias, column name, or 'node_id' fallback)\n */\nexport function getNodeIdAlias(expr: RecursiveNodeIdExpr): string {\n\tif (expr.as) return expr.as;\n\tif (expr.kind === 'column') return expr.name;\n\tif (expr.kind === 'literal') return 'node_id';\n\t// Binary expression needs explicit alias\n\treturn 'node_id';\n}\n\n/**\n * Adjacency-list traversal (self-referential table).\n * Example: roles.parent_id → roles.id\n */\nexport interface AdjacencyTraversal {\n\treadonly kind: 'adjacency';\n\n\t/** Table containing hierarchical data */\n\treadonly nodeTable: string;\n\n\t/** Primary key column (e.g., \"id\") */\n\treadonly nodeId: string;\n\n\t/** Foreign key pointing to parent (e.g., \"parent_id\") */\n\treadonly parentId: string;\n\n\t/** Traversal direction */\n\treadonly direction: 'descendants' | 'ancestors';\n\n\t/** Filter applied to each step (e.g., active = true) */\n\treadonly stepWhere?: WhereIntent;\n}\n\n/**\n * Edge-table traversal (separate join table).\n * Example: role_inheritance(from_role_id, to_role_id)\n */\nexport interface EdgeTableTraversal {\n\treadonly kind: 'edge-table';\n\n\t/** Node table containing hierarchical data */\n\treadonly nodeTable: string;\n\n\t/** Edge table containing relationships */\n\treadonly edgeTable: string;\n\n\t/** Primary key column in node table (e.g., \"id\") */\n\treadonly nodeId: string;\n\n\t/** Source column in edge table (e.g., \"from_role_id\") */\n\treadonly edgeFrom: string;\n\n\t/** Target column in edge table (e.g., \"to_role_id\") */\n\treadonly edgeTo: string;\n\n\t/** Traversal direction */\n\treadonly direction: 'out' | 'in' | 'both';\n\n\t/** Filter on edges (e.g., relationship_type = 'inheritance') */\n\treadonly edgeWhere?: WhereIntent;\n\n\t/** Filter on nodes (e.g., active = true) */\n\treadonly nodeWhere?: WhereIntent;\n\n\t/** Edge attributes to include in result */\n\treadonly edgeSelect?: readonly string[];\n\n\t/**\n\t * Hint for edge storage semantics (only affects `direction: 'both'`).\n\t *\n\t * - 'unknown' (default): Edges may exist in both directions (A→B and B→A).\n\t * Uses UNION (distinct) to avoid duplicates. Safe but slower.\n\t * - 'directed-only': Caller guarantees edges are stored once only.\n\t * Uses UNION ALL for performance. INCORRECT if duplicates exist.\n\t */\n\treadonly edgeStorageHint?: 'unknown' | 'directed-only';\n}\n\n/**\n * Custom traversal for complex cases (P2 escape hatch).\n */\nexport interface CustomTraversal {\n\treadonly kind: 'custom';\n\t/** Explicit step query builder - reserved for P2 */\n\treadonly stepBuilder?: unknown;\n}\n\n/**\n * Recursive traversal type union.\n */\nexport type RecursiveTraversal =\n\t| AdjacencyTraversal\n\t| EdgeTableTraversal\n\t| CustomTraversal;\n\n/**\n * Tracking options for recursive traversal.\n */\nexport interface RecursiveTrackOptions {\n\t/** Depth counter (starts at 0) */\n\treadonly depth?: {\n\t\treadonly as?: string; // Default: \"depth\"\n\t};\n\n\t/** Path tracking for cycle detection + debugging */\n\treadonly path?: {\n\t\t/** Columns to trace in path (default: nodeId only) */\n\t\treadonly by?: 'nodeId' | readonly string[];\n\t\t/** Result column name (default: \"path\") */\n\t\treadonly as?: string;\n\t\t/** Storage strategy (default: 'array' for PostgreSQL, 'string' for others) */\n\t\treadonly strategy?: 'array' | 'string';\n\t\t/** Separator for string strategy (default: '/') */\n\t\treadonly separator?: string;\n\t};\n\n\t/** Cycle detection marker */\n\treadonly isCycle?: {\n\t\treadonly as?: string; // Default: \"is_cycle\"\n\t};\n}\n\n/**\n * Join clause for CTE emit composition.\n * Allows joining the CTE result with additional tables for final projection.\n */\nexport interface EmitJoinClause {\n\t/** Table to join with */\n\treadonly table: string;\n\n\t/** Join type (default: 'inner') */\n\treadonly type?: 'inner' | 'left';\n\n\t/** Alias for this table (auto-generated if not provided) */\n\treadonly as?: string;\n\n\t/** Join condition */\n\treadonly on: {\n\t\t/** Column from CTE or previous joined table */\n\t\treadonly left: string;\n\t\t/** Column from this table */\n\t\treadonly right: string;\n\t};\n\n\t/** Columns to select from this table */\n\treadonly select?: readonly (\n\t\t| string\n\t\t| { readonly column: string; readonly as: string }\n\t)[];\n}\n\n/**\n * Emit options for recursive CTE final projection.\n */\nexport interface RecursiveEmitOptions {\n\t/** Fields to select from CTE */\n\treadonly select?: readonly string[];\n\t/** Filter on generated rows */\n\treadonly where?: WhereIntent;\n\t/** Ordering */\n\treadonly orderBy?: readonly OrderByIntent[];\n\t/** Join CTE result with additional tables for composition */\n\treadonly joinWith?: readonly EmitJoinClause[];\n\t/** Apply DISTINCT to final result */\n\treadonly distinct?: boolean;\n}\n\n/**\n * PostgreSQL-specific options for recursive CTE (capability-gated).\n */\nexport interface RecursiveAdvancedOptions {\n\t/**\n\t * Cycle detection strategy (adapter-specific implementation).\n\t * - 'error': Throw on cycle detection\n\t * - 'stop': Stop traversal at cycle (prune branch)\n\t * - 'mark': Add is_cycle column to results\n\t *\n\t * PostgreSQL 14+ uses native CYCLE clause.\n\t * Other adapters may use application-level detection.\n\t */\n\treadonly cycle?: 'error' | 'stop' | 'mark';\n\n\t/**\n\t * Traversal search order (adapter-specific implementation).\n\t * - 'depth': Depth-first search order\n\t * - 'breadth': Breadth-first search order\n\t *\n\t * PostgreSQL 14+ uses native SEARCH clause.\n\t * Other adapters may use ORDER BY on depth column.\n\t */\n\treadonly search?: 'depth' | 'breadth';\n}\n\n/**\n * Deduplication strategy for recursive CTE.\n *\n * - 'none': No dedup. May return same node multiple times via different paths.\n * Fastest. Use when you need all paths or when graph is known to be a tree.\n *\n * - 'final': One row per nodeId in final output.\n * Implemented via `DISTINCT ON (nodeId)` (PostgreSQL) or\n * `ROW_NUMBER() OVER (PARTITION BY nodeId)` fallback.\n * ⚠️ NOT the same as `query.distinct()` which dedupes on entire row!\n *\n * Note: 'global' (UNION instead of UNION ALL) was considered but not implemented.\n * 'final' provides the same end result with better performance characteristics.\n */\nexport type RecursiveDedupe = 'none' | 'final';\n\n/**\n * Recursive CTE intent for hierarchical data traversal.\n *\n * Key invariant: anchor and step MUST produce identical column shape.\n * The planner validates this and auto-injects nodeIdExpr.\n *\n * @see RFC-001 for detailed specification\n */\nexport interface RecursiveIntent {\n\treadonly type: 'recursive';\n\n\t/** CTE name for the recursive query */\n\treadonly cteName: string;\n\n\t// ─────────────────────────────────────────────────────────────────────────\n\t// START (anchor/seed)\n\t// ─────────────────────────────────────────────────────────────────────────\n\n\treadonly start: {\n\t\t/** Source table for anchor query */\n\t\treadonly from: string;\n\n\t\t/** Filter for seed rows (e.g., where id = $userId) */\n\t\treadonly where?: WhereIntent;\n\n\t\t/**\n\t\t * REQUIRED: Expression for node ID. Auto-injected into select.\n\t\t * This ensures the recursive join always has the key column.\n\t\t */\n\t\treadonly nodeIdExpr: RecursiveNodeIdExpr;\n\n\t\t/** Additional fields to select (beyond nodeId) */\n\t\treadonly select?: readonly string[];\n\t};\n\n\t// ─────────────────────────────────────────────────────────────────────────\n\t// TRAVERSAL\n\t// ─────────────────────────────────────────────────────────────────────────\n\n\t/** Traversal configuration (adjacency-list or edge-table) */\n\treadonly traversal: RecursiveTraversal;\n\n\t// ─────────────────────────────────────────────────────────────────────────\n\t// TRACKING (system columns)\n\t// ─────────────────────────────────────────────────────────────────────────\n\n\t/** Tracking options for depth, path, and cycle detection */\n\treadonly track?: RecursiveTrackOptions;\n\n\t// ─────────────────────────────────────────────────────────────────────────\n\t// SAFETY\n\t// ─────────────────────────────────────────────────────────────────────────\n\n\t/** Maximum recursion depth (REQUIRED) */\n\treadonly maxDepth: number;\n\n\t/** Maximum rows (optional safety limit) */\n\treadonly maxRows?: number;\n\n\t/** Deduplication strategy */\n\treadonly dedupe?: RecursiveDedupe;\n\n\t// ─────────────────────────────────────────────────────────────────────────\n\t// EMIT (final projection)\n\t// ─────────────────────────────────────────────────────────────────────────\n\n\t/** Final projection options */\n\treadonly emit?: RecursiveEmitOptions;\n\n\t// ─────────────────────────────────────────────────────────────────────────\n\t// ADVANCED OPTIONS (capability-gated, adapter-specific implementation)\n\t// ─────────────────────────────────────────────────────────────────────────\n\n\t/** Advanced recursive options (cycle detection, search order) */\n\treadonly advancedOptions?: RecursiveAdvancedOptions;\n}\n","/**\n * NQL-origin SELECT function allowlist.\n *\n * This is the shared security gate for function names that originated in NQL\n * SELECT text and later cross the IntentAST-to-SQL adapter boundary. Extend it\n * only after adding compiler and adapter coverage proving the function is\n * intentionally supported for NQL-origin SELECT projections.\n */\nexport const NQL_SELECT_AGGREGATE_FUNCTIONS = [\n\t'count',\n\t'sum',\n\t'avg',\n\t'min',\n\t'max',\n] as const;\n\nexport const NQL_SELECT_JSON_FUNCTIONS = [\n\t'json_extract',\n\t'json_extract_text',\n\t'json_path',\n\t'json_path_text',\n] as const;\n\nexport const NQL_SELECT_VALUE_FUNCTIONS = [\n\t'coalesce',\n\t'lower',\n\t'now',\n\t'round',\n\t'upper',\n] as const;\n\nexport const NQL_SELECT_SCALAR_FUNCTIONS = [\n\t...NQL_SELECT_AGGREGATE_FUNCTIONS,\n\t...NQL_SELECT_JSON_FUNCTIONS,\n\t...NQL_SELECT_VALUE_FUNCTIONS,\n] as const;\n\nexport const NQL_SELECT_WINDOW_ONLY_FUNCTIONS = [\n\t'row_number',\n\t'rank',\n\t'dense_rank',\n\t'lag',\n\t'lead',\n] as const;\n\nexport const NQL_SELECT_WINDOW_FUNCTIONS = [\n\t...NQL_SELECT_WINDOW_ONLY_FUNCTIONS,\n\t'count',\n\t'sum',\n\t'avg',\n\t'min',\n\t'max',\n] as const;\n\nexport const NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST: ReadonlySet<string> =\n\tnew Set(NQL_SELECT_SCALAR_FUNCTIONS);\n\nexport const NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST: ReadonlySet<string> =\n\tnew Set(NQL_SELECT_WINDOW_FUNCTIONS);\n\nexport const NQL_SELECT_FUNCTION_ALLOWLIST: ReadonlySet<string> = new Set([\n\t...NQL_SELECT_SCALAR_FUNCTIONS,\n\t...NQL_SELECT_WINDOW_FUNCTIONS,\n]);\n\ntype NqlSelectScalarFunction = (typeof NQL_SELECT_SCALAR_FUNCTIONS)[number];\ntype NqlSelectWindowFunction = (typeof NQL_SELECT_WINDOW_FUNCTIONS)[number];\n\nexport function isNqlSelectScalarFunctionAllowed(\n\tname: string,\n): name is NqlSelectScalarFunction {\n\treturn NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST.has(name.toLowerCase());\n}\n\nexport function isNqlSelectFunctionAllowed(name: string): boolean {\n\treturn NQL_SELECT_FUNCTION_ALLOWLIST.has(name.toLowerCase());\n}\n\nexport function isNqlSelectWindowFunctionAllowed(\n\tname: string,\n): name is NqlSelectWindowFunction {\n\treturn NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST.has(name.toLowerCase());\n}\n","/**\n * @module intent/type-guards\n * Type guard functions for all intent AST types.\n */\n\nimport type {\n\tAggregateWindowFunction,\n\tCoalesceExpressionIntent,\n\tColumnAliasIntent,\n\tExpressionIntent,\n\tOffsetWindowFunction,\n\tRankingWindowFunction,\n\tRawExpressionIntent,\n\tRelationColumnIntent,\n\tWindowFunction,\n\tWindowIntent,\n} from './expression-intent.js';\nimport type {\n\tDeleteIntent,\n\tInsertIntent,\n\tMutationIntent,\n\tUpdateIntent,\n\tUpsertIntent,\n} from './mutation-intent.js';\nimport type { QueryIntent } from './query-intent.js';\nimport type {\n\tAdjacencyTraversal,\n\tCustomTraversal,\n\tEdgeTableTraversal,\n\tRecursiveIntent,\n\tRecursiveTraversal,\n} from './recursive-intent.js';\nimport type {\n\tSelectAggregateIntent,\n\tSelectAllIntent,\n\tSelectFieldsIntent,\n\tSelectIntent,\n\tSelectWithExpressionsIntent,\n} from './select-intent.js';\nimport type {\n\tSubqueryRefIntent,\n\tWhereAndIntent,\n\tWhereAnyIntent,\n\tWhereComparisonIntent,\n\tWhereExistsIntent,\n\tWhereInIntent,\n\tWhereIntent,\n\tWhereLikeIntent,\n\tWhereNotExistsIntent,\n\tWhereNotIntent,\n\tWhereNullIntent,\n\tWhereOrIntent,\n\tWhereRangeIntent,\n\tWhereRelationFilterIntent,\n\tWhereSubqueryIntent,\n} from './where-intent.js';\n\n// ============================================================================\n// Window Intent Type Guards\n// ============================================================================\n\n/**\n * Check if an intent is a window function intent\n */\nexport function isWindowIntent(intent: unknown): intent is WindowIntent {\n\treturn (\n\t\ttypeof intent === 'object' &&\n\t\tintent !== null &&\n\t\t'kind' in intent &&\n\t\t(intent as Record<string, unknown>).kind === 'window'\n\t);\n}\n\n/**\n * Check if a window function requires a field (aggregate or offset functions)\n */\nexport function isAggregateWindowFunction(\n\tfn: WindowFunction,\n): fn is AggregateWindowFunction | OffsetWindowFunction {\n\treturn ['sum', 'avg', 'count', 'min', 'max', 'lag', 'lead'].includes(fn);\n}\n\n/**\n * Check if a window function is a ranking function (no field required)\n */\nexport function isRankingWindowFunction(\n\tfn: WindowFunction,\n): fn is RankingWindowFunction {\n\treturn ['row_number', 'rank', 'dense_rank'].includes(fn);\n}\n\n// ============================================================================\n// Where Intent Type Guards\n// ============================================================================\n\n/**\n * Check if a where intent is a comparison\n */\nexport function isWhereComparison(\n\twhere: WhereIntent,\n): where is WhereComparisonIntent {\n\treturn where.kind === 'comparison';\n}\n\n/**\n * Check if a where intent is a like filter\n */\nexport function isWhereLike(where: WhereIntent): where is WhereLikeIntent {\n\treturn where.kind === 'like';\n}\n\n/**\n * Check if a where intent is a subquery filter\n */\nexport function isWhereSubquery(\n\twhere: WhereIntent,\n): where is WhereSubqueryIntent {\n\treturn where.kind === 'subquery';\n}\n\n/**\n * Check if a value is a subquery ref (column reference in subquery)\n */\nexport function isSubqueryRef(value: unknown): value is SubqueryRefIntent {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'kind' in value &&\n\t\t(value as Record<string, unknown>).kind === 'ref'\n\t);\n}\n\n/**\n * Check if a where intent is an in filter\n */\nexport function isWhereIn(where: WhereIntent): where is WhereInIntent {\n\treturn where.kind === 'in';\n}\n\n/**\n * Check if a where intent is an any filter (= ANY($N::type[]))\n */\nexport function isWhereAny(where: WhereIntent): where is WhereAnyIntent {\n\treturn where.kind === 'any';\n}\n\n/**\n * Check if a where intent is a null filter\n */\nexport function isWhereNull(where: WhereIntent): where is WhereNullIntent {\n\treturn where.kind === 'null';\n}\n\n/**\n * Check if a where intent is a range filter (PostgreSQL range types)\n */\nexport function isWhereRange(where: WhereIntent): where is WhereRangeIntent {\n\treturn where.kind === 'range';\n}\n\n/**\n * Check if a where intent is a logical AND\n */\nexport function isWhereAnd(where: WhereIntent): where is WhereAndIntent {\n\treturn where.kind === 'and';\n}\n\n/**\n * Check if a where intent is a logical OR\n */\nexport function isWhereOr(where: WhereIntent): where is WhereOrIntent {\n\treturn where.kind === 'or';\n}\n\n/**\n * Check if a where intent is a logical NOT\n */\nexport function isWhereNot(where: WhereIntent): where is WhereNotIntent {\n\treturn where.kind === 'not';\n}\n\n/**\n * Check if a where intent is an exists filter\n */\nexport function isWhereExists(where: WhereIntent): where is WhereExistsIntent {\n\treturn where.kind === 'exists';\n}\n\n/**\n * Check if a where intent is a not exists filter\n */\nexport function isWhereNotExists(\n\twhere: WhereIntent,\n): where is WhereNotExistsIntent {\n\treturn where.kind === 'notExists';\n}\n\n/**\n * Check if a where intent is a relation filter\n */\nexport function isWhereRelationFilter(\n\twhere: WhereIntent,\n): where is WhereRelationFilterIntent {\n\treturn where.kind === 'relationFilter';\n}\n\n/**\n * Check if a where intent is any relation-based filter\n */\nexport function isWhereRelationBased(\n\twhere: WhereIntent,\n): where is\n\t| WhereExistsIntent\n\t| WhereNotExistsIntent\n\t| WhereRelationFilterIntent {\n\treturn (\n\t\twhere.kind === 'exists' ||\n\t\twhere.kind === 'notExists' ||\n\t\twhere.kind === 'relationFilter'\n\t);\n}\n\n/**\n * Check if a where intent is a logical operator (and/or/not)\n */\nexport function isWhereLogical(\n\twhere: WhereIntent,\n): where is WhereAndIntent | WhereOrIntent | WhereNotIntent {\n\treturn where.kind === 'and' || where.kind === 'or' || where.kind === 'not';\n}\n\n// ============================================================================\n// Select Intent Type Guards\n// ============================================================================\n\n/**\n * Check if a select intent selects all columns\n */\nexport function isSelectAll(select: SelectIntent): select is SelectAllIntent {\n\treturn select.type === 'all';\n}\n\n/**\n * Check if a select intent selects specific fields\n */\nexport function isSelectFields(\n\tselect: SelectIntent,\n): select is SelectFieldsIntent {\n\treturn select.type === 'fields';\n}\n\n/**\n * Check if a select intent is an aggregate select\n */\nexport function isSelectAggregate(\n\tselect: SelectIntent,\n): select is SelectAggregateIntent {\n\treturn select.type === 'aggregate';\n}\n\n/**\n * Check if a select intent has expressions\n */\nexport function isSelectWithExpressions(\n\tselect: SelectIntent,\n): select is SelectWithExpressionsIntent {\n\treturn select.type === 'expressions';\n}\n\n// ============================================================================\n// Expression Intent Type Guards\n// ============================================================================\n\n/**\n * Check if an expression is a COALESCE expression\n */\nexport function isCoalesceExpression(\n\texpr: ExpressionIntent,\n): expr is CoalesceExpressionIntent {\n\treturn expr.kind === 'coalesce';\n}\n\n/**\n * Check if an expression is a raw SQL expression\n */\nexport function isRawExpression(\n\texpr: ExpressionIntent,\n): expr is RawExpressionIntent {\n\treturn expr.kind === 'raw';\n}\n\n/**\n * Check if an expression is a column alias expression\n */\nexport function isColumnAliasExpression(\n\texpr: ExpressionIntent,\n): expr is ColumnAliasIntent {\n\treturn expr.kind === 'columnAlias';\n}\n\n/**\n * Check if an expression is a relation column expression\n */\nexport function isRelationColumnExpression(\n\texpr: ExpressionIntent,\n): expr is RelationColumnIntent {\n\treturn expr.kind === 'relationColumn';\n}\n\n// ============================================================================\n// Recursive CTE Type Guards\n// ============================================================================\n\n/**\n * Check if a traversal is adjacency-list based\n */\nexport function isAdjacencyTraversal(\n\ttraversal: RecursiveTraversal,\n): traversal is AdjacencyTraversal {\n\treturn traversal.kind === 'adjacency';\n}\n\n/**\n * Check if a traversal is edge-table based\n */\nexport function isEdgeTableTraversal(\n\ttraversal: RecursiveTraversal,\n): traversal is EdgeTableTraversal {\n\treturn traversal.kind === 'edge-table';\n}\n\n/**\n * Check if a traversal is custom\n */\nexport function isCustomTraversal(\n\ttraversal: RecursiveTraversal,\n): traversal is CustomTraversal {\n\treturn traversal.kind === 'custom';\n}\n\n/**\n * Check if an intent is a recursive CTE intent\n */\nexport function isRecursiveIntent(\n\tintent: QueryIntent | RecursiveIntent,\n): intent is RecursiveIntent {\n\treturn intent.type === 'recursive';\n}\n\n// ============================================================================\n// Mutation Intent Type Guards\n// ============================================================================\n\n/**\n * Check if an intent is an insert intent\n */\nexport function isInsertIntent(\n\tintent: QueryIntent | RecursiveIntent | MutationIntent,\n): intent is InsertIntent {\n\treturn intent.type === 'insert';\n}\n\n/**\n * Check if an intent is an update intent\n */\nexport function isUpdateIntent(\n\tintent: QueryIntent | RecursiveIntent | MutationIntent,\n): intent is UpdateIntent {\n\treturn intent.type === 'update';\n}\n\n/**\n * Check if an intent is a delete intent\n */\nexport function isDeleteIntent(\n\tintent: QueryIntent | RecursiveIntent | MutationIntent,\n): intent is DeleteIntent {\n\treturn intent.type === 'delete';\n}\n\n/**\n * Check if an intent is an upsert intent (DX-026)\n */\nexport function isUpsertIntent(\n\tintent: QueryIntent | RecursiveIntent | MutationIntent,\n): intent is UpsertIntent {\n\treturn intent.type === 'upsert';\n}\n\n/**\n * Check if an intent is any mutation intent\n */\nexport function isMutationIntent(\n\tintent: QueryIntent | RecursiveIntent | MutationIntent,\n): intent is MutationIntent {\n\treturn (\n\t\tintent.type === 'insert' ||\n\t\tintent.type === 'insert_from' ||\n\t\tintent.type === 'upsert_from' ||\n\t\tintent.type === 'update' ||\n\t\tintent.type === 'batchUpdate' ||\n\t\tintent.type === 'delete' ||\n\t\tintent.type === 'upsert'\n\t);\n}\n","/**\n * @module intent/where-intent\n * Where intent types for filter conditions.\n */\n\nimport type { ColumnListInput } from '../column-list.js';\nimport type { RangeValue } from '../shared/utils.js';\nimport type {\n\tExpressionIntent,\n\tParamIntent,\n\tStandaloneWhereExpressionIntent,\n} from './expression-intent.js';\nimport type { ComparisonOperator, NullOperator } from './operators.js';\nimport type { QueryIntent } from './query-intent.js';\nimport type { RecursiveExistsOptions } from './recursive-types.js';\n\nexport type { RangeValue };\n\n// ============================================================================\n// Where Intent - Filter Conditions\n// ============================================================================\n\n/**\n * Typed field reference for cross-table column comparisons in relation filters.\n *\n * When using aliased relation filters like `some(orders as o, o.total > minOrder)`,\n * the RHS `minOrder` is a reference to the parent table's column, not a literal value.\n * FieldRef captures this distinction so the adapter can compile it as a column reference\n * instead of a parameterized value.\n *\n * @example\n * // some(rel as r, r.col > bareCol) → value: { kind: 'fieldRef', column: 'bareCol', scope: 'outer' }\n * // some(rel as r, r.col > r.otherCol) → value: { kind: 'fieldRef', column: 'otherCol', scope: 'inner' }\n * // some(a as x, some(b as y, y.f > x.g)) → value: { kind: 'fieldRef', column: 'g', scope: 'outer', alias: 'x' }\n */\nexport interface FieldRef {\n\treadonly kind: 'fieldRef';\n\treadonly column: string;\n\treadonly scope: 'inner' | 'outer';\n\t/** Named alias for outer scope (when referencing a specific outer alias in nested filters) */\n\treadonly alias?: string;\n}\n\n/**\n * Type guard for FieldRef values\n */\nexport function isFieldRef(value: unknown): value is FieldRef {\n\treturn (\n\t\tvalue !== null &&\n\t\ttypeof value === 'object' &&\n\t\t(value as Record<string, unknown>).kind === 'fieldRef'\n\t);\n}\n\nexport interface WhereComparisonIntent {\n\treadonly kind: 'comparison';\n\treadonly field: string;\n\treadonly operator: ComparisonOperator;\n\treadonly value: unknown;\n\t/** JSON path extraction before comparison (e.g., data->'key' = 'val') */\n\treadonly jsonPath?: readonly (string | ParamIntent)[];\n\t/** JSON extraction mode: 'json' = ->, 'text' = ->> */\n\treadonly jsonMode?: 'json' | 'text';\n}\n\n/**\n * String filter: field like pattern\n */\nexport interface WhereLikeIntent {\n\treadonly kind: 'like';\n\treadonly field: string;\n\treadonly pattern: string | ParamIntent;\n\t/** Case-insensitive matching */\n\treadonly caseInsensitive?: boolean;\n\t/** Escape character for LIKE pattern (e.g. '\\\\' to escape _ and %) */\n\treadonly escape?: string;\n}\n\n/**\n * Array filter: field in [values]\n */\n/**\n * Array filter (values branch): field IN (v1, v2, ...)\n */\nexport interface WhereInValueIntent {\n\treadonly kind: 'in';\n\treadonly field: string;\n\treadonly values: readonly unknown[];\n\treadonly subquery?: never;\n\treadonly not?: boolean;\n}\n\n/**\n * Array filter (subquery branch): field IN (SELECT ...)\n */\nexport interface WhereInSubqueryIntent {\n\treadonly kind: 'in';\n\treadonly field: string;\n\treadonly subquery: QueryIntent;\n\treadonly values?: never;\n\treadonly not?: boolean;\n}\n\n/**\n * Array filter: field in [values] OR field IN (subquery)\n * XOR: exactly one of `values` or `subquery` must be present.\n */\nexport type WhereInIntent = WhereInValueIntent | WhereInSubqueryIntent;\n\n/**\n * Array membership filter using PostgreSQL ANY() operator.\n * Compiles to: \"col\" = ANY($N::type[])\n */\nexport interface WhereAnyIntent {\n\treadonly kind: 'any';\n\treadonly field: string;\n\treadonly values: readonly unknown[] | ParamIntent;\n}\n\n/**\n * Operand accepted by range WHERE filters.\n * - RangeValue: for range-to-range operators (overlaps, contains, containedBy)\n * - string: ISO date/timestamp literals (e.g. '2025-01-15', '2025-01-15T08:00:00Z')\n * - number: integer/numeric point values (e.g. 50000 for salary_range @> 50000)\n * - boolean: rarely used but valid PostgreSQL range operand\n */\nexport type RangeOperand = RangeValue | string | number | boolean;\n\n/**\n * Range operator for PostgreSQL range types.\n * - overlaps: && (ranges have common points)\n * - contains: @> (range contains value or range)\n * - containedBy: <@ (range is contained by another range)\n */\nexport type RangeOperator = 'overlaps' | 'contains' | 'containedBy' | 'between';\n\n/**\n * Range filter: field overlaps/contains/containedBy range value\n * PostgreSQL range types: daterange, tsrange, tstzrange, int4range, int8range, numrange\n *\n * @example\n * // Check if booking dates overlap a period\n * { kind: 'range', field: 'dates', operator: 'overlaps', value: { lower: '2025-01-15', upper: '2025-01-20' } }\n *\n * // Check if salary range contains a value\n * { kind: 'range', field: 'salary_range', operator: 'contains', value: 50000 }\n */\n/**\n * Range filter: field overlaps/contains/containedBy range value\n * PostgreSQL range types: daterange, tsrange, tstzrange, int4range, int8range, numrange\n *\n * @example\n * // Check if booking dates overlap a period\n * { kind: 'range', field: 'dates', operator: 'overlaps', value: { lower: '2025-01-15', upper: '2025-01-20' } }\n *\n * // Check if salary range contains a value\n * { kind: 'range', field: 'salary_range', operator: 'contains', value: 50000 }\n */\nexport interface WhereRangeIntent {\n\treadonly kind: 'range';\n\treadonly field: string;\n\treadonly operator: RangeOperator;\n\t/** Operand: RangeValue for range-to-range ops, or a scalar (string | number | boolean) for point-in-range ops */\n\treadonly value: RangeOperand;\n}\n\n/**\n * Null filter: field is null / is not null\n */\nexport interface WhereNullIntent {\n\treadonly kind: 'null';\n\treadonly field: string;\n\treadonly operator: NullOperator;\n}\n\n/**\n * Logical AND: all conditions must match\n */\nexport interface WhereAndIntent {\n\treadonly kind: 'and';\n\treadonly conditions: readonly WhereIntent[];\n}\n\n/**\n * Logical OR: at least one condition must match\n */\nexport interface WhereOrIntent {\n\treadonly kind: 'or';\n\treadonly conditions: readonly WhereIntent[];\n}\n\n/**\n * Logical NOT: condition must not match\n */\nexport interface WhereNotIntent {\n\treadonly kind: 'not';\n\treadonly condition: WhereIntent;\n}\n\n/**\n * Relation exists filter: filter by existence of related records\n * Critical for Q1 golden test - enables EXISTS subquery strategy\n *\n * @example\n * // Find users who have at least one published post\n * { kind: 'exists', relation: 'posts', where: { kind: 'comparison', field: 'status', operator: 'eq', value: 'published' } }\n */\nexport interface WhereExistsIntent {\n\treadonly kind: 'exists';\n\t/** Relation name to check existence */\n\treadonly relation: string;\n\t/** Optional filter on related records */\n\treadonly where?: WhereIntent;\n\t/**\n\t * Recursive options for ancestor/descendant existence checks.\n\t * When present, generates a recursive CTE instead of simple EXISTS.\n\t */\n\treadonly recursive?: RecursiveExistsOptions;\n\t/**\n\t * Optional JOIN declarations inside the EXISTS subquery.\n\t * Keys are relation names (used as aliases), values specify join type.\n\t * Enables filtering on joined tables inside the subquery.\n\t *\n\t * @example\n\t * exists('callers', {\n\t * include: { callerFile: { join: 'inner' } },\n\t * where: eq('callerFile.project_id', projectId)\n\t * })\n\t */\n\treadonly include?: Readonly<Record<string, { join?: 'inner' | 'left' }>>;\n}\n\n/**\n * Relation not exists filter: filter by absence of related records\n *\n * @example\n * // Find users who have no posts\n * { kind: 'notExists', relation: 'posts' }\n */\nexport interface WhereNotExistsIntent {\n\treadonly kind: 'notExists';\n\t/** Relation name to check absence */\n\treadonly relation: string;\n\t/** Optional filter on related records */\n\treadonly where?: WhereIntent;\n\t/**\n\t * Recursive options for ancestor/descendant absence checks.\n\t * When present, generates a recursive CTE instead of simple NOT EXISTS.\n\t */\n\treadonly recursive?: RecursiveExistsOptions;\n\t/**\n\t * Optional JOIN declarations inside the NOT EXISTS subquery.\n\t * Keys are relation names (used as aliases), values specify join type.\n\t * Enables filtering on joined tables inside the subquery.\n\t *\n\t * @example\n\t * notExists('callers', {\n\t * include: { callerFile: { join: 'inner' } },\n\t * where: eq('callerFile.project_id', projectId)\n\t * })\n\t */\n\treadonly include?: Readonly<Record<string, { join?: 'inner' | 'left' }>>;\n}\n\n/**\n * Raw EXISTS subquery filter using an arbitrary QueryIntent.\n * Unlike WhereExistsIntent (which uses FK-resolved relation names),\n * this wraps a fully-specified subquery for correlated EXISTS checks.\n *\n * @example\n * // EXISTS (SELECT 1 FROM symbols WHERE symbols.id = calls.symbol_id AND ...)\n * exists(subquery('symbols').where(eq('id', ref('calls.symbol_id'))))\n */\nexport interface WhereRawExistsIntent {\n\treadonly kind: 'rawExists';\n\t/** The subquery producing rows for the EXISTS check */\n\treadonly subquery: QueryIntent;\n}\n\n/**\n * Raw NOT EXISTS subquery filter using an arbitrary QueryIntent.\n *\n * @example\n * // NOT EXISTS (SELECT 1 FROM symbols WHERE ...)\n * notExists(subquery('symbols').where(...))\n */\nexport interface WhereRawNotExistsIntent {\n\treadonly kind: 'rawNotExists';\n\t/** The subquery producing rows for the NOT EXISTS check */\n\treadonly subquery: QueryIntent;\n}\n\n/**\n * Relation filter: filter parent by conditions on related records\n * More flexible than exists - allows filtering by related record attributes\n *\n * @example\n * // Find users whose latest post was created in 2024\n * { kind: 'relationFilter', relation: 'posts', where: {...}, mode: 'some' }\n */\nexport interface WhereRelationFilterIntent {\n\treadonly kind: 'relationFilter';\n\t/**\n\t * Relation path for filtering.\n\t * - Single relation: 'posts' or ['posts']\n\t * - Multi-hop (SPEC-002): ['author', 'company'] for author.company traversal\n\t */\n\treadonly relation: string | readonly string[];\n\t/** Filter conditions on related records */\n\treadonly where: WhereIntent;\n\t/**\n\t * Match mode:\n\t * - 'some': At least one related record matches (default)\n\t * - 'every': All related records match\n\t * - 'none': No related records match\n\t */\n\treadonly mode: 'some' | 'every' | 'none';\n\t/** Optional alias for complex conditions (SPEC-002) */\n\treadonly alias?: string | undefined;\n\t/**\n\t * Optional display/debug metadata for pre-resolved relation filters.\n\t * These fields are not trusted for compilation. Internal compiler paths that\n\t * prove a virtual source maps to a real model relation use a module-private\n\t * proof payload instead.\n\t */\n\treadonly targetTable?: string | undefined;\n\treadonly sourceColumn?: ColumnListInput;\n\treadonly targetColumn?: ColumnListInput;\n}\n\n// ============================================================================\n// Subquery Intent - Scalar Subquery in WHERE\n// ============================================================================\n\n/**\n * Reference to a parent query column in a subquery.\n * Used to create correlated subqueries.\n *\n * The `outer` field is a discriminator set by `outerRef()` in\n * `@dbsp/core` to distinguish a genuine outer-query reference from an\n * inner `ref()` expression (RefExpressionIntent), which has the same\n * structural shape `{ kind: 'ref', column }`. Converters that need to\n * detect correlated subqueries check `outer === true`; an intent built\n * without `outer` (i.e. a plain `{ kind: 'ref', column }`) is treated\n * as a non-correlated inner expression reference.\n *\n * @example\n * // Outer reference produced by outerRef('id'):\n * { kind: 'ref', column: 'id', outer: true }\n *\n * // Inner column reference (not a correlated outer ref):\n * { kind: 'ref', column: 'id' } // outer is absent / undefined\n */\nexport interface SubqueryRefIntent {\n\treadonly kind: 'ref';\n\t/** Column name or aliased column (e.g., 'id' or 't0.id') */\n\treadonly column: string;\n\t/**\n\t * Discriminator that marks this as a genuine outer-query reference\n\t * (set by `outerRef()`). Absent on plain inner expression refs.\n\t * Optional so that existing raw intents built per the type without\n\t * this field remain valid (non-breaking addition).\n\t */\n\treadonly outer?: true;\n}\n\n/**\n * Subquery intent for scalar subquery comparisons.\n * Produces correlated subqueries in SQL.\n *\n * @example\n * // Find products where price equals max price of category\n * {\n * kind: 'subquery',\n * field: 'price',\n * operator: 'eq',\n * subquery: { from: 'products', select: { kind: 'aggregate', fn: 'max', field: 'price' } }\n * }\n */\nexport interface WhereSubqueryIntent {\n\treadonly kind: 'subquery';\n\t/** Field to compare on the parent query */\n\treadonly field: string;\n\t/** Comparison operator */\n\treadonly operator: ComparisonOperator;\n\t/** Subquery producing scalar value */\n\treadonly subquery: QueryIntent;\n}\n\n// ============================================================================\n// JSON/JSONB WHERE Intents (E13)\n// ============================================================================\n\n/**\n * JSON containment filter: col @> value or col <@ value.\n * @example { kind: 'jsonContains', field: 'data', value: '{\"active\":true}', reversed: false }\n * → WHERE \"data\" @> $1\n */\nexport interface WhereJsonContainsIntent {\n\treadonly kind: 'jsonContains';\n\treadonly field: string;\n\treadonly value: unknown;\n\t/** false = @> (field contains value), true = <@ (field contained by value) */\n\treadonly reversed: boolean;\n}\n\n/**\n * JSON key existence filter: col ? 'key'.\n * @example { kind: 'jsonExists', field: 'data', key: 'email' }\n * → WHERE \"data\" ? $1\n */\nexport interface WhereJsonExistsIntent {\n\treadonly kind: 'jsonExists';\n\treadonly field: string;\n\treadonly key: string | ParamIntent;\n}\n\n/** WHERE clause using a custom expression, optionally compared to a value. */\nexport type WhereExpressionIntent =\n\t| {\n\t\t\treadonly kind: 'expression';\n\t\t\treadonly expr: ExpressionIntent;\n\t\t\treadonly operator: ComparisonOperator;\n\t\t\treadonly value: unknown;\n\t }\n\t| {\n\t\t\treadonly kind: 'expression';\n\t\t\treadonly expr: StandaloneWhereExpressionIntent;\n\t\t\t/** A standalone expression that is already a SQL predicate. */\n\t\t\treadonly operator?: never;\n\t\t\treadonly value?: never;\n\t };\n\n/**\n * Where intent - filter conditions union type\n * Discriminated union using 'kind' field\n */\nexport type WhereIntent =\n\t| WhereComparisonIntent\n\t| WhereLikeIntent\n\t| WhereInIntent\n\t| WhereAnyIntent\n\t| WhereNullIntent\n\t| WhereRangeIntent\n\t| WhereAndIntent\n\t| WhereOrIntent\n\t| WhereNotIntent\n\t| WhereExistsIntent\n\t| WhereNotExistsIntent\n\t| WhereRawExistsIntent\n\t| WhereRawNotExistsIntent\n\t| WhereRelationFilterIntent\n\t| WhereSubqueryIntent\n\t| WhereJsonContainsIntent\n\t| WhereJsonExistsIntent\n\t| WhereExpressionIntent;\n","import { toColumnList } from './column-list.js';\nimport type { TableIR } from './model-ir.js';\n\n/**\n * Dialect-neutral json_agg order intent.\n *\n * `fallback` means the table has no declared primary key, so adapters should\n * realize the all-column deterministic fallback in their own dialect.\n */\nexport interface JsonAggOrderKey {\n\treadonly columns: readonly string[];\n\treadonly fallback: boolean;\n}\n\nexport function resolveJsonAggOrderKey(table: TableIR): JsonAggOrderKey {\n\tconst pkColumns = toColumnList(table.primaryKey);\n\treturn pkColumns.length > 0\n\t\t? { columns: pkColumns, fallback: false }\n\t\t: { columns: table.columns.map((col) => col.name), fallback: true };\n}\n","import type { ModelIR } from './model-ir.js';\n\n/**\n * Canonical shape of a `schema()` factory result as produced by\n * `createOrm({schema: ...})` callers and consumed by tooling\n * (cli, gui sidecar, mcp-server).\n *\n * ARCH-005: Schema type from schema() function.\n * Contains the definition, pre-computed ModelIR, and table names.\n */\nexport interface LoadedSchema {\n\treadonly definition: Record<string, unknown>;\n\t/** Retained schema() inputs used when per-object declarations are sliced. */\n\treadonly constraints?: unknown;\n\treadonly extras?: unknown;\n\treadonly options?: unknown;\n\treadonly model: ModelIR;\n\treadonly tableNames: readonly string[];\n}\n\nfunction isMap(value: unknown): value is Map<unknown, unknown> {\n\tif (typeof value !== 'object' || value === null) return false;\n\ttry {\n\t\tMap.prototype.has.call(value, undefined);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Runtime type guard for a `schema()` result. Checks the shapes, not just the\n * key names: the model's `tables` and `relations` must be real Maps and its\n * methods real functions, `definition` an object, and `tableNames` an array of\n * strings. Callers load these from disk and then call `.get()` / `.entries()`\n * on the model, so an object that merely has the right keys must not pass.\n *\n * It does not validate the schema's contents — only that this is a `schema()`\n * result rather than an arbitrary object.\n */\nexport function isValidSchema(schema: unknown): schema is LoadedSchema {\n\tif (\n\t\ttypeof schema !== 'object' ||\n\t\tschema === null ||\n\t\t!('model' in schema) ||\n\t\t!('definition' in schema) ||\n\t\t!('tableNames' in schema)\n\t) {\n\t\treturn false;\n\t}\n\tconst s = schema as LoadedSchema;\n\tif (typeof s.model !== 'object' || s.model === null) return false;\n\tif (!('tables' in s.model) || !('relations' in s.model)) return false;\n\tif (!isMap(s.model.tables)) return false;\n\tif (!isMap(s.model.relations)) return false;\n\tif (typeof s.definition !== 'object' || s.definition === null) return false;\n\tif (!Array.isArray(s.tableNames)) return false;\n\tif (s.tableNames.some((name) => typeof name !== 'string')) return false;\n\t// Validate required ModelIR methods are present\n\tif (typeof s.model.getTable !== 'function') return false;\n\tif (typeof s.model.getRelation !== 'function') return false;\n\tif (typeof s.model.getRelationsFrom !== 'function') return false;\n\tif (typeof s.model.getRelationsTo !== 'function') return false;\n\tif (typeof s.model.isAmbiguous !== 'function') return false;\n\treturn true;\n}\n","import type { ColumnJsReadType } from './model-ir.js';\n\nexport type OutputValueShape =\n\t| { readonly kind: 'scalar'; readonly cardinality: 'one' }\n\t| {\n\t\t\treadonly kind: 'array';\n\t\t\treadonly cardinality: 'many';\n\t\t\treadonly aggregate?: 'json_agg' | 'array_agg';\n\t }\n\t| {\n\t\t\treadonly kind: 'object';\n\t\t\treadonly cardinality: 'one';\n\t\t\treadonly aggregate?: 'json_agg';\n\t }\n\t| { readonly kind: 'aggregate-scalar'; readonly aggregate: string }\n\t| { readonly kind: 'unknown'; readonly reason: string };\n\nexport type OutputSource =\n\t| {\n\t\t\treadonly kind: 'modelColumn';\n\t\t\treadonly table: string;\n\t\t\treadonly column: string;\n\t\t\treadonly js?: ColumnJsReadType;\n\t }\n\t| { readonly kind: 'expression'; readonly reason: string }\n\t| { readonly kind: 'ambiguous'; readonly reason: string }\n\t| { readonly kind: 'unresolved'; readonly reason: string };\n\nexport type OutputDescriptor = {\n\treadonly outputKey: string;\n\treadonly source: OutputSource;\n\treadonly shape: OutputValueShape;\n};\n\nexport type OutputReadHandling =\n\t| {\n\t\t\treadonly kind: 'scalarConvert';\n\t\t\treadonly table: string;\n\t\t\treadonly column: string;\n\t\t\treadonly js: ColumnJsReadType;\n\t }\n\t| {\n\t\t\treadonly kind: 'nestedTransform';\n\t\t\treadonly table: string;\n\t\t\treadonly column: string;\n\t\t\treadonly js: ColumnJsReadType;\n\t\t\t/** Emitted nested JSON key; absent metadata keeps legacy column lookup. */\n\t\t\treadonly outputKey?: string;\n\t }\n\t| { readonly kind: 'none' };\n\nexport type NestedOutputReadHandling = Extract<\n\tOutputReadHandling,\n\t{ readonly kind: 'nestedTransform' }\n>;\n\nexport function resolveOutputReadHandling(\n\tdescriptor: OutputDescriptor,\n): OutputReadHandling {\n\tconst { source } = descriptor;\n\tif (source.kind !== 'modelColumn' || source.js === undefined) {\n\t\treturn { kind: 'none' };\n\t}\n\n\tswitch (descriptor.shape.kind) {\n\t\tcase 'scalar':\n\t\t\treturn {\n\t\t\t\tkind: 'scalarConvert',\n\t\t\t\ttable: source.table,\n\t\t\t\tcolumn: source.column,\n\t\t\t\tjs: source.js,\n\t\t\t};\n\t\tcase 'array':\n\t\tcase 'object':\n\t\t\treturn {\n\t\t\t\tkind: 'nestedTransform',\n\t\t\t\ttable: source.table,\n\t\t\t\tcolumn: source.column,\n\t\t\t\tjs: source.js,\n\t\t\t};\n\t\tcase 'aggregate-scalar':\n\t\tcase 'unknown':\n\t\t\treturn { kind: 'none' };\n\t}\n}\n","/** A dialect-neutral address of one declared or derived database name.\n *\n * `name` is always in the model's logical spelling. For derived objects it is\n * the template result from logical parts (for example `pk_<table>`), rather\n * than a database spelling.\n */\nexport type LogicalNameAddress =\n\t| {\n\t\t\treadonly kind: 'table' | 'enum' | 'sequence';\n\t\t\treadonly schema: string;\n\t\t\treadonly name: string;\n\t }\n\t| {\n\t\t\treadonly kind: 'column' | 'index' | 'constraint' | 'policy';\n\t\t\treadonly schema: string;\n\t\t\treadonly table: string;\n\t\t\treadonly name: string;\n\t };\n\nexport interface PhysicalNameEntry {\n\treadonly logical: LogicalNameAddress;\n\treadonly physical: string;\n\t/** Sequence entries distinguish authored declarations from serial/identity predictions. */\n\treadonly sequenceProvenance?: 'declared' | 'generated';\n}\n\nexport class PhysicalNameInventoryDuplicateError extends Error {\n\tconstructor(\n\t\tpublic readonly scope: 'logical-address' | 'table' | 'column',\n\t\tpublic readonly first: PhysicalNameEntry,\n\t\tpublic readonly second: PhysicalNameEntry,\n\t) {\n\t\tsuper(\n\t\t\t`Duplicate physical-name inventory ${scope}: ` +\n\t\t\t\t`\"${first.physical}\" is claimed by ${addressText(first.logical)} and ${addressText(second.logical)}.`,\n\t\t);\n\t\tthis.name = 'PhysicalNameInventoryDuplicateError';\n\t}\n}\n\nexport interface PhysicalNameInventory {\n\treadonly entries: readonly PhysicalNameEntry[];\n\thas(address: LogicalNameAddress): boolean;\n\tget(address: LogicalNameAddress): string;\n}\n\n/** Creates an immutable, canonical logical-address-to-physical-name inventory. */\nexport function createPhysicalNameInventory(\n\tentries: readonly PhysicalNameEntry[],\n): PhysicalNameInventory {\n\tconst byAddress = new Map<string, PhysicalNameEntry>();\n\tconst tables = new Map<string, PhysicalNameEntry>();\n\tconst columns = new Map<string, PhysicalNameEntry>();\n\tconst copied = entries.map((entry) =>\n\t\tObject.freeze({\n\t\t\tlogical: Object.freeze({ ...entry.logical }) as LogicalNameAddress,\n\t\t\tphysical: entry.physical,\n\t\t\t...(entry.sequenceProvenance === undefined\n\t\t\t\t? {}\n\t\t\t\t: { sequenceProvenance: entry.sequenceProvenance }),\n\t\t}),\n\t);\n\tconst physicalTables = new Map<string, string>();\n\tfor (const entry of copied) {\n\t\tif (entry.logical.kind === 'table')\n\t\t\tphysicalTables.set(\n\t\t\t\t`${entry.logical.schema}\\u0000${entry.logical.name}`,\n\t\t\t\tentry.physical,\n\t\t\t);\n\t}\n\n\tfor (const entry of copied) {\n\t\tconst key = addressKey(entry.logical);\n\t\tconst firstAddress = byAddress.get(key);\n\t\tif (firstAddress)\n\t\t\tthrow new PhysicalNameInventoryDuplicateError(\n\t\t\t\t'logical-address',\n\t\t\t\tfirstAddress,\n\t\t\t\tentry,\n\t\t\t);\n\t\tbyAddress.set(key, entry);\n\n\t\tif (entry.logical.kind === 'table') {\n\t\t\tconst tableKey = `${entry.logical.schema}\\u0000${entry.physical}`;\n\t\t\tconst firstTable = tables.get(tableKey);\n\t\t\tif (firstTable)\n\t\t\t\tthrow new PhysicalNameInventoryDuplicateError(\n\t\t\t\t\t'table',\n\t\t\t\t\tfirstTable,\n\t\t\t\t\tentry,\n\t\t\t\t);\n\t\t\ttables.set(tableKey, entry);\n\t\t}\n\t\tif (entry.logical.kind === 'column') {\n\t\t\tconst physicalTable =\n\t\t\t\tphysicalTables.get(\n\t\t\t\t\t`${entry.logical.schema}\\u0000${entry.logical.table}`,\n\t\t\t\t) ?? entry.logical.table;\n\t\t\tconst columnKey = `${entry.logical.schema}\\u0000${physicalTable}\\u0000${entry.physical}`;\n\t\t\tconst firstColumn = columns.get(columnKey);\n\t\t\tif (firstColumn)\n\t\t\t\tthrow new PhysicalNameInventoryDuplicateError(\n\t\t\t\t\t'column',\n\t\t\t\t\tfirstColumn,\n\t\t\t\t\tentry,\n\t\t\t\t);\n\t\t\tcolumns.set(columnKey, entry);\n\t\t}\n\t}\n\n\tconst sorted = Object.freeze(\n\t\t[...copied].sort((left, right) =>\n\t\t\taddressKey(left.logical) < addressKey(right.logical)\n\t\t\t\t? -1\n\t\t\t\t: addressKey(left.logical) > addressKey(right.logical)\n\t\t\t\t\t? 1\n\t\t\t\t\t: 0,\n\t\t),\n\t);\n\treturn Object.freeze({\n\t\tentries: sorted,\n\t\thas(address: LogicalNameAddress): boolean {\n\t\t\treturn byAddress.has(addressKey(address));\n\t\t},\n\t\tget(address: LogicalNameAddress): string {\n\t\t\tconst entry = byAddress.get(addressKey(address));\n\t\t\tif (!entry) throw new PhysicalNameInventoryMissingError(address);\n\t\t\treturn entry.physical;\n\t\t},\n\t});\n}\n\nexport class PhysicalNameInventoryMissingError extends Error {\n\tconstructor(public readonly address: LogicalNameAddress) {\n\t\tsuper(`Physical name inventory has no entry for ${addressText(address)}.`);\n\t\tthis.name = 'PhysicalNameInventoryMissingError';\n\t}\n}\n\nfunction addressKey(address: LogicalNameAddress): string {\n\treturn 'table' in address\n\t\t? `${address.kind}\\u0000${address.schema}\\u0000${address.table}\\u0000${address.name}`\n\t\t: `${address.kind}\\u0000${address.schema}\\u0000${address.name}`;\n}\n\nfunction addressText(address: LogicalNameAddress): string {\n\treturn 'table' in address\n\t\t? `${address.kind} ${address.schema}.${address.table}.${address.name}`\n\t\t: `${address.kind} ${address.schema}.${address.name}`;\n}\n","import type { ColumnListInput } from './column-list.js';\nimport { toColumnList } from './column-list.js';\nimport type { ForeignKeyIR, RelationIR } from './model-ir.js';\n\nconst DEFAULT_REFERENCED_COLUMN = 'id';\n\nexport type RelationKeyDirection = 'belongsTo' | 'inverse';\n\nexport type RelationKeyForeignKey = Pick<ForeignKeyIR, 'references'> & {\n\treadonly columns: ColumnListInput;\n};\n\nexport interface RelationKeyBuilderOptions {\n\treadonly defaultReferencedColumn?: string;\n\treadonly foreignKeyShape?: ColumnListInput;\n\treadonly referencedKeyShape?: ColumnListInput;\n}\n\nexport type RelationKeyFields = Pick<RelationIR, 'foreignKey'> &\n\tPartial<Pick<RelationIR, 'sourceKey' | 'targetKey'>>;\n\nfunction columnListValue(\n\tcolumns: readonly string[],\n\tshape?: ColumnListInput,\n): string | readonly string[] {\n\tif (shape !== undefined && typeof shape !== 'string') return columns;\n\t// biome-ignore lint/style/noNonNullAssertion: columns.length === 1 guaranteed by the ternary condition on this line\n\treturn columns.length === 1 ? columns[0]! : columns;\n}\n\n/**\n * Build RelationIR key fields from a foreign key while preserving both sides.\n *\n * The local FK columns and referenced columns are normalized with toColumnList()\n * so composite keys cannot silently degrade to their first column.\n */\nexport function buildRelationKeyFields(\n\tfk: RelationKeyForeignKey,\n\tdirection: RelationKeyDirection,\n\toptions: RelationKeyBuilderOptions = {},\n): RelationKeyFields {\n\tconst foreignKeyColumns = toColumnList(fk.columns);\n\tconst referencedColumns = toColumnList(fk.references.columns);\n\n\tif (foreignKeyColumns.length !== referencedColumns.length) {\n\t\tthrow new Error(\n\t\t\t`Foreign key column count (${foreignKeyColumns.length}) must match referenced column count (${referencedColumns.length})`,\n\t\t);\n\t}\n\n\tconst foreignKey = columnListValue(\n\t\tforeignKeyColumns,\n\t\toptions.foreignKeyShape,\n\t);\n\tconst defaultReferencedColumn =\n\t\toptions.defaultReferencedColumn ?? DEFAULT_REFERENCED_COLUMN;\n\tconst isImplicitDefaultReference =\n\t\toptions.referencedKeyShape === undefined &&\n\t\treferencedColumns.length === 1 &&\n\t\treferencedColumns[0] === defaultReferencedColumn;\n\n\tif (!isImplicitDefaultReference) {\n\t\tconst referencedKey = columnListValue(\n\t\t\treferencedColumns,\n\t\t\toptions.referencedKeyShape,\n\t\t);\n\t\tif (direction === 'belongsTo') {\n\t\t\treturn { foreignKey, targetKey: referencedKey };\n\t\t}\n\t\treturn { foreignKey, sourceKey: referencedKey };\n\t}\n\n\treturn { foreignKey };\n}\n","/**\n * Durable, reviewed conditions for executing a serialized transition plan.\n *\n * This is deliberately a small document format rather than a second copy of\n * ObservationContext. Its requirements are canonicalized before persistence\n * and are covered by the plan digest.\n */\nexport const EXECUTION_CONTRACT_VERSION = 1 as const;\n\nexport type ExecutionRequirementMode =\n\t| 'must-match'\n\t| 'set-and-verify'\n\t| 'must-satisfy'\n\t| 'provenance';\n\nexport interface PostgreSqlNamespaceIdentity {\n\treadonly name: string;\n\treadonly oid: string;\n}\n\nexport interface PostgreSqlPhysicalTargetRequirement {\n\treadonly kind: 'postgresql.physical-target';\n\treadonly mode: 'must-match';\n\treadonly systemIdentifier: string;\n\treadonly databaseOid: string;\n\t/** Canonical lexical set, never a positional list. */\n\treadonly namespaces: readonly PostgreSqlNamespaceIdentity[];\n}\n\nexport interface PostgreSqlEngineRequirement {\n\treadonly kind: 'postgresql.engine-version';\n\treadonly mode: 'must-satisfy';\n\treadonly stepId: string;\n\treadonly minServerVersionNum?: number;\n\treadonly maxServerVersionNum?: number;\n}\n\n/** Authority is a capability over an object, never a role-name comparison. */\nexport interface PostgreSqlAuthorityRequirement {\n\treadonly kind: 'postgresql.authority';\n\treadonly mode: 'must-satisfy';\n\treadonly action: 'schema-usage' | 'table-alter' | 'type-alter';\n\treadonly schema: string;\n\treadonly object?: string;\n}\n\nexport interface PostgreSqlSessionSettingRequirement {\n\treadonly kind: 'postgresql.session-setting';\n\treadonly mode: 'set-and-verify' | 'provenance';\n\treadonly setting:\n\t\t| 'standard_conforming_strings'\n\t\t| 'search_path'\n\t\t| 'client_encoding'\n\t\t| 'TimeZone';\n\treadonly value: string;\n}\n\nexport type ExecutionRequirement =\n\t| PostgreSqlPhysicalTargetRequirement\n\t| PostgreSqlEngineRequirement\n\t| PostgreSqlAuthorityRequirement\n\t| PostgreSqlSessionSettingRequirement;\n\nexport interface ExecutionContract {\n\treadonly version: typeof EXECUTION_CONTRACT_VERSION;\n\t/** A canonically ordered set. Unknown kinds and modes are invalid. */\n\treadonly requirements: readonly ExecutionRequirement[];\n}\n","import type { JsonValue } from './json.js';\nimport type { RefusalCode } from './refusal.js';\nimport type { CatalogueIdentity, ResourceAddress } from './resource.js';\n\n/** The outcome protocol is closed at the fourteen ADR 0006 event kinds. */\nexport const LEDGER_EVENT_KINDS = [\n\t'adopt-intent',\n\t'adopt',\n\t'intent',\n\t'retire-intent',\n\t'readdress-intent',\n\t'refused',\n\t'executing',\n\t'observed',\n\t'absent',\n\t'indeterminate',\n\t'resolved',\n\t'readdressed-to',\n\t'readdressed-from',\n\t'released',\n] as const;\n\nexport type LedgerEventKind = (typeof LEDGER_EVENT_KINDS)[number];\n\nexport type LedgerClaimKind = Extract<\n\tLedgerEventKind,\n\t'adopt-intent' | 'intent' | 'retire-intent' | 'readdress-intent'\n>;\n\n/**\n * A canonical address is recorded as columns by PostgreSQL and as this shape at\n * the adapter boundary. `scope` selects exactly one physical ledger.\n */\nexport interface LedgerAddress extends ResourceAddress {\n\treadonly scope: 'schema' | 'database';\n}\n\n/**\n * Construct the one parent shape used by ledger-bearing child addresses.\n *\n * A parent identifies containment only. Ledger scope belongs to the child\n * address, while a catalogue identity is an observed, non-address fact. Keep\n * both out of this recursive serialization so every producer names a physical\n * child the same way.\n */\nexport function canonicalResourceParent(\n\taddress: ResourceAddress,\n): ResourceAddress {\n\treturn {\n\t\tengine: address.engine,\n\t\tdatabase: address.database,\n\t\t...(address.schema === undefined ? {} : { schema: address.schema }),\n\t\t...(address.parent === undefined || address.parent === null\n\t\t\t? {}\n\t\t\t: { parent: canonicalResourceParent(address.parent) }),\n\t\tkind: address.kind,\n\t\tname: address.name,\n\t};\n}\n\n/**\n * JSON-compatible structural serialization whose object-member order is stable.\n * Ledger parents are persisted through PostgreSQL jsonb, which normalizes that\n * order before a later read-back.\n */\nfunction canonicalJson(value: unknown): string {\n\tif (value === null) return 'null';\n\tif (value === undefined) return 'null';\n\tif (Array.isArray(value)) {\n\t\tconst entries: string[] = [];\n\t\tfor (let index = 0; index < value.length; index += 1)\n\t\t\tentries.push(\n\t\t\t\tObject.hasOwn(value, index) ? canonicalJson(value[index]) : 'null',\n\t\t\t);\n\t\treturn `[${entries.join(',')}]`;\n\t}\n\tif (typeof value === 'object') {\n\t\tconst entries = Object.entries(value as Record<string, unknown>)\n\t\t\t.filter(([, item]) => item !== undefined)\n\t\t\t.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))\n\t\t\t.map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`);\n\t\treturn `{${entries.join(',')}}`;\n\t}\n\treturn JSON.stringify(value);\n}\n\nfunction normalizedParent(\n\tparent: ResourceAddress | null | undefined,\n): Record<string, unknown> | null {\n\tif (parent === null || parent === undefined) return null;\n\tconst canonical = canonicalResourceParent(parent);\n\treturn {\n\t\tengine: canonical.engine,\n\t\tdatabase: canonical.database,\n\t\t...(canonical.schema === undefined ? {} : { schema: canonical.schema }),\n\t\tparent: normalizedParent(canonical.parent),\n\t\tkind: canonical.kind,\n\t\tname: canonical.name,\n\t};\n}\n\n/** The complete address tuple that names one physical ledger row. */\nfunction canonicalLedgerAddress(\n\taddress: LedgerAddress,\n): Record<string, unknown> {\n\treturn {\n\t\tscope: address.scope,\n\t\tengine: address.engine,\n\t\tdatabase: address.database,\n\t\t...(address.schema === undefined ? {} : { schema: address.schema }),\n\t\tparent: normalizedParent(address.parent),\n\t\tkind: address.kind,\n\t\tname: address.name,\n\t};\n}\n\n/**\n * The sole structural equality for a ledger address. Parent absence is\n * canonicalized so `undefined` and `null` mean the same root address.\n */\nexport function sameLedgerAddress(\n\tleft: LedgerAddress,\n\tright: LedgerAddress,\n): boolean {\n\treturn ledgerAddressKey(left) === ledgerAddressKey(right);\n}\n\n/** A canonical map key with the same key-order-insensitive parent semantics. */\nexport function ledgerAddressKey(address: LedgerAddress): string {\n\treturn canonicalJson(canonicalLedgerAddress(address));\n}\n\n/**\n * Canonical parent representation for PostgreSQL's `address_parent` column.\n * Catalogue observations never create another physical ledger address.\n */\nexport function ledgerAddressParentJson(address: LedgerAddress): string {\n\treturn canonicalJson(normalizedParent(address.parent));\n}\n\nexport interface LedgerPayload {\n\treadonly value: JsonValue;\n\treadonly digest: string;\n}\n\n/**\n * The durable, operator-facing explanation attached to a `refused` terminal.\n * The address itself remains in the event's canonical address columns; these\n * values preserve the other facts needed to explain a historic refusal.\n */\nexport interface LedgerRefusal {\n\t/** Closed durable vocabulary; stored strings are validated at the reader. */\n\treadonly code: RefusalCode;\n\treadonly cause: string;\n\treadonly state: 'unknown' | 'managed' | 'absent';\n\treadonly withheldAuthority: string;\n\treadonly resolvingCommand: string;\n}\n\nexport interface LedgerChainMember {\n\treadonly eventId: string;\n\treadonly executionId?: string;\n\treadonly plannedClaimKey?: string;\n\treadonly claimGroupId?: string;\n\treadonly rootClaimId?: string;\n\treadonly address: LedgerAddress;\n\treadonly catalogueIdentity?: CatalogueIdentity;\n\treadonly eventKind: LedgerEventKind;\n\treadonly predecessor?: string;\n\treadonly pairId?: string;\n\treadonly declared?: LedgerPayload;\n\treadonly observed?: LedgerPayload;\n\t/** Present exactly on a durable `refused` terminal. */\n\treadonly refusal?: LedgerRefusal;\n\treadonly controller: string;\n\t/** The durable OID paired with `controller` when the event was recorded. */\n\treadonly controllerOid?: string;\n\treadonly recordedAt?: string;\n}\n\n/** A durable effects-closure reservation, anchored in its root claim's ledger. */\nexport interface LedgerReservationRow {\n\treadonly address: LedgerAddress;\n\treadonly claimKind: LedgerClaimKind;\n\treadonly executionId: string;\n\treadonly pairId?: string;\n\treadonly rootClaimId: string;\n\treadonly homeLedger: LedgerHome;\n}\n\nexport interface LedgerHome {\n\treadonly scope: 'schema' | 'database';\n\t/** Present exactly for a schema ledger. */\n\treadonly schema?: string;\n}\n\n/** The lineage facts stored beside every ledger; their admission rules ship later. */\nexport interface LedgerIdentity {\n\treadonly clusterSystemIdentifier: string;\n\treadonly databaseOid: string;\n\treadonly namespaceOid?: string;\n}\n\nexport interface LedgerShapeMarker {\n\treadonly version: number;\n}\n\n/**\n * The only marker vocabulary understood by the reinitialize-preflight path.\n * `absent` is deliberately distinct from a malformed or old marker: a\n * missing marker is how a new scope enters the cutover.\n */\nexport type LedgerMarkerState =\n\t| { readonly kind: 'current' }\n\t| { readonly kind: 'absent' }\n\t| { readonly kind: 'older'; readonly version: number }\n\t| { readonly kind: 'future'; readonly version: number }\n\t| { readonly kind: 'mixed'; readonly versions: readonly number[] }\n\t| { readonly kind: 'unreadable'; readonly reason: string };\n\n/** The closed result set for one explicit reinitialize-preflight scope. */\nexport type ReinitializePreflightScopeOutcome =\n\t| 'current'\n\t| 'unchanged'\n\t| 'failed'\n\t| 'not-attempted';\n\nexport type ReinitializePreflightRefusalCode =\n\t| 'database-read-only'\n\t| 'reinitialize-preflight-marker-not-current'\n\t| 'reinitialize-preflight-advisory-lock'\n\t| 'reinitialize-preflight-ownership'\n\t| 'reinitialize-preflight-grants'\n\t| 'reinitialize-preflight-lineage'\n\t| 'reinitialize-preflight-failed';\n\n/** The exact operation that produced a reported preflight failure. */\nexport type ReinitializePreflightFailureStep =\n\t| 'advisory-lock'\n\t| 'marker'\n\t| 'identity'\n\t| 'ownership-grants'\n\t| 'archive'\n\t| 'create'\n\t| 'record-identity'\n\t| 'creation-grants'\n\t| 'write-marker'\n\t| 'output';\n\n/** PostgreSQL's unmodified message, paired with the engine step that failed. */\nexport interface ReinitializePreflightFailureReason {\n\treadonly step: ReinitializePreflightFailureStep;\n\treadonly message: string;\n}\n\ninterface ReinitializePreflightScopeReportBase {\n\treadonly ledger: LedgerHome;\n\treadonly marker: LedgerMarkerState;\n\treadonly refusal?: {\n\t\treadonly code: ReinitializePreflightRefusalCode;\n\t\treadonly detail: string;\n\t};\n}\n\n/** A failed scope is structurally required to retain its diagnostic. */\nexport type ReinitializePreflightScopeReport =\n\t| (ReinitializePreflightScopeReportBase & {\n\t\t\treadonly outcome: 'failed';\n\t\t\treadonly reason: ReinitializePreflightFailureReason;\n\t })\n\t| (ReinitializePreflightScopeReportBase & {\n\t\t\treadonly outcome: Exclude<ReinitializePreflightScopeOutcome, 'failed'>;\n\t\t\treadonly reason?: never;\n\t });\n\n/** A current DSL declaration for which no chain exists in its home ledger. */\nexport interface ReinitializePreflightAdoptionCandidate {\n\treadonly address: LedgerAddress;\n\treadonly declaration: LedgerPayload;\n}\n\nexport interface ReinitializePreflightReport {\n\treadonly scopes: readonly ReinitializePreflightScopeReport[];\n\treadonly adoptionCandidates: readonly ReinitializePreflightAdoptionCandidate[];\n}\n","import type { LedgerAddress, LedgerRefusal } from './ledger.js';\n\n/** The unit-9/SC-64 vocabulary is the one source for durable refusal prose. */\nexport const REFUSAL_VOCABULARY = {\n\t'ERR-01': {\n\t\tcause: 'unaccepted non-transactional segment',\n\t\twithheldAuthority: 'non-transactional execution authority',\n\t\tresolvingCommand: 'dbsp apply',\n\t},\n\t'ERR-02': {\n\t\tcause: 'pre-existing object has no admitted adoption',\n\t\twithheldAuthority: 'creation authority over an occupied address',\n\t\tresolvingCommand: 'dbsp apply',\n\t},\n\t'ERR-03': {\n\t\tcause: 'managed-ledger preflight is not current',\n\t\twithheldAuthority: 'managed-ledger mutation authority',\n\t\tresolvingCommand: 'dbsp preflight --reinitialize',\n\t},\n\t'ERR-04': {\n\t\tcause: 'removal containment cannot be proven',\n\t\twithheldAuthority: 'destructive removal authority',\n\t\tresolvingCommand: 'dbsp apply',\n\t},\n\t'ERR-05': {\n\t\tcause: 'recorded identity differs from the live object',\n\t\twithheldAuthority: 'managed mutation authority',\n\t\tresolvingCommand: 'dbsp apply',\n\t},\n\t'ERR-06': {\n\t\tcause: 'managed-ledger lineage does not match this target',\n\t\twithheldAuthority: 'managed-ledger mutation authority',\n\t\tresolvingCommand: 'dbsp preflight --reinitialize',\n\t},\n\t'ERR-07': {\n\t\tcause: 'target database is read-only',\n\t\twithheldAuthority: 'database write authority',\n\t\tresolvingCommand: 'dbsp apply',\n\t},\n\t'ERR-08': {\n\t\tcause: 'ledger chain is malformed',\n\t\twithheldAuthority: 'managed mutation authority',\n\t\tresolvingCommand: 'dbsp inspect',\n\t},\n\t'ERR-09': {\n\t\tcause: 'catalogue read is unavailable',\n\t\twithheldAuthority: 'outcome classification authority',\n\t\tresolvingCommand: 'dbsp reconcile',\n\t},\n\t'ERR-10': {\n\t\tcause: 'recorded-plan path cannot execute a removal',\n\t\twithheldAuthority: 'recorded-plan removal execution',\n\t\tresolvingCommand: 'dbsp apply',\n\t},\n\t'ERR-11': {\n\t\tcause: 'recovery proved the interrupted operation had no effect',\n\t\twithheldAuthority: 'recovery execution authority',\n\t\tresolvingCommand: 'dbsp reconcile',\n\t},\n} as const;\n\nexport type RefusalCode = keyof typeof REFUSAL_VOCABULARY;\n\n/** Bind a catalogue entry to the address state that existed at refusal time. */\nexport function refusalFor(\n\tcode: RefusalCode,\n\tinput: Pick<LedgerRefusal, 'state'> & { readonly address?: LedgerAddress },\n): LedgerRefusal {\n\t// `address` documents the call-site contract: address columns persist it.\n\tvoid input.address;\n\treturn { code, ...REFUSAL_VOCABULARY[code], state: input.state };\n}\n","import type { JsonObject } from './json.js';\n\n/** The managed catalogue kinds. This union is intentionally closed. */\nexport type DeclarableKind =\n\t| 'table'\n\t| 'column'\n\t| 'index'\n\t| 'constraint'\n\t| 'enum'\n\t| 'sequence'\n\t| 'extension';\n\n/** Adapter-owned, versioned durable catalogue identity. */\nexport interface CatalogueIdentity {\n\treadonly engine: string;\n\treadonly format: number;\n\treadonly value: JsonObject;\n}\n\n/**\n * The durable PostgreSQL role identity which controls a managed ledger entry.\n * A role name alone is reusable after DROP/CREATE; the OID binds the record to\n * the role that was actually present when the event was written.\n */\nexport interface ControllerIdentity {\n\treadonly name: string;\n\treadonly oid: string;\n}\n\n/** Compare the complete durable controller identity in one place. */\nexport function sameControllerIdentity(\n\trecorded: ControllerIdentity,\n\tcurrent: ControllerIdentity,\n): boolean {\n\treturn recorded.name === current.name && recorded.oid === current.oid;\n}\n\nexport interface ResourceAddress {\n\treadonly engine: string;\n\treadonly database: string;\n\treadonly schema?: string;\n\t/** The containing object, for example an index or column's table. */\n\treadonly parent?: ResourceAddress;\n\treadonly kind: string;\n\treadonly name: string;\n\t/** Recorded catalogue identity. It is absent only for legacy/non-managed scope. */\n\treadonly catalogueIdentity?: CatalogueIdentity;\n\treadonly qualifiedBy?: readonly string[];\n}\n\n/** A managed declaration cannot spell a kind outside the declarable set. */\nexport type DeclarableResourceAddress<\n\tK extends DeclarableKind = DeclarableKind,\n> = Omit<ResourceAddress, 'kind'> & {\n\treadonly kind: K;\n};\n\nexport interface ResourceSelector {\n\treadonly kind?: string;\n\treadonly schema?: string;\n\treadonly name?: string;\n\treadonly within?: ResourceAddress;\n}\n"],"mappings":";AAQA,IAAM,kBAAkB,OAAO,OAAO,gBAAgB;AACtD,IAAM,kBAAkB,OAAO,OAAO,gBAAgB;AACtD,IAAM,oBAAoB;AAE1B,SAAS,YAAY,OAAwB;AAC5C,MAAI,OAAO,UAAU,SAAU,QAAO,IAAI,KAAK;AAC/C,MAAI,OAAO,UAAU,SAAU,QAAO,GAAG,MAAM,SAAS,CAAC;AACzD,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,WAAW;AAC5D,WAAO,OAAO,KAAK;AAAA,EACpB;AACA,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI;AACH,WAAO,KAAK,UAAU,KAAK,KAAK,OAAO,KAAK;AAAA,EAC7C,QAAQ;AACP,WAAO,OAAO,KAAK;AAAA,EACpB;AACD;AAEA,SAAS,gBACR,OACA,QACA,KACA,QACa;AACb,SAAO,IAAI;AAAA,IACV,4CAA4C,IAAI,KAAK,IAAI,IAAI,MAAM,iBAAiB,IAAI,SAAS,WAAW,YAAY,KAAK,CAAC,OAAO,MAAM,KAAK,MAAM;AAAA,EACvJ;AACD;AAEA,SAAS,eACR,OACA,QACA,KACS;AACT,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,OAAO,UAAU,UAAU;AAC9B,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,CAAC,kBAAkB,KAAK,OAAO,GAAG;AACrC,YAAM;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD;AACA,WAAO,OAAO,OAAO;AAAA,EACtB;AACA,MAAI,OAAO,UAAU,UAAU;AAC9B,QAAI,CAAC,OAAO,cAAc,KAAK,GAAG;AACjC,YAAM;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD;AACA,WAAO,OAAO,KAAK;AAAA,EACpB;AACA,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;AAEO,SAAS,yBACf,OACA,IACA,KACU;AACV,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAElD,UAAQ,IAAI;AAAA,IACX,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO,eAAe,OAAO,UAAU,GAAG;AAAA,IAC3C,KAAK,UAAU;AACd,YAAM,cAAc,eAAe,OAAO,UAAU,GAAG;AACvD,UAAI,cAAc,mBAAmB,cAAc,iBAAiB;AACnE,cAAM;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,aAAO,OAAO,WAAW;AAAA,IAC1B;AAAA,IACA;AACC,YAAM,IAAI;AAAA,QACT,gCAAgC,OAAO,EAAE,CAAC,mCAAmC,IAAI,KAAK,IAAI,IAAI,MAAM;AAAA,MACrG;AAAA,EACF;AACD;;;AC/FO,SAAS,aAAa,KAAyC;AACrE,MAAI,QAAQ,OAAW,QAAO,CAAC;AAC/B,SAAO,OAAO,QAAQ,WAAW,CAAC,GAAG,IAAI;AAC1C;;;AC2WO,SAAS,cAAc,OAAsC;AACnE,SACC,OAAO,UAAU,YACjB,UAAU,QACT,MAAkC,SAAS,WAC5C,WAAY;AAEd;;;ACxVO,SAAS,eAAe,MAAmC;AACjE,MAAI,KAAK,GAAI,QAAO,KAAK;AACzB,MAAI,KAAK,SAAS,SAAU,QAAO,KAAK;AACxC,MAAI,KAAK,SAAS,UAAW,QAAO;AAEpC,SAAO;AACR;;;ACpCO,IAAM,iCAAiC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEO,IAAM,4BAA4B;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEO,IAAM,6BAA6B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEO,IAAM,8BAA8B;AAAA,EAC1C,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACJ;AAEO,IAAM,mCAAmC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEO,IAAM,8BAA8B;AAAA,EAC1C,GAAG;AAAA,EACH;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEO,IAAM,uCACZ,IAAI,IAAI,2BAA2B;AAE7B,IAAM,uCACZ,IAAI,IAAI,2BAA2B;AAE7B,IAAM,gCAAqD,oBAAI,IAAI;AAAA,EACzE,GAAG;AAAA,EACH,GAAG;AACJ,CAAC;AAKM,SAAS,iCACf,MACkC;AAClC,SAAO,qCAAqC,IAAI,KAAK,YAAY,CAAC;AACnE;AAEO,SAAS,2BAA2B,MAAuB;AACjE,SAAO,8BAA8B,IAAI,KAAK,YAAY,CAAC;AAC5D;AAEO,SAAS,iCACf,MACkC;AAClC,SAAO,qCAAqC,IAAI,KAAK,YAAY,CAAC;AACnE;;;AClBO,SAAS,eAAe,QAAyC;AACvE,SACC,OAAO,WAAW,YAClB,WAAW,QACX,UAAU,UACT,OAAmC,SAAS;AAE/C;AAKO,SAAS,0BACf,IACuD;AACvD,SAAO,CAAC,OAAO,OAAO,SAAS,OAAO,OAAO,OAAO,MAAM,EAAE,SAAS,EAAE;AACxE;AAKO,SAAS,wBACf,IAC8B;AAC9B,SAAO,CAAC,cAAc,QAAQ,YAAY,EAAE,SAAS,EAAE;AACxD;AASO,SAAS,kBACf,OACiC;AACjC,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,YAAY,OAA8C;AACzE,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,gBACf,OAC+B;AAC/B,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,cAAc,OAA4C;AACzE,SACC,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACT,MAAkC,SAAS;AAE9C;AAKO,SAAS,UAAU,OAA4C;AACrE,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,WAAW,OAA6C;AACvE,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,YAAY,OAA8C;AACzE,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,aAAa,OAA+C;AAC3E,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,WAAW,OAA6C;AACvE,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,UAAU,OAA4C;AACrE,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,WAAW,OAA6C;AACvE,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,cAAc,OAAgD;AAC7E,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,iBACf,OACgC;AAChC,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,sBACf,OACqC;AACrC,SAAO,MAAM,SAAS;AACvB;AAKO,SAAS,qBACf,OAI4B;AAC5B,SACC,MAAM,SAAS,YACf,MAAM,SAAS,eACf,MAAM,SAAS;AAEjB;AAKO,SAAS,eACf,OAC2D;AAC3D,SAAO,MAAM,SAAS,SAAS,MAAM,SAAS,QAAQ,MAAM,SAAS;AACtE;AASO,SAAS,YAAY,QAAiD;AAC5E,SAAO,OAAO,SAAS;AACxB;AAKO,SAAS,eACf,QAC+B;AAC/B,SAAO,OAAO,SAAS;AACxB;AAKO,SAAS,kBACf,QACkC;AAClC,SAAO,OAAO,SAAS;AACxB;AAKO,SAAS,wBACf,QACwC;AACxC,SAAO,OAAO,SAAS;AACxB;AASO,SAAS,qBACf,MACmC;AACnC,SAAO,KAAK,SAAS;AACtB;AAKO,SAAS,gBACf,MAC8B;AAC9B,SAAO,KAAK,SAAS;AACtB;AAKO,SAAS,wBACf,MAC4B;AAC5B,SAAO,KAAK,SAAS;AACtB;AAKO,SAAS,2BACf,MAC+B;AAC/B,SAAO,KAAK,SAAS;AACtB;AASO,SAAS,qBACf,WACkC;AAClC,SAAO,UAAU,SAAS;AAC3B;AAKO,SAAS,qBACf,WACkC;AAClC,SAAO,UAAU,SAAS;AAC3B;AAKO,SAAS,kBACf,WAC+B;AAC/B,SAAO,UAAU,SAAS;AAC3B;AAKO,SAAS,kBACf,QAC4B;AAC5B,SAAO,OAAO,SAAS;AACxB;AASO,SAAS,eACf,QACyB;AACzB,SAAO,OAAO,SAAS;AACxB;AAKO,SAAS,eACf,QACyB;AACzB,SAAO,OAAO,SAAS;AACxB;AAKO,SAAS,eACf,QACyB;AACzB,SAAO,OAAO,SAAS;AACxB;AAKO,SAAS,eACf,QACyB;AACzB,SAAO,OAAO,SAAS;AACxB;AAKO,SAAS,iBACf,QAC2B;AAC3B,SACC,OAAO,SAAS,YAChB,OAAO,SAAS,iBAChB,OAAO,SAAS,iBAChB,OAAO,SAAS,YAChB,OAAO,SAAS,iBAChB,OAAO,SAAS,YAChB,OAAO,SAAS;AAElB;;;ACtWO,SAAS,WAAW,OAAmC;AAC7D,SACC,UAAU,QACV,OAAO,UAAU,YAChB,MAAkC,SAAS;AAE9C;;;ACtCO,SAAS,uBAAuB,OAAiC;AACvE,QAAM,YAAY,aAAa,MAAM,UAAU;AAC/C,SAAO,UAAU,SAAS,IACvB,EAAE,SAAS,WAAW,UAAU,MAAM,IACtC,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC,QAAQ,IAAI,IAAI,GAAG,UAAU,KAAK;AACpE;;;ACCA,SAAS,MAAM,OAAgD;AAC9D,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,MAAI;AACH,QAAI,UAAU,IAAI,KAAK,OAAO,MAAS;AACvC,WAAO;AAAA,EACR,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAYO,SAAS,cAAc,QAAyC;AACtE,MACC,OAAO,WAAW,YAClB,WAAW,QACX,EAAE,WAAW,WACb,EAAE,gBAAgB,WAClB,EAAE,gBAAgB,SACjB;AACD,WAAO;AAAA,EACR;AACA,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,UAAU,YAAY,EAAE,UAAU,KAAM,QAAO;AAC5D,MAAI,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,OAAQ,QAAO;AAChE,MAAI,CAAC,MAAM,EAAE,MAAM,MAAM,EAAG,QAAO;AACnC,MAAI,CAAC,MAAM,EAAE,MAAM,SAAS,EAAG,QAAO;AACtC,MAAI,OAAO,EAAE,eAAe,YAAY,EAAE,eAAe,KAAM,QAAO;AACtE,MAAI,CAAC,MAAM,QAAQ,EAAE,UAAU,EAAG,QAAO;AACzC,MAAI,EAAE,WAAW,KAAK,CAAC,SAAS,OAAO,SAAS,QAAQ,EAAG,QAAO;AAElE,MAAI,OAAO,EAAE,MAAM,aAAa,WAAY,QAAO;AACnD,MAAI,OAAO,EAAE,MAAM,gBAAgB,WAAY,QAAO;AACtD,MAAI,OAAO,EAAE,MAAM,qBAAqB,WAAY,QAAO;AAC3D,MAAI,OAAO,EAAE,MAAM,mBAAmB,WAAY,QAAO;AACzD,MAAI,OAAO,EAAE,MAAM,gBAAgB,WAAY,QAAO;AACtD,SAAO;AACR;;;ACTO,SAAS,0BACf,YACqB;AACrB,QAAM,EAAE,OAAO,IAAI;AACnB,MAAI,OAAO,SAAS,iBAAiB,OAAO,OAAO,QAAW;AAC7D,WAAO,EAAE,MAAM,OAAO;AAAA,EACvB;AAEA,UAAQ,WAAW,MAAM,MAAM;AAAA,IAC9B,KAAK;AACJ,aAAO;AAAA,QACN,MAAM;AAAA,QACN,OAAO,OAAO;AAAA,QACd,QAAQ,OAAO;AAAA,QACf,IAAI,OAAO;AAAA,MACZ;AAAA,IACD,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,QACN,MAAM;AAAA,QACN,OAAO,OAAO;AAAA,QACd,QAAQ,OAAO;AAAA,QACf,IAAI,OAAO;AAAA,MACZ;AAAA,IACD,KAAK;AAAA,IACL,KAAK;AACJ,aAAO,EAAE,MAAM,OAAO;AAAA,EACxB;AACD;;;AC1DO,IAAM,sCAAN,cAAkD,MAAM;AAAA,EAC9D,YACiB,OACA,OACA,QACf;AACD;AAAA,MACC,qCAAqC,KAAK,MACrC,MAAM,QAAQ,mBAAmB,YAAY,MAAM,OAAO,CAAC,QAAQ,YAAY,OAAO,OAAO,CAAC;AAAA,IACpG;AAPgB;AACA;AACA;AAMhB,SAAK,OAAO;AAAA,EACb;AAAA,EATiB;AAAA,EACA;AAAA,EACA;AAQlB;AASO,SAAS,4BACf,SACwB;AACxB,QAAM,YAAY,oBAAI,IAA+B;AACrD,QAAM,SAAS,oBAAI,IAA+B;AAClD,QAAM,UAAU,oBAAI,IAA+B;AACnD,QAAM,SAAS,QAAQ;AAAA,IAAI,CAAC,UAC3B,OAAO,OAAO;AAAA,MACb,SAAS,OAAO,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC;AAAA,MAC3C,UAAU,MAAM;AAAA,MAChB,GAAI,MAAM,uBAAuB,SAC9B,CAAC,IACD,EAAE,oBAAoB,MAAM,mBAAmB;AAAA,IACnD,CAAC;AAAA,EACF;AACA,QAAM,iBAAiB,oBAAI,IAAoB;AAC/C,aAAW,SAAS,QAAQ;AAC3B,QAAI,MAAM,QAAQ,SAAS;AAC1B,qBAAe;AAAA,QACd,GAAG,MAAM,QAAQ,MAAM,KAAS,MAAM,QAAQ,IAAI;AAAA,QAClD,MAAM;AAAA,MACP;AAAA,EACF;AAEA,aAAW,SAAS,QAAQ;AAC3B,UAAM,MAAM,WAAW,MAAM,OAAO;AACpC,UAAM,eAAe,UAAU,IAAI,GAAG;AACtC,QAAI;AACH,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACD;AACD,cAAU,IAAI,KAAK,KAAK;AAExB,QAAI,MAAM,QAAQ,SAAS,SAAS;AACnC,YAAM,WAAW,GAAG,MAAM,QAAQ,MAAM,KAAS,MAAM,QAAQ;AAC/D,YAAM,aAAa,OAAO,IAAI,QAAQ;AACtC,UAAI;AACH,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QACD;AACD,aAAO,IAAI,UAAU,KAAK;AAAA,IAC3B;AACA,QAAI,MAAM,QAAQ,SAAS,UAAU;AACpC,YAAM,gBACL,eAAe;AAAA,QACd,GAAG,MAAM,QAAQ,MAAM,KAAS,MAAM,QAAQ,KAAK;AAAA,MACpD,KAAK,MAAM,QAAQ;AACpB,YAAM,YAAY,GAAG,MAAM,QAAQ,MAAM,KAAS,aAAa,KAAS,MAAM,QAAQ;AACtF,YAAM,cAAc,QAAQ,IAAI,SAAS;AACzC,UAAI;AACH,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QACD;AACD,cAAQ,IAAI,WAAW,KAAK;AAAA,IAC7B;AAAA,EACD;AAEA,QAAM,SAAS,OAAO;AAAA,IACrB,CAAC,GAAG,MAAM,EAAE;AAAA,MAAK,CAAC,MAAM,UACvB,WAAW,KAAK,OAAO,IAAI,WAAW,MAAM,OAAO,IAChD,KACA,WAAW,KAAK,OAAO,IAAI,WAAW,MAAM,OAAO,IAClD,IACA;AAAA,IACL;AAAA,EACD;AACA,SAAO,OAAO,OAAO;AAAA,IACpB,SAAS;AAAA,IACT,IAAI,SAAsC;AACzC,aAAO,UAAU,IAAI,WAAW,OAAO,CAAC;AAAA,IACzC;AAAA,IACA,IAAI,SAAqC;AACxC,YAAM,QAAQ,UAAU,IAAI,WAAW,OAAO,CAAC;AAC/C,UAAI,CAAC,MAAO,OAAM,IAAI,kCAAkC,OAAO;AAC/D,aAAO,MAAM;AAAA,IACd;AAAA,EACD,CAAC;AACF;AAEO,IAAM,oCAAN,cAAgD,MAAM;AAAA,EAC5D,YAA4B,SAA6B;AACxD,UAAM,4CAA4C,YAAY,OAAO,CAAC,GAAG;AAD9C;AAE3B,SAAK,OAAO;AAAA,EACb;AAAA,EAH4B;AAI7B;AAEA,SAAS,WAAW,SAAqC;AACxD,SAAO,WAAW,UACf,GAAG,QAAQ,IAAI,KAAS,QAAQ,MAAM,KAAS,QAAQ,KAAK,KAAS,QAAQ,IAAI,KACjF,GAAG,QAAQ,IAAI,KAAS,QAAQ,MAAM,KAAS,QAAQ,IAAI;AAC/D;AAEA,SAAS,YAAY,SAAqC;AACzD,SAAO,WAAW,UACf,GAAG,QAAQ,IAAI,IAAI,QAAQ,MAAM,IAAI,QAAQ,KAAK,IAAI,QAAQ,IAAI,KAClE,GAAG,QAAQ,IAAI,IAAI,QAAQ,MAAM,IAAI,QAAQ,IAAI;AACrD;;;ACjJA,IAAM,4BAA4B;AAiBlC,SAAS,gBACR,SACA,OAC6B;AAC7B,MAAI,UAAU,UAAa,OAAO,UAAU,SAAU,QAAO;AAE7D,SAAO,QAAQ,WAAW,IAAI,QAAQ,CAAC,IAAK;AAC7C;AAQO,SAAS,uBACf,IACA,WACA,UAAqC,CAAC,GAClB;AACpB,QAAM,oBAAoB,aAAa,GAAG,OAAO;AACjD,QAAM,oBAAoB,aAAa,GAAG,WAAW,OAAO;AAE5D,MAAI,kBAAkB,WAAW,kBAAkB,QAAQ;AAC1D,UAAM,IAAI;AAAA,MACT,6BAA6B,kBAAkB,MAAM,yCAAyC,kBAAkB,MAAM;AAAA,IACvH;AAAA,EACD;AAEA,QAAM,aAAa;AAAA,IAClB;AAAA,IACA,QAAQ;AAAA,EACT;AACA,QAAM,0BACL,QAAQ,2BAA2B;AACpC,QAAM,6BACL,QAAQ,uBAAuB,UAC/B,kBAAkB,WAAW,KAC7B,kBAAkB,CAAC,MAAM;AAE1B,MAAI,CAAC,4BAA4B;AAChC,UAAM,gBAAgB;AAAA,MACrB;AAAA,MACA,QAAQ;AAAA,IACT;AACA,QAAI,cAAc,aAAa;AAC9B,aAAO,EAAE,YAAY,WAAW,cAAc;AAAA,IAC/C;AACA,WAAO,EAAE,YAAY,WAAW,cAAc;AAAA,EAC/C;AAEA,SAAO,EAAE,WAAW;AACrB;;;AClEO,IAAM,6BAA6B;;;ACFnC,IAAM,qBAAqB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAyBO,SAAS,wBACf,SACkB;AAClB,SAAO;AAAA,IACN,QAAQ,QAAQ;AAAA,IAChB,UAAU,QAAQ;AAAA,IAClB,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,IACjE,GAAI,QAAQ,WAAW,UAAa,QAAQ,WAAW,OACpD,CAAC,IACD,EAAE,QAAQ,wBAAwB,QAAQ,MAAM,EAAE;AAAA,IACrD,MAAM,QAAQ;AAAA,IACd,MAAM,QAAQ;AAAA,EACf;AACD;AAOA,SAAS,cAAc,OAAwB;AAC9C,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,MAAM,QAAQ,KAAK,GAAG;AACzB,UAAM,UAAoB,CAAC;AAC3B,aAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS;AAClD,cAAQ;AAAA,QACP,OAAO,OAAO,OAAO,KAAK,IAAI,cAAc,MAAM,KAAK,CAAC,IAAI;AAAA,MAC7D;AACD,WAAO,IAAI,QAAQ,KAAK,GAAG,CAAC;AAAA,EAC7B;AACA,MAAI,OAAO,UAAU,UAAU;AAC9B,UAAM,UAAU,OAAO,QAAQ,KAAgC,EAC7D,OAAO,CAAC,CAAC,EAAE,IAAI,MAAM,SAAS,MAAS,EACvC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,MAAO,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI,CAAE,EACpE,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,GAAG,KAAK,UAAU,GAAG,CAAC,IAAI,cAAc,IAAI,CAAC,EAAE;AACtE,WAAO,IAAI,QAAQ,KAAK,GAAG,CAAC;AAAA,EAC7B;AACA,SAAO,KAAK,UAAU,KAAK;AAC5B;AAEA,SAAS,iBACR,QACiC;AACjC,MAAI,WAAW,QAAQ,WAAW,OAAW,QAAO;AACpD,QAAM,YAAY,wBAAwB,MAAM;AAChD,SAAO;AAAA,IACN,QAAQ,UAAU;AAAA,IAClB,UAAU,UAAU;AAAA,IACpB,GAAI,UAAU,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,UAAU,OAAO;AAAA,IACrE,QAAQ,iBAAiB,UAAU,MAAM;AAAA,IACzC,MAAM,UAAU;AAAA,IAChB,MAAM,UAAU;AAAA,EACjB;AACD;AAGA,SAAS,uBACR,SAC0B;AAC1B,SAAO;AAAA,IACN,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ;AAAA,IAChB,UAAU,QAAQ;AAAA,IAClB,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,IACjE,QAAQ,iBAAiB,QAAQ,MAAM;AAAA,IACvC,MAAM,QAAQ;AAAA,IACd,MAAM,QAAQ;AAAA,EACf;AACD;AAMO,SAAS,kBACf,MACA,OACU;AACV,SAAO,iBAAiB,IAAI,MAAM,iBAAiB,KAAK;AACzD;AAGO,SAAS,iBAAiB,SAAgC;AAChE,SAAO,cAAc,uBAAuB,OAAO,CAAC;AACrD;AAMO,SAAS,wBAAwB,SAAgC;AACvE,SAAO,cAAc,iBAAiB,QAAQ,MAAM,CAAC;AACtD;;;ACvIO,IAAM,qBAAqB;AAAA,EACjC,UAAU;AAAA,IACT,OAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACnB;AAAA,EACA,UAAU;AAAA,IACT,OAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACnB;AAAA,EACA,UAAU;AAAA,IACT,OAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACnB;AAAA,EACA,UAAU;AAAA,IACT,OAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACnB;AAAA,EACA,UAAU;AAAA,IACT,OAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACnB;AAAA,EACA,UAAU;AAAA,IACT,OAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACnB;AAAA,EACA,UAAU;AAAA,IACT,OAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACnB;AAAA,EACA,UAAU;AAAA,IACT,OAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACnB;AAAA,EACA,UAAU;AAAA,IACT,OAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACnB;AAAA,EACA,UAAU;AAAA,IACT,OAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACnB;AAAA,EACA,UAAU;AAAA,IACT,OAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACnB;AACD;AAKO,SAAS,WACf,MACA,OACgB;AAEhB,OAAK,MAAM;AACX,SAAO,EAAE,MAAM,GAAG,mBAAmB,IAAI,GAAG,OAAO,MAAM,MAAM;AAChE;;;ACzCO,SAAS,uBACf,UACA,SACU;AACV,SAAO,SAAS,SAAS,QAAQ,QAAQ,SAAS,QAAQ,QAAQ;AACnE;","names":[]}
|