prisma-zero 0.1.0 → 0.1.2
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 +8 -0
- package/dist/generator.cjs +119 -43
- package/dist/generator.js +119 -43
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -93,6 +93,14 @@ generator zero {
|
|
|
93
93
|
// Optional list of Prisma Model names you want to exclude from the generated schema
|
|
94
94
|
// This does *not* change tables that replicate to zero-cache - only the types on the client
|
|
95
95
|
excludeTables = ["Posts", "Comments", ...]
|
|
96
|
+
// When true, skip generating the query builder (`zql` and `builder` exports)
|
|
97
|
+
skipBuilder = true
|
|
98
|
+
// When true, skip generating the module augmentation for default types in Zero
|
|
99
|
+
skipDeclare = true
|
|
100
|
+
// When true, enable legacy CRUD mutators (sets `enableLegacyMutators` to `true` in the generated schema)
|
|
101
|
+
enableLegacyMutators = true
|
|
102
|
+
// When true, enable legacy CRUD queries (sets `enableLegacyQueries` to `true` in the generated schema)
|
|
103
|
+
enableLegacyQueries = true
|
|
96
104
|
}
|
|
97
105
|
```
|
|
98
106
|
|
package/dist/generator.cjs
CHANGED
|
@@ -39,14 +39,16 @@ var import_promises = require("fs/promises");
|
|
|
39
39
|
var import_path = require("path");
|
|
40
40
|
|
|
41
41
|
// package.json
|
|
42
|
-
var version = "0.1.
|
|
42
|
+
var version = "0.1.2";
|
|
43
43
|
|
|
44
44
|
// src/generators/code-generator.ts
|
|
45
|
-
function generateImports(schema) {
|
|
45
|
+
function generateImports(schema, config) {
|
|
46
46
|
const usedImports = /* @__PURE__ */ new Set();
|
|
47
47
|
usedImports.add("table");
|
|
48
48
|
usedImports.add("createSchema");
|
|
49
|
-
|
|
49
|
+
if (!config.skipBuilder) {
|
|
50
|
+
usedImports.add("createBuilder");
|
|
51
|
+
}
|
|
50
52
|
schema.models.forEach((model) => {
|
|
51
53
|
Object.values(model.columns).forEach((mapping) => {
|
|
52
54
|
const match = mapping.type.match(/^([a-z]+)/);
|
|
@@ -150,7 +152,7 @@ ${relationshipsStr}
|
|
|
150
152
|
const filteredRelationships = modelRelationships.filter(Boolean);
|
|
151
153
|
return filteredRelationships.length > 0 ? filteredRelationships.join("") : "";
|
|
152
154
|
}
|
|
153
|
-
function generateSchema(schema) {
|
|
155
|
+
function generateSchema(schema, config) {
|
|
154
156
|
let output = "/**\n";
|
|
155
157
|
output += " * The Zero schema object.\n";
|
|
156
158
|
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
@@ -175,43 +177,53 @@ function generateSchema(schema) {
|
|
|
175
177
|
});
|
|
176
178
|
output += " ],\n";
|
|
177
179
|
}
|
|
180
|
+
if (config.enableLegacyMutators) {
|
|
181
|
+
output += " enableLegacyMutators: true,\n";
|
|
182
|
+
}
|
|
183
|
+
if (config.enableLegacyQueries) {
|
|
184
|
+
output += " enableLegacyQueries: true,\n";
|
|
185
|
+
}
|
|
178
186
|
output += "});\n\n";
|
|
179
187
|
output += "/**\n";
|
|
180
188
|
output += " * Represents the Zero schema type.\n";
|
|
181
189
|
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
182
190
|
output += " */\n";
|
|
183
191
|
output += "export type Schema = typeof schema;\n";
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
192
|
+
if (!config.skipBuilder) {
|
|
193
|
+
output += "/**\n";
|
|
194
|
+
output += " * Represents the ZQL query builder.\n";
|
|
195
|
+
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
196
|
+
output += " */\n";
|
|
197
|
+
output += "export const zql = createBuilder(schema);\n";
|
|
198
|
+
output += "/**\n";
|
|
199
|
+
output += " * Represents the Zero schema query builder.\n";
|
|
200
|
+
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
201
|
+
output += " *\n";
|
|
202
|
+
output += " * @deprecated Use `zql` instead.\n";
|
|
203
|
+
output += " */\n";
|
|
204
|
+
output += "export const builder = zql;\n";
|
|
205
|
+
}
|
|
206
|
+
if (!config.skipDeclare) {
|
|
207
|
+
output += "/** Defines the default types for Zero */\n";
|
|
208
|
+
output += 'declare module "@rocicorp/zero" {\n';
|
|
209
|
+
output += " interface DefaultTypes {\n";
|
|
210
|
+
output += " schema: Schema;\n";
|
|
211
|
+
output += " }\n";
|
|
212
|
+
output += "}\n";
|
|
213
|
+
}
|
|
202
214
|
return output;
|
|
203
215
|
}
|
|
204
|
-
function generateCode(schema) {
|
|
216
|
+
function generateCode(schema, config) {
|
|
205
217
|
let output = `${HEADER_PREFIX}
|
|
206
218
|
|
|
207
219
|
`;
|
|
208
|
-
output += generateImports(schema);
|
|
220
|
+
output += generateImports(schema, config);
|
|
209
221
|
output += generateUnionTypes(schema);
|
|
210
222
|
schema.models.forEach((model) => {
|
|
211
223
|
output += generateModelSchema(model);
|
|
212
224
|
});
|
|
213
225
|
output += generateRelationships(schema.models);
|
|
214
|
-
output += generateSchema(schema);
|
|
226
|
+
output += generateSchema(schema, config);
|
|
215
227
|
return output;
|
|
216
228
|
}
|
|
217
229
|
var HEADER_PREFIX = `// This file was automatically generated by prisma-zero.
|
|
@@ -229,21 +241,27 @@ var TYPE_MAP = {
|
|
|
229
241
|
BigInt: "number()",
|
|
230
242
|
Decimal: "number()"
|
|
231
243
|
};
|
|
244
|
+
var ARRAY_TS_TYPE_MAP = {
|
|
245
|
+
String: "string[]",
|
|
246
|
+
Boolean: "boolean[]",
|
|
247
|
+
Int: "number[]",
|
|
248
|
+
Float: "number[]",
|
|
249
|
+
DateTime: "number[]",
|
|
250
|
+
Json: "any[]",
|
|
251
|
+
BigInt: "number[]",
|
|
252
|
+
Decimal: "number[]"
|
|
253
|
+
};
|
|
232
254
|
function mapPrismaTypeToZero(field) {
|
|
255
|
+
if (field.kind === "unsupported") {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
233
258
|
const isOptional = !field.isRequired;
|
|
234
259
|
const mappedName = field.dbName && field.dbName !== field.name ? field.dbName : null;
|
|
235
260
|
if (field.isList) {
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
Float: "number[]",
|
|
241
|
-
DateTime: "number[]",
|
|
242
|
-
Json: "any[]",
|
|
243
|
-
BigInt: "number[]",
|
|
244
|
-
Decimal: "number[]"
|
|
245
|
-
};
|
|
246
|
-
const tsType = field.kind === "enum" ? `${field.type}[]` : tsTypeMap[field.type] || "any[]";
|
|
261
|
+
const tsType = field.kind === "enum" ? `${field.type}[]` : ARRAY_TS_TYPE_MAP[field.type];
|
|
262
|
+
if (!tsType) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
247
265
|
return {
|
|
248
266
|
type: `json<${tsType}>()`,
|
|
249
267
|
isOptional,
|
|
@@ -257,7 +275,13 @@ function mapPrismaTypeToZero(field) {
|
|
|
257
275
|
mappedName
|
|
258
276
|
};
|
|
259
277
|
}
|
|
260
|
-
|
|
278
|
+
if (field.kind !== "scalar") {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
const baseType = TYPE_MAP[field.type];
|
|
282
|
+
if (!baseType) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
261
285
|
return {
|
|
262
286
|
type: baseType,
|
|
263
287
|
isOptional,
|
|
@@ -325,6 +349,12 @@ function createImplicitManyToManyModel(model1, model2, relationName, config) {
|
|
|
325
349
|
}
|
|
326
350
|
const columnAType = mapPrismaTypeToZero(idFieldA);
|
|
327
351
|
const columnBType = mapPrismaTypeToZero(idFieldB);
|
|
352
|
+
if (!columnAType || !columnBType) {
|
|
353
|
+
const unsupportedModel = !columnAType ? modelA : modelB;
|
|
354
|
+
throw new Error(
|
|
355
|
+
`Implicit relation ${relationName ?? "unknown"}: Model ${unsupportedModel.name} has an unsupported @id field.`
|
|
356
|
+
);
|
|
357
|
+
}
|
|
328
358
|
return {
|
|
329
359
|
tableName,
|
|
330
360
|
originalTableName,
|
|
@@ -353,6 +383,14 @@ function createImplicitManyToManyModel(model1, model2, relationName, config) {
|
|
|
353
383
|
}
|
|
354
384
|
function mapRelationships(model, dmmf, config) {
|
|
355
385
|
const relationships = {};
|
|
386
|
+
const isSupportedField = (target, fieldName) => {
|
|
387
|
+
const field = target.fields.find((f) => f.name === fieldName);
|
|
388
|
+
if (!field) {
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
return mapPrismaTypeToZero(field) !== null;
|
|
392
|
+
};
|
|
393
|
+
const areFieldsSupported = (target, fieldNames) => fieldNames.every((fieldName) => isSupportedField(target, fieldName));
|
|
356
394
|
model.fields.filter((field) => field.relationName).forEach((field) => {
|
|
357
395
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
358
396
|
const targetModel = dmmf.datamodel.models.find(
|
|
@@ -387,17 +425,25 @@ function mapRelationships(model, dmmf, config) {
|
|
|
387
425
|
}
|
|
388
426
|
const isSelfReferential = model.name === targetModel.name;
|
|
389
427
|
const isModelA = isSelfReferential ? backReference ? field.name.localeCompare(backReference.name) < 0 : true : model.name === modelA.name;
|
|
428
|
+
const sourceField = [((_b = model.fields.find((f) => f.isId)) == null ? void 0 : _b.name) || "id"];
|
|
429
|
+
const destField = [isModelA ? "A" : "B"];
|
|
430
|
+
const targetDestField = [
|
|
431
|
+
((_c = targetModel.fields.find((f) => f.isId)) == null ? void 0 : _c.name) || "id"
|
|
432
|
+
];
|
|
433
|
+
if (!areFieldsSupported(model, sourceField) || !areFieldsSupported(targetModel, targetDestField)) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
390
436
|
relationships[field.name] = {
|
|
391
437
|
type: "many",
|
|
392
438
|
chain: [
|
|
393
439
|
{
|
|
394
|
-
sourceField
|
|
395
|
-
destField
|
|
440
|
+
sourceField,
|
|
441
|
+
destField,
|
|
396
442
|
destSchema: getZeroTableName(joinTableName)
|
|
397
443
|
},
|
|
398
444
|
{
|
|
399
445
|
sourceField: [isModelA ? "B" : "A"],
|
|
400
|
-
destField:
|
|
446
|
+
destField: targetDestField,
|
|
401
447
|
destSchema: getZeroTableName(targetModel.name)
|
|
402
448
|
}
|
|
403
449
|
]
|
|
@@ -407,6 +453,9 @@ function mapRelationships(model, dmmf, config) {
|
|
|
407
453
|
const primaryKeyFields = ((_e = model.primaryKey) == null ? void 0 : _e.fields) || (idField ? [idField] : []);
|
|
408
454
|
const sourceFields = ensureStringArray(primaryKeyFields);
|
|
409
455
|
const destFields = (backReference == null ? void 0 : backReference.relationFromFields) ? ensureStringArray(backReference.relationFromFields) : [];
|
|
456
|
+
if (!areFieldsSupported(model, sourceFields) || !areFieldsSupported(targetModel, destFields)) {
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
410
459
|
relationships[field.name] = {
|
|
411
460
|
sourceField: sourceFields,
|
|
412
461
|
destField: destFields,
|
|
@@ -424,6 +473,9 @@ function mapRelationships(model, dmmf, config) {
|
|
|
424
473
|
sourceFields = backReference.relationToFields ? ensureStringArray(backReference.relationToFields) : [];
|
|
425
474
|
destFields = ensureStringArray(backReference.relationFromFields);
|
|
426
475
|
}
|
|
476
|
+
if (!areFieldsSupported(model, sourceFields) || !areFieldsSupported(targetModel, destFields)) {
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
427
479
|
relationships[field.name] = {
|
|
428
480
|
sourceField: sourceFields,
|
|
429
481
|
destField: destFields,
|
|
@@ -438,13 +490,29 @@ function mapModel(model, dmmf, config) {
|
|
|
438
490
|
var _a, _b;
|
|
439
491
|
const columns = {};
|
|
440
492
|
model.fields.filter((field) => !field.relationName).forEach((field) => {
|
|
441
|
-
|
|
493
|
+
const mapping = mapPrismaTypeToZero(field);
|
|
494
|
+
if (!mapping) {
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
columns[field.name] = mapping;
|
|
442
498
|
});
|
|
443
499
|
const idField = (_a = model.fields.find((f) => f.isId)) == null ? void 0 : _a.name;
|
|
444
500
|
const primaryKey = ((_b = model.primaryKey) == null ? void 0 : _b.fields) || (idField ? [idField] : []);
|
|
445
501
|
if (!primaryKey[0]) {
|
|
446
502
|
throw new Error(`No primary key found for ${model.name}`);
|
|
447
503
|
}
|
|
504
|
+
const unsupportedPrimaryKeys = primaryKey.filter((fieldName) => {
|
|
505
|
+
const field = model.fields.find((f) => f.name === fieldName);
|
|
506
|
+
if (!field) {
|
|
507
|
+
return false;
|
|
508
|
+
}
|
|
509
|
+
return mapPrismaTypeToZero(field) === null;
|
|
510
|
+
});
|
|
511
|
+
if (unsupportedPrimaryKeys.length > 0) {
|
|
512
|
+
throw new Error(
|
|
513
|
+
`Primary key field(s) ${unsupportedPrimaryKeys.join(", ")} in ${model.name} are not supported by Zero.`
|
|
514
|
+
);
|
|
515
|
+
}
|
|
448
516
|
const databaseTableName = getTableNameFromModel(model);
|
|
449
517
|
const tableName = getTableName(model.name, config);
|
|
450
518
|
const shouldRemap = tableName !== databaseTableName;
|
|
@@ -515,10 +583,18 @@ async function onGenerate(options) {
|
|
|
515
583
|
// Default true
|
|
516
584
|
camelCase: generator.config.camelCase === "true",
|
|
517
585
|
// Default false
|
|
518
|
-
excludeTables: loadExcludeTables(generator)
|
|
586
|
+
excludeTables: loadExcludeTables(generator),
|
|
587
|
+
skipBuilder: generator.config.skipBuilder === "true",
|
|
588
|
+
// Default false
|
|
589
|
+
skipDeclare: generator.config.skipDeclare === "true",
|
|
590
|
+
// Default false
|
|
591
|
+
enableLegacyMutators: generator.config.enableLegacyMutators === "true",
|
|
592
|
+
// Default false
|
|
593
|
+
enableLegacyQueries: generator.config.enableLegacyQueries === "true"
|
|
594
|
+
// Default false
|
|
519
595
|
};
|
|
520
596
|
const transformedSchema = transformSchema(dmmf, config);
|
|
521
|
-
let output = generateCode(transformedSchema);
|
|
597
|
+
let output = generateCode(transformedSchema, config);
|
|
522
598
|
if (config.prettier) {
|
|
523
599
|
let prettier;
|
|
524
600
|
try {
|
package/dist/generator.js
CHANGED
|
@@ -6,14 +6,16 @@ import { mkdir, writeFile } from "fs/promises";
|
|
|
6
6
|
import { join } from "path";
|
|
7
7
|
|
|
8
8
|
// package.json
|
|
9
|
-
var version = "0.1.
|
|
9
|
+
var version = "0.1.2";
|
|
10
10
|
|
|
11
11
|
// src/generators/code-generator.ts
|
|
12
|
-
function generateImports(schema) {
|
|
12
|
+
function generateImports(schema, config) {
|
|
13
13
|
const usedImports = /* @__PURE__ */ new Set();
|
|
14
14
|
usedImports.add("table");
|
|
15
15
|
usedImports.add("createSchema");
|
|
16
|
-
|
|
16
|
+
if (!config.skipBuilder) {
|
|
17
|
+
usedImports.add("createBuilder");
|
|
18
|
+
}
|
|
17
19
|
schema.models.forEach((model) => {
|
|
18
20
|
Object.values(model.columns).forEach((mapping) => {
|
|
19
21
|
const match = mapping.type.match(/^([a-z]+)/);
|
|
@@ -117,7 +119,7 @@ ${relationshipsStr}
|
|
|
117
119
|
const filteredRelationships = modelRelationships.filter(Boolean);
|
|
118
120
|
return filteredRelationships.length > 0 ? filteredRelationships.join("") : "";
|
|
119
121
|
}
|
|
120
|
-
function generateSchema(schema) {
|
|
122
|
+
function generateSchema(schema, config) {
|
|
121
123
|
let output = "/**\n";
|
|
122
124
|
output += " * The Zero schema object.\n";
|
|
123
125
|
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
@@ -142,43 +144,53 @@ function generateSchema(schema) {
|
|
|
142
144
|
});
|
|
143
145
|
output += " ],\n";
|
|
144
146
|
}
|
|
147
|
+
if (config.enableLegacyMutators) {
|
|
148
|
+
output += " enableLegacyMutators: true,\n";
|
|
149
|
+
}
|
|
150
|
+
if (config.enableLegacyQueries) {
|
|
151
|
+
output += " enableLegacyQueries: true,\n";
|
|
152
|
+
}
|
|
145
153
|
output += "});\n\n";
|
|
146
154
|
output += "/**\n";
|
|
147
155
|
output += " * Represents the Zero schema type.\n";
|
|
148
156
|
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
149
157
|
output += " */\n";
|
|
150
158
|
output += "export type Schema = typeof schema;\n";
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
159
|
+
if (!config.skipBuilder) {
|
|
160
|
+
output += "/**\n";
|
|
161
|
+
output += " * Represents the ZQL query builder.\n";
|
|
162
|
+
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
163
|
+
output += " */\n";
|
|
164
|
+
output += "export const zql = createBuilder(schema);\n";
|
|
165
|
+
output += "/**\n";
|
|
166
|
+
output += " * Represents the Zero schema query builder.\n";
|
|
167
|
+
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
168
|
+
output += " *\n";
|
|
169
|
+
output += " * @deprecated Use `zql` instead.\n";
|
|
170
|
+
output += " */\n";
|
|
171
|
+
output += "export const builder = zql;\n";
|
|
172
|
+
}
|
|
173
|
+
if (!config.skipDeclare) {
|
|
174
|
+
output += "/** Defines the default types for Zero */\n";
|
|
175
|
+
output += 'declare module "@rocicorp/zero" {\n';
|
|
176
|
+
output += " interface DefaultTypes {\n";
|
|
177
|
+
output += " schema: Schema;\n";
|
|
178
|
+
output += " }\n";
|
|
179
|
+
output += "}\n";
|
|
180
|
+
}
|
|
169
181
|
return output;
|
|
170
182
|
}
|
|
171
|
-
function generateCode(schema) {
|
|
183
|
+
function generateCode(schema, config) {
|
|
172
184
|
let output = `${HEADER_PREFIX}
|
|
173
185
|
|
|
174
186
|
`;
|
|
175
|
-
output += generateImports(schema);
|
|
187
|
+
output += generateImports(schema, config);
|
|
176
188
|
output += generateUnionTypes(schema);
|
|
177
189
|
schema.models.forEach((model) => {
|
|
178
190
|
output += generateModelSchema(model);
|
|
179
191
|
});
|
|
180
192
|
output += generateRelationships(schema.models);
|
|
181
|
-
output += generateSchema(schema);
|
|
193
|
+
output += generateSchema(schema, config);
|
|
182
194
|
return output;
|
|
183
195
|
}
|
|
184
196
|
var HEADER_PREFIX = `// This file was automatically generated by prisma-zero.
|
|
@@ -196,21 +208,27 @@ var TYPE_MAP = {
|
|
|
196
208
|
BigInt: "number()",
|
|
197
209
|
Decimal: "number()"
|
|
198
210
|
};
|
|
211
|
+
var ARRAY_TS_TYPE_MAP = {
|
|
212
|
+
String: "string[]",
|
|
213
|
+
Boolean: "boolean[]",
|
|
214
|
+
Int: "number[]",
|
|
215
|
+
Float: "number[]",
|
|
216
|
+
DateTime: "number[]",
|
|
217
|
+
Json: "any[]",
|
|
218
|
+
BigInt: "number[]",
|
|
219
|
+
Decimal: "number[]"
|
|
220
|
+
};
|
|
199
221
|
function mapPrismaTypeToZero(field) {
|
|
222
|
+
if (field.kind === "unsupported") {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
200
225
|
const isOptional = !field.isRequired;
|
|
201
226
|
const mappedName = field.dbName && field.dbName !== field.name ? field.dbName : null;
|
|
202
227
|
if (field.isList) {
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
Float: "number[]",
|
|
208
|
-
DateTime: "number[]",
|
|
209
|
-
Json: "any[]",
|
|
210
|
-
BigInt: "number[]",
|
|
211
|
-
Decimal: "number[]"
|
|
212
|
-
};
|
|
213
|
-
const tsType = field.kind === "enum" ? `${field.type}[]` : tsTypeMap[field.type] || "any[]";
|
|
228
|
+
const tsType = field.kind === "enum" ? `${field.type}[]` : ARRAY_TS_TYPE_MAP[field.type];
|
|
229
|
+
if (!tsType) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
214
232
|
return {
|
|
215
233
|
type: `json<${tsType}>()`,
|
|
216
234
|
isOptional,
|
|
@@ -224,7 +242,13 @@ function mapPrismaTypeToZero(field) {
|
|
|
224
242
|
mappedName
|
|
225
243
|
};
|
|
226
244
|
}
|
|
227
|
-
|
|
245
|
+
if (field.kind !== "scalar") {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
const baseType = TYPE_MAP[field.type];
|
|
249
|
+
if (!baseType) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
228
252
|
return {
|
|
229
253
|
type: baseType,
|
|
230
254
|
isOptional,
|
|
@@ -292,6 +316,12 @@ function createImplicitManyToManyModel(model1, model2, relationName, config) {
|
|
|
292
316
|
}
|
|
293
317
|
const columnAType = mapPrismaTypeToZero(idFieldA);
|
|
294
318
|
const columnBType = mapPrismaTypeToZero(idFieldB);
|
|
319
|
+
if (!columnAType || !columnBType) {
|
|
320
|
+
const unsupportedModel = !columnAType ? modelA : modelB;
|
|
321
|
+
throw new Error(
|
|
322
|
+
`Implicit relation ${relationName ?? "unknown"}: Model ${unsupportedModel.name} has an unsupported @id field.`
|
|
323
|
+
);
|
|
324
|
+
}
|
|
295
325
|
return {
|
|
296
326
|
tableName,
|
|
297
327
|
originalTableName,
|
|
@@ -320,6 +350,14 @@ function createImplicitManyToManyModel(model1, model2, relationName, config) {
|
|
|
320
350
|
}
|
|
321
351
|
function mapRelationships(model, dmmf, config) {
|
|
322
352
|
const relationships = {};
|
|
353
|
+
const isSupportedField = (target, fieldName) => {
|
|
354
|
+
const field = target.fields.find((f) => f.name === fieldName);
|
|
355
|
+
if (!field) {
|
|
356
|
+
return true;
|
|
357
|
+
}
|
|
358
|
+
return mapPrismaTypeToZero(field) !== null;
|
|
359
|
+
};
|
|
360
|
+
const areFieldsSupported = (target, fieldNames) => fieldNames.every((fieldName) => isSupportedField(target, fieldName));
|
|
323
361
|
model.fields.filter((field) => field.relationName).forEach((field) => {
|
|
324
362
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
325
363
|
const targetModel = dmmf.datamodel.models.find(
|
|
@@ -354,17 +392,25 @@ function mapRelationships(model, dmmf, config) {
|
|
|
354
392
|
}
|
|
355
393
|
const isSelfReferential = model.name === targetModel.name;
|
|
356
394
|
const isModelA = isSelfReferential ? backReference ? field.name.localeCompare(backReference.name) < 0 : true : model.name === modelA.name;
|
|
395
|
+
const sourceField = [((_b = model.fields.find((f) => f.isId)) == null ? void 0 : _b.name) || "id"];
|
|
396
|
+
const destField = [isModelA ? "A" : "B"];
|
|
397
|
+
const targetDestField = [
|
|
398
|
+
((_c = targetModel.fields.find((f) => f.isId)) == null ? void 0 : _c.name) || "id"
|
|
399
|
+
];
|
|
400
|
+
if (!areFieldsSupported(model, sourceField) || !areFieldsSupported(targetModel, targetDestField)) {
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
357
403
|
relationships[field.name] = {
|
|
358
404
|
type: "many",
|
|
359
405
|
chain: [
|
|
360
406
|
{
|
|
361
|
-
sourceField
|
|
362
|
-
destField
|
|
407
|
+
sourceField,
|
|
408
|
+
destField,
|
|
363
409
|
destSchema: getZeroTableName(joinTableName)
|
|
364
410
|
},
|
|
365
411
|
{
|
|
366
412
|
sourceField: [isModelA ? "B" : "A"],
|
|
367
|
-
destField:
|
|
413
|
+
destField: targetDestField,
|
|
368
414
|
destSchema: getZeroTableName(targetModel.name)
|
|
369
415
|
}
|
|
370
416
|
]
|
|
@@ -374,6 +420,9 @@ function mapRelationships(model, dmmf, config) {
|
|
|
374
420
|
const primaryKeyFields = ((_e = model.primaryKey) == null ? void 0 : _e.fields) || (idField ? [idField] : []);
|
|
375
421
|
const sourceFields = ensureStringArray(primaryKeyFields);
|
|
376
422
|
const destFields = (backReference == null ? void 0 : backReference.relationFromFields) ? ensureStringArray(backReference.relationFromFields) : [];
|
|
423
|
+
if (!areFieldsSupported(model, sourceFields) || !areFieldsSupported(targetModel, destFields)) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
377
426
|
relationships[field.name] = {
|
|
378
427
|
sourceField: sourceFields,
|
|
379
428
|
destField: destFields,
|
|
@@ -391,6 +440,9 @@ function mapRelationships(model, dmmf, config) {
|
|
|
391
440
|
sourceFields = backReference.relationToFields ? ensureStringArray(backReference.relationToFields) : [];
|
|
392
441
|
destFields = ensureStringArray(backReference.relationFromFields);
|
|
393
442
|
}
|
|
443
|
+
if (!areFieldsSupported(model, sourceFields) || !areFieldsSupported(targetModel, destFields)) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
394
446
|
relationships[field.name] = {
|
|
395
447
|
sourceField: sourceFields,
|
|
396
448
|
destField: destFields,
|
|
@@ -405,13 +457,29 @@ function mapModel(model, dmmf, config) {
|
|
|
405
457
|
var _a, _b;
|
|
406
458
|
const columns = {};
|
|
407
459
|
model.fields.filter((field) => !field.relationName).forEach((field) => {
|
|
408
|
-
|
|
460
|
+
const mapping = mapPrismaTypeToZero(field);
|
|
461
|
+
if (!mapping) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
columns[field.name] = mapping;
|
|
409
465
|
});
|
|
410
466
|
const idField = (_a = model.fields.find((f) => f.isId)) == null ? void 0 : _a.name;
|
|
411
467
|
const primaryKey = ((_b = model.primaryKey) == null ? void 0 : _b.fields) || (idField ? [idField] : []);
|
|
412
468
|
if (!primaryKey[0]) {
|
|
413
469
|
throw new Error(`No primary key found for ${model.name}`);
|
|
414
470
|
}
|
|
471
|
+
const unsupportedPrimaryKeys = primaryKey.filter((fieldName) => {
|
|
472
|
+
const field = model.fields.find((f) => f.name === fieldName);
|
|
473
|
+
if (!field) {
|
|
474
|
+
return false;
|
|
475
|
+
}
|
|
476
|
+
return mapPrismaTypeToZero(field) === null;
|
|
477
|
+
});
|
|
478
|
+
if (unsupportedPrimaryKeys.length > 0) {
|
|
479
|
+
throw new Error(
|
|
480
|
+
`Primary key field(s) ${unsupportedPrimaryKeys.join(", ")} in ${model.name} are not supported by Zero.`
|
|
481
|
+
);
|
|
482
|
+
}
|
|
415
483
|
const databaseTableName = getTableNameFromModel(model);
|
|
416
484
|
const tableName = getTableName(model.name, config);
|
|
417
485
|
const shouldRemap = tableName !== databaseTableName;
|
|
@@ -482,10 +550,18 @@ async function onGenerate(options) {
|
|
|
482
550
|
// Default true
|
|
483
551
|
camelCase: generator.config.camelCase === "true",
|
|
484
552
|
// Default false
|
|
485
|
-
excludeTables: loadExcludeTables(generator)
|
|
553
|
+
excludeTables: loadExcludeTables(generator),
|
|
554
|
+
skipBuilder: generator.config.skipBuilder === "true",
|
|
555
|
+
// Default false
|
|
556
|
+
skipDeclare: generator.config.skipDeclare === "true",
|
|
557
|
+
// Default false
|
|
558
|
+
enableLegacyMutators: generator.config.enableLegacyMutators === "true",
|
|
559
|
+
// Default false
|
|
560
|
+
enableLegacyQueries: generator.config.enableLegacyQueries === "true"
|
|
561
|
+
// Default false
|
|
486
562
|
};
|
|
487
563
|
const transformedSchema = transformSchema(dmmf, config);
|
|
488
|
-
let output = generateCode(transformedSchema);
|
|
564
|
+
let output = generateCode(transformedSchema, config);
|
|
489
565
|
if (config.prettier) {
|
|
490
566
|
let prettier;
|
|
491
567
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prisma-zero",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Generate Zero schemas from Prisma ORM schemas",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@rocicorp/prettier-config": "^0.4.0",
|
|
44
|
-
"@rocicorp/zero": "0.25.
|
|
44
|
+
"@rocicorp/zero": "0.25.2",
|
|
45
45
|
"@types/node": "^24.10.1",
|
|
46
46
|
"@types/pg": "^8.15.6",
|
|
47
47
|
"@types/pluralize": "^0.0.33",
|