prisma-arktype 2.4.0 → 2.5.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 CHANGED
@@ -132,6 +132,216 @@ const whereResult = UserWhere(whereClause);
132
132
  // ...
133
133
  ```
134
134
 
135
+ ## Where Clause Filters
136
+
137
+ Where clauses support advanced filtering through dedicated filter types. Fields can accept either direct values or filter objects with comparison operators.
138
+
139
+ ### Filter Types
140
+
141
+ #### String Filters
142
+
143
+ String fields can use `StringFilter` for advanced text filtering:
144
+
145
+ ```typescript
146
+ import { UserWhere } from "./generated/validators";
147
+
148
+ // Direct value
149
+ const result1 = UserWhere({ email: "user@example.com" });
150
+
151
+ // Filter object
152
+ const result2 = UserWhere({
153
+ email: {
154
+ contains: "example", // Contains substring
155
+ startsWith: "user", // Starts with prefix
156
+ endsWith: ".com", // Ends with suffix
157
+ equals: "user@example.com", // Exact match
158
+ not: "admin@example.com", // Not equal to
159
+ in: ["user1@example.com", "user2@example.com"], // In array
160
+ notIn: ["banned@example.com"], // Not in array
161
+ gt: "a", // Greater than (lexicographic)
162
+ gte: "a", // Greater than or equal
163
+ lt: "z", // Less than
164
+ lte: "z" // Less than or equal
165
+ }
166
+ });
167
+ ```
168
+
169
+ **Available operations:** `contains`, `startsWith`, `endsWith`, `equals`, `not`, `in`, `notIn`, `gt`, `gte`, `lt`, `lte`
170
+
171
+ #### Number Filters
172
+
173
+ Integer fields (`Int`, `BigInt`) use `IntFilter`, while floating-point fields (`Float`, `Decimal`) use `NumberFilter`:
174
+
175
+ ```typescript
176
+ import { PostWhere } from "./generated/validators";
177
+
178
+ // Direct value
179
+ const result1 = PostWhere({ views: 100 });
180
+
181
+ // Filter object for integers
182
+ const result2 = PostWhere({
183
+ views: {
184
+ equals: 100,
185
+ gt: 50, // Greater than
186
+ gte: 50, // Greater than or equal
187
+ lt: 200, // Less than
188
+ lte: 200, // Less than or equal
189
+ in: [100, 200, 300], // In array
190
+ notIn: [0], // Not in array
191
+ not: 0 // Not equal to
192
+ }
193
+ });
194
+
195
+ // Filter object for floats/decimals
196
+ const result3 = PostWhere({
197
+ rating: {
198
+ gte: 4.5,
199
+ lte: 5.0
200
+ }
201
+ });
202
+ ```
203
+
204
+ **Available operations:** `equals`, `gt`, `gte`, `lt`, `lte`, `in`, `notIn`, `not`
205
+
206
+ #### Boolean Filters
207
+
208
+ Boolean fields use `BooleanFilter`:
209
+
210
+ ```typescript
211
+ import { PostWhere } from "./generated/validators";
212
+
213
+ // Direct value
214
+ const result1 = PostWhere({ published: true });
215
+
216
+ // Filter object
217
+ const result2 = PostWhere({
218
+ published: {
219
+ equals: true,
220
+ not: false
221
+ }
222
+ });
223
+ ```
224
+
225
+ **Available operations:** `equals`, `not`
226
+
227
+ #### Enum Filters
228
+
229
+ Enum fields use the generic `enumFilter`:
230
+
231
+ ```typescript
232
+ import { PaymentWhere } from "./generated/validators";
233
+
234
+ // Direct enum value
235
+ const result1 = PaymentWhere({ currency: "USD" });
236
+
237
+ // Filter object
238
+ const result2 = PaymentWhere({
239
+ currency: {
240
+ equals: "USD",
241
+ in: ["USD", "EUR", "GBP"],
242
+ notIn: ["JPY"],
243
+ not: "CAD"
244
+ }
245
+ });
246
+ ```
247
+
248
+ **Available operations:** `equals`, `in`, `notIn`, `not`
249
+
250
+ #### DateTime Filters
251
+
252
+ DateTime fields use `DateTimeFilter`:
253
+
254
+ ```typescript
255
+ import { PostWhere } from "./generated/validators";
256
+
257
+ // Direct Date value
258
+ const result1 = PostWhere({ createdAt: new Date("2024-01-01") });
259
+
260
+ // Filter object
261
+ const result2 = PostWhere({
262
+ createdAt: {
263
+ equals: new Date("2024-01-01"),
264
+ gt: new Date("2024-01-01"), // After
265
+ gte: new Date("2024-01-01"), // On or after
266
+ lt: new Date("2024-12-31"), // Before
267
+ lte: new Date("2024-12-31"), // On or before
268
+ in: [new Date("2024-01-01"), new Date("2024-06-01")],
269
+ notIn: [new Date("2024-07-04")],
270
+ not: new Date("2024-01-01")
271
+ }
272
+ });
273
+ ```
274
+
275
+ **Available operations:** `equals`, `gt`, `gte`, `lt`, `lte`, `in`, `notIn`, `not`
276
+
277
+ #### Array Filters
278
+
279
+ Array fields use specialized array filters with operations for list matching:
280
+
281
+ ```typescript
282
+ import { TagWhere } from "./generated/validators";
283
+
284
+ // String arrays
285
+ const result1 = TagWhere({
286
+ labels: {
287
+ isEmpty: false, // Array is empty
288
+ has: "important", // Array contains value
289
+ hasEvery: ["tag1", "tag2"], // Array contains all values
290
+ hasSome: ["tag1", "tag2"], // Array contains at least one value
291
+ equals: ["exact", "match"] // Array exactly matches
292
+ }
293
+ });
294
+
295
+ // Number arrays
296
+ const result2 = ScoresWhere({
297
+ values: {
298
+ isEmpty: false,
299
+ has: 100,
300
+ hasEvery: [90, 95, 100],
301
+ hasSome: [100, 200],
302
+ equals: [90, 95, 100]
303
+ }
304
+ });
305
+
306
+ // Enum arrays
307
+ const result3 = PermissionsWhere({
308
+ roles: {
309
+ isEmpty: false,
310
+ has: "ADMIN",
311
+ hasEvery: ["USER", "ADMIN"],
312
+ hasSome: ["ADMIN", "MODERATOR"],
313
+ equals: ["USER"]
314
+ }
315
+ });
316
+ ```
317
+
318
+ **Available array filter types:**
319
+ - `StringArrayFilter` - for `String[]` fields
320
+ - `NumberArrayFilter` - for `Int[]`, `Float[]`, `Decimal[]` fields
321
+ - `BigIntArrayFilter` - for `BigInt[]` fields
322
+ - `arrayFilter(EnumType)` - for enum array fields
323
+
324
+ **Available operations:** `isEmpty`, `has`, `hasEvery`, `hasSome`, `equals`
325
+
326
+ ### Combining Filters
327
+
328
+ You can combine multiple filters in a single where clause:
329
+
330
+ ```typescript
331
+ import { PostWhere } from "./generated/validators";
332
+
333
+ const complexQuery = PostWhere({
334
+ title: { contains: "TypeScript" },
335
+ views: { gte: 100 },
336
+ published: true,
337
+ rating: { gte: 4.0 },
338
+ createdAt: {
339
+ gte: new Date("2024-01-01"),
340
+ lt: new Date("2024-12-31")
341
+ }
342
+ });
343
+ ```
344
+
135
345
  ### Generated Code Examples
136
346
 
137
347
  #### Enum Generation
package/dist/index.js CHANGED
@@ -2,7 +2,9 @@
2
2
  import { writeFile, access, rm, mkdir } from 'node:fs/promises';
3
3
  import generatorHelperPkg from '@prisma/generator-helper';
4
4
  import { type, ArkErrors } from 'arktype';
5
- import { join } from 'node:path';
5
+ import { readFileSync } from 'node:fs';
6
+ import { createRequire } from 'node:module';
7
+ import { dirname, join } from 'node:path';
6
8
 
7
9
  const configSchema = type({
8
10
  output: "string = './prisma/generated/validators'",
@@ -151,6 +153,21 @@ function extractAnnotations(documentation) {
151
153
  };
152
154
  }
153
155
 
156
+ const require = createRequire(import.meta.url);
157
+ function isPrismaV7OrHigher() {
158
+ try {
159
+ const prismaClientPath = require.resolve("@prisma/client");
160
+ const clientDir = dirname(prismaClientPath);
161
+ const packageJsonPath = join(clientDir, "package.json");
162
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
163
+ const version = packageJson.version;
164
+ const majorVersion = Number.parseInt(version.split(".")[0], 10);
165
+ return majorVersion >= 7;
166
+ } catch {
167
+ return false;
168
+ }
169
+ }
170
+ const IS_PRISMA_V7_OR_HIGHER = isPrismaV7OrHigher();
154
171
  const primitiveTypes = [
155
172
  "Int",
156
173
  "BigInt",
@@ -182,7 +199,10 @@ function stringifyPrimitiveType(type, annotations) {
182
199
  case "Boolean":
183
200
  return `"boolean"`;
184
201
  case "Bytes":
185
- return `"instanceof Buffer"`;
202
+ if (IS_PRISMA_V7_OR_HIGHER) {
203
+ return "Uint8ArrayInstance";
204
+ }
205
+ return "BufferInstance";
186
206
  default:
187
207
  throw new Error(`Unsupported primitive type: ${type}`);
188
208
  }
@@ -218,6 +238,7 @@ function stringifyEnum(enumData) {
218
238
  }
219
239
 
220
240
  const processedPlain = [];
241
+ const extRegex$1 = /\.(ts|js)$/;
221
242
  function processPlain(models) {
222
243
  for (const model of models) {
223
244
  const result = stringifyPlain(model);
@@ -226,7 +247,8 @@ function processPlain(models) {
226
247
  name: model.name,
227
248
  stringified: result.stringified,
228
249
  enumDependencies: result.enumDependencies,
229
- externalSchemaDependencies: result.externalSchemaDependencies
250
+ externalSchemaDependencies: result.externalSchemaDependencies,
251
+ runtimeDependencies: result.runtimeDependencies
230
252
  });
231
253
  }
232
254
  }
@@ -234,17 +256,16 @@ function processPlain(models) {
234
256
  }
235
257
  function stringifyPlain(model, isInputCreate = false, isInputUpdate = false) {
236
258
  const config = getConfig();
237
- const { hidden } = extractAnnotations(
238
- model.documentation
239
- );
259
+ const { hidden } = extractAnnotations(model.documentation);
240
260
  if (hidden) {
241
261
  return;
242
262
  }
243
263
  const fields = [];
244
264
  const enumDependencies = [];
245
265
  const externalSchemaDependencies = [];
266
+ const runtimeDependencies = [];
246
267
  function generateUniqueAlias(path, exportName, fieldName) {
247
- const baseName = exportName || path.split("/").pop()?.replace(/\.(ts|js)$/, "") || "Schema";
268
+ const baseName = exportName || path.split("/").pop()?.replace(extRegex$1, "") || "Schema";
248
269
  const suffix = fieldName ? `_${fieldName}` : "";
249
270
  return `${baseName}${suffix}`;
250
271
  }
@@ -309,15 +330,22 @@ function stringifyPlain(model, isInputCreate = false, isInputUpdate = false) {
309
330
  }
310
331
  const isEnumType = field.kind === "enum" && !typeOverwrite && !schemaAnnotation;
311
332
  const isExternalSchema = schemaAnnotation?.isExternal === true;
333
+ const isBytesField = field.type === "Bytes" && !typeOverwrite && !schemaAnnotation;
334
+ if (isBytesField) {
335
+ const runtimeDep = fieldType;
336
+ if (!runtimeDependencies.includes(runtimeDep)) {
337
+ runtimeDependencies.push(runtimeDep);
338
+ }
339
+ }
312
340
  if (field.isList) {
313
- if (isExternalSchema || isEnumType) {
341
+ if (isExternalSchema || isEnumType || isBytesField) {
314
342
  fieldType = `${fieldType}.array()`;
315
343
  } else {
316
344
  fieldType = `"${wrapPrimitiveWithArray(fieldType.slice(1, -1))}"`;
317
345
  }
318
346
  }
319
347
  if (!field.isRequired) {
320
- if (isExternalSchema || isEnumType) {
348
+ if (isExternalSchema || isEnumType || isBytesField) {
321
349
  fieldType = `${fieldType}.or("null")`;
322
350
  } else {
323
351
  const inner = fieldType.slice(1, -1);
@@ -337,7 +365,8 @@ function stringifyPlain(model, isInputCreate = false, isInputUpdate = false) {
337
365
  ${fields.join(",\n ")}
338
366
  }`,
339
367
  enumDependencies,
340
- externalSchemaDependencies
368
+ externalSchemaDependencies,
369
+ runtimeDependencies
341
370
  };
342
371
  }
343
372
  function stringifyPlainInputCreate(model) {
@@ -358,7 +387,8 @@ function processCreate(models) {
358
387
  name: model.name,
359
388
  stringified: result.stringified,
360
389
  enumDependencies: result.enumDependencies,
361
- externalSchemaDependencies: result.externalSchemaDependencies
390
+ externalSchemaDependencies: result.externalSchemaDependencies,
391
+ runtimeDependencies: result.runtimeDependencies
362
392
  });
363
393
  }
364
394
  }
@@ -451,9 +481,7 @@ function processRelations(models) {
451
481
  Object.freeze(processedRelations);
452
482
  }
453
483
  function stringifyRelations(model) {
454
- const { hidden } = extractAnnotations(
455
- model.documentation
456
- );
484
+ const { hidden } = extractAnnotations(model.documentation);
457
485
  if (hidden) {
458
486
  return;
459
487
  }
@@ -500,9 +528,7 @@ function processRelationsCreate(models) {
500
528
  Object.freeze(processedRelationsCreate);
501
529
  }
502
530
  function stringifyRelationsInputCreate(model, allModels) {
503
- const { hidden } = extractAnnotations(
504
- model.documentation
505
- );
531
+ const { hidden } = extractAnnotations(model.documentation);
506
532
  if (hidden) {
507
533
  return;
508
534
  }
@@ -547,9 +573,7 @@ function processRelationsUpdate(models) {
547
573
  Object.freeze(processedRelationsUpdate);
548
574
  }
549
575
  function stringifyRelationsInputUpdate(model, allModels) {
550
- const { hidden } = extractAnnotations(
551
- model.documentation
552
- );
576
+ const { hidden } = extractAnnotations(model.documentation);
553
577
  if (hidden) {
554
578
  return;
555
579
  }
@@ -634,7 +658,8 @@ function processUpdate(models) {
634
658
  name: model.name,
635
659
  stringified: result.stringified,
636
660
  enumDependencies: result.enumDependencies,
637
- externalSchemaDependencies: result.externalSchemaDependencies
661
+ externalSchemaDependencies: result.externalSchemaDependencies,
662
+ runtimeDependencies: result.runtimeDependencies
638
663
  });
639
664
  }
640
665
  }
@@ -652,7 +677,8 @@ function processWhere(models) {
652
677
  name: model.name,
653
678
  stringified: result.stringified,
654
679
  enumDependencies: result.enumDependencies,
655
- externalSchemaDependencies: result.externalSchemaDependencies
680
+ externalSchemaDependencies: result.externalSchemaDependencies,
681
+ runtimeDependencies: result.runtimeDependencies
656
682
  });
657
683
  }
658
684
  const uniqueResult = stringifyWhereUnique(model);
@@ -661,7 +687,8 @@ function processWhere(models) {
661
687
  name: model.name,
662
688
  stringified: uniqueResult.stringified,
663
689
  enumDependencies: uniqueResult.enumDependencies,
664
- externalSchemaDependencies: uniqueResult.externalSchemaDependencies
690
+ externalSchemaDependencies: uniqueResult.externalSchemaDependencies,
691
+ runtimeDependencies: uniqueResult.runtimeDependencies
665
692
  });
666
693
  }
667
694
  }
@@ -676,6 +703,7 @@ function stringifyWhere(model) {
676
703
  const fields = [];
677
704
  const enumDependencies = [];
678
705
  const externalSchemaDependencies = [];
706
+ const runtimeDependencies = [];
679
707
  function generateUniqueAlias(path, exportName, fieldName) {
680
708
  const baseName = exportName || path.split("/").pop()?.replace(extRegex, "") || "Schema";
681
709
  const suffix = fieldName ? `_${fieldName}` : "";
@@ -729,14 +757,82 @@ function stringifyWhere(model) {
729
757
  }
730
758
  const isEnumType = field.kind === "enum" && !typeOverwrite && !schemaAnnotation;
731
759
  const isExternalSchema = schemaAnnotation?.isExternal === true;
760
+ const isDateTimeField = field.type === "DateTime" && !typeOverwrite && !schemaAnnotation;
761
+ const isStringField = field.type === "String" && !typeOverwrite && !schemaAnnotation;
762
+ const isIntField = (field.type === "Int" || field.type === "BigInt") && !typeOverwrite && !schemaAnnotation;
763
+ const isFloatField = (field.type === "Float" || field.type === "Decimal") && !typeOverwrite && !schemaAnnotation;
764
+ const isBooleanField = field.type === "Boolean" && !typeOverwrite && !schemaAnnotation;
765
+ const isBytesField = field.type === "Bytes" && !typeOverwrite && !schemaAnnotation;
766
+ if (isBytesField) {
767
+ const runtimeDep = fieldType;
768
+ if (!runtimeDependencies.includes(runtimeDep)) {
769
+ runtimeDependencies.push(runtimeDep);
770
+ }
771
+ }
732
772
  if (field.isList) {
733
- if (isExternalSchema || isEnumType) {
773
+ if (isEnumType) {
774
+ fieldType = `arrayFilter(${fieldType})`;
775
+ if (!runtimeDependencies.includes("arrayFilter")) {
776
+ runtimeDependencies.push("arrayFilter");
777
+ }
778
+ } else if (field.type === "String" && !typeOverwrite && !schemaAnnotation) {
779
+ fieldType = "StringArrayFilter";
780
+ if (!runtimeDependencies.includes("StringArrayFilter")) {
781
+ runtimeDependencies.push("StringArrayFilter");
782
+ }
783
+ } else if ((field.type === "Int" || field.type === "Float" || field.type === "Decimal") && !typeOverwrite && !schemaAnnotation) {
784
+ fieldType = "NumberArrayFilter";
785
+ if (!runtimeDependencies.includes("NumberArrayFilter")) {
786
+ runtimeDependencies.push("NumberArrayFilter");
787
+ }
788
+ } else if (field.type === "BigInt" && !typeOverwrite && !schemaAnnotation) {
789
+ fieldType = "BigIntArrayFilter";
790
+ if (!runtimeDependencies.includes("BigIntArrayFilter")) {
791
+ runtimeDependencies.push("BigIntArrayFilter");
792
+ }
793
+ } else if (isExternalSchema || isBytesField) {
734
794
  fieldType = `${fieldType}.array()`;
735
795
  } else {
736
796
  const inner = fieldType.slice(1, -1);
737
797
  fieldType = `"${wrapPrimitiveWithArray(inner)}"`;
738
798
  }
739
799
  }
800
+ if (isDateTimeField && !field.isList) {
801
+ fieldType = `type("Date").or(DateTimeFilter)`;
802
+ if (!runtimeDependencies.includes("DateTimeFilter")) {
803
+ runtimeDependencies.push("DateTimeFilter");
804
+ }
805
+ }
806
+ if (isStringField && !field.isList) {
807
+ fieldType = `type("string").or(StringFilter)`;
808
+ if (!runtimeDependencies.includes("StringFilter")) {
809
+ runtimeDependencies.push("StringFilter");
810
+ }
811
+ }
812
+ if (isIntField && !field.isList) {
813
+ fieldType = `type("number.integer").or(IntFilter)`;
814
+ if (!runtimeDependencies.includes("IntFilter")) {
815
+ runtimeDependencies.push("IntFilter");
816
+ }
817
+ }
818
+ if (isFloatField && !field.isList) {
819
+ fieldType = `type("number").or(NumberFilter)`;
820
+ if (!runtimeDependencies.includes("NumberFilter")) {
821
+ runtimeDependencies.push("NumberFilter");
822
+ }
823
+ }
824
+ if (isEnumType && !field.isList) {
825
+ fieldType = `type(${fieldType}).or(enumFilter(${fieldType}))`;
826
+ if (!runtimeDependencies.includes("enumFilter")) {
827
+ runtimeDependencies.push("enumFilter");
828
+ }
829
+ }
830
+ if (isBooleanField && !field.isList) {
831
+ fieldType = `type("boolean").or(BooleanFilter)`;
832
+ if (!runtimeDependencies.includes("BooleanFilter")) {
833
+ runtimeDependencies.push("BooleanFilter");
834
+ }
835
+ }
740
836
  fields.push(`"${field.name}?": ${fieldType}`);
741
837
  }
742
838
  return {
@@ -744,7 +840,8 @@ function stringifyWhere(model) {
744
840
  ${fields.join(",\n ")}
745
841
  }`,
746
842
  enumDependencies,
747
- externalSchemaDependencies
843
+ externalSchemaDependencies,
844
+ runtimeDependencies
748
845
  };
749
846
  }
750
847
  function stringifyWhereUnique(model) {
@@ -755,6 +852,7 @@ function stringifyWhereUnique(model) {
755
852
  const fields = [];
756
853
  const enumDependencies = [];
757
854
  const externalSchemaDependencies = [];
855
+ const runtimeDependencies = [];
758
856
  function generateUniqueAlias(path, exportName, fieldName) {
759
857
  const baseName = exportName || path.split("/").pop()?.replace(extRegex, "") || "Schema";
760
858
  const suffix = fieldName ? `_${fieldName}` : "";
@@ -807,6 +905,20 @@ function stringifyWhereUnique(model) {
807
905
  } else {
808
906
  continue;
809
907
  }
908
+ const isDateTimeField = field.type === "DateTime" && !typeOverwrite && !schemaAnnotation;
909
+ const isBytesField = field.type === "Bytes" && !typeOverwrite && !schemaAnnotation;
910
+ if (isBytesField) {
911
+ const runtimeDep = fieldType;
912
+ if (!runtimeDependencies.includes(runtimeDep)) {
913
+ runtimeDependencies.push(runtimeDep);
914
+ }
915
+ }
916
+ if (isDateTimeField) {
917
+ fieldType = `type("Date").or(DateTimeFilter)`;
918
+ if (!runtimeDependencies.includes("DateTimeFilter")) {
919
+ runtimeDependencies.push("DateTimeFilter");
920
+ }
921
+ }
810
922
  fields.push(`"${field.name}?": ${fieldType}`);
811
923
  }
812
924
  if (fields.length === 0) {
@@ -817,7 +929,8 @@ function stringifyWhereUnique(model) {
817
929
  ${fields.join(",\n ")}
818
930
  }`,
819
931
  enumDependencies,
820
- externalSchemaDependencies
932
+ externalSchemaDependencies,
933
+ runtimeDependencies
821
934
  };
822
935
  }
823
936
 
@@ -852,6 +965,38 @@ function generateExternalSchemaImports(externalSchemaDependencies) {
852
965
  }).join("\n")}
853
966
  `;
854
967
  }
968
+ const RUNTIME_DEPENDENCY_IMPORTS = {
969
+ DateTimeFilter: `import { DateTimeFilter } from "prisma-arktype/runtime/filters";
970
+ `,
971
+ StringFilter: `import { StringFilter } from "prisma-arktype/runtime/stringFilter";
972
+ `,
973
+ NumberFilter: `import { NumberFilter } from "prisma-arktype/runtime/numberFilter";
974
+ `,
975
+ IntFilter: `import { IntFilter } from "prisma-arktype/runtime/numberFilter";
976
+ `,
977
+ BooleanFilter: `import { BooleanFilter } from "prisma-arktype/runtime/booleanFilter";
978
+ `,
979
+ enumFilter: `import { enumFilter } from "prisma-arktype/runtime/enumFilter";
980
+ `,
981
+ BufferInstance: `import { BufferInstance } from "prisma-arktype/runtime/buffer";
982
+ `,
983
+ Uint8ArrayInstance: `import { Uint8ArrayInstance } from "prisma-arktype/runtime/uint8array";
984
+ `,
985
+ arrayFilter: `import { arrayFilter } from "prisma-arktype/runtime/arrayFilters";
986
+ `,
987
+ StringArrayFilter: `import { StringArrayFilter } from "prisma-arktype/runtime/arrayFilters";
988
+ `,
989
+ NumberArrayFilter: `import { NumberArrayFilter } from "prisma-arktype/runtime/arrayFilters";
990
+ `,
991
+ BigIntArrayFilter: `import { BigIntArrayFilter } from "prisma-arktype/runtime/arrayFilters";
992
+ `
993
+ };
994
+ function generateRuntimeDependencyImports(runtimeDependencies) {
995
+ if (!runtimeDependencies || runtimeDependencies.length === 0) {
996
+ return "";
997
+ }
998
+ return runtimeDependencies.map((dep) => RUNTIME_DEPENDENCY_IMPORTS[dep]).join("");
999
+ }
855
1000
  function mapAllModelsForWrite(processedEnums, processedPlain, processedRelations, processedWhere, processedWhereUnique, processedCreate, processedUpdate, processedRelationsCreate, processedRelationsUpdate, processedSelect, processedInclude, processedOrderBy) {
856
1001
  const config = getConfig();
857
1002
  const modelMap = /* @__PURE__ */ new Map();
@@ -868,7 +1013,10 @@ function mapAllModelsForWrite(processedEnums, processedPlain, processedRelations
868
1013
  const externalSchemaImports = generateExternalSchemaImports(
869
1014
  model.externalSchemaDependencies
870
1015
  );
871
- const content = `${arktypeImport}${enumImports}${externalSchemaImports}export const ${model.name}Plain = type(${model.stringified});
1016
+ const runtimeImports = generateRuntimeDependencyImports(
1017
+ model.runtimeDependencies
1018
+ );
1019
+ const content = `${arktypeImport}${enumImports}${externalSchemaImports}${runtimeImports}export const ${model.name}Plain = type(${model.stringified});
872
1020
  `;
873
1021
  modelMap.set(`${model.name}Plain`, content);
874
1022
  }
@@ -900,7 +1048,10 @@ export const ${plain.name} = ${plain.name}Plain;
900
1048
  const externalSchemaImports = generateExternalSchemaImports(
901
1049
  model.externalSchemaDependencies
902
1050
  );
903
- const content = `${arktypeImport}${enumImports}${externalSchemaImports}export const ${model.name}Where = type(${model.stringified});
1051
+ const runtimeImports = generateRuntimeDependencyImports(
1052
+ model.runtimeDependencies
1053
+ );
1054
+ const content = `${arktypeImport}${enumImports}${externalSchemaImports}${runtimeImports}export const ${model.name}Where = type(${model.stringified});
904
1055
  `;
905
1056
  modelMap.set(`${model.name}Where`, content);
906
1057
  }
@@ -909,7 +1060,10 @@ export const ${plain.name} = ${plain.name}Plain;
909
1060
  const externalSchemaImports = generateExternalSchemaImports(
910
1061
  model.externalSchemaDependencies
911
1062
  );
912
- const content = `${arktypeImport}${enumImports}${externalSchemaImports}export const ${model.name}WhereUnique = type(${model.stringified});
1063
+ const runtimeImports = generateRuntimeDependencyImports(
1064
+ model.runtimeDependencies
1065
+ );
1066
+ const content = `${arktypeImport}${enumImports}${externalSchemaImports}${runtimeImports}export const ${model.name}WhereUnique = type(${model.stringified});
913
1067
  `;
914
1068
  modelMap.set(`${model.name}WhereUnique`, content);
915
1069
  }
@@ -918,7 +1072,10 @@ export const ${plain.name} = ${plain.name}Plain;
918
1072
  const externalSchemaImports = generateExternalSchemaImports(
919
1073
  model.externalSchemaDependencies
920
1074
  );
921
- const content = `${arktypeImport}${enumImports}${externalSchemaImports}export const ${model.name}Create = type(${model.stringified});
1075
+ const runtimeImports = generateRuntimeDependencyImports(
1076
+ model.runtimeDependencies
1077
+ );
1078
+ const content = `${arktypeImport}${enumImports}${externalSchemaImports}${runtimeImports}export const ${model.name}Create = type(${model.stringified});
922
1079
  `;
923
1080
  modelMap.set(`${model.name}Create`, content);
924
1081
  }
@@ -927,7 +1084,10 @@ export const ${plain.name} = ${plain.name}Plain;
927
1084
  const externalSchemaImports = generateExternalSchemaImports(
928
1085
  model.externalSchemaDependencies
929
1086
  );
930
- const content = `${arktypeImport}${enumImports}${externalSchemaImports}export const ${model.name}Update = type(${model.stringified});
1087
+ const runtimeImports = generateRuntimeDependencyImports(
1088
+ model.runtimeDependencies
1089
+ );
1090
+ const content = `${arktypeImport}${enumImports}${externalSchemaImports}${runtimeImports}export const ${model.name}Update = type(${model.stringified});
931
1091
  `;
932
1092
  modelMap.set(`${model.name}Update`, content);
933
1093
  }
@@ -0,0 +1,46 @@
1
+ import * as arktype_internal_variants_object_ts from 'arktype/internal/variants/object.ts';
2
+ import * as arktype from 'arktype';
3
+
4
+ /**
5
+ * @description Generic array filter for Prisma where clauses
6
+ * Supports: isEmpty, has, hasEvery, hasSome, equals
7
+ */
8
+ declare const arrayFilter: arktype.Generic<[["t", unknown]], {
9
+ readonly "isEmpty?": "boolean";
10
+ readonly "has?": "t";
11
+ readonly "hasEvery?": "t[]";
12
+ readonly "hasSome?": "t[]";
13
+ readonly "equals?": "t[]";
14
+ }, {}, {}>;
15
+ /**
16
+ * @description String array filter for Prisma where clauses
17
+ */
18
+ declare const StringArrayFilter: arktype_internal_variants_object_ts.ObjectType<{
19
+ isEmpty?: boolean;
20
+ has?: string;
21
+ hasEvery?: string[];
22
+ hasSome?: string[];
23
+ equals?: string[];
24
+ }, {}>;
25
+ /**
26
+ * @description Number array filter for Prisma where clauses
27
+ */
28
+ declare const NumberArrayFilter: arktype_internal_variants_object_ts.ObjectType<{
29
+ isEmpty?: boolean;
30
+ has?: number;
31
+ hasEvery?: number[];
32
+ hasSome?: number[];
33
+ equals?: number[];
34
+ }, {}>;
35
+ /**
36
+ * @description BigInt array filter for Prisma where clauses
37
+ */
38
+ declare const BigIntArrayFilter: arktype_internal_variants_object_ts.ObjectType<{
39
+ isEmpty?: boolean;
40
+ has?: number;
41
+ hasEvery?: number[];
42
+ hasSome?: number[];
43
+ equals?: number[];
44
+ }, {}>;
45
+
46
+ export { BigIntArrayFilter, NumberArrayFilter, StringArrayFilter, arrayFilter };
@@ -0,0 +1,14 @@
1
+ import { type } from 'arktype';
2
+
3
+ const arrayFilter = type("<t>", {
4
+ "isEmpty?": "boolean",
5
+ "has?": "t",
6
+ "hasEvery?": "t[]",
7
+ "hasSome?": "t[]",
8
+ "equals?": "t[]"
9
+ });
10
+ const StringArrayFilter = arrayFilter("string");
11
+ const NumberArrayFilter = arrayFilter("number");
12
+ const BigIntArrayFilter = arrayFilter("number.integer");
13
+
14
+ export { BigIntArrayFilter, NumberArrayFilter, StringArrayFilter, arrayFilter };
@@ -0,0 +1,12 @@
1
+ import * as arktype_internal_variants_object_ts from 'arktype/internal/variants/object.ts';
2
+
3
+ /**
4
+ * @description Boolean filter for Prisma where clauses
5
+ * Supports: equals, not
6
+ */
7
+ declare const BooleanFilter: arktype_internal_variants_object_ts.ObjectType<{
8
+ equals?: boolean;
9
+ not?: boolean;
10
+ }, {}>;
11
+
12
+ export { BooleanFilter };
@@ -0,0 +1,8 @@
1
+ import { type } from 'arktype';
2
+
3
+ const BooleanFilter = type({
4
+ "equals?": "boolean",
5
+ "not?": "boolean"
6
+ });
7
+
8
+ export { BooleanFilter };
@@ -0,0 +1,8 @@
1
+ import * as arktype_internal_variants_object_ts from 'arktype/internal/variants/object.ts';
2
+
3
+ /**
4
+ * @description Buffer instance type
5
+ */
6
+ declare const BufferInstance: arktype_internal_variants_object_ts.ObjectType<Buffer<ArrayBufferLike>, {}>;
7
+
8
+ export { BufferInstance };
@@ -0,0 +1,14 @@
1
+ import { type } from 'arktype';
2
+
3
+ const BufferInstance = type("unknown").narrow(
4
+ (value, ctx) => {
5
+ if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) {
6
+ return true;
7
+ } else if (typeof Buffer === "undefined") {
8
+ ctx.errors.add(ctx.error("Buffer is not defined in this environment"));
9
+ }
10
+ return ctx.mustBe("an instance of Buffer");
11
+ }
12
+ );
13
+
14
+ export { BufferInstance };
@@ -0,0 +1,14 @@
1
+ import * as arktype from 'arktype';
2
+
3
+ /**
4
+ * @description Generic enum filter for Prisma where clauses
5
+ * Supports: equals, in, not, notIn
6
+ */
7
+ declare const enumFilter: arktype.Generic<[["t", unknown]], {
8
+ readonly "equals?": "t";
9
+ readonly "in?": "t[]";
10
+ readonly "not?": "t";
11
+ readonly "notIn?": "t[]";
12
+ }, {}, {}>;
13
+
14
+ export { enumFilter };
@@ -0,0 +1,10 @@
1
+ import { type } from 'arktype';
2
+
3
+ const enumFilter = type("<t>", {
4
+ "equals?": "t",
5
+ "in?": "t[]",
6
+ "not?": "t",
7
+ "notIn?": "t[]"
8
+ });
9
+
10
+ export { enumFilter };
@@ -0,0 +1,19 @@
1
+ import * as arktype_internal_variants_object_ts from 'arktype/internal/variants/object.ts';
2
+
3
+ /**
4
+ * DateTimeFilter allows querying DateTime fields with comparison operators.
5
+ * Can be used instead of a direct Date value in where clauses.
6
+ */
7
+ declare const DateTimeFilter: arktype_internal_variants_object_ts.ObjectType<{
8
+ equals?: Date;
9
+ in?: Date[];
10
+ notIn?: Date[];
11
+ lt?: Date;
12
+ lte?: Date;
13
+ gt?: Date;
14
+ gte?: Date;
15
+ not?: Date;
16
+ }, {}>;
17
+ type DateTimeFilter = typeof DateTimeFilter.infer;
18
+
19
+ export { DateTimeFilter };
@@ -0,0 +1,14 @@
1
+ import { type } from 'arktype';
2
+
3
+ const DateTimeFilter = type({
4
+ "equals?": "Date",
5
+ "in?": "Date[]",
6
+ "notIn?": "Date[]",
7
+ "lt?": "Date",
8
+ "lte?": "Date",
9
+ "gt?": "Date",
10
+ "gte?": "Date",
11
+ "not?": "Date"
12
+ });
13
+
14
+ export { DateTimeFilter };
@@ -0,0 +1,32 @@
1
+ import * as arktype_internal_variants_object_ts from 'arktype/internal/variants/object.ts';
2
+
3
+ /**
4
+ * @description Number filter for Prisma where clauses
5
+ * Supports: equals, gt, gte, in, lt, lte, not, notIn
6
+ */
7
+ declare const NumberFilter: arktype_internal_variants_object_ts.ObjectType<{
8
+ equals?: number;
9
+ gt?: number;
10
+ gte?: number;
11
+ in?: number[];
12
+ lt?: number;
13
+ lte?: number;
14
+ not?: number;
15
+ notIn?: number[];
16
+ }, {}>;
17
+ /**
18
+ * @description Integer filter for Prisma where clauses (Int, BigInt)
19
+ * Supports: equals, gt, gte, in, lt, lte, not, notIn
20
+ */
21
+ declare const IntFilter: arktype_internal_variants_object_ts.ObjectType<{
22
+ equals?: number;
23
+ gt?: number;
24
+ gte?: number;
25
+ in?: number[];
26
+ lt?: number;
27
+ lte?: number;
28
+ not?: number;
29
+ notIn?: number[];
30
+ }, {}>;
31
+
32
+ export { IntFilter, NumberFilter };
@@ -0,0 +1,24 @@
1
+ import { type } from 'arktype';
2
+
3
+ const NumberFilter = type({
4
+ "equals?": "number",
5
+ "gt?": "number",
6
+ "gte?": "number",
7
+ "in?": "number[]",
8
+ "lt?": "number",
9
+ "lte?": "number",
10
+ "not?": "number",
11
+ "notIn?": "number[]"
12
+ });
13
+ const IntFilter = type({
14
+ "equals?": "number.integer",
15
+ "gt?": "number.integer",
16
+ "gte?": "number.integer",
17
+ "in?": "number.integer[]",
18
+ "lt?": "number.integer",
19
+ "lte?": "number.integer",
20
+ "not?": "number.integer",
21
+ "notIn?": "number.integer[]"
22
+ });
23
+
24
+ export { IntFilter, NumberFilter };
@@ -0,0 +1,21 @@
1
+ import * as arktype_internal_variants_object_ts from 'arktype/internal/variants/object.ts';
2
+
3
+ /**
4
+ * @description String filter for Prisma where clauses
5
+ * Supports: contains, endsWith, equals, gt, gte, in, lt, lte, not, notIn, startsWith
6
+ */
7
+ declare const StringFilter: arktype_internal_variants_object_ts.ObjectType<{
8
+ contains?: string;
9
+ endsWith?: string;
10
+ equals?: string;
11
+ gt?: string;
12
+ gte?: string;
13
+ in?: string[];
14
+ lt?: string;
15
+ lte?: string;
16
+ not?: string;
17
+ notIn?: string[];
18
+ startsWith?: string;
19
+ }, {}>;
20
+
21
+ export { StringFilter };
@@ -0,0 +1,17 @@
1
+ import { type } from 'arktype';
2
+
3
+ const StringFilter = type({
4
+ "contains?": "string",
5
+ "endsWith?": "string",
6
+ "equals?": "string",
7
+ "gt?": "string",
8
+ "gte?": "string",
9
+ "in?": "string[]",
10
+ "lt?": "string",
11
+ "lte?": "string",
12
+ "not?": "string",
13
+ "notIn?": "string[]",
14
+ "startsWith?": "string"
15
+ });
16
+
17
+ export { StringFilter };
@@ -0,0 +1,9 @@
1
+ import * as arktype_internal_variants_object_ts from 'arktype/internal/variants/object.ts';
2
+
3
+ /**
4
+ * @description Uint8Array instance type for Prisma v7+
5
+ * In Prisma v7+, Bytes fields return as Uint8Array instead of Buffer
6
+ */
7
+ declare const Uint8ArrayInstance: arktype_internal_variants_object_ts.ObjectType<Uint8Array<ArrayBufferLike>, {}>;
8
+
9
+ export { Uint8ArrayInstance };
@@ -0,0 +1,12 @@
1
+ import { type } from 'arktype';
2
+
3
+ const Uint8ArrayInstance = type("unknown").narrow(
4
+ (value, ctx) => {
5
+ if (value instanceof Uint8Array) {
6
+ return true;
7
+ }
8
+ return ctx.mustBe("an instance of Uint8Array");
9
+ }
10
+ );
11
+
12
+ export { Uint8ArrayInstance };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prisma-arktype",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "Generate ArkType schemas from your Prisma schema",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -9,6 +9,38 @@
9
9
  ".": {
10
10
  "import": "./dist/index.js",
11
11
  "types": "./dist/index.d.ts"
12
+ },
13
+ "./runtime/filters": {
14
+ "import": "./dist/runtime/filters.js",
15
+ "types": "./dist/runtime/filters.d.ts"
16
+ },
17
+ "./runtime/buffer": {
18
+ "import": "./dist/runtime/buffer.js",
19
+ "types": "./dist/runtime/buffer.d.ts"
20
+ },
21
+ "./runtime/uint8array": {
22
+ "import": "./dist/runtime/uint8array.js",
23
+ "types": "./dist/runtime/uint8array.d.ts"
24
+ },
25
+ "./runtime/arrayFilters": {
26
+ "import": "./dist/runtime/arrayFilters.js",
27
+ "types": "./dist/runtime/arrayFilters.d.ts"
28
+ },
29
+ "./runtime/stringFilter": {
30
+ "import": "./dist/runtime/stringFilter.js",
31
+ "types": "./dist/runtime/stringFilter.d.ts"
32
+ },
33
+ "./runtime/numberFilter": {
34
+ "import": "./dist/runtime/numberFilter.js",
35
+ "types": "./dist/runtime/numberFilter.d.ts"
36
+ },
37
+ "./runtime/enumFilter": {
38
+ "import": "./dist/runtime/enumFilter.js",
39
+ "types": "./dist/runtime/enumFilter.d.ts"
40
+ },
41
+ "./runtime/booleanFilter": {
42
+ "import": "./dist/runtime/booleanFilter.js",
43
+ "types": "./dist/runtime/booleanFilter.d.ts"
12
44
  }
13
45
  },
14
46
  "bin": {
@@ -39,12 +71,16 @@
39
71
  "@prisma/generator-helper": "^6.18.0",
40
72
  "arktype": "^2.1.25"
41
73
  },
74
+ "peerDependencies": {
75
+ "@prisma/client": ">=6"
76
+ },
42
77
  "devDependencies": {
43
78
  "@biomejs/biome": "2.3.11",
44
79
  "@changesets/cli": "2.29.8",
45
80
  "@commitlint/cli": "^20.1.0",
46
81
  "@commitlint/config-conventional": "^20.0.0",
47
- "@prisma/client": "^6.18.0",
82
+ "@prisma/client": "7.2.0",
83
+ "@prisma/internals": "7.2.0",
48
84
  "@tilli-pro/biome": "0.9.0",
49
85
  "@types/node": "^24.10.0",
50
86
  "lefthook": "^2.0.2",
@@ -66,6 +102,16 @@
66
102
  "lint:fix": "biome check --write",
67
103
  "changeset": "changeset",
68
104
  "version": "changeset version",
69
- "release": "pnpm build && changeset publish"
105
+ "release": "pnpm build && changeset publish",
106
+ "bench": "vitest bench --config vitest.bench.config.ts",
107
+ "bench:ui": "vitest bench --ui --config vitest.bench.config.ts",
108
+ "bench:generation": "vitest bench __benchmarks__/suites/generation.bench.ts --config vitest.bench.config.ts",
109
+ "bench:processors": "vitest bench __benchmarks__/suites/processors.bench.ts --config vitest.bench.config.ts",
110
+ "bench:annotations": "vitest bench __benchmarks__/suites/annotations.bench.ts --config vitest.bench.config.ts",
111
+ "bench:memory": "node --expose-gc node_modules/.bin/vitest bench __benchmarks__/suites/memory.bench.ts --config vitest.bench.config.ts",
112
+ "bench:compare": "tsx __benchmarks__/scripts/compare.ts",
113
+ "bench:update-baseline": "tsx __benchmarks__/scripts/update-baseline.ts",
114
+ "bench:profile": "node --cpu-prof --expose-gc node_modules/.bin/vitest bench --config vitest.bench.config.ts",
115
+ "bench:ci": "tsx __benchmarks__/scripts/run-and-save.ts"
70
116
  }
71
117
  }