@kurotako/parser-prisma 0.1.0 → 0.2.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/dist/index.js CHANGED
@@ -37,18 +37,536 @@ ${prismaMessage}`,
37
37
  this.prismaMessage = prismaMessage;
38
38
  }
39
39
  };
40
+ var PrismaContractError = class extends TakoError {
41
+ constructor(detail, options) {
42
+ super(
43
+ "prisma_contract",
44
+ `invalid Prisma 8 contract.json: ${detail}`,
45
+ options
46
+ );
47
+ }
48
+ };
49
+ var PrismaContractVersionError = class extends TakoError {
50
+ found;
51
+ constructor(found, expected) {
52
+ super(
53
+ "prisma_contract_version",
54
+ `unsupported Prisma contract schemaVersion '${found}' (expected one of: ${expected.join(", ")})`
55
+ );
56
+ this.found = found;
57
+ }
58
+ };
59
+ var PrismaDialectError = class extends TakoError {
60
+ codecId;
61
+ constructor(codecId) {
62
+ const dialect = codecId.split("/")[0] ?? codecId;
63
+ super(
64
+ "prisma_dialect",
65
+ `unsupported Prisma contract dialect '${dialect}' in codec '${codecId}'; only PostgreSQL contracts are supported currently`
66
+ );
67
+ this.codecId = codecId;
68
+ }
69
+ };
70
+ var PrismaEntityCollisionError = class extends TakoError {
71
+ entityName;
72
+ models;
73
+ constructor(entityName, models) {
74
+ super(
75
+ "prisma_entity_collision",
76
+ `Prisma contract models ${models.join(", ")} resolve to the same entity name '${entityName}'`
77
+ );
78
+ this.entityName = entityName;
79
+ this.models = models;
80
+ }
81
+ };
82
+ var PrismaAmbiguousRelationError = class extends TakoError {
83
+ constructor(modelName) {
84
+ super(
85
+ "prisma_ambiguous_relation",
86
+ `Prisma contract relation targets '${modelName}', which exists in multiple namespaces; Prisma 8 RC does not resolve this reliably`
87
+ );
88
+ }
89
+ };
40
90
 
41
91
  // src/options.ts
42
92
  import * as v from "valibot";
43
93
  var PrismaParserOptions = v.strictObject({
44
94
  schema: v.optional(v.string(), "./prisma/schema.prisma"),
45
- version: v.optional(v.picklist([7, 8]))
95
+ version: v.optional(v.picklist([7, 8])),
96
+ namespacePrefix: v.optional(v.record(v.string(), v.string())),
97
+ rename: v.optional(v.record(v.string(), v.string()))
46
98
  });
47
99
 
48
100
  // src/parser.ts
101
+ import { readFile as readFile3 } from "fs/promises";
49
102
  import { dirname as dirname2, resolve as resolve2 } from "path";
50
103
  import { defineParser } from "@kurotako/config";
51
104
 
105
+ // src/contract/codecs.ts
106
+ var CODECS = {
107
+ "pg/text": { scalar: "string" },
108
+ "pg/text-array": { scalar: "string" },
109
+ "pg/varchar": { scalar: "string", needsLength: true },
110
+ "sql/varchar": { scalar: "string", needsLength: true },
111
+ "pg/char": { scalar: "string" },
112
+ "pg/bpchar": { scalar: "string" },
113
+ "pg/bool": { scalar: "boolean" },
114
+ "pg/int": { scalar: "int" },
115
+ "pg/int2": { scalar: "int" },
116
+ "pg/int4": { scalar: "int" },
117
+ "pg/int8": { scalar: "bigint" },
118
+ "pg/int8number": { scalar: "int" },
119
+ "pg/unboundedint": { scalar: "bigint" },
120
+ "pg/float": { scalar: "float" },
121
+ "pg/float4": { scalar: "float" },
122
+ "pg/float8": { scalar: "float" },
123
+ "pg/numeric": { scalar: "decimal" },
124
+ "pg/uuid": { scalar: "uuid" },
125
+ "pg/timestamp-string": { scalar: "datetime" },
126
+ "pg/timestamp-temporal": { scalar: "datetime" },
127
+ "pg/timestamptz-string": { scalar: "datetime" },
128
+ "pg/timestamptz-temporal": { scalar: "datetime" },
129
+ "pg/date-string": { scalar: "date" },
130
+ "pg/date-temporal": { scalar: "date" },
131
+ "pg/time-string": { scalar: "datetime", format: "time" },
132
+ "pg/time-temporal": { scalar: "datetime", format: "time" },
133
+ "pg/timetz": { scalar: "datetime", format: "time" },
134
+ "pg/json": { scalar: "json" },
135
+ "pg/jsonb": { scalar: "json" },
136
+ "pg/bytea": { scalar: "bytes" }
137
+ };
138
+ function splitCodec(codecId) {
139
+ const at = codecId.lastIndexOf("@");
140
+ return at === -1 ? { name: codecId } : { name: codecId.slice(0, at), version: codecId.slice(at + 1) };
141
+ }
142
+ function mapCodec(codecId, logger) {
143
+ const { name, version } = splitCodec(codecId);
144
+ if (version !== void 0) {
145
+ logger?.debug(`prisma parser: contract codec '${name}' version ${version}`);
146
+ }
147
+ const entry = CODECS[name];
148
+ if (entry) {
149
+ return {
150
+ type: { kind: "scalar", scalar: entry.scalar },
151
+ ...entry.format !== void 0 ? { format: entry.format } : {},
152
+ ...entry.needsLength ? { needsLength: true } : {}
153
+ };
154
+ }
155
+ if (!name.startsWith("pg/") && !name.startsWith("sql/")) {
156
+ throw new PrismaDialectError(codecId);
157
+ }
158
+ logger?.debug(`prisma parser: unknown contract codec '${codecId}'`);
159
+ return { type: { kind: "unknown", hint: codecId } };
160
+ }
161
+
162
+ // src/contract/naming.ts
163
+ function resolveNames(models, options) {
164
+ const names = /* @__PURE__ */ new Map();
165
+ const collisions = /* @__PURE__ */ new Map();
166
+ for (const { namespace, name } of models) {
167
+ const key = `${namespace}.${name}`;
168
+ const target = options.rename?.[key] ?? `${options.namespacePrefix?.[namespace] ?? ""}${name}`;
169
+ names.set(key, target);
170
+ const entries = collisions.get(target) ?? [];
171
+ entries.push(key);
172
+ collisions.set(target, entries);
173
+ }
174
+ for (const [target, modelsForTarget] of collisions) {
175
+ if (modelsForTarget.length > 1) {
176
+ throw new PrismaEntityCollisionError(target, modelsForTarget);
177
+ }
178
+ }
179
+ return names;
180
+ }
181
+
182
+ // src/contract/schema.ts
183
+ import * as v2 from "valibot";
184
+ var scalarType = v2.looseObject({
185
+ kind: v2.literal("scalar"),
186
+ codecId: v2.string(),
187
+ typeParams: v2.optional(v2.looseObject({ length: v2.optional(v2.number()) }))
188
+ });
189
+ var valueObjectType = v2.looseObject({
190
+ kind: v2.literal("valueObject"),
191
+ name: v2.string()
192
+ });
193
+ var field = v2.looseObject({
194
+ nullable: v2.boolean(),
195
+ many: v2.optional(v2.boolean()),
196
+ type: v2.union([scalarType, valueObjectType]),
197
+ valueSet: v2.optional(v2.looseObject({ entityName: v2.string() }))
198
+ });
199
+ var relation = v2.looseObject({
200
+ cardinality: v2.picklist(["1:1", "1:N", "N:1", "N:M"]),
201
+ to: v2.looseObject({ namespace: v2.string(), model: v2.string() }),
202
+ on: v2.looseObject({
203
+ localFields: v2.array(v2.string()),
204
+ targetFields: v2.array(v2.string())
205
+ })
206
+ });
207
+ var model = v2.looseObject({
208
+ fields: v2.record(v2.string(), field),
209
+ relations: v2.optional(v2.record(v2.string(), relation)),
210
+ storage: v2.looseObject({
211
+ table: v2.string(),
212
+ namespaceId: v2.string(),
213
+ fields: v2.record(v2.string(), v2.looseObject({ column: v2.string() }))
214
+ })
215
+ });
216
+ var enumDef = v2.looseObject({
217
+ members: v2.array(v2.looseObject({ name: v2.string(), value: v2.string() }))
218
+ });
219
+ var column = v2.looseObject({
220
+ codecId: v2.string(),
221
+ nullable: v2.boolean(),
222
+ many: v2.optional(v2.boolean()),
223
+ default: v2.optional(
224
+ v2.looseObject({
225
+ kind: v2.picklist(["function", "literal"]),
226
+ expression: v2.optional(v2.string()),
227
+ value: v2.optional(
228
+ v2.union([
229
+ v2.string(),
230
+ v2.number(),
231
+ v2.boolean(),
232
+ v2.array(v2.union([v2.string(), v2.number(), v2.boolean()]))
233
+ ])
234
+ )
235
+ })
236
+ )
237
+ });
238
+ var table = v2.looseObject({
239
+ columns: v2.record(v2.string(), column),
240
+ primaryKey: v2.optional(v2.looseObject({ columns: v2.array(v2.string()) })),
241
+ uniques: v2.optional(
242
+ v2.array(
243
+ v2.looseObject({
244
+ columns: v2.array(v2.string()),
245
+ name: v2.optional(v2.string())
246
+ })
247
+ )
248
+ ),
249
+ indexes: v2.optional(
250
+ v2.array(
251
+ v2.looseObject({
252
+ columns: v2.array(v2.string()),
253
+ name: v2.optional(v2.string()),
254
+ type: v2.optional(v2.string())
255
+ })
256
+ )
257
+ ),
258
+ foreignKeys: v2.optional(
259
+ v2.array(
260
+ v2.looseObject({
261
+ source: v2.looseObject({ columns: v2.array(v2.string()) }),
262
+ onDelete: v2.optional(v2.string()),
263
+ onUpdate: v2.optional(v2.string())
264
+ })
265
+ )
266
+ )
267
+ });
268
+ var ContractSchema = v2.looseObject({
269
+ schemaVersion: v2.string(),
270
+ target: v2.string(),
271
+ targetFamily: v2.string(),
272
+ domain: v2.looseObject({
273
+ namespaces: v2.record(
274
+ v2.string(),
275
+ v2.looseObject({
276
+ models: v2.record(v2.string(), model),
277
+ enum: v2.optional(v2.record(v2.string(), enumDef))
278
+ })
279
+ )
280
+ }),
281
+ storage: v2.looseObject({
282
+ namespaces: v2.record(
283
+ v2.string(),
284
+ v2.looseObject({
285
+ entries: v2.looseObject({
286
+ table: v2.optional(v2.record(v2.string(), table)),
287
+ valueSet: v2.optional(
288
+ v2.record(
289
+ v2.string(),
290
+ v2.looseObject({ values: v2.array(v2.string()) })
291
+ )
292
+ )
293
+ })
294
+ })
295
+ )
296
+ }),
297
+ execution: v2.optional(
298
+ v2.looseObject({
299
+ mutations: v2.optional(
300
+ v2.looseObject({
301
+ defaults: v2.optional(
302
+ v2.array(
303
+ v2.looseObject({
304
+ ref: v2.looseObject({
305
+ namespace: v2.string(),
306
+ table: v2.string(),
307
+ column: v2.string()
308
+ }),
309
+ onCreate: v2.optional(
310
+ v2.looseObject({ kind: v2.string(), id: v2.string() })
311
+ ),
312
+ onUpdate: v2.optional(
313
+ v2.looseObject({ kind: v2.string(), id: v2.string() })
314
+ )
315
+ })
316
+ )
317
+ )
318
+ })
319
+ )
320
+ })
321
+ )
322
+ });
323
+ function issuePath(err) {
324
+ if (err instanceof v2.ValiError) {
325
+ return err.issues.map(
326
+ (issue) => issue.path?.map((part) => String(part.key)).join(".") ?? "<root>"
327
+ ).join(", ");
328
+ }
329
+ return "<root>";
330
+ }
331
+ function parseContract(raw) {
332
+ let value;
333
+ try {
334
+ value = JSON.parse(raw);
335
+ } catch (err) {
336
+ throw new PrismaContractError("invalid JSON", { cause: err });
337
+ }
338
+ try {
339
+ return v2.parse(ContractSchema, value);
340
+ } catch (err) {
341
+ throw new PrismaContractError(`invalid structure at ${issuePath(err)}`, {
342
+ cause: err
343
+ });
344
+ }
345
+ }
346
+
347
+ // src/contract/version.ts
348
+ var SUPPORTED_SCHEMA_VERSIONS = /* @__PURE__ */ new Set(["1"]);
349
+ function assertSupportedVersion(found) {
350
+ if (!SUPPORTED_SCHEMA_VERSIONS.has(found)) {
351
+ throw new PrismaContractVersionError(found, [...SUPPORTED_SCHEMA_VERSIONS]);
352
+ }
353
+ }
354
+
355
+ // src/contract/read.ts
356
+ function record3(value) {
357
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
358
+ }
359
+ function strings(value) {
360
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
361
+ }
362
+ function storageTable(contract, namespace, tableName) {
363
+ const namespaces = record3(record3(contract.storage).namespaces);
364
+ const entries = record3(record3(namespaces[namespace]).entries);
365
+ return record3(record3(entries.table)[tableName]);
366
+ }
367
+ function defaultValue(value) {
368
+ const raw = record3(value);
369
+ if (raw.kind === "literal") {
370
+ return raw.value;
371
+ }
372
+ if (raw.kind === "function" && typeof raw.expression === "string") {
373
+ const expression = raw.expression;
374
+ const match = /^(\\w+)\\((.*)\\)$/.exec(expression);
375
+ return match ? { name: match[1] ?? expression, args: [] } : { name: expression, args: [] };
376
+ }
377
+ return void 0;
378
+ }
379
+ function generatorDefault(contract, namespace, table2, column2) {
380
+ const defaults = record3(
381
+ record3(record3(contract.execution).mutations).defaults
382
+ );
383
+ if (!Array.isArray(defaults)) return void 0;
384
+ return defaults.map(record3).find((entry) => {
385
+ const ref = record3(entry.ref);
386
+ return ref.namespace === namespace && ref.table === table2 && ref.column === column2;
387
+ });
388
+ }
389
+ function readField(name, raw, storageColumn, generator, logger) {
390
+ const type = record3(raw.type);
391
+ if (type.kind === "valueObject") {
392
+ return {
393
+ name,
394
+ type: typeof type.name === "string" ? type.name : "valueObject",
395
+ kind: "unsupported",
396
+ isList: raw.many === true,
397
+ isRequired: raw.nullable !== true,
398
+ isUnique: false,
399
+ isUpdatedAt: false,
400
+ hasDefaultValue: generator !== void 0 || storageColumn.default !== void 0,
401
+ nativeType: null
402
+ };
403
+ }
404
+ const codecId = String(type.codecId);
405
+ const mapped = mapCodec(codecId, logger);
406
+ const valueSet = record3(raw.valueSet);
407
+ const isEnum = typeof valueSet.entityName === "string";
408
+ const typeParams = record3(type.typeParams);
409
+ const maxLength = mapped.needsLength && typeof typeParams.length === "number" ? typeParams.length : void 0;
410
+ const field2 = {
411
+ name,
412
+ type: isEnum ? String(valueSet.entityName) : codecId,
413
+ kind: isEnum ? "enum" : "scalar",
414
+ isList: raw.many === true,
415
+ isRequired: raw.nullable !== true,
416
+ isUnique: false,
417
+ isUpdatedAt: record3(generator?.onUpdate).id === "instantNow",
418
+ hasDefaultValue: generator !== void 0 || storageColumn.default !== void 0,
419
+ nativeType: null
420
+ };
421
+ if (isEnum) return field2;
422
+ field2.mappedType = mapped.type;
423
+ field2.scalarOverride = mapped.scalarOverride;
424
+ field2.format = mapped.format;
425
+ field2.maxLength = maxLength;
426
+ const parsedDefault = defaultValue(storageColumn.default);
427
+ if (parsedDefault !== void 0) field2.default = parsedDefault;
428
+ return field2;
429
+ }
430
+ function readRelationEdges(relations, names, sourceName, table2) {
431
+ const foreignKeys = Array.isArray(table2.foreignKeys) ? table2.foreignKeys.map(record3) : [];
432
+ return Object.entries(relations).map(([fieldName, relation2]) => {
433
+ const raw = record3(relation2);
434
+ const to = record3(raw.to);
435
+ const on = record3(raw.on);
436
+ const localFields = strings(on.localFields);
437
+ const targetFields = strings(on.targetFields);
438
+ const fk = foreignKeys.find((candidate) => {
439
+ const source = record3(candidate.source);
440
+ return JSON.stringify(strings(source.columns)) === JSON.stringify(localFields);
441
+ });
442
+ const targetKey = `${String(to.namespace)}.${String(to.model)}`;
443
+ const cardinality = raw.cardinality;
444
+ const edge = {
445
+ fieldName,
446
+ relationName: [sourceName, String(to.model)].sort().join(":") + `:${[...localFields, ...targetFields].sort().join(",")}`,
447
+ targetEntity: names.get(targetKey) ?? String(to.model),
448
+ isList: cardinality === "1:N" || cardinality === "N:M",
449
+ isRequired: cardinality !== "1:N" && cardinality !== "N:M",
450
+ fromFields: fk ? localFields : [],
451
+ toFields: fk ? targetFields : []
452
+ };
453
+ if (typeof fk?.onDelete === "string") edge.onDelete = fk.onDelete;
454
+ if (typeof fk?.onUpdate === "string") edge.onUpdate = fk.onUpdate;
455
+ return edge;
456
+ });
457
+ }
458
+ function readContract(raw, ctx, options) {
459
+ const parsed = parseContract(raw);
460
+ assertSupportedVersion(parsed.schemaVersion);
461
+ const contract = parsed;
462
+ const namespaces = record3(record3(contract.domain).namespaces);
463
+ const models = Object.entries(namespaces).flatMap(
464
+ ([namespace, rawNamespace]) => Object.keys(record3(record3(rawNamespace).models)).map((name) => ({
465
+ namespace,
466
+ name
467
+ }))
468
+ );
469
+ const modelCounts = /* @__PURE__ */ new Map();
470
+ for (const model2 of models) {
471
+ modelCounts.set(model2.name, (modelCounts.get(model2.name) ?? 0) + 1);
472
+ }
473
+ for (const rawNamespace of Object.values(namespaces)) {
474
+ for (const rawModel of Object.values(record3(record3(rawNamespace).models))) {
475
+ for (const relation2 of Object.values(
476
+ record3(record3(rawModel).relations)
477
+ )) {
478
+ const target = record3(record3(relation2).to);
479
+ if (typeof target.model === "string" && (modelCounts.get(target.model) ?? 0) > 1) {
480
+ throw new PrismaAmbiguousRelationError(target.model);
481
+ }
482
+ }
483
+ }
484
+ }
485
+ const names = resolveNames(models, options);
486
+ const entities = [];
487
+ const enums = [];
488
+ for (const [namespace, rawNamespace] of Object.entries(namespaces)) {
489
+ const namespaceData = record3(rawNamespace);
490
+ const modelDefs = record3(namespaceData.models);
491
+ for (const [sourceName, rawModel] of Object.entries(modelDefs)) {
492
+ const model2 = record3(rawModel);
493
+ const bridge = record3(model2.storage);
494
+ const tableName = String(bridge.table);
495
+ const table2 = storageTable(
496
+ contract,
497
+ String(bridge.namespaceId),
498
+ tableName
499
+ );
500
+ const columns = record3(table2.columns);
501
+ const bridgeFields = record3(bridge.fields);
502
+ const fields = Object.entries(record3(model2.fields)).map(
503
+ ([name, rawField]) => {
504
+ const column2 = String(record3(bridgeFields[name]).column);
505
+ return readField(
506
+ name,
507
+ record3(rawField),
508
+ record3(columns[column2]),
509
+ generatorDefault(
510
+ contract,
511
+ String(bridge.namespaceId),
512
+ tableName,
513
+ column2
514
+ ),
515
+ ctx.logger
516
+ );
517
+ }
518
+ );
519
+ const uniqueColumns = new Set(
520
+ (Array.isArray(table2.uniques) ? table2.uniques : []).flatMap(
521
+ (entry) => strings(record3(entry).columns)
522
+ )
523
+ );
524
+ for (const field2 of fields)
525
+ field2.isUnique = uniqueColumns.has(field2.name);
526
+ const entity = {
527
+ name: names.get(`${namespace}.${sourceName}`) ?? sourceName,
528
+ dbName: tableName === sourceName ? void 0 : tableName,
529
+ fields,
530
+ relationEdges: readRelationEdges(
531
+ record3(model2.relations),
532
+ names,
533
+ sourceName,
534
+ table2
535
+ ),
536
+ primaryKey: strings(record3(table2.primaryKey).columns),
537
+ uniques: (Array.isArray(table2.uniques) ? table2.uniques : []).map(
538
+ (entry) => ({
539
+ fields: strings(record3(entry).columns),
540
+ ...typeof record3(entry).name === "string" ? { name: String(record3(entry).name) } : {}
541
+ })
542
+ ),
543
+ indexes: (Array.isArray(table2.indexes) ? table2.indexes : []).map(
544
+ (entry) => ({
545
+ fields: strings(record3(entry).columns),
546
+ ...typeof record3(entry).name === "string" ? { name: String(record3(entry).name) } : {},
547
+ ...typeof record3(entry).type === "string" ? { type: String(record3(entry).type) } : {}
548
+ })
549
+ )
550
+ };
551
+ entities.push(entity);
552
+ }
553
+ for (const [name, rawEnum] of Object.entries(record3(namespaceData.enum))) {
554
+ const members = Array.isArray(record3(rawEnum).members) ? record3(rawEnum).members : [];
555
+ enums.push({
556
+ name,
557
+ values: members.map((member) => {
558
+ const value = record3(member);
559
+ return {
560
+ name: String(value.name),
561
+ ...String(value.value) !== String(value.name) ? { dbName: String(value.value) } : {}
562
+ };
563
+ })
564
+ });
565
+ }
566
+ }
567
+ return { model: { entities, enums }, generatorVersion: parsed.schemaVersion };
568
+ }
569
+
52
570
  // src/detect.ts
53
571
  import { readdir, readFile, stat } from "fs/promises";
54
572
  import { basename, dirname, join, relative, resolve, sep } from "path";
@@ -174,8 +692,8 @@ import { join as join2 } from "path";
174
692
  import { pathToFileURL } from "url";
175
693
 
176
694
  // src/dmmf/read.ts
177
- function readField(f) {
178
- const field = {
695
+ function readField2(f) {
696
+ const field2 = {
179
697
  name: f.name,
180
698
  type: f.type,
181
699
  kind: f.kind === "enum" ? "enum" : f.kind === "unsupported" ? "unsupported" : "scalar",
@@ -187,12 +705,12 @@ function readField(f) {
187
705
  nativeType: f.nativeType ? [f.nativeType[0], [...f.nativeType[1]]] : null
188
706
  };
189
707
  if (f.default !== void 0) {
190
- field.default = f.default;
708
+ field2.default = f.default;
191
709
  }
192
710
  if (f.documentation !== void 0) {
193
- field.doc = f.documentation;
711
+ field2.doc = f.documentation;
194
712
  }
195
- return field;
713
+ return field2;
196
714
  }
197
715
  function readEdge(f) {
198
716
  const edge = {
@@ -212,16 +730,16 @@ function readEdge(f) {
212
730
  }
213
731
  return edge;
214
732
  }
215
- function readPrimaryKey(model) {
216
- if (model.primaryKey && model.primaryKey.fields.length > 0) {
217
- return [...model.primaryKey.fields];
733
+ function readPrimaryKey(model2) {
734
+ if (model2.primaryKey && model2.primaryKey.fields.length > 0) {
735
+ return [...model2.primaryKey.fields];
218
736
  }
219
- const id = model.fields.find((f) => f.isId);
737
+ const id = model2.fields.find((f) => f.isId);
220
738
  return id ? [id.name] : [];
221
739
  }
222
- function readUniques(model) {
223
- if (model.uniqueIndexes.length > 0) {
224
- return model.uniqueIndexes.map((u) => {
740
+ function readUniques(model2) {
741
+ if (model2.uniqueIndexes.length > 0) {
742
+ return model2.uniqueIndexes.map((u) => {
225
743
  const entry = { fields: [...u.fields] };
226
744
  if (u.name) {
227
745
  entry.name = u.name;
@@ -229,7 +747,7 @@ function readUniques(model) {
229
747
  return entry;
230
748
  });
231
749
  }
232
- return model.uniqueFields.map((fields) => ({ fields: [...fields] }));
750
+ return model2.uniqueFields.map((fields) => ({ fields: [...fields] }));
233
751
  }
234
752
  function readIndexes(modelName, all) {
235
753
  if (!all) {
@@ -246,29 +764,29 @@ function readIndexes(modelName, all) {
246
764
  return entry;
247
765
  });
248
766
  }
249
- function readEntity(model, doc) {
767
+ function readEntity(model2, doc) {
250
768
  const fields = [];
251
769
  const relationEdges = [];
252
- for (const f of model.fields) {
770
+ for (const f of model2.fields) {
253
771
  if (f.kind === "object") {
254
772
  relationEdges.push(readEdge(f));
255
773
  } else {
256
- fields.push(readField(f));
774
+ fields.push(readField2(f));
257
775
  }
258
776
  }
259
777
  const entity = {
260
- name: model.name,
778
+ name: model2.name,
261
779
  fields,
262
780
  relationEdges,
263
- primaryKey: readPrimaryKey(model),
264
- uniques: readUniques(model),
265
- indexes: readIndexes(model.name, doc.datamodel.indexes)
781
+ primaryKey: readPrimaryKey(model2),
782
+ uniques: readUniques(model2),
783
+ indexes: readIndexes(model2.name, doc.datamodel.indexes)
266
784
  };
267
- if (model.dbName) {
268
- entity.dbName = model.dbName;
785
+ if (model2.dbName) {
786
+ entity.dbName = model2.dbName;
269
787
  }
270
- if (model.documentation !== void 0) {
271
- entity.doc = model.documentation;
788
+ if (model2.documentation !== void 0) {
789
+ entity.doc = model2.documentation;
272
790
  }
273
791
  return entity;
274
792
  }
@@ -291,11 +809,27 @@ function readEnum(e) {
291
809
  }
292
810
  return def;
293
811
  }
294
- function toPrismaModel(doc) {
295
- return {
812
+ function toPrismaModel(doc, options) {
813
+ const result = {
296
814
  entities: doc.datamodel.models.map((m) => readEntity(m, doc)),
297
815
  enums: doc.datamodel.enums.map(readEnum)
298
816
  };
817
+ if (!options?.rename) {
818
+ return result;
819
+ }
820
+ const names = new Map(
821
+ result.entities.map((entity) => [
822
+ entity.name,
823
+ options.rename?.[entity.name] ?? entity.name
824
+ ])
825
+ );
826
+ for (const entity of result.entities) {
827
+ entity.name = names.get(entity.name) ?? entity.name;
828
+ for (const edge of entity.relationEdges) {
829
+ edge.targetEntity = names.get(edge.targetEntity) ?? edge.targetEntity;
830
+ }
831
+ }
832
+ return result;
299
833
  }
300
834
 
301
835
  // src/dmmf/load.ts
@@ -334,7 +868,7 @@ async function resolveInternals(ctx) {
334
868
  }
335
869
  return { getDMMF, prismaVersion };
336
870
  }
337
- async function readDmmf(input, ctx) {
871
+ async function readDmmf(input, ctx, options) {
338
872
  const { getDMMF, prismaVersion } = await resolveInternals(ctx);
339
873
  const datamodel = input.kind === "file" ? input.files[0]?.[1] ?? "" : input.files.map(([path, content]) => [path, content]);
340
874
  let doc;
@@ -344,7 +878,7 @@ async function readDmmf(input, ctx) {
344
878
  const message = err instanceof Error ? err.message : String(err);
345
879
  throw new PrismaSchemaError(ctx.namespace, message, { cause: err });
346
880
  }
347
- return { model: toPrismaModel(doc), prismaVersion };
881
+ return { model: toPrismaModel(doc, options), prismaVersion };
348
882
  }
349
883
 
350
884
  // src/map/build.ts
@@ -420,7 +954,7 @@ var NOOP_NATIVE = /* @__PURE__ */ new Set([
420
954
  "DateTime2",
421
955
  "DateTimeOffset"
422
956
  ]);
423
- function refineNative(native, constraints, result, field, logger) {
957
+ function refineNative(native, constraints, result, field2, logger) {
424
958
  const [name, args] = native;
425
959
  if (LENGTH_NATIVE.has(name)) {
426
960
  const n = Number(args[0]);
@@ -445,27 +979,27 @@ function refineNative(native, constraints, result, field, logger) {
445
979
  return;
446
980
  }
447
981
  logger?.debug(`prisma parser: ignoring unmapped native type @db.${name}`, {
448
- field: field.name
982
+ field: field2.name
449
983
  });
450
984
  }
451
- function mapFieldType(field, logger) {
985
+ function mapFieldType(field2, logger) {
452
986
  const constraints = {};
453
- if (field.kind === "unsupported") {
454
- return { type: { kind: "unknown", hint: field.type }, constraints };
987
+ if (field2.kind === "unsupported") {
988
+ return { type: { kind: "unknown", hint: field2.type }, constraints };
455
989
  }
456
- if (field.kind === "enum") {
457
- return { type: { kind: "enum", ref: field.type }, constraints };
990
+ if (field2.kind === "enum") {
991
+ return { type: { kind: "enum", ref: field2.type }, constraints };
458
992
  }
459
- const scalar = SCALAR_TABLE[field.type];
993
+ const scalar = SCALAR_TABLE[field2.type];
460
994
  if (scalar === void 0) {
461
- return { type: { kind: "unknown", hint: field.type }, constraints };
995
+ return { type: { kind: "unknown", hint: field2.type }, constraints };
462
996
  }
463
997
  const result = {
464
998
  type: { kind: "scalar", scalar },
465
999
  constraints
466
1000
  };
467
- if (field.nativeType) {
468
- refineNative(field.nativeType, constraints, result, field, logger);
1001
+ if (field2.nativeType) {
1002
+ refineNative(field2.nativeType, constraints, result, field2, logger);
469
1003
  }
470
1004
  return result;
471
1005
  }
@@ -493,9 +1027,9 @@ function pkScalar(entities, entityName, logger) {
493
1027
  const entity = entities.get(entityName);
494
1028
  if (entity && entity.primaryKey.length === 1) {
495
1029
  const pkName = entity.primaryKey[0];
496
- const field = entity.fields.find((f) => f.name === pkName);
497
- if (field) {
498
- const mapped = mapFieldType(field);
1030
+ const field2 = entity.fields.find((f) => f.name === pkName);
1031
+ if (field2) {
1032
+ const mapped = mapFieldType(field2);
499
1033
  if (mapped.scalarOverride) {
500
1034
  return mapped.scalarOverride;
501
1035
  }
@@ -511,7 +1045,7 @@ function pkScalar(entities, entityName, logger) {
511
1045
  }
512
1046
  function normalRelation(edge, back) {
513
1047
  const owning = edge.fromFields.length > 0;
514
- const relation = {
1048
+ const relation2 = {
515
1049
  name: edge.fieldName,
516
1050
  target: { namespace: "", entity: edge.targetEntity },
517
1051
  cardinality: edge.isList ? "many" : "one",
@@ -519,21 +1053,21 @@ function normalRelation(edge, back) {
519
1053
  owning
520
1054
  };
521
1055
  if (owning) {
522
- relation.fkFields = [...edge.fromFields];
523
- relation.references = [...edge.toFields];
1056
+ relation2.fkFields = [...edge.fromFields];
1057
+ relation2.references = [...edge.toFields];
524
1058
  }
525
1059
  if (back) {
526
- relation.backRelation = back.fieldName;
1060
+ relation2.backRelation = back.fieldName;
527
1061
  }
528
1062
  const onDelete = mapAction(edge.onDelete);
529
1063
  if (onDelete) {
530
- relation.onDelete = onDelete;
1064
+ relation2.onDelete = onDelete;
531
1065
  }
532
1066
  const onUpdate = mapAction(edge.onUpdate);
533
1067
  if (onUpdate) {
534
- relation.onUpdate = onUpdate;
1068
+ relation2.onUpdate = onUpdate;
535
1069
  }
536
- return relation;
1070
+ return relation2;
537
1071
  }
538
1072
  function materialiseM2M(a, b, relationName, entities, logger) {
539
1073
  const sorted = [a.owner, b.owner].sort(
@@ -598,17 +1132,17 @@ function materialiseM2M(a, b, relationName, entities, logger) {
598
1132
  ]
599
1133
  };
600
1134
  }
601
- function buildRelations(model, logger) {
602
- const entities = new Map(model.entities.map((e) => [e.name, e]));
1135
+ function buildRelations(model2, logger) {
1136
+ const entities = new Map(model2.entities.map((e) => [e.name, e]));
603
1137
  const relations = /* @__PURE__ */ new Map();
604
1138
  const syntheticEntities = [];
605
- const push = (owner, relation) => {
1139
+ const push = (owner, relation2) => {
606
1140
  const list = relations.get(owner) ?? [];
607
- list.push(relation);
1141
+ list.push(relation2);
608
1142
  relations.set(owner, list);
609
1143
  };
610
1144
  const groups = /* @__PURE__ */ new Map();
611
- for (const entity of model.entities) {
1145
+ for (const entity of model2.entities) {
612
1146
  for (const edge of entity.relationEdges) {
613
1147
  const list = groups.get(edge.relationName) ?? [];
614
1148
  list.push({ owner: entity.name, edge });
@@ -626,8 +1160,8 @@ function buildRelations(model, logger) {
626
1160
  logger
627
1161
  );
628
1162
  syntheticEntities.push(synthetic);
629
- for (const { owner, relation } of rewrites) {
630
- push(owner, relation);
1163
+ for (const { owner, relation: relation2 } of rewrites) {
1164
+ push(owner, relation2);
631
1165
  }
632
1166
  continue;
633
1167
  }
@@ -700,17 +1234,24 @@ function addRelation(eb, rel, namespace) {
700
1234
  }
701
1235
  });
702
1236
  }
703
- function buildSourceIR(namespace, model, parserVersion, logger) {
1237
+ function buildSourceIR(namespace, model2, parserVersion, logger) {
704
1238
  const b = createSourceIR({ namespace, parser: "prisma", parserVersion });
705
- for (const e of model.enums) {
1239
+ for (const e of model2.enums) {
706
1240
  b.addEnum(e.name, (eb) => fillEnum(eb, e));
707
1241
  }
708
- const { relations, syntheticEntities } = buildRelations(model, logger);
709
- for (const entity of model.entities) {
1242
+ const { relations, syntheticEntities } = buildRelations(model2, logger);
1243
+ for (const entity of model2.entities) {
710
1244
  b.addEntity(entity.name, (eb) => {
711
- for (const field of entity.fields) {
712
- eb.field(field.name, (fb) => {
713
- const mapped = mapFieldType(field, logger);
1245
+ for (const field2 of entity.fields) {
1246
+ eb.field(field2.name, (fb) => {
1247
+ const mapped = field2.mappedType ? {
1248
+ type: field2.mappedType,
1249
+ constraints: {
1250
+ ...field2.maxLength !== void 0 ? { maxLength: field2.maxLength } : {},
1251
+ ...field2.format !== void 0 ? { format: field2.format } : {}
1252
+ },
1253
+ scalarOverride: field2.scalarOverride
1254
+ } : mapFieldType(field2, logger);
714
1255
  const scalar = mapped.scalarOverride ?? (mapped.type.kind === "scalar" ? mapped.type.scalar : void 0);
715
1256
  if (scalar !== void 0) {
716
1257
  fb.scalar(scalar);
@@ -726,7 +1267,7 @@ function buildSourceIR(namespace, model, parserVersion, logger) {
726
1267
  if (maxLength !== void 0) {
727
1268
  fb.maxLength(maxLength);
728
1269
  }
729
- const mappedDefault = mapDefault(field.default);
1270
+ const mappedDefault = mapDefault(field2.default);
730
1271
  if (mappedDefault.default) {
731
1272
  fb.default(mappedDefault.default);
732
1273
  }
@@ -736,24 +1277,24 @@ function buildSourceIR(namespace, model, parserVersion, logger) {
736
1277
  fb.format(format);
737
1278
  } else {
738
1279
  logger?.debug(
739
- `prisma parser: dropping format '${format}' on non-string field '${entity.name}.${field.name}'`
1280
+ `prisma parser: dropping format '${format}' on non-string field '${entity.name}.${field2.name}'`
740
1281
  );
741
1282
  }
742
1283
  }
743
- if (field.isList) {
1284
+ if (field2.isList) {
744
1285
  fb.list();
745
1286
  }
746
- if (!field.isRequired) {
1287
+ if (!field2.isRequired) {
747
1288
  fb.nullable();
748
1289
  }
749
- if (field.hasDefaultValue || field.isUpdatedAt) {
1290
+ if (field2.hasDefaultValue || field2.isUpdatedAt) {
750
1291
  fb.optional();
751
1292
  }
752
- if (field.isUnique) {
1293
+ if (field2.isUnique) {
753
1294
  fb.unique();
754
1295
  }
755
- if (field.doc !== void 0) {
756
- fb.doc(field.doc);
1296
+ if (field2.doc !== void 0) {
1297
+ fb.doc(field2.doc);
757
1298
  }
758
1299
  });
759
1300
  }
@@ -790,8 +1331,8 @@ function buildSourceIR(namespace, model, parserVersion, logger) {
790
1331
  }
791
1332
  for (const synthetic of syntheticEntities) {
792
1333
  b.addEntity(synthetic.name, (eb) => {
793
- for (const field of synthetic.fields) {
794
- eb.field(field.name, (fb) => fb.scalar(field.scalar));
1334
+ for (const field2 of synthetic.fields) {
1335
+ eb.field(field2.name, (fb) => fb.scalar(field2.scalar));
795
1336
  }
796
1337
  eb.primaryKey(...synthetic.primaryKey);
797
1338
  for (const rel of synthetic.relations) {
@@ -809,16 +1350,24 @@ var prismaParser = defineParser({
809
1350
  async parse(ctx, options) {
810
1351
  const input = await resolveInput(ctx.cwd, options, ctx.namespace);
811
1352
  if (input.mode === 8) {
812
- throw new PrismaInputError(
1353
+ const raw = await readFile3(input.contractPath, "utf8");
1354
+ const { model: model3, generatorVersion } = readContract(raw, ctx, options);
1355
+ return buildSourceIR(
813
1356
  ctx.namespace,
814
- input.contractPath,
815
- "the Prisma 8 contract.json mode is not implemented in kurotako v1"
1357
+ model3,
1358
+ `prisma-contract@${generatorVersion}`,
1359
+ ctx.logger
1360
+ );
1361
+ }
1362
+ if (options.namespacePrefix) {
1363
+ ctx.logger.warn(
1364
+ "prisma parser: namespacePrefix is ignored in Prisma 7 mode"
816
1365
  );
817
1366
  }
818
- const { model, prismaVersion } = await readDmmf(input, ctx);
1367
+ const { model: model2, prismaVersion } = await readDmmf(input, ctx, options);
819
1368
  return buildSourceIR(
820
1369
  ctx.namespace,
821
- model,
1370
+ model2,
822
1371
  `prisma@${prismaVersion}`,
823
1372
  ctx.logger
824
1373
  );
@@ -831,6 +1380,11 @@ var prismaParser = defineParser({
831
1380
  }
832
1381
  });
833
1382
  export {
1383
+ PrismaAmbiguousRelationError,
1384
+ PrismaContractError,
1385
+ PrismaContractVersionError,
1386
+ PrismaDialectError,
1387
+ PrismaEntityCollisionError,
834
1388
  PrismaInputError,
835
1389
  PrismaParserOptions,
836
1390
  PrismaPeerMissingError,