@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.
- package/README.md +50 -107
- package/dist/adapter.d.ts +250 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/bulk-upsert.d.ts +282 -0
- package/dist/bulk-upsert.d.ts.map +1 -0
- package/dist/client.d.ts +200 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/codecs.d.ts +170 -0
- package/dist/codecs.d.ts.map +1 -0
- package/dist/computed.d.ts +43 -0
- package/dist/computed.d.ts.map +1 -0
- package/dist/db-now.d.ts +41 -0
- package/dist/db-now.d.ts.map +1 -0
- package/dist/diagnostics/index.d.ts +12 -0
- package/dist/diagnostics/index.d.ts.map +1 -0
- package/dist/diagnostics/insight.d.ts +63 -0
- package/dist/diagnostics/insight.d.ts.map +1 -0
- package/dist/diagnostics/plan.d.ts +88 -0
- package/dist/diagnostics/plan.d.ts.map +1 -0
- package/dist/diagnostics/preview.d.ts +43 -0
- package/dist/diagnostics/preview.d.ts.map +1 -0
- package/dist/diagnostics/types.d.ts +223 -0
- package/dist/diagnostics/types.d.ts.map +1 -0
- package/dist/diagnostics/workload.d.ts +32 -0
- package/dist/diagnostics/workload.d.ts.map +1 -0
- package/dist/extensions.d.ts +102 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13070 -0
- package/dist/index.js.map +43 -0
- package/dist/keyset-iterator.d.ts +73 -0
- package/dist/keyset-iterator.d.ts.map +1 -0
- package/dist/keyset.d.ts +121 -0
- package/dist/keyset.d.ts.map +1 -0
- package/dist/model-meta.d.ts +200 -0
- package/dist/model-meta.d.ts.map +1 -0
- package/dist/nested-writes.d.ts +67 -0
- package/dist/nested-writes.d.ts.map +1 -0
- package/dist/policy-operation.d.ts +14 -0
- package/dist/policy-operation.d.ts.map +1 -0
- package/dist/policy.d.ts +17 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/query-builder.d.ts +271 -0
- package/dist/query-builder.d.ts.map +1 -0
- package/dist/relation-key.d.ts +23 -0
- package/dist/relation-key.d.ts.map +1 -0
- package/dist/relation-loader.d.ts +46 -0
- package/dist/relation-loader.d.ts.map +1 -0
- package/dist/relation-plan.d.ts +141 -0
- package/dist/relation-plan.d.ts.map +1 -0
- package/dist/render-cache.d.ts +48 -0
- package/dist/render-cache.d.ts.map +1 -0
- package/dist/rls-context.d.ts +14 -0
- package/dist/rls-context.d.ts.map +1 -0
- package/dist/rls-readiness.d.ts +114 -0
- package/dist/rls-readiness.d.ts.map +1 -0
- package/dist/scoped.d.ts +104 -0
- package/dist/scoped.d.ts.map +1 -0
- package/dist/strict-args.d.ts +47 -0
- package/dist/strict-args.d.ts.map +1 -0
- package/dist/telemetry/collector.d.ts +53 -0
- package/dist/telemetry/collector.d.ts.map +1 -0
- package/dist/telemetry/config.d.ts +53 -0
- package/dist/telemetry/config.d.ts.map +1 -0
- package/dist/telemetry/fingerprint.d.ts +38 -0
- package/dist/telemetry/fingerprint.d.ts.map +1 -0
- package/dist/telemetry/index.d.ts +18 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/recorder.d.ts +93 -0
- package/dist/telemetry/recorder.d.ts.map +1 -0
- package/dist/telemetry/statement.d.ts +53 -0
- package/dist/telemetry/statement.d.ts.map +1 -0
- package/dist/telemetry/types.d.ts +265 -0
- package/dist/telemetry/types.d.ts.map +1 -0
- package/dist/validators.d.ts +61 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/views.d.ts +97 -0
- package/dist/views.d.ts.map +1 -0
- package/dist/write-scope.d.ts +14 -0
- package/dist/write-scope.d.ts.map +1 -0
- package/package.json +33 -26
- package/src/adapter.ts +0 -146
- package/src/client.ts +0 -2172
- package/src/coerce.ts +0 -184
- package/src/count-loader.ts +0 -152
- package/src/errors.ts +0 -492
- package/src/id-generators.ts +0 -151
- package/src/index.ts +0 -55
- package/src/lateral-join-builder.ts +0 -1053
- package/src/query-builder.ts +0 -1832
- package/src/relation-loader.ts +0 -534
- package/src/retry.ts +0 -183
- package/src/types.ts +0 -317
- package/src/view.ts +0 -629
- 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":"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"}
|
|
@@ -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"}
|