@vibeorm/runtime 1.3.0 → 2.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +50 -107
  2. package/dist/adapter.d.ts +250 -0
  3. package/dist/adapter.d.ts.map +1 -0
  4. package/dist/bulk-upsert.d.ts +282 -0
  5. package/dist/bulk-upsert.d.ts.map +1 -0
  6. package/dist/client.d.ts +200 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/codecs.d.ts +170 -0
  9. package/dist/codecs.d.ts.map +1 -0
  10. package/dist/computed.d.ts +43 -0
  11. package/dist/computed.d.ts.map +1 -0
  12. package/dist/db-now.d.ts +41 -0
  13. package/dist/db-now.d.ts.map +1 -0
  14. package/dist/diagnostics/index.d.ts +12 -0
  15. package/dist/diagnostics/index.d.ts.map +1 -0
  16. package/dist/diagnostics/insight.d.ts +63 -0
  17. package/dist/diagnostics/insight.d.ts.map +1 -0
  18. package/dist/diagnostics/plan.d.ts +88 -0
  19. package/dist/diagnostics/plan.d.ts.map +1 -0
  20. package/dist/diagnostics/preview.d.ts +43 -0
  21. package/dist/diagnostics/preview.d.ts.map +1 -0
  22. package/dist/diagnostics/types.d.ts +223 -0
  23. package/dist/diagnostics/types.d.ts.map +1 -0
  24. package/dist/diagnostics/workload.d.ts +32 -0
  25. package/dist/diagnostics/workload.d.ts.map +1 -0
  26. package/dist/extensions.d.ts +102 -0
  27. package/dist/extensions.d.ts.map +1 -0
  28. package/dist/index.d.ts +59 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +13070 -0
  31. package/dist/index.js.map +43 -0
  32. package/dist/keyset-iterator.d.ts +73 -0
  33. package/dist/keyset-iterator.d.ts.map +1 -0
  34. package/dist/keyset.d.ts +121 -0
  35. package/dist/keyset.d.ts.map +1 -0
  36. package/dist/model-meta.d.ts +200 -0
  37. package/dist/model-meta.d.ts.map +1 -0
  38. package/dist/nested-writes.d.ts +67 -0
  39. package/dist/nested-writes.d.ts.map +1 -0
  40. package/dist/policy-operation.d.ts +14 -0
  41. package/dist/policy-operation.d.ts.map +1 -0
  42. package/dist/policy.d.ts +17 -0
  43. package/dist/policy.d.ts.map +1 -0
  44. package/dist/query-builder.d.ts +271 -0
  45. package/dist/query-builder.d.ts.map +1 -0
  46. package/dist/relation-key.d.ts +23 -0
  47. package/dist/relation-key.d.ts.map +1 -0
  48. package/dist/relation-loader.d.ts +46 -0
  49. package/dist/relation-loader.d.ts.map +1 -0
  50. package/dist/relation-plan.d.ts +141 -0
  51. package/dist/relation-plan.d.ts.map +1 -0
  52. package/dist/render-cache.d.ts +48 -0
  53. package/dist/render-cache.d.ts.map +1 -0
  54. package/dist/rls-context.d.ts +14 -0
  55. package/dist/rls-context.d.ts.map +1 -0
  56. package/dist/rls-readiness.d.ts +114 -0
  57. package/dist/rls-readiness.d.ts.map +1 -0
  58. package/dist/scoped.d.ts +104 -0
  59. package/dist/scoped.d.ts.map +1 -0
  60. package/dist/strict-args.d.ts +47 -0
  61. package/dist/strict-args.d.ts.map +1 -0
  62. package/dist/telemetry/collector.d.ts +53 -0
  63. package/dist/telemetry/collector.d.ts.map +1 -0
  64. package/dist/telemetry/config.d.ts +53 -0
  65. package/dist/telemetry/config.d.ts.map +1 -0
  66. package/dist/telemetry/fingerprint.d.ts +38 -0
  67. package/dist/telemetry/fingerprint.d.ts.map +1 -0
  68. package/dist/telemetry/index.d.ts +18 -0
  69. package/dist/telemetry/index.d.ts.map +1 -0
  70. package/dist/telemetry/recorder.d.ts +93 -0
  71. package/dist/telemetry/recorder.d.ts.map +1 -0
  72. package/dist/telemetry/statement.d.ts +53 -0
  73. package/dist/telemetry/statement.d.ts.map +1 -0
  74. package/dist/telemetry/types.d.ts +265 -0
  75. package/dist/telemetry/types.d.ts.map +1 -0
  76. package/dist/validators.d.ts +61 -0
  77. package/dist/validators.d.ts.map +1 -0
  78. package/dist/views.d.ts +97 -0
  79. package/dist/views.d.ts.map +1 -0
  80. package/dist/write-scope.d.ts +14 -0
  81. package/dist/write-scope.d.ts.map +1 -0
  82. package/package.json +33 -26
  83. package/src/adapter.ts +0 -146
  84. package/src/client.ts +0 -2172
  85. package/src/coerce.ts +0 -184
  86. package/src/count-loader.ts +0 -152
  87. package/src/errors.ts +0 -492
  88. package/src/id-generators.ts +0 -151
  89. package/src/index.ts +0 -55
  90. package/src/lateral-join-builder.ts +0 -1053
  91. package/src/query-builder.ts +0 -1832
  92. package/src/relation-loader.ts +0 -534
  93. package/src/retry.ts +0 -183
  94. package/src/types.ts +0 -317
  95. package/src/view.ts +0 -629
  96. package/src/where-builder.ts +0 -772
@@ -0,0 +1,271 @@
1
+ /**
2
+ * The query builder: `{ model, method, args }` → a SQL AST statement, purely.
3
+ *
4
+ * Nothing here touches a database, a clock-free input always produces the same
5
+ * statement, and every branch is reachable from the query catalog
6
+ * (`tests/query-catalog/`) — which pins the rendered SQL for all three dialects
7
+ * and exports it to the reviewable root `sql-catalog.md`.
8
+ *
9
+ * Division of labour:
10
+ * - shapes and SQL text live in @vibeorm/sql (this file never writes SQL),
11
+ * - value transport lives in codecs.ts (this file never coerces),
12
+ * - dialect gaps become VIBE_UNSUPPORTED_CAPABILITY here, at build time,
13
+ * which is the earliest knowable moment for a query-level feature,
14
+ * - bad input becomes VIBE_VALIDATION naming the model, field and operator.
15
+ */
16
+ import type { OrderByColumn, SqlDialect, SqlExpr, SqlStatement } from "@vibeorm/sql";
17
+ import type { KeysetOrderInput } from "./keyset.ts";
18
+ import type { ModelMeta, RuntimeMeta } from "./model-meta.ts";
19
+ import type { RelationSelection, RelationTreeNode } from "./relation-plan.ts";
20
+ /** Every ORM method the query builder builds SQL for. */
21
+ export type QueryMethod = "findMany" | "findFirst" | "findUnique" | "create" | "createMany" | "createManyAndReturn" | "update" | "updateMany" | "updateManyAndReturn" | "upsert" | "upsertMany" | "delete" | "deleteMany" | "count" | "aggregate" | "groupBy";
22
+ /** Client-level options that shape SQL (subset of ClientOptions the builder needs). */
23
+ export type BuilderClientOptions = {
24
+ /** Append the primary key to ORDER BY when no explicit orderBy was given (default false). */
25
+ readonly defaultOrderByPk?: boolean;
26
+ /** Append the primary key as a `distinct` tie-breaker for determinism (default true). */
27
+ readonly distinctOrderByPk?: boolean;
28
+ };
29
+ /** The five aggregate selector keys, in the deterministic order they project. */
30
+ export type AggregateKey = "_count" | "_avg" | "_sum" | "_min" | "_max";
31
+ /**
32
+ * One projected aggregate. `field: null` is `_all` (COUNT(*)). The alias is the
33
+ * deterministic `<key>__<selector>` scheme (`_count___all`, `_avg__score`) —
34
+ * results are read back by construction from these aliases, never parsed.
35
+ */
36
+ export type AggregateSelection = {
37
+ readonly key: AggregateKey;
38
+ readonly field: string | null;
39
+ readonly alias: string;
40
+ };
41
+ /** Everything the client needs to decode an aggregate/groupBy/count-select row. */
42
+ export type AggregateSpec = {
43
+ readonly selections: readonly AggregateSelection[];
44
+ /** `_count: true` — the result's `_count` is a bare number, not an object. */
45
+ readonly countShorthand: boolean;
46
+ };
47
+ /** How included relations are fetched. */
48
+ export type RelationStrategy = "query" | "join";
49
+ /**
50
+ * A built query plus everything the client needs after execution. The plan is
51
+ * data only: the client decides how to run it.
52
+ */
53
+ export type QueryPlan = {
54
+ readonly method: QueryMethod;
55
+ readonly model: ModelMeta;
56
+ readonly statement: SqlStatement;
57
+ /**
58
+ * Field names the statement projects, in order, or `null` when it projects
59
+ * every scalar field. Mutations RETURNING extra primary-key columns are
60
+ * narrowed back down to this list by the client.
61
+ */
62
+ readonly selectedFields: readonly string[] | null;
63
+ /**
64
+ * What the CALLER should see: the user's scalar select plus relation names
65
+ * and `_count`, or `null` for "all scalars (plus attached relations)".
66
+ * Differs from `selectedFields` when stitching keys were added to the SQL
67
+ * projection — the client narrows back down to this after relation loading.
68
+ */
69
+ readonly resultFields: readonly string[] | null;
70
+ /**
71
+ * Computed fields to attach to result rows (config-declared), resolved from
72
+ * select/omit — always a concrete name list, `null` when none apply. Their
73
+ * `needs` ride `selectedFields` like stitch keys and are narrowed away by
74
+ * `resultFields` unless selected themselves.
75
+ */
76
+ readonly computed: readonly string[] | null;
77
+ /** Relations to load after the base rows, or `null` when none were asked for. */
78
+ readonly relations: RelationSelection | null;
79
+ /**
80
+ * How relations load. With `"join"` on a find method the base statement IS
81
+ * the lateral statement (level-1 relations ride along as JSON columns);
82
+ * deeper levels always fall back to `"query"` batches (v1 semantics).
83
+ */
84
+ readonly relationStrategy: RelationStrategy;
85
+ /** True when `take` produced a LIMIT. */
86
+ readonly takeApplied: boolean;
87
+ /** Alias the COUNT(*) value is projected under (`count` only). */
88
+ readonly countAlias: string | null;
89
+ /**
90
+ * Unique WHERE identifying the affected row, for the re-select a dialect
91
+ * without RETURNING needs. `null` when the row cannot be identified before
92
+ * the write (an autoincrement key the database assigns).
93
+ */
94
+ readonly refetchWhere: Readonly<Record<string, unknown>> | null;
95
+ /**
96
+ * Upsert only: the unique where WITHOUT the update-arm overlay. The INSERT
97
+ * arm's row answers this key (its create row binds the conflict target — the
98
+ * B1 native-eligibility gate), so the mysql read-back tries the overlaid
99
+ * `refetchWhere` first, then this. `null` on every other method.
100
+ */
101
+ readonly refetchWhereBase: Readonly<Record<string, unknown>> | null;
102
+ /**
103
+ * createMany/createManyAndReturn only: when the call compiles to MORE than
104
+ * one statement (sqlite's heterogeneous column-set groups — M4 — or the M7
105
+ * parameter-budget chunks), every statement in order (`statement` is the
106
+ * first). The client executes them in ONE transaction, summing counts /
107
+ * concatenating returned rows. Absent for single-statement calls.
108
+ */
109
+ readonly batch?: readonly SqlStatement[];
110
+ /**
111
+ * upsertMany only (EPIC 10): the number of rows this plan submits, summed
112
+ * across chunks. It IS the operation's affected count under the one
113
+ * cross-dialect definition — every submitted row is inserted or updated —
114
+ * and it is computed here because the drivers do not agree: mysql's ON
115
+ * DUPLICATE KEY scores an insert 1, a changed update 2 and an unchanged
116
+ * update 0, so its number is not a row count at all.
117
+ */
118
+ readonly upsertRowCount?: number;
119
+ /** The caller's `select`, replayed on that re-select. */
120
+ readonly selectArg: Readonly<Record<string, unknown>> | null;
121
+ /** How to decode aggregate/groupBy/count-select rows; `null` elsewhere. */
122
+ readonly aggregateSpec: AggregateSpec | null;
123
+ /** groupBy's `by` field names, for row assembly; `null` elsewhere. */
124
+ readonly groupByFields: readonly string[] | null;
125
+ /** Negative `take`: the SQL ordering was flipped; re-reverse rows after fetch. */
126
+ readonly reverseRows: boolean;
127
+ /**
128
+ * `distinct` + an explicit user orderBy (N1, board #22): the arrangement
129
+ * DISTINCT ON needs demotes the user's order behind the distinct fields, so
130
+ * the client re-sorts the FINAL rows by these keys — Prisma's presentation
131
+ * order, on every dialect. `nulls` is resolved at build time to the
132
+ * dialect's own NULL placement so the re-sort mirrors what the SQL order
133
+ * would have produced. `null` when no re-sort is needed.
134
+ */
135
+ readonly resortBy: readonly ResortKey[] | null;
136
+ };
137
+ /** One client-side re-sort key (see QueryPlan.resortBy). */
138
+ export type ResortKey = {
139
+ readonly field: string;
140
+ readonly direction: "asc" | "desc";
141
+ readonly nulls: "first" | "last";
142
+ /** B4 mirror: Decimal ranks numerically — the SQL side ordered a number. */
143
+ readonly decimal: boolean;
144
+ };
145
+ /** Column alias for COUNT(*) — postgres and sqlite/mysql name it differently otherwise. */
146
+ export declare const COUNT_ALIAS: string;
147
+ /**
148
+ * Compile a Prisma-shaped where object; `undefined` when it constrains nothing.
149
+ *
150
+ * `qualify` table-qualifies every column reference (used inside lateral and
151
+ * EXISTS subqueries); `aliasSeq` threads the statement-wide subquery-alias
152
+ * counter so nested relation filters never collide.
153
+ */
154
+ export declare function compileWhere(params: {
155
+ dialect: SqlDialect;
156
+ meta: RuntimeMeta;
157
+ model: ModelMeta;
158
+ where: Record<string, unknown>;
159
+ qualify?: string;
160
+ aliasSeq?: {
161
+ n: number;
162
+ };
163
+ }): SqlExpr | undefined;
164
+ /** Compile `orderBy` (a single object or an array of them) into order terms. */
165
+ export declare function compileOrderBy(params: {
166
+ model: ModelMeta;
167
+ orderBy: unknown;
168
+ qualify?: string;
169
+ /** When given, B4's sqlite Decimal ordering cast applies (`CAST … AS REAL`). */
170
+ dialect?: SqlDialect;
171
+ }): OrderByColumn[];
172
+ /**
173
+ * Compile `select` into scalar field names, projecting EXACTLY what was asked
174
+ * — the primary key is not smuggled in. Relation keys and `_count` are the
175
+ * relation resolver's business (`relation-plan.ts`) and are skipped here;
176
+ * `allowEmpty` permits a select of ONLY relations (the stitching key is added
177
+ * separately and stripped from the result).
178
+ */
179
+ export declare function compileSelect(params: {
180
+ model: ModelMeta;
181
+ select: unknown;
182
+ allowEmpty?: boolean;
183
+ }): string[];
184
+ /**
185
+ * Whether `upsert({ where, create, update })` can ride ONE native
186
+ * `INSERT … ON CONFLICT`/`ON DUPLICATE KEY` statement — Prisma's own
187
+ * criterion: the create data must bind every conflict-target column with the
188
+ * SAME value the where names. Otherwise the conflict can never fire on the
189
+ * addressed row (postgres/sqlite would silently insert instead of update;
190
+ * mysql's ODKU could update an unrelated row — SQL review B1) and the client
191
+ * must run the transactional find-then-write fallback instead.
192
+ */
193
+ /**
194
+ * Whether `upsert({ where, create, update })` can ride ONE native
195
+ * `INSERT … ON CONFLICT`/`ON DUPLICATE KEY` statement — Prisma's own
196
+ * criterion, two halves:
197
+ * 1. the create data binds every conflict-target column with the SAME value
198
+ * the where names (otherwise the conflict can never fire on the
199
+ * addressed row — postgres/sqlite would silently insert instead of
200
+ * update; mysql's ODKU could update an unrelated row — SQL review B1);
201
+ * 2. the where carries NO fields beyond the conflict target (PG-2): a guard
202
+ * field (`where: { email, active: true }`) is invisible to ON CONFLICT —
203
+ * the update arm would fire even when the guard fails, where update()
204
+ * honors the same guard.
205
+ * Ineligible shapes run the client's transactional find-then-write fallback,
206
+ * whose probe honors the FULL where.
207
+ */
208
+ export declare function upsertUsesNativeStatement(params: {
209
+ model: ModelMeta;
210
+ args: Record<string, unknown>;
211
+ }): boolean;
212
+ /**
213
+ * Compile a raw `orderBy` argument into keyset order inputs — the ONE parsing
214
+ * path the iterator and the `after` bound share, so a token's signature can
215
+ * never drift from the ordering the statement carries.
216
+ */
217
+ export declare function compileKeysetOrderInputs(params: {
218
+ dialect: SqlDialect;
219
+ meta: RuntimeMeta;
220
+ model: ModelMeta;
221
+ orderBy: unknown;
222
+ }): KeysetOrderInput[];
223
+ /** The column a relation's JSON payload is exposed under in the outer row. */
224
+ export declare function lateralColumnAlias(params: {
225
+ relation: string;
226
+ }): string;
227
+ /**
228
+ * PG-3 (SQL review round 2): order fields the lateral subselect must project
229
+ * HIDDEN — the aggregate's explicit `ORDER BY "__sub".…` (N2) can only
230
+ * reference projected columns, and a per-relation orderBy on a field outside
231
+ * the child select otherwise left the aggregate relying on "usually preserves
232
+ * subquery order". The loader deletes these after parsing (the stitch-key
233
+ * pattern). Empty when the projection is full or no orderBy was given.
234
+ */
235
+ export declare function lateralHiddenOrderFields(params: {
236
+ node: RelationTreeNode;
237
+ }): string[];
238
+ /**
239
+ * The relation selection + caller-visible field list for one call, WITHOUT
240
+ * building a statement — the nested-write path orchestrates its own
241
+ * statements but still needs the validated result shape for relation loading
242
+ * and projection.
243
+ */
244
+ export declare function resolveResultShape(params: {
245
+ meta: RuntimeMeta;
246
+ model: ModelMeta;
247
+ method: QueryMethod;
248
+ args: Record<string, unknown>;
249
+ }): {
250
+ relations: RelationSelection | null;
251
+ resultFields: readonly string[] | null;
252
+ computed: readonly string[] | null;
253
+ };
254
+ /**
255
+ * Build the SQL plan for one ORM call. Pure: same inputs, same statement —
256
+ * except for app-generated defaults (uuid/cuid/nanoid/ulid/now), which are by
257
+ * definition fresh per call.
258
+ *
259
+ * `defaultRelationStrategy` is the client-level option; a per-query
260
+ * `relationStrategy` argument (find methods only) overrides it.
261
+ */
262
+ export declare function buildQuery(params: {
263
+ meta: RuntimeMeta;
264
+ dialect: SqlDialect;
265
+ model: string;
266
+ method: QueryMethod;
267
+ args?: Record<string, unknown>;
268
+ defaultRelationStrategy?: RelationStrategy;
269
+ clientOptions?: BuilderClientOptions;
270
+ }): QueryPlan;
271
+ //# sourceMappingURL=query-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-builder.d.ts","sourceRoot":"","sources":["../src/query-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /** Compare decoded relation keys by value, including DateTime milliseconds and binary bytes. */
2
+ export declare function relationValueKey(params: {
3
+ value: unknown;
4
+ }): unknown;
5
+ /**
6
+ * A collision-safe Map key for an ORDERED key tuple, or `null` when the tuple
7
+ * is INCOMPLETE (any member null/undefined) — an incomplete foreign key must
8
+ * never attach a parent, so it gets no key at all rather than a key that could
9
+ * collide with another incomplete tuple.
10
+ *
11
+ * The encoding is `JSON.stringify` over the per-member {@link relationValueKey}
12
+ * tags, NOT a separator join: JSON string escaping is injective, so a member
13
+ * containing the separator of a naive `a + "\u0000" + b` scheme (or `","`, or
14
+ * `"|"`) cannot forge another tuple's key.
15
+ *
16
+ * A member whose equality cannot be implemented faithfully — any object that is
17
+ * neither `Date` nor `Uint8Array`, where `String(value)` would be a lossy stand-in
18
+ * — is refused rather than silently mis-grouped.
19
+ */
20
+ export declare function relationTupleKey(params: {
21
+ values: readonly unknown[];
22
+ }): string | null;
23
+ //# sourceMappingURL=relation-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation-key.d.ts","sourceRoot":"","sources":["../src/relation-key.ts"],"names":[],"mappings":"AAEA,gGAAgG;AAChG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAqBpE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAgBtF"}
@@ -0,0 +1,46 @@
1
+ import type { SelectStatement, SqlDialect, WireFidelity } from "@vibeorm/sql";
2
+ import type { ModelMeta, RuntimeMeta } from "./model-meta.ts";
3
+ import type { RelationSelection } from "./relation-plan.ts";
4
+ /** A materialized row relations are stitched onto. */
5
+ export type LoadedRow = Record<string, unknown>;
6
+ /**
7
+ * Executes one SELECT and returns RAW driver rows — the loader decodes them
8
+ * itself (the child model's codecs, at every materialization point). The
9
+ * client provides this bound to its adapter + onQuery reporting.
10
+ */
11
+ export type RelationExecutor = (params: {
12
+ statement: SelectStatement;
13
+ model: string;
14
+ method: string;
15
+ }) => Promise<Record<string, unknown>[]>;
16
+ /**
17
+ * "query"-strategy loading: batched statements per relation, in declaration
18
+ * order, recursively. Mutates `rows` in place (relations become properties).
19
+ */
20
+ export declare function attachRelations(params: {
21
+ dialect: SqlDialect;
22
+ meta: RuntimeMeta;
23
+ model: ModelMeta;
24
+ rows: LoadedRow[];
25
+ selection: RelationSelection;
26
+ execute: RelationExecutor;
27
+ /** The executing adapter's wire declaration (board #30). */
28
+ wire?: WireFidelity;
29
+ }): Promise<void>;
30
+ /**
31
+ * "join"-strategy post-processing: parse each row's `__rel_<name>` JSON
32
+ * column, decode the children through the child model's codecs, stitch, then
33
+ * recurse deeper levels through the query strategy (v1 semantics) and load
34
+ * `_count` separately.
35
+ */
36
+ export declare function attachLateralRelations(params: {
37
+ dialect: SqlDialect;
38
+ meta: RuntimeMeta;
39
+ model: ModelMeta;
40
+ rows: LoadedRow[];
41
+ selection: RelationSelection;
42
+ execute: RelationExecutor;
43
+ /** The executing adapter's wire declaration (board #30 — deeper levels recurse through the query strategy). */
44
+ wire?: WireFidelity;
45
+ }): Promise<void>;
46
+ //# sourceMappingURL=relation-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation-loader.d.ts","sourceRoot":"","sources":["../src/relation-loader.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAU,eAAe,EAAE,UAAU,EAAW,YAAY,EAAE,MAAM,cAAc,CAAC;AAG/F,OAAO,KAAK,EAAa,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGzE,OAAO,KAAK,EAAmC,iBAAiB,EAAoB,MAAM,oBAAoB,CAAC;AAI/G,sDAAsD;AACtD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEhD;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE;IACtC,SAAS,EAAE,eAAe,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;AA6wBzC;;;GAGG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,OAAO,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,4DAA4D;IAC5D,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,EAAE;IACnD,OAAO,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,+GAA+G;IAC/G,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4DhB"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Relation RESOLUTION: `select`/`include` args → a validated relation tree,
3
+ * plus the structural link (FK fields, join table) each relation loads through.
4
+ *
5
+ * Pure structure — no SQL, no execution. The query builder consumes this to
6
+ * gate strategies and augment projections at build time (the earliest knowable
7
+ * moment); the relation loader consumes it to run and stitch.
8
+ *
9
+ * v1 semantics carried:
10
+ * - `select: { rel: … }` and `include: { rel: … }` both load; `include` wins
11
+ * when both name the same relation.
12
+ * - `_count` uses the v1 shape: `include._count: true | { select: { rel: true } }`
13
+ * (or under `select`) and counts LIST relations only. A count entry may also
14
+ * be `{ where: … }` (EPIC 4): the filter is carried on the resolved node and
15
+ * compiled by the loader through the ordinary where compiler.
16
+ * - Implicit many-to-many resolves through the ONE shared join-table rule
17
+ * (`implicitJoinTable` in @vibeorm/schema) — never re-derived here.
18
+ */
19
+ import type { RelationIR } from "@vibeorm/schema";
20
+ import type { FieldMeta, ModelMeta, RuntimeMeta } from "./model-meta.ts";
21
+ /** How a relation is physically wired. */
22
+ export type RelationKind =
23
+ /** Children hold the FK (`oneToMany`) — batch `WHERE fk IN (parents)`. */
24
+ "toManyFk"
25
+ /** THIS model holds the FK (`manyToOne` / owning `oneToOne`). */
26
+ | "toOneOwner"
27
+ /** The other side holds the FK (non-owning `oneToOne`). */
28
+ | "toOneInverse"
29
+ /** Implicit join table (`manyToMany`). */
30
+ | "manyToMany";
31
+ /** The resolved physical link for one relation. */
32
+ export type RelationLink = {
33
+ readonly kind: RelationKind;
34
+ readonly relation: RelationIR;
35
+ readonly target: ModelMeta;
36
+ /**
37
+ * ORDERED parent-side correlation fields — index `i` pairs with
38
+ * `childKeys[i]`. A composite foreign key carries every column here; there is
39
+ * deliberately no singular accessor, so no call site can truncate a tuple to
40
+ * its first member.
41
+ */
42
+ readonly parentKeys: readonly FieldMeta[];
43
+ /** ORDERED child-side correlation fields, positionally paired with {@link parentKeys}. */
44
+ readonly childKeys: readonly FieldMeta[];
45
+ /** Join-table wiring; `null` unless kind is `manyToMany`. */
46
+ readonly join: {
47
+ readonly tableName: string;
48
+ readonly parentColumn: "A" | "B";
49
+ readonly childColumn: "A" | "B";
50
+ } | null;
51
+ };
52
+ /** Nested args for one relation to load, validated. */
53
+ export type RelationArgs = {
54
+ readonly where: Record<string, unknown> | undefined;
55
+ readonly orderBy: unknown;
56
+ readonly take: number | undefined;
57
+ readonly skip: number | undefined;
58
+ /** Child scalar fields the CALLER asked for, or `null` for all scalars. */
59
+ readonly select: readonly string[] | null;
60
+ /** SQL projection: `select` plus stitching keys — what the child statement fetches. */
61
+ readonly projected: readonly string[] | null;
62
+ /** Fields in `projected` the caller did NOT ask for — deleted after stitching. */
63
+ readonly strip: readonly string[];
64
+ /** Computed fields to attach to loaded children, or `null` — resolved like the top level. */
65
+ readonly computed: readonly string[] | null;
66
+ /** Deeper relation levels under this one. */
67
+ readonly nested: RelationSelection | null;
68
+ };
69
+ export type RelationTreeNode = {
70
+ /** Relation field name on the parent (`posts`). */
71
+ readonly name: string;
72
+ readonly link: RelationLink;
73
+ readonly args: RelationArgs;
74
+ };
75
+ /**
76
+ * One relation counted into `_count`, with the filter that narrows it.
77
+ *
78
+ * The link is resolved HERE, once, so no later consumer has to re-derive a
79
+ * relation's ordered key tuples just to count through them.
80
+ */
81
+ export type RelationCountNode = {
82
+ /** List-relation field name on the parent (`posts`). */
83
+ readonly name: string;
84
+ /** Structural link the count correlates and groups on. */
85
+ readonly link: RelationLink;
86
+ /**
87
+ * Validated `where` narrowing the counted children, or `undefined` for
88
+ * "count every child". The loader compiles it with `compileWhere` — the same
89
+ * centralized compiler and codecs an ordinary query where goes through.
90
+ */
91
+ readonly where: Record<string, unknown> | undefined;
92
+ };
93
+ /** Everything relation-shaped one query level asked for. */
94
+ export type RelationSelection = {
95
+ readonly relations: readonly RelationTreeNode[];
96
+ /** List relations to count into `_count`, each with its own filter. */
97
+ readonly counts: readonly RelationCountNode[];
98
+ };
99
+ /**
100
+ * The ONE correlation pair of an arity-1 link, for the paths that are single-key
101
+ * by construction (implicit many-to-many, whose join table has one column per
102
+ * side). Refuses a composite link with a typed capability error BEFORE any
103
+ * statement runs — never truncates.
104
+ */
105
+ export declare function singleKeyPair(params: {
106
+ link: RelationLink;
107
+ what: string;
108
+ }): {
109
+ readonly parent: FieldMeta;
110
+ readonly child: FieldMeta;
111
+ };
112
+ /** Resolve how one relation is physically wired. */
113
+ export declare function resolveRelationLink(params: {
114
+ meta: RuntimeMeta;
115
+ model: ModelMeta;
116
+ relation: RelationIR;
117
+ }): RelationLink;
118
+ /**
119
+ * The parent-side fields a selection needs for stitching: each relation's
120
+ * `parentKey`, and each counted relation's `parentKey`.
121
+ */
122
+ export declare function requiredParentFields(params: {
123
+ meta: RuntimeMeta;
124
+ model: ModelMeta;
125
+ selection: RelationSelection;
126
+ }): string[];
127
+ /**
128
+ * Resolve everything relation-shaped in one level's `select`/`include`.
129
+ * Returns `null` when neither names a relation or `_count`.
130
+ *
131
+ * Scalar keys in `select` are ignored here (the query builder projects them);
132
+ * every key in `include` must be a relation or `_count` — anything else is a
133
+ * loud validation error.
134
+ */
135
+ export declare function resolveRelationSelection(params: {
136
+ meta: RuntimeMeta;
137
+ model: ModelMeta;
138
+ select: unknown;
139
+ include: unknown;
140
+ }): RelationSelection | null;
141
+ //# sourceMappingURL=relation-plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation-plan.d.ts","sourceRoot":"","sources":["../src/relation-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAIzE,0CAA0C;AAC1C,MAAM,MAAM,YAAY;AACtB,0EAA0E;AACxE,UAAU;AACZ,iEAAiE;GAC/D,YAAY;AACd,2DAA2D;GACzD,cAAc;AAChB,0CAA0C;GACxC,YAAY,CAAC;AAEjB,mDAAmD;AACnD,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,0FAA0F;IAC1F,QAAQ,CAAC,SAAS,EAAE,SAAS,SAAS,EAAE,CAAC;IACzC,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE;QACb,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,YAAY,EAAE,GAAG,GAAG,GAAG,CAAC;QACjC,QAAQ,CAAC,WAAW,EAAE,GAAG,GAAG,GAAG,CAAC;KACjC,GAAG,IAAI,CAAC;CACV,CAAC;AAEF,uDAAuD;AACvD,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAC1C,uFAAuF;IACvF,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAC7C,kFAAkF;IAClF,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,6FAA6F;IAC7F,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5C,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CACrD,CAAC;AAEF,4DAA4D;AAC5D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAChD,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAC/C,CAAC;AAoEF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,CAU5D;AAsBD,oDAAoD;AACpD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,UAAU,CAAC;CACtB,GAAG,YAAY,CAYf;AA8ND;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,iBAAiB,CAAC;CAC9B,GAAG,MAAM,EAAE,CAUX;AAiND;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE;IAC/C,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB,GAAG,iBAAiB,GAAG,IAAI,CAsD3B"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The compiled-query cache — §9's "query-shape cache (structural hash → SQL
3
+ * skeleton)", constitution rule 8 (perf) under rule 3's constraint: the SQL
4
+ * text is ALWAYS the renderer's, byte-identical — this module never builds SQL.
5
+ *
6
+ * How it works: a statement AST is walked ONCE, producing (a) a structural key
7
+ * covering everything that affects the rendered text — kinds, identifiers,
8
+ * operators, flags, literal LIMIT/OFFSET, arity where a dialect expands
9
+ * placeholders per element — and (b) the parameter values in exactly the
10
+ * renderer's collection order. A key hit reuses the cached text with the fresh
11
+ * values; a miss renders for real and caches the text.
12
+ *
13
+ * SAFETY: the walk mirrors @vibeorm/sql's render traversal. Two guards keep a
14
+ * divergence from ever mis-binding parameters:
15
+ * 1. every MISS cross-checks the walked values against the renderer's
16
+ * collected values (element-wise); a mismatch poisons the key so that
17
+ * shape renders uncached forever, and
18
+ * 2. constructs with dialect-conditional value branching that is not worth
19
+ * mirroring (jsonFilter) are declared uncacheable outright.
20
+ * The cache is invalidation-free by construction: the key IS the shape, and
21
+ * equal shapes render equal text (shape-purity). Statement ASTs are treated as
22
+ * immutable by the whole runtime, so cached texts can never go stale.
23
+ */
24
+ import type { RenderedQuery, SqlDialect, SqlStatement } from "@vibeorm/sql";
25
+ type CachedText = {
26
+ readonly text: string;
27
+ readonly returning: "native" | "omitted" | "none";
28
+ };
29
+ /** `null` = poisoned: this shape verified unsafe once — never cache it. */
30
+ type CacheSlot = CachedText | null;
31
+ /** One per client (dialect-stable); shared across its transaction clients. */
32
+ export declare class StatementRenderCache {
33
+ private readonly entries;
34
+ get(key: string): CacheSlot | undefined;
35
+ set(key: string, slot: CacheSlot): void;
36
+ }
37
+ /**
38
+ * Render through the shape cache: hit = cached text + freshly walked values;
39
+ * miss = real render, cross-checked against the walk before caching. Anything
40
+ * uncacheable (or a verification failure — poisoned) renders directly.
41
+ */
42
+ export declare function renderStatementCached(params: {
43
+ dialect: SqlDialect;
44
+ statement: SqlStatement;
45
+ cache: StatementRenderCache;
46
+ }): RenderedQuery;
47
+ export {};
48
+ //# sourceMappingURL=render-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-cache.d.ts","sourceRoot":"","sources":["../src/render-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAWH,OAAO,KAAK,EAMV,aAAa,EAEb,UAAU,EAEV,YAAY,EAGb,MAAM,cAAc,CAAC;AAItB,KAAK,UAAU,GAAG;IAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;CACnD,CAAC;AAEF,2EAA2E;AAC3E,KAAK,SAAS,GAAG,UAAU,GAAG,IAAI,CAAC;AAInC,8EAA8E;AAC9E,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAE7D,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEtC;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAKtC;CACF;AA0fD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,OAAO,EAAE,UAAU,CAAC;IACpB,SAAS,EAAE,YAAY,CAAC;IACxB,KAAK,EAAE,oBAAoB,CAAC;CAC7B,GAAG,aAAa,CAoBhB"}
@@ -0,0 +1,14 @@
1
+ import type { SchemaIR } from "@vibeorm/schema";
2
+ import type { SqlDialect } from "@vibeorm/sql";
3
+ /** Private, copied identity and its total transaction-settings transport. */
4
+ export type BoundRlsContext = {
5
+ readonly values: Readonly<Record<string, unknown>>;
6
+ readonly settings: Readonly<Record<string, string | null>>;
7
+ };
8
+ /** Validate before serialization; missing nullable slots are still missing keys. */
9
+ export declare function bindRlsContext(params: {
10
+ schema: SchemaIR;
11
+ dialect: SqlDialect;
12
+ context: unknown;
13
+ }): BoundRlsContext;
14
+ //# sourceMappingURL=rls-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rls-context.d.ts","sourceRoot":"","sources":["../src/rls-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,6EAA6E;AAC7E,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;CAC5D,CAAC;AA0BF,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,eAAe,CA6CnH"}