prisma-sql 1.71.0 → 1.73.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.
@@ -2323,7 +2323,7 @@ var require_package = __commonJS({
2323
2323
  "package.json"(exports$1, module) {
2324
2324
  module.exports = {
2325
2325
  name: "prisma-sql",
2326
- version: "1.71.0",
2326
+ version: "1.73.0",
2327
2327
  description: "Convert Prisma queries to optimized SQL with type safety. 2-7x faster than Prisma Client.",
2328
2328
  main: "dist/index.cjs",
2329
2329
  module: "dist/index.js",
@@ -2389,13 +2389,13 @@ var require_package = __commonJS({
2389
2389
  license: "MIT",
2390
2390
  dependencies: {
2391
2391
  "@dee-wan/schema-parser": "1.4.0",
2392
- "@prisma/generator-helper": "^6.19.2",
2393
- "@prisma/internals": "^6.19.2"
2392
+ "@prisma/generator-helper": "^7.4.0",
2393
+ "@prisma/internals": "^7.4.0"
2394
2394
  },
2395
2395
  devDependencies: {
2396
2396
  "@faker-js/faker": "^10.2.0",
2397
- "@prisma/adapter-better-sqlite3": "^6.19.2",
2398
- "@prisma/adapter-pg": "^6.19.2",
2397
+ "@prisma/adapter-better-sqlite3": "^7.4.0",
2398
+ "@prisma/adapter-pg": "^7.4.0",
2399
2399
  "@semantic-release/changelog": "^6.0.3",
2400
2400
  "@semantic-release/git": "^10.0.1",
2401
2401
  "@types/better-sqlite3": "^7.6.13",
@@ -2409,8 +2409,8 @@ var require_package = __commonJS({
2409
2409
  tsx: "^4.21.0",
2410
2410
  typescript: "^5.9.3",
2411
2411
  vitest: "^4.0.18",
2412
- "@prisma/client": "6.19.2",
2413
- prisma: "6.19.2"
2412
+ "@prisma/client": "7.4.0",
2413
+ prisma: "7.4.0"
2414
2414
  },
2415
2415
  engines: {
2416
2416
  node: ">=16.0.0"
@@ -2418,6 +2418,241 @@ var require_package = __commonJS({
2418
2418
  };
2419
2419
  }
2420
2420
  });
2421
+ var MAX_DEPTH = 20;
2422
+ function normalizeValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
2423
+ if (depth > MAX_DEPTH) {
2424
+ throw new Error(`Max normalization depth exceeded (${MAX_DEPTH} levels)`);
2425
+ }
2426
+ if (value instanceof Date) {
2427
+ return normalizeDateValue(value);
2428
+ }
2429
+ if (typeof value === "bigint") {
2430
+ return value.toString();
2431
+ }
2432
+ if (Array.isArray(value)) {
2433
+ return normalizeArrayValue(value, seen, depth);
2434
+ }
2435
+ if (value && typeof value === "object") {
2436
+ return normalizeObjectValue(value, seen, depth);
2437
+ }
2438
+ return value;
2439
+ }
2440
+ function normalizeDateValue(date) {
2441
+ const t = date.getTime();
2442
+ if (!Number.isFinite(t)) {
2443
+ throw new Error("Invalid Date value in SQL params");
2444
+ }
2445
+ return date.toISOString();
2446
+ }
2447
+ function normalizeArrayValue(value, seen, depth) {
2448
+ const arrRef = value;
2449
+ if (seen.has(arrRef)) {
2450
+ throw new Error("Circular reference in SQL params");
2451
+ }
2452
+ seen.add(arrRef);
2453
+ const out = value.map((v) => normalizeValue(v, seen, depth + 1));
2454
+ seen.delete(arrRef);
2455
+ return out;
2456
+ }
2457
+ function normalizeObjectValue(value, seen, depth) {
2458
+ if (value instanceof Uint8Array) return value;
2459
+ if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return value;
2460
+ const proto = Object.getPrototypeOf(value);
2461
+ const isPlain = proto === Object.prototype || proto === null;
2462
+ if (!isPlain) return value;
2463
+ const obj = value;
2464
+ if (seen.has(obj)) {
2465
+ throw new Error("Circular reference in SQL params");
2466
+ }
2467
+ seen.add(obj);
2468
+ const out = {};
2469
+ for (const [k, v] of Object.entries(obj)) {
2470
+ out[k] = normalizeValue(v, seen, depth + 1);
2471
+ }
2472
+ seen.delete(obj);
2473
+ return out;
2474
+ }
2475
+
2476
+ // src/sql-builder-dialect.ts
2477
+ var globalDialect = "postgres";
2478
+ function setGlobalDialect(dialect) {
2479
+ if (dialect !== "postgres" && dialect !== "sqlite") {
2480
+ throw new Error(
2481
+ `Invalid dialect: ${dialect}. Must be 'postgres' or 'sqlite'`
2482
+ );
2483
+ }
2484
+ globalDialect = dialect;
2485
+ }
2486
+ function getGlobalDialect() {
2487
+ return globalDialect;
2488
+ }
2489
+ function assertNonEmpty(value, name) {
2490
+ if (!value || value.trim().length === 0) {
2491
+ throw new Error(`${name} is required and cannot be empty`);
2492
+ }
2493
+ }
2494
+ function arrayContains(column, value, arrayType, dialect) {
2495
+ assertNonEmpty(column, "arrayContains column");
2496
+ assertNonEmpty(value, "arrayContains value");
2497
+ if (dialect === "postgres") {
2498
+ return `${column} @> ARRAY[${value}]::${arrayType}`;
2499
+ }
2500
+ return `EXISTS (SELECT 1 FROM json_each(${column}) WHERE value = ${value})`;
2501
+ }
2502
+ function arrayOverlaps(column, value, arrayType, dialect) {
2503
+ assertNonEmpty(column, "arrayOverlaps column");
2504
+ assertNonEmpty(value, "arrayOverlaps value");
2505
+ if (dialect === "postgres") {
2506
+ return `${column} && ${value}::${arrayType}`;
2507
+ }
2508
+ return `EXISTS (
2509
+ SELECT 1 FROM json_each(${column}) AS col
2510
+ JOIN json_each(${value}) AS val
2511
+ WHERE col.value = val.value
2512
+ )`;
2513
+ }
2514
+ function arrayContainsAll(column, value, arrayType, dialect) {
2515
+ assertNonEmpty(column, "arrayContainsAll column");
2516
+ assertNonEmpty(value, "arrayContainsAll value");
2517
+ if (dialect === "postgres") {
2518
+ return `${column} @> ${value}::${arrayType}`;
2519
+ }
2520
+ return `NOT EXISTS (
2521
+ SELECT 1 FROM json_each(${value}) AS val
2522
+ WHERE NOT EXISTS (
2523
+ SELECT 1 FROM json_each(${column}) AS col
2524
+ WHERE col.value = val.value
2525
+ )
2526
+ )`;
2527
+ }
2528
+ function arrayIsEmpty(column, dialect) {
2529
+ assertNonEmpty(column, "arrayIsEmpty column");
2530
+ if (dialect === "postgres") {
2531
+ return `(${column} IS NULL OR array_length(${column}, 1) IS NULL)`;
2532
+ }
2533
+ return `(${column} IS NULL OR json_array_length(${column}) = 0)`;
2534
+ }
2535
+ function arrayIsNotEmpty(column, dialect) {
2536
+ assertNonEmpty(column, "arrayIsNotEmpty column");
2537
+ if (dialect === "postgres") {
2538
+ return `(${column} IS NOT NULL AND array_length(${column}, 1) IS NOT NULL)`;
2539
+ }
2540
+ return `(${column} IS NOT NULL AND json_array_length(${column}) > 0)`;
2541
+ }
2542
+ function arrayEquals(column, value, arrayType, dialect) {
2543
+ assertNonEmpty(column, "arrayEquals column");
2544
+ assertNonEmpty(value, "arrayEquals value");
2545
+ if (dialect === "postgres") {
2546
+ return `${column} = ${value}::${arrayType}`;
2547
+ }
2548
+ return `json(${column}) = json(${value})`;
2549
+ }
2550
+ function caseInsensitiveLike(column, pattern, dialect) {
2551
+ assertNonEmpty(column, "caseInsensitiveLike column");
2552
+ assertNonEmpty(pattern, "caseInsensitiveLike pattern");
2553
+ if (dialect === "postgres") {
2554
+ return `${column} ILIKE ${pattern}`;
2555
+ }
2556
+ return `LOWER(${column}) LIKE LOWER(${pattern})`;
2557
+ }
2558
+ function caseInsensitiveEquals(column, value, dialect) {
2559
+ assertNonEmpty(column, "caseInsensitiveEquals column");
2560
+ assertNonEmpty(value, "caseInsensitiveEquals value");
2561
+ return `LOWER(${column}) = LOWER(${value})`;
2562
+ }
2563
+ function jsonExtractText(column, path, dialect) {
2564
+ assertNonEmpty(column, "jsonExtractText column");
2565
+ assertNonEmpty(path, "jsonExtractText path");
2566
+ if (dialect === "postgres") {
2567
+ const p = String(path).trim();
2568
+ const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
2569
+ return `${column}#>>${pathExpr}`;
2570
+ }
2571
+ return `json_extract(${column}, ${path})`;
2572
+ }
2573
+ function jsonExtractNumeric(column, path, dialect) {
2574
+ assertNonEmpty(column, "jsonExtractNumeric column");
2575
+ assertNonEmpty(path, "jsonExtractNumeric path");
2576
+ if (dialect === "postgres") {
2577
+ const p = String(path).trim();
2578
+ const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
2579
+ return `(${column}#>>${pathExpr})::numeric`;
2580
+ }
2581
+ return `CAST(json_extract(${column}, ${path}) AS REAL)`;
2582
+ }
2583
+ function jsonToText(column, dialect) {
2584
+ assertNonEmpty(column, "jsonToText column");
2585
+ if (dialect === "postgres") {
2586
+ return `${column}::text`;
2587
+ }
2588
+ return column;
2589
+ }
2590
+ function inArray(column, value, dialect) {
2591
+ assertNonEmpty(column, "inArray column");
2592
+ assertNonEmpty(value, "inArray value");
2593
+ if (dialect === "postgres") {
2594
+ return `${column} = ANY(${value})`;
2595
+ }
2596
+ return `${column} IN (SELECT value FROM json_each(${value}))`;
2597
+ }
2598
+ function notInArray(column, value, dialect) {
2599
+ assertNonEmpty(column, "notInArray column");
2600
+ assertNonEmpty(value, "notInArray value");
2601
+ if (dialect === "postgres") {
2602
+ return `${column} != ALL(${value})`;
2603
+ }
2604
+ return `${column} NOT IN (SELECT value FROM json_each(${value}))`;
2605
+ }
2606
+ function getArrayType(prismaType, dialect) {
2607
+ if (!prismaType || prismaType.length === 0) {
2608
+ return dialect === "sqlite" ? "TEXT" : "text[]";
2609
+ }
2610
+ if (dialect === "sqlite") {
2611
+ return "TEXT";
2612
+ }
2613
+ const baseType = prismaType.replace(/\[\]|\?/g, "");
2614
+ switch (baseType) {
2615
+ case "String":
2616
+ return "text[]";
2617
+ case "Int":
2618
+ return "integer[]";
2619
+ case "Float":
2620
+ return "double precision[]";
2621
+ case "Decimal":
2622
+ return "numeric[]";
2623
+ case "Boolean":
2624
+ return "boolean[]";
2625
+ case "BigInt":
2626
+ return "bigint[]";
2627
+ case "DateTime":
2628
+ return "timestamptz[]";
2629
+ default:
2630
+ return `"${baseType}"[]`;
2631
+ }
2632
+ }
2633
+ function jsonAgg(content, dialect) {
2634
+ assertNonEmpty(content, "jsonAgg content");
2635
+ if (dialect === "postgres") {
2636
+ return `json_agg(${content})`;
2637
+ }
2638
+ return `json_group_array(${content})`;
2639
+ }
2640
+ function jsonBuildObject(pairs, dialect) {
2641
+ const safePairs = (pairs != null ? pairs : "").trim();
2642
+ if (dialect === "postgres") {
2643
+ return safePairs.length > 0 ? `json_build_object(${safePairs})` : `json_build_object()`;
2644
+ }
2645
+ return safePairs.length > 0 ? `json_object(${safePairs})` : `json_object()`;
2646
+ }
2647
+ function prepareArrayParam(value, dialect) {
2648
+ if (!Array.isArray(value)) {
2649
+ throw new Error("prepareArrayParam requires array value");
2650
+ }
2651
+ if (dialect === "postgres") {
2652
+ return value.map((v) => normalizeValue(v));
2653
+ }
2654
+ return JSON.stringify(value.map((v) => normalizeValue(v)));
2655
+ }
2421
2656
 
2422
2657
  // src/builder/shared/constants.ts
2423
2658
  var IS_PRODUCTION = process.env.NODE_ENV === "production";
@@ -3243,241 +3478,6 @@ function joinCondition(field, parentModel, childModel, parentAlias, childAlias)
3243
3478
  function getModelByName(schemas, name) {
3244
3479
  return schemas.find((m) => m.name === name);
3245
3480
  }
3246
- var MAX_DEPTH = 20;
3247
- function normalizeValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
3248
- if (depth > MAX_DEPTH) {
3249
- throw new Error(`Max normalization depth exceeded (${MAX_DEPTH} levels)`);
3250
- }
3251
- if (value instanceof Date) {
3252
- return normalizeDateValue(value);
3253
- }
3254
- if (typeof value === "bigint") {
3255
- return value.toString();
3256
- }
3257
- if (Array.isArray(value)) {
3258
- return normalizeArrayValue(value, seen, depth);
3259
- }
3260
- if (value && typeof value === "object") {
3261
- return normalizeObjectValue(value, seen, depth);
3262
- }
3263
- return value;
3264
- }
3265
- function normalizeDateValue(date) {
3266
- const t = date.getTime();
3267
- if (!Number.isFinite(t)) {
3268
- throw new Error("Invalid Date value in SQL params");
3269
- }
3270
- return date.toISOString();
3271
- }
3272
- function normalizeArrayValue(value, seen, depth) {
3273
- const arrRef = value;
3274
- if (seen.has(arrRef)) {
3275
- throw new Error("Circular reference in SQL params");
3276
- }
3277
- seen.add(arrRef);
3278
- const out = value.map((v) => normalizeValue(v, seen, depth + 1));
3279
- seen.delete(arrRef);
3280
- return out;
3281
- }
3282
- function normalizeObjectValue(value, seen, depth) {
3283
- if (value instanceof Uint8Array) return value;
3284
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return value;
3285
- const proto = Object.getPrototypeOf(value);
3286
- const isPlain = proto === Object.prototype || proto === null;
3287
- if (!isPlain) return value;
3288
- const obj = value;
3289
- if (seen.has(obj)) {
3290
- throw new Error("Circular reference in SQL params");
3291
- }
3292
- seen.add(obj);
3293
- const out = {};
3294
- for (const [k, v] of Object.entries(obj)) {
3295
- out[k] = normalizeValue(v, seen, depth + 1);
3296
- }
3297
- seen.delete(obj);
3298
- return out;
3299
- }
3300
-
3301
- // src/sql-builder-dialect.ts
3302
- var globalDialect = "postgres";
3303
- function setGlobalDialect(dialect) {
3304
- if (dialect !== "postgres" && dialect !== "sqlite") {
3305
- throw new Error(
3306
- `Invalid dialect: ${dialect}. Must be 'postgres' or 'sqlite'`
3307
- );
3308
- }
3309
- globalDialect = dialect;
3310
- }
3311
- function getGlobalDialect() {
3312
- return globalDialect;
3313
- }
3314
- function assertNonEmpty(value, name) {
3315
- if (!value || value.trim().length === 0) {
3316
- throw new Error(`${name} is required and cannot be empty`);
3317
- }
3318
- }
3319
- function arrayContains(column, value, arrayType, dialect) {
3320
- assertNonEmpty(column, "arrayContains column");
3321
- assertNonEmpty(value, "arrayContains value");
3322
- if (dialect === "postgres") {
3323
- return `${column} @> ARRAY[${value}]::${arrayType}`;
3324
- }
3325
- return `EXISTS (SELECT 1 FROM json_each(${column}) WHERE value = ${value})`;
3326
- }
3327
- function arrayOverlaps(column, value, arrayType, dialect) {
3328
- assertNonEmpty(column, "arrayOverlaps column");
3329
- assertNonEmpty(value, "arrayOverlaps value");
3330
- if (dialect === "postgres") {
3331
- return `${column} && ${value}::${arrayType}`;
3332
- }
3333
- return `EXISTS (
3334
- SELECT 1 FROM json_each(${column}) AS col
3335
- JOIN json_each(${value}) AS val
3336
- WHERE col.value = val.value
3337
- )`;
3338
- }
3339
- function arrayContainsAll(column, value, arrayType, dialect) {
3340
- assertNonEmpty(column, "arrayContainsAll column");
3341
- assertNonEmpty(value, "arrayContainsAll value");
3342
- if (dialect === "postgres") {
3343
- return `${column} @> ${value}::${arrayType}`;
3344
- }
3345
- return `NOT EXISTS (
3346
- SELECT 1 FROM json_each(${value}) AS val
3347
- WHERE NOT EXISTS (
3348
- SELECT 1 FROM json_each(${column}) AS col
3349
- WHERE col.value = val.value
3350
- )
3351
- )`;
3352
- }
3353
- function arrayIsEmpty(column, dialect) {
3354
- assertNonEmpty(column, "arrayIsEmpty column");
3355
- if (dialect === "postgres") {
3356
- return `(${column} IS NULL OR array_length(${column}, 1) IS NULL)`;
3357
- }
3358
- return `(${column} IS NULL OR json_array_length(${column}) = 0)`;
3359
- }
3360
- function arrayIsNotEmpty(column, dialect) {
3361
- assertNonEmpty(column, "arrayIsNotEmpty column");
3362
- if (dialect === "postgres") {
3363
- return `(${column} IS NOT NULL AND array_length(${column}, 1) IS NOT NULL)`;
3364
- }
3365
- return `(${column} IS NOT NULL AND json_array_length(${column}) > 0)`;
3366
- }
3367
- function arrayEquals(column, value, arrayType, dialect) {
3368
- assertNonEmpty(column, "arrayEquals column");
3369
- assertNonEmpty(value, "arrayEquals value");
3370
- if (dialect === "postgres") {
3371
- return `${column} = ${value}::${arrayType}`;
3372
- }
3373
- return `json(${column}) = json(${value})`;
3374
- }
3375
- function caseInsensitiveLike(column, pattern, dialect) {
3376
- assertNonEmpty(column, "caseInsensitiveLike column");
3377
- assertNonEmpty(pattern, "caseInsensitiveLike pattern");
3378
- if (dialect === "postgres") {
3379
- return `${column} ILIKE ${pattern}`;
3380
- }
3381
- return `LOWER(${column}) LIKE LOWER(${pattern})`;
3382
- }
3383
- function caseInsensitiveEquals(column, value, dialect) {
3384
- assertNonEmpty(column, "caseInsensitiveEquals column");
3385
- assertNonEmpty(value, "caseInsensitiveEquals value");
3386
- return `LOWER(${column}) = LOWER(${value})`;
3387
- }
3388
- function jsonExtractText(column, path, dialect) {
3389
- assertNonEmpty(column, "jsonExtractText column");
3390
- assertNonEmpty(path, "jsonExtractText path");
3391
- if (dialect === "postgres") {
3392
- const p = String(path).trim();
3393
- const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
3394
- return `${column}#>>${pathExpr}`;
3395
- }
3396
- return `json_extract(${column}, ${path})`;
3397
- }
3398
- function jsonExtractNumeric(column, path, dialect) {
3399
- assertNonEmpty(column, "jsonExtractNumeric column");
3400
- assertNonEmpty(path, "jsonExtractNumeric path");
3401
- if (dialect === "postgres") {
3402
- const p = String(path).trim();
3403
- const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
3404
- return `(${column}#>>${pathExpr})::numeric`;
3405
- }
3406
- return `CAST(json_extract(${column}, ${path}) AS REAL)`;
3407
- }
3408
- function jsonToText(column, dialect) {
3409
- assertNonEmpty(column, "jsonToText column");
3410
- if (dialect === "postgres") {
3411
- return `${column}::text`;
3412
- }
3413
- return column;
3414
- }
3415
- function inArray(column, value, dialect) {
3416
- assertNonEmpty(column, "inArray column");
3417
- assertNonEmpty(value, "inArray value");
3418
- if (dialect === "postgres") {
3419
- return `${column} = ANY(${value})`;
3420
- }
3421
- return `${column} IN (SELECT value FROM json_each(${value}))`;
3422
- }
3423
- function notInArray(column, value, dialect) {
3424
- assertNonEmpty(column, "notInArray column");
3425
- assertNonEmpty(value, "notInArray value");
3426
- if (dialect === "postgres") {
3427
- return `${column} != ALL(${value})`;
3428
- }
3429
- return `${column} NOT IN (SELECT value FROM json_each(${value}))`;
3430
- }
3431
- function getArrayType(prismaType, dialect) {
3432
- if (!prismaType || prismaType.length === 0) {
3433
- return dialect === "sqlite" ? "TEXT" : "text[]";
3434
- }
3435
- if (dialect === "sqlite") {
3436
- return "TEXT";
3437
- }
3438
- const baseType = prismaType.replace(/\[\]|\?/g, "");
3439
- switch (baseType) {
3440
- case "String":
3441
- return "text[]";
3442
- case "Int":
3443
- return "integer[]";
3444
- case "Float":
3445
- return "double precision[]";
3446
- case "Decimal":
3447
- return "numeric[]";
3448
- case "Boolean":
3449
- return "boolean[]";
3450
- case "BigInt":
3451
- return "bigint[]";
3452
- case "DateTime":
3453
- return "timestamptz[]";
3454
- default:
3455
- return `"${baseType}"[]`;
3456
- }
3457
- }
3458
- function jsonAgg(content, dialect) {
3459
- assertNonEmpty(content, "jsonAgg content");
3460
- if (dialect === "postgres") {
3461
- return `json_agg(${content})`;
3462
- }
3463
- return `json_group_array(${content})`;
3464
- }
3465
- function jsonBuildObject(pairs, dialect) {
3466
- const safePairs = (pairs != null ? pairs : "").trim();
3467
- if (dialect === "postgres") {
3468
- return safePairs.length > 0 ? `json_build_object(${safePairs})` : `json_build_object()`;
3469
- }
3470
- return safePairs.length > 0 ? `json_object(${safePairs})` : `json_object()`;
3471
- }
3472
- function prepareArrayParam(value, dialect) {
3473
- if (!Array.isArray(value)) {
3474
- throw new Error("prepareArrayParam requires array value");
3475
- }
3476
- if (dialect === "postgres") {
3477
- return value.map((v) => normalizeValue(v));
3478
- }
3479
- return JSON.stringify(value.map((v) => normalizeValue(v)));
3480
- }
3481
3481
  function normalizeIntLike(name, v, opts = {}) {
3482
3482
  var _a3, _b;
3483
3483
  if (!isNotNullish(v)) return void 0;
@@ -7164,7 +7164,6 @@ var DEFAULT_SELECT_CACHE = /* @__PURE__ */ new WeakMap();
7164
7164
  function toSelectEntries(select2) {
7165
7165
  const out = [];
7166
7166
  for (const [k, v] of Object.entries(select2)) {
7167
- if (k === "_count") continue;
7168
7167
  if (v !== false && v !== void 0) out.push([k, v]);
7169
7168
  }
7170
7169
  return out;
@@ -7257,7 +7256,9 @@ function validateFieldKeys(entries, scalarSet, relationSet, allowCount = false)
7257
7256
  if (!scalarSet.has(k) && !relationSet.has(k)) unknown.push(k);
7258
7257
  }
7259
7258
  if (unknown.length > 0) {
7260
- throw new Error(`Select contains unknown fields: ${unknown.join(", ")}`);
7259
+ throw new Error(
7260
+ `Unknown field '${unknown.join("', '")}' does not exist on this model`
7261
+ );
7261
7262
  }
7262
7263
  }
7263
7264
  function buildSelectedScalarParts(entries, scalarNames, alias, model) {
@@ -7438,23 +7439,56 @@ function buildNestedToOneJoins(relations, baseAlias, baseModel, aliasGen, dialec
7438
7439
  }
7439
7440
  return { joins, aliasMap };
7440
7441
  }
7441
- function buildNestedToOneSelects(relations, aliasMap) {
7442
+ function buildNestedToOneSelects(relations, aliasMap, dialect) {
7442
7443
  const selects = [];
7443
7444
  for (const rel of relations) {
7444
7445
  const relAlias = aliasMap.get(rel.name);
7445
7446
  if (!relAlias) continue;
7446
7447
  const relSelect = buildRelationSelect(rel.args, rel.model, relAlias);
7447
7448
  if (!relSelect || relSelect.trim().length === 0) continue;
7448
- selects.push(`${sqlStringLiteral(rel.name)}, ${relSelect}`);
7449
+ const jsonExpr = jsonBuildObject(relSelect, dialect);
7450
+ const pkField = getPrimaryKeyField(rel.model);
7451
+ const pkCol = `${relAlias}.${quoteColumn(rel.model, pkField)}`;
7452
+ const nullSafeExpr = `CASE WHEN ${pkCol} IS NOT NULL THEN ${jsonExpr} ELSE NULL END`;
7453
+ selects.push(`${sqlStringLiteral(rel.name)}, ${nullSafeExpr}`);
7449
7454
  }
7450
7455
  return selects;
7451
7456
  }
7457
+ function extractCountSelectFromRelArgs(relArgs) {
7458
+ if (!isPlainObject(relArgs)) return null;
7459
+ const obj = relArgs;
7460
+ if (!isPlainObject(obj.select)) return null;
7461
+ const sel = obj.select;
7462
+ const countRaw = sel["_count"];
7463
+ if (!countRaw) return null;
7464
+ if (isPlainObject(countRaw) && "select" in countRaw) {
7465
+ return countRaw.select;
7466
+ }
7467
+ return null;
7468
+ }
7452
7469
  function buildSelectWithNestedIncludes(relArgs, relModel, relAlias, ctx) {
7453
7470
  const nestedToOnes = extractNestedToOneRelations(
7454
7471
  relArgs,
7455
7472
  relModel,
7456
7473
  ctx.schemaByName
7457
7474
  );
7475
+ const countSelect = extractCountSelectFromRelArgs(relArgs);
7476
+ const countJoins = [];
7477
+ function appendCountToSelect(baseSelect2) {
7478
+ if (!countSelect || Object.keys(countSelect).length === 0) return baseSelect2;
7479
+ const countBuild = buildRelationCountSql(
7480
+ countSelect,
7481
+ relModel,
7482
+ ctx.schemas,
7483
+ relAlias,
7484
+ ctx.params,
7485
+ ctx.dialect
7486
+ );
7487
+ if (!countBuild.jsonPairs) return baseSelect2;
7488
+ countJoins.push(...countBuild.joins);
7489
+ const countExpr = `'_count', ${jsonBuildObject(countBuild.jsonPairs, ctx.dialect)}`;
7490
+ return baseSelect2 ? `${baseSelect2}${SQL_SEPARATORS.FIELD_LIST}${countExpr}` : countExpr;
7491
+ }
7458
7492
  if (nestedToOnes.length === 0) {
7459
7493
  let relSelect = buildRelationSelect(relArgs, relModel, relAlias);
7460
7494
  let nestedIncludes = [];
@@ -7483,7 +7517,8 @@ function buildSelectWithNestedIncludes(relArgs, relModel, relAlias, ctx) {
7483
7517
  ).join(SQL_SEPARATORS.FIELD_LIST);
7484
7518
  relSelect = isNotNullish(relSelect) && relSelect.trim().length > 0 ? `${relSelect}${SQL_SEPARATORS.FIELD_LIST}${nestedSelects2}` : nestedSelects2;
7485
7519
  }
7486
- return { select: relSelect, nestedJoins: [] };
7520
+ relSelect = appendCountToSelect(relSelect);
7521
+ return { select: relSelect, nestedJoins: countJoins };
7487
7522
  }
7488
7523
  const { joins, aliasMap } = buildNestedToOneJoins(
7489
7524
  nestedToOnes,
@@ -7493,7 +7528,11 @@ function buildSelectWithNestedIncludes(relArgs, relModel, relAlias, ctx) {
7493
7528
  ctx.dialect
7494
7529
  );
7495
7530
  const baseSelect = buildRelationSelect(relArgs, relModel, relAlias);
7496
- const nestedSelects = buildNestedToOneSelects(nestedToOnes, aliasMap);
7531
+ const nestedSelects = buildNestedToOneSelects(
7532
+ nestedToOnes,
7533
+ aliasMap,
7534
+ ctx.dialect
7535
+ );
7497
7536
  const allParts = [];
7498
7537
  if (baseSelect && baseSelect.trim().length > 0) {
7499
7538
  allParts.push(baseSelect);
@@ -7501,9 +7540,11 @@ function buildSelectWithNestedIncludes(relArgs, relModel, relAlias, ctx) {
7501
7540
  for (const ns of nestedSelects) {
7502
7541
  allParts.push(ns);
7503
7542
  }
7543
+ let finalSelect = allParts.join(SQL_SEPARATORS.FIELD_LIST);
7544
+ finalSelect = appendCountToSelect(finalSelect);
7504
7545
  return {
7505
- select: allParts.join(SQL_SEPARATORS.FIELD_LIST),
7506
- nestedJoins: joins
7546
+ select: finalSelect,
7547
+ nestedJoins: [...joins, ...countJoins]
7507
7548
  };
7508
7549
  }
7509
7550
  function buildWhereParts(whereInput, relModel, relAlias, ctx) {
@@ -7885,7 +7926,7 @@ function validateDistinct(model, distinct) {
7885
7926
  const relationSet = getRelationFieldSet(model);
7886
7927
  if (relationSet.has(f)) {
7887
7928
  throw new Error(
7888
- `distinct field '${f}' is a relation. Only scalar fields are allowed.
7929
+ `distinct field '${f}' is a relation field. Only scalar fields are allowed.
7889
7930
  Available scalar fields: ${[...scalarSet].join(", ")}`
7890
7931
  );
7891
7932
  }
@@ -7923,7 +7964,7 @@ function validateOrderBy(model, orderBy) {
7923
7964
  if (!scalarSet.has(f)) {
7924
7965
  if (relationSet.has(f)) {
7925
7966
  throw new Error(
7926
- `orderBy field '${f}' is a relation. Only scalar fields are allowed.
7967
+ `orderBy field '${f}' is a relation field. Only scalar fields are allowed.
7927
7968
  Available scalar fields: ${[...scalarSet].join(", ")}`
7928
7969
  );
7929
7970
  }