turbine-orm 0.34.0 → 0.36.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/README.md +18 -16
- package/dist/cjs/cli/index.js +109 -16
- package/dist/cjs/cli/migrate.js +78 -3
- package/dist/cjs/cli/studio-ui.generated.js +1 -1
- package/dist/cjs/cli/studio.js +333 -22
- package/dist/cjs/cli/ui.js +7 -1
- package/dist/cjs/client.js +26 -4
- package/dist/cjs/dialect.js +2 -1
- package/dist/cjs/errors.js +41 -1
- package/dist/cjs/generate.js +23 -2
- package/dist/cjs/index.js +4 -2
- package/dist/cjs/mssql.js +27 -5
- package/dist/cjs/mysql.js +4 -0
- package/dist/cjs/powdb.js +197 -25
- package/dist/cjs/powql.js +515 -51
- package/dist/cjs/query/aggregates.js +683 -0
- package/dist/cjs/query/batched-loader.js +2 -0
- package/dist/cjs/query/builder.js +361 -4508
- package/dist/cjs/query/filters.js +12 -0
- package/dist/cjs/query/relations.js +1698 -0
- package/dist/cjs/query/where-compile.js +180 -0
- package/dist/cjs/query/where.js +1491 -0
- package/dist/cjs/query/writes.js +680 -0
- package/dist/cjs/schema-builder.js +6 -0
- package/dist/cjs/schema-metadata.js +4 -0
- package/dist/cjs/schema-sql.js +265 -3
- package/dist/cjs/sqlite.js +4 -1
- package/dist/cli/index.d.ts +8 -2
- package/dist/cli/index.js +111 -18
- package/dist/cli/migrate.d.ts +24 -1
- package/dist/cli/migrate.js +77 -3
- package/dist/cli/studio-ui.generated.js +1 -1
- package/dist/cli/studio.d.ts +46 -13
- package/dist/cli/studio.js +331 -23
- package/dist/cli/ui.js +7 -1
- package/dist/client.d.ts +32 -5
- package/dist/client.js +26 -4
- package/dist/dialect.d.ts +28 -6
- package/dist/dialect.js +2 -1
- package/dist/errors.d.ts +36 -0
- package/dist/errors.js +39 -0
- package/dist/generate.js +23 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/mssql.js +27 -5
- package/dist/mysql.js +4 -0
- package/dist/powdb.d.ts +135 -9
- package/dist/powdb.js +197 -25
- package/dist/powql.d.ts +166 -4
- package/dist/powql.js +516 -52
- package/dist/query/aggregates.d.ts +74 -0
- package/dist/query/aggregates.js +641 -0
- package/dist/query/batched-loader.d.ts +6 -0
- package/dist/query/batched-loader.js +2 -0
- package/dist/query/builder.d.ts +98 -830
- package/dist/query/builder.js +366 -4513
- package/dist/query/deferred.d.ts +13 -2
- package/dist/query/filters.d.ts +7 -0
- package/dist/query/filters.js +11 -0
- package/dist/query/relations.d.ts +441 -0
- package/dist/query/relations.js +1627 -0
- package/dist/query/types.d.ts +25 -6
- package/dist/query/where-compile.d.ts +139 -0
- package/dist/query/where-compile.js +175 -0
- package/dist/query/where.d.ts +494 -0
- package/dist/query/where.js +1431 -0
- package/dist/query/writes.d.ts +131 -0
- package/dist/query/writes.js +626 -0
- package/dist/schema-builder.d.ts +18 -3
- package/dist/schema-builder.js +6 -0
- package/dist/schema-metadata.js +4 -0
- package/dist/schema-sql.d.ts +60 -3
- package/dist/schema-sql.js +261 -4
- package/dist/schema.d.ts +10 -0
- package/dist/sqlite.js +4 -1
- package/package.json +4 -4
package/dist/powql.d.ts
CHANGED
|
@@ -57,8 +57,16 @@ export declare class PowqlInterface<T extends object = Record<string, unknown>>
|
|
|
57
57
|
constructor(pool: PowdbPool, table: string, schema: SchemaMetadata, middlewares?: MiddlewareFn[], options?: QueryInterfaceOptions);
|
|
58
58
|
/** Resolve a camelCase field name (or raw snake) to its column metadata. */
|
|
59
59
|
private column;
|
|
60
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* PowQL column reference for a field. Unqualified it is a dotted field
|
|
62
|
+
* reference (`.snake_name`), which bypasses keyword lookup. When an `alias`
|
|
63
|
+
* is supplied (the F2 join path) it is qualified (`alias.snake_name`) and the
|
|
64
|
+
* column name is backtick-quoted if it is a reserved word (a qualified
|
|
65
|
+
* `p.order` does NOT bypass keyword lookup, unlike the dotted `.order`).
|
|
66
|
+
*/
|
|
61
67
|
private ref;
|
|
68
|
+
/** Render a raw column name as a PowQL reference, qualified with `alias` when given. */
|
|
69
|
+
private colRefName;
|
|
62
70
|
/**
|
|
63
71
|
* Push a value into the param array and return its `$N` placeholder. When the
|
|
64
72
|
* value targets a `float` column it is wrapped in {@link PowdbFloatParam} so
|
|
@@ -92,6 +100,13 @@ export declare class PowqlInterface<T extends object = Record<string, unknown>>
|
|
|
92
100
|
/**
|
|
93
101
|
* Compile a {@link WhereClause} into a PowQL filter expression, pushing every
|
|
94
102
|
* value as a positional `$N` param. Returns `''` when there are no conditions.
|
|
103
|
+
*
|
|
104
|
+
* When `alias` is supplied (the F2 native-join path) every field reference is
|
|
105
|
+
* qualified with it (`.col` → `alias.col`, JSON path bases too); params bind
|
|
106
|
+
* exactly as in the unqualified path. The caller only ever passes an alias for
|
|
107
|
+
* an already-RESOLVED where (relation filters pre-resolved to literal in-lists
|
|
108
|
+
* by {@link resolveRelationFilters}): the relation-key branch below still
|
|
109
|
+
* throws, so an unresolved relation filter can never leak into a join.
|
|
95
110
|
*/
|
|
96
111
|
private buildWhere;
|
|
97
112
|
/** Build a single `field: value | operator` condition. */
|
|
@@ -160,8 +175,40 @@ export declare class PowqlInterface<T extends object = Record<string, unknown>>
|
|
|
160
175
|
private resolveRelationCondition;
|
|
161
176
|
/** Resolve a manyToMany filter through the junction to `{ sourceRefField: { in|notIn: [...] } }`. */
|
|
162
177
|
private resolveManyToManyCondition;
|
|
163
|
-
/**
|
|
178
|
+
/**
|
|
179
|
+
* Resolve the set of columns to project, honouring `select` / `omit` and the
|
|
180
|
+
* query-level `includePii` opt-in. PII-tagged (`defineSchema` `pii: true`)
|
|
181
|
+
* columns are EXCLUDED from a default (or omit-only) projection unless
|
|
182
|
+
* `includePii` is true; an explicit `select` naming a PII column IS the opt-in
|
|
183
|
+
* and returns it regardless. Untagged tables project exactly as before.
|
|
184
|
+
*/
|
|
164
185
|
private projectedColumns;
|
|
186
|
+
/**
|
|
187
|
+
* The snake_case names of this table's PII-tagged columns. Empty for a table
|
|
188
|
+
* with no `pii: true` column, so untagged tables keep their prior projection.
|
|
189
|
+
*/
|
|
190
|
+
private piiColumnNames;
|
|
191
|
+
/**
|
|
192
|
+
* The camelCase field names of this table's PII-tagged columns: the read
|
|
193
|
+
* policy applied to a write's returned row (create/update/upsert/delete accept
|
|
194
|
+
* no `includePii`/`select`, so their result always drops PII; you may still
|
|
195
|
+
* write PII fields freely).
|
|
196
|
+
*
|
|
197
|
+
* SPEC LIMITATION (PowQL): the driver contract
|
|
198
|
+
* (`docs/integrations/powql-for-drivers.md`) exposes `returning` only as a
|
|
199
|
+
* bare keyword that hands back every column; it accepts NO column list, so
|
|
200
|
+
* (unlike the SQL engines, which emit an explicit non-PII `RETURNING`/`OUTPUT`
|
|
201
|
+
* projection) the create/update/delete `returning` paths cannot exclude PII at
|
|
202
|
+
* the query-language level and must strip it here after the fact. This is the
|
|
203
|
+
* client-side strip of last resort, not defense-in-depth, for those paths; we
|
|
204
|
+
* do NOT reverse-engineer an undocumented projection form. The upsert path is
|
|
205
|
+
* different: it has no `returning` and reselects by PK through the read
|
|
206
|
+
* projection ({@link projectedColumns}), which already omits PII, so PII never
|
|
207
|
+
* crosses the wire there. If a future spec revision lets `returning` take a
|
|
208
|
+
* projection, switch the write paths to emit the non-PII list and this strip
|
|
209
|
+
* becomes a no-op like {@link parseWriteRow} on the SQL engines.
|
|
210
|
+
*/
|
|
211
|
+
private stripWritePii;
|
|
165
212
|
/** `{ .c1, .c2, … }` projection clause. */
|
|
166
213
|
private projection;
|
|
167
214
|
/**
|
|
@@ -189,6 +236,8 @@ export declare class PowqlInterface<T extends object = Record<string, unknown>>
|
|
|
189
236
|
* read. Read statements pass a read-shaped action from {@link POWQL_READ_ACTIONS}.
|
|
190
237
|
*/
|
|
191
238
|
private exec;
|
|
239
|
+
/** Build the E018 refusal for a write / `begin` on a read-only pool. */
|
|
240
|
+
private readOnlyError;
|
|
192
241
|
/**
|
|
193
242
|
* Execute one statement, with the opt-in single stale-frame READ replay. When
|
|
194
243
|
* `retryStaleReads` is on and a first-statement READ fails with the stale-wire
|
|
@@ -217,13 +266,44 @@ export declare class PowqlInterface<T extends object = Record<string, unknown>>
|
|
|
217
266
|
* rare caller with no per-result flag (hand-built test pools). */
|
|
218
267
|
private shape;
|
|
219
268
|
findMany(args?: FindManyArgs<T>): Promise<T[]>;
|
|
220
|
-
/**
|
|
269
|
+
/**
|
|
270
|
+
* Compile the flat findMany select into PowQL (no execution), pushing values
|
|
271
|
+
* into `params`. Returns the query plus the RESOLVED where (relation filters
|
|
272
|
+
* already collapsed to literal in-lists) so the F2 join path can re-emit the
|
|
273
|
+
* exact parent predicate alias-qualified, and so {@link explain} can wrap it.
|
|
274
|
+
*/
|
|
275
|
+
private buildFind;
|
|
276
|
+
/** Build + run the flat findMany select; returns raw rows, the serving wire, and the resolved where. */
|
|
221
277
|
private runFind;
|
|
278
|
+
/**
|
|
279
|
+
* Diagnostic surface: compile the same PowQL {@link findMany} would run for
|
|
280
|
+
* `args` (no cache) and return the engine's plan as one string per line.
|
|
281
|
+
*
|
|
282
|
+
* Runs as a READ (`explain <query>`), so it is safe on a read-only pool and
|
|
283
|
+
* eligible for the stale-read replay. The line content is engine-owned and is
|
|
284
|
+
* NOT covered by semver (match plan node names / tree shape, never exact
|
|
285
|
+
* bytes; mirrors PowDB's own `explain` contract).
|
|
286
|
+
*
|
|
287
|
+
* Does NOT run through the middleware chain: plan text is a diagnostic, not
|
|
288
|
+
* entity rows, and `QueryInterface.explain` deliberately bypasses middleware
|
|
289
|
+
* too, so both engines agree.
|
|
290
|
+
*/
|
|
291
|
+
explain(args?: FindManyArgs<T>): Promise<string[]>;
|
|
222
292
|
findUnique(args: FindUniqueArgs<T>): Promise<T | null>;
|
|
223
293
|
findFirst(args?: FindManyArgs<T>): Promise<T | null>;
|
|
224
294
|
findUniqueOrThrow(args: FindUniqueArgs<T>): Promise<T>;
|
|
225
295
|
findFirstOrThrow(args?: FindManyArgs<T>): Promise<T>;
|
|
226
|
-
/**
|
|
296
|
+
/**
|
|
297
|
+
* Load each requested relation for `parents` and attach it onto each row.
|
|
298
|
+
*
|
|
299
|
+
* `parent` is supplied ONLY by the top-level {@link findMany} (its args +
|
|
300
|
+
* resolved where). When the effective `relationLoadStrategy` resolves to an
|
|
301
|
+
* explicit `'join'` and the pool advertises `serverJoins`, an eligible
|
|
302
|
+
* top-level relation is loaded with a native PowQL join instead of the keyed
|
|
303
|
+
* loaders (F2); everything else (nested `with` levels, ineligible shapes, and
|
|
304
|
+
* the default `'batched'` strategy) keeps the loaders. Output is byte-equal
|
|
305
|
+
* either way (the join reuses the same stitch / shape helpers).
|
|
306
|
+
*/
|
|
227
307
|
private loadRelations;
|
|
228
308
|
/**
|
|
229
309
|
* manyToMany nested read — a three-hop batched loader (no `json_agg`/join
|
|
@@ -234,6 +314,88 @@ export declare class PowqlInterface<T extends object = Record<string, unknown>>
|
|
|
234
314
|
* (composite junction keys would need PowQL tuple-`in`, which it lacks).
|
|
235
315
|
*/
|
|
236
316
|
private loadManyToMany;
|
|
317
|
+
/**
|
|
318
|
+
* Resolve the effective relation-load strategy: the per-query arg wins, then
|
|
319
|
+
* the client config, then the PowDB default of `'batched'` (the keyed
|
|
320
|
+
* loaders). PowDB deliberately does NOT inherit the SQL-side implicit `'join'`
|
|
321
|
+
* default (that would silently flip every existing PowDB user onto brand-new
|
|
322
|
+
* join generation). Only a value the user actually set to `'join'` activates it.
|
|
323
|
+
*/
|
|
324
|
+
private resolveStrategy;
|
|
325
|
+
/**
|
|
326
|
+
* Per-relation eligibility for the join path (checked before the serverJoins
|
|
327
|
+
* capability). Any `false` here is a SILENT fallback to the keyed loaders (it
|
|
328
|
+
* is never an error), so an off-page or nested-`with` shape still returns
|
|
329
|
+
* correct rows:
|
|
330
|
+
* - the parent query must not be paged (`limit`/`offset`/`take`, including the
|
|
331
|
+
* configured `defaultLimit`): a parent-filter join under a page would scan
|
|
332
|
+
* children of off-page parents, where the loaders are strictly better;
|
|
333
|
+
* - the relation must not request a nested `with` (its subtree stays on the
|
|
334
|
+
* loaders this round) or a `distinct`;
|
|
335
|
+
* - single-column relation keys only (a composite key falls to the loader,
|
|
336
|
+
* which throws the same E017 as today);
|
|
337
|
+
* - the PARENT-SIDE correlation column must be a single-column PK or unique
|
|
338
|
+
* column, or the INNER join would re-emit one child copy per matching
|
|
339
|
+
* parent row (a non-unique correlation key produces duplicate children the
|
|
340
|
+
* loader never would). For hasMany/hasOne/m2m that column is the relation's
|
|
341
|
+
* `referenceKey` on THIS (fetched) table; for belongsTo it is the
|
|
342
|
+
* `referenceKey` on the TARGET table (the join's non-fetched side);
|
|
343
|
+
* - m2m keeps any `orderBy`/`limit`/`offset` on the loader (the junction-order
|
|
344
|
+
* stitch can't be reproduced by the 3-table join deterministically);
|
|
345
|
+
* - a to-one relation `limit`/`offset` (meaningless) stays on the loader, as
|
|
346
|
+
* does a to-many relation `limit`/`offset` when the parent set spills past
|
|
347
|
+
* one loader chunk (the loader limits per chunk, the join once globally).
|
|
348
|
+
*/
|
|
349
|
+
private joinEligible;
|
|
350
|
+
/**
|
|
351
|
+
* True when `col` is a single-column unique key of `tableMeta`: the sole
|
|
352
|
+
* primary-key column, a single-column entry in `uniqueColumns` (where a
|
|
353
|
+
* per-column `unique: true` and an introspected single-column unique constraint
|
|
354
|
+
* both land), or a single-column unique index. Used by {@link joinEligible} to
|
|
355
|
+
* keep the INNER-join path off relations whose parent-side correlation column
|
|
356
|
+
* can repeat (which would duplicate children).
|
|
357
|
+
*/
|
|
358
|
+
private isSingleColumnUnique;
|
|
359
|
+
/** Dispatch one eligible relation to the correct native-join loader. */
|
|
360
|
+
private loadRelationViaJoin;
|
|
361
|
+
/**
|
|
362
|
+
* manyToMany via chained joins: the target (alias `t`) → junction (alias `j`)
|
|
363
|
+
* → the already-fetched side (alias `p`), correlating `__tpk` from the
|
|
364
|
+
* junction's source key. Always a list, stitched exactly like the loader.
|
|
365
|
+
*/
|
|
366
|
+
private loadManyToManyViaJoin;
|
|
367
|
+
/**
|
|
368
|
+
* The target column list to project through the join (honouring select/omit),
|
|
369
|
+
* with a loud guard: a real column named `__tpk` would collide with the
|
|
370
|
+
* reserved correlation alias, so refuse rather than silently mis-stitch.
|
|
371
|
+
*/
|
|
372
|
+
private joinChildCols;
|
|
373
|
+
/**
|
|
374
|
+
* `{ __tpk: <tpkExpr>, <col>: <childAlias>.<col>, … }`. Each child column is
|
|
375
|
+
* ALIASED to its bare name (a bare qualified ref `c.col` would come back named
|
|
376
|
+
* `c.col`, not `col`) so the stitched rows shape identically to a flat select.
|
|
377
|
+
*/
|
|
378
|
+
private joinProjection;
|
|
379
|
+
/**
|
|
380
|
+
* `filter <parentWhere qualified p> [and <relationWhere qualified childAlias>]`.
|
|
381
|
+
* The parent where is the ALREADY-RESOLVED predicate (relation filters collapsed
|
|
382
|
+
* to literal in-lists before the base query ran); the relation where is resolved
|
|
383
|
+
* on the target the same way before qualifying, so a nested relation filter in
|
|
384
|
+
* the relation `where` never reaches the join unresolved. Params bind in order.
|
|
385
|
+
*/
|
|
386
|
+
private joinFilter;
|
|
387
|
+
/** Group join rows by their (normalized) `__tpk`, stripping it and shaping each child. */
|
|
388
|
+
private bucketByTpk;
|
|
389
|
+
/**
|
|
390
|
+
* Normalize a correlation key to a stable string map key so a parent's key
|
|
391
|
+
* value (a shaped entity field) and a child row's `__tpk` cell match across
|
|
392
|
+
* wires and column types. A `Date` maps to microseconds
|
|
393
|
+
* (`getTime()` ms times 1000), because a datetime correlation cell arrives as
|
|
394
|
+
* raw micros (bigint on the native wire, a micros string on the legacy wire),
|
|
395
|
+
* never as ms. bigint / number / string all stringify to the same digits, so
|
|
396
|
+
* an int key matches whether it came back typed or as text.
|
|
397
|
+
*/
|
|
398
|
+
private joinKey;
|
|
237
399
|
/** Split `data` into scalar assignments; reject relation (nested-write) keys. */
|
|
238
400
|
private scalarData;
|
|
239
401
|
/**
|