prisma-arktype 2.0.0 → 2.1.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 +103 -25
- package/dist/index.js +45 -76
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -132,75 +132,102 @@ const whereResult = UserWhere(whereClause);
|
|
|
132
132
|
|
|
133
133
|
## Annotations
|
|
134
134
|
|
|
135
|
-
Control schema generation using annotations in your Prisma schema
|
|
135
|
+
Control schema generation using annotations in your Prisma schema. All annotations are added as documentation comments (`///`).
|
|
136
|
+
|
|
137
|
+
### Available Annotations
|
|
138
|
+
|
|
139
|
+
| Annotation | Scope | Description |
|
|
140
|
+
|------------|-------|-------------|
|
|
141
|
+
| `@prisma-arktype.hide` | Model or Field | Completely hide from all generated schemas |
|
|
142
|
+
| `@prisma-arktype.input.hide` | Field | Hide from Create and Update input schemas |
|
|
143
|
+
| `@prisma-arktype.create.input.hide` | Field | Hide from Create input schema only |
|
|
144
|
+
| `@prisma-arktype.update.input.hide` | Field | Hide from Update input schema only |
|
|
145
|
+
| `@prisma-arktype.typeOverwrite="<type>"` | Field | Override the generated ArkType type |
|
|
136
146
|
|
|
137
147
|
### Hide Fields/Models
|
|
138
148
|
|
|
149
|
+
Completely exclude models or fields from all generated schemas:
|
|
150
|
+
|
|
139
151
|
```prisma
|
|
140
152
|
/// @prisma-arktype.hide
|
|
141
153
|
model InternalModel {
|
|
142
154
|
id String @id
|
|
155
|
+
secret String
|
|
143
156
|
}
|
|
144
157
|
|
|
145
158
|
model User {
|
|
146
159
|
id String @id
|
|
160
|
+
email String
|
|
147
161
|
/// @prisma-arktype.hide
|
|
148
|
-
|
|
162
|
+
passwordHash String
|
|
149
163
|
}
|
|
150
164
|
```
|
|
151
165
|
|
|
152
166
|
### Hide from Input Models
|
|
153
167
|
|
|
168
|
+
Control which fields appear in Create and Update schemas:
|
|
169
|
+
|
|
154
170
|
```prisma
|
|
155
171
|
model User {
|
|
156
172
|
id String @id
|
|
173
|
+
email String
|
|
174
|
+
|
|
157
175
|
/// @prisma-arktype.input.hide
|
|
176
|
+
/// Hidden from both Create and Update
|
|
158
177
|
computedField String
|
|
178
|
+
|
|
159
179
|
/// @prisma-arktype.create.input.hide
|
|
160
|
-
|
|
180
|
+
/// Only appears in Update schema
|
|
181
|
+
lastModified DateTime
|
|
182
|
+
|
|
161
183
|
/// @prisma-arktype.update.input.hide
|
|
162
|
-
|
|
184
|
+
/// Only appears in Create schema
|
|
185
|
+
initialStatus String
|
|
163
186
|
}
|
|
164
187
|
```
|
|
165
188
|
|
|
166
189
|
### Type Override
|
|
167
190
|
|
|
191
|
+
Override the default type mapping with custom ArkType type strings:
|
|
192
|
+
|
|
168
193
|
```prisma
|
|
169
194
|
model User {
|
|
170
195
|
id String @id
|
|
171
196
|
/// @prisma-arktype.typeOverwrite="string.email"
|
|
172
197
|
email String
|
|
198
|
+
/// @prisma-arktype.typeOverwrite="string.url"
|
|
199
|
+
website String
|
|
173
200
|
/// @prisma-arktype.typeOverwrite="string.numeric"
|
|
174
201
|
phone String
|
|
175
202
|
}
|
|
176
203
|
```
|
|
177
204
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
```prisma
|
|
181
|
-
model User {
|
|
182
|
-
id String @id
|
|
183
|
-
/// @prisma-arktype.options{minLength: 3, maxLength: 50}
|
|
184
|
-
username String
|
|
185
|
-
}
|
|
186
|
-
```
|
|
205
|
+
This allows you to use any ArkType type definition, including built-in refinements like `string.email`, `string.url`, `number.integer`, etc.
|
|
187
206
|
|
|
188
207
|
## Type Mapping
|
|
189
208
|
|
|
190
209
|
Prisma types are mapped to ArkType as follows:
|
|
191
210
|
|
|
192
|
-
| Prisma Type | ArkType Type |
|
|
193
|
-
|
|
194
|
-
| `String` | `"string"` |
|
|
195
|
-
| `Int` | `"integer"` |
|
|
196
|
-
| `BigInt` | `"integer"` |
|
|
197
|
-
| `Float` | `"number"` |
|
|
198
|
-
| `Decimal` | `"number"` |
|
|
199
|
-
| `Boolean` | `"boolean"` |
|
|
200
|
-
| `DateTime` | `"Date"` |
|
|
201
|
-
| `Json` | `"unknown"` |
|
|
202
|
-
| `Bytes` | `"instanceof Buffer"` |
|
|
203
|
-
| Enums | Union of literal values |
|
|
211
|
+
| Prisma Type | ArkType Type | Example Output |
|
|
212
|
+
|-------------|--------------|----------------|
|
|
213
|
+
| `String` | `"string"` | `"string"` |
|
|
214
|
+
| `Int` | `"number.integer"` | `"number.integer"` |
|
|
215
|
+
| `BigInt` | `"number.integer"` | `"number.integer"` |
|
|
216
|
+
| `Float` | `"number"` | `"number"` |
|
|
217
|
+
| `Decimal` | `"number"` | `"number"` |
|
|
218
|
+
| `Boolean` | `"boolean"` | `"boolean"` |
|
|
219
|
+
| `DateTime` | `"Date"` | `"Date"` |
|
|
220
|
+
| `Json` | `"unknown"` | `"unknown"` |
|
|
221
|
+
| `Bytes` | `"instanceof Buffer"` | `"instanceof Buffer"` |
|
|
222
|
+
| Enums | Union of literal values | `type("'USD' \| 'EUR' \| 'GBP'")` |
|
|
223
|
+
| Relations | `"unknown"` | `type("unknown").array()` for lists |
|
|
224
|
+
|
|
225
|
+
### Special Handling
|
|
226
|
+
|
|
227
|
+
- **Optional fields**: Use `?` on the key name (`"name?": "string"`)
|
|
228
|
+
- **Nullable fields**: Add `| null` to the type (`"string | null"`)
|
|
229
|
+
- **Arrays**: Use `.array()` syntax for lists (`type("string").array()`)
|
|
230
|
+
- **Enums**: Generated as string literal unions wrapped in `type()`
|
|
204
231
|
|
|
205
232
|
## Differences from prismabox
|
|
206
233
|
|
|
@@ -239,6 +266,57 @@ pnpm lint
|
|
|
239
266
|
pnpm lint:fix
|
|
240
267
|
```
|
|
241
268
|
|
|
269
|
+
### Testing
|
|
270
|
+
|
|
271
|
+
This library has a **completely schema-independent test suite** using self-contained test models in `prisma/schema/test-models.prisma`.
|
|
272
|
+
|
|
273
|
+
#### Running Tests
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
# Run all tests
|
|
277
|
+
pnpm test:e2e
|
|
278
|
+
|
|
279
|
+
# Run tests in watch mode
|
|
280
|
+
pnpm test:watch
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
#### Test Architecture
|
|
284
|
+
|
|
285
|
+
The test suite is designed to be **100% independent** of production schemas:
|
|
286
|
+
|
|
287
|
+
- **Self-Contained Schema** - `prisma/schema/test-models.prisma` contains all models needed for testing
|
|
288
|
+
- **No Production Dependencies** - Tests work even if production schemas don't exist
|
|
289
|
+
- **Comprehensive Coverage** - Test models cover all Prisma types, relations, and generator features
|
|
290
|
+
- **Portable** - Can be used across different projects or extracted as a standalone test suite
|
|
291
|
+
|
|
292
|
+
#### Test Model Categories
|
|
293
|
+
|
|
294
|
+
The test schema includes specialized models for testing:
|
|
295
|
+
|
|
296
|
+
1. **Basic CRUD** - `TestUser`, `TestPost`, `TestProfile`
|
|
297
|
+
2. **All Prisma Types** - `TestAllTypes` (String, Int, BigInt, Float, Decimal, Boolean, DateTime, Json, Bytes)
|
|
298
|
+
3. **Relations** - One-to-one, one-to-many, many-to-many, composite keys
|
|
299
|
+
4. **Annotations** - `@prisma-arktype.hide`, `@prisma-arktype.input.hide`, `@prisma-arktype.typeOverwrite`
|
|
300
|
+
5. **Query Operations** - Select, Include, OrderBy schemas
|
|
301
|
+
6. **Enums** - `TestCurrency`, `TestStatus`
|
|
302
|
+
|
|
303
|
+
#### Adding New Tests
|
|
304
|
+
|
|
305
|
+
1. **Add test models** to `prisma/schema/test-models.prisma` if needed
|
|
306
|
+
2. **Update mapping** in `__tests__/config/model-mapping.ts` to reference your models
|
|
307
|
+
3. **Write tests** using helper functions from `__tests__/utils/test-helpers.ts`
|
|
308
|
+
4. **Run tests** - `pnpm test`
|
|
309
|
+
|
|
310
|
+
See existing test files for examples.
|
|
311
|
+
|
|
312
|
+
#### Why Schema-Independent?
|
|
313
|
+
|
|
314
|
+
- ✅ Tests never break due to production schema changes
|
|
315
|
+
- ✅ Contributors can run tests without setting up production databases
|
|
316
|
+
- ✅ Tests can be run in isolation (CI/CD, local development)
|
|
317
|
+
- ✅ Clear, documented examples of generator usage
|
|
318
|
+
- ✅ Easy to test new features by adding new test models
|
|
319
|
+
|
|
242
320
|
### Publishing
|
|
243
321
|
|
|
244
322
|
This project uses [Changesets](https://github.com/changesets/changesets) for version management and publishing.
|
package/dist/index.js
CHANGED
|
@@ -40,9 +40,6 @@ function isHiddenInputCreate(annotation) {
|
|
|
40
40
|
function isHiddenInputUpdate(annotation) {
|
|
41
41
|
return annotation.type === "HIDDEN_INPUT_UPDATE";
|
|
42
42
|
}
|
|
43
|
-
function isOptions(annotation) {
|
|
44
|
-
return annotation.type === "OPTIONS";
|
|
45
|
-
}
|
|
46
43
|
function isTypeOverwrite(annotation) {
|
|
47
44
|
return annotation.type === "TYPE_OVERWRITE";
|
|
48
45
|
}
|
|
@@ -69,10 +66,8 @@ const annotationKeys = [
|
|
|
69
66
|
],
|
|
70
67
|
type: "HIDDEN_INPUT_UPDATE"
|
|
71
68
|
},
|
|
72
|
-
{ keys: ["@prisma-arktype.options"], type: "OPTIONS" },
|
|
73
69
|
{ keys: ["@prisma-arktype.typeOverwrite"], type: "TYPE_OVERWRITE" }
|
|
74
70
|
];
|
|
75
|
-
const prismaArktypeOptionsRegex = /@prisma-arktype\.options\{(.+)\}/;
|
|
76
71
|
const prismaArktypeTypeOverwriteRegex = /@prisma-arktype\.typeOverwrite=(.+)/;
|
|
77
72
|
function extractAnnotations(documentation) {
|
|
78
73
|
const annotations = [];
|
|
@@ -84,14 +79,7 @@ function extractAnnotations(documentation) {
|
|
|
84
79
|
for (const key of keys) {
|
|
85
80
|
if (line.includes(key)) {
|
|
86
81
|
isAnnotation = true;
|
|
87
|
-
if (type === "
|
|
88
|
-
const match = line.match(prismaArktypeOptionsRegex);
|
|
89
|
-
if (match && match[1]) {
|
|
90
|
-
annotations.push({ type: "OPTIONS", value: match[1] });
|
|
91
|
-
} else {
|
|
92
|
-
throw new Error(`Invalid OPTIONS annotation: ${line}`);
|
|
93
|
-
}
|
|
94
|
-
} else if (type === "TYPE_OVERWRITE") {
|
|
82
|
+
if (type === "TYPE_OVERWRITE") {
|
|
95
83
|
const match = line.match(prismaArktypeTypeOverwriteRegex);
|
|
96
84
|
if (match && match[1]) {
|
|
97
85
|
annotations.push({
|
|
@@ -123,13 +111,6 @@ function extractAnnotations(documentation) {
|
|
|
123
111
|
hiddenInputUpdate: annotations.some(isHiddenInputUpdate)
|
|
124
112
|
};
|
|
125
113
|
}
|
|
126
|
-
function generateArktypeOptions(annotations) {
|
|
127
|
-
const optionsAnnotations = annotations.filter(isOptions);
|
|
128
|
-
if (optionsAnnotations.length === 0) {
|
|
129
|
-
return "";
|
|
130
|
-
}
|
|
131
|
-
return `.pipe(${optionsAnnotations.map((a) => a.value).join(", ")})`;
|
|
132
|
-
}
|
|
133
114
|
|
|
134
115
|
const primitiveTypes = [
|
|
135
116
|
"Int",
|
|
@@ -146,30 +127,29 @@ function isPrimitivePrismaFieldType(type) {
|
|
|
146
127
|
return primitiveTypes.includes(type);
|
|
147
128
|
}
|
|
148
129
|
function stringifyPrimitiveType(type, annotations) {
|
|
149
|
-
const options = generateArktypeOptions(annotations);
|
|
150
130
|
switch (type) {
|
|
151
131
|
case "Int":
|
|
152
132
|
case "BigInt":
|
|
153
|
-
return `"number.integer"
|
|
133
|
+
return `"number.integer"`;
|
|
154
134
|
case "Float":
|
|
155
135
|
case "Decimal":
|
|
156
|
-
return `"number"
|
|
136
|
+
return `"number"`;
|
|
157
137
|
case "String":
|
|
158
|
-
return `"string"
|
|
138
|
+
return `"string"`;
|
|
159
139
|
case "DateTime":
|
|
160
|
-
return `"Date"
|
|
140
|
+
return `"Date"`;
|
|
161
141
|
case "Json":
|
|
162
|
-
return `"unknown"
|
|
142
|
+
return `"unknown"`;
|
|
163
143
|
case "Boolean":
|
|
164
|
-
return `"boolean"
|
|
144
|
+
return `"boolean"`;
|
|
165
145
|
case "Bytes":
|
|
166
|
-
return `"instanceof Buffer"
|
|
146
|
+
return `"instanceof Buffer"`;
|
|
167
147
|
default:
|
|
168
148
|
throw new Error(`Unsupported primitive type: ${type}`);
|
|
169
149
|
}
|
|
170
150
|
}
|
|
171
151
|
|
|
172
|
-
function
|
|
152
|
+
function wrapPrimitiveWithArray(input) {
|
|
173
153
|
return `${input}[]`;
|
|
174
154
|
}
|
|
175
155
|
function makeUnion(inputModels) {
|
|
@@ -190,13 +170,12 @@ function processEnums(enums) {
|
|
|
190
170
|
Object.freeze(processedEnums);
|
|
191
171
|
}
|
|
192
172
|
function stringifyEnum(enumData) {
|
|
193
|
-
const {
|
|
173
|
+
const { hidden } = extractAnnotations(enumData.documentation);
|
|
194
174
|
if (hidden) {
|
|
195
175
|
return;
|
|
196
176
|
}
|
|
197
177
|
const values = enumData.values.map((v) => `'${v.name}'`);
|
|
198
|
-
|
|
199
|
-
return `type("${makeUnion(values)}")${options}`;
|
|
178
|
+
return `type("${makeUnion(values)}")`;
|
|
200
179
|
}
|
|
201
180
|
|
|
202
181
|
const processedPlain = [];
|
|
@@ -215,7 +194,7 @@ function processPlain(models) {
|
|
|
215
194
|
const enumMatch$1 = /type\("(.+)"\)/;
|
|
216
195
|
function stringifyPlain(model, isInputCreate = false, isInputUpdate = false) {
|
|
217
196
|
const config = getConfig();
|
|
218
|
-
const {
|
|
197
|
+
const { hidden } = extractAnnotations(
|
|
219
198
|
model.documentation
|
|
220
199
|
);
|
|
221
200
|
if (hidden) {
|
|
@@ -244,7 +223,7 @@ function stringifyPlain(model, isInputCreate = false, isInputUpdate = false) {
|
|
|
244
223
|
if (typeOverwrite) {
|
|
245
224
|
fieldType = typeOverwrite.value;
|
|
246
225
|
} else if (isPrimitivePrismaFieldType(field.type)) {
|
|
247
|
-
fieldType = stringifyPrimitiveType(field.type
|
|
226
|
+
fieldType = stringifyPrimitiveType(field.type);
|
|
248
227
|
} else if (field.kind === "enum") {
|
|
249
228
|
const enumDef = processedEnums.find((e) => e.name === field.type);
|
|
250
229
|
if (!enumDef) continue;
|
|
@@ -254,7 +233,7 @@ function stringifyPlain(model, isInputCreate = false, isInputUpdate = false) {
|
|
|
254
233
|
continue;
|
|
255
234
|
}
|
|
256
235
|
if (field.isList) {
|
|
257
|
-
fieldType = `"${
|
|
236
|
+
fieldType = `"${wrapPrimitiveWithArray(fieldType.slice(1, -1))}"`;
|
|
258
237
|
}
|
|
259
238
|
if (!field.isRequired) {
|
|
260
239
|
const inner = fieldType.slice(1, -1);
|
|
@@ -268,10 +247,9 @@ function stringifyPlain(model, isInputCreate = false, isInputUpdate = false) {
|
|
|
268
247
|
}
|
|
269
248
|
fields.push(`"${fieldName}": ${fieldType}`);
|
|
270
249
|
}
|
|
271
|
-
const options = generateArktypeOptions(modelAnnotations);
|
|
272
250
|
return `{
|
|
273
251
|
${fields.join(",\n ")}
|
|
274
|
-
}
|
|
252
|
+
}`;
|
|
275
253
|
}
|
|
276
254
|
function stringifyPlainInputCreate(model) {
|
|
277
255
|
return stringifyPlain(model, true, false);
|
|
@@ -310,7 +288,7 @@ function processInclude(models) {
|
|
|
310
288
|
Object.freeze(processedInclude);
|
|
311
289
|
}
|
|
312
290
|
function stringifyInclude(model) {
|
|
313
|
-
const {
|
|
291
|
+
const { hidden } = extractAnnotations(
|
|
314
292
|
model.documentation
|
|
315
293
|
);
|
|
316
294
|
if (hidden) {
|
|
@@ -327,10 +305,9 @@ function stringifyInclude(model) {
|
|
|
327
305
|
if (fields.length <= 1) {
|
|
328
306
|
return;
|
|
329
307
|
}
|
|
330
|
-
const options = generateArktypeOptions(modelAnnotations);
|
|
331
308
|
return `{
|
|
332
309
|
${fields.join(",\n ")}
|
|
333
|
-
}
|
|
310
|
+
}`;
|
|
334
311
|
}
|
|
335
312
|
|
|
336
313
|
const processedOrderBy = [];
|
|
@@ -347,7 +324,7 @@ function processOrderBy(models) {
|
|
|
347
324
|
Object.freeze(processedOrderBy);
|
|
348
325
|
}
|
|
349
326
|
function stringifyOrderBy(model) {
|
|
350
|
-
const {
|
|
327
|
+
const { hidden } = extractAnnotations(
|
|
351
328
|
model.documentation
|
|
352
329
|
);
|
|
353
330
|
if (hidden) {
|
|
@@ -361,10 +338,9 @@ function stringifyOrderBy(model) {
|
|
|
361
338
|
if (field.kind === "object") continue;
|
|
362
339
|
fields.push(`"${field.name}?": ${sortOrder}`);
|
|
363
340
|
}
|
|
364
|
-
const options = generateArktypeOptions(modelAnnotations);
|
|
365
341
|
return `{
|
|
366
342
|
${fields.join(",\n ")}
|
|
367
|
-
}
|
|
343
|
+
}`;
|
|
368
344
|
}
|
|
369
345
|
|
|
370
346
|
const processedRelations = [];
|
|
@@ -383,7 +359,7 @@ function processRelations(models) {
|
|
|
383
359
|
Object.freeze(processedRelations);
|
|
384
360
|
}
|
|
385
361
|
function stringifyRelations(model) {
|
|
386
|
-
const {
|
|
362
|
+
const { hidden } = extractAnnotations(
|
|
387
363
|
model.documentation
|
|
388
364
|
);
|
|
389
365
|
if (hidden) {
|
|
@@ -394,22 +370,22 @@ function stringifyRelations(model) {
|
|
|
394
370
|
const { hidden: fieldHidden } = extractAnnotations(field.documentation);
|
|
395
371
|
if (fieldHidden) continue;
|
|
396
372
|
if (field.kind !== "object") continue;
|
|
397
|
-
let fieldType
|
|
373
|
+
let fieldType;
|
|
398
374
|
if (field.isList) {
|
|
399
|
-
fieldType = `"unknown
|
|
400
|
-
}
|
|
401
|
-
if (!field.isRequired) {
|
|
375
|
+
fieldType = `type("unknown").array()`;
|
|
376
|
+
} else if (!field.isRequired) {
|
|
402
377
|
fieldType = `"unknown | null"`;
|
|
378
|
+
} else {
|
|
379
|
+
fieldType = `"unknown"`;
|
|
403
380
|
}
|
|
404
381
|
fields.push(`"${field.name}": ${fieldType}`);
|
|
405
382
|
}
|
|
406
383
|
if (fields.length === 0) {
|
|
407
384
|
return;
|
|
408
385
|
}
|
|
409
|
-
const options = generateArktypeOptions(modelAnnotations);
|
|
410
386
|
return `{
|
|
411
387
|
${fields.join(",\n ")}
|
|
412
|
-
}
|
|
388
|
+
}`;
|
|
413
389
|
}
|
|
414
390
|
function processRelationsCreate(models) {
|
|
415
391
|
for (const model of models) {
|
|
@@ -424,7 +400,7 @@ function processRelationsCreate(models) {
|
|
|
424
400
|
Object.freeze(processedRelationsCreate);
|
|
425
401
|
}
|
|
426
402
|
function stringifyRelationsInputCreate(model, allModels) {
|
|
427
|
-
const {
|
|
403
|
+
const { hidden } = extractAnnotations(
|
|
428
404
|
model.documentation
|
|
429
405
|
);
|
|
430
406
|
if (hidden) {
|
|
@@ -454,10 +430,9 @@ function stringifyRelationsInputCreate(model, allModels) {
|
|
|
454
430
|
if (fields.length === 0) {
|
|
455
431
|
return;
|
|
456
432
|
}
|
|
457
|
-
const options = generateArktypeOptions(modelAnnotations);
|
|
458
433
|
return `{
|
|
459
434
|
${fields.join(",\n ")}
|
|
460
|
-
}
|
|
435
|
+
}`;
|
|
461
436
|
}
|
|
462
437
|
function processRelationsUpdate(models) {
|
|
463
438
|
for (const model of models) {
|
|
@@ -472,7 +447,7 @@ function processRelationsUpdate(models) {
|
|
|
472
447
|
Object.freeze(processedRelationsUpdate);
|
|
473
448
|
}
|
|
474
449
|
function stringifyRelationsInputUpdate(model, allModels) {
|
|
475
|
-
const {
|
|
450
|
+
const { hidden } = extractAnnotations(
|
|
476
451
|
model.documentation
|
|
477
452
|
);
|
|
478
453
|
if (hidden) {
|
|
@@ -498,12 +473,14 @@ function stringifyRelationsInputUpdate(model, allModels) {
|
|
|
498
473
|
}
|
|
499
474
|
let fieldType;
|
|
500
475
|
if (field.isList) {
|
|
501
|
-
|
|
476
|
+
const connectType = `type({ "id": ${idType} }).array()`;
|
|
477
|
+
const disconnectType = `type({ "id": ${idType} }).array()`;
|
|
478
|
+
fieldType = `{ "connect?": ${connectType}, "disconnect?": ${disconnectType} }`;
|
|
502
479
|
} else {
|
|
503
480
|
if (field.isRequired) {
|
|
504
481
|
fieldType = `{ "connect": { "id": ${idType} } }`;
|
|
505
482
|
} else {
|
|
506
|
-
fieldType = `{ "connect"
|
|
483
|
+
fieldType = `{ "connect?": { "id": ${idType} }, "disconnect?": "boolean" }`;
|
|
507
484
|
}
|
|
508
485
|
}
|
|
509
486
|
fields.push(`"${field.name}?": ${fieldType}`);
|
|
@@ -511,10 +488,9 @@ function stringifyRelationsInputUpdate(model, allModels) {
|
|
|
511
488
|
if (fields.length === 0) {
|
|
512
489
|
return;
|
|
513
490
|
}
|
|
514
|
-
const options = generateArktypeOptions(modelAnnotations);
|
|
515
491
|
return `{
|
|
516
492
|
${fields.join(",\n ")}
|
|
517
|
-
}
|
|
493
|
+
}`;
|
|
518
494
|
}
|
|
519
495
|
|
|
520
496
|
const processedSelect = [];
|
|
@@ -531,7 +507,7 @@ function processSelect(models) {
|
|
|
531
507
|
Object.freeze(processedSelect);
|
|
532
508
|
}
|
|
533
509
|
function stringifySelect(model) {
|
|
534
|
-
const {
|
|
510
|
+
const { hidden } = extractAnnotations(
|
|
535
511
|
model.documentation
|
|
536
512
|
);
|
|
537
513
|
if (hidden) {
|
|
@@ -544,10 +520,9 @@ function stringifySelect(model) {
|
|
|
544
520
|
fields.push(`"${field.name}?": "boolean"`);
|
|
545
521
|
}
|
|
546
522
|
fields.push(`"_count?": "boolean"`);
|
|
547
|
-
const options = generateArktypeOptions(modelAnnotations);
|
|
548
523
|
return `{
|
|
549
524
|
${fields.join(",\n ")}
|
|
550
|
-
}
|
|
525
|
+
}`;
|
|
551
526
|
}
|
|
552
527
|
|
|
553
528
|
const processedUpdate = [];
|
|
@@ -590,7 +565,7 @@ function processWhere(models) {
|
|
|
590
565
|
}
|
|
591
566
|
const enumMatch = /type\("(.+)"\)/;
|
|
592
567
|
function stringifyWhere(model) {
|
|
593
|
-
const {
|
|
568
|
+
const { hidden } = extractAnnotations(
|
|
594
569
|
model.documentation
|
|
595
570
|
);
|
|
596
571
|
if (hidden) {
|
|
@@ -604,9 +579,9 @@ function stringifyWhere(model) {
|
|
|
604
579
|
const typeOverwrite = fieldAnnotations.find(isTypeOverwrite);
|
|
605
580
|
let fieldType;
|
|
606
581
|
if (typeOverwrite) {
|
|
607
|
-
fieldType =
|
|
582
|
+
fieldType = typeOverwrite.value;
|
|
608
583
|
} else if (isPrimitivePrismaFieldType(field.type)) {
|
|
609
|
-
fieldType = stringifyPrimitiveType(field.type
|
|
584
|
+
fieldType = stringifyPrimitiveType(field.type);
|
|
610
585
|
} else if (field.kind === "enum") {
|
|
611
586
|
const enumDef = processedEnums.find((e) => e.name === field.type);
|
|
612
587
|
if (!enumDef) continue;
|
|
@@ -617,17 +592,16 @@ function stringifyWhere(model) {
|
|
|
617
592
|
}
|
|
618
593
|
if (field.isList) {
|
|
619
594
|
const inner = fieldType.slice(1, -1);
|
|
620
|
-
fieldType = `"${
|
|
595
|
+
fieldType = `"${wrapPrimitiveWithArray(inner)}"`;
|
|
621
596
|
}
|
|
622
597
|
fields.push(`"${field.name}?": ${fieldType}`);
|
|
623
598
|
}
|
|
624
|
-
const options = generateArktypeOptions(modelAnnotations);
|
|
625
599
|
return `{
|
|
626
600
|
${fields.join(",\n ")}
|
|
627
|
-
}
|
|
601
|
+
}`;
|
|
628
602
|
}
|
|
629
603
|
function stringifyWhereUnique(model) {
|
|
630
|
-
const {
|
|
604
|
+
const { hidden } = extractAnnotations(
|
|
631
605
|
model.documentation
|
|
632
606
|
);
|
|
633
607
|
if (hidden) {
|
|
@@ -642,9 +616,9 @@ function stringifyWhereUnique(model) {
|
|
|
642
616
|
const typeOverwrite = fieldAnnotations.find(isTypeOverwrite);
|
|
643
617
|
let fieldType;
|
|
644
618
|
if (typeOverwrite) {
|
|
645
|
-
fieldType =
|
|
619
|
+
fieldType = typeOverwrite.value;
|
|
646
620
|
} else if (isPrimitivePrismaFieldType(field.type)) {
|
|
647
|
-
fieldType = stringifyPrimitiveType(field.type
|
|
621
|
+
fieldType = stringifyPrimitiveType(field.type);
|
|
648
622
|
} else if (field.kind === "enum") {
|
|
649
623
|
const enumDef = processedEnums.find((e) => e.name === field.type);
|
|
650
624
|
if (!enumDef) continue;
|
|
@@ -658,10 +632,9 @@ function stringifyWhereUnique(model) {
|
|
|
658
632
|
if (fields.length === 0) {
|
|
659
633
|
return;
|
|
660
634
|
}
|
|
661
|
-
const options = generateArktypeOptions(modelAnnotations);
|
|
662
635
|
return `{
|
|
663
636
|
${fields.join(",\n ")}
|
|
664
|
-
}
|
|
637
|
+
}`;
|
|
665
638
|
}
|
|
666
639
|
|
|
667
640
|
async function format(input) {
|
|
@@ -773,10 +746,6 @@ async function write(processedEnums, processedPlain, processedRelations, process
|
|
|
773
746
|
const filePath = join(config.output, `${name}.ts`);
|
|
774
747
|
writePromises.push(writeFile(filePath, await format(content)));
|
|
775
748
|
}
|
|
776
|
-
const barrelExports = Array.from(modelMap.keys()).map((name) => `export * from "./${name}";`).join("\n");
|
|
777
|
-
writePromises.push(
|
|
778
|
-
writeFile(join(config.output, "index.ts"), await format(barrelExports))
|
|
779
|
-
);
|
|
780
749
|
await Promise.all(writePromises);
|
|
781
750
|
}
|
|
782
751
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prisma-arktype",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Generate ArkType schemas from your Prisma schema",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -40,19 +40,19 @@
|
|
|
40
40
|
"arktype": "^2.1.25"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@biomejs/biome": "
|
|
43
|
+
"@biomejs/biome": "2.3.11",
|
|
44
44
|
"@changesets/cli": "^2.29.7",
|
|
45
45
|
"@commitlint/cli": "^20.1.0",
|
|
46
46
|
"@commitlint/config-conventional": "^20.0.0",
|
|
47
47
|
"@prisma/client": "^6.18.0",
|
|
48
|
-
"@tilli-pro/biome": "
|
|
48
|
+
"@tilli-pro/biome": "0.9.0",
|
|
49
49
|
"@types/node": "^24.10.0",
|
|
50
50
|
"lefthook": "^2.0.2",
|
|
51
51
|
"pkgroll": "^2.20.1",
|
|
52
|
-
"prisma": "
|
|
53
|
-
"tsx": "^4.
|
|
52
|
+
"prisma": "7.2.0",
|
|
53
|
+
"tsx": "^4.21.0",
|
|
54
54
|
"typescript": "^5.9.3",
|
|
55
|
-
"vitest": "^
|
|
55
|
+
"vitest": "^4.0.16"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "pkgroll",
|