UNPKG

@palmares/drizzle-engine

Version:

This is the engine that wraps the hole drizzle interface in a way palmares can understand and have full control of

532 lines (516 loc) 20.6 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); // src/fields/index.ts import { adapterFields } from "@palmares/databases"; // src/fields/big-integer.ts import { adapterBigIntegerFieldParser } from "@palmares/databases"; // src/fields/utils.ts function getBuilderArgs(builder, callback) { const defaultOptions = callback([]); return (customAttributesArgs, customAttributesOptions) => { const customAttributesDefined = new Set(Object.keys(customAttributesOptions || {})); const builderArgs = Object.entries(customAttributesOptions || {}).map(([method, args]) => { return [ method, args.map((arg) => typeof arg === "object" ? JSON.stringify(arg) : arg.toString()).join(", ") ]; }); for (const [method, args] of defaultOptions) if (!customAttributesDefined.has(method)) builderArgs.push([ method, args ]); const builderArguments = builderArgs.map(([method, args]) => { return (args || []).length > 0 ? `.${method}(${args})` : `.${method}()`; }).join(""); return `${builder.withoutD ? "" : "d."}${builder.type}('${builder.databaseName}'${customAttributesArgs !== void 0 || builder.args ? `, ${customAttributesArgs !== void 0 ? JSON.stringify(customAttributesArgs) : builder.args}` : ""})${builderArguments}`; }; } __name(getBuilderArgs, "getBuilderArgs"); // src/fields/big-integer.ts var bigIntegerFieldParser = adapterBigIntegerFieldParser({ translate: /* @__PURE__ */ __name(async (args) => { const defaultOptions = await args.fieldParser.translate(args); const field = args.field; const mainType = args.engine.instance.mainType; const builderArgsFormatted = getBuilderArgs({ type: mainType === "sqlite" ? "integer" : mainType !== "postgres" ? "bigint" : defaultOptions.autoincrement ? "bigserial" : "bigint", databaseName: field.databaseName, args: "{ mode: 'number' }" }, (defaultBuilderArgs) => { if (defaultOptions.primaryKey) defaultBuilderArgs.push([ "primaryKey", mainType === "sqlite" ? "{ autoIncrement: true }" : "" ]); if (defaultOptions.default) defaultBuilderArgs.push([ "default", defaultOptions.default ]); if (defaultOptions.nullable !== true) defaultBuilderArgs.push([ "notNull", "" ]); if (defaultOptions.unique) defaultBuilderArgs.push([ "unique", "" ]); if (mainType === "mysql" && defaultOptions.autoincrement) defaultBuilderArgs.push([ "autoIncrement", "" ]); return defaultBuilderArgs; })(args.customAttributes.args, args.customAttributes.options); return builderArgsFormatted; }, "translate") }); // src/fields/boolean.ts import { adapterBooleanFieldParser } from "@palmares/databases"; var booleanFieldParser = adapterBooleanFieldParser({ translate: /* @__PURE__ */ __name(async (args) => { const defaultOptions = await args.fieldParser.translate(args); const field = args.field; const mainType = args.engine.instance.mainType; const builderArgsFormatted = getBuilderArgs({ type: mainType === "sqlite" ? "integer" : "boolean", databaseName: field.databaseName, args: mainType === "sqlite" ? "{ mode: 'number' }" : void 0 }, (defaultBuilderArgs) => { if (defaultOptions.primaryKey) defaultBuilderArgs.push([ "primaryKey", "" ]); if (typeof defaultOptions.default === "boolean") if (mainType === "sqlite") defaultBuilderArgs.push([ "default", defaultOptions.default ? "1" : "0" ]); else defaultBuilderArgs.push([ "default", JSON.stringify(defaultOptions.default) ]); if (defaultOptions.nullable !== true) defaultBuilderArgs.push([ "notNull", "" ]); if (defaultOptions.unique) defaultBuilderArgs.push([ "unique", "" ]); return defaultBuilderArgs; })(args.customAttributes.args, args.customAttributes.options); return builderArgsFormatted; }, "translate") }); // src/fields/char.ts import { adapterCharFieldParser } from "@palmares/databases"; var charFieldParser = adapterCharFieldParser({ translate: /* @__PURE__ */ __name(async (args) => { const defaultOptions = await args.fieldParser.translate(args); const field = args.field; const mainType = args.engine.instance.mainType; return getBuilderArgs({ type: mainType === "sqlite" ? "text" : "varchar", databaseName: field.databaseName, args: `{ length: ${args.field.maxLength} }` }, (defaultBuilderArgs) => { if (defaultOptions.primaryKey) defaultBuilderArgs.push([ "primaryKey", "" ]); if (defaultOptions.default) defaultBuilderArgs.push([ "default", `"${defaultOptions.default}"` ]); if (defaultOptions.nullable !== true) defaultBuilderArgs.push([ "notNull", "" ]); if (defaultOptions.unique) defaultBuilderArgs.push([ "unique", "" ]); return defaultBuilderArgs; })(args.customAttributes.args, args.customAttributes.options); }, "translate") }); // src/fields/date.ts import { adapterDateFieldParser } from "@palmares/databases"; var dateFieldParser = adapterDateFieldParser({ translate: /* @__PURE__ */ __name(async (args) => { const defaultOptions = await args.fieldParser.translate(args); const field = args.field; const mainType = args.engine.instance.mainType; return getBuilderArgs({ type: mainType === "sqlite" ? "text" : mainType === "postgres" ? "timestamp" : "datetime", databaseName: field.databaseName, args: mainType === "postgres" ? "{ precision: 6, withTimezone: true, mode: 'date' }" : mainType === "sqlite" ? "" : "{ fsp: 6, mode: 'date' }" }, (defaultBuilderArgs) => { if (defaultOptions.primaryKey) defaultBuilderArgs.push([ "primaryKey", "" ]); if (defaultOptions.default) defaultBuilderArgs.push([ "default", defaultOptions.default ]); if (defaultOptions.nullable !== true) defaultBuilderArgs.push([ "notNull", "" ]); if (defaultOptions.unique) defaultBuilderArgs.push([ "unique", "" ]); if (field.autoNowAdd) if (mainType === "sqlite") defaultBuilderArgs.push([ "default", "drzl.sql`(current_timestamp)`" ]); else defaultBuilderArgs.push([ "defaultNow", "" ]); if (field.autoNow) if (mainType === "sqlite") defaultBuilderArgs.push([ "$onUpdate", "() => drzl.sql`CURRENT_TIMESTAMP`" ]); else defaultBuilderArgs.push([ "$onUpdate", "() => drzl.sql`now()`" ]); return defaultBuilderArgs; })(args.customAttributes.args, args.customAttributes.options); }, "translate") }); // src/fields/decimal.ts import { adapterDecimalFieldParser } from "@palmares/databases"; var decimalFieldParser = adapterDecimalFieldParser({ translate: /* @__PURE__ */ __name(async (args) => { const defaultOptions = await args.fieldParser.translate(args); const field = args.field; const mainType = args.engine.instance.mainType; return getBuilderArgs({ type: mainType === "sqlite" ? "real" : mainType === "postgres" ? "numeric" : "decimal", databaseName: field.databaseName, args: mainType === "sqlite" ? "" : `{ precision: ${field.decimalPlaces}, scale: ${field.maxDigits} }` }, (defaultBuilderArgs) => { if (defaultOptions.primaryKey) defaultBuilderArgs.push([ "primaryKey", "" ]); if (defaultOptions.default) defaultBuilderArgs.push([ "default", defaultOptions.default ]); if (defaultOptions.nullable !== true) defaultBuilderArgs.push([ "notNull", "" ]); if (defaultOptions.unique) defaultBuilderArgs.push([ "unique", "" ]); return defaultBuilderArgs; })(args.customAttributes.args, args.customAttributes.options); }, "translate") }); // src/fields/enum.ts import { adapterEnumFieldParser } from "@palmares/databases"; var enumFieldParse = adapterEnumFieldParser({ translate: /* @__PURE__ */ __name(async (args) => { const defaultOptions = await args.fieldParser.translate(args); const field = args.field; const mainType = args.engine.instance.mainType; const optionsAsString = args.field.choices.map((choice) => `"${choice}"`).join(", "); const enumVariableName = `${field.fieldName}Enum`; if (mainType === "postgres") { args.lazyEvaluate({ type: "enum", data: `export const ${enumVariableName} = d.pgEnum('${field.databaseName}', [${optionsAsString}]);` }); } return getBuilderArgs({ type: mainType === "sqlite" ? "text" : mainType === "postgres" ? enumVariableName : "mysqlEnum", databaseName: field.databaseName, args: mainType === "sqlite" ? `{ enum: [${optionsAsString}] }` : mainType === "mysql" ? `[${optionsAsString}]` : "", withoutD: mainType === "postgres" ? true : false }, (defaultBuilderArgs) => { if (defaultOptions.primaryKey) defaultBuilderArgs.push([ "primaryKey", "" ]); if (defaultOptions.default) defaultBuilderArgs.push([ "default", `${typeof defaultOptions.default === "string" ? `'${defaultOptions.default}'` : defaultOptions.default}` ]); if (defaultOptions.nullable !== true) defaultBuilderArgs.push([ "notNull", "" ]); if (defaultOptions.unique) defaultBuilderArgs.push([ "unique", "" ]); return defaultBuilderArgs; })(args.customAttributes.args, args.customAttributes.options); }, "translate") }); // src/fields/field.ts import { adapterFieldParser } from "@palmares/databases"; var fieldParser = adapterFieldParser({ // eslint-disable-next-line ts/require-await translate: /* @__PURE__ */ __name(async (args) => { if (args.customAttributes.type) return getBuilderArgs({ type: args.customAttributes.type, databaseName: args.field.databaseName, args: args.customAttributes.args }, (defaultBuilderArgs) => defaultBuilderArgs)(args.customAttributes.args, args.customAttributes.options); if (args.field.dbIndex) { args.lazyEvaluate({ type: "index", indexAttributes: { modelName: args.modelName, fieldName: args.field.fieldName, databaseName: args.field.databaseName, unique: args.field.unique } }); } const fieldData = { fieldName: args.field.fieldName, primaryKey: args.field.primaryKey, unique: args.field.unique, nullable: args.field.allowNull, dbIndex: args.field.dbIndex, default: args.field.defaultValue, autoincrement: args.field.isAuto, databaseName: args.field.databaseName, custom: args.customAttributes }; return fieldData; }, "translate") }); // src/fields/foreign-key.ts import { adapterForeignKeyFieldParser } from "@palmares/databases"; var foreignKeyFieldParser = adapterForeignKeyFieldParser({ translate: /* @__PURE__ */ __name(async (args) => { const defaultOptions = await args.fieldParser.translate(args); args.lazyEvaluate({ type: "foreign-key", fieldAttributes: { ...defaultOptions, foreignData: { ...args.field, toField: args.field.toField, relatedToModelName: args.field.relatedTo, relatedName: args.field.relatedName, relationName: args.field.relationName, action: args.field.onDelete } } }); }, "translate") }); // src/fields/integer.ts import { adapterIntegerFieldParser } from "@palmares/databases"; var integerFieldParser = adapterIntegerFieldParser({ translate: /* @__PURE__ */ __name(async (args) => { const defaultOptions = await args.fieldParser.translate(args); const field = args.field; const mainType = args.engine.instance.mainType; const builderArgsFormatted = getBuilderArgs({ type: mainType === "sqlite" ? "integer" : mainType !== "postgres" ? "bigint" : defaultOptions.autoincrement ? "serial" : "integer", databaseName: field.databaseName, args: mainType === "sqlite" ? "{ mode: 'number' }" : "" }, (defaultBuilderArgs) => { if (defaultOptions.primaryKey) defaultBuilderArgs.push([ "primaryKey", mainType === "sqlite" ? "{ autoIncrement: true }" : "" ]); if (defaultOptions.default) defaultBuilderArgs.push([ "default", defaultOptions.default ]); if (defaultOptions.nullable !== true) defaultBuilderArgs.push([ "notNull", "" ]); if (defaultOptions.unique) defaultBuilderArgs.push([ "unique", "" ]); if (mainType === "mysql" && defaultOptions.autoincrement) defaultBuilderArgs.push([ "autoIncrement", "" ]); return defaultBuilderArgs; })(args.customAttributes.args, args.customAttributes.options); return builderArgsFormatted; }, "translate") }); // src/fields/text.ts import { adapterTextFieldParser } from "@palmares/databases"; var textFieldParser = adapterTextFieldParser({ translate: /* @__PURE__ */ __name(async (args) => { const defaultOptions = await args.fieldParser.translate(args); const field = args.field; return getBuilderArgs({ type: "text", databaseName: field.databaseName, args: void 0 }, (defaultBuilderArgs) => { if (defaultOptions.primaryKey) defaultBuilderArgs.push([ "primaryKey", "" ]); if (defaultOptions.default) defaultBuilderArgs.push([ "default", `"${defaultOptions.default}"` ]); if (defaultOptions.nullable !== true) defaultBuilderArgs.push([ "notNull", "" ]); if (defaultOptions.unique) defaultBuilderArgs.push([ "unique", "" ]); return defaultBuilderArgs; })(args.customAttributes.args, args.customAttributes.options); }, "translate") }); // src/fields/uuid.ts import { adapterUuidFieldParser } from "@palmares/databases"; var uuidFieldParser = adapterUuidFieldParser({ translate: /* @__PURE__ */ __name(async (args) => { const defaultOptions = await args.fieldParser.translate({ ...args, field: { ...args.field, isAuto: false } }); const field = args.field; const mainType = args.engine.instance.mainType; if (field.isAuto && mainType !== "postgres") { args.lazyEvaluate({ type: "uuid", data: `import * as pdb from '@palmares/databases;'` }); } return getBuilderArgs({ type: mainType === "sqlite" ? "text" : mainType === "postgres" ? "uuid" : "varchar", databaseName: field.databaseName, args: mainType === "sqlite" || mainType === "postgres" ? "" : `{ length: 36 }` }, (defaultBuilderArgs) => { if (defaultOptions.primaryKey) defaultBuilderArgs.push([ "primaryKey", "" ]); if (defaultOptions.default) defaultBuilderArgs.push([ "default", `"${defaultOptions.default}"` ]); if (defaultOptions.nullable !== true) defaultBuilderArgs.push([ "notNull", "" ]); if (defaultOptions.unique) defaultBuilderArgs.push([ "unique", "" ]); if (field.isAuto) { if (mainType === "postgres") defaultBuilderArgs.push([ "defaultRandom", "" ]); else defaultBuilderArgs.push([ "$defaultFn", "() => pdb.generateUUID()" ]); } return defaultBuilderArgs; })(args.customAttributes.args, args.customAttributes.options); }, "translate") }); // src/fields/index.ts function createOneToOneRelation(modelName, modelFieldName, relatedModelName, relatedFieldName) { return `args.one(${relatedModelName}, { fields: [${modelName}.${modelFieldName}], references: [${relatedModelName}.${relatedFieldName}] })`; } __name(createOneToOneRelation, "createOneToOneRelation"); async function formatForeignKeyField(engine, modelName, translatedModel, _field, fieldTranslated, parseAgain) { const foreignData = fieldTranslated.fieldAttributes.foreignData; const data = await parseAgain({ fieldName: foreignData.toField, modelName: foreignData.relatedToModelName, optionsOverrideCallback: { isAuto: /* @__PURE__ */ __name(() => foreignData.isAuto, "isAuto"), primaryKey: /* @__PURE__ */ __name(() => foreignData.isPrimaryKey, "primaryKey"), unique: /* @__PURE__ */ __name(() => foreignData.isUnique, "unique"), allowNull: /* @__PURE__ */ __name(() => foreignData.allowNull, "allowNull"), defaultValue: /* @__PURE__ */ __name(() => foreignData.defaultValue, "defaultValue"), customAttributes: /* @__PURE__ */ __name(() => foreignData.customAttributes, "customAttributes"), databaseName: /* @__PURE__ */ __name(() => foreignData.databaseName, "databaseName"), dbIndex: /* @__PURE__ */ __name(() => foreignData.dbIndex, "dbIndex"), fieldName: /* @__PURE__ */ __name(() => foreignData.fieldName, "fieldName"), underscored: /* @__PURE__ */ __name(() => foreignData.underscored, "underscored"), autoNow: /* @__PURE__ */ __name(() => false, "autoNow"), autoNowAdd: /* @__PURE__ */ __name(() => false, "autoNowAdd"), allowBlank: /* @__PURE__ */ __name(() => false, "allowBlank"), maxLength: /* @__PURE__ */ __name(() => false, "maxLength") } }); const columnType = engine.instance.mainType === "postgres" ? "d.AnyPgColumn" : engine.instance.mainType === "sqlite" ? "d.AnySQLiteColumn" : "d.AnyMySqlColumn"; translatedModel.fields[fieldTranslated.fieldAttributes.fieldName] = `${data}.references((): ${columnType} => ${foreignData.relatedToModelName}.${foreignData.toField})`; translatedModel.options.relationships ??= {}; translatedModel.options.relationships[modelName] ??= {}; translatedModel.options.relationships[modelName][foreignData.relationName] = createOneToOneRelation(modelName, fieldTranslated.fieldAttributes.fieldName, foreignData.relatedToModelName, foreignData.toField); const ifIndirectOneRelation = createOneToOneRelation(foreignData.relatedToModelName, foreignData.toField, modelName, fieldTranslated.fieldAttributes.fieldName); const ifIndirectManyRelation = `args.many(${modelName})`; translatedModel.options.relationships[foreignData.relatedToModelName] ??= {}; translatedModel.options.relationships[foreignData.relatedToModelName][foreignData.relatedName] = fieldTranslated.fieldAttributes.unique ? ifIndirectOneRelation : ifIndirectManyRelation; } __name(formatForeignKeyField, "formatForeignKeyField"); var fields = adapterFields({ fieldsParser: new fieldParser(), bigIntegerFieldParser: new bigIntegerFieldParser(), charFieldParser: new charFieldParser(), dateFieldParser: new dateFieldParser(), decimalFieldParser: new decimalFieldParser(), foreignKeyFieldParser: new foreignKeyFieldParser(), integerFieldParser: new integerFieldParser(), textFieldParser: new textFieldParser(), uuidFieldParser: new uuidFieldParser(), enumFieldParser: new enumFieldParse(), booleanFieldParser: new booleanFieldParser(), lazyEvaluateField: /* @__PURE__ */ __name(async (engine, modelName, translatedModel, fieldAttributes, fieldTranslated, parseAgain) => { switch (fieldTranslated.type) { case "enum": { translatedModel.options.enums ??= []; translatedModel.options.enums.push(fieldTranslated.data); return translatedModel; } case "uuid": { translatedModel.options.imports ??= /* @__PURE__ */ new Set(); translatedModel.options.imports.add(`import * as pdb from '@palmares/databases';`); return translatedModel; } case "foreign-key": { await formatForeignKeyField(engine, modelName, translatedModel, fieldAttributes, fieldTranslated, parseAgain); return translatedModel; } case "index": { if (modelName === fieldTranslated.indexAttributes.modelName) { translatedModel.options.drizzleIndexes ??= []; translatedModel.options.drizzleIndexes.push(fieldTranslated.indexAttributes); return translatedModel; } break; } } return void 0; }, "lazyEvaluateField") }); export { fields };