turbine-orm 0.76.0 → 0.77.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/cli/index.js +2 -2
- package/dist/cjs/cli/migrate.js +8 -8
- package/dist/cjs/cli/studio.js +6 -3
- package/dist/cjs/client.js +10 -10
- package/dist/cjs/dialect.js +1 -1
- package/dist/cjs/errors.d.ts +2 -2
- package/dist/cjs/errors.js +21 -25
- package/dist/cjs/generate.js +1 -1
- package/dist/cjs/introspect.js +5 -5
- package/dist/cjs/mssql.js +12 -12
- package/dist/cjs/mysql.js +5 -5
- package/dist/cjs/nested-write.js +31 -31
- package/dist/cjs/observe.js +1 -1
- package/dist/cjs/pipeline-submittable.js +5 -1
- package/dist/cjs/pipeline.js +8 -0
- package/dist/cjs/powdb-introspect.d.ts +1 -1
- package/dist/cjs/powdb-introspect.js +4 -4
- package/dist/cjs/powdb-shared.d.ts +348 -0
- package/dist/cjs/powdb-shared.js +587 -0
- package/dist/cjs/powdb.d.ts +12 -299
- package/dist/cjs/powdb.js +106 -567
- package/dist/cjs/powql.d.ts +1 -1
- package/dist/cjs/powql.js +89 -89
- package/dist/cjs/prisma-compat.js +16 -16
- package/dist/cjs/query/aggregates.js +19 -20
- package/dist/cjs/query/batched-loader.js +8 -8
- package/dist/cjs/query/builder.js +8 -8
- package/dist/cjs/query/compound-unique.js +2 -2
- package/dist/cjs/query/filters.js +1 -1
- package/dist/cjs/query/relations.js +60 -48
- package/dist/cjs/query/types.js +4 -4
- package/dist/cjs/query/utils.js +5 -5
- package/dist/cjs/query/warn-registry.d.ts +7 -0
- package/dist/cjs/query/warn-registry.js +7 -0
- package/dist/cjs/query/where-compile.js +1 -1
- package/dist/cjs/query/where.js +30 -31
- package/dist/cjs/query/writes.js +7 -7
- package/dist/cjs/realtime.js +4 -4
- package/dist/cjs/schema-metadata.js +1 -1
- package/dist/cjs/schema-sql.js +3 -3
- package/dist/cjs/seed.js +1 -1
- package/dist/cjs/sqlite.js +7 -7
- package/dist/cjs/typed-sql.js +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/migrate.js +8 -8
- package/dist/cli/studio.js +6 -3
- package/dist/client.js +10 -10
- package/dist/dialect.js +1 -1
- package/dist/errors.d.ts +2 -2
- package/dist/errors.js +21 -25
- package/dist/generate.js +1 -1
- package/dist/introspect.js +5 -5
- package/dist/mssql.js +12 -12
- package/dist/mysql.js +5 -5
- package/dist/nested-write.js +31 -31
- package/dist/observe.js +1 -1
- package/dist/pipeline-submittable.js +6 -2
- package/dist/pipeline.js +9 -1
- package/dist/powdb-introspect.d.ts +1 -1
- package/dist/powdb-introspect.js +2 -2
- package/dist/powdb-shared.d.ts +348 -0
- package/dist/powdb-shared.js +570 -0
- package/dist/powdb.d.ts +12 -299
- package/dist/powdb.js +71 -534
- package/dist/powql.d.ts +1 -1
- package/dist/powql.js +43 -43
- package/dist/prisma-compat.js +16 -16
- package/dist/query/aggregates.js +19 -20
- package/dist/query/batched-loader.js +8 -8
- package/dist/query/builder.js +8 -8
- package/dist/query/compound-unique.js +2 -2
- package/dist/query/filters.js +1 -1
- package/dist/query/relations.js +60 -48
- package/dist/query/types.js +4 -4
- package/dist/query/utils.js +5 -5
- package/dist/query/warn-registry.d.ts +7 -0
- package/dist/query/warn-registry.js +7 -0
- package/dist/query/where-compile.js +1 -1
- package/dist/query/where.js +30 -31
- package/dist/query/writes.js +7 -7
- package/dist/realtime.js +4 -4
- package/dist/schema-metadata.js +1 -1
- package/dist/schema-sql.js +3 -3
- package/dist/seed.js +1 -1
- package/dist/sqlite.js +7 -7
- package/dist/typed-sql.js +1 -1
- package/package.json +15 -7
|
@@ -361,7 +361,7 @@ function assertTranslateDepth(depth, clause) {
|
|
|
361
361
|
// The two clauses core also walks raise core's own error, verbatim.
|
|
362
362
|
if (clause === 'where' || clause === 'having')
|
|
363
363
|
(0, where_compile_js_1.assertWhereDepth)(depth, clause);
|
|
364
|
-
throw new errors_js_1.ValidationError(
|
|
364
|
+
throw new errors_js_1.ValidationError(`\`${clause}\` nests more than ${where_compile_js_1.MAX_WHERE_DEPTH} levels deep. That is far past anything a real ` +
|
|
365
365
|
`query needs, and an unbounded walk over caller-supplied nesting is a stack-overflow surface, so it is ` +
|
|
366
366
|
`refused. If this is a generated argument, flatten it: a single array of N entries is one level, not N.`);
|
|
367
367
|
}
|
|
@@ -752,7 +752,7 @@ function translateOmit(ctx, mm, omit) {
|
|
|
752
752
|
if (val === false || val == null)
|
|
753
753
|
continue;
|
|
754
754
|
if (mm.relations[key]) {
|
|
755
|
-
throw new errors_js_1.ValidationError(`
|
|
755
|
+
throw new errors_js_1.ValidationError(`prisma-compat: \`omit\` on model "${modelName(ctx, mm)}" takes scalar fields, but "${key}" ` +
|
|
756
756
|
'is a relation. Leave the relation out of `include` instead.');
|
|
757
757
|
}
|
|
758
758
|
out[renameField(mm, key)] = true;
|
|
@@ -778,10 +778,10 @@ function translateProjection(ctx, mm, args, depth = 0) {
|
|
|
778
778
|
const select = args.select;
|
|
779
779
|
const omitArg = args.omit;
|
|
780
780
|
if (include && select) {
|
|
781
|
-
throw new errors_js_1.ValidationError('
|
|
781
|
+
throw new errors_js_1.ValidationError('prisma-compat: `include` and `select` are mutually exclusive.');
|
|
782
782
|
}
|
|
783
783
|
if (select && omitArg) {
|
|
784
|
-
throw new errors_js_1.ValidationError('
|
|
784
|
+
throw new errors_js_1.ValidationError('prisma-compat: `select` and `omit` are mutually exclusive. ' +
|
|
785
785
|
'A `select` already lists exactly the fields you want.');
|
|
786
786
|
}
|
|
787
787
|
const omit = omitArg ? translateOmit(ctx, mm, omitArg) : undefined;
|
|
@@ -798,7 +798,7 @@ function translateProjection(ctx, mm, args, depth = 0) {
|
|
|
798
798
|
}
|
|
799
799
|
const rel = mm.relations[key];
|
|
800
800
|
if (!rel) {
|
|
801
|
-
throw new errors_js_1.ValidationError(`
|
|
801
|
+
throw new errors_js_1.ValidationError(`prisma-compat: unknown relation "${key}" in include on model "${modelName(ctx, mm)}".`);
|
|
802
802
|
}
|
|
803
803
|
withClause[rel.name] = translateWithOption(ctx, mm, rel.name, val, depth + 1);
|
|
804
804
|
hasWith = true;
|
|
@@ -853,7 +853,7 @@ function assertWriteProjectionField(ctx, mm, op, clause, key) {
|
|
|
853
853
|
return;
|
|
854
854
|
const known = Object.keys(mm.fields);
|
|
855
855
|
const suggestion = (0, utils_js_1.suggestKey)(key, new Set(known));
|
|
856
|
-
throw new errors_js_1.ValidationError(`
|
|
856
|
+
throw new errors_js_1.ValidationError(`prisma-compat: unknown field "${key}" in \`${clause}\` on ${modelName(ctx, mm)}.${op}().` +
|
|
857
857
|
(suggestion ? ` Did you mean "${suggestion}"?` : '') +
|
|
858
858
|
` Known fields: ${known.join(', ') || '(none)'}.`);
|
|
859
859
|
}
|
|
@@ -885,10 +885,10 @@ function resolveWriteProjection(ctx, mm, op, args) {
|
|
|
885
885
|
const select = args.select;
|
|
886
886
|
const omitArg = args.omit;
|
|
887
887
|
if (include && select) {
|
|
888
|
-
throw new errors_js_1.ValidationError('
|
|
888
|
+
throw new errors_js_1.ValidationError('prisma-compat: `include` and `select` are mutually exclusive.');
|
|
889
889
|
}
|
|
890
890
|
if (select && omitArg) {
|
|
891
|
-
throw new errors_js_1.ValidationError('
|
|
891
|
+
throw new errors_js_1.ValidationError('prisma-compat: `select` and `omit` are mutually exclusive. ' +
|
|
892
892
|
'A `select` already lists exactly the fields you want.');
|
|
893
893
|
}
|
|
894
894
|
if (include) {
|
|
@@ -922,7 +922,7 @@ function resolveWriteProjection(ctx, mm, op, args) {
|
|
|
922
922
|
if (val === false || val == null)
|
|
923
923
|
continue;
|
|
924
924
|
if (mm.relations[key]) {
|
|
925
|
-
throw new errors_js_1.ValidationError(`
|
|
925
|
+
throw new errors_js_1.ValidationError(`prisma-compat: \`omit\` on model "${modelName(ctx, mm)}" takes scalar fields, but "${key}" ` +
|
|
926
926
|
'is a relation.');
|
|
927
927
|
}
|
|
928
928
|
assertWriteProjectionField(ctx, mm, op, 'omit', key);
|
|
@@ -1805,7 +1805,7 @@ function makeDelegate(ctx, mm, getQI, runInTx) {
|
|
|
1805
1805
|
};
|
|
1806
1806
|
const requireWhere = (args, op) => {
|
|
1807
1807
|
if (!args || args.where === undefined) {
|
|
1808
|
-
throw new errors_js_1.ValidationError(`
|
|
1808
|
+
throw new errors_js_1.ValidationError(`prisma-compat: ${op} on "${modelName(ctx, mm)}" requires a \`where\`.`);
|
|
1809
1809
|
}
|
|
1810
1810
|
return args;
|
|
1811
1811
|
};
|
|
@@ -1971,7 +1971,7 @@ function makeDelegate(ctx, mm, getQI, runInTx) {
|
|
|
1971
1971
|
function poolOf(db) {
|
|
1972
1972
|
const pool = db.pool;
|
|
1973
1973
|
if (!pool)
|
|
1974
|
-
throw new errors_js_1.ValidationError('
|
|
1974
|
+
throw new errors_js_1.ValidationError('prisma-compat: raw SQL needs a TurbineClient with an active pool.');
|
|
1975
1975
|
return pool;
|
|
1976
1976
|
}
|
|
1977
1977
|
function placeholderOf(db) {
|
|
@@ -2164,7 +2164,7 @@ const EMPTY_EXTENSIONS = { client: {}, model: new Map(), allModels: {} };
|
|
|
2164
2164
|
*/
|
|
2165
2165
|
function applyExtension(prev, ext, modelKeys, clientKeys) {
|
|
2166
2166
|
if (typeof ext !== 'object' || ext === null) {
|
|
2167
|
-
throw new errors_js_1.ValidationError('
|
|
2167
|
+
throw new errors_js_1.ValidationError('prisma-compat: $extends expects an extension object or a function ' +
|
|
2168
2168
|
`(Prisma.defineExtension callback form), received ${ext === null ? 'null' : typeof ext}.`);
|
|
2169
2169
|
}
|
|
2170
2170
|
for (const [component, value] of Object.entries(ext)) {
|
|
@@ -2182,7 +2182,7 @@ function applyExtension(prev, ext, modelKeys, clientKeys) {
|
|
|
2182
2182
|
const client = { ...prev.client };
|
|
2183
2183
|
for (const [name, member] of Object.entries(ext.client ?? {})) {
|
|
2184
2184
|
if (clientKeys.has(name)) {
|
|
2185
|
-
throw new errors_js_1.ValidationError(`
|
|
2185
|
+
throw new errors_js_1.ValidationError(`prisma-compat: $extends \`client\` member "${name}" would shadow an existing client ` +
|
|
2186
2186
|
'member (a model delegate or a client-level method). Rename it.');
|
|
2187
2187
|
}
|
|
2188
2188
|
client[name] = member;
|
|
@@ -2196,7 +2196,7 @@ function applyExtension(prev, ext, modelKeys, clientKeys) {
|
|
|
2196
2196
|
}
|
|
2197
2197
|
const canonical = modelKeys.get(key);
|
|
2198
2198
|
if (!canonical) {
|
|
2199
|
-
throw new errors_js_1.ValidationError(`
|
|
2199
|
+
throw new errors_js_1.ValidationError(`prisma-compat: $extends \`model\` key "${key}" is not a model on this client. ` +
|
|
2200
2200
|
`Known models: ${[...new Set(modelKeys.values())].sort().join(', ') || '(none)'}.`);
|
|
2201
2201
|
}
|
|
2202
2202
|
model.set(canonical, { ...(model.get(canonical) ?? {}), ...members });
|
|
@@ -2302,7 +2302,7 @@ function createPrismaCompatClient(client, map, options = {}) {
|
|
|
2302
2302
|
*/
|
|
2303
2303
|
const txRunRaw = (tx) => async (text, params) => {
|
|
2304
2304
|
if (typeof tx.rawQuery !== 'function') {
|
|
2305
|
-
throw decorate(new errors_js_1.ValidationError('
|
|
2305
|
+
throw decorate(new errors_js_1.ValidationError('prisma-compat: raw SQL inside $transaction needs a transaction client that can execute it ' +
|
|
2306
2306
|
'(core TransactionClient.rawQuery). Refusing to run the statement on a pool connection, which would ' +
|
|
2307
2307
|
'silently place it outside the transaction.'), ctx.options.prismaErrorCodes);
|
|
2308
2308
|
}
|
|
@@ -2347,7 +2347,7 @@ function createPrismaCompatClient(client, map, options = {}) {
|
|
|
2347
2347
|
const batchables = arg.map((p, i) => {
|
|
2348
2348
|
const b = batchableOf(p);
|
|
2349
2349
|
if (!b) {
|
|
2350
|
-
throw new errors_js_1.ValidationError(`
|
|
2350
|
+
throw new errors_js_1.ValidationError(`prisma-compat: $transaction([...]) item ${i} is not a lazy model call. Pass un-awaited delegate calls (e.g. prisma.User.create(...)).`);
|
|
2351
2351
|
}
|
|
2352
2352
|
return b;
|
|
2353
2353
|
});
|
|
@@ -80,7 +80,7 @@ function assertAggregatePiiOptIn(table, meta, field, column, usage, includePii)
|
|
|
80
80
|
const colMeta = meta.columns.find((c) => c.name === column);
|
|
81
81
|
if (!colMeta?.pii)
|
|
82
82
|
return;
|
|
83
|
-
throw new errors_js_1.ValidationError(
|
|
83
|
+
throw new errors_js_1.ValidationError(`${usage} on column "${field}" of table "${table}" is refused: that column is ` +
|
|
84
84
|
'PII-tagged (`pii: true`), and this aggregate returns its stored values, which are excluded ' +
|
|
85
85
|
'from every default projection. Pass `includePii: UNSAFE` on this call to opt in ' +
|
|
86
86
|
"(import { UNSAFE } from 'turbine-orm'). " +
|
|
@@ -144,7 +144,7 @@ function buildGroupBy(qi, args) {
|
|
|
144
144
|
const usedResultKeys = new Set();
|
|
145
145
|
const claimResultKey = (key, what) => {
|
|
146
146
|
if (key === '_count' || usedResultKeys.has(key)) {
|
|
147
|
-
throw new errors_js_1.ValidationError(`
|
|
147
|
+
throw new errors_js_1.ValidationError(`groupBy output name "${key}" (${what}) collides with another output column on table ` +
|
|
148
148
|
`"${qi.table}": set an explicit \`alias\` (or rename the aggregate key) to disambiguate.`);
|
|
149
149
|
}
|
|
150
150
|
usedResultKeys.add(key);
|
|
@@ -267,7 +267,7 @@ function buildGroupBy(qi, args) {
|
|
|
267
267
|
}
|
|
268
268
|
const alwaysNumeric = aggKey === '_sum' || aggKey === '_avg';
|
|
269
269
|
if (alwaysNumeric && target.type === 'text') {
|
|
270
|
-
throw new errors_js_1.ValidationError(`
|
|
270
|
+
throw new errors_js_1.ValidationError(`groupBy ${aggKey} target "${key}" on table "${qi.table}": ` +
|
|
271
271
|
`${aggKey} over a JSON path is always numeric: remove \`type: 'text'\`.`);
|
|
272
272
|
}
|
|
273
273
|
const numeric = alwaysNumeric || target.type === 'numeric';
|
|
@@ -489,7 +489,7 @@ function buildGroupByOrderBy(qi, orderBy, byOrderExprs, aggOrderExprs) {
|
|
|
489
489
|
if (key === '_count') {
|
|
490
490
|
const expr = aggOrderExprs.get('_count');
|
|
491
491
|
if (!expr) {
|
|
492
|
-
throw new errors_js_1.ValidationError(`
|
|
492
|
+
throw new errors_js_1.ValidationError(`Cannot order groupBy by "_count" on table "${qi.table}": _count is not selected. ` +
|
|
493
493
|
`Orderable keys: ${validKeys()}.`);
|
|
494
494
|
}
|
|
495
495
|
// Refuse a direction that is neither asc nor desc BEFORE normalizeOrderBy,
|
|
@@ -500,7 +500,7 @@ function buildGroupByOrderBy(qi, orderBy, byOrderExprs, aggOrderExprs) {
|
|
|
500
500
|
}
|
|
501
501
|
// `_sum` / `_avg` / `_min` / `_max`: an object of field → direction/spec.
|
|
502
502
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
503
|
-
throw new errors_js_1.ValidationError(`
|
|
503
|
+
throw new errors_js_1.ValidationError(`Invalid groupBy orderBy for "${key}" on table "${qi.table}": ` +
|
|
504
504
|
`expected a field map like { ${key}: { amount: 'desc' } }.`);
|
|
505
505
|
}
|
|
506
506
|
for (const [field, dirSpec] of Object.entries(value)) {
|
|
@@ -512,7 +512,7 @@ function buildGroupByOrderBy(qi, orderBy, byOrderExprs, aggOrderExprs) {
|
|
|
512
512
|
const expr = aggOrderExprs.get(`${key}:${field}`) ??
|
|
513
513
|
(canonical === undefined ? undefined : aggOrderExprs.get(`${key}:${canonical}`));
|
|
514
514
|
if (!expr) {
|
|
515
|
-
throw new errors_js_1.ValidationError(`
|
|
515
|
+
throw new errors_js_1.ValidationError(`Cannot order groupBy by "${key}.${field}" on table "${qi.table}": ` +
|
|
516
516
|
`that aggregate is not requested in this call. Orderable keys: ${validKeys()}.`);
|
|
517
517
|
}
|
|
518
518
|
(0, types_js_1.assertOrderDirection)(dirSpec, `groupBy orderBy "${key}.${field}" on table "${qi.table}"`);
|
|
@@ -523,8 +523,7 @@ function buildGroupByOrderBy(qi, orderBy, byOrderExprs, aggOrderExprs) {
|
|
|
523
523
|
// Plain by-field name or JSON group-key alias.
|
|
524
524
|
const expr = lookupGroupKey(qi, byOrderExprs, key);
|
|
525
525
|
if (!expr) {
|
|
526
|
-
throw new errors_js_1.ValidationError(`
|
|
527
|
-
`Orderable keys: ${validKeys()}.`);
|
|
526
|
+
throw new errors_js_1.ValidationError(`Unknown field "${key}" in groupBy orderBy on table "${qi.table}". ` + `Orderable keys: ${validKeys()}.`);
|
|
528
527
|
}
|
|
529
528
|
(0, types_js_1.assertOrderDirection)(value, `groupBy orderBy "${key}" on table "${qi.table}"`);
|
|
530
529
|
pushOrderTerm(expr, key, value);
|
|
@@ -538,18 +537,18 @@ function buildGroupByOrderBy(qi, orderBy, byOrderExprs, aggOrderExprs) {
|
|
|
538
537
|
*/
|
|
539
538
|
function resolveJsonPathTarget(qi, context, field, path) {
|
|
540
539
|
if (typeof field !== 'string') {
|
|
541
|
-
throw new errors_js_1.ValidationError(`
|
|
540
|
+
throw new errors_js_1.ValidationError(`groupBy ${context} on table "${qi.table}" requires a string \`field\`.`);
|
|
542
541
|
}
|
|
543
542
|
const col = qi.toColumn(field);
|
|
544
543
|
if (!Array.isArray(path) ||
|
|
545
544
|
path.length === 0 ||
|
|
546
545
|
path.some((el) => typeof el !== 'string' && !(typeof el === 'number' && Number.isFinite(el)))) {
|
|
547
|
-
throw new errors_js_1.ValidationError(`
|
|
546
|
+
throw new errors_js_1.ValidationError(`groupBy ${context} on "${field}" (table "${qi.table}") requires a non-empty \`path\` ` +
|
|
548
547
|
`array of keys/indexes (e.g. { field: '${field}', path: ['category'] }).`);
|
|
549
548
|
}
|
|
550
549
|
const colType = whereMod.pgTypeForColumn(qi, qi.tableMeta, col);
|
|
551
550
|
if (!whereMod.isJsonColumnType(qi, colType)) {
|
|
552
|
-
throw new errors_js_1.ValidationError(`
|
|
551
|
+
throw new errors_js_1.ValidationError(`groupBy ${context} on "${field}": column "${col}" on table "${qi.table}" is not a JSON ` +
|
|
553
552
|
`column (actual type: ${colType}).`);
|
|
554
553
|
}
|
|
555
554
|
return col;
|
|
@@ -573,11 +572,11 @@ function buildDistinctOnSource(qi, distinctOn, whereSql, params) {
|
|
|
573
572
|
throw new errors_js_1.UnsupportedFeatureError('DISTINCT ON row source (groupBy distinctOn)', qi.dialect.name, 'groupBy({ distinctOn }) requires PostgreSQL: SELECT DISTINCT ON is not portable.');
|
|
574
573
|
}
|
|
575
574
|
if (!Array.isArray(distinctOn.columns) || distinctOn.columns.length === 0) {
|
|
576
|
-
throw new errors_js_1.ValidationError(`
|
|
575
|
+
throw new errors_js_1.ValidationError(`groupBy distinctOn on table "${qi.table}" requires a non-empty \`columns\` array.`);
|
|
577
576
|
}
|
|
578
577
|
const orderEntries = Object.entries(distinctOn.orderBy ?? {});
|
|
579
578
|
if (orderEntries.length === 0) {
|
|
580
|
-
throw new errors_js_1.ValidationError(`
|
|
579
|
+
throw new errors_js_1.ValidationError(`groupBy distinctOn on table "${qi.table}" requires \`orderBy\` to pick ONE row per ` +
|
|
581
580
|
"column combination deterministically (e.g. orderBy: { createdAt: 'desc' }).");
|
|
582
581
|
}
|
|
583
582
|
// A repeated DISTINCT ON column is a no-op, so drop it rather than emit it
|
|
@@ -597,7 +596,7 @@ function buildDistinctOnSource(qi, distinctOn, whereSql, params) {
|
|
|
597
596
|
continue;
|
|
598
597
|
}
|
|
599
598
|
if ((0, filters_js_1.isVectorOrderBy)(value) || qi.isRelationOrderByValue(value)) {
|
|
600
|
-
throw new errors_js_1.ValidationError(`
|
|
599
|
+
throw new errors_js_1.ValidationError(`groupBy distinctOn.orderBy on "${key}" (table "${qi.table}") supports plain columns, ` +
|
|
601
600
|
'sort specs, and JSON-path orderings only.');
|
|
602
601
|
}
|
|
603
602
|
const col = qi.resolveOrderByColumn(qi.table, qi.tableMeta, key);
|
|
@@ -711,7 +710,7 @@ function splitHavingField(qi, field, value) {
|
|
|
711
710
|
aggEntries.push({ key: k, fn, filter: v });
|
|
712
711
|
}
|
|
713
712
|
else if (k.startsWith('_')) {
|
|
714
|
-
throw new errors_js_1.ValidationError(`
|
|
713
|
+
throw new errors_js_1.ValidationError(`Unknown aggregate "${k}" in having for field "${field}" on table "${qi.table}". ` +
|
|
715
714
|
`Supported: ${Object.keys(HAVING_AGGREGATE_FNS).join(', ')}.`);
|
|
716
715
|
}
|
|
717
716
|
else {
|
|
@@ -747,7 +746,7 @@ function buildHavingCombinator(qi, key, value, params, jsonAggExprs, groupKeys,
|
|
|
747
746
|
const parts = [];
|
|
748
747
|
for (const condition of conditions) {
|
|
749
748
|
if (!(0, filters_js_1.isUnmatchedPlainObject)(condition)) {
|
|
750
|
-
throw new errors_js_1.ValidationError(`
|
|
749
|
+
throw new errors_js_1.ValidationError(`Invalid having "${key}" on table "${qi.table}": expected ` +
|
|
751
750
|
`${key === 'OR' ? 'an array of having objects' : 'a having object (or an array of them)'}.`);
|
|
752
751
|
}
|
|
753
752
|
const sub = buildHavingClauses(qi, condition, params, jsonAggExprs, groupKeys, depth + 1);
|
|
@@ -788,7 +787,7 @@ function buildHavingScalarClauses(qi, field, value, params, groupKeys) {
|
|
|
788
787
|
const ref = groupKeys ? lookupGroupKey(qi, groupKeys, field) : undefined;
|
|
789
788
|
if (!ref) {
|
|
790
789
|
const known = groupKeys ? [...groupKeys.keys()] : [];
|
|
791
|
-
throw new errors_js_1.ValidationError(`
|
|
790
|
+
throw new errors_js_1.ValidationError(`having on "${field}" (table "${qi.table}") filters the grouped value itself, but ` +
|
|
792
791
|
`"${field}" is not one of the \`by\` group keys [${known.join(', ') || 'none'}]. A predicate on a ` +
|
|
793
792
|
'non-grouped column cannot go in HAVING: move it to `where` (it filters rows, not groups), add ' +
|
|
794
793
|
`"${field}" to \`by\`, or filter an aggregate of it instead (e.g. { ${field}: { _count: { gt: 0 } } }).`);
|
|
@@ -808,7 +807,7 @@ function buildHavingScalarClauses(qi, field, value, params, groupKeys) {
|
|
|
808
807
|
clauses.push(...whereMod.buildOperatorClauses(qi, ref.expr, value, params));
|
|
809
808
|
}
|
|
810
809
|
else if ((0, filters_js_1.isUnmatchedPlainObject)(value)) {
|
|
811
|
-
throw new errors_js_1.ValidationError(`
|
|
810
|
+
throw new errors_js_1.ValidationError(`Unknown operator${Object.keys(value).length > 1 ? 's' : ''} ` +
|
|
812
811
|
`${Object.keys(value)
|
|
813
812
|
.map((k) => `"${k}"`)
|
|
814
813
|
.join(', ')} on ${ref.label} in having for table "${qi.table}".`);
|
|
@@ -828,7 +827,7 @@ function buildHavingScalarClauses(qi, field, value, params, groupKeys) {
|
|
|
828
827
|
*/
|
|
829
828
|
function buildHavingNumericClauses(qi, expr, filter, params) {
|
|
830
829
|
if (filter === null) {
|
|
831
|
-
throw new errors_js_1.ValidationError(`
|
|
830
|
+
throw new errors_js_1.ValidationError(`Invalid having filter on "${expr}" for table "${qi.table}": expected a value or operator object.`);
|
|
832
831
|
}
|
|
833
832
|
// Bare value (number, string, boolean, Date, …) → equality.
|
|
834
833
|
if (typeof filter !== 'object' || filter instanceof Date) {
|
|
@@ -839,7 +838,7 @@ function buildHavingNumericClauses(qi, expr, filter, params) {
|
|
|
839
838
|
const allowedKeys = new Set(['equals', 'not', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn']);
|
|
840
839
|
for (const k of Object.keys(op)) {
|
|
841
840
|
if (!allowedKeys.has(k)) {
|
|
842
|
-
throw new errors_js_1.ValidationError(`
|
|
841
|
+
throw new errors_js_1.ValidationError(`Unknown having operator "${k}" on "${expr}" for table "${qi.table}". ` +
|
|
843
842
|
`Supported: ${[...allowedKeys].join(', ')}.`);
|
|
844
843
|
}
|
|
845
844
|
}
|
|
@@ -428,11 +428,11 @@ function resolveCountRelations(parentMeta, countSpec) {
|
|
|
428
428
|
continue;
|
|
429
429
|
const rel = (0, utils_js_1.ownLookup)(parentMeta.relations, relName);
|
|
430
430
|
if (!rel) {
|
|
431
|
-
throw new errors_js_1.RelationError(`
|
|
431
|
+
throw new errors_js_1.RelationError(`Unknown relation "${relName}" in _count on table "${parentMeta.name}". ` +
|
|
432
432
|
(0, utils_js_1.availableClause)(Object.keys(parentMeta.relations), 'It has no relations.'));
|
|
433
433
|
}
|
|
434
434
|
if (!isToMany(rel)) {
|
|
435
|
-
throw new errors_js_1.ValidationError(`
|
|
435
|
+
throw new errors_js_1.ValidationError(`_count is only supported for to-many relations; "${relName}" on ` +
|
|
436
436
|
`"${parentMeta.name}" is a to-one relation.`);
|
|
437
437
|
}
|
|
438
438
|
out.push(rel);
|
|
@@ -462,7 +462,7 @@ function rejectNestedPickOrder(withClause) {
|
|
|
462
462
|
if (options.orderBy) {
|
|
463
463
|
for (const [key, value] of Object.entries(options.orderBy)) {
|
|
464
464
|
if ((0, filters_js_1.isRelationPickOrderBy)(value)) {
|
|
465
|
-
throw new errors_js_1.ValidationError(`
|
|
465
|
+
throw new errors_js_1.ValidationError(`Pick-row ordering on relation "${key}" is only supported in a top-level ` +
|
|
466
466
|
'findMany orderBy: nested `with` orderBy does not support it.');
|
|
467
467
|
}
|
|
468
468
|
}
|
|
@@ -504,7 +504,7 @@ async function loadRelationsBatched(ctx, parents, withClause, timeout, depth = 0
|
|
|
504
504
|
// RelationError (E005), NOT ValidationError: the join strategy throws
|
|
505
505
|
// E005 for this exact shape (relations.ts), and under 'auto' the two
|
|
506
506
|
// must refuse identically or the error CODE depends on table size.
|
|
507
|
-
throw new errors_js_1.RelationError(`
|
|
507
|
+
throw new errors_js_1.RelationError(`Unknown relation "${relName}" on table "${ctx.parentMeta.name}". ` +
|
|
508
508
|
(0, utils_js_1.availableClause)(Object.keys(ctx.parentMeta.relations), 'It has no relations.'));
|
|
509
509
|
}
|
|
510
510
|
resolved.push({ relName, rel, options: spec === true ? {} : spec });
|
|
@@ -532,7 +532,7 @@ async function loadRelationsBatched(ctx, parents, withClause, timeout, depth = 0
|
|
|
532
532
|
// nested projections all learning it together, which is a feature release,
|
|
533
533
|
// not a line in a correctness fix. Until then both strategies say no.
|
|
534
534
|
if (hasCount && depth > 0) {
|
|
535
|
-
throw new errors_js_1.RelationError(`
|
|
535
|
+
throw new errors_js_1.RelationError(`Unknown relation "_count" on table "${ctx.parentMeta.name}". ` +
|
|
536
536
|
`${(0, utils_js_1.availableClause)(Object.keys(ctx.parentMeta.relations), 'It has no relations.')} ` +
|
|
537
537
|
'(`_count` is supported on the top-level `with` only, on every relationLoadStrategy.)');
|
|
538
538
|
}
|
|
@@ -814,7 +814,7 @@ function stripRankColumn(result) {
|
|
|
814
814
|
async function loadManyToMany(ctx, parents, rel, relName, options, timeout, depth, path) {
|
|
815
815
|
const through = rel.through;
|
|
816
816
|
if (!through) {
|
|
817
|
-
throw new errors_js_1.ValidationError(`
|
|
817
|
+
throw new errors_js_1.ValidationError(`manyToMany relation "${relName}" is missing its junction (\`through\`).`);
|
|
818
818
|
}
|
|
819
819
|
const sourceJ = (0, schema_js_1.normalizeKeyColumns)(through.sourceKey);
|
|
820
820
|
const targetJ = (0, schema_js_1.normalizeKeyColumns)(through.targetKey);
|
|
@@ -972,7 +972,7 @@ async function loadOneCount(ctx, parents, rel) {
|
|
|
972
972
|
if (rel.type === 'manyToMany') {
|
|
973
973
|
const through = rel.through;
|
|
974
974
|
if (!through) {
|
|
975
|
-
throw new errors_js_1.ValidationError(`
|
|
975
|
+
throw new errors_js_1.ValidationError(`manyToMany relation "${rel.name}" is missing its junction (\`through\`).`);
|
|
976
976
|
}
|
|
977
977
|
const sourceRef = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
|
|
978
978
|
const sourceJ = (0, schema_js_1.normalizeKeyColumns)(through.sourceKey);
|
|
@@ -1157,6 +1157,6 @@ function groupBy(rows, field) {
|
|
|
1157
1157
|
function requireTable(schema, table, relName) {
|
|
1158
1158
|
const meta = schema.tables[table];
|
|
1159
1159
|
if (!meta)
|
|
1160
|
-
throw new errors_js_1.RelationError(`
|
|
1160
|
+
throw new errors_js_1.RelationError(`Unknown relation target "${table}" (relation "${relName}").`);
|
|
1161
1161
|
return meta;
|
|
1162
1162
|
}
|
|
@@ -707,7 +707,7 @@ class QueryInterface {
|
|
|
707
707
|
this.schema = schema;
|
|
708
708
|
const meta = schema.tables[table];
|
|
709
709
|
if (!meta) {
|
|
710
|
-
throw new errors_js_1.ValidationError(`
|
|
710
|
+
throw new errors_js_1.ValidationError(`Unknown table "${table}". ${(0, utils_js_1.availableClause)(Object.keys(schema.tables), 'The schema has no tables.')}`);
|
|
711
711
|
}
|
|
712
712
|
this.tableMeta = meta;
|
|
713
713
|
this.middlewares = middlewares ?? [];
|
|
@@ -1008,7 +1008,7 @@ class QueryInterface {
|
|
|
1008
1008
|
paginationValue(value, arg) {
|
|
1009
1009
|
const n = Number(value);
|
|
1010
1010
|
if (!Number.isSafeInteger(n) || n < 0) {
|
|
1011
|
-
throw new errors_js_1.ValidationError(
|
|
1011
|
+
throw new errors_js_1.ValidationError(`${arg} on "${this.table}" must be a non-negative integer, received: ${String(value)}`);
|
|
1012
1012
|
}
|
|
1013
1013
|
return n;
|
|
1014
1014
|
}
|
|
@@ -1092,7 +1092,7 @@ class QueryInterface {
|
|
|
1092
1092
|
return this.currentJsonEncoding;
|
|
1093
1093
|
}
|
|
1094
1094
|
if (!JSON_ENCODINGS.includes(argEncoding)) {
|
|
1095
|
-
throw new errors_js_1.ValidationError(`
|
|
1095
|
+
throw new errors_js_1.ValidationError(`Invalid \`jsonEncoding\` on "${this.table}": ${JSON.stringify(argEncoding)}. ` +
|
|
1096
1096
|
`Expected ${JSON_ENCODINGS.map((e) => `'${e}'`).join(' or ')}.`);
|
|
1097
1097
|
}
|
|
1098
1098
|
this.currentJsonEncoding = argEncoding;
|
|
@@ -1920,7 +1920,7 @@ class QueryInterface {
|
|
|
1920
1920
|
if (!paramsOk) {
|
|
1921
1921
|
details.push(`cache-hit params and freshly-built params diverge (collected ${collectedParams.length}, built ${freshParams.length})`);
|
|
1922
1922
|
}
|
|
1923
|
-
const message = `
|
|
1923
|
+
const message = `SQL cache lockstep violation on ${op} (fingerprint "${cacheKey}"). ` +
|
|
1924
1924
|
`This is a Turbine internal invariant violation, please report it at ` +
|
|
1925
1925
|
`https://github.com/zvndev/turbine-orm/issues. The fingerprint, SQL-build, and ` +
|
|
1926
1926
|
`param-collect paths must enumerate where-clause keys identically.\n${details.join('\n')}`;
|
|
@@ -2014,7 +2014,7 @@ class QueryInterface {
|
|
|
2014
2014
|
'engine has no such cache to keep it out of. Remove the option, or set it only on PostgreSQL queries.');
|
|
2015
2015
|
}
|
|
2016
2016
|
if (this.options?.planCacheMode === 'force_generic_plan') {
|
|
2017
|
-
throw new errors_js_1.ValidationError('
|
|
2017
|
+
throw new errors_js_1.ValidationError('forceCustomPlan: true cannot be honoured on a client configured with ' +
|
|
2018
2018
|
"planCacheMode: 'force_generic_plan'. That setting is a connection parameter and it governs UNNAMED " +
|
|
2019
2019
|
'statements as well as named ones, so the mechanism this option uses (withholding the ' +
|
|
2020
2020
|
'prepared-statement name, so the driver re-parses the statement on every execution and it is planned ' +
|
|
@@ -2258,7 +2258,7 @@ class QueryInterface {
|
|
|
2258
2258
|
// optional filter" is its whole contract and Prisma's `findFirst` behaves
|
|
2259
2259
|
// the same way; ask for one row by identity with `findUnique`.
|
|
2260
2260
|
if (whereMod.userPredicateIsEmpty(this.ctx, (args.where ?? {}))) {
|
|
2261
|
-
throw new errors_js_1.ValidationError(`
|
|
2261
|
+
throw new errors_js_1.ValidationError(`findUnique on "${this.table}" refused: the \`where\` clause has no predicate, ` +
|
|
2262
2262
|
'so this would return an arbitrary row rather than a specific one. ' +
|
|
2263
2263
|
'A key whose value is `undefined` does not count, check that the value you are looking up is defined. ' +
|
|
2264
2264
|
'If you meant "any row matching an optional filter", use `findFirst`.');
|
|
@@ -2699,7 +2699,7 @@ class QueryInterface {
|
|
|
2699
2699
|
if (args?.distinct && args.distinct.length > 0 && args.orderBy) {
|
|
2700
2700
|
for (const [, d] of (0, filters_js_1.orderByEntries)(args.orderBy)) {
|
|
2701
2701
|
if (this.isRelationOrderByValue(d)) {
|
|
2702
|
-
throw new errors_js_1.ValidationError('
|
|
2702
|
+
throw new errors_js_1.ValidationError('`distinct` cannot be combined with relation orderBy (pick-row, `_count`, or ' +
|
|
2703
2703
|
'to-one relation ordering): the outer re-order cannot reference the parent table.');
|
|
2704
2704
|
}
|
|
2705
2705
|
}
|
|
@@ -2896,7 +2896,7 @@ class QueryInterface {
|
|
|
2896
2896
|
// the user's order (picks the right representative row), outer re-ordered
|
|
2897
2897
|
// by the user's order alone.
|
|
2898
2898
|
if ((0, filters_js_1.orderByEntries)(args.orderBy).some(([, d]) => (0, filters_js_1.isVectorOrderBy)(d))) {
|
|
2899
|
-
throw new errors_js_1.ValidationError('
|
|
2899
|
+
throw new errors_js_1.ValidationError('`distinct` cannot be combined with vector distance ordering.');
|
|
2900
2900
|
}
|
|
2901
2901
|
const userOrder = this.buildOrderBy(args.orderBy, freshParams);
|
|
2902
2902
|
const inner = `SELECT ${distinctPrefix}${selectClause} FROM ${qt}${tail} ORDER BY ${distinctCols
|
|
@@ -185,7 +185,7 @@ function expandCompoundUniqueWhere(meta, where) {
|
|
|
185
185
|
providedByColumn.size === expected.size &&
|
|
186
186
|
[...providedByColumn.keys()].every((c) => expected.has(c));
|
|
187
187
|
if (!exact) {
|
|
188
|
-
throw new errors_js_1.ValidationError(`
|
|
188
|
+
throw new errors_js_1.ValidationError(`Compound unique selector "${key}" on table "${meta.name}" must supply exactly ` +
|
|
189
189
|
`{ ${fields.join(', ')} }, received { ${provided.join(', ') || '(none)'} }.`);
|
|
190
190
|
}
|
|
191
191
|
result ??= { ...where };
|
|
@@ -242,7 +242,7 @@ function assertWhereIdentifiesOneRow(meta, table, where) {
|
|
|
242
242
|
? `Name a unique key (${keys.join(', ')}), or use \`findFirst\` if you meant "any row matching a filter".`
|
|
243
243
|
: `Table "${table}" declares no primary key and no unique constraint, so no \`where\` can identify one row ` +
|
|
244
244
|
'here. Use `findFirst` (add an `orderBy` to make which row it is deterministic).';
|
|
245
|
-
throw new errors_js_1.ValidationError(`
|
|
245
|
+
throw new errors_js_1.ValidationError(`findUnique on "${table}" refused: the \`where\` clause does not identify a single row, ` +
|
|
246
246
|
`so this would return an arbitrary one of the rows that match. ${advice}`);
|
|
247
247
|
}
|
|
248
248
|
function uniqueKeyNames(meta) {
|
|
@@ -165,7 +165,7 @@ function fingerprintOperatorShape(value) {
|
|
|
165
165
|
function assertBindableEqualsOperand(value, column) {
|
|
166
166
|
if (!isUnmatchedPlainObject(value))
|
|
167
167
|
return;
|
|
168
|
-
throw new errors_js_1.ValidationError(`
|
|
168
|
+
throw new errors_js_1.ValidationError(`Plain-object value for operator 'equals' on ${column}: ` +
|
|
169
169
|
`objects are only valid 'equals' values on JSON (json/jsonb) columns, ` +
|
|
170
170
|
`where 'equals' is the JSONB containment filter.`);
|
|
171
171
|
}
|