prisma-zero 0.1.0-canary.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/LICENSE +201 -0
- package/README.md +134 -0
- package/dist/generator.cjs +563 -0
- package/dist/generator.d.cts +5 -0
- package/dist/generator.d.ts +5 -0
- package/dist/generator.js +529 -0
- package/package.json +74 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
|
|
31
|
+
// src/generator.ts
|
|
32
|
+
var generator_exports = {};
|
|
33
|
+
__export(generator_exports, {
|
|
34
|
+
onGenerate: () => onGenerate
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(generator_exports);
|
|
37
|
+
var import_generator_helper = __toESM(require("@prisma/generator-helper"), 1);
|
|
38
|
+
var import_promises = require("fs/promises");
|
|
39
|
+
var import_path = require("path");
|
|
40
|
+
|
|
41
|
+
// package.json
|
|
42
|
+
var version = "0.1.0-canary.0";
|
|
43
|
+
|
|
44
|
+
// src/generators/code-generator.ts
|
|
45
|
+
function generateImports(schema) {
|
|
46
|
+
const usedImports = /* @__PURE__ */ new Set();
|
|
47
|
+
usedImports.add("table");
|
|
48
|
+
usedImports.add("createSchema");
|
|
49
|
+
usedImports.add("createBuilder");
|
|
50
|
+
usedImports.add("createCRUDBuilder");
|
|
51
|
+
schema.models.forEach((model) => {
|
|
52
|
+
Object.values(model.columns).forEach((mapping) => {
|
|
53
|
+
const baseType = mapping.type.split("(")[0];
|
|
54
|
+
if (baseType) {
|
|
55
|
+
usedImports.add(baseType);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
if (model.relationships && Object.keys(model.relationships).length > 0) {
|
|
59
|
+
usedImports.add("relationships");
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
const sortedImports = Array.from(usedImports).sort();
|
|
63
|
+
return `import {
|
|
64
|
+
${sortedImports.join(",\n ")},
|
|
65
|
+
} from "@rocicorp/zero";
|
|
66
|
+
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
function generateUnionTypes(schema) {
|
|
70
|
+
if (schema.enums.length === 0) return "";
|
|
71
|
+
let output = "";
|
|
72
|
+
schema.enums.forEach((enumType) => {
|
|
73
|
+
output += `export type ${enumType.name} = `;
|
|
74
|
+
const values = enumType.values.map((value) => {
|
|
75
|
+
const enumValue = value.dbName || value.name;
|
|
76
|
+
return `"${enumValue}"`;
|
|
77
|
+
});
|
|
78
|
+
output += values.join(" | ");
|
|
79
|
+
output += ";\n\n";
|
|
80
|
+
});
|
|
81
|
+
return output;
|
|
82
|
+
}
|
|
83
|
+
function generateColumnDefinition(name, mapping) {
|
|
84
|
+
let typeStr = mapping.type;
|
|
85
|
+
if (mapping.mappedName) {
|
|
86
|
+
typeStr += `.from('${mapping.mappedName}')`;
|
|
87
|
+
}
|
|
88
|
+
if (mapping.isOptional) {
|
|
89
|
+
typeStr += `.optional()`;
|
|
90
|
+
}
|
|
91
|
+
return ` ${name}: ${typeStr}`;
|
|
92
|
+
}
|
|
93
|
+
function generateModelSchema(model) {
|
|
94
|
+
let output = `export const ${model.zeroTableName} = table("${model.tableName}")`;
|
|
95
|
+
if (model.originalTableName) {
|
|
96
|
+
output += `
|
|
97
|
+
.from("${model.originalTableName}")`;
|
|
98
|
+
}
|
|
99
|
+
output += "\n .columns({\n";
|
|
100
|
+
Object.entries(model.columns).forEach(([name, mapping]) => {
|
|
101
|
+
output += generateColumnDefinition(name, mapping) + ",\n";
|
|
102
|
+
});
|
|
103
|
+
output += " })";
|
|
104
|
+
output += `
|
|
105
|
+
.primaryKey(${model.primaryKey.map((key) => `"${key}"`).join(", ")});
|
|
106
|
+
|
|
107
|
+
`;
|
|
108
|
+
return output;
|
|
109
|
+
}
|
|
110
|
+
function generateRelationshipConfig(rel) {
|
|
111
|
+
if ("chain" in rel) {
|
|
112
|
+
return rel.chain.map(
|
|
113
|
+
(link) => `{
|
|
114
|
+
sourceField: ${JSON.stringify(link.sourceField)},
|
|
115
|
+
destField: ${JSON.stringify(link.destField)},
|
|
116
|
+
destSchema: ${link.destSchema},
|
|
117
|
+
}`
|
|
118
|
+
).join(", ");
|
|
119
|
+
} else {
|
|
120
|
+
return `{
|
|
121
|
+
sourceField: ${JSON.stringify(rel.sourceField)},
|
|
122
|
+
destField: ${JSON.stringify(rel.destField)},
|
|
123
|
+
destSchema: ${rel.destSchema},
|
|
124
|
+
}`;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function generateRelationships(models) {
|
|
128
|
+
const modelRelationships = models.map((model) => {
|
|
129
|
+
if (!model.relationships) return "";
|
|
130
|
+
const relationshipEntries = Object.entries(model.relationships);
|
|
131
|
+
if (relationshipEntries.length === 0) return "";
|
|
132
|
+
const hasOneRelation = relationshipEntries.some(
|
|
133
|
+
([, rel]) => rel.type === "one"
|
|
134
|
+
);
|
|
135
|
+
const hasManyRelation = relationshipEntries.some(
|
|
136
|
+
([, rel]) => rel.type === "many"
|
|
137
|
+
);
|
|
138
|
+
const relationshipImports = [];
|
|
139
|
+
if (hasOneRelation) relationshipImports.push("one");
|
|
140
|
+
if (hasManyRelation) relationshipImports.push("many");
|
|
141
|
+
const relationshipsStr = relationshipEntries.map(([name, rel]) => {
|
|
142
|
+
const configStr = generateRelationshipConfig(rel);
|
|
143
|
+
return ` ${name}: ${rel.type}(${configStr})`;
|
|
144
|
+
}).join(",\n");
|
|
145
|
+
return `export const ${model.zeroTableName}Relationships = relationships(${model.zeroTableName}, ({ ${relationshipImports.join(", ")} }) => ({
|
|
146
|
+
${relationshipsStr}
|
|
147
|
+
}));
|
|
148
|
+
`;
|
|
149
|
+
});
|
|
150
|
+
const filteredRelationships = modelRelationships.filter(Boolean);
|
|
151
|
+
return filteredRelationships.length > 0 ? filteredRelationships.join("") : "";
|
|
152
|
+
}
|
|
153
|
+
function generateSchema(schema) {
|
|
154
|
+
let output = "/**\n";
|
|
155
|
+
output += " * The Zero schema object.\n";
|
|
156
|
+
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
157
|
+
output += " */\n";
|
|
158
|
+
output += "export const schema = createSchema({\n";
|
|
159
|
+
output += " tables: [\n";
|
|
160
|
+
schema.models.forEach((model) => {
|
|
161
|
+
output += ` ${model.zeroTableName},
|
|
162
|
+
`;
|
|
163
|
+
});
|
|
164
|
+
output += " ],\n";
|
|
165
|
+
const hasRelationships = schema.models.some(
|
|
166
|
+
(model) => model.relationships && Object.keys(model.relationships).length > 0
|
|
167
|
+
);
|
|
168
|
+
if (hasRelationships) {
|
|
169
|
+
output += " relationships: [\n";
|
|
170
|
+
schema.models.forEach((model) => {
|
|
171
|
+
if (model.relationships && Object.keys(model.relationships).length > 0) {
|
|
172
|
+
output += ` ${model.zeroTableName}Relationships,
|
|
173
|
+
`;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
output += " ],\n";
|
|
177
|
+
}
|
|
178
|
+
output += "});\n\n";
|
|
179
|
+
output += "/**\n";
|
|
180
|
+
output += " * Represents the Zero schema type.\n";
|
|
181
|
+
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
182
|
+
output += " */\n";
|
|
183
|
+
output += "export type Schema = typeof schema;\n";
|
|
184
|
+
output += "/**\n";
|
|
185
|
+
output += " * Represents the ZQL query builder.\n";
|
|
186
|
+
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
187
|
+
output += " */\n";
|
|
188
|
+
output += "export const zql = createBuilder(schema);\n";
|
|
189
|
+
output += "/**\n";
|
|
190
|
+
output += " * Represents the Zero schema query builder.\n";
|
|
191
|
+
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
192
|
+
output += " *\n";
|
|
193
|
+
output += " * @deprecated Use `zql` instead.\n";
|
|
194
|
+
output += " */\n";
|
|
195
|
+
output += "export const builder = zql;\n";
|
|
196
|
+
output += "/**\n";
|
|
197
|
+
output += " * Represents the Zero schema CRUD builder.\n";
|
|
198
|
+
output += " * This type is auto-generated from your Prisma schema definition.\n";
|
|
199
|
+
output += " */\n";
|
|
200
|
+
output += "export const crud = createCRUDBuilder(schema);\n";
|
|
201
|
+
output += "/** Defines the default types for Zero */\n";
|
|
202
|
+
output += 'declare module "@rocicorp/zero" {\n';
|
|
203
|
+
output += " interface DefaultTypes {\n";
|
|
204
|
+
output += " schema: Schema;\n";
|
|
205
|
+
output += " }\n";
|
|
206
|
+
output += "}\n";
|
|
207
|
+
return output;
|
|
208
|
+
}
|
|
209
|
+
function generateCode(schema) {
|
|
210
|
+
let output = `${HEADER_PREFIX}
|
|
211
|
+
|
|
212
|
+
`;
|
|
213
|
+
output += generateImports(schema);
|
|
214
|
+
output += generateUnionTypes(schema);
|
|
215
|
+
schema.models.forEach((model) => {
|
|
216
|
+
output += generateModelSchema(model);
|
|
217
|
+
});
|
|
218
|
+
output += generateRelationships(schema.models);
|
|
219
|
+
output += generateSchema(schema);
|
|
220
|
+
return output;
|
|
221
|
+
}
|
|
222
|
+
var HEADER_PREFIX = `// This file was automatically generated by prisma-zero.
|
|
223
|
+
// You should NOT make any changes in this file as it will be overwritten.`;
|
|
224
|
+
|
|
225
|
+
// src/mappers/type-mapper.ts
|
|
226
|
+
var TYPE_MAP = {
|
|
227
|
+
String: "string()",
|
|
228
|
+
Boolean: "boolean()",
|
|
229
|
+
Int: "number()",
|
|
230
|
+
Float: "number()",
|
|
231
|
+
DateTime: "number()",
|
|
232
|
+
// Zero uses timestamps
|
|
233
|
+
Json: "json()",
|
|
234
|
+
BigInt: "number()",
|
|
235
|
+
Decimal: "number()"
|
|
236
|
+
};
|
|
237
|
+
function mapPrismaTypeToZero(field) {
|
|
238
|
+
const isOptional = !field.isRequired;
|
|
239
|
+
const mappedName = field.dbName && field.dbName !== field.name ? field.dbName : null;
|
|
240
|
+
if (field.isList) {
|
|
241
|
+
const tsTypeMap = {
|
|
242
|
+
String: "string[]",
|
|
243
|
+
Boolean: "boolean[]",
|
|
244
|
+
Int: "number[]",
|
|
245
|
+
Float: "number[]",
|
|
246
|
+
DateTime: "number[]",
|
|
247
|
+
Json: "any[]",
|
|
248
|
+
BigInt: "number[]",
|
|
249
|
+
Decimal: "number[]"
|
|
250
|
+
};
|
|
251
|
+
const tsType = field.kind === "enum" ? `${field.type}[]` : tsTypeMap[field.type] || "any[]";
|
|
252
|
+
return {
|
|
253
|
+
type: `json<${tsType}>()`,
|
|
254
|
+
isOptional,
|
|
255
|
+
mappedName
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
if (field.kind === "enum") {
|
|
259
|
+
return {
|
|
260
|
+
type: `enumeration<${field.type}>()`,
|
|
261
|
+
isOptional,
|
|
262
|
+
mappedName
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
const baseType = TYPE_MAP[field.type] || "string()";
|
|
266
|
+
return {
|
|
267
|
+
type: baseType,
|
|
268
|
+
isOptional,
|
|
269
|
+
mappedName
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// src/mappers/schema-mapper.ts
|
|
274
|
+
var import_camelcase = __toESM(require("camelcase"), 1);
|
|
275
|
+
function getTableNameFromModel(model) {
|
|
276
|
+
return model.dbName || model.name;
|
|
277
|
+
}
|
|
278
|
+
function getZeroTableName(str) {
|
|
279
|
+
const tableName = getTableName(str, { camelCase: true });
|
|
280
|
+
return tableName + "Table";
|
|
281
|
+
}
|
|
282
|
+
function ensureStringArray(arr) {
|
|
283
|
+
return Array.from(arr).filter((item) => item !== void 0);
|
|
284
|
+
}
|
|
285
|
+
function getImplicitManyToManyTableName(model1, model2, relationName) {
|
|
286
|
+
if (relationName) {
|
|
287
|
+
return `_${relationName}`;
|
|
288
|
+
}
|
|
289
|
+
const [first, second] = [model1, model2].sort();
|
|
290
|
+
return `_${first}To${second}`;
|
|
291
|
+
}
|
|
292
|
+
function toCamelCase(str) {
|
|
293
|
+
const prefixMatch = str.match(/^_+/);
|
|
294
|
+
const prefix = prefixMatch ? prefixMatch[0] : "";
|
|
295
|
+
const rest = str.slice(prefix.length);
|
|
296
|
+
return prefix + (0, import_camelcase.default)(rest);
|
|
297
|
+
}
|
|
298
|
+
function getTableName(tableName, config) {
|
|
299
|
+
if (config == null ? void 0 : config.camelCase) {
|
|
300
|
+
return toCamelCase(tableName);
|
|
301
|
+
}
|
|
302
|
+
return tableName;
|
|
303
|
+
}
|
|
304
|
+
function createImplicitManyToManyModel(model1, model2, relationName, config) {
|
|
305
|
+
const originalTableName = getImplicitManyToManyTableName(
|
|
306
|
+
model1.name,
|
|
307
|
+
model2.name,
|
|
308
|
+
relationName
|
|
309
|
+
);
|
|
310
|
+
const [modelA, modelB] = [model1, model2].sort(
|
|
311
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
312
|
+
);
|
|
313
|
+
if (!modelA || !modelB) {
|
|
314
|
+
throw new Error(
|
|
315
|
+
`Implicit relation ${relationName}: Model ${(modelA == null ? void 0 : modelA.name) ?? "unknown"} or ${(modelB == null ? void 0 : modelB.name) ?? "unknown"} not found.`
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
const tableName = getTableName(originalTableName, config);
|
|
319
|
+
const idFieldA = modelA.fields.find((f) => f.isId);
|
|
320
|
+
const idFieldB = modelB.fields.find((f) => f.isId);
|
|
321
|
+
if (!idFieldA) {
|
|
322
|
+
throw new Error(
|
|
323
|
+
`Implicit relation ${relationName}: Model ${modelA.name} has no @id field.`
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
if (!idFieldB) {
|
|
327
|
+
throw new Error(
|
|
328
|
+
`Implicit relation ${relationName}: Model ${modelB.name} has no @id field.`
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
const columnAType = mapPrismaTypeToZero(idFieldA);
|
|
332
|
+
const columnBType = mapPrismaTypeToZero(idFieldB);
|
|
333
|
+
return {
|
|
334
|
+
tableName,
|
|
335
|
+
originalTableName,
|
|
336
|
+
modelName: originalTableName,
|
|
337
|
+
zeroTableName: getZeroTableName(originalTableName),
|
|
338
|
+
columns: {
|
|
339
|
+
A: columnAType,
|
|
340
|
+
B: columnBType
|
|
341
|
+
},
|
|
342
|
+
relationships: {
|
|
343
|
+
modelA: {
|
|
344
|
+
sourceField: ["A"],
|
|
345
|
+
destField: [idFieldA.name],
|
|
346
|
+
destSchema: getZeroTableName(modelA.name),
|
|
347
|
+
type: "one"
|
|
348
|
+
},
|
|
349
|
+
modelB: {
|
|
350
|
+
sourceField: ["B"],
|
|
351
|
+
destField: [idFieldB.name],
|
|
352
|
+
destSchema: getZeroTableName(modelB.name),
|
|
353
|
+
type: "one"
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
primaryKey: ["A", "B"]
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
function mapRelationships(model, dmmf, config) {
|
|
360
|
+
const relationships = {};
|
|
361
|
+
model.fields.filter((field) => field.relationName).forEach((field) => {
|
|
362
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
363
|
+
const targetModel = dmmf.datamodel.models.find(
|
|
364
|
+
(m) => m.name === field.type
|
|
365
|
+
);
|
|
366
|
+
if (!targetModel) {
|
|
367
|
+
throw new Error(
|
|
368
|
+
`Target model ${field.type} not found for relationship ${field.name}`
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
if ((_a = config.excludeTables) == null ? void 0 : _a.includes(targetModel.name)) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
const backReference = targetModel.fields.find(
|
|
375
|
+
(f) => f.relationName === field.relationName && f.type === model.name
|
|
376
|
+
);
|
|
377
|
+
if (field.isList) {
|
|
378
|
+
if (backReference == null ? void 0 : backReference.isList) {
|
|
379
|
+
const joinTableName = getImplicitManyToManyTableName(
|
|
380
|
+
model.name,
|
|
381
|
+
targetModel.name,
|
|
382
|
+
field.relationName
|
|
383
|
+
);
|
|
384
|
+
const [modelA] = [model, targetModel].sort(
|
|
385
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
386
|
+
);
|
|
387
|
+
if (!modelA) {
|
|
388
|
+
throw new Error(
|
|
389
|
+
`Implicit relation ${field.name}: Model ${model.name} or ${targetModel.name} not found.`
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
const isModelA = model.name === modelA.name;
|
|
393
|
+
relationships[field.name] = {
|
|
394
|
+
type: "many",
|
|
395
|
+
chain: [
|
|
396
|
+
{
|
|
397
|
+
sourceField: [((_b = model.fields.find((f) => f.isId)) == null ? void 0 : _b.name) || "id"],
|
|
398
|
+
destField: [isModelA ? "A" : "B"],
|
|
399
|
+
destSchema: getZeroTableName(joinTableName)
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
sourceField: [isModelA ? "B" : "A"],
|
|
403
|
+
destField: [((_c = targetModel.fields.find((f) => f.isId)) == null ? void 0 : _c.name) || "id"],
|
|
404
|
+
destSchema: getZeroTableName(targetModel.name)
|
|
405
|
+
}
|
|
406
|
+
]
|
|
407
|
+
};
|
|
408
|
+
} else {
|
|
409
|
+
const idField = (_d = model.fields.find((f) => f.isId)) == null ? void 0 : _d.name;
|
|
410
|
+
const primaryKeyFields = ((_e = model.primaryKey) == null ? void 0 : _e.fields) || (idField ? [idField] : []);
|
|
411
|
+
const sourceFields = ensureStringArray(primaryKeyFields);
|
|
412
|
+
const destFields = (backReference == null ? void 0 : backReference.relationFromFields) ? ensureStringArray(backReference.relationFromFields) : [];
|
|
413
|
+
relationships[field.name] = {
|
|
414
|
+
sourceField: sourceFields,
|
|
415
|
+
destField: destFields,
|
|
416
|
+
destSchema: getZeroTableName(targetModel.name),
|
|
417
|
+
type: "many"
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
} else {
|
|
421
|
+
let sourceFields = [];
|
|
422
|
+
let destFields = [];
|
|
423
|
+
if ((_f = field.relationFromFields) == null ? void 0 : _f.length) {
|
|
424
|
+
sourceFields = ensureStringArray(field.relationFromFields);
|
|
425
|
+
destFields = field.relationToFields ? ensureStringArray(field.relationToFields) : [];
|
|
426
|
+
} else if ((_g = backReference == null ? void 0 : backReference.relationFromFields) == null ? void 0 : _g.length) {
|
|
427
|
+
sourceFields = backReference.relationToFields ? ensureStringArray(backReference.relationToFields) : [];
|
|
428
|
+
destFields = ensureStringArray(backReference.relationFromFields);
|
|
429
|
+
}
|
|
430
|
+
relationships[field.name] = {
|
|
431
|
+
sourceField: sourceFields,
|
|
432
|
+
destField: destFields,
|
|
433
|
+
destSchema: getZeroTableName(targetModel.name),
|
|
434
|
+
type: "one"
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
return relationships;
|
|
439
|
+
}
|
|
440
|
+
function mapModel(model, dmmf, config) {
|
|
441
|
+
var _a, _b;
|
|
442
|
+
const columns = {};
|
|
443
|
+
model.fields.filter((field) => !field.relationName).forEach((field) => {
|
|
444
|
+
columns[field.name] = mapPrismaTypeToZero(field);
|
|
445
|
+
});
|
|
446
|
+
const idField = (_a = model.fields.find((f) => f.isId)) == null ? void 0 : _a.name;
|
|
447
|
+
const primaryKey = ((_b = model.primaryKey) == null ? void 0 : _b.fields) || (idField ? [idField] : []);
|
|
448
|
+
if (!primaryKey[0]) {
|
|
449
|
+
throw new Error(`No primary key found for ${model.name}`);
|
|
450
|
+
}
|
|
451
|
+
const tableName = getTableNameFromModel(model);
|
|
452
|
+
const camelCasedName = (config == null ? void 0 : config.camelCase) ? toCamelCase(tableName) : tableName;
|
|
453
|
+
const shouldRemap = config.camelCase && camelCasedName !== tableName;
|
|
454
|
+
return {
|
|
455
|
+
tableName: shouldRemap ? camelCasedName : tableName,
|
|
456
|
+
originalTableName: shouldRemap ? tableName : null,
|
|
457
|
+
modelName: model.name,
|
|
458
|
+
zeroTableName: getZeroTableName(model.name),
|
|
459
|
+
columns,
|
|
460
|
+
relationships: mapRelationships(model, dmmf, config),
|
|
461
|
+
primaryKey: ensureStringArray(primaryKey)
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
function transformSchema(dmmf, config) {
|
|
465
|
+
const filteredModels = dmmf.datamodel.models.filter((model) => {
|
|
466
|
+
var _a;
|
|
467
|
+
return !((_a = config.excludeTables) == null ? void 0 : _a.includes(model.name));
|
|
468
|
+
});
|
|
469
|
+
const models = filteredModels.map((model) => mapModel(model, dmmf, config));
|
|
470
|
+
const implicitJoinTables = filteredModels.flatMap((model) => {
|
|
471
|
+
return model.fields.filter((field) => field.relationName && field.isList).map((field) => {
|
|
472
|
+
var _a;
|
|
473
|
+
const targetModel = dmmf.datamodel.models.find(
|
|
474
|
+
(m) => m.name === field.type
|
|
475
|
+
);
|
|
476
|
+
if (!targetModel) return null;
|
|
477
|
+
if ((_a = config.excludeTables) == null ? void 0 : _a.includes(targetModel.name)) return null;
|
|
478
|
+
const backReference = targetModel.fields.find(
|
|
479
|
+
(f) => f.relationName === field.relationName && f.type === model.name
|
|
480
|
+
);
|
|
481
|
+
if (backReference == null ? void 0 : backReference.isList) {
|
|
482
|
+
if (model.name.localeCompare(targetModel.name) < 0) {
|
|
483
|
+
return createImplicitManyToManyModel(
|
|
484
|
+
model,
|
|
485
|
+
targetModel,
|
|
486
|
+
field.relationName,
|
|
487
|
+
config
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return null;
|
|
492
|
+
}).filter((table) => table !== null);
|
|
493
|
+
});
|
|
494
|
+
return {
|
|
495
|
+
models: [...models, ...implicitJoinTables],
|
|
496
|
+
enums: [...dmmf.datamodel.enums]
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// src/generator.ts
|
|
501
|
+
var { generatorHandler } = import_generator_helper.default;
|
|
502
|
+
async function onGenerate(options) {
|
|
503
|
+
var _a;
|
|
504
|
+
const { generator, dmmf } = options;
|
|
505
|
+
const outputFile = "schema.ts";
|
|
506
|
+
const outputDir = (_a = generator.output) == null ? void 0 : _a.value;
|
|
507
|
+
if (!outputDir) {
|
|
508
|
+
throw new Error("Output directory is required");
|
|
509
|
+
}
|
|
510
|
+
const config = {
|
|
511
|
+
name: generator.name,
|
|
512
|
+
prettier: generator.config.prettier === "true",
|
|
513
|
+
// Default false,
|
|
514
|
+
resolvePrettierConfig: generator.config.resolvePrettierConfig !== "false",
|
|
515
|
+
// Default true
|
|
516
|
+
camelCase: generator.config.camelCase === "true",
|
|
517
|
+
// Default false
|
|
518
|
+
excludeTables: loadExcludeTables(generator)
|
|
519
|
+
};
|
|
520
|
+
const transformedSchema = transformSchema(dmmf, config);
|
|
521
|
+
let output = generateCode(transformedSchema);
|
|
522
|
+
if (config.prettier) {
|
|
523
|
+
let prettier;
|
|
524
|
+
try {
|
|
525
|
+
prettier = await import("prettier");
|
|
526
|
+
} catch {
|
|
527
|
+
throw new Error(
|
|
528
|
+
"\u26A0\uFE0F prisma-zero: prettier could not be found. Install it locally with\n npm i -D prettier"
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
const prettierOptions = config.resolvePrettierConfig ? await prettier.resolveConfig(outputFile) : null;
|
|
532
|
+
output = await prettier.format(output, {
|
|
533
|
+
...prettierOptions,
|
|
534
|
+
parser: "typescript"
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
await (0, import_promises.mkdir)(outputDir, { recursive: true });
|
|
538
|
+
await (0, import_promises.writeFile)((0, import_path.join)(outputDir, outputFile), output);
|
|
539
|
+
}
|
|
540
|
+
generatorHandler({
|
|
541
|
+
onManifest() {
|
|
542
|
+
return {
|
|
543
|
+
version,
|
|
544
|
+
defaultOutput: "generated/zero",
|
|
545
|
+
prettyName: "Zero Schema"
|
|
546
|
+
};
|
|
547
|
+
},
|
|
548
|
+
onGenerate
|
|
549
|
+
});
|
|
550
|
+
function loadExcludeTables(generator) {
|
|
551
|
+
const value = generator.config.excludeTables;
|
|
552
|
+
if (value === void 0) {
|
|
553
|
+
return [];
|
|
554
|
+
}
|
|
555
|
+
if (!Array.isArray(value)) {
|
|
556
|
+
throw new Error("excludeTables must be an array");
|
|
557
|
+
}
|
|
558
|
+
return value;
|
|
559
|
+
}
|
|
560
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
561
|
+
0 && (module.exports = {
|
|
562
|
+
onGenerate
|
|
563
|
+
});
|