turbine-orm 0.56.0 → 0.58.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 +16 -1
- package/dist/cjs/cli/index.js +284 -38
- package/dist/cjs/client.js +3 -39
- package/dist/cjs/plan-divergence.d.ts +320 -38
- package/dist/cjs/plan-divergence.js +413 -67
- package/dist/cjs/plan-flip-probe.d.ts +165 -0
- package/dist/cjs/plan-flip-probe.js +304 -0
- package/dist/cjs/prisma-compat.d.ts +32 -1
- package/dist/cjs/prisma-compat.js +297 -41
- package/dist/cjs/query/index.d.ts +2 -0
- package/dist/cjs/query/index.js +18 -1
- package/dist/cjs/query/option-surface.d.ts +100 -0
- package/dist/cjs/query/option-surface.js +214 -0
- package/dist/cjs/query/utils.d.ts +16 -0
- package/dist/cjs/query/utils.js +50 -0
- package/dist/cjs/query/warn-registry.d.ts +8 -0
- package/dist/cjs/query/warn-registry.js +8 -0
- package/dist/cli/index.js +285 -39
- package/dist/client.js +4 -40
- package/dist/plan-divergence.d.ts +320 -38
- package/dist/plan-divergence.js +412 -67
- package/dist/plan-flip-probe.d.ts +165 -0
- package/dist/plan-flip-probe.js +262 -0
- package/dist/prisma-compat.d.ts +32 -1
- package/dist/prisma-compat.js +297 -41
- package/dist/query/index.d.ts +2 -0
- package/dist/query/index.js +1 -0
- package/dist/query/option-surface.d.ts +100 -0
- package/dist/query/option-surface.js +209 -0
- package/dist/query/utils.d.ts +16 -0
- package/dist/query/utils.js +49 -0
- package/dist/query/warn-registry.d.ts +8 -0
- package/dist/query/warn-registry.js +8 -0
- package/package.json +1 -1
|
@@ -32,6 +32,15 @@
|
|
|
32
32
|
* atomic.
|
|
33
33
|
* - **Result reshaping**: `_count` objects keyed back to Prisma relation names,
|
|
34
34
|
* and to-one relations surfaced as `object | null`.
|
|
35
|
+
* - **Turbine-native query options** (`timeout`, `forceCustomPlan`,
|
|
36
|
+
* `warnOnUnlimited`, `skipGlobalFilters`, `stableRelationOrder`,
|
|
37
|
+
* `allowFullTableScan`, `includePii`, `optimisticLock`, `distinctOn`) reach
|
|
38
|
+
* core on every operation whose arg surface declares them. The set is not a
|
|
39
|
+
* hand-maintained list here: it comes from the compiler-checked tables in
|
|
40
|
+
* `query/option-surface.ts`, so a new core option cannot be silently stranded
|
|
41
|
+
* by this layer, and a key that is neither a Prisma arg nor a turbine option
|
|
42
|
+
* gets a dev-mode warning instead of vanishing (see
|
|
43
|
+
* {@link PRISMA_ARG_KEYS} and `warnUnknownQueryOptions`).
|
|
35
44
|
*
|
|
36
45
|
* ## What it deliberately does NOT do (documented divergences)
|
|
37
46
|
*
|
|
@@ -64,6 +73,14 @@
|
|
|
64
73
|
* exclusive-cursor + `offset` translation.
|
|
65
74
|
* - **Negative `take`** (take-from-end) and **`skip` on a nested relation
|
|
66
75
|
* include** throw, Turbine's `with` clause has no offset and no reverse-take.
|
|
76
|
+
* - **`limit` on `updateMany` / `deleteMany`** (Prisma 6.7+) throws. Turbine has
|
|
77
|
+
* no row-bounded mass mutation, and dropping a SAFETY BOUND with a warning
|
|
78
|
+
* would turn "change at most 10 rows" into "change every matching row".
|
|
79
|
+
* - **Write projections** (`select` / `include` / `omit` on
|
|
80
|
+
* create/update/delete/upsert), **`select` on `count`**, and
|
|
81
|
+
* **`orderBy` / `cursor` / `take` / `skip` on `aggregate`** are accepted and
|
|
82
|
+
* IGNORED (they are legitimate Prisma, so they never warn); the full row / a
|
|
83
|
+
* plain number comes back.
|
|
67
84
|
*
|
|
68
85
|
* ## Type dependencies (0.41.0)
|
|
69
86
|
*
|
|
@@ -94,10 +111,12 @@
|
|
|
94
111
|
* ```
|
|
95
112
|
*/
|
|
96
113
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
97
|
-
exports.CLIENT_RESERVED_KEYS = exports.COMPAT_DEFERRED = exports.Prisma = void 0;
|
|
114
|
+
exports.CLIENT_RESERVED_KEYS = exports.COMPAT_DEFERRED = exports.PRISMA_ARG_KEYS = exports.Prisma = void 0;
|
|
98
115
|
exports.createPrismaCompatClient = createPrismaCompatClient;
|
|
99
116
|
const errors_js_1 = require("./errors.js");
|
|
100
117
|
const nested_write_js_1 = require("./nested-write.js");
|
|
118
|
+
const index_js_1 = require("./query/index.js");
|
|
119
|
+
const utils_js_1 = require("./query/utils.js");
|
|
101
120
|
const warn_registry_js_1 = require("./query/warn-registry.js");
|
|
102
121
|
// ---------------------------------------------------------------------------
|
|
103
122
|
// Prisma.sql-style raw fragments (local, minimal, never imports @prisma/client)
|
|
@@ -256,6 +275,199 @@ function isPlainObject(v) {
|
|
|
256
275
|
function renameField(mm, prismaField) {
|
|
257
276
|
return mm.fields[prismaField] ?? prismaField;
|
|
258
277
|
}
|
|
278
|
+
/** The turbine arg surface each operation compiles into. */
|
|
279
|
+
const OPERATION_TABLES = {
|
|
280
|
+
findMany: index_js_1.FIND_MANY_OPTIONS,
|
|
281
|
+
findFirst: index_js_1.FIND_MANY_OPTIONS,
|
|
282
|
+
findFirstOrThrow: index_js_1.FIND_MANY_OPTIONS,
|
|
283
|
+
findUnique: index_js_1.FIND_UNIQUE_OPTIONS,
|
|
284
|
+
findUniqueOrThrow: index_js_1.FIND_UNIQUE_OPTIONS,
|
|
285
|
+
create: index_js_1.CREATE_OPTIONS,
|
|
286
|
+
createMany: index_js_1.CREATE_MANY_OPTIONS,
|
|
287
|
+
update: index_js_1.UPDATE_OPTIONS,
|
|
288
|
+
updateMany: index_js_1.UPDATE_MANY_OPTIONS,
|
|
289
|
+
delete: index_js_1.DELETE_OPTIONS,
|
|
290
|
+
deleteMany: index_js_1.DELETE_MANY_OPTIONS,
|
|
291
|
+
upsert: index_js_1.UPSERT_OPTIONS,
|
|
292
|
+
count: index_js_1.COUNT_OPTIONS,
|
|
293
|
+
aggregate: index_js_1.AGGREGATE_OPTIONS,
|
|
294
|
+
groupBy: index_js_1.GROUP_BY_OPTIONS,
|
|
295
|
+
};
|
|
296
|
+
/**
|
|
297
|
+
* Every argument key Prisma itself accepts, per operation.
|
|
298
|
+
*
|
|
299
|
+
* Extracted from a generated `@prisma/client` 7.9.0 `index.d.ts` (the
|
|
300
|
+
* `<Model><Op>Args` blocks). It must stay the UNION across the Prisma majors
|
|
301
|
+
* this adapter supports, never one version's set: a key a newer major
|
|
302
|
+
* introduces should degrade to one noisy dev line, never to a throw, and a key
|
|
303
|
+
* an older major had must keep working. The drift test in
|
|
304
|
+
* `src/test/prisma-compat-option-surface.test.ts` re-extracts from a generated
|
|
305
|
+
* client when one is present and asserts this stays a superset.
|
|
306
|
+
*/
|
|
307
|
+
exports.PRISMA_ARG_KEYS = {
|
|
308
|
+
findMany: [
|
|
309
|
+
'select',
|
|
310
|
+
'omit',
|
|
311
|
+
'include',
|
|
312
|
+
'where',
|
|
313
|
+
'orderBy',
|
|
314
|
+
'cursor',
|
|
315
|
+
'take',
|
|
316
|
+
'skip',
|
|
317
|
+
'distinct',
|
|
318
|
+
'relationLoadStrategy',
|
|
319
|
+
],
|
|
320
|
+
findFirst: [
|
|
321
|
+
'select',
|
|
322
|
+
'omit',
|
|
323
|
+
'include',
|
|
324
|
+
'where',
|
|
325
|
+
'orderBy',
|
|
326
|
+
'cursor',
|
|
327
|
+
'take',
|
|
328
|
+
'skip',
|
|
329
|
+
'distinct',
|
|
330
|
+
'relationLoadStrategy',
|
|
331
|
+
],
|
|
332
|
+
findFirstOrThrow: [
|
|
333
|
+
'select',
|
|
334
|
+
'omit',
|
|
335
|
+
'include',
|
|
336
|
+
'where',
|
|
337
|
+
'orderBy',
|
|
338
|
+
'cursor',
|
|
339
|
+
'take',
|
|
340
|
+
'skip',
|
|
341
|
+
'distinct',
|
|
342
|
+
'relationLoadStrategy',
|
|
343
|
+
],
|
|
344
|
+
findUnique: ['select', 'omit', 'include', 'where', 'relationLoadStrategy'],
|
|
345
|
+
findUniqueOrThrow: ['select', 'omit', 'include', 'where', 'relationLoadStrategy'],
|
|
346
|
+
create: ['select', 'omit', 'include', 'data', 'relationLoadStrategy'],
|
|
347
|
+
createMany: ['data', 'skipDuplicates'],
|
|
348
|
+
update: ['select', 'omit', 'include', 'data', 'where', 'relationLoadStrategy'],
|
|
349
|
+
updateMany: ['data', 'where', 'limit'],
|
|
350
|
+
delete: ['select', 'omit', 'include', 'where', 'relationLoadStrategy'],
|
|
351
|
+
deleteMany: ['where', 'limit'],
|
|
352
|
+
upsert: ['select', 'omit', 'include', 'where', 'create', 'update', 'relationLoadStrategy'],
|
|
353
|
+
count: ['where', 'orderBy', 'cursor', 'take', 'skip', 'select'],
|
|
354
|
+
aggregate: ['where', 'orderBy', 'cursor', 'take', 'skip', '_count', '_avg', '_sum', '_min', '_max'],
|
|
355
|
+
groupBy: ['where', 'orderBy', 'by', 'having', 'take', 'skip', '_count', '_avg', '_sum', '_min', '_max'],
|
|
356
|
+
};
|
|
357
|
+
/**
|
|
358
|
+
* Turbine spellings whose Prisma equivalent is spelled differently. A caller
|
|
359
|
+
* who reaches for one of these is not confused about the NAME, they are
|
|
360
|
+
* confused about which surface they are on, so they get a specific message
|
|
361
|
+
* rather than a fuzzy did-you-mean.
|
|
362
|
+
*/
|
|
363
|
+
const ALIAS_HINT = {
|
|
364
|
+
limit: 'take',
|
|
365
|
+
offset: 'skip',
|
|
366
|
+
with: 'include',
|
|
367
|
+
};
|
|
368
|
+
/**
|
|
369
|
+
* Known(op) = Prisma's own keys for that operation, plus every key the
|
|
370
|
+
* operation's turbine arg surface declares except the `'internal'` ones.
|
|
371
|
+
*
|
|
372
|
+
* The second half is NOT just the `'native'` keys. Two turbine-only options are
|
|
373
|
+
* classified `'prisma'` because their values carry field names and so must be
|
|
374
|
+
* hand-translated (`optimisticLock`, `distinctOn`); they are fully honoured, and
|
|
375
|
+
* warning about a key the adapter just acted on would be the worst possible
|
|
376
|
+
* diagnostic. `'nativeAlias'` members are in the set on purpose too: `limit` on
|
|
377
|
+
* `findMany` IS recognized, it simply gets the alias message rather than the
|
|
378
|
+
* generic one. Only `'internal'` is excluded, because nothing on this surface
|
|
379
|
+
* can reach it.
|
|
380
|
+
*
|
|
381
|
+
* A `Set` rather than an `in` test on a record, so an inherited
|
|
382
|
+
* `Object.prototype` name (`toString`, `constructor`) is treated as the unknown
|
|
383
|
+
* key it is.
|
|
384
|
+
*/
|
|
385
|
+
const KNOWN_KEYS = (() => {
|
|
386
|
+
const out = {};
|
|
387
|
+
for (const op of Object.keys(OPERATION_TABLES)) {
|
|
388
|
+
out[op] = new Set([
|
|
389
|
+
...exports.PRISMA_ARG_KEYS[op],
|
|
390
|
+
...(0, index_js_1.optionKeysOfKind)(OPERATION_TABLES[op], 'prisma', 'native', 'nativeAlias'),
|
|
391
|
+
]);
|
|
392
|
+
}
|
|
393
|
+
return out;
|
|
394
|
+
})();
|
|
395
|
+
/**
|
|
396
|
+
* Dev-mode notice for a key on a delegate's args object that this operation has
|
|
397
|
+
* no meaning for.
|
|
398
|
+
*
|
|
399
|
+
* An unrecognized key is silently ignored (JavaScript objects have no schema),
|
|
400
|
+
* which makes a typo, a turbine spelling, and a genuinely missing feature all
|
|
401
|
+
* look identical: nothing happens. The client-config warner
|
|
402
|
+
* (`warnUnknownConfigKeys` in client.ts) exists for the same reason and this is
|
|
403
|
+
* its query-level twin, down to the ranking of the suggestion.
|
|
404
|
+
*
|
|
405
|
+
* Deliberately a WARNING, never an error. Throwing would turn a working app
|
|
406
|
+
* into a failing one on upgrade over one stray key, and a key from a Prisma
|
|
407
|
+
* major newer than {@link PRISMA_ARG_KEYS} would be exactly that key. The whole
|
|
408
|
+
* body is wrapped so a hostile or exotic args object (a Proxy whose `ownKeys`
|
|
409
|
+
* throws) can never be the reason a query fails. Dev-only and once per
|
|
410
|
+
* `model.operation.key` per process, like every other advisory here.
|
|
411
|
+
*/
|
|
412
|
+
function warnUnknownQueryOptions(model, op, args) {
|
|
413
|
+
if (process.env.NODE_ENV === 'production')
|
|
414
|
+
return;
|
|
415
|
+
if (!isPlainObject(args))
|
|
416
|
+
return;
|
|
417
|
+
try {
|
|
418
|
+
const known = KNOWN_KEYS[op];
|
|
419
|
+
const table = OPERATION_TABLES[op];
|
|
420
|
+
for (const key of Object.keys(args)) {
|
|
421
|
+
// `{ ...maybeOptions }` routinely materializes keys with no value.
|
|
422
|
+
// Nothing is being dropped when the value is undefined.
|
|
423
|
+
if (args[key] === undefined)
|
|
424
|
+
continue;
|
|
425
|
+
const alias = table[key] === 'nativeAlias' ? ALIAS_HINT[key] : undefined;
|
|
426
|
+
if (!alias && known.has(key))
|
|
427
|
+
continue;
|
|
428
|
+
if (!(0, warn_registry_js_1.shouldWarnOnce)(warn_registry_js_1.WARN_NS.unknownQueryOption, `${model}.${op}.${key}`))
|
|
429
|
+
continue;
|
|
430
|
+
if (alias) {
|
|
431
|
+
console.warn(`[turbine] prisma-compat: "${key}" is Turbine's spelling and is ignored here;` +
|
|
432
|
+
` prisma-compat takes Prisma's "${alias}". (${model}.${op})`);
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
const suggestion = (0, utils_js_1.suggestKey)(key, known);
|
|
436
|
+
console.warn(`[turbine] prisma-compat: unknown option "${key}" in ${model}.${op}(), it is ignored.` +
|
|
437
|
+
(suggestion ? ` Did you mean "${suggestion}"?` : ''));
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
catch {
|
|
441
|
+
// Key enumeration is the only thing that can fail here, and a diagnostic
|
|
442
|
+
// must never be the reason a query fails.
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Prisma 6.7+ accepts `limit` on `updateMany` / `deleteMany` to BOUND how many
|
|
447
|
+
* rows a mass mutation touches. Turbine has no row-bounded mass mutation, so
|
|
448
|
+
* this one is refused rather than warned about: everywhere else in this design
|
|
449
|
+
* a dropped option costs the caller a feature, but silently dropping a safety
|
|
450
|
+
* bound turns "change at most 10 rows" into "change every row".
|
|
451
|
+
*/
|
|
452
|
+
function refuseRowLimit(model, op, args) {
|
|
453
|
+
if (!isPlainObject(args) || args.limit === undefined)
|
|
454
|
+
return;
|
|
455
|
+
throw new errors_js_1.UnsupportedFeatureError(`\`limit\` on ${op} (row-bounded mass mutation)`, 'prisma-compat', `Turbine has no row-bounded ${op}; select the rows you mean with \`where\`` +
|
|
456
|
+
` (on ${model}.${op}), or page them and mutate by primary key.`);
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Prisma's `relationLoadStrategy` and Turbine's share a name and NOT a value
|
|
460
|
+
* domain: Prisma has `'query' | 'join'`, Turbine has
|
|
461
|
+
* `'join' | 'batched' | 'auto' | 'flatten'`. Core's strategy resolution has no
|
|
462
|
+
* branch for `'query'` and returns the value unchanged, so forwarding it
|
|
463
|
+
* verbatim gave a caller who asked for the per-relation query plan the JOIN
|
|
464
|
+
* plan, the exact opposite of the request. Prisma's `'query'` IS Turbine's
|
|
465
|
+
* `'batched'` (one follow-up statement per relation); the turbine-only values
|
|
466
|
+
* pass through so a compat caller can still reach them.
|
|
467
|
+
*/
|
|
468
|
+
function mapRelationLoadStrategy(value) {
|
|
469
|
+
return value === 'query' ? 'batched' : value;
|
|
470
|
+
}
|
|
259
471
|
/**
|
|
260
472
|
* Translate a Prisma `where` (or nested relation where) into a Turbine `where`.
|
|
261
473
|
* Renames scalar field keys and relation keys through the map, recurses into
|
|
@@ -450,6 +662,13 @@ function modelName(ctx, mm) {
|
|
|
450
662
|
*/
|
|
451
663
|
function translateReadArgs(ctx, mm, prismaArgs, kind) {
|
|
452
664
|
const t = {};
|
|
665
|
+
// FIRST, so a per-call `stableRelationOrder` overrides it: the client-level
|
|
666
|
+
// option is a default, the arg is an instruction.
|
|
667
|
+
if (ctx.options.stablePkOrder)
|
|
668
|
+
t.stableRelationOrder = true;
|
|
669
|
+
// Every turbine-native option the arg surface declares, in one line that
|
|
670
|
+
// cannot fall behind the interface (see the option-surface tables).
|
|
671
|
+
(0, index_js_1.applyNativeOptions)(kind === 'unique' ? index_js_1.FIND_UNIQUE_OPTIONS : index_js_1.FIND_MANY_OPTIONS, prismaArgs, t);
|
|
453
672
|
if (prismaArgs.where !== undefined)
|
|
454
673
|
t.where = translateWhere(ctx, mm, prismaArgs.where);
|
|
455
674
|
if (prismaArgs.orderBy !== undefined)
|
|
@@ -462,17 +681,9 @@ function translateReadArgs(ctx, mm, prismaArgs, kind) {
|
|
|
462
681
|
if (Array.isArray(prismaArgs.distinct)) {
|
|
463
682
|
t.distinct = prismaArgs.distinct.map((f) => renameField(mm, f));
|
|
464
683
|
}
|
|
465
|
-
if (prismaArgs.relationLoadStrategy !== undefined)
|
|
466
|
-
t.relationLoadStrategy = prismaArgs.relationLoadStrategy;
|
|
467
|
-
|
|
468
|
-
t.timeout = prismaArgs.timeout;
|
|
469
|
-
// Turbine-only passthrough. Prisma has no PII concept, so a compat caller
|
|
470
|
-
// whose schema tags columns needs SOME way to opt in; without this the
|
|
471
|
-
// adapter is a one-way door into redacted reads and refused aggregates.
|
|
472
|
-
if (prismaArgs.includePii !== undefined)
|
|
473
|
-
t.includePii = prismaArgs.includePii;
|
|
474
|
-
if (ctx.options.stablePkOrder)
|
|
475
|
-
t.stableRelationOrder = true;
|
|
684
|
+
if (prismaArgs.relationLoadStrategy !== undefined) {
|
|
685
|
+
t.relationLoadStrategy = mapRelationLoadStrategy(prismaArgs.relationLoadStrategy);
|
|
686
|
+
}
|
|
476
687
|
// ORDER IS LOAD-BEARING: translateCursor MUST run BEFORE applyImplicitPkOrder.
|
|
477
688
|
// The cursor translation reads `t.orderBy` to decide the seek direction and to
|
|
478
689
|
// validate that a bare inclusive cursor names the sort key; it must see the
|
|
@@ -771,6 +982,7 @@ function translateUpsertNested(ctx, target, p) {
|
|
|
771
982
|
const AGG_FIELD_BLOCKS = ['_sum', '_avg', '_min', '_max'];
|
|
772
983
|
function translateAggregateArgs(ctx, mm, args, isGroupBy) {
|
|
773
984
|
const t = {};
|
|
985
|
+
(0, index_js_1.applyNativeOptions)(isGroupBy ? index_js_1.GROUP_BY_OPTIONS : index_js_1.AGGREGATE_OPTIONS, args, t);
|
|
774
986
|
if (args.where !== undefined)
|
|
775
987
|
t.where = translateWhere(ctx, mm, args.where);
|
|
776
988
|
if (args._count !== undefined)
|
|
@@ -779,12 +991,6 @@ function translateAggregateArgs(ctx, mm, args, isGroupBy) {
|
|
|
779
991
|
if (args[block] !== undefined)
|
|
780
992
|
t[block] = renameAggBlock(mm, args[block], false);
|
|
781
993
|
}
|
|
782
|
-
if (typeof args.timeout === 'number')
|
|
783
|
-
t.timeout = args.timeout;
|
|
784
|
-
// Turbine-only passthrough: the PII gate on groupBy keys and _min/_max needs
|
|
785
|
-
// an opt-in that Prisma's arg shape has no equivalent for.
|
|
786
|
-
if (args.includePii !== undefined)
|
|
787
|
-
t.includePii = args.includePii;
|
|
788
994
|
if (isGroupBy) {
|
|
789
995
|
if (Array.isArray(args.by))
|
|
790
996
|
t.by = args.by.map((f) => renameField(mm, f));
|
|
@@ -792,6 +998,8 @@ function translateAggregateArgs(ctx, mm, args, isGroupBy) {
|
|
|
792
998
|
t.orderBy = translateOrderBy(ctx, mm, args.orderBy);
|
|
793
999
|
if (args.having !== undefined)
|
|
794
1000
|
t.having = renameHaving(mm, args.having);
|
|
1001
|
+
if (args.distinctOn !== undefined)
|
|
1002
|
+
t.distinctOn = translateDistinctOn(ctx, mm, args.distinctOn);
|
|
795
1003
|
if (typeof args.take === 'number')
|
|
796
1004
|
t.limit = mapTake(args.take);
|
|
797
1005
|
if (typeof args.skip === 'number')
|
|
@@ -799,6 +1007,23 @@ function translateAggregateArgs(ctx, mm, args, isGroupBy) {
|
|
|
799
1007
|
}
|
|
800
1008
|
return t;
|
|
801
1009
|
}
|
|
1010
|
+
/**
|
|
1011
|
+
* Translate a turbine-native groupBy `distinctOn`. Both halves of its value
|
|
1012
|
+
* (`columns`, `orderBy`) are FIELD NAMES, so this is the concrete reason the
|
|
1013
|
+
* option surface refuses to copy unknown keys through by default: a blind
|
|
1014
|
+
* passthrough is correct on a model whose Prisma and turbine names coincide and
|
|
1015
|
+
* silently wrong on one with a `@map`.
|
|
1016
|
+
*/
|
|
1017
|
+
function translateDistinctOn(ctx, mm, val) {
|
|
1018
|
+
if (!isPlainObject(val))
|
|
1019
|
+
return val;
|
|
1020
|
+
const out = { ...val };
|
|
1021
|
+
if (Array.isArray(val.columns))
|
|
1022
|
+
out.columns = val.columns.map((f) => renameField(mm, f));
|
|
1023
|
+
if (val.orderBy !== undefined)
|
|
1024
|
+
out.orderBy = translateOrderBy(ctx, mm, val.orderBy);
|
|
1025
|
+
return out;
|
|
1026
|
+
}
|
|
802
1027
|
/** Rename field keys inside an aggregate block; `_count`'s `_all` passes through. */
|
|
803
1028
|
function renameAggBlock(mm, block, isCount) {
|
|
804
1029
|
if (block === true || !isPlainObject(block))
|
|
@@ -1143,6 +1368,8 @@ async function createManyByRun(qi, t, runs) {
|
|
|
1143
1368
|
const args = { data: run };
|
|
1144
1369
|
if (t.skipDuplicates)
|
|
1145
1370
|
args.skipDuplicates = true;
|
|
1371
|
+
if (t.timeout !== undefined)
|
|
1372
|
+
args.timeout = t.timeout;
|
|
1146
1373
|
count += (await qi.createMany(args)).length;
|
|
1147
1374
|
}
|
|
1148
1375
|
return { count };
|
|
@@ -1158,7 +1385,14 @@ function makeDelegate(ctx, mm, getQI, runInTx) {
|
|
|
1158
1385
|
// async run wrapper also converts any synchronous throw from the underlying
|
|
1159
1386
|
// `qi.*` build into a rejection; the array `$transaction([...])` batch path
|
|
1160
1387
|
// catches the same throw from `batch.build`.
|
|
1161
|
-
const defer = (
|
|
1388
|
+
const defer = (op, rawArgs, translateRaw, run, batch) => {
|
|
1389
|
+
// The unknown-key check rides the SAME deferred boundary as the translation
|
|
1390
|
+
// itself, for the same reason (see the comment above): a compat promise that
|
|
1391
|
+
// is built and never awaited must produce no output at all.
|
|
1392
|
+
const translate = () => {
|
|
1393
|
+
warnUnknownQueryOptions(modelName(ctx, mm), op, rawArgs);
|
|
1394
|
+
return translateRaw();
|
|
1395
|
+
};
|
|
1162
1396
|
const batchable = batch
|
|
1163
1397
|
? {
|
|
1164
1398
|
build: () => batch.build(getQI(), translate()),
|
|
@@ -1198,27 +1432,27 @@ function makeDelegate(ctx, mm, getQI, runInTx) {
|
|
|
1198
1432
|
return args;
|
|
1199
1433
|
};
|
|
1200
1434
|
return {
|
|
1201
|
-
findMany: (args = {}) => defer(() => translateReadArgs(ctx, mm, args, 'many'), (qi, t) => qi.findMany(t).then((r) => reshapeRows(ctx, mm, r)), { build: (qi, t) => qi.buildFindMany(t), reshape: (raw) => reshapeRows(ctx, mm, raw) }),
|
|
1202
|
-
findFirst: (args = {}) => defer(() => translateReadArgs(ctx, mm, args, 'first'), (qi, t) => qi.findFirst(t).then((r) => reshapeRowOrNull(ctx, mm, r)), { build: (qi, t) => qi.buildFindFirst(t), reshape: (raw) => reshapeRowOrNull(ctx, mm, raw) }),
|
|
1203
|
-
findUnique: (args) => defer(() => translateReadArgs(ctx, mm, requireWhere(args, 'findUnique'), 'unique'), (qi, t) => qi.findUnique(t).then((r) => reshapeRowOrNull(ctx, mm, r)), { build: (qi, t) => qi.buildFindUnique(t), reshape: (raw) => reshapeRowOrNull(ctx, mm, raw) }),
|
|
1204
|
-
findFirstOrThrow: (args = {}) => defer(() => translateReadArgs(ctx, mm, args, 'first'), (qi, t) => qi.findFirstOrThrow(t).then((r) => reshapeRow(ctx, mm, r)), { build: (qi, t) => qi.buildFindFirstOrThrow(t), reshape: (raw) => reshapeRow(ctx, mm, raw) }),
|
|
1205
|
-
findUniqueOrThrow: (args) => defer(() => translateReadArgs(ctx, mm, requireWhere(args, 'findUniqueOrThrow'), 'unique'), (qi, t) => qi.findUniqueOrThrow(t).then((r) => reshapeRow(ctx, mm, r)), { build: (qi, t) => qi.buildFindUniqueOrThrow(t), reshape: (raw) => reshapeRow(ctx, mm, raw) }),
|
|
1206
|
-
create: (args) => defer(() => {
|
|
1435
|
+
findMany: (args = {}) => defer('findMany', args, () => translateReadArgs(ctx, mm, args, 'many'), (qi, t) => qi.findMany(t).then((r) => reshapeRows(ctx, mm, r)), { build: (qi, t) => qi.buildFindMany(t), reshape: (raw) => reshapeRows(ctx, mm, raw) }),
|
|
1436
|
+
findFirst: (args = {}) => defer('findFirst', args, () => translateReadArgs(ctx, mm, args, 'first'), (qi, t) => qi.findFirst(t).then((r) => reshapeRowOrNull(ctx, mm, r)), { build: (qi, t) => qi.buildFindFirst(t), reshape: (raw) => reshapeRowOrNull(ctx, mm, raw) }),
|
|
1437
|
+
findUnique: (args) => defer('findUnique', args, () => translateReadArgs(ctx, mm, requireWhere(args, 'findUnique'), 'unique'), (qi, t) => qi.findUnique(t).then((r) => reshapeRowOrNull(ctx, mm, r)), { build: (qi, t) => qi.buildFindUnique(t), reshape: (raw) => reshapeRowOrNull(ctx, mm, raw) }),
|
|
1438
|
+
findFirstOrThrow: (args = {}) => defer('findFirstOrThrow', args, () => translateReadArgs(ctx, mm, args, 'first'), (qi, t) => qi.findFirstOrThrow(t).then((r) => reshapeRow(ctx, mm, r)), { build: (qi, t) => qi.buildFindFirstOrThrow(t), reshape: (raw) => reshapeRow(ctx, mm, raw) }),
|
|
1439
|
+
findUniqueOrThrow: (args) => defer('findUniqueOrThrow', args, () => translateReadArgs(ctx, mm, requireWhere(args, 'findUniqueOrThrow'), 'unique'), (qi, t) => qi.findUniqueOrThrow(t).then((r) => reshapeRow(ctx, mm, r)), { build: (qi, t) => qi.buildFindUniqueOrThrow(t), reshape: (raw) => reshapeRow(ctx, mm, raw) }),
|
|
1440
|
+
create: (args) => defer('create', args, () => {
|
|
1207
1441
|
const t = { data: translateWriteData(ctx, mm, applyCreateDefaults(mm, args.data)) };
|
|
1208
|
-
|
|
1209
|
-
t.timeout = args.timeout;
|
|
1442
|
+
(0, index_js_1.applyNativeOptions)(index_js_1.CREATE_OPTIONS, args, t);
|
|
1210
1443
|
return t;
|
|
1211
1444
|
}, (qi, t) => qi.create(t).then((r) => reshapeRow(ctx, mm, r)), {
|
|
1212
1445
|
build: (qi, t) => qi.buildCreate(t),
|
|
1213
1446
|
reshape: (raw) => reshapeRow(ctx, mm, raw),
|
|
1214
1447
|
nested: (t) => hasNestedKeys(ctx, mm, t.data),
|
|
1215
1448
|
}),
|
|
1216
|
-
createMany: (args) => defer(() => {
|
|
1449
|
+
createMany: (args) => defer('createMany', args, () => {
|
|
1217
1450
|
const data = args.data;
|
|
1218
1451
|
const rows = Array.isArray(data)
|
|
1219
1452
|
? data.map((d) => translateWriteData(ctx, mm, applyCreateDefaults(mm, d)))
|
|
1220
1453
|
: [];
|
|
1221
1454
|
const t = { data: rows };
|
|
1455
|
+
(0, index_js_1.applyNativeOptions)(index_js_1.CREATE_MANY_OPTIONS, args, t);
|
|
1222
1456
|
if (args.skipDuplicates)
|
|
1223
1457
|
t.skipDuplicates = true;
|
|
1224
1458
|
return t;
|
|
@@ -1239,45 +1473,68 @@ function makeDelegate(ctx, mm, getQI, runInTx) {
|
|
|
1239
1473
|
nested: (t) => createManyRunsOf(t).length > 1,
|
|
1240
1474
|
execInTx: (table, t) => createManyByRun(table(mm.table), t, createManyRunsOf(t)),
|
|
1241
1475
|
}),
|
|
1242
|
-
update: (args) => defer(() => {
|
|
1476
|
+
update: (args) => defer('update', args, () => {
|
|
1243
1477
|
const a = requireWhere(args, 'update');
|
|
1244
|
-
|
|
1478
|
+
const t = {
|
|
1245
1479
|
where: translateWhere(ctx, mm, a.where),
|
|
1246
1480
|
data: translateWriteData(ctx, mm, applyUpdateTouch(mm, a.data)),
|
|
1247
1481
|
};
|
|
1482
|
+
(0, index_js_1.applyNativeOptions)(index_js_1.UPDATE_OPTIONS, a, t);
|
|
1483
|
+
// `optimisticLock.field` is a FIELD NAME, so it is renamed rather than
|
|
1484
|
+
// copied: a blind passthrough would send the Prisma spelling into core
|
|
1485
|
+
// and break on any model whose column is `@map`ped.
|
|
1486
|
+
if (isPlainObject(a.optimisticLock)) {
|
|
1487
|
+
t.optimisticLock = {
|
|
1488
|
+
...a.optimisticLock,
|
|
1489
|
+
field: renameField(mm, String(a.optimisticLock.field)),
|
|
1490
|
+
};
|
|
1491
|
+
}
|
|
1492
|
+
return t;
|
|
1248
1493
|
}, (qi, t) => qi.update(t).then((r) => reshapeRow(ctx, mm, r)), {
|
|
1249
1494
|
build: (qi, t) => qi.buildUpdate(t),
|
|
1250
1495
|
reshape: (raw) => reshapeRow(ctx, mm, raw),
|
|
1251
1496
|
nested: (t) => hasNestedKeys(ctx, mm, t.data),
|
|
1252
1497
|
}),
|
|
1253
|
-
updateMany: (args) => defer(() => {
|
|
1498
|
+
updateMany: (args) => defer('updateMany', args, () => {
|
|
1254
1499
|
const a = args;
|
|
1500
|
+
refuseRowLimit(modelName(ctx, mm), 'updateMany', a);
|
|
1255
1501
|
const t = {
|
|
1256
1502
|
where: translateWhere(ctx, mm, a.where ?? {}),
|
|
1257
1503
|
data: translateWriteData(ctx, mm, applyUpdateTouch(mm, a.data)),
|
|
1258
1504
|
};
|
|
1505
|
+
(0, index_js_1.applyNativeOptions)(index_js_1.UPDATE_MANY_OPTIONS, a, t);
|
|
1506
|
+
// LAST, so it wins: a Prisma updateMany with no `where` affects every
|
|
1507
|
+
// row, and an explicit `allowFullTableScan: false` must not be able to
|
|
1508
|
+
// turn that parity into a thrown empty-where guard.
|
|
1259
1509
|
if (a.where === undefined)
|
|
1260
1510
|
t.allowFullTableScan = true;
|
|
1261
1511
|
return t;
|
|
1262
1512
|
}, (qi, t) => qi.updateMany(t), { build: (qi, t) => qi.buildUpdateMany(t), reshape: (raw) => raw }),
|
|
1263
|
-
delete: (args) => defer(() => {
|
|
1513
|
+
delete: (args) => defer('delete', args, () => {
|
|
1264
1514
|
const a = requireWhere(args, 'delete');
|
|
1265
|
-
|
|
1515
|
+
const t = { where: translateWhere(ctx, mm, a.where) };
|
|
1516
|
+
(0, index_js_1.applyNativeOptions)(index_js_1.DELETE_OPTIONS, a, t);
|
|
1517
|
+
return t;
|
|
1266
1518
|
}, (qi, t) => qi.delete(t).then((r) => reshapeRow(ctx, mm, r)), { build: (qi, t) => qi.buildDelete(t), reshape: (raw) => reshapeRow(ctx, mm, raw) }),
|
|
1267
|
-
deleteMany: (args = {}) => defer(() => {
|
|
1519
|
+
deleteMany: (args = {}) => defer('deleteMany', args, () => {
|
|
1268
1520
|
const a = args;
|
|
1521
|
+
refuseRowLimit(modelName(ctx, mm), 'deleteMany', a);
|
|
1269
1522
|
const t = { where: translateWhere(ctx, mm, a.where ?? {}) };
|
|
1523
|
+
(0, index_js_1.applyNativeOptions)(index_js_1.DELETE_MANY_OPTIONS, a, t);
|
|
1524
|
+
// LAST, so it wins. See the same note on updateMany.
|
|
1270
1525
|
if (a.where === undefined)
|
|
1271
1526
|
t.allowFullTableScan = true;
|
|
1272
1527
|
return t;
|
|
1273
1528
|
}, (qi, t) => qi.deleteMany(t), { build: (qi, t) => qi.buildDeleteMany(t), reshape: (raw) => raw }),
|
|
1274
|
-
upsert: (args) => defer(() => {
|
|
1529
|
+
upsert: (args) => defer('upsert', args, () => {
|
|
1275
1530
|
const a = requireWhere(args, 'upsert');
|
|
1276
|
-
|
|
1531
|
+
const t = {
|
|
1277
1532
|
where: translateWhere(ctx, mm, a.where),
|
|
1278
1533
|
create: translateWriteData(ctx, mm, applyCreateDefaults(mm, a.create)),
|
|
1279
1534
|
update: translateWriteData(ctx, mm, applyUpdateTouch(mm, a.update)),
|
|
1280
1535
|
};
|
|
1536
|
+
(0, index_js_1.applyNativeOptions)(index_js_1.UPSERT_OPTIONS, a, t);
|
|
1537
|
+
return t;
|
|
1281
1538
|
}, (qi, t) => {
|
|
1282
1539
|
// Native ON CONFLICT upsert is only Prisma-equivalent when the where
|
|
1283
1540
|
// key values equal the create values AND no nested write data is
|
|
@@ -1300,16 +1557,15 @@ function makeDelegate(ctx, mm, getQI, runInTx) {
|
|
|
1300
1557
|
return reshapeRow(ctx, mm, await upsertLookupFirst(table(mm.table), t));
|
|
1301
1558
|
},
|
|
1302
1559
|
}),
|
|
1303
|
-
count: (args = {}) => defer(() => {
|
|
1560
|
+
count: (args = {}) => defer('count', args, () => {
|
|
1304
1561
|
const t = {};
|
|
1562
|
+
(0, index_js_1.applyNativeOptions)(index_js_1.COUNT_OPTIONS, args, t);
|
|
1305
1563
|
if (args.where !== undefined)
|
|
1306
1564
|
t.where = translateWhere(ctx, mm, args.where);
|
|
1307
|
-
if (typeof args.timeout === 'number')
|
|
1308
|
-
t.timeout = args.timeout;
|
|
1309
1565
|
return t;
|
|
1310
1566
|
}, (qi, t) => qi.count(t), { build: (qi, t) => qi.buildCount(t), reshape: (raw) => raw }),
|
|
1311
|
-
aggregate: (args) => defer(() => translateAggregateArgs(ctx, mm, args, false), (qi, t) => qi.aggregate(t).then((r) => reshapeAggregate(ctx, mm, r)), { build: (qi, t) => qi.buildAggregate(t), reshape: (raw) => reshapeAggregate(ctx, mm, raw) }),
|
|
1312
|
-
groupBy: (args) => defer(() => translateAggregateArgs(ctx, mm, args, true), (qi, t) => qi.groupBy(t).then((rows) => rows.map((r) => reshapeGroupRow(ctx, mm, r))), {
|
|
1567
|
+
aggregate: (args) => defer('aggregate', args, () => translateAggregateArgs(ctx, mm, args, false), (qi, t) => qi.aggregate(t).then((r) => reshapeAggregate(ctx, mm, r)), { build: (qi, t) => qi.buildAggregate(t), reshape: (raw) => reshapeAggregate(ctx, mm, raw) }),
|
|
1568
|
+
groupBy: (args) => defer('groupBy', args, () => translateAggregateArgs(ctx, mm, args, true), (qi, t) => qi.groupBy(t).then((rows) => rows.map((r) => reshapeGroupRow(ctx, mm, r))), {
|
|
1313
1569
|
build: (qi, t) => qi.buildGroupBy(t),
|
|
1314
1570
|
reshape: (raw) => raw.map((r) => reshapeGroupRow(ctx, mm, r)),
|
|
1315
1571
|
}),
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
export type { AggregateArgs, AggregateResult, ArrayFilter, ColumnRef, ConnectOrCreateOp, CountArgs, CreateArgs, CreateDataInput, CreateManyArgs, DeleteArgs, DeleteManyArgs, FieldResult, FindManyArgs, FindManyStreamArgs, FindUniqueArgs, GlobalFilters, GroupByAggregateSpec, GroupByArgs, GroupByDistinctOn, GroupByResult, HavingClause, JsonFilter, JsonPathAggregateTarget, JsonPathGroupKey, JsonPathOrderBy, NestedCreateOp, NestedUpdateOp, NestedUpdateOpItem, NestedUpsertOpItem, OmitResult, OrderByClause, OrderByObject, OrderDirection, QueryResult, RelationDescriptor, RelationFilter, RelationLoadStrategy, RelationPickBy, RelationPickOrderBy, SelectResult, SkipGlobalFilters, TextSearchFilter, TypedWithClause, UpdateArgs, UpdateDataInput, UpdateInput, UpdateManyArgs, UpdateOperatorInput, UpsertArgs, VectorDistanceFilter, VectorFilter, VectorMetric, VectorOrderBy, VectorOrderByDistance, WhereClause, WhereOperator, WhereValue, WithClause, WithOptions, WithOrderByObject, WithResult, } from './types.js';
|
|
9
9
|
export type { BuiltStatement, BulkInsertStatementInput, ColumnDefinitionInput, ColumnTypeInput, CreateIndexStatementInput, CreateTableStatementInput, Dialect, InsertStatementInput, UpsertStatementInput, } from '../dialect.js';
|
|
10
10
|
export { postgresDialect } from '../dialect.js';
|
|
11
|
+
export type { OptionKind, OptionTable } from './option-surface.js';
|
|
12
|
+
export { AGGREGATE_OPTIONS, ALL_OPTION_TABLES, applyNativeOptions, COUNT_OPTIONS, CREATE_MANY_OPTIONS, CREATE_OPTIONS, DELETE_MANY_OPTIONS, DELETE_OPTIONS, FIND_MANY_OPTIONS, FIND_MANY_STREAM_OPTIONS, FIND_UNIQUE_OPTIONS, GROUP_BY_OPTIONS, optionKeysOfKind, UPDATE_MANY_OPTIONS, UPDATE_OPTIONS, UPSERT_OPTIONS, } from './option-surface.js';
|
|
11
13
|
export type { SqlCacheEntry } from './utils.js';
|
|
12
14
|
export { buildCorrelation, escapeLike, escSingleQuote, fnv1a64Hex, LRUCache, OPERATOR_KEYS, quoteIdent, sqlToPreparedName, } from './utils.js';
|
|
13
15
|
export type { DeferredQuery, MiddlewareFn, QueryEvent, QueryEventListener, QueryInterfaceOptions, ReselectExecutor, TemporalInfinityReading, } from './builder.js';
|
package/dist/cjs/query/index.js
CHANGED
|
@@ -7,9 +7,26 @@
|
|
|
7
7
|
* former monolithic `import { … } from './query.js'`.
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.QueryInterface = exports.AUTO_TO_ONE_JOIN_ROWS_MIN = exports.AUTO_TO_ONE_JOIN_ROWS_MAX = exports.AUTO_TO_ONE_JOIN_MAX_ROWS = exports.AUTO_JOIN_PENALTY_MS_PER_ROW = exports.AUTO_COUNT_BATCH_MIN_PARENT_ROWS = exports.AUTO_ASSUMED_ROUND_TRIP_MS = exports.sqlToPreparedName = exports.quoteIdent = exports.OPERATOR_KEYS = exports.LRUCache = exports.fnv1a64Hex = exports.escSingleQuote = exports.escapeLike = exports.buildCorrelation = exports.postgresDialect = void 0;
|
|
10
|
+
exports.QueryInterface = exports.AUTO_TO_ONE_JOIN_ROWS_MIN = exports.AUTO_TO_ONE_JOIN_ROWS_MAX = exports.AUTO_TO_ONE_JOIN_MAX_ROWS = exports.AUTO_JOIN_PENALTY_MS_PER_ROW = exports.AUTO_COUNT_BATCH_MIN_PARENT_ROWS = exports.AUTO_ASSUMED_ROUND_TRIP_MS = exports.sqlToPreparedName = exports.quoteIdent = exports.OPERATOR_KEYS = exports.LRUCache = exports.fnv1a64Hex = exports.escSingleQuote = exports.escapeLike = exports.buildCorrelation = exports.UPSERT_OPTIONS = exports.UPDATE_OPTIONS = exports.UPDATE_MANY_OPTIONS = exports.optionKeysOfKind = exports.GROUP_BY_OPTIONS = exports.FIND_UNIQUE_OPTIONS = exports.FIND_MANY_STREAM_OPTIONS = exports.FIND_MANY_OPTIONS = exports.DELETE_OPTIONS = exports.DELETE_MANY_OPTIONS = exports.CREATE_OPTIONS = exports.CREATE_MANY_OPTIONS = exports.COUNT_OPTIONS = exports.applyNativeOptions = exports.ALL_OPTION_TABLES = exports.AGGREGATE_OPTIONS = exports.postgresDialect = void 0;
|
|
11
11
|
var dialect_js_1 = require("../dialect.js");
|
|
12
12
|
Object.defineProperty(exports, "postgresDialect", { enumerable: true, get: function () { return dialect_js_1.postgresDialect; } });
|
|
13
|
+
var option_surface_js_1 = require("./option-surface.js");
|
|
14
|
+
Object.defineProperty(exports, "AGGREGATE_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.AGGREGATE_OPTIONS; } });
|
|
15
|
+
Object.defineProperty(exports, "ALL_OPTION_TABLES", { enumerable: true, get: function () { return option_surface_js_1.ALL_OPTION_TABLES; } });
|
|
16
|
+
Object.defineProperty(exports, "applyNativeOptions", { enumerable: true, get: function () { return option_surface_js_1.applyNativeOptions; } });
|
|
17
|
+
Object.defineProperty(exports, "COUNT_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.COUNT_OPTIONS; } });
|
|
18
|
+
Object.defineProperty(exports, "CREATE_MANY_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.CREATE_MANY_OPTIONS; } });
|
|
19
|
+
Object.defineProperty(exports, "CREATE_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.CREATE_OPTIONS; } });
|
|
20
|
+
Object.defineProperty(exports, "DELETE_MANY_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.DELETE_MANY_OPTIONS; } });
|
|
21
|
+
Object.defineProperty(exports, "DELETE_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.DELETE_OPTIONS; } });
|
|
22
|
+
Object.defineProperty(exports, "FIND_MANY_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.FIND_MANY_OPTIONS; } });
|
|
23
|
+
Object.defineProperty(exports, "FIND_MANY_STREAM_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.FIND_MANY_STREAM_OPTIONS; } });
|
|
24
|
+
Object.defineProperty(exports, "FIND_UNIQUE_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.FIND_UNIQUE_OPTIONS; } });
|
|
25
|
+
Object.defineProperty(exports, "GROUP_BY_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.GROUP_BY_OPTIONS; } });
|
|
26
|
+
Object.defineProperty(exports, "optionKeysOfKind", { enumerable: true, get: function () { return option_surface_js_1.optionKeysOfKind; } });
|
|
27
|
+
Object.defineProperty(exports, "UPDATE_MANY_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.UPDATE_MANY_OPTIONS; } });
|
|
28
|
+
Object.defineProperty(exports, "UPDATE_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.UPDATE_OPTIONS; } });
|
|
29
|
+
Object.defineProperty(exports, "UPSERT_OPTIONS", { enumerable: true, get: function () { return option_surface_js_1.UPSERT_OPTIONS; } });
|
|
13
30
|
var utils_js_1 = require("./utils.js");
|
|
14
31
|
Object.defineProperty(exports, "buildCorrelation", { enumerable: true, get: function () { return utils_js_1.buildCorrelation; } });
|
|
15
32
|
Object.defineProperty(exports, "escapeLike", { enumerable: true, get: function () { return utils_js_1.escapeLike; } });
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* turbine-orm, the query-argument OPTION SURFACE as runtime data.
|
|
3
|
+
*
|
|
4
|
+
* ## Why this file exists
|
|
5
|
+
*
|
|
6
|
+
* TypeScript erases interfaces, so `FindManyArgs` does not exist at runtime and
|
|
7
|
+
* any layer that has to decide, key by key, what to do with an args object has
|
|
8
|
+
* to keep its own hand-written list. `turbine-orm/prisma-compat` is exactly
|
|
9
|
+
* such a layer: it builds a FRESH turbine args object out of Prisma-shaped
|
|
10
|
+
* input and copies over the keys it recognizes. Every time core gained a
|
|
11
|
+
* query-level option, that ad-hoc allowlist silently failed to gain it, and the
|
|
12
|
+
* option was accepted by the caller's type-checker and then dropped on the
|
|
13
|
+
* floor. There was no feedback of any kind: no error, no warning, no test.
|
|
14
|
+
*
|
|
15
|
+
* These tables are the fix. Each one is a `Record<keyof SomeArgs<Row>,
|
|
16
|
+
* OptionKind>`, the same mechanism `TURBINE_CONFIG_KEYS` (client.ts) uses for
|
|
17
|
+
* the client-config surface, and it binds the compiler in BOTH directions:
|
|
18
|
+
*
|
|
19
|
+
* - add an option to an arg interface and this file stops compiling until a
|
|
20
|
+
* human classifies it ("Property 'fooMode' is missing in type ..."), so an
|
|
21
|
+
* option can no longer be stranded BY OMISSION;
|
|
22
|
+
* - list a key here that is not on the interface and it fails as an excess
|
|
23
|
+
* property, so a table can never drift into describing an option that does
|
|
24
|
+
* not exist.
|
|
25
|
+
*
|
|
26
|
+
* It deliberately does NOT make "add the option in one place" sufficient: it
|
|
27
|
+
* makes the second edit a BUILD FAILURE rather than a silent drop. That trade is
|
|
28
|
+
* intentional. A passthrough-by-default translator would satisfy the shorter
|
|
29
|
+
* wording and be actively wrong, because two of the options below carry FIELD
|
|
30
|
+
* NAMES in their values (`optimisticLock.field`, `distinctOn.columns`), which a
|
|
31
|
+
* compat layer must rename before core ever sees them. Copying those blind
|
|
32
|
+
* works on a schema whose names happen to coincide and breaks on one that
|
|
33
|
+
* renames a column, i.e. it makes the failure mode depend on the schema.
|
|
34
|
+
*
|
|
35
|
+
* ## THE ONE RULE for classifying a new option
|
|
36
|
+
*
|
|
37
|
+
* Classify a key `'native'` ONLY when its value contains no field, relation,
|
|
38
|
+
* column, or model NAME. If the value names anything in the schema, it is
|
|
39
|
+
* `'prisma'`: a name-translating consumer has to walk it by hand.
|
|
40
|
+
*
|
|
41
|
+
* @module
|
|
42
|
+
*/
|
|
43
|
+
import type { AggregateArgs, CountArgs, CreateArgs, CreateManyArgs, DeleteArgs, DeleteManyArgs, FindManyArgs, FindManyStreamArgs, FindUniqueArgs, GroupByArgs, UpdateArgs, UpdateManyArgs, UpsertArgs } from './types.js';
|
|
44
|
+
/**
|
|
45
|
+
* How a name-translating consumer (today: `turbine-orm/prisma-compat`) must
|
|
46
|
+
* handle one key of a turbine query-arg interface.
|
|
47
|
+
*
|
|
48
|
+
* - `'prisma'`, the key is a Prisma concept too, or its VALUE carries names
|
|
49
|
+
* that live in the caller's naming space. Translated by hand; NEVER copied
|
|
50
|
+
* verbatim.
|
|
51
|
+
* - `'native'`, turbine-only and its value is opaque to naming (a boolean, a
|
|
52
|
+
* number, a list of table names). Copied through untouched.
|
|
53
|
+
* - `'nativeAlias'`, the turbine SPELLING of a concept the caller's surface
|
|
54
|
+
* already has under another name (`with`/`limit`/`offset` vs
|
|
55
|
+
* `include`/`take`/`skip`). Refused, because forwarding it would collide with
|
|
56
|
+
* the translated key and would carry turbine relation names into a call
|
|
57
|
+
* written in the caller's names. The diagnostic names the right key instead.
|
|
58
|
+
* - `'internal'`, not reachable through the compat surface at all
|
|
59
|
+
* (`batchSize` belongs to a streaming method compat does not expose), so it
|
|
60
|
+
* is not part of any known set and passing it is reported as unknown.
|
|
61
|
+
*/
|
|
62
|
+
export type OptionKind = 'prisma' | 'native' | 'nativeAlias' | 'internal';
|
|
63
|
+
/**
|
|
64
|
+
* The generic parameter the tables are instantiated at. `keyof FindManyArgs<T>`
|
|
65
|
+
* is the literal union of the DECLARED key names regardless of `T`, so a
|
|
66
|
+
* neutral row type keeps the tables stable and free of entity coupling.
|
|
67
|
+
*/
|
|
68
|
+
type Row = Record<string, unknown>;
|
|
69
|
+
/** One option table: every declared key of one arg interface, classified. */
|
|
70
|
+
export type OptionTable<A> = Readonly<Record<keyof A, OptionKind>>;
|
|
71
|
+
export declare const FIND_UNIQUE_OPTIONS: OptionTable<FindUniqueArgs<Row>>;
|
|
72
|
+
export declare const FIND_MANY_OPTIONS: OptionTable<FindManyArgs<Row>>;
|
|
73
|
+
export declare const FIND_MANY_STREAM_OPTIONS: OptionTable<FindManyStreamArgs<Row>>;
|
|
74
|
+
export declare const CREATE_OPTIONS: OptionTable<CreateArgs<Row>>;
|
|
75
|
+
export declare const CREATE_MANY_OPTIONS: OptionTable<CreateManyArgs<Row>>;
|
|
76
|
+
export declare const UPDATE_OPTIONS: OptionTable<UpdateArgs<Row>>;
|
|
77
|
+
export declare const UPDATE_MANY_OPTIONS: OptionTable<UpdateManyArgs<Row>>;
|
|
78
|
+
export declare const DELETE_OPTIONS: OptionTable<DeleteArgs<Row>>;
|
|
79
|
+
export declare const DELETE_MANY_OPTIONS: OptionTable<DeleteManyArgs<Row>>;
|
|
80
|
+
export declare const UPSERT_OPTIONS: OptionTable<UpsertArgs<Row>>;
|
|
81
|
+
export declare const COUNT_OPTIONS: OptionTable<CountArgs<Row>>;
|
|
82
|
+
export declare const AGGREGATE_OPTIONS: OptionTable<AggregateArgs<Row>>;
|
|
83
|
+
export declare const GROUP_BY_OPTIONS: OptionTable<GroupByArgs<Row>>;
|
|
84
|
+
/**
|
|
85
|
+
* Every table, so a test can assert the set is complete and well-formed without
|
|
86
|
+
* naming each one (a table stubbed out during a refactor shows up here).
|
|
87
|
+
*/
|
|
88
|
+
export declare const ALL_OPTION_TABLES: Readonly<Record<string, Readonly<Record<string, OptionKind>>>>;
|
|
89
|
+
/**
|
|
90
|
+
* Copy every `'native'` key present on `src` onto `dst`.
|
|
91
|
+
*
|
|
92
|
+
* Iterates `src` (a small caller-supplied object) rather than the table, so the
|
|
93
|
+
* cost is proportional to what was actually passed. `undefined` values are
|
|
94
|
+
* skipped: `{ ...maybeOpts }` routinely materializes keys with no value, and
|
|
95
|
+
* writing `undefined` through would be indistinguishable from passing it.
|
|
96
|
+
*/
|
|
97
|
+
export declare function applyNativeOptions(table: Readonly<Record<string, OptionKind>>, src: Record<string, unknown>, dst: Record<string, unknown>): void;
|
|
98
|
+
/** The keys of `table` with the given kind, as a set. */
|
|
99
|
+
export declare function optionKeysOfKind(table: Readonly<Record<string, OptionKind>>, ...kinds: OptionKind[]): string[];
|
|
100
|
+
export {};
|