prisma-sql 1.54.0 → 1.56.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.
@@ -56,7 +56,7 @@ var require_package = __commonJS({
56
56
  "package.json"(exports$1, module) {
57
57
  module.exports = {
58
58
  name: "prisma-sql",
59
- version: "1.54.0",
59
+ version: "1.56.0",
60
60
  description: "Convert Prisma queries to optimized SQL with type safety. 2-7x faster than Prisma Client.",
61
61
  main: "dist/index.cjs",
62
62
  module: "dist/index.js",
@@ -815,6 +815,9 @@ function assertNoControlChars(label, s) {
815
815
  );
816
816
  }
817
817
  }
818
+ function quoteRawIdent(id) {
819
+ return `"${id.replace(/"/g, '""')}"`;
820
+ }
818
821
  function isIdentCharCode(c) {
819
822
  return c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 95;
820
823
  }
@@ -836,33 +839,33 @@ function parseQuotedPart(input, start) {
836
839
  }
837
840
  if (!sawAny) {
838
841
  throw new Error(
839
- `tableName/tableRef has empty quoted identifier part: ${JSON.stringify(input)}`
842
+ `qualified name has empty quoted identifier part: ${JSON.stringify(input)}`
840
843
  );
841
844
  }
842
845
  return i + 1;
843
846
  }
844
847
  if (c === 10 || c === 13 || c === 0) {
845
848
  throw new Error(
846
- `tableName/tableRef contains invalid characters: ${JSON.stringify(input)}`
849
+ `qualified name contains invalid characters: ${JSON.stringify(input)}`
847
850
  );
848
851
  }
849
852
  sawAny = true;
850
853
  i++;
851
854
  }
852
855
  throw new Error(
853
- `tableName/tableRef has unterminated quoted identifier: ${JSON.stringify(input)}`
856
+ `qualified name has unterminated quoted identifier: ${JSON.stringify(input)}`
854
857
  );
855
858
  }
856
859
  function parseUnquotedPart(input, start) {
857
860
  const n = input.length;
858
861
  let i = start;
859
862
  if (i >= n) {
860
- throw new Error(`tableName/tableRef is invalid: ${JSON.stringify(input)}`);
863
+ throw new Error(`qualified name is invalid: ${JSON.stringify(input)}`);
861
864
  }
862
865
  const c0 = input.charCodeAt(i);
863
866
  if (!isIdentStartCharCode(c0)) {
864
867
  throw new Error(
865
- `tableName/tableRef must use identifiers (or quoted identifiers). Got: ${JSON.stringify(input)}`
868
+ `qualified name must use identifiers (or quoted identifiers). Got: ${JSON.stringify(input)}`
866
869
  );
867
870
  }
868
871
  i++;
@@ -871,15 +874,15 @@ function parseUnquotedPart(input, start) {
871
874
  if (c === 46) break;
872
875
  if (!isIdentCharCode(c)) {
873
876
  throw new Error(
874
- `tableName/tableRef contains invalid identifier characters: ${JSON.stringify(input)}`
877
+ `qualified name contains invalid identifier characters: ${JSON.stringify(input)}`
875
878
  );
876
879
  }
877
880
  i++;
878
881
  }
879
882
  return i;
880
883
  }
881
- function assertSafeQualifiedName(tableRef) {
882
- const raw = String(tableRef);
884
+ function assertSafeQualifiedName(input) {
885
+ const raw = String(input);
883
886
  const trimmed = raw.trim();
884
887
  if (trimmed.length === 0) {
885
888
  throw new Error("tableName/tableRef is required and cannot be empty");
@@ -953,7 +956,7 @@ function quote2(id) {
953
956
  );
954
957
  }
955
958
  if (needsQuoting(id)) {
956
- return `"${id.replace(/"/g, '""')}"`;
959
+ return quoteRawIdent(id);
957
960
  }
958
961
  return id;
959
962
  }
@@ -2592,28 +2595,24 @@ function buildOperator(expr, op, val, ctx, mode, fieldType) {
2592
2595
  function toSafeSqlIdentifier(input) {
2593
2596
  const raw = String(input);
2594
2597
  const n = raw.length;
2598
+ if (n === 0) return "_t";
2595
2599
  let out = "";
2596
2600
  for (let i = 0; i < n; i++) {
2597
2601
  const c = raw.charCodeAt(i);
2598
2602
  const isAZ = c >= 65 && c <= 90 || c >= 97 && c <= 122;
2599
2603
  const is09 = c >= 48 && c <= 57;
2600
2604
  const isUnderscore = c === 95;
2601
- if (isAZ || is09 || isUnderscore) {
2602
- out += raw[i];
2603
- } else {
2604
- out += "_";
2605
- }
2605
+ out += isAZ || is09 || isUnderscore ? raw[i] : "_";
2606
2606
  }
2607
- if (out.length === 0) out = "_t";
2608
2607
  const c0 = out.charCodeAt(0);
2609
2608
  const startsOk = c0 >= 65 && c0 <= 90 || c0 >= 97 && c0 <= 122 || c0 === 95;
2610
- if (!startsOk) out = `_${out}`;
2611
- const lowered = out.toLowerCase();
2609
+ const lowered = (startsOk ? out : `_${out}`).toLowerCase();
2612
2610
  return ALIAS_FORBIDDEN_KEYWORDS.has(lowered) ? `_${lowered}` : lowered;
2613
2611
  }
2614
2612
  function createAliasGenerator(maxAliases = 1e4) {
2615
2613
  let counter = 0;
2616
2614
  const usedAliases = /* @__PURE__ */ new Set();
2615
+ const maxLen = 63;
2617
2616
  return {
2618
2617
  next(baseName) {
2619
2618
  if (usedAliases.size >= maxAliases) {
@@ -2623,14 +2622,13 @@ function createAliasGenerator(maxAliases = 1e4) {
2623
2622
  }
2624
2623
  const base = toSafeSqlIdentifier(baseName);
2625
2624
  const suffix = `_${counter}`;
2626
- const maxLen = 63;
2627
2625
  const baseMax = Math.max(1, maxLen - suffix.length);
2628
2626
  const trimmedBase = base.length > baseMax ? base.slice(0, baseMax) : base;
2629
2627
  const alias = `${trimmedBase}${suffix}`;
2630
2628
  counter += 1;
2631
2629
  if (usedAliases.has(alias)) {
2632
2630
  throw new Error(
2633
- `CRITICAL: Duplicate alias '${alias}' at counter=${counter}. This indicates a bug in alias generation logic.`
2631
+ `CRITICAL: Duplicate alias '${alias}' at counter=${counter}.`
2634
2632
  );
2635
2633
  }
2636
2634
  usedAliases.add(alias);
@@ -2682,24 +2680,19 @@ function normalizeDynamicNameOrThrow(dynamicName, index) {
2682
2680
  }
2683
2681
  return dn;
2684
2682
  }
2685
- function assertUniqueDynamicName(dn, seen) {
2686
- if (seen.has(dn)) {
2687
- throw new Error(`CRITICAL: Duplicate dynamic param name in mappings: ${dn}`);
2688
- }
2689
- seen.add(dn);
2690
- }
2691
- function validateMappingEntry(m, expectedIndex, seenDynamic) {
2692
- assertSequentialIndex(m.index, expectedIndex);
2693
- assertExactlyOneOfDynamicOrValue(m);
2694
- if (typeof m.dynamicName === "string") {
2695
- const dn = normalizeDynamicNameOrThrow(m.dynamicName, m.index);
2696
- assertUniqueDynamicName(dn, seenDynamic);
2697
- }
2698
- }
2699
2683
  function validateMappings(mappings) {
2700
2684
  const seenDynamic = /* @__PURE__ */ new Set();
2701
2685
  for (let i = 0; i < mappings.length; i++) {
2702
- validateMappingEntry(mappings[i], i + 1, seenDynamic);
2686
+ const m = mappings[i];
2687
+ assertSequentialIndex(m.index, i + 1);
2688
+ assertExactlyOneOfDynamicOrValue(m);
2689
+ if (typeof m.dynamicName === "string") {
2690
+ const dn = normalizeDynamicNameOrThrow(m.dynamicName, m.index);
2691
+ if (seenDynamic.has(dn)) {
2692
+ throw new Error(`CRITICAL: Duplicate dynamic param name: ${dn}`);
2693
+ }
2694
+ seenDynamic.add(dn);
2695
+ }
2703
2696
  }
2704
2697
  }
2705
2698
  function validateState(params, mappings, index) {
@@ -2711,16 +2704,19 @@ function validateState(params, mappings, index) {
2711
2704
  }
2712
2705
  function createStoreInternal(startIndex, initialParams = [], initialMappings = []) {
2713
2706
  let index = startIndex;
2714
- const params = initialParams.length > 0 ? [...initialParams] : [];
2715
- const mappings = initialMappings.length > 0 ? [...initialMappings] : [];
2707
+ const params = initialParams.length > 0 ? initialParams.slice() : [];
2708
+ const mappings = initialMappings.length > 0 ? initialMappings.slice() : [];
2716
2709
  const dynamicNameToIndex = /* @__PURE__ */ new Map();
2717
- for (const m of mappings) {
2710
+ for (let i = 0; i < mappings.length; i++) {
2711
+ const m = mappings[i];
2718
2712
  if (typeof m.dynamicName === "string") {
2719
2713
  dynamicNameToIndex.set(m.dynamicName.trim(), m.index);
2720
2714
  }
2721
2715
  }
2722
2716
  let dirty = true;
2723
2717
  let cachedSnapshot = null;
2718
+ let frozenParams = null;
2719
+ let frozenMappings = null;
2724
2720
  function assertCanAdd() {
2725
2721
  if (index > MAX_PARAM_INDEX) {
2726
2722
  throw new Error(
@@ -2772,13 +2768,17 @@ function createStoreInternal(startIndex, initialParams = [], initialMappings = [
2772
2768
  }
2773
2769
  function snapshot() {
2774
2770
  if (!dirty && cachedSnapshot) return cachedSnapshot;
2771
+ if (!frozenParams) frozenParams = Object.freeze(params.slice());
2772
+ if (!frozenMappings) frozenMappings = Object.freeze(mappings.slice());
2775
2773
  const snap = {
2776
2774
  index,
2777
- params,
2778
- mappings
2775
+ params: frozenParams,
2776
+ mappings: frozenMappings
2779
2777
  };
2780
2778
  cachedSnapshot = snap;
2781
2779
  dirty = false;
2780
+ frozenParams = null;
2781
+ frozenMappings = null;
2782
2782
  return snap;
2783
2783
  }
2784
2784
  return {
@@ -2802,11 +2802,11 @@ function createParamStore(startIndex = 1) {
2802
2802
  return createStoreInternal(startIndex);
2803
2803
  }
2804
2804
  function createParamStoreFrom(existingParams, existingMappings, nextIndex) {
2805
- validateState([...existingParams], [...existingMappings], nextIndex);
2805
+ validateState(existingParams, existingMappings, nextIndex);
2806
2806
  return createStoreInternal(
2807
2807
  nextIndex,
2808
- [...existingParams],
2809
- [...existingMappings]
2808
+ existingParams.slice(),
2809
+ existingMappings.slice()
2810
2810
  );
2811
2811
  }
2812
2812
 
@@ -2988,7 +2988,7 @@ function getRelationTableReference(relModel, dialect) {
2988
2988
  dialect
2989
2989
  );
2990
2990
  }
2991
- function resolveRelationOrThrow(model, schemas, schemaByName, relName) {
2991
+ function resolveRelationOrThrow(model, schemaByName, relName) {
2992
2992
  const field = model.fields.find((f) => f.name === relName);
2993
2993
  if (!isNotNullish(field)) {
2994
2994
  throw new Error(
@@ -3042,8 +3042,9 @@ function validateOrderByForModel(model, orderBy) {
3042
3042
  throw new Error("orderBy array entries must have exactly one field");
3043
3043
  }
3044
3044
  const fieldName = String(entries[0][0]).trim();
3045
- if (fieldName.length === 0)
3045
+ if (fieldName.length === 0) {
3046
3046
  throw new Error("orderBy field name cannot be empty");
3047
+ }
3047
3048
  if (!scalarSet.has(fieldName)) {
3048
3049
  throw new Error(
3049
3050
  `orderBy references unknown or non-scalar field '${fieldName}' on model ${model.name}`
@@ -3102,8 +3103,9 @@ function extractRelationPaginationConfig(relArgs) {
3102
3103
  function maybeReverseNegativeTake(takeVal, hasOrderBy, orderByInput) {
3103
3104
  if (typeof takeVal !== "number") return { takeVal, orderByInput };
3104
3105
  if (takeVal >= 0) return { takeVal, orderByInput };
3105
- if (!hasOrderBy)
3106
+ if (!hasOrderBy) {
3106
3107
  throw new Error("Negative take requires orderBy for deterministic results");
3108
+ }
3107
3109
  return {
3108
3110
  takeVal: Math.abs(takeVal),
3109
3111
  orderByInput: reverseOrderByInput(orderByInput)
@@ -3113,9 +3115,7 @@ function finalizeOrderByForInclude(args) {
3113
3115
  if (args.hasOrderBy && isNotNullish(args.orderByInput)) {
3114
3116
  validateOrderByForModel(args.relModel, args.orderByInput);
3115
3117
  }
3116
- if (!args.hasPagination) {
3117
- return args.orderByInput;
3118
- }
3118
+ if (!args.hasPagination) return args.orderByInput;
3119
3119
  return ensureDeterministicOrderByInput({
3120
3120
  orderBy: args.hasOrderBy ? args.orderByInput : void 0,
3121
3121
  model: args.relModel,
@@ -3176,7 +3176,9 @@ function buildOrderBySql(finalOrderByInput, relAlias, dialect, relModel) {
3176
3176
  return isNotNullish(finalOrderByInput) ? buildOrderBy(finalOrderByInput, relAlias, dialect, relModel) : "";
3177
3177
  }
3178
3178
  function buildBaseSql(args) {
3179
- return `${SQL_TEMPLATES.SELECT} ${args.selectExpr} ${SQL_TEMPLATES.FROM} ${args.relTable} ${args.relAlias} ${args.joins} ${SQL_TEMPLATES.WHERE} ${args.joinPredicate}${args.whereClause}`;
3179
+ const joins = args.joins ? ` ${args.joins}` : "";
3180
+ const where = `${SQL_TEMPLATES.WHERE} ${args.joinPredicate}${args.whereClause}`;
3181
+ return `${SQL_TEMPLATES.SELECT} ${args.selectExpr} ${SQL_TEMPLATES.FROM} ${args.relTable} ${args.relAlias}${joins} ` + where;
3180
3182
  }
3181
3183
  function buildOneToOneIncludeSql(args) {
3182
3184
  const objExpr = jsonBuildObject(args.relSelect, args.ctx.dialect);
@@ -3188,9 +3190,7 @@ function buildOneToOneIncludeSql(args) {
3188
3190
  joinPredicate: args.joinPredicate,
3189
3191
  whereClause: args.whereClause
3190
3192
  });
3191
- if (args.orderBySql) {
3192
- sql += ` ${SQL_TEMPLATES.ORDER_BY} ${args.orderBySql}`;
3193
- }
3193
+ if (args.orderBySql) sql += ` ${SQL_TEMPLATES.ORDER_BY} ${args.orderBySql}`;
3194
3194
  if (isNotNullish(args.takeVal)) {
3195
3195
  return appendLimitOffset(
3196
3196
  sql,
@@ -3243,7 +3243,7 @@ function buildListIncludeSpec(args) {
3243
3243
  `include.${args.relName}`
3244
3244
  );
3245
3245
  const selectExpr = jsonAgg("row", args.ctx.dialect);
3246
- const sql = `${SQL_TEMPLATES.SELECT} ${selectExpr} ${SQL_TEMPLATES.FROM} (${base}) ${rowAlias}`;
3246
+ const sql = `${SQL_TEMPLATES.SELECT} ${selectExpr} ${SQL_TEMPLATES.FROM} (${base}) ${SQL_TEMPLATES.AS} ${rowAlias}`;
3247
3247
  return Object.freeze({ name: args.relName, sql, isOneToOne: false });
3248
3248
  }
3249
3249
  function buildSingleInclude(relName, relArgs, field, relModel, ctx) {
@@ -3341,12 +3341,7 @@ function buildIncludeSqlInternal(args, model, schemas, schemaByName, parentAlias
3341
3341
  `Query complexity limit exceeded: ${stats.totalSubqueries} subqueries generated. Maximum allowed: ${MAX_TOTAL_SUBQUERIES}. This indicates exponential include nesting. Stats: depth=${stats.maxDepth}, includes=${stats.totalIncludes}. Path: ${visitPath.join(" -> ")}. Simplify your include structure or split into multiple queries.`
3342
3342
  );
3343
3343
  }
3344
- const resolved = resolveRelationOrThrow(
3345
- model,
3346
- schemas,
3347
- schemaByName,
3348
- relName
3349
- );
3344
+ const resolved = resolveRelationOrThrow(model, schemaByName, relName);
3350
3345
  const relationPath = `${model.name}.${relName}`;
3351
3346
  const currentPath = [...visitPath, relationPath];
3352
3347
  if (visitPath.includes(relationPath)) {
@@ -3402,7 +3397,7 @@ function buildIncludeSql(args, model, schemas, parentAlias, params, dialect) {
3402
3397
  stats
3403
3398
  );
3404
3399
  }
3405
- function resolveCountRelationOrThrow(relName, model, schemas, schemaByName) {
3400
+ function resolveCountRelationOrThrow(relName, model, schemaByName) {
3406
3401
  const relationSet = getRelationFieldSet(model);
3407
3402
  if (!relationSet.has(relName)) {
3408
3403
  throw new Error(
@@ -3410,10 +3405,11 @@ function resolveCountRelationOrThrow(relName, model, schemas, schemaByName) {
3410
3405
  );
3411
3406
  }
3412
3407
  const field = model.fields.find((f) => f.name === relName);
3413
- if (!field)
3408
+ if (!field) {
3414
3409
  throw new Error(
3415
3410
  `_count.${relName} references unknown relation on model ${model.name}`
3416
3411
  );
3412
+ }
3417
3413
  if (!isValidRelationField(field)) {
3418
3414
  throw new Error(
3419
3415
  `_count.${relName} has invalid relation metadata on model ${model.name}`
@@ -3441,8 +3437,9 @@ function defaultReferencesForCount(fkCount) {
3441
3437
  }
3442
3438
  function resolveCountKeyPairs(field) {
3443
3439
  const fkFields = normalizeKeyList(field.foreignKey);
3444
- if (fkFields.length === 0)
3440
+ if (fkFields.length === 0) {
3445
3441
  throw new Error("Relation count requires foreignKey");
3442
+ }
3446
3443
  const refsRaw = field.references;
3447
3444
  const refs = normalizeKeyList(refsRaw);
3448
3445
  const refFields = refs.length > 0 ? refs : defaultReferencesForCount(fkFields.length);
@@ -3518,12 +3515,7 @@ function buildRelationCountSql(countSelect, model, schemas, parentAlias, _params
3518
3515
  for (const m of schemas) schemaByName.set(m.name, m);
3519
3516
  for (const [relName, shouldCount] of Object.entries(countSelect)) {
3520
3517
  if (!shouldCount) continue;
3521
- const resolved = resolveCountRelationOrThrow(
3522
- relName,
3523
- model,
3524
- schemas,
3525
- schemaByName
3526
- );
3518
+ const resolved = resolveCountRelationOrThrow(relName, model, schemaByName);
3527
3519
  const built = buildCountJoinAndPair({
3528
3520
  relName,
3529
3521
  field: resolved.field,
@@ -4953,24 +4945,7 @@ function generateCode(models, queries, dialect, datamodel) {
4953
4945
  }));
4954
4946
  const { mappings, fieldTypes } = extractEnumMappings(datamodel);
4955
4947
  return `// Generated by @prisma-sql/generator - DO NOT EDIT
4956
- import { buildSQL, buildBatchSql, parseBatchResults, buildBatchCountSql, parseBatchCountResults, createTransactionExecutor, transformQueryResults, type PrismaMethod, type Model, type BatchQuery, type TransactionQuery, type TransactionOptions } from 'prisma-sql'
4957
-
4958
- export interface BatchCountQuery {
4959
- model: string
4960
- method: 'count'
4961
- args?: { where?: Record<string, unknown> }
4962
- }
4963
-
4964
- export interface TransactionQuery {
4965
- model: string
4966
- method: PrismaMethod
4967
- args?: Record<string, unknown>
4968
- }
4969
-
4970
- export interface TransactionOptions {
4971
- isolationLevel?: 'ReadCommitted' | 'RepeatableRead' | 'Serializable'
4972
- timeout?: number
4973
- }
4948
+ import { buildSQL, buildBatchSql, parseBatchResults, buildBatchCountSql, parseBatchCountResults, createTransactionExecutor, transformQueryResults, type PrismaMethod, type Model, type BatchQuery, type BatchCountQuery, type TransactionQuery, type TransactionOptions } from 'prisma-sql'
4974
4949
 
4975
4950
  class DeferredQuery {
4976
4951
  constructor(
@@ -5091,6 +5066,10 @@ function normalizeValue(value: unknown, seen = new WeakSet<object>(), depth = 0)
5091
5066
  return value
5092
5067
  }
5093
5068
 
5069
+ function normalizeParams(params: unknown[]): unknown[] {
5070
+ return params.map(p => normalizeValue(p))
5071
+ }
5072
+
5094
5073
  function getByPath(obj: any, path: string): unknown {
5095
5074
  if (!obj || !path) return undefined
5096
5075
  const keys = path.split('.')
@@ -5102,11 +5081,6 @@ function getByPath(obj: any, path: string): unknown {
5102
5081
  return result
5103
5082
  }
5104
5083
 
5105
- function normalizeParams(params: unknown[]): unknown[] {
5106
- return params.map(p => normalizeValue(p))
5107
- }
5108
-
5109
-
5110
5084
  export const MODELS: Model[] = ${JSON.stringify(cleanModels, null, 2)}
5111
5085
 
5112
5086
  const ENUM_MAPPINGS: Record<string, Record<string, string>> = ${JSON.stringify(mappings, null, 2)}
@@ -5124,8 +5098,11 @@ const DIALECT = ${JSON.stringify(dialect)}
5124
5098
 
5125
5099
  const MODEL_MAP = new Map(MODELS.map(m => [m.name, m]))
5126
5100
 
5127
- function isDynamicParam(key: string): boolean {
5128
- return key === 'skip' || key === 'take' || key === 'cursor'
5101
+ function isDynamicKeyForQueryKey(path: string[], key: string): boolean {
5102
+ if (key !== 'skip' && key !== 'take' && key !== 'cursor') return false
5103
+ if (path.includes('where')) return false
5104
+ if (path.includes('data')) return false
5105
+ return true
5129
5106
  }
5130
5107
 
5131
5108
  function transformEnumInValue(value: unknown, enumType: string | undefined): unknown {
@@ -5154,28 +5131,43 @@ function transformEnumInValue(value: unknown, enumType: string | undefined): unk
5154
5131
  return value
5155
5132
  }
5156
5133
 
5157
- function transformEnumValues(modelName: string, obj: any, currentPath: string[] = []): any {
5134
+ function getRelatedModelName(currentModelName: string, relationFieldName: string): string | null {
5135
+ const m = MODEL_MAP.get(currentModelName)
5136
+ if (!m) return null
5137
+ const f: any = (m as any).fields?.find((x: any) => x?.name === relationFieldName)
5138
+ if (!f || !f.isRelation) return null
5139
+ return f.relatedModel || null
5140
+ }
5141
+
5142
+ function transformEnumValuesByModel(modelName: string, obj: any, path: string[] = []): any {
5158
5143
  if (obj === null || obj === undefined) {
5159
5144
  return obj
5160
5145
  }
5161
-
5146
+
5162
5147
  if (Array.isArray(obj)) {
5163
- return obj.map(item => transformEnumValues(modelName, item, currentPath))
5148
+ return obj.map(item => transformEnumValuesByModel(modelName, item, path))
5164
5149
  }
5165
-
5150
+
5166
5151
  if (obj instanceof Date) {
5167
5152
  return obj
5168
5153
  }
5169
-
5154
+
5170
5155
  if (typeof obj === 'object') {
5171
5156
  const transformed: any = {}
5172
5157
  const modelFields = ENUM_FIELDS[modelName] || {}
5173
-
5158
+
5174
5159
  for (const [key, value] of Object.entries(obj)) {
5175
- const newPath = [...currentPath, key]
5176
-
5160
+ const nextPath = [...path, key]
5161
+
5162
+ const relModel = getRelatedModelName(modelName, key)
5163
+
5164
+ if (relModel && value && typeof value === 'object') {
5165
+ transformed[key] = transformEnumValuesByModel(relModel, value, nextPath)
5166
+ continue
5167
+ }
5168
+
5177
5169
  const enumType = modelFields[key]
5178
-
5170
+
5179
5171
  if (enumType) {
5180
5172
  if (value && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {
5181
5173
  const transformedOperators: any = {}
@@ -5189,46 +5181,46 @@ function transformEnumValues(modelName: string, obj: any, currentPath: string[]
5189
5181
  } else if (value instanceof Date) {
5190
5182
  transformed[key] = value
5191
5183
  } else if (typeof value === 'object' && value !== null) {
5192
- transformed[key] = transformEnumValues(modelName, value, newPath)
5184
+ transformed[key] = transformEnumValuesByModel(modelName, value, nextPath)
5193
5185
  } else {
5194
5186
  transformed[key] = value
5195
5187
  }
5196
5188
  }
5189
+
5197
5190
  return transformed
5198
5191
  }
5199
-
5192
+
5200
5193
  return obj
5201
5194
  }
5202
5195
 
5203
-
5204
5196
  function normalizeQuery(args: any): string {
5205
5197
  if (!args) return '{}'
5206
-
5198
+
5207
5199
  const normalized = JSON.parse(JSON.stringify(args))
5208
-
5209
- function replaceDynamicParams(obj: any): any {
5200
+
5201
+ function replaceDynamicParams(obj: any, path: string[] = []): any {
5210
5202
  if (!obj || typeof obj !== 'object') return obj
5211
-
5203
+
5212
5204
  if (Array.isArray(obj)) {
5213
- return obj.map(replaceDynamicParams)
5205
+ return obj.map((v) => replaceDynamicParams(v, path))
5214
5206
  }
5215
-
5207
+
5216
5208
  const result: any = {}
5217
5209
  for (const [key, value] of Object.entries(obj)) {
5218
- if (isDynamicParam(key)) {
5210
+ if (isDynamicKeyForQueryKey(path, key)) {
5219
5211
  result[key] = \`__DYNAMIC_\${key}__\`
5220
5212
  } else {
5221
- result[key] = replaceDynamicParams(value)
5213
+ result[key] = replaceDynamicParams(value, [...path, key])
5222
5214
  }
5223
5215
  }
5224
5216
  return result
5225
5217
  }
5226
-
5218
+
5227
5219
  const withMarkers = replaceDynamicParams(normalized)
5228
-
5220
+
5229
5221
  function removeEmptyObjects(obj: any): any {
5230
5222
  if (!obj || typeof obj !== 'object' || Array.isArray(obj)) return obj
5231
-
5223
+
5232
5224
  const result: any = {}
5233
5225
  for (const [key, value] of Object.entries(obj)) {
5234
5226
  if (value && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length === 0) {
@@ -5238,14 +5230,14 @@ function normalizeQuery(args: any): string {
5238
5230
  }
5239
5231
  return result
5240
5232
  }
5241
-
5233
+
5242
5234
  const cleaned = removeEmptyObjects(withMarkers)
5243
-
5235
+
5244
5236
  return JSON.stringify(cleaned, (key, value) => {
5245
5237
  if (value && typeof value === 'object' && !Array.isArray(value)) {
5246
5238
  const sorted: Record<string, unknown> = {}
5247
5239
  for (const k of Object.keys(value).sort()) {
5248
- sorted[k] = value[k]
5240
+ sorted[k] = (value as any)[k]
5249
5241
  }
5250
5242
  return sorted
5251
5243
  }
@@ -5273,7 +5265,6 @@ function extractDynamicParams(args: any, dynamicKeys: string[]): unknown[] {
5273
5265
  return params
5274
5266
  }
5275
5267
 
5276
-
5277
5268
  async function executeQuery(client: any, sql: string, params: unknown[]): Promise<unknown[]> {
5278
5269
  const normalizedParams = normalizeParams(params)
5279
5270
 
@@ -5336,7 +5327,7 @@ export function speedExtension(config: {
5336
5327
  const modelName = this?.name || this?.$name
5337
5328
  const startTime = Date.now()
5338
5329
 
5339
- const transformedArgs = transformEnumValues(modelName, args || {})
5330
+ const transformedArgs = transformEnumValuesByModel(modelName, args || {})
5340
5331
 
5341
5332
  const queryKey = normalizeQuery(transformedArgs)
5342
5333
  const prebakedQuery = QUERIES[modelName]?.[method]?.[queryKey]
@@ -5489,7 +5480,7 @@ export function speedExtension(config: {
5489
5480
 
5490
5481
  onQuery?.({
5491
5482
  model: '_transaction',
5492
- method: 'count',
5483
+ method: 'transaction',
5493
5484
  sql: \`TRANSACTION(\${queries.length})\`,
5494
5485
  params: [],
5495
5486
  duration,
@@ -5501,7 +5492,7 @@ export function speedExtension(config: {
5501
5492
 
5502
5493
  return prisma.$extends({
5503
5494
  name: 'prisma-sql-generated',
5504
-
5495
+
5505
5496
  client: {
5506
5497
  $original: prisma,
5507
5498
  $batch: batch as <T extends Record<string, DeferredQuery>>(
@@ -5546,6 +5537,8 @@ export type SpeedClient<T> = T & {
5546
5537
  $batchCount(queries: BatchCountQuery[]): Promise<number[]>
5547
5538
  $transaction(queries: TransactionQuery[], options?: TransactionOptions): Promise<unknown[]>
5548
5539
  }
5540
+
5541
+ export type { BatchCountQuery, TransactionQuery, TransactionOptions }
5549
5542
  `;
5550
5543
  }
5551
5544
  function formatQueries(queries) {