@dbsp/types 1.0.3 → 1.1.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/{chunk-HNIQJ2TL.js → chunk-N47PVUJW.js} +76 -1
- package/dist/chunk-N47PVUJW.js.map +1 -0
- package/dist/index.d.ts +69 -15
- package/dist/index.js +27 -1
- package/dist/internal.d.ts +20 -2
- package/dist/internal.js +33 -1
- package/dist/internal.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-HNIQJ2TL.js.map +0 -1
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
// src/intent/expression-intent.ts
|
|
2
|
+
function isParamIntent(value) {
|
|
3
|
+
return typeof value === "object" && value !== null && value.kind === "param" && "value" in value;
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
// src/intent/recursive-intent.ts
|
|
2
7
|
function getNodeIdAlias(expr) {
|
|
3
8
|
if (expr.as) return expr.as;
|
|
@@ -6,6 +11,63 @@ function getNodeIdAlias(expr) {
|
|
|
6
11
|
return "node_id";
|
|
7
12
|
}
|
|
8
13
|
|
|
14
|
+
// src/intent/select-function-allowlist.ts
|
|
15
|
+
var NQL_SELECT_AGGREGATE_FUNCTIONS = [
|
|
16
|
+
"count",
|
|
17
|
+
"sum",
|
|
18
|
+
"avg",
|
|
19
|
+
"min",
|
|
20
|
+
"max"
|
|
21
|
+
];
|
|
22
|
+
var NQL_SELECT_JSON_FUNCTIONS = [
|
|
23
|
+
"json_extract",
|
|
24
|
+
"json_extract_text",
|
|
25
|
+
"json_path",
|
|
26
|
+
"json_path_text"
|
|
27
|
+
];
|
|
28
|
+
var NQL_SELECT_VALUE_FUNCTIONS = [
|
|
29
|
+
"coalesce",
|
|
30
|
+
"lower",
|
|
31
|
+
"now",
|
|
32
|
+
"round",
|
|
33
|
+
"upper"
|
|
34
|
+
];
|
|
35
|
+
var NQL_SELECT_SCALAR_FUNCTIONS = [
|
|
36
|
+
...NQL_SELECT_AGGREGATE_FUNCTIONS,
|
|
37
|
+
...NQL_SELECT_JSON_FUNCTIONS,
|
|
38
|
+
...NQL_SELECT_VALUE_FUNCTIONS
|
|
39
|
+
];
|
|
40
|
+
var NQL_SELECT_WINDOW_ONLY_FUNCTIONS = [
|
|
41
|
+
"row_number",
|
|
42
|
+
"rank",
|
|
43
|
+
"dense_rank",
|
|
44
|
+
"lag",
|
|
45
|
+
"lead"
|
|
46
|
+
];
|
|
47
|
+
var NQL_SELECT_WINDOW_FUNCTIONS = [
|
|
48
|
+
...NQL_SELECT_WINDOW_ONLY_FUNCTIONS,
|
|
49
|
+
"count",
|
|
50
|
+
"sum",
|
|
51
|
+
"avg",
|
|
52
|
+
"min",
|
|
53
|
+
"max"
|
|
54
|
+
];
|
|
55
|
+
var NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST = new Set(NQL_SELECT_SCALAR_FUNCTIONS);
|
|
56
|
+
var NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST = new Set(NQL_SELECT_WINDOW_FUNCTIONS);
|
|
57
|
+
var NQL_SELECT_FUNCTION_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
58
|
+
...NQL_SELECT_SCALAR_FUNCTIONS,
|
|
59
|
+
...NQL_SELECT_WINDOW_FUNCTIONS
|
|
60
|
+
]);
|
|
61
|
+
function isNqlSelectScalarFunctionAllowed(name) {
|
|
62
|
+
return NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST.has(name.toLowerCase());
|
|
63
|
+
}
|
|
64
|
+
function isNqlSelectFunctionAllowed(name) {
|
|
65
|
+
return NQL_SELECT_FUNCTION_ALLOWLIST.has(name.toLowerCase());
|
|
66
|
+
}
|
|
67
|
+
function isNqlSelectWindowFunctionAllowed(name) {
|
|
68
|
+
return NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST.has(name.toLowerCase());
|
|
69
|
+
}
|
|
70
|
+
|
|
9
71
|
// src/intent/type-guards.ts
|
|
10
72
|
function isWindowIntent(intent) {
|
|
11
73
|
return typeof intent === "object" && intent !== null && "kind" in intent && intent.kind === "window";
|
|
@@ -139,7 +201,20 @@ function isValidSchema(schema) {
|
|
|
139
201
|
}
|
|
140
202
|
|
|
141
203
|
export {
|
|
204
|
+
isParamIntent,
|
|
142
205
|
getNodeIdAlias,
|
|
206
|
+
NQL_SELECT_AGGREGATE_FUNCTIONS,
|
|
207
|
+
NQL_SELECT_JSON_FUNCTIONS,
|
|
208
|
+
NQL_SELECT_VALUE_FUNCTIONS,
|
|
209
|
+
NQL_SELECT_SCALAR_FUNCTIONS,
|
|
210
|
+
NQL_SELECT_WINDOW_ONLY_FUNCTIONS,
|
|
211
|
+
NQL_SELECT_WINDOW_FUNCTIONS,
|
|
212
|
+
NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST,
|
|
213
|
+
NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST,
|
|
214
|
+
NQL_SELECT_FUNCTION_ALLOWLIST,
|
|
215
|
+
isNqlSelectScalarFunctionAllowed,
|
|
216
|
+
isNqlSelectFunctionAllowed,
|
|
217
|
+
isNqlSelectWindowFunctionAllowed,
|
|
143
218
|
isWindowIntent,
|
|
144
219
|
isAggregateWindowFunction,
|
|
145
220
|
isRankingWindowFunction,
|
|
@@ -179,4 +254,4 @@ export {
|
|
|
179
254
|
isFieldRef,
|
|
180
255
|
isValidSchema
|
|
181
256
|
};
|
|
182
|
-
//# sourceMappingURL=chunk-
|
|
257
|
+
//# sourceMappingURL=chunk-N47PVUJW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../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/loaded-schema.ts"],"sourcesContent":["/**\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 * Uses native Kysely eb.ref().as() - type-safe and dialect-portable\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 * Auto-creates JOIN via include mechanism and selects with custom alias\n * @example { kind: 'relationColumn', relation: 'category', column: 'name', as: 'categoryName' }\n * → SELECT t1.\"name\" AS \"categoryName\" (where t1 is the joined category table)\n * @example { kind: 'relationColumn', relation: 'category.parent', column: 'name', as: 'parentCategoryName' }\n * → Multi-level join: products → category → parent, select parent.name\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/** 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/** 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// 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 { RangeValue } from '../shared/utils.js';\nimport type { ExpressionIntent, ParamIntent } 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}\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 * Scalar subquery intent - produces a single value.\n * Simplified QueryIntent for subquery context.\n */\n/** @deprecated Use QueryIntent instead — subqueries are full queries with contextual validation */\nexport type ScalarSubqueryIntent = QueryIntent;\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 with comparison */\nexport interface WhereExpressionIntent {\n\treadonly kind: 'expression';\n\treadonly expr: ExpressionIntent;\n\treadonly operator: ComparisonOperator;\n\treadonly value: unknown;\n}\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 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\treadonly model: ModelIR;\n\treadonly tableNames: readonly string[];\n}\n\n/**\n * Runtime type guard for `LoadedSchema` — verifies the object has\n * `definition`, `model` (with nested `tables` + `relations`), and\n * `tableNames` as an array. Structural check only — does not validate\n * the inner values of any field.\n *\n * Type guard for ARCH-005 schema() output.\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 (!Array.isArray(s.tableNames)) 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"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -633,7 +633,7 @@ interface WhereComparisonIntent {
|
|
|
633
633
|
readonly operator: ComparisonOperator;
|
|
634
634
|
readonly value: unknown;
|
|
635
635
|
/** JSON path extraction before comparison (e.g., data->'key' = 'val') */
|
|
636
|
-
readonly jsonPath?: readonly string[];
|
|
636
|
+
readonly jsonPath?: readonly (string | ParamIntent)[];
|
|
637
637
|
/** JSON extraction mode: 'json' = ->, 'text' = ->> */
|
|
638
638
|
readonly jsonMode?: 'json' | 'text';
|
|
639
639
|
}
|
|
@@ -643,7 +643,7 @@ interface WhereComparisonIntent {
|
|
|
643
643
|
interface WhereLikeIntent {
|
|
644
644
|
readonly kind: 'like';
|
|
645
645
|
readonly field: string;
|
|
646
|
-
readonly pattern: string;
|
|
646
|
+
readonly pattern: string | ParamIntent;
|
|
647
647
|
/** Case-insensitive matching */
|
|
648
648
|
readonly caseInsensitive?: boolean;
|
|
649
649
|
/** Escape character for LIKE pattern (e.g. '\\' to escape _ and %) */
|
|
@@ -684,7 +684,7 @@ type WhereInIntent = WhereInValueIntent | WhereInSubqueryIntent;
|
|
|
684
684
|
interface WhereAnyIntent {
|
|
685
685
|
readonly kind: 'any';
|
|
686
686
|
readonly field: string;
|
|
687
|
-
readonly values: readonly unknown[];
|
|
687
|
+
readonly values: readonly unknown[] | ParamIntent;
|
|
688
688
|
}
|
|
689
689
|
/**
|
|
690
690
|
* Operand accepted by range WHERE filters.
|
|
@@ -959,7 +959,7 @@ interface WhereJsonContainsIntent {
|
|
|
959
959
|
interface WhereJsonExistsIntent {
|
|
960
960
|
readonly kind: 'jsonExists';
|
|
961
961
|
readonly field: string;
|
|
962
|
-
readonly key: string;
|
|
962
|
+
readonly key: string | ParamIntent;
|
|
963
963
|
}
|
|
964
964
|
/** WHERE clause using a custom expression with comparison */
|
|
965
965
|
interface WhereExpressionIntent {
|
|
@@ -1276,7 +1276,7 @@ interface CaseExpressionIntent {
|
|
|
1276
1276
|
interface JsonExtractIntent {
|
|
1277
1277
|
readonly kind: 'jsonExtract';
|
|
1278
1278
|
readonly field: string;
|
|
1279
|
-
readonly path: readonly string[];
|
|
1279
|
+
readonly path: readonly (string | ParamIntent)[];
|
|
1280
1280
|
/** 'json' = returns JSON value (->), 'text' = returns text (->>) */
|
|
1281
1281
|
readonly mode: 'json' | 'text';
|
|
1282
1282
|
readonly as?: string | undefined;
|
|
@@ -1305,8 +1305,8 @@ interface JsonExistsIntent {
|
|
|
1305
1305
|
interface JsonPathExtractIntent {
|
|
1306
1306
|
readonly kind: 'jsonPathExtract';
|
|
1307
1307
|
readonly field: string;
|
|
1308
|
-
/** PostgreSQL
|
|
1309
|
-
readonly path: string;
|
|
1308
|
+
/** PostgreSQL JSON path segments. Bound as one text[] parameter by adapters. */
|
|
1309
|
+
readonly path: readonly (string | ParamIntent)[];
|
|
1310
1310
|
/** 'json' = returns JSON (#>), 'text' = returns text (#>>) */
|
|
1311
1311
|
readonly mode: 'json' | 'text';
|
|
1312
1312
|
readonly as?: string | undefined;
|
|
@@ -1342,11 +1342,26 @@ interface RefExpressionIntent {
|
|
|
1342
1342
|
readonly kind: 'ref';
|
|
1343
1343
|
readonly column: string;
|
|
1344
1344
|
}
|
|
1345
|
-
/**
|
|
1345
|
+
/**
|
|
1346
|
+
* Public bound-parameter node.
|
|
1347
|
+
*
|
|
1348
|
+
* A value that originated from an NQL named parameter or template binding is
|
|
1349
|
+
* represented explicitly in the public IntentAST. The inner value is opaque:
|
|
1350
|
+
* consumers must bind it as a value and must not inspect its shape to decide
|
|
1351
|
+
* whether it is query structure.
|
|
1352
|
+
*
|
|
1353
|
+
* @public
|
|
1354
|
+
*/
|
|
1346
1355
|
interface ParamExpressionIntent {
|
|
1347
1356
|
readonly kind: 'param';
|
|
1348
1357
|
readonly value: unknown;
|
|
1358
|
+
/** Optional alias when used as a SELECT expression. */
|
|
1359
|
+
readonly as?: string | undefined;
|
|
1349
1360
|
}
|
|
1361
|
+
/** @public */
|
|
1362
|
+
type ParamIntent = ParamExpressionIntent;
|
|
1363
|
+
/** Single-level only — never recurse into .value; the inner bound value is opaque user data. @public */
|
|
1364
|
+
declare function isParamIntent(value: unknown): value is ParamIntent;
|
|
1350
1365
|
/** Type cast expression */
|
|
1351
1366
|
interface CastExpressionIntent {
|
|
1352
1367
|
readonly kind: 'cast';
|
|
@@ -1655,7 +1670,7 @@ interface OrderByFieldIntent {
|
|
|
1655
1670
|
interface OrderByExpressionIntent {
|
|
1656
1671
|
readonly field?: never;
|
|
1657
1672
|
/** Expression to sort by */
|
|
1658
|
-
readonly expression: ExpressionIntent;
|
|
1673
|
+
readonly expression: ExpressionIntent | ParamIntent;
|
|
1659
1674
|
/** Sort direction */
|
|
1660
1675
|
readonly direction: SortDirection;
|
|
1661
1676
|
/**
|
|
@@ -1797,9 +1812,9 @@ interface QueryIntent {
|
|
|
1797
1812
|
*/
|
|
1798
1813
|
readonly distinctOn?: readonly string[];
|
|
1799
1814
|
/** Maximum number of rows */
|
|
1800
|
-
readonly limit?: number;
|
|
1815
|
+
readonly limit?: number | ParamIntent;
|
|
1801
1816
|
/** Number of rows to skip */
|
|
1802
|
-
readonly offset?: number;
|
|
1817
|
+
readonly offset?: number | ParamIntent;
|
|
1803
1818
|
/**
|
|
1804
1819
|
* When true, the adapter wraps the query in SELECT EXISTS(...).
|
|
1805
1820
|
* The inner SELECT list is replaced with `1` and the result is `{ exists: boolean }`.
|
|
@@ -1943,7 +1958,7 @@ interface InsertFromIntent {
|
|
|
1943
1958
|
/** Filter condition for source rows */
|
|
1944
1959
|
readonly where?: WhereIntent | undefined;
|
|
1945
1960
|
/** Limit number of rows to insert */
|
|
1946
|
-
readonly limit?: number | undefined;
|
|
1961
|
+
readonly limit?: number | ParamIntent | undefined;
|
|
1947
1962
|
/**
|
|
1948
1963
|
* Columns to return from inserted rows (DX-026).
|
|
1949
1964
|
* Requires adapter capability: supportsReturning
|
|
@@ -1971,7 +1986,7 @@ interface UpsertFromIntent {
|
|
|
1971
1986
|
/** Filter condition for source rows */
|
|
1972
1987
|
readonly where?: WhereIntent | undefined;
|
|
1973
1988
|
/** Limit number of rows */
|
|
1974
|
-
readonly limit?: number | undefined;
|
|
1989
|
+
readonly limit?: number | ParamIntent | undefined;
|
|
1975
1990
|
/**
|
|
1976
1991
|
* Columns to return from affected rows.
|
|
1977
1992
|
* Requires adapter capability: supportsReturning
|
|
@@ -2348,6 +2363,29 @@ interface RecursiveIntent {
|
|
|
2348
2363
|
readonly advancedOptions?: RecursiveAdvancedOptions;
|
|
2349
2364
|
}
|
|
2350
2365
|
|
|
2366
|
+
/**
|
|
2367
|
+
* NQL-origin SELECT function allowlist.
|
|
2368
|
+
*
|
|
2369
|
+
* This is the shared security gate for function names that originated in NQL
|
|
2370
|
+
* SELECT text and later cross the IntentAST-to-SQL adapter boundary. Extend it
|
|
2371
|
+
* only after adding compiler and adapter coverage proving the function is
|
|
2372
|
+
* intentionally supported for NQL-origin SELECT projections.
|
|
2373
|
+
*/
|
|
2374
|
+
declare const NQL_SELECT_AGGREGATE_FUNCTIONS: readonly ["count", "sum", "avg", "min", "max"];
|
|
2375
|
+
declare const NQL_SELECT_JSON_FUNCTIONS: readonly ["json_extract", "json_extract_text", "json_path", "json_path_text"];
|
|
2376
|
+
declare const NQL_SELECT_VALUE_FUNCTIONS: readonly ["coalesce", "lower", "now", "round", "upper"];
|
|
2377
|
+
declare const NQL_SELECT_SCALAR_FUNCTIONS: readonly ["count", "sum", "avg", "min", "max", "json_extract", "json_extract_text", "json_path", "json_path_text", "coalesce", "lower", "now", "round", "upper"];
|
|
2378
|
+
declare const NQL_SELECT_WINDOW_ONLY_FUNCTIONS: readonly ["row_number", "rank", "dense_rank", "lag", "lead"];
|
|
2379
|
+
declare const NQL_SELECT_WINDOW_FUNCTIONS: readonly ["row_number", "rank", "dense_rank", "lag", "lead", "count", "sum", "avg", "min", "max"];
|
|
2380
|
+
declare const NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST: ReadonlySet<string>;
|
|
2381
|
+
declare const NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST: ReadonlySet<string>;
|
|
2382
|
+
declare const NQL_SELECT_FUNCTION_ALLOWLIST: ReadonlySet<string>;
|
|
2383
|
+
type NqlSelectScalarFunction = (typeof NQL_SELECT_SCALAR_FUNCTIONS)[number];
|
|
2384
|
+
type NqlSelectWindowFunction = (typeof NQL_SELECT_WINDOW_FUNCTIONS)[number];
|
|
2385
|
+
declare function isNqlSelectScalarFunctionAllowed(name: string): name is NqlSelectScalarFunction;
|
|
2386
|
+
declare function isNqlSelectFunctionAllowed(name: string): boolean;
|
|
2387
|
+
declare function isNqlSelectWindowFunctionAllowed(name: string): name is NqlSelectWindowFunction;
|
|
2388
|
+
|
|
2351
2389
|
/**
|
|
2352
2390
|
* @module intent/type-guards
|
|
2353
2391
|
* Type guard functions for all intent AST types.
|
|
@@ -2736,6 +2774,22 @@ interface CompileOptionsBase {
|
|
|
2736
2774
|
*/
|
|
2737
2775
|
readonly maxBatchSize?: number;
|
|
2738
2776
|
}
|
|
2777
|
+
/**
|
|
2778
|
+
* Adapter-facing NQL compile bundle.
|
|
2779
|
+
*/
|
|
2780
|
+
interface CompiledNqlQuery {
|
|
2781
|
+
readonly query?: QueryIntent;
|
|
2782
|
+
/** CTE query (WITH clause): wraps outer QueryIntent in CteQueryIntent */
|
|
2783
|
+
readonly cteQuery?: CteQueryIntent;
|
|
2784
|
+
readonly mutation?: MutationIntent;
|
|
2785
|
+
readonly returning?: readonly string[];
|
|
2786
|
+
/** Named bindings from `| bind X` clauses (CTE source queries) */
|
|
2787
|
+
readonly bindings?: ReadonlyMap<string, QueryIntent>;
|
|
2788
|
+
/** Named mutation bindings from `mutation | select cols | bind X` clauses. */
|
|
2789
|
+
readonly mutationBindings?: ReadonlyMap<string, MutationIntent>;
|
|
2790
|
+
/** Set operation (UNION/INTERSECT/EXCEPT) wrapping two queries */
|
|
2791
|
+
readonly setOperation?: SetOperationIntent;
|
|
2792
|
+
}
|
|
2739
2793
|
/**
|
|
2740
2794
|
* Options for streaming query results.
|
|
2741
2795
|
*/
|
|
@@ -2856,7 +2910,7 @@ interface BaseAdapter {
|
|
|
2856
2910
|
*/
|
|
2857
2911
|
interface CompilingAdapter extends BaseAdapter {
|
|
2858
2912
|
/** Compile a plan to executable SQL. */
|
|
2859
|
-
compile<T = unknown>(plan: PlanReport, options?: CompileOptions): CompiledQuery<T>;
|
|
2913
|
+
compile<T = unknown>(plan: PlanReport | CompiledNqlQuery, options?: CompileOptions): CompiledQuery<T>;
|
|
2860
2914
|
/** Compile a plan with includes, returning subquery include metadata (DX-033). */
|
|
2861
2915
|
compileWithIncludes<T = unknown>(plan: PlanReport, options?: CompileOptions): CompileResultWithIncludes<T>;
|
|
2862
2916
|
/** Compile a subquery include query for given parent IDs (DX-033). */
|
|
@@ -3222,4 +3276,4 @@ interface LoadedSchema {
|
|
|
3222
3276
|
*/
|
|
3223
3277
|
declare function isValidSchema(schema: unknown): schema is LoadedSchema;
|
|
3224
3278
|
|
|
3225
|
-
export { type Adapter, type AdapterCapabilities, type AdapterLogger, type AdapterStreamOptions, type AdjacencyTraversal, type AggOrderByArg, type AggregateCountIntent, type AggregateExpressionIntent, type AggregateFieldIntent, type AggregateFunction, type AggregateIntent, type AggregateWindowFunction, type AggregateWindowIntent, type AliasIncludedColumnsMode, type AlterColumnOptions, type AmbiguityCheckResult, type ArithmeticExpressionIntent, type ArrayExpressionIntent, type ArrayOperator, type BaseAdapter, type BatchUpdateIntent, type BatchValuesJoinPayload, type CTEDefinition, type Cardinality, type CaseExpressionIntent, type CastExpressionIntent, type CheckConstraintIR, type CoalesceExpressionIntent, type ColumnAliasIntent, type ColumnExpressionIntent, type ColumnIR, type ColumnType, type CommonColumnType, type ComparisonExpressionIntent, type ComparisonOperator, type CompileOnlyAdapter, type CompileOptions, type CompileOptionsBase, type CompileResultWithIncludes, type CompiledQuery, type CompilingAdapter, type CreateIndexOptions, type CteQueryIntent, type CustomFnExpressionIntent, type CustomOpExpressionIntent, type CustomTraversal, type DDLFeature, type DDLFeatureElementMap, type DDLFeatureVersionRange, type DDLGeneratingAdapter, type DbCasing, type DecisionType, type DeleteIntent, type DialectCapabilities, type DialectName, type DropIndexOptions, type DuckDBColumnType, type Dump, type DumpMeta, type EdgeTableTraversal, type EmitJoinClause, type EnumIR, type ExecutingAdapter, type ExpressionIntent, type FeatureBehaviorConfig, type FeatureTranslator, type FeatureWarning, type FieldRef, type FilterStrategy, type ForeignKeyIR, type FunctionExpressionIntent, type HierarchyIR, type IncludeIntent, type IncludeRecursiveOptions, type IncludeStrategy, type IndexColumnDef, type IndexIR, type IndexInfo, type IndexMethod, type InsertFromIntent, type InsertIntent, type IntrospectingAdapter, type IntrospectionOptions, type IntrospectionResult, type IsTypeSupported, type JoinDefault, type JoinIntent, type JsonContainsIntent, type JsonExistsIntent, type JsonExtractIntent, type JsonPathExtractIntent, type LiteralExpressionIntent, type LoadedSchema, type LockIntent, type LockStrength, type LockWaitPolicy, type LogicalOperator, type MSSQLColumnType, type ModelIR, type MutationIntent, type MySQLColumnType, type NamedArgExpressionIntent, type NullOperator, type NullsPosition, type OffsetWindowFunction, type OffsetWindowIntent, type OnDeleteAction, type Optionality, type OrderByExpressionIntent, type OrderByFieldIntent, type OrderByIntent, type ParamExpressionIntent, type PartitionIR, type PlanDecision, type PlanOptions, type PlanReport, type PlanWarning, type PlanWarningCode, type PolicyIR, type PostgresColumnType, type PostgresOnlyColumnType, type PseudoColumnExpressionIntent, type PseudoColumnMetadata, type PseudoColumnTraversal, type QueryIntent, type RangeOperand, type RangeOperator, type RangeValue, type RankingWindowFunction, type RankingWindowIntent, type RawCteIntent, type RawExpressionIntent, type RawSqlAdapter, type RecursiveAdvancedOptions, type RecursiveDedupe, type RecursiveDirection, type RecursiveEmitOptions, type RecursiveExistsOptions, type RecursiveIntent, type RecursiveMetadata, type RecursiveNodeIdExpr, type RecursivePlanOptions, type RecursivePlanReport, type RecursiveTrackOptions, type RecursiveTraversal, type RefExpressionIntent, type RelationColumnIntent, type RelationIR, type RelationKind, type RelationOperator, type RelationType, type ResolvedIncludeStrategy, type SQLiteColumnType, type ScalarSubqueryIntent, type SelectAggregateIntent, type SelectAllIntent, type SelectFieldsIntent, type SelectIntent, type SelectWithExpressionsIntent, type SequenceIR, type SetOperationIntent, type SetOperationType, type SimpleCteIntent, type SortDirection, type StarExpressionIntent, type StreamingAdapter, type StringOperator, type SubqueryExpressionIntent, type SubqueryIncludeInfo, type SubqueryRefIntent, type SupportedColumnTypes, type TableDDLGeneratorAdapter, type TableIR, type TransactionalAdapter, type TranslationContext, type TruncateOptions, type UnaryExpressionIntent, type UnnestCteIntent, type UnsupportedFeatureBehavior, type UpdateIntent, type UpsertConflictAction, type UpsertConflictTarget, type UpsertFromIntent, type UpsertIntent, type VacuumOptions, type WhereAndIntent, type WhereAnyIntent, type WhereComparisonIntent, type WhereExistsIntent, type WhereExpressionIntent, type WhereInIntent, type WhereInSubqueryIntent, type WhereInValueIntent, type WhereIntent, type WhereJsonContainsIntent, type WhereJsonExistsIntent, type WhereLikeIntent, type WhereNotExistsIntent, type WhereNotIntent, type WhereNullIntent, type WhereOrIntent, type WhereRangeIntent, type WhereRawExistsIntent, type WhereRawNotExistsIntent, type WhereRelationFilterIntent, type WhereSubqueryIntent, type WindowFunction, type WindowIntent, type WindowOrderBy, getNodeIdAlias, isAdjacencyTraversal, isAggregateWindowFunction, isCoalesceExpression, isColumnAliasExpression, isCustomTraversal, isDeleteIntent, isEdgeTableTraversal, isFieldRef, isInsertIntent, isMutationIntent, isRankingWindowFunction, isRawExpression, isRecursiveIntent, isRelationColumnExpression, isSelectAggregate, isSelectAll, isSelectFields, isSelectWithExpressions, isSubqueryRef, isUpdateIntent, isUpsertIntent, isValidSchema, isWhereAnd, isWhereAny, isWhereComparison, isWhereExists, isWhereIn, isWhereLike, isWhereLogical, isWhereNot, isWhereNotExists, isWhereNull, isWhereOr, isWhereRange, isWhereRelationBased, isWhereRelationFilter, isWhereSubquery, isWindowIntent };
|
|
3279
|
+
export { type Adapter, type AdapterCapabilities, type AdapterLogger, type AdapterStreamOptions, type AdjacencyTraversal, type AggOrderByArg, type AggregateCountIntent, type AggregateExpressionIntent, type AggregateFieldIntent, type AggregateFunction, type AggregateIntent, type AggregateWindowFunction, type AggregateWindowIntent, type AliasIncludedColumnsMode, type AlterColumnOptions, type AmbiguityCheckResult, type ArithmeticExpressionIntent, type ArrayExpressionIntent, type ArrayOperator, type BaseAdapter, type BatchUpdateIntent, type BatchValuesJoinPayload, type CTEDefinition, type Cardinality, type CaseExpressionIntent, type CastExpressionIntent, type CheckConstraintIR, type CoalesceExpressionIntent, type ColumnAliasIntent, type ColumnExpressionIntent, type ColumnIR, type ColumnType, type CommonColumnType, type ComparisonExpressionIntent, type ComparisonOperator, type CompileOnlyAdapter, type CompileOptions, type CompileOptionsBase, type CompileResultWithIncludes, type CompiledNqlQuery, type CompiledQuery, type CompilingAdapter, type CreateIndexOptions, type CteQueryIntent, type CustomFnExpressionIntent, type CustomOpExpressionIntent, type CustomTraversal, type DDLFeature, type DDLFeatureElementMap, type DDLFeatureVersionRange, type DDLGeneratingAdapter, type DbCasing, type DecisionType, type DeleteIntent, type DialectCapabilities, type DialectName, type DropIndexOptions, type DuckDBColumnType, type Dump, type DumpMeta, type EdgeTableTraversal, type EmitJoinClause, type EnumIR, type ExecutingAdapter, type ExpressionIntent, type FeatureBehaviorConfig, type FeatureTranslator, type FeatureWarning, type FieldRef, type FilterStrategy, type ForeignKeyIR, type FunctionExpressionIntent, type HierarchyIR, type IncludeIntent, type IncludeRecursiveOptions, type IncludeStrategy, type IndexColumnDef, type IndexIR, type IndexInfo, type IndexMethod, type InsertFromIntent, type InsertIntent, type IntrospectingAdapter, type IntrospectionOptions, type IntrospectionResult, type IsTypeSupported, type JoinDefault, type JoinIntent, type JsonContainsIntent, type JsonExistsIntent, type JsonExtractIntent, type JsonPathExtractIntent, type LiteralExpressionIntent, type LoadedSchema, type LockIntent, type LockStrength, type LockWaitPolicy, type LogicalOperator, type MSSQLColumnType, type ModelIR, type MutationIntent, type MySQLColumnType, NQL_SELECT_AGGREGATE_FUNCTIONS, NQL_SELECT_FUNCTION_ALLOWLIST, NQL_SELECT_JSON_FUNCTIONS, NQL_SELECT_SCALAR_FUNCTIONS, NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST, NQL_SELECT_VALUE_FUNCTIONS, NQL_SELECT_WINDOW_FUNCTIONS, NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST, NQL_SELECT_WINDOW_ONLY_FUNCTIONS, type NamedArgExpressionIntent, type NullOperator, type NullsPosition, type OffsetWindowFunction, type OffsetWindowIntent, type OnDeleteAction, type Optionality, type OrderByExpressionIntent, type OrderByFieldIntent, type OrderByIntent, type ParamExpressionIntent, type ParamIntent, type PartitionIR, type PlanDecision, type PlanOptions, type PlanReport, type PlanWarning, type PlanWarningCode, type PolicyIR, type PostgresColumnType, type PostgresOnlyColumnType, type PseudoColumnExpressionIntent, type PseudoColumnMetadata, type PseudoColumnTraversal, type QueryIntent, type RangeOperand, type RangeOperator, type RangeValue, type RankingWindowFunction, type RankingWindowIntent, type RawCteIntent, type RawExpressionIntent, type RawSqlAdapter, type RecursiveAdvancedOptions, type RecursiveDedupe, type RecursiveDirection, type RecursiveEmitOptions, type RecursiveExistsOptions, type RecursiveIntent, type RecursiveMetadata, type RecursiveNodeIdExpr, type RecursivePlanOptions, type RecursivePlanReport, type RecursiveTrackOptions, type RecursiveTraversal, type RefExpressionIntent, type RelationColumnIntent, type RelationIR, type RelationKind, type RelationOperator, type RelationType, type ResolvedIncludeStrategy, type SQLiteColumnType, type ScalarSubqueryIntent, type SelectAggregateIntent, type SelectAllIntent, type SelectFieldsIntent, type SelectIntent, type SelectWithExpressionsIntent, type SequenceIR, type SetOperationIntent, type SetOperationType, type SimpleCteIntent, type SortDirection, type StarExpressionIntent, type StreamingAdapter, type StringOperator, type SubqueryExpressionIntent, type SubqueryIncludeInfo, type SubqueryRefIntent, type SupportedColumnTypes, type TableDDLGeneratorAdapter, type TableIR, type TransactionalAdapter, type TranslationContext, type TruncateOptions, type UnaryExpressionIntent, type UnnestCteIntent, type UnsupportedFeatureBehavior, type UpdateIntent, type UpsertConflictAction, type UpsertConflictTarget, type UpsertFromIntent, type UpsertIntent, type VacuumOptions, type WhereAndIntent, type WhereAnyIntent, type WhereComparisonIntent, type WhereExistsIntent, type WhereExpressionIntent, type WhereInIntent, type WhereInSubqueryIntent, type WhereInValueIntent, type WhereIntent, type WhereJsonContainsIntent, type WhereJsonExistsIntent, type WhereLikeIntent, type WhereNotExistsIntent, type WhereNotIntent, type WhereNullIntent, type WhereOrIntent, type WhereRangeIntent, type WhereRawExistsIntent, type WhereRawNotExistsIntent, type WhereRelationFilterIntent, type WhereSubqueryIntent, type WindowFunction, type WindowIntent, type WindowOrderBy, getNodeIdAlias, isAdjacencyTraversal, isAggregateWindowFunction, isCoalesceExpression, isColumnAliasExpression, isCustomTraversal, isDeleteIntent, isEdgeTableTraversal, isFieldRef, isInsertIntent, isMutationIntent, isNqlSelectFunctionAllowed, isNqlSelectScalarFunctionAllowed, isNqlSelectWindowFunctionAllowed, isParamIntent, isRankingWindowFunction, isRawExpression, isRecursiveIntent, isRelationColumnExpression, isSelectAggregate, isSelectAll, isSelectFields, isSelectWithExpressions, isSubqueryRef, isUpdateIntent, isUpsertIntent, isValidSchema, isWhereAnd, isWhereAny, isWhereComparison, isWhereExists, isWhereIn, isWhereLike, isWhereLogical, isWhereNot, isWhereNotExists, isWhereNull, isWhereOr, isWhereRange, isWhereRelationBased, isWhereRelationFilter, isWhereSubquery, isWindowIntent };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
NQL_SELECT_AGGREGATE_FUNCTIONS,
|
|
3
|
+
NQL_SELECT_FUNCTION_ALLOWLIST,
|
|
4
|
+
NQL_SELECT_JSON_FUNCTIONS,
|
|
5
|
+
NQL_SELECT_SCALAR_FUNCTIONS,
|
|
6
|
+
NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST,
|
|
7
|
+
NQL_SELECT_VALUE_FUNCTIONS,
|
|
8
|
+
NQL_SELECT_WINDOW_FUNCTIONS,
|
|
9
|
+
NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST,
|
|
10
|
+
NQL_SELECT_WINDOW_ONLY_FUNCTIONS,
|
|
2
11
|
getNodeIdAlias,
|
|
3
12
|
isAdjacencyTraversal,
|
|
4
13
|
isAggregateWindowFunction,
|
|
@@ -10,6 +19,10 @@ import {
|
|
|
10
19
|
isFieldRef,
|
|
11
20
|
isInsertIntent,
|
|
12
21
|
isMutationIntent,
|
|
22
|
+
isNqlSelectFunctionAllowed,
|
|
23
|
+
isNqlSelectScalarFunctionAllowed,
|
|
24
|
+
isNqlSelectWindowFunctionAllowed,
|
|
25
|
+
isParamIntent,
|
|
13
26
|
isRankingWindowFunction,
|
|
14
27
|
isRawExpression,
|
|
15
28
|
isRecursiveIntent,
|
|
@@ -38,8 +51,17 @@ import {
|
|
|
38
51
|
isWhereRelationFilter,
|
|
39
52
|
isWhereSubquery,
|
|
40
53
|
isWindowIntent
|
|
41
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-N47PVUJW.js";
|
|
42
55
|
export {
|
|
56
|
+
NQL_SELECT_AGGREGATE_FUNCTIONS,
|
|
57
|
+
NQL_SELECT_FUNCTION_ALLOWLIST,
|
|
58
|
+
NQL_SELECT_JSON_FUNCTIONS,
|
|
59
|
+
NQL_SELECT_SCALAR_FUNCTIONS,
|
|
60
|
+
NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST,
|
|
61
|
+
NQL_SELECT_VALUE_FUNCTIONS,
|
|
62
|
+
NQL_SELECT_WINDOW_FUNCTIONS,
|
|
63
|
+
NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST,
|
|
64
|
+
NQL_SELECT_WINDOW_ONLY_FUNCTIONS,
|
|
43
65
|
getNodeIdAlias,
|
|
44
66
|
isAdjacencyTraversal,
|
|
45
67
|
isAggregateWindowFunction,
|
|
@@ -51,6 +73,10 @@ export {
|
|
|
51
73
|
isFieldRef,
|
|
52
74
|
isInsertIntent,
|
|
53
75
|
isMutationIntent,
|
|
76
|
+
isNqlSelectFunctionAllowed,
|
|
77
|
+
isNqlSelectScalarFunctionAllowed,
|
|
78
|
+
isNqlSelectWindowFunctionAllowed,
|
|
79
|
+
isParamIntent,
|
|
54
80
|
isRankingWindowFunction,
|
|
55
81
|
isRawExpression,
|
|
56
82
|
isRecursiveIntent,
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { Adapter, AdapterCapabilities, AdapterLogger, AdapterStreamOptions, AdjacencyTraversal, AggOrderByArg, AggregateCountIntent, AggregateExpressionIntent, AggregateFieldIntent, AggregateFunction, AggregateIntent, AggregateWindowFunction, AggregateWindowIntent, AliasIncludedColumnsMode, AlterColumnOptions, AmbiguityCheckResult, ArithmeticExpressionIntent, ArrayExpressionIntent, ArrayOperator, BaseAdapter, BatchUpdateIntent, BatchValuesJoinPayload, CTEDefinition, Cardinality, CaseExpressionIntent, CastExpressionIntent, CheckConstraintIR, CoalesceExpressionIntent, ColumnAliasIntent, ColumnExpressionIntent, ColumnIR, ColumnType, CommonColumnType, ComparisonExpressionIntent, ComparisonOperator, CompileOnlyAdapter, CompileOptions, CompileOptionsBase, CompileResultWithIncludes, CompiledQuery, CompilingAdapter, CreateIndexOptions, CteQueryIntent, CustomFnExpressionIntent, CustomOpExpressionIntent, CustomTraversal, DDLFeature, DDLFeatureElementMap, DDLFeatureVersionRange, DDLGeneratingAdapter, DbCasing, DecisionType, DeleteIntent, DialectCapabilities, DialectName, DropIndexOptions, DuckDBColumnType, Dump, DumpMeta, EdgeTableTraversal, EmitJoinClause, EnumIR, ExecutingAdapter, ExpressionIntent, FeatureBehaviorConfig, FeatureTranslator, FeatureWarning, FieldRef, FilterStrategy, ForeignKeyIR, FunctionExpressionIntent, HierarchyIR, IncludeIntent, IncludeRecursiveOptions, IncludeStrategy, IndexColumnDef, IndexIR, IndexInfo, IndexMethod, InsertFromIntent, InsertIntent, IntrospectingAdapter, IntrospectionOptions, IntrospectionResult, IsTypeSupported, JoinDefault, JoinIntent, JsonContainsIntent, JsonExistsIntent, JsonExtractIntent, JsonPathExtractIntent, LiteralExpressionIntent, LoadedSchema, LockIntent, LockStrength, LockWaitPolicy, LogicalOperator, MSSQLColumnType, ModelIR, MutationIntent, MySQLColumnType, NamedArgExpressionIntent, NullOperator, NullsPosition, OffsetWindowFunction, OffsetWindowIntent, OnDeleteAction, Optionality, OrderByExpressionIntent, OrderByFieldIntent, OrderByIntent, ParamExpressionIntent, PartitionIR, PlanDecision, PlanOptions, PlanReport, PlanWarning, PlanWarningCode, PolicyIR, PostgresColumnType, PostgresOnlyColumnType, PseudoColumnExpressionIntent, PseudoColumnMetadata, PseudoColumnTraversal, QueryIntent, RangeOperand, RangeOperator, RangeValue, RankingWindowFunction, RankingWindowIntent, RawCteIntent, RawExpressionIntent, RawSqlAdapter, RecursiveAdvancedOptions, RecursiveDedupe, RecursiveDirection, RecursiveEmitOptions, RecursiveExistsOptions, RecursiveIntent, RecursiveMetadata, RecursiveNodeIdExpr, RecursivePlanOptions, RecursivePlanReport, RecursiveTrackOptions, RecursiveTraversal, RefExpressionIntent, RelationColumnIntent, RelationIR, RelationKind, RelationOperator, RelationType, ResolvedIncludeStrategy, SQLiteColumnType, ScalarSubqueryIntent, SelectAggregateIntent, SelectAllIntent, SelectFieldsIntent, SelectIntent, SelectWithExpressionsIntent, SequenceIR, SetOperationIntent, SetOperationType, SimpleCteIntent, SortDirection, StarExpressionIntent, StreamingAdapter, StringOperator, SubqueryExpressionIntent, SubqueryIncludeInfo, SubqueryRefIntent, SupportedColumnTypes, TableDDLGeneratorAdapter, TableIR, TransactionalAdapter, TranslationContext, TruncateOptions, UnaryExpressionIntent, UnnestCteIntent, UnsupportedFeatureBehavior, UpdateIntent, UpsertConflictAction, UpsertConflictTarget, UpsertFromIntent, UpsertIntent, VacuumOptions, WhereAndIntent, WhereAnyIntent, WhereComparisonIntent, WhereExistsIntent, WhereExpressionIntent, WhereInIntent, WhereInSubqueryIntent, WhereInValueIntent, WhereIntent, WhereJsonContainsIntent, WhereJsonExistsIntent, WhereLikeIntent, WhereNotExistsIntent, WhereNotIntent, WhereNullIntent, WhereOrIntent, WhereRangeIntent, WhereRawExistsIntent, WhereRawNotExistsIntent, WhereRelationFilterIntent, WhereSubqueryIntent, WindowFunction, WindowIntent, WindowOrderBy, getNodeIdAlias, isAdjacencyTraversal, isAggregateWindowFunction, isCoalesceExpression, isColumnAliasExpression, isCustomTraversal, isDeleteIntent, isEdgeTableTraversal, isFieldRef, isInsertIntent, isMutationIntent, isRankingWindowFunction, isRawExpression, isRecursiveIntent, isRelationColumnExpression, isSelectAggregate, isSelectAll, isSelectFields, isSelectWithExpressions, isSubqueryRef, isUpdateIntent, isUpsertIntent, isValidSchema, isWhereAnd, isWhereAny, isWhereComparison, isWhereExists, isWhereIn, isWhereLike, isWhereLogical, isWhereNot, isWhereNotExists, isWhereNull, isWhereOr, isWhereRange, isWhereRelationBased, isWhereRelationFilter, isWhereSubquery, isWindowIntent } from './index.js';
|
|
1
|
+
export { Adapter, AdapterCapabilities, AdapterLogger, AdapterStreamOptions, AdjacencyTraversal, AggOrderByArg, AggregateCountIntent, AggregateExpressionIntent, AggregateFieldIntent, AggregateFunction, AggregateIntent, AggregateWindowFunction, AggregateWindowIntent, AliasIncludedColumnsMode, AlterColumnOptions, AmbiguityCheckResult, ArithmeticExpressionIntent, ArrayExpressionIntent, ArrayOperator, BaseAdapter, BatchUpdateIntent, BatchValuesJoinPayload, CTEDefinition, Cardinality, CaseExpressionIntent, CastExpressionIntent, CheckConstraintIR, CoalesceExpressionIntent, ColumnAliasIntent, ColumnExpressionIntent, ColumnIR, ColumnType, CommonColumnType, ComparisonExpressionIntent, ComparisonOperator, CompileOnlyAdapter, CompileOptions, CompileOptionsBase, CompileResultWithIncludes, CompiledNqlQuery, CompiledQuery, CompilingAdapter, CreateIndexOptions, CteQueryIntent, CustomFnExpressionIntent, CustomOpExpressionIntent, CustomTraversal, DDLFeature, DDLFeatureElementMap, DDLFeatureVersionRange, DDLGeneratingAdapter, DbCasing, DecisionType, DeleteIntent, DialectCapabilities, DialectName, DropIndexOptions, DuckDBColumnType, Dump, DumpMeta, EdgeTableTraversal, EmitJoinClause, EnumIR, ExecutingAdapter, ExpressionIntent, FeatureBehaviorConfig, FeatureTranslator, FeatureWarning, FieldRef, FilterStrategy, ForeignKeyIR, FunctionExpressionIntent, HierarchyIR, IncludeIntent, IncludeRecursiveOptions, IncludeStrategy, IndexColumnDef, IndexIR, IndexInfo, IndexMethod, InsertFromIntent, InsertIntent, IntrospectingAdapter, IntrospectionOptions, IntrospectionResult, IsTypeSupported, JoinDefault, JoinIntent, JsonContainsIntent, JsonExistsIntent, JsonExtractIntent, JsonPathExtractIntent, LiteralExpressionIntent, LoadedSchema, LockIntent, LockStrength, LockWaitPolicy, LogicalOperator, MSSQLColumnType, ModelIR, MutationIntent, MySQLColumnType, NQL_SELECT_AGGREGATE_FUNCTIONS, NQL_SELECT_FUNCTION_ALLOWLIST, NQL_SELECT_JSON_FUNCTIONS, NQL_SELECT_SCALAR_FUNCTIONS, NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST, NQL_SELECT_VALUE_FUNCTIONS, NQL_SELECT_WINDOW_FUNCTIONS, NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST, NQL_SELECT_WINDOW_ONLY_FUNCTIONS, NamedArgExpressionIntent, NullOperator, NullsPosition, OffsetWindowFunction, OffsetWindowIntent, OnDeleteAction, Optionality, OrderByExpressionIntent, OrderByFieldIntent, OrderByIntent, ParamExpressionIntent, ParamIntent, PartitionIR, PlanDecision, PlanOptions, PlanReport, PlanWarning, PlanWarningCode, PolicyIR, PostgresColumnType, PostgresOnlyColumnType, PseudoColumnExpressionIntent, PseudoColumnMetadata, PseudoColumnTraversal, QueryIntent, RangeOperand, RangeOperator, RangeValue, RankingWindowFunction, RankingWindowIntent, RawCteIntent, RawExpressionIntent, RawSqlAdapter, RecursiveAdvancedOptions, RecursiveDedupe, RecursiveDirection, RecursiveEmitOptions, RecursiveExistsOptions, RecursiveIntent, RecursiveMetadata, RecursiveNodeIdExpr, RecursivePlanOptions, RecursivePlanReport, RecursiveTrackOptions, RecursiveTraversal, RefExpressionIntent, RelationColumnIntent, RelationIR, RelationKind, RelationOperator, RelationType, ResolvedIncludeStrategy, SQLiteColumnType, ScalarSubqueryIntent, SelectAggregateIntent, SelectAllIntent, SelectFieldsIntent, SelectIntent, SelectWithExpressionsIntent, SequenceIR, SetOperationIntent, SetOperationType, SimpleCteIntent, SortDirection, StarExpressionIntent, StreamingAdapter, StringOperator, SubqueryExpressionIntent, SubqueryIncludeInfo, SubqueryRefIntent, SupportedColumnTypes, TableDDLGeneratorAdapter, TableIR, TransactionalAdapter, TranslationContext, TruncateOptions, UnaryExpressionIntent, UnnestCteIntent, UnsupportedFeatureBehavior, UpdateIntent, UpsertConflictAction, UpsertConflictTarget, UpsertFromIntent, UpsertIntent, VacuumOptions, WhereAndIntent, WhereAnyIntent, WhereComparisonIntent, WhereExistsIntent, WhereExpressionIntent, WhereInIntent, WhereInSubqueryIntent, WhereInValueIntent, WhereIntent, WhereJsonContainsIntent, WhereJsonExistsIntent, WhereLikeIntent, WhereNotExistsIntent, WhereNotIntent, WhereNullIntent, WhereOrIntent, WhereRangeIntent, WhereRawExistsIntent, WhereRawNotExistsIntent, WhereRelationFilterIntent, WhereSubqueryIntent, WindowFunction, WindowIntent, WindowOrderBy, getNodeIdAlias, isAdjacencyTraversal, isAggregateWindowFunction, isCoalesceExpression, isColumnAliasExpression, isCustomTraversal, isDeleteIntent, isEdgeTableTraversal, isFieldRef, isInsertIntent, isMutationIntent, isNqlSelectFunctionAllowed, isNqlSelectScalarFunctionAllowed, isNqlSelectWindowFunctionAllowed, isParamIntent, isRankingWindowFunction, isRawExpression, isRecursiveIntent, isRelationColumnExpression, isSelectAggregate, isSelectAll, isSelectFields, isSelectWithExpressions, isSubqueryRef, isUpdateIntent, isUpsertIntent, isValidSchema, isWhereAnd, isWhereAny, isWhereComparison, isWhereExists, isWhereIn, isWhereLike, isWhereLogical, isWhereNot, isWhereNotExists, isWhereNull, isWhereOr, isWhereRange, isWhereRelationBased, isWhereRelationFilter, isWhereSubquery, isWindowIntent } from './index.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @module builders
|
|
@@ -27,4 +27,22 @@ type Mutable<T> = {
|
|
|
27
27
|
*/
|
|
28
28
|
type IntentBuilder<T, TRequired extends keyof T> = Pick<T, TRequired> & Partial<Omit<T, TRequired>>;
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
/**
|
|
31
|
+
* @dbsp/types/internal - Internal type definitions
|
|
32
|
+
*
|
|
33
|
+
* These types are for internal use by @dbsp package implementations.
|
|
34
|
+
* They are NOT part of the public API and may change without notice.
|
|
35
|
+
*
|
|
36
|
+
* @module @dbsp/types/internal
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @internal Shared compiler-options marker for trusted NQL package internals.
|
|
42
|
+
*
|
|
43
|
+
* Deliberately uses Symbol(), not Symbol.for(), so knowing the description does
|
|
44
|
+
* not let callers forge the marker through the global symbol registry.
|
|
45
|
+
*/
|
|
46
|
+
declare const NQL_INTERNAL_COMPILER_OPTIONS: unique symbol;
|
|
47
|
+
|
|
48
|
+
export { type IntentBuilder, type Mutable, NQL_INTERNAL_COMPILER_OPTIONS };
|
package/dist/internal.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
NQL_SELECT_AGGREGATE_FUNCTIONS,
|
|
3
|
+
NQL_SELECT_FUNCTION_ALLOWLIST,
|
|
4
|
+
NQL_SELECT_JSON_FUNCTIONS,
|
|
5
|
+
NQL_SELECT_SCALAR_FUNCTIONS,
|
|
6
|
+
NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST,
|
|
7
|
+
NQL_SELECT_VALUE_FUNCTIONS,
|
|
8
|
+
NQL_SELECT_WINDOW_FUNCTIONS,
|
|
9
|
+
NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST,
|
|
10
|
+
NQL_SELECT_WINDOW_ONLY_FUNCTIONS,
|
|
2
11
|
getNodeIdAlias,
|
|
3
12
|
isAdjacencyTraversal,
|
|
4
13
|
isAggregateWindowFunction,
|
|
@@ -10,6 +19,10 @@ import {
|
|
|
10
19
|
isFieldRef,
|
|
11
20
|
isInsertIntent,
|
|
12
21
|
isMutationIntent,
|
|
22
|
+
isNqlSelectFunctionAllowed,
|
|
23
|
+
isNqlSelectScalarFunctionAllowed,
|
|
24
|
+
isNqlSelectWindowFunctionAllowed,
|
|
25
|
+
isParamIntent,
|
|
13
26
|
isRankingWindowFunction,
|
|
14
27
|
isRawExpression,
|
|
15
28
|
isRecursiveIntent,
|
|
@@ -38,8 +51,23 @@ import {
|
|
|
38
51
|
isWhereRelationFilter,
|
|
39
52
|
isWhereSubquery,
|
|
40
53
|
isWindowIntent
|
|
41
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-N47PVUJW.js";
|
|
55
|
+
|
|
56
|
+
// src/internal.ts
|
|
57
|
+
var NQL_INTERNAL_COMPILER_OPTIONS = /* @__PURE__ */ Symbol(
|
|
58
|
+
"@dbsp/nql/internalCompilerOptions"
|
|
59
|
+
);
|
|
42
60
|
export {
|
|
61
|
+
NQL_INTERNAL_COMPILER_OPTIONS,
|
|
62
|
+
NQL_SELECT_AGGREGATE_FUNCTIONS,
|
|
63
|
+
NQL_SELECT_FUNCTION_ALLOWLIST,
|
|
64
|
+
NQL_SELECT_JSON_FUNCTIONS,
|
|
65
|
+
NQL_SELECT_SCALAR_FUNCTIONS,
|
|
66
|
+
NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST,
|
|
67
|
+
NQL_SELECT_VALUE_FUNCTIONS,
|
|
68
|
+
NQL_SELECT_WINDOW_FUNCTIONS,
|
|
69
|
+
NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST,
|
|
70
|
+
NQL_SELECT_WINDOW_ONLY_FUNCTIONS,
|
|
43
71
|
getNodeIdAlias,
|
|
44
72
|
isAdjacencyTraversal,
|
|
45
73
|
isAggregateWindowFunction,
|
|
@@ -51,6 +79,10 @@ export {
|
|
|
51
79
|
isFieldRef,
|
|
52
80
|
isInsertIntent,
|
|
53
81
|
isMutationIntent,
|
|
82
|
+
isNqlSelectFunctionAllowed,
|
|
83
|
+
isNqlSelectScalarFunctionAllowed,
|
|
84
|
+
isNqlSelectWindowFunctionAllowed,
|
|
85
|
+
isParamIntent,
|
|
54
86
|
isRankingWindowFunction,
|
|
55
87
|
isRawExpression,
|
|
56
88
|
isRecursiveIntent,
|
package/dist/internal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/internal.ts"],"sourcesContent":["/**\n * @dbsp/types/internal - Internal type definitions\n *\n * These types are for internal use by @dbsp package implementations.\n * They are NOT part of the public API and may change without notice.\n *\n * @module @dbsp/types/internal\n * @internal\n */\n\n// Internal-only build utilities (NOT part of public API)\nexport type { IntentBuilder, Mutable } from './builders.js';\n\n/**\n * @internal Shared compiler-options marker for trusted NQL package internals.\n *\n * Deliberately uses Symbol(), not Symbol.for(), so knowing the description does\n * not let callers forge the marker through the global symbol registry.\n */\nexport const NQL_INTERNAL_COMPILER_OPTIONS: unique symbol = Symbol(\n\t'@dbsp/nql/internalCompilerOptions',\n);\n\n// Re-export all public types for convenience\nexport * from './index.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmBO,IAAM,gCAA+C;AAAA,EAC3D;AACD;","names":[]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/intent/recursive-intent.ts","../src/intent/type-guards.ts","../src/intent/where-intent.ts","../src/loaded-schema.ts"],"sourcesContent":["/**\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 * @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 { RangeValue } from '../shared/utils.js';\nimport type { ExpressionIntent } 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[];\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;\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[];\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}\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 * Scalar subquery intent - produces a single value.\n * Simplified QueryIntent for subquery context.\n */\n/** @deprecated Use QueryIntent instead — subqueries are full queries with contextual validation */\nexport type ScalarSubqueryIntent = QueryIntent;\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;\n}\n\n/** WHERE clause using a custom expression with comparison */\nexport interface WhereExpressionIntent {\n\treadonly kind: 'expression';\n\treadonly expr: ExpressionIntent;\n\treadonly operator: ComparisonOperator;\n\treadonly value: unknown;\n}\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 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\treadonly model: ModelIR;\n\treadonly tableNames: readonly string[];\n}\n\n/**\n * Runtime type guard for `LoadedSchema` — verifies the object has\n * `definition`, `model` (with nested `tables` + `relations`), and\n * `tableNames` as an array. Structural check only — does not validate\n * the inner values of any field.\n *\n * Type guard for ARCH-005 schema() output.\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 (!Array.isArray(s.tableNames)) 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"],"mappings":"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","names":[]}
|