prisma-arktype 2.3.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
@@ -239,6 +449,7 @@ Control schema generation using annotations in your Prisma schema. All annotatio
239
449
  | `@prisma-arktype.input.hide` | Field | Hide from Create and Update input schemas |
240
450
  | `@prisma-arktype.create.input.hide` | Field | Hide from Create input schema only |
241
451
  | `@prisma-arktype.update.input.hide` | Field | Hide from Update input schema only |
452
+ | `@prisma-arktype.schema="<schema>"` | Field | Custom ArkType schema (inline or external) |
242
453
  | `@prisma-arktype.typeOverwrite="<type>"` | Field | Override the generated ArkType type |
243
454
 
244
455
  ### Hide Fields/Models
@@ -301,6 +512,48 @@ model User {
301
512
 
302
513
  This allows you to use any ArkType type definition, including built-in refinements like `string.email`, `string.url`, `number.integer`, etc.
303
514
 
515
+ ### Custom Schemas
516
+
517
+ Bring your own ArkType schemas for any field using `@prisma-arktype.schema`:
518
+
519
+ ```prisma
520
+ model User {
521
+ id String @id
522
+
523
+ /// Inline schema for structured JSON
524
+ /// @prisma-arktype.schema="{ name: 'string', age: 'number' }"
525
+ profile Json
526
+
527
+ /// External schema from a file (named export)
528
+ /// @prisma-arktype.schema="../schemas/address:AddressSchema"
529
+ address Json
530
+
531
+ /// External schema (default export)
532
+ /// @prisma-arktype.schema="../schemas/config"
533
+ settings Json
534
+ }
535
+ ```
536
+
537
+ **Import Path Rules:**
538
+ - Paths are relative to the generated validators directory
539
+ - Named exports use colon syntax: `"path:ExportName"`
540
+ - Default exports omit the colon: `"path"`
541
+ - Works with ANY field type (not just Json)
542
+
543
+ **Priority:** `schema` > `typeOverwrite` > default type mapping
544
+
545
+ **Example external schema file** (`schemas/address.ts`):
546
+ ```typescript
547
+ import { type } from "arktype";
548
+
549
+ export const AddressSchema = type({
550
+ street: "string",
551
+ city: "string",
552
+ zipCode: "string",
553
+ country: "string",
554
+ });
555
+ ```
556
+
304
557
  ## Type Mapping
305
558
 
306
559
  Prisma types are mapped to ArkType as follows:
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'",
@@ -43,6 +45,9 @@ function isHiddenInputUpdate(annotation) {
43
45
  function isTypeOverwrite(annotation) {
44
46
  return annotation.type === "TYPE_OVERWRITE";
45
47
  }
48
+ function isSchema(annotation) {
49
+ return annotation.type === "SCHEMA";
50
+ }
46
51
  const annotationKeys = [
47
52
  {
48
53
  keys: ["@prisma-arktype.hide", "@prisma-arktype.hidden"],
@@ -66,9 +71,11 @@ const annotationKeys = [
66
71
  ],
67
72
  type: "HIDDEN_INPUT_UPDATE"
68
73
  },
69
- { keys: ["@prisma-arktype.typeOverwrite"], type: "TYPE_OVERWRITE" }
74
+ { keys: ["@prisma-arktype.typeOverwrite"], type: "TYPE_OVERWRITE" },
75
+ { keys: ["@prisma-arktype.schema"], type: "SCHEMA" }
70
76
  ];
71
77
  const prismaArktypeTypeOverwriteRegex = /@prisma-arktype\.typeOverwrite=(.+)/;
78
+ const prismaArktypeSchemaRegex = /@prisma-arktype\.schema="([^"]+)"/;
72
79
  function extractAnnotations(documentation) {
73
80
  const annotations = [];
74
81
  const descriptionLines = [];
@@ -78,18 +85,52 @@ function extractAnnotations(documentation) {
78
85
  for (const { keys, type } of annotationKeys) {
79
86
  for (const key of keys) {
80
87
  if (line.includes(key)) {
81
- isAnnotation = true;
82
88
  if (type === "TYPE_OVERWRITE") {
83
89
  const match = line.match(prismaArktypeTypeOverwriteRegex);
84
90
  if (match && match[1]) {
91
+ isAnnotation = true;
85
92
  annotations.push({
86
93
  type: "TYPE_OVERWRITE",
87
94
  value: match[1].trim()
88
95
  });
89
- } else {
90
- throw new Error(`Invalid TYPE_OVERWRITE annotation: ${line}`);
96
+ }
97
+ } else if (type === "SCHEMA") {
98
+ const match = line.match(prismaArktypeSchemaRegex);
99
+ if (match && match[1]) {
100
+ isAnnotation = true;
101
+ const schemaValue = match[1].trim();
102
+ const isExternal = schemaValue.includes("/") || !(schemaValue.startsWith("{") || schemaValue.startsWith('"') || schemaValue.startsWith("'")) && schemaValue.includes(":") && // Ensure it's a module:export pattern, not object syntax like { key: value }
103
+ !schemaValue.includes(" ") && !schemaValue.includes(",");
104
+ if (isExternal) {
105
+ const colonIndex = schemaValue.indexOf(":");
106
+ if (colonIndex > 0) {
107
+ const path = schemaValue.substring(0, colonIndex).trim();
108
+ const exportName = schemaValue.substring(colonIndex + 1).trim();
109
+ annotations.push({
110
+ type: "SCHEMA",
111
+ value: schemaValue,
112
+ isExternal: true,
113
+ importPath: path,
114
+ exportName
115
+ });
116
+ } else {
117
+ annotations.push({
118
+ type: "SCHEMA",
119
+ value: schemaValue,
120
+ isExternal: true,
121
+ importPath: schemaValue
122
+ });
123
+ }
124
+ } else {
125
+ annotations.push({
126
+ type: "SCHEMA",
127
+ value: schemaValue,
128
+ isExternal: false
129
+ });
130
+ }
91
131
  }
92
132
  } else {
133
+ isAnnotation = true;
93
134
  annotations.push({ type });
94
135
  }
95
136
  break;
@@ -112,6 +153,21 @@ function extractAnnotations(documentation) {
112
153
  };
113
154
  }
114
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();
115
171
  const primitiveTypes = [
116
172
  "Int",
117
173
  "BigInt",
@@ -143,7 +199,10 @@ function stringifyPrimitiveType(type, annotations) {
143
199
  case "Boolean":
144
200
  return `"boolean"`;
145
201
  case "Bytes":
146
- return `"instanceof Buffer"`;
202
+ if (IS_PRISMA_V7_OR_HIGHER) {
203
+ return "Uint8ArrayInstance";
204
+ }
205
+ return "BufferInstance";
147
206
  default:
148
207
  throw new Error(`Unsupported primitive type: ${type}`);
149
208
  }
@@ -179,6 +238,7 @@ function stringifyEnum(enumData) {
179
238
  }
180
239
 
181
240
  const processedPlain = [];
241
+ const extRegex$1 = /\.(ts|js)$/;
182
242
  function processPlain(models) {
183
243
  for (const model of models) {
184
244
  const result = stringifyPlain(model);
@@ -186,7 +246,9 @@ function processPlain(models) {
186
246
  processedPlain.push({
187
247
  name: model.name,
188
248
  stringified: result.stringified,
189
- enumDependencies: result.enumDependencies
249
+ enumDependencies: result.enumDependencies,
250
+ externalSchemaDependencies: result.externalSchemaDependencies,
251
+ runtimeDependencies: result.runtimeDependencies
190
252
  });
191
253
  }
192
254
  }
@@ -194,14 +256,19 @@ function processPlain(models) {
194
256
  }
195
257
  function stringifyPlain(model, isInputCreate = false, isInputUpdate = false) {
196
258
  const config = getConfig();
197
- const { hidden } = extractAnnotations(
198
- model.documentation
199
- );
259
+ const { hidden } = extractAnnotations(model.documentation);
200
260
  if (hidden) {
201
261
  return;
202
262
  }
203
263
  const fields = [];
204
264
  const enumDependencies = [];
265
+ const externalSchemaDependencies = [];
266
+ const runtimeDependencies = [];
267
+ function generateUniqueAlias(path, exportName, fieldName) {
268
+ const baseName = exportName || path.split("/").pop()?.replace(extRegex$1, "") || "Schema";
269
+ const suffix = fieldName ? `_${fieldName}` : "";
270
+ return `${baseName}${suffix}`;
271
+ }
205
272
  for (const field of model.fields) {
206
273
  const {
207
274
  annotations: fieldAnnotations,
@@ -218,10 +285,36 @@ function stringifyPlain(model, isInputCreate = false, isInputUpdate = false) {
218
285
  if (config.ignoredKeysOnInputModels.includes(field.name)) continue;
219
286
  if (field.name.endsWith("Id") && field.relationName) continue;
220
287
  }
288
+ const schemaAnnotation = fieldAnnotations.find(isSchema);
221
289
  const typeOverwrite = fieldAnnotations.find(isTypeOverwrite);
222
290
  let fieldType;
223
291
  let fieldName = field.name;
224
- if (typeOverwrite) {
292
+ if (schemaAnnotation) {
293
+ if (schemaAnnotation.isExternal) {
294
+ const alias = generateUniqueAlias(
295
+ schemaAnnotation.importPath,
296
+ schemaAnnotation.exportName,
297
+ field.name
298
+ );
299
+ if (!externalSchemaDependencies.some((d) => d.localAlias === alias)) {
300
+ const dependency = {
301
+ importPath: schemaAnnotation.importPath,
302
+ localAlias: alias
303
+ };
304
+ if (schemaAnnotation.exportName) {
305
+ dependency.exportName = schemaAnnotation.exportName;
306
+ }
307
+ externalSchemaDependencies.push(dependency);
308
+ }
309
+ fieldType = alias;
310
+ } else {
311
+ if (schemaAnnotation.value.trim().startsWith("{")) {
312
+ fieldType = schemaAnnotation.value;
313
+ } else {
314
+ fieldType = `"${schemaAnnotation.value}"`;
315
+ }
316
+ }
317
+ } else if (typeOverwrite) {
225
318
  fieldType = typeOverwrite.value;
226
319
  } else if (isPrimitivePrismaFieldType(field.type)) {
227
320
  fieldType = stringifyPrimitiveType(field.type);
@@ -235,16 +328,24 @@ function stringifyPlain(model, isInputCreate = false, isInputUpdate = false) {
235
328
  } else {
236
329
  continue;
237
330
  }
238
- const isEnumType = field.kind === "enum" && !typeOverwrite;
331
+ const isEnumType = field.kind === "enum" && !typeOverwrite && !schemaAnnotation;
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
+ }
239
340
  if (field.isList) {
240
- if (isEnumType) {
341
+ if (isExternalSchema || isEnumType || isBytesField) {
241
342
  fieldType = `${fieldType}.array()`;
242
343
  } else {
243
344
  fieldType = `"${wrapPrimitiveWithArray(fieldType.slice(1, -1))}"`;
244
345
  }
245
346
  }
246
347
  if (!field.isRequired) {
247
- if (isEnumType) {
348
+ if (isExternalSchema || isEnumType || isBytesField) {
248
349
  fieldType = `${fieldType}.or("null")`;
249
350
  } else {
250
351
  const inner = fieldType.slice(1, -1);
@@ -263,7 +364,9 @@ function stringifyPlain(model, isInputCreate = false, isInputUpdate = false) {
263
364
  stringified: `{
264
365
  ${fields.join(",\n ")}
265
366
  }`,
266
- enumDependencies
367
+ enumDependencies,
368
+ externalSchemaDependencies,
369
+ runtimeDependencies
267
370
  };
268
371
  }
269
372
  function stringifyPlainInputCreate(model) {
@@ -283,7 +386,9 @@ function processCreate(models) {
283
386
  processedCreate.push({
284
387
  name: model.name,
285
388
  stringified: result.stringified,
286
- enumDependencies: result.enumDependencies
389
+ enumDependencies: result.enumDependencies,
390
+ externalSchemaDependencies: result.externalSchemaDependencies,
391
+ runtimeDependencies: result.runtimeDependencies
287
392
  });
288
393
  }
289
394
  }
@@ -376,9 +481,7 @@ function processRelations(models) {
376
481
  Object.freeze(processedRelations);
377
482
  }
378
483
  function stringifyRelations(model) {
379
- const { hidden } = extractAnnotations(
380
- model.documentation
381
- );
484
+ const { hidden } = extractAnnotations(model.documentation);
382
485
  if (hidden) {
383
486
  return;
384
487
  }
@@ -425,9 +528,7 @@ function processRelationsCreate(models) {
425
528
  Object.freeze(processedRelationsCreate);
426
529
  }
427
530
  function stringifyRelationsInputCreate(model, allModels) {
428
- const { hidden } = extractAnnotations(
429
- model.documentation
430
- );
531
+ const { hidden } = extractAnnotations(model.documentation);
431
532
  if (hidden) {
432
533
  return;
433
534
  }
@@ -472,9 +573,7 @@ function processRelationsUpdate(models) {
472
573
  Object.freeze(processedRelationsUpdate);
473
574
  }
474
575
  function stringifyRelationsInputUpdate(model, allModels) {
475
- const { hidden } = extractAnnotations(
476
- model.documentation
477
- );
576
+ const { hidden } = extractAnnotations(model.documentation);
478
577
  if (hidden) {
479
578
  return;
480
579
  }
@@ -532,9 +631,7 @@ function processSelect(models) {
532
631
  Object.freeze(processedSelect);
533
632
  }
534
633
  function stringifySelect(model) {
535
- const { hidden } = extractAnnotations(
536
- model.documentation
537
- );
634
+ const { hidden } = extractAnnotations(model.documentation);
538
635
  if (hidden) {
539
636
  return;
540
637
  }
@@ -560,7 +657,9 @@ function processUpdate(models) {
560
657
  processedUpdate.push({
561
658
  name: model.name,
562
659
  stringified: result.stringified,
563
- enumDependencies: result.enumDependencies
660
+ enumDependencies: result.enumDependencies,
661
+ externalSchemaDependencies: result.externalSchemaDependencies,
662
+ runtimeDependencies: result.runtimeDependencies
564
663
  });
565
664
  }
566
665
  }
@@ -569,6 +668,7 @@ function processUpdate(models) {
569
668
 
570
669
  const processedWhere = [];
571
670
  const processedWhereUnique = [];
671
+ const extRegex = /\.(ts|js)$/;
572
672
  function processWhere(models) {
573
673
  for (const model of models) {
574
674
  const result = stringifyWhere(model);
@@ -576,7 +676,9 @@ function processWhere(models) {
576
676
  processedWhere.push({
577
677
  name: model.name,
578
678
  stringified: result.stringified,
579
- enumDependencies: result.enumDependencies
679
+ enumDependencies: result.enumDependencies,
680
+ externalSchemaDependencies: result.externalSchemaDependencies,
681
+ runtimeDependencies: result.runtimeDependencies
580
682
  });
581
683
  }
582
684
  const uniqueResult = stringifyWhereUnique(model);
@@ -584,7 +686,9 @@ function processWhere(models) {
584
686
  processedWhereUnique.push({
585
687
  name: model.name,
586
688
  stringified: uniqueResult.stringified,
587
- enumDependencies: uniqueResult.enumDependencies
689
+ enumDependencies: uniqueResult.enumDependencies,
690
+ externalSchemaDependencies: uniqueResult.externalSchemaDependencies,
691
+ runtimeDependencies: uniqueResult.runtimeDependencies
588
692
  });
589
693
  }
590
694
  }
@@ -592,21 +696,52 @@ function processWhere(models) {
592
696
  Object.freeze(processedWhereUnique);
593
697
  }
594
698
  function stringifyWhere(model) {
595
- const { hidden } = extractAnnotations(
596
- model.documentation
597
- );
699
+ const { hidden } = extractAnnotations(model.documentation);
598
700
  if (hidden) {
599
701
  return;
600
702
  }
601
703
  const fields = [];
602
704
  const enumDependencies = [];
705
+ const externalSchemaDependencies = [];
706
+ const runtimeDependencies = [];
707
+ function generateUniqueAlias(path, exportName, fieldName) {
708
+ const baseName = exportName || path.split("/").pop()?.replace(extRegex, "") || "Schema";
709
+ const suffix = fieldName ? `_${fieldName}` : "";
710
+ return `${baseName}${suffix}`;
711
+ }
603
712
  for (const field of model.fields) {
604
713
  const { annotations: fieldAnnotations, hidden: fieldHidden } = extractAnnotations(field.documentation);
605
714
  if (fieldHidden) continue;
606
715
  if (field.kind === "object") continue;
716
+ const schemaAnnotation = fieldAnnotations.find(isSchema);
607
717
  const typeOverwrite = fieldAnnotations.find(isTypeOverwrite);
608
718
  let fieldType;
609
- if (typeOverwrite) {
719
+ if (schemaAnnotation) {
720
+ if (schemaAnnotation.isExternal) {
721
+ const alias = generateUniqueAlias(
722
+ schemaAnnotation.importPath,
723
+ schemaAnnotation.exportName,
724
+ field.name
725
+ );
726
+ if (!externalSchemaDependencies.some((d) => d.localAlias === alias)) {
727
+ const dependency = {
728
+ importPath: schemaAnnotation.importPath,
729
+ localAlias: alias
730
+ };
731
+ if (schemaAnnotation.exportName) {
732
+ dependency.exportName = schemaAnnotation.exportName;
733
+ }
734
+ externalSchemaDependencies.push(dependency);
735
+ }
736
+ fieldType = alias;
737
+ } else {
738
+ if (schemaAnnotation.value.trim().startsWith("{")) {
739
+ fieldType = schemaAnnotation.value;
740
+ } else {
741
+ fieldType = `"${schemaAnnotation.value}"`;
742
+ }
743
+ }
744
+ } else if (typeOverwrite) {
610
745
  fieldType = typeOverwrite.value;
611
746
  } else if (isPrimitivePrismaFieldType(field.type)) {
612
747
  fieldType = stringifyPrimitiveType(field.type);
@@ -620,41 +755,143 @@ function stringifyWhere(model) {
620
755
  } else {
621
756
  continue;
622
757
  }
623
- const isEnumType = field.kind === "enum" && !typeOverwrite;
758
+ const isEnumType = field.kind === "enum" && !typeOverwrite && !schemaAnnotation;
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
+ }
624
772
  if (field.isList) {
625
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) {
626
794
  fieldType = `${fieldType}.array()`;
627
795
  } else {
628
796
  const inner = fieldType.slice(1, -1);
629
797
  fieldType = `"${wrapPrimitiveWithArray(inner)}"`;
630
798
  }
631
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
+ }
632
836
  fields.push(`"${field.name}?": ${fieldType}`);
633
837
  }
634
838
  return {
635
839
  stringified: `{
636
840
  ${fields.join(",\n ")}
637
841
  }`,
638
- enumDependencies
842
+ enumDependencies,
843
+ externalSchemaDependencies,
844
+ runtimeDependencies
639
845
  };
640
846
  }
641
847
  function stringifyWhereUnique(model) {
642
- const { hidden } = extractAnnotations(
643
- model.documentation
644
- );
848
+ const { hidden } = extractAnnotations(model.documentation);
645
849
  if (hidden) {
646
850
  return;
647
851
  }
648
852
  const fields = [];
649
853
  const enumDependencies = [];
854
+ const externalSchemaDependencies = [];
855
+ const runtimeDependencies = [];
856
+ function generateUniqueAlias(path, exportName, fieldName) {
857
+ const baseName = exportName || path.split("/").pop()?.replace(extRegex, "") || "Schema";
858
+ const suffix = fieldName ? `_${fieldName}` : "";
859
+ return `${baseName}${suffix}`;
860
+ }
650
861
  for (const field of model.fields) {
651
862
  const { annotations: fieldAnnotations, hidden: fieldHidden } = extractAnnotations(field.documentation);
652
863
  if (fieldHidden) continue;
653
864
  if (field.kind === "object") continue;
654
865
  if (!(field.isId || field.isUnique)) continue;
866
+ const schemaAnnotation = fieldAnnotations.find(isSchema);
655
867
  const typeOverwrite = fieldAnnotations.find(isTypeOverwrite);
656
868
  let fieldType;
657
- if (typeOverwrite) {
869
+ if (schemaAnnotation) {
870
+ if (schemaAnnotation.isExternal) {
871
+ const alias = generateUniqueAlias(
872
+ schemaAnnotation.importPath,
873
+ schemaAnnotation.exportName,
874
+ field.name
875
+ );
876
+ if (!externalSchemaDependencies.some((d) => d.localAlias === alias)) {
877
+ const dependency = {
878
+ importPath: schemaAnnotation.importPath,
879
+ localAlias: alias
880
+ };
881
+ if (schemaAnnotation.exportName) {
882
+ dependency.exportName = schemaAnnotation.exportName;
883
+ }
884
+ externalSchemaDependencies.push(dependency);
885
+ }
886
+ fieldType = alias;
887
+ } else {
888
+ if (schemaAnnotation.value.trim().startsWith("{")) {
889
+ fieldType = schemaAnnotation.value;
890
+ } else {
891
+ fieldType = `"${schemaAnnotation.value}"`;
892
+ }
893
+ }
894
+ } else if (typeOverwrite) {
658
895
  fieldType = typeOverwrite.value;
659
896
  } else if (isPrimitivePrismaFieldType(field.type)) {
660
897
  fieldType = stringifyPrimitiveType(field.type);
@@ -668,6 +905,20 @@ function stringifyWhereUnique(model) {
668
905
  } else {
669
906
  continue;
670
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
+ }
671
922
  fields.push(`"${field.name}?": ${fieldType}`);
672
923
  }
673
924
  if (fields.length === 0) {
@@ -677,7 +928,9 @@ function stringifyWhereUnique(model) {
677
928
  stringified: `{
678
929
  ${fields.join(",\n ")}
679
930
  }`,
680
- enumDependencies
931
+ enumDependencies,
932
+ externalSchemaDependencies,
933
+ runtimeDependencies
681
934
  };
682
935
  }
683
936
 
@@ -700,6 +953,50 @@ function generateModelImports(modelDependencies) {
700
953
  ).join("\n")}
701
954
  `;
702
955
  }
956
+ function generateExternalSchemaImports(externalSchemaDependencies) {
957
+ if (!externalSchemaDependencies || externalSchemaDependencies.length === 0) {
958
+ return "";
959
+ }
960
+ return `${externalSchemaDependencies.map((dep) => {
961
+ if (dep.exportName) {
962
+ return `import { ${dep.exportName} as ${dep.localAlias} } from "${dep.importPath}";`;
963
+ }
964
+ return `import ${dep.localAlias} from "${dep.importPath}";`;
965
+ }).join("\n")}
966
+ `;
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
+ }
703
1000
  function mapAllModelsForWrite(processedEnums, processedPlain, processedRelations, processedWhere, processedWhereUnique, processedCreate, processedUpdate, processedRelationsCreate, processedRelationsUpdate, processedSelect, processedInclude, processedOrderBy) {
704
1001
  const config = getConfig();
705
1002
  const modelMap = /* @__PURE__ */ new Map();
@@ -713,7 +1010,13 @@ function mapAllModelsForWrite(processedEnums, processedPlain, processedRelations
713
1010
  }
714
1011
  for (const model of processedPlain) {
715
1012
  const enumImports = generateEnumImports(model.enumDependencies);
716
- const content = `${arktypeImport}${enumImports}export const ${model.name}Plain = type(${model.stringified});
1013
+ const externalSchemaImports = generateExternalSchemaImports(
1014
+ model.externalSchemaDependencies
1015
+ );
1016
+ const runtimeImports = generateRuntimeDependencyImports(
1017
+ model.runtimeDependencies
1018
+ );
1019
+ const content = `${arktypeImport}${enumImports}${externalSchemaImports}${runtimeImports}export const ${model.name}Plain = type(${model.stringified});
717
1020
  `;
718
1021
  modelMap.set(`${model.name}Plain`, content);
719
1022
  }
@@ -742,25 +1045,49 @@ export const ${plain.name} = ${plain.name}Plain;
742
1045
  }
743
1046
  for (const model of processedWhere) {
744
1047
  const enumImports = generateEnumImports(model.enumDependencies);
745
- const content = `${arktypeImport}${enumImports}export const ${model.name}Where = type(${model.stringified});
1048
+ const externalSchemaImports = generateExternalSchemaImports(
1049
+ model.externalSchemaDependencies
1050
+ );
1051
+ const runtimeImports = generateRuntimeDependencyImports(
1052
+ model.runtimeDependencies
1053
+ );
1054
+ const content = `${arktypeImport}${enumImports}${externalSchemaImports}${runtimeImports}export const ${model.name}Where = type(${model.stringified});
746
1055
  `;
747
1056
  modelMap.set(`${model.name}Where`, content);
748
1057
  }
749
1058
  for (const model of processedWhereUnique) {
750
1059
  const enumImports = generateEnumImports(model.enumDependencies);
751
- const content = `${arktypeImport}${enumImports}export const ${model.name}WhereUnique = type(${model.stringified});
1060
+ const externalSchemaImports = generateExternalSchemaImports(
1061
+ model.externalSchemaDependencies
1062
+ );
1063
+ const runtimeImports = generateRuntimeDependencyImports(
1064
+ model.runtimeDependencies
1065
+ );
1066
+ const content = `${arktypeImport}${enumImports}${externalSchemaImports}${runtimeImports}export const ${model.name}WhereUnique = type(${model.stringified});
752
1067
  `;
753
1068
  modelMap.set(`${model.name}WhereUnique`, content);
754
1069
  }
755
1070
  for (const model of processedCreate) {
756
1071
  const enumImports = generateEnumImports(model.enumDependencies);
757
- const content = `${arktypeImport}${enumImports}export const ${model.name}Create = type(${model.stringified});
1072
+ const externalSchemaImports = generateExternalSchemaImports(
1073
+ model.externalSchemaDependencies
1074
+ );
1075
+ const runtimeImports = generateRuntimeDependencyImports(
1076
+ model.runtimeDependencies
1077
+ );
1078
+ const content = `${arktypeImport}${enumImports}${externalSchemaImports}${runtimeImports}export const ${model.name}Create = type(${model.stringified});
758
1079
  `;
759
1080
  modelMap.set(`${model.name}Create`, content);
760
1081
  }
761
1082
  for (const model of processedUpdate) {
762
1083
  const enumImports = generateEnumImports(model.enumDependencies);
763
- const content = `${arktypeImport}${enumImports}export const ${model.name}Update = type(${model.stringified});
1084
+ const externalSchemaImports = generateExternalSchemaImports(
1085
+ model.externalSchemaDependencies
1086
+ );
1087
+ const runtimeImports = generateRuntimeDependencyImports(
1088
+ model.runtimeDependencies
1089
+ );
1090
+ const content = `${arktypeImport}${enumImports}${externalSchemaImports}${runtimeImports}export const ${model.name}Update = type(${model.stringified});
764
1091
  `;
765
1092
  modelMap.set(`${model.name}Update`, content);
766
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.3.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",
@@ -55,17 +91,27 @@
55
91
  "vitest": "^4.0.16"
56
92
  },
57
93
  "scripts": {
58
- "build": "pkgroll",
94
+ "build": "pkgroll && prisma generate",
59
95
  "dev": "pkgroll --watch",
60
96
  "test": "vitest run",
61
97
  "test:watch": "vitest",
62
- "test:e2e": "pnpm build && prisma generate && vitest run",
98
+ "test:e2e": "pnpm build && vitest run",
63
99
  "pretest": "pnpm build",
64
100
  "postinstall": "lefthook install",
65
101
  "lint": "biome check",
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
  }