@farming-labs/orm 0.0.8 → 0.0.10
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.cjs +332 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -2
- package/dist/index.d.ts +38 -2
- package/dist/index.js +326 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -32,12 +32,17 @@ __export(index_exports, {
|
|
|
32
32
|
hasOne: () => hasOne,
|
|
33
33
|
id: () => id,
|
|
34
34
|
manyToMany: () => manyToMany,
|
|
35
|
+
mergeUniqueLookupCreateData: () => mergeUniqueLookupCreateData,
|
|
35
36
|
model: () => model,
|
|
36
37
|
renderDrizzleSchema: () => renderDrizzleSchema,
|
|
37
38
|
renderPrismaSchema: () => renderPrismaSchema,
|
|
38
39
|
renderSafeSql: () => renderSafeSql,
|
|
39
40
|
replaceGeneratedBlock: () => replaceGeneratedBlock,
|
|
40
|
-
|
|
41
|
+
requireUniqueLookup: () => requireUniqueLookup,
|
|
42
|
+
resolveRowIdentityLookup: () => resolveRowIdentityLookup,
|
|
43
|
+
string: () => string,
|
|
44
|
+
toUniqueLookupWhere: () => toUniqueLookupWhere,
|
|
45
|
+
validateUniqueLookupUpdateData: () => validateUniqueLookupUpdateData
|
|
41
46
|
});
|
|
42
47
|
module.exports = __toCommonJS(index_exports);
|
|
43
48
|
|
|
@@ -187,6 +192,199 @@ function datetime() {
|
|
|
187
192
|
}
|
|
188
193
|
|
|
189
194
|
// src/manifest.ts
|
|
195
|
+
function equalLookupValues(left, right) {
|
|
196
|
+
if (left instanceof Date && right instanceof Date) {
|
|
197
|
+
return left.getTime() === right.getTime();
|
|
198
|
+
}
|
|
199
|
+
return Object.is(left, right);
|
|
200
|
+
}
|
|
201
|
+
function isFilterObject(value) {
|
|
202
|
+
return !!value && typeof value === "object" && !(value instanceof Date) && !Array.isArray(value);
|
|
203
|
+
}
|
|
204
|
+
function extractEqualityValue(filter) {
|
|
205
|
+
if (!isFilterObject(filter)) {
|
|
206
|
+
return {
|
|
207
|
+
supported: true,
|
|
208
|
+
value: filter
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const keys = Object.keys(filter);
|
|
212
|
+
if (keys.length === 1 && "eq" in filter) {
|
|
213
|
+
return {
|
|
214
|
+
supported: true,
|
|
215
|
+
value: filter.eq
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
supported: false,
|
|
220
|
+
value: void 0
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function requireEqualityValues(model2, where, operation) {
|
|
224
|
+
const keys = Object.keys(where).filter((key) => key !== "AND" && key !== "OR" && key !== "NOT");
|
|
225
|
+
if ("AND" in where || "OR" in where || "NOT" in where || keys.length === 0) {
|
|
226
|
+
throw new Error(
|
|
227
|
+
`${operation} on model "${model2.name}" requires a unique equality filter in "where".`
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
const values = {};
|
|
231
|
+
for (const fieldName of keys) {
|
|
232
|
+
const field = model2.fields[fieldName];
|
|
233
|
+
if (!field) {
|
|
234
|
+
throw new Error(`Unknown field "${fieldName}" on model "${model2.name}".`);
|
|
235
|
+
}
|
|
236
|
+
const { supported, value } = extractEqualityValue(where[fieldName]);
|
|
237
|
+
if (!supported || value === void 0 || value === null) {
|
|
238
|
+
throw new Error(
|
|
239
|
+
`${operation} on model "${model2.name}" requires the "where" field "${fieldName}" to use a single non-null equality value.`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
values[fieldName] = value;
|
|
243
|
+
}
|
|
244
|
+
return values;
|
|
245
|
+
}
|
|
246
|
+
function sameFieldSet(left, right) {
|
|
247
|
+
return left.length === right.length && left.every((fieldName) => right.includes(fieldName));
|
|
248
|
+
}
|
|
249
|
+
function requireUniqueLookup(model2, where, operation) {
|
|
250
|
+
const values = requireEqualityValues(model2, where, operation);
|
|
251
|
+
const keys = Object.keys(values);
|
|
252
|
+
if (keys.length === 1) {
|
|
253
|
+
const field = model2.fields[keys[0]];
|
|
254
|
+
if (field.kind === "id") {
|
|
255
|
+
return {
|
|
256
|
+
kind: "id",
|
|
257
|
+
fields: [field],
|
|
258
|
+
values
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
if (field.unique) {
|
|
262
|
+
return {
|
|
263
|
+
kind: "field",
|
|
264
|
+
fields: [field],
|
|
265
|
+
values
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const constraint = model2.constraints.unique.find(
|
|
270
|
+
(candidate) => sameFieldSet([...candidate.fields], keys)
|
|
271
|
+
);
|
|
272
|
+
if (!constraint) {
|
|
273
|
+
throw new Error(
|
|
274
|
+
`${operation} on model "${model2.name}" requires the "where" clause to match an id field, unique field, or declared unique constraint using equality values only.`
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
kind: "constraint",
|
|
279
|
+
fields: constraint.fields.map((fieldName) => model2.fields[fieldName]),
|
|
280
|
+
values: Object.fromEntries(
|
|
281
|
+
constraint.fields.map((fieldName) => [fieldName, values[fieldName]])
|
|
282
|
+
),
|
|
283
|
+
constraint
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
function resolveRowIdentityLookup(model2, row) {
|
|
287
|
+
const idField = model2.fields.id;
|
|
288
|
+
if (idField && row[idField.name] !== void 0 && row[idField.name] !== null) {
|
|
289
|
+
return {
|
|
290
|
+
kind: "id",
|
|
291
|
+
fields: [idField],
|
|
292
|
+
values: {
|
|
293
|
+
[idField.name]: row[idField.name]
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
const uniqueField = Object.values(model2.fields).find(
|
|
298
|
+
(field) => field.unique && row[field.name] !== void 0 && row[field.name] !== null
|
|
299
|
+
);
|
|
300
|
+
if (uniqueField) {
|
|
301
|
+
return {
|
|
302
|
+
kind: "field",
|
|
303
|
+
fields: [uniqueField],
|
|
304
|
+
values: {
|
|
305
|
+
[uniqueField.name]: row[uniqueField.name]
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
for (const constraint of model2.constraints.unique) {
|
|
310
|
+
if (constraint.fields.every(
|
|
311
|
+
(fieldName) => row[fieldName] !== void 0 && row[fieldName] !== null
|
|
312
|
+
)) {
|
|
313
|
+
return {
|
|
314
|
+
kind: "constraint",
|
|
315
|
+
fields: constraint.fields.map((fieldName) => model2.fields[fieldName]),
|
|
316
|
+
values: Object.fromEntries(
|
|
317
|
+
constraint.fields.map((fieldName) => [fieldName, row[fieldName]])
|
|
318
|
+
),
|
|
319
|
+
constraint
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
throw new Error(
|
|
324
|
+
`Model "${model2.name}" requires an "id" field, unique field, or declared unique constraint with non-null values for identity lookups.`
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
function toUniqueLookupWhere(lookup) {
|
|
328
|
+
return Object.fromEntries(lookup.fields.map((field) => [field.name, lookup.values[field.name]]));
|
|
329
|
+
}
|
|
330
|
+
function mergeUniqueLookupCreateData(model2, createData, lookup, operation) {
|
|
331
|
+
const output = {
|
|
332
|
+
...createData
|
|
333
|
+
};
|
|
334
|
+
for (const field of lookup.fields) {
|
|
335
|
+
const currentValue = output[field.name];
|
|
336
|
+
const expectedValue = lookup.values[field.name];
|
|
337
|
+
if (currentValue !== void 0 && !equalLookupValues(currentValue, expectedValue)) {
|
|
338
|
+
throw new Error(
|
|
339
|
+
`${operation} on model "${model2.name}" requires create.${field.name} to match where.${field.name}.`
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
output[field.name] = currentValue ?? expectedValue;
|
|
343
|
+
}
|
|
344
|
+
return output;
|
|
345
|
+
}
|
|
346
|
+
function validateUniqueLookupUpdateData(model2, updateData, lookup, operation) {
|
|
347
|
+
for (const field of lookup.fields) {
|
|
348
|
+
const nextValue = updateData[field.name];
|
|
349
|
+
if (nextValue !== void 0 && !equalLookupValues(nextValue, lookup.values[field.name])) {
|
|
350
|
+
throw new Error(
|
|
351
|
+
`${operation} on model "${model2.name}" cannot change the conflict field "${field.name}".`
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
function createConstraintName(table, columns, suffix) {
|
|
357
|
+
const base = [table, ...columns].join("_").replace(/[^a-zA-Z0-9_]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toLowerCase();
|
|
358
|
+
return `${base}_${suffix}`;
|
|
359
|
+
}
|
|
360
|
+
function normalizeConstraints(modelName, table, fields, constraints) {
|
|
361
|
+
const normalize = (entries, unique) => (entries ?? []).map((entry) => {
|
|
362
|
+
if (!entry.length) {
|
|
363
|
+
throw new Error(
|
|
364
|
+
`Model "${modelName}" defines an empty ${unique ? "unique" : "index"} constraint.`
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
const columns = entry.map((fieldName) => {
|
|
368
|
+
const field = fields[fieldName];
|
|
369
|
+
if (!field) {
|
|
370
|
+
throw new Error(
|
|
371
|
+
`Model "${modelName}" defines a ${unique ? "unique" : "index"} constraint on unknown field "${fieldName}".`
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
return field.column;
|
|
375
|
+
});
|
|
376
|
+
return {
|
|
377
|
+
name: createConstraintName(table, columns, unique ? "unique" : "idx"),
|
|
378
|
+
fields: [...entry],
|
|
379
|
+
columns,
|
|
380
|
+
unique
|
|
381
|
+
};
|
|
382
|
+
});
|
|
383
|
+
return {
|
|
384
|
+
unique: normalize(constraints.unique, true),
|
|
385
|
+
indexes: normalize(constraints.indexes, false)
|
|
386
|
+
};
|
|
387
|
+
}
|
|
190
388
|
function createManifest(schema) {
|
|
191
389
|
const models = Object.fromEntries(
|
|
192
390
|
Object.entries(schema.models).map(
|
|
@@ -214,7 +412,13 @@ function createManifest(schema) {
|
|
|
214
412
|
table: definition.table,
|
|
215
413
|
description: definition.description,
|
|
216
414
|
fields,
|
|
217
|
-
relations: definition.relations
|
|
415
|
+
relations: definition.relations,
|
|
416
|
+
constraints: normalizeConstraints(
|
|
417
|
+
name,
|
|
418
|
+
definition.table,
|
|
419
|
+
fields,
|
|
420
|
+
definition.constraints
|
|
421
|
+
)
|
|
218
422
|
}
|
|
219
423
|
];
|
|
220
424
|
}
|
|
@@ -226,6 +430,7 @@ function createManifest(schema) {
|
|
|
226
430
|
// src/generators.ts
|
|
227
431
|
var capitalize = (value) => value.charAt(0).toUpperCase() + value.slice(1);
|
|
228
432
|
var pluralize = (value) => value.endsWith("s") ? value : `${value}s`;
|
|
433
|
+
var camelize = (value) => value.replace(/[^a-zA-Z0-9]+(.)/g, (_, char) => char.toUpperCase()).replace(/^[^a-zA-Z]+/, "").replace(/^[A-Z]/, (char) => char.toLowerCase());
|
|
229
434
|
function resolveReferenceTarget(manifest, model2, foreignKey, fallbackTarget) {
|
|
230
435
|
const reference = model2.fields[foreignKey]?.references;
|
|
231
436
|
if (!reference) {
|
|
@@ -260,6 +465,16 @@ function prismaType(field) {
|
|
|
260
465
|
return "DateTime";
|
|
261
466
|
}
|
|
262
467
|
}
|
|
468
|
+
function drizzleConstraintProperty(constraint) {
|
|
469
|
+
return camelize(constraint.name) || "constraint";
|
|
470
|
+
}
|
|
471
|
+
function constrainedFields(model2) {
|
|
472
|
+
return new Set(
|
|
473
|
+
[...model2.constraints.unique, ...model2.constraints.indexes].flatMap(
|
|
474
|
+
(constraint) => constraint.fields
|
|
475
|
+
)
|
|
476
|
+
);
|
|
477
|
+
}
|
|
263
478
|
function drizzleImports(dialect, manifest) {
|
|
264
479
|
const models = Object.values(manifest.models);
|
|
265
480
|
const needsBoolean = models.some(
|
|
@@ -268,12 +483,17 @@ function drizzleImports(dialect, manifest) {
|
|
|
268
483
|
const needsDate = models.some(
|
|
269
484
|
(model2) => Object.values(model2.fields).some((field) => field.kind === "datetime")
|
|
270
485
|
);
|
|
486
|
+
const needsIndexes = models.some(
|
|
487
|
+
(model2) => model2.constraints.indexes.length || model2.constraints.unique.length
|
|
488
|
+
);
|
|
271
489
|
if (dialect === "pg") {
|
|
272
490
|
return [
|
|
273
491
|
"pgTable",
|
|
274
492
|
"text",
|
|
275
493
|
needsBoolean ? "boolean" : null,
|
|
276
|
-
needsDate ? "timestamp" : null
|
|
494
|
+
needsDate ? "timestamp" : null,
|
|
495
|
+
needsIndexes ? "index" : null,
|
|
496
|
+
needsIndexes ? "uniqueIndex" : null
|
|
277
497
|
].filter(Boolean);
|
|
278
498
|
}
|
|
279
499
|
if (dialect === "mysql") {
|
|
@@ -282,12 +502,20 @@ function drizzleImports(dialect, manifest) {
|
|
|
282
502
|
"varchar",
|
|
283
503
|
"text",
|
|
284
504
|
needsBoolean ? "boolean" : null,
|
|
285
|
-
needsDate ? "datetime" : null
|
|
505
|
+
needsDate ? "datetime" : null,
|
|
506
|
+
needsIndexes ? "index" : null,
|
|
507
|
+
needsIndexes ? "uniqueIndex" : null
|
|
286
508
|
].filter(Boolean);
|
|
287
509
|
}
|
|
288
|
-
return [
|
|
510
|
+
return [
|
|
511
|
+
"sqliteTable",
|
|
512
|
+
"text",
|
|
513
|
+
"integer",
|
|
514
|
+
needsIndexes ? "index" : null,
|
|
515
|
+
needsIndexes ? "uniqueIndex" : null
|
|
516
|
+
].filter(Boolean);
|
|
289
517
|
}
|
|
290
|
-
function drizzleColumn(field, dialect) {
|
|
518
|
+
function drizzleColumn(field, dialect, options = {}) {
|
|
291
519
|
if (field.kind === "id") {
|
|
292
520
|
if (dialect === "mysql") {
|
|
293
521
|
return `varchar("${field.column}", { length: 191 }).primaryKey()`;
|
|
@@ -296,7 +524,7 @@ function drizzleColumn(field, dialect) {
|
|
|
296
524
|
}
|
|
297
525
|
if (field.kind === "string") {
|
|
298
526
|
if (dialect === "mysql") {
|
|
299
|
-
const base = field.unique || field.references ? `varchar("${field.column}", { length: 191 })` : `text("${field.column}")`;
|
|
527
|
+
const base = field.unique || field.references || options.indexed ? `varchar("${field.column}", { length: 191 })` : `text("${field.column}")`;
|
|
300
528
|
return `${base}${field.nullable ? "" : ".notNull()"}${field.unique ? ".unique()" : ""}${field.defaultValue !== void 0 ? `.default(${JSON.stringify(field.defaultValue)})` : ""}`;
|
|
301
529
|
}
|
|
302
530
|
return `text("${field.column}")${field.nullable ? "" : ".notNull()"}${field.unique ? ".unique()" : ""}${field.defaultValue !== void 0 ? `.default(${JSON.stringify(field.defaultValue)})` : ""}`;
|
|
@@ -313,14 +541,14 @@ function drizzleColumn(field, dialect) {
|
|
|
313
541
|
if (dialect === "sqlite") {
|
|
314
542
|
return `integer("${field.column}", { mode: "timestamp" })${field.nullable ? "" : ".notNull()"}`;
|
|
315
543
|
}
|
|
316
|
-
return `timestamp("${field.column}")${field.nullable ? "" : ".notNull()"}`;
|
|
544
|
+
return `timestamp("${field.column}", { withTimezone: true, mode: "date" })${field.nullable ? "" : ".notNull()"}`;
|
|
317
545
|
}
|
|
318
|
-
function sqlType(field, dialect) {
|
|
546
|
+
function sqlType(field, dialect, options = {}) {
|
|
319
547
|
if (field.kind === "id") {
|
|
320
548
|
return dialect === "mysql" ? "varchar(191)" : "text";
|
|
321
549
|
}
|
|
322
550
|
if (field.kind === "string") {
|
|
323
|
-
return dialect === "mysql" && (field.unique || field.references) ? "varchar(191)" : "text";
|
|
551
|
+
return dialect === "mysql" && (field.unique || field.references || options.indexed) ? "varchar(191)" : "text";
|
|
324
552
|
}
|
|
325
553
|
if (field.kind === "boolean") {
|
|
326
554
|
return dialect === "sqlite" ? "integer" : "boolean";
|
|
@@ -331,7 +559,7 @@ function sqlType(field, dialect) {
|
|
|
331
559
|
if (dialect === "sqlite") {
|
|
332
560
|
return "text";
|
|
333
561
|
}
|
|
334
|
-
return "
|
|
562
|
+
return "timestamptz";
|
|
335
563
|
}
|
|
336
564
|
function sqlIdentifier(dialect, value) {
|
|
337
565
|
if (dialect === "mysql") {
|
|
@@ -339,6 +567,14 @@ function sqlIdentifier(dialect, value) {
|
|
|
339
567
|
}
|
|
340
568
|
return `"${value}"`;
|
|
341
569
|
}
|
|
570
|
+
function sqlCreateIndexStatement(dialect, table, constraint) {
|
|
571
|
+
const indexName = sqlIdentifier(dialect, constraint.name);
|
|
572
|
+
const tableName = sqlIdentifier(dialect, table);
|
|
573
|
+
const columns = constraint.columns.map((column) => sqlIdentifier(dialect, column)).join(", ");
|
|
574
|
+
const createKeyword = constraint.unique ? "create unique index" : "create index";
|
|
575
|
+
const ifNotExists = dialect === "mysql" ? "" : " if not exists";
|
|
576
|
+
return `${createKeyword}${ifNotExists} ${indexName} on ${tableName}(${columns});`;
|
|
577
|
+
}
|
|
342
578
|
function renderPrismaSchema(schema, options = {}) {
|
|
343
579
|
const manifest = createManifest(schema);
|
|
344
580
|
const provider = options.provider ?? "postgresql";
|
|
@@ -421,10 +657,18 @@ function renderPrismaSchema(schema, options = {}) {
|
|
|
421
657
|
relation.many ? ` ${relationName} ${capitalize(relation.sourceModel)}[]` : ` ${relationName} ${capitalize(relation.sourceModel)}?`
|
|
422
658
|
);
|
|
423
659
|
}
|
|
424
|
-
const
|
|
425
|
-
|
|
660
|
+
const modelLines = [
|
|
661
|
+
...lines,
|
|
662
|
+
...model2.constraints.unique.map(
|
|
663
|
+
(constraint) => ` @@unique([${constraint.fields.join(", ")}])`
|
|
664
|
+
),
|
|
665
|
+
...model2.constraints.indexes.map(
|
|
666
|
+
(constraint) => ` @@index([${constraint.fields.join(", ")}])`
|
|
667
|
+
),
|
|
668
|
+
...model2.table !== modelName ? [` @@map("${model2.table}")`] : []
|
|
669
|
+
];
|
|
426
670
|
return `model ${modelName} {
|
|
427
|
-
${
|
|
671
|
+
${modelLines.join("\n")}
|
|
428
672
|
}`;
|
|
429
673
|
});
|
|
430
674
|
return `generator ${generatorName} {
|
|
@@ -444,17 +688,33 @@ function renderDrizzleSchema(schema, options) {
|
|
|
444
688
|
const coreImports = drizzleImports(options.dialect, manifest).join(", ");
|
|
445
689
|
const tableFactory = options.dialect === "pg" ? "pgTable" : options.dialect === "mysql" ? "mysqlTable" : "sqliteTable";
|
|
446
690
|
const modelBlocks = Object.values(manifest.models).map((model2) => {
|
|
691
|
+
const indexedFields = constrainedFields(model2);
|
|
447
692
|
const lines = Object.values(model2.fields).map((field) => {
|
|
448
|
-
let value = drizzleColumn(field, options.dialect);
|
|
693
|
+
let value = drizzleColumn(field, options.dialect, { indexed: indexedFields.has(field.name) });
|
|
449
694
|
if (field.references) {
|
|
450
695
|
const [targetModel, targetField] = field.references.split(".");
|
|
451
696
|
value += `.references(() => ${targetModel}.${targetField})`;
|
|
452
697
|
}
|
|
453
698
|
return ` ${field.name}: ${value}`;
|
|
454
699
|
});
|
|
455
|
-
|
|
700
|
+
const constraintLines = [
|
|
701
|
+
...model2.constraints.unique.map(
|
|
702
|
+
(constraint) => ` ${drizzleConstraintProperty(constraint)}: uniqueIndex("${constraint.name}").on(${constraint.fields.map((fieldName) => `table.${fieldName}`).join(", ")})`
|
|
703
|
+
),
|
|
704
|
+
...model2.constraints.indexes.map(
|
|
705
|
+
(constraint) => ` ${drizzleConstraintProperty(constraint)}: index("${constraint.name}").on(${constraint.fields.map((fieldName) => `table.${fieldName}`).join(", ")})`
|
|
706
|
+
)
|
|
707
|
+
];
|
|
708
|
+
if (!constraintLines.length) {
|
|
709
|
+
return `export const ${model2.name} = ${tableFactory}("${model2.table}", {
|
|
456
710
|
${lines.join(",\n")}
|
|
457
711
|
});`;
|
|
712
|
+
}
|
|
713
|
+
return `export const ${model2.name} = ${tableFactory}("${model2.table}", {
|
|
714
|
+
${lines.join(",\n")}
|
|
715
|
+
}, (table) => ({
|
|
716
|
+
${constraintLines.join(",\n")}
|
|
717
|
+
}));`;
|
|
458
718
|
});
|
|
459
719
|
const relationBlocks = Object.values(manifest.models).map((model2) => {
|
|
460
720
|
const lines = Object.entries(model2.relations).flatMap(([relationName, relation]) => {
|
|
@@ -493,10 +753,13 @@ ${[...modelBlocks, ...relationBlocks].join("\n\n")}
|
|
|
493
753
|
}
|
|
494
754
|
function renderSafeSql(schema, options) {
|
|
495
755
|
const manifest = createManifest(schema);
|
|
496
|
-
const statements = Object.values(manifest.models).
|
|
756
|
+
const statements = Object.values(manifest.models).flatMap((model2) => {
|
|
757
|
+
const indexedFields = constrainedFields(model2);
|
|
497
758
|
const columns = Object.values(model2.fields).map((field) => {
|
|
498
759
|
const parts = [
|
|
499
|
-
`${sqlIdentifier(options.dialect, field.column)} ${sqlType(field, options.dialect
|
|
760
|
+
`${sqlIdentifier(options.dialect, field.column)} ${sqlType(field, options.dialect, {
|
|
761
|
+
indexed: indexedFields.has(field.name)
|
|
762
|
+
})}`
|
|
500
763
|
];
|
|
501
764
|
if (field.kind === "id") parts.push("primary key");
|
|
502
765
|
if (!field.nullable) parts.push("not null");
|
|
@@ -519,9 +782,17 @@ function renderSafeSql(schema, options) {
|
|
|
519
782
|
}
|
|
520
783
|
return ` ${parts.join(" ")}`;
|
|
521
784
|
});
|
|
522
|
-
return
|
|
785
|
+
return [
|
|
786
|
+
`create table if not exists ${sqlIdentifier(options.dialect, model2.table)} (
|
|
523
787
|
${columns.join(",\n")}
|
|
524
|
-
)
|
|
788
|
+
);`,
|
|
789
|
+
...model2.constraints.unique.map(
|
|
790
|
+
(constraint) => sqlCreateIndexStatement(options.dialect, model2.table, constraint)
|
|
791
|
+
),
|
|
792
|
+
...model2.constraints.indexes.map(
|
|
793
|
+
(constraint) => sqlCreateIndexStatement(options.dialect, model2.table, constraint)
|
|
794
|
+
)
|
|
795
|
+
];
|
|
525
796
|
});
|
|
526
797
|
return `${statements.join("\n\n")}
|
|
527
798
|
`;
|
|
@@ -545,6 +816,14 @@ ${block}
|
|
|
545
816
|
// src/memory.ts
|
|
546
817
|
var import_node_crypto = require("crypto");
|
|
547
818
|
var isDate = (value) => value instanceof Date;
|
|
819
|
+
var manifestCache = /* @__PURE__ */ new WeakMap();
|
|
820
|
+
function getManifest(schema) {
|
|
821
|
+
const cached = manifestCache.get(schema);
|
|
822
|
+
if (cached) return cached;
|
|
823
|
+
const next = createManifest(schema);
|
|
824
|
+
manifestCache.set(schema, next);
|
|
825
|
+
return next;
|
|
826
|
+
}
|
|
548
827
|
function evaluateFilter(value, filter) {
|
|
549
828
|
if (filter === void 0 || filter === null || typeof filter !== "object" || isDate(filter) || Array.isArray(filter)) {
|
|
550
829
|
return value === filter;
|
|
@@ -737,6 +1016,11 @@ function createMemoryDriver(seed) {
|
|
|
737
1016
|
return projectRow(schema, model2, row, args.select);
|
|
738
1017
|
},
|
|
739
1018
|
async findUnique(schema, model2, args) {
|
|
1019
|
+
requireUniqueLookup(
|
|
1020
|
+
getManifest(schema).models[model2],
|
|
1021
|
+
args.where,
|
|
1022
|
+
"FindUnique"
|
|
1023
|
+
);
|
|
740
1024
|
const row = applyQuery(getRows(model2), args)[0];
|
|
741
1025
|
if (!row) return null;
|
|
742
1026
|
return projectRow(schema, model2, row, args.select);
|
|
@@ -768,12 +1052,32 @@ function createMemoryDriver(seed) {
|
|
|
768
1052
|
return rows.length;
|
|
769
1053
|
},
|
|
770
1054
|
async upsert(schema, model2, args) {
|
|
1055
|
+
const lookup = requireUniqueLookup(
|
|
1056
|
+
getManifest(schema).models[model2],
|
|
1057
|
+
args.where,
|
|
1058
|
+
"Upsert"
|
|
1059
|
+
);
|
|
1060
|
+
validateUniqueLookupUpdateData(
|
|
1061
|
+
getManifest(schema).models[model2],
|
|
1062
|
+
args.update,
|
|
1063
|
+
lookup,
|
|
1064
|
+
"Upsert"
|
|
1065
|
+
);
|
|
771
1066
|
const row = getRows(model2).find((item) => matchesWhere(item, args.where));
|
|
772
1067
|
if (row) {
|
|
773
1068
|
Object.assign(row, args.update);
|
|
774
1069
|
return projectRow(schema, model2, row, args.select);
|
|
775
1070
|
}
|
|
776
|
-
const created = buildRow(
|
|
1071
|
+
const created = buildRow(
|
|
1072
|
+
schema,
|
|
1073
|
+
model2,
|
|
1074
|
+
mergeUniqueLookupCreateData(
|
|
1075
|
+
getManifest(schema).models[model2],
|
|
1076
|
+
args.create,
|
|
1077
|
+
lookup,
|
|
1078
|
+
"Upsert"
|
|
1079
|
+
)
|
|
1080
|
+
);
|
|
777
1081
|
getRows(model2).push(created);
|
|
778
1082
|
return projectRow(schema, model2, created, args.select);
|
|
779
1083
|
},
|
|
@@ -845,6 +1149,7 @@ function model(config) {
|
|
|
845
1149
|
table: config.table,
|
|
846
1150
|
fields: config.fields,
|
|
847
1151
|
relations: config.relations ?? {},
|
|
1152
|
+
constraints: config.constraints ?? {},
|
|
848
1153
|
description: config.description
|
|
849
1154
|
};
|
|
850
1155
|
}
|
|
@@ -868,11 +1173,16 @@ function defineSchema(models) {
|
|
|
868
1173
|
hasOne,
|
|
869
1174
|
id,
|
|
870
1175
|
manyToMany,
|
|
1176
|
+
mergeUniqueLookupCreateData,
|
|
871
1177
|
model,
|
|
872
1178
|
renderDrizzleSchema,
|
|
873
1179
|
renderPrismaSchema,
|
|
874
1180
|
renderSafeSql,
|
|
875
1181
|
replaceGeneratedBlock,
|
|
876
|
-
|
|
1182
|
+
requireUniqueLookup,
|
|
1183
|
+
resolveRowIdentityLookup,
|
|
1184
|
+
string,
|
|
1185
|
+
toUniqueLookupWhere,
|
|
1186
|
+
validateUniqueLookupUpdateData
|
|
877
1187
|
});
|
|
878
1188
|
//# sourceMappingURL=index.cjs.map
|