123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793 |
- "use strict";
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.AutoGenerator = void 0;
- const lodash_1 = __importDefault(require("lodash"));
- const types_1 = require("./types");
- /** Generates text from each table in TableData */
- class AutoGenerator {
- constructor(tableData, dialect, options) {
- this.tables = tableData.tables;
- this.foreignKeys = tableData.foreignKeys;
- this.hasTriggerTables = tableData.hasTriggerTables;
- this.indexes = tableData.indexes;
- this.relations = tableData.relations;
- this.dialect = dialect;
- this.options = options;
- this.options.lang = this.options.lang || 'es5';
- this.space = (0, types_1.makeIndent)(this.options.spaces, this.options.indentation);
- this.attrbuitesstr = '';
- }
- makeHeaderTemplate() {
- const header = "import { Column, DataType, Table, Model,Sequelize } from 'sequelize-typescript';\n\n";
- return header;
- }
- // 生成文本
- generateText() {
- const tableNames = lodash_1.default.keys(this.tables);
- // 创建通用文件头部内容
- const header = this.makeHeaderTemplate();
- const text = {};
- tableNames.forEach(table => {
- let str = header;
- const [schemaName, tableNameOrig] = (0, types_1.qNameSplit)(table);
- const tableName = (0, types_1.makeTableName)(this.options.caseModel, tableNameOrig, this.options.singularize, this.options.lang);
- // 为表的模型创建一个字符串
- str += this.addTable(table).trim();
- const re = new RegExp('#TABLE#', 'g');
- str = str.replace(re, tableName);
- text[table] = str;
- });
- return text;
- }
- addTable(table) {
- const [schemaName, tableNameOrig] = (0, types_1.qNameSplit)(table);
- const space = this.space;
- let timestamps = (this.options.additional && this.options.additional.timestamps === true) || false;
- let paranoid = (this.options.additional && this.options.additional.paranoid === true) || false;
- // 为表全部的字段生成字符串
- let str = '@Table({\n';
- str += space[2] + "tableName: '" + tableNameOrig + "',\n";
- if (schemaName && this.dialect.hasSchema) {
- str += space[2] + "schema: '" + schemaName + "',\n";
- }
- if (this.hasTriggerTables[table]) {
- str += space[2] + "hasTrigger: true,\n";
- }
- str += space[2] + "timestamps: " + timestamps + ",\n";
- if (paranoid) {
- str += space[2] + "paranoid: true,\n";
- }
- // 有条件地添加额外选项
- const hasadditional = lodash_1.default.isObject(this.options.additional) && lodash_1.default.keys(this.options.additional).length > 0;
- if (hasadditional) {
- lodash_1.default.each(this.options.additional, (value, key) => {
- if (key === 'name') {
- // name: true - preserve table name always
- str += space[2] + "name: {\n";
- str += space[3] + "singular: '" + table + "',\n";
- str += space[3] + "plural: '" + table + "'\n";
- str += space[2] + "},\n";
- }
- else if (key === "timestamps" || key === "paranoid") {
- // handled above
- }
- else {
- value = lodash_1.default.isBoolean(value) ? value : ("'" + value + "'");
- str += space[2] + key + ": " + value + ",\n";
- }
- });
- }
- if (!this.options.noIndexes) {
- // 添加索引
- str += this.addIndexes(table);
- }
- str = space[2] + str.trim();
- str = str.substring(0, str.length - 1);
- str += "\n})\n";
- const characters = [...lodash_1.default.camelCase(tableNameOrig)];
- characters[0] = characters[0].toUpperCase();
- const entityName = characters.join("");
- str += `export class ${entityName}Entity extends Model {\n`;
- const fields = lodash_1.default.keys(this.tables[table]);
- fields.forEach((field, index) => {
- // 判断是否为 created_at 和 updated_at 字段
- timestamps || (timestamps = this.isTimestampField(field));
- // 判断是否为 deleted_at 字段
- paranoid || (paranoid = this.isParanoidField(field));
- // 创建一个包含字段属性(类型、defaultValue等)的字符串
- str += this.addField(table, field);
- });
- // 移除最后的 ",\n"
- str = str.substring(0, str.length - 2) + "\n}";
- str += this.addAttributesHeader(entityName,this.attrbuitesstr);
- this.attrbuitesstr = '';
- return str;
- }
- addField(table, field) {
- // 忽略 Sequelize 标准字段
- const additional = this.options.additional;
- if (additional && (additional.timestamps !== false) && (this.isTimestampField(field) || this.isParanoidField(field))) {
- return '';
- }
- // 判断是否为配置的忽略字段
- if (this.isIgnoredField(field)) {
- return '';
- }
- // 发现外键
- const foreignKey = this.foreignKeys[table] && this.foreignKeys[table][field] ? this.foreignKeys[table][field] : null;
- const fieldObj = this.tables[table][field];
- if (lodash_1.default.isObject(foreignKey)) {
- fieldObj.foreignKey = foreignKey;
- }
- const fieldName = (0, types_1.recase)(this.options.caseProp, field);
- let str = "@Column({\n";
- const quoteWrapper = '"';
- const unique = fieldObj.unique || fieldObj.foreignKey && fieldObj.foreignKey.isUnique;
- const isSerialKey = (fieldObj.foreignKey && fieldObj.foreignKey.isSerialKey) ||
- this.dialect.isSerialKey && this.dialect.isSerialKey(fieldObj);
- let wroteAutoIncrement = false;
- let wroteTimestamp = false;
- const space = this.space;
- // 列的属性
- let typeStr;
- const fieldAttrs = lodash_1.default.keys(fieldObj);
- fieldAttrs.forEach(attr => {
- // 我们不需要来自postgresql的特殊属性; "unique"被单独处理
- if (attr === "special" || attr === "elementType" || attr === "unique") {
- return true;
- }
- if (isSerialKey && !wroteAutoIncrement) {
- str += space[3] + "autoIncrement: true,\n";
- // 默认使用Postgres的GENERATED作为IDENTITY,而不是SERIAL
- if (this.dialect.name === "postgres" && fieldObj.foreignKey && fieldObj.foreignKey.isPrimaryKey === true &&
- (fieldObj.foreignKey.generation === "ALWAYS" || fieldObj.foreignKey.generation === "BY DEFAULT")) {
- str += space[3] + "autoIncrementIdentity: true,\n";
- }
- wroteAutoIncrement = true;
- }
- if (attr === "foreignKey") { // 外键属性
- if (foreignKey && foreignKey.isForeignKey) {
- str += space[3] + "references: {\n";
- str += space[4] + "model: \'" + fieldObj[attr].foreignSources.target_table + "\',\n";
- str += space[4] + "key: \'" + fieldObj[attr].foreignSources.target_column + "\'\n";
- str += space[3] + "}";
- }
- else {
- return true;
- }
- }
- else if (attr === "references") {
- // covered by foreignKey
- return true;
- }
- else if (attr === "primaryKey") { // 主键属性
- if (fieldObj[attr] === true && (!lodash_1.default.has(fieldObj, 'foreignKey') || !!fieldObj.foreignKey.isPrimaryKey)) {
- str += space[3] + "primaryKey: true";
- }
- else {
- return true;
- }
- }
- else if (attr === "autoIncrement") { // 自动增长属性
- if (fieldObj[attr] === true && !wroteAutoIncrement) {
- str += space[3] + "autoIncrement: true,\n";
- // Resort to Postgres' GENERATED BY DEFAULT AS IDENTITY instead of SERIAL
- if (this.dialect.name === "postgres" && fieldObj.foreignKey && fieldObj.foreignKey.isPrimaryKey === true && (fieldObj.foreignKey.generation === "ALWAYS" || fieldObj.foreignKey.generation === "BY DEFAULT")) {
- str += space[3] + "autoIncrementIdentity: true,\n";
- }
- wroteAutoIncrement = true;
- }
- return true;
- }
- else if (attr === "allowNull") { // 允许为null
- str += space[3] + attr + ": " + fieldObj[attr];
- }
- else if (attr === "defaultValue") { // 有默认值
- let defaultVal = fieldObj.defaultValue;
- if (this.dialect.name === "mssql" && defaultVal && defaultVal.toLowerCase() === '(newid())') {
- defaultVal = null; // disable adding "default value" attribute for UUID fields if generating for MS SQL
- }
- if (this.dialect.name === "mssql" && (["(NULL)", "NULL"].includes(defaultVal) || typeof defaultVal === "undefined")) {
- defaultVal = null; // Override default NULL in MS SQL to javascript null
- }
- if (defaultVal === null || defaultVal === undefined) {
- return true;
- }
- if (isSerialKey) {
- return true; // value generated in the database
- }
- let val_text = defaultVal;
- if (lodash_1.default.isString(defaultVal)) {
- const field_type = fieldObj.type.toLowerCase();
- defaultVal = this.escapeSpecial(defaultVal);
- while (defaultVal.startsWith('(') && defaultVal.endsWith(')')) {
- // remove extra parens around mssql defaults
- defaultVal = defaultVal.replace(/^[(]/, '').replace(/[)]$/, '');
- }
- if (field_type === 'bit(1)' || field_type === 'bit' || field_type === 'boolean') {
- // convert string to boolean
- val_text = /1|true/i.test(defaultVal) ? "true" : "false";
- }
- else if (this.isArray(field_type)) {
- // remove outer {}
- val_text = defaultVal.replace(/^{/, '').replace(/}$/, '');
- if (val_text && this.isString(fieldObj.elementType)) {
- // quote the array elements
- val_text = val_text.split(',').map(s => `"${s}"`).join(',');
- }
- val_text = `[${val_text}]`;
- }
- else if (field_type.match(/^(json)/)) {
- // don't quote json
- val_text = defaultVal;
- }
- else if (field_type === 'uuid' && (defaultVal === 'gen_random_uuid()' || defaultVal === 'uuid_generate_v4()')) {
- val_text = "DataType.UUIDV4";
- }
- else if (defaultVal.match(/\w+\(\)$/)) {
- // replace db function with sequelize function
- val_text = "Sequelize.fn('" + defaultVal.replace(/\(\)$/g, "") + "')";
- }
- else if (this.isNumber(field_type)) {
- if (defaultVal.match(/\(\)/g)) {
- // assume it's a server function if it contains parens
- val_text = "Sequelize.literal('" + defaultVal + "')";
- }
- else {
- // don't quote numbers
- val_text = defaultVal;
- }
- }
- else if (defaultVal.match(/\(\)/g)) {
- // embedded function, pass as literal
- val_text = "Sequelize.literal('" + defaultVal + "')";
- }
- else if (field_type.indexOf('date') === 0 || field_type.indexOf('timestamp') === 0) {
- if (lodash_1.default.includes(['current_timestamp', 'current_date', 'current_time', 'localtime', 'localtimestamp'], defaultVal.toLowerCase())) {
- val_text = "Sequelize.literal('" + defaultVal + "')";
- wroteTimestamp = true;
- }
- else {
- val_text = quoteWrapper + defaultVal + quoteWrapper;
- }
- }
- else {
- val_text = quoteWrapper + defaultVal + quoteWrapper;
- }
- }
- str += space[3] + attr + ": " + val_text;
- }
- else if (attr === "comment" && (!fieldObj[attr] || this.dialect.name === "mssql")) { // 有备注
- return true;
- }
- else {
- let val = null;
- if (attr === "type") {
- val = this.getSqType(fieldObj, attr);
- typeStr = this.getFieldType(fieldObj, attr);
- }
- if (val == null) {
- val = fieldObj[attr];
- val = lodash_1.default.isString(val) ? quoteWrapper + this.escapeSpecial(val) + quoteWrapper : val;
- }
- str += space[3] + attr + ": " + val;
- }
- str += ",\n";
- });
- if (unique) {
- const uniq = lodash_1.default.isString(unique) ? quoteWrapper + unique.replace(/\"/g, '\\"') + quoteWrapper : unique;
- str += space[3] + "unique: " + uniq + ",\n";
- }
- if (field !== fieldName) {
- str += space[3] + "field: '" + field + "',\n";
- }
- // 删除属性选项中的最后一个“,”
- str = str.trim().replace(/,+$/, '') + "\n";
- str = space[2] + str + space[2] + "})\n";
- str += space[2] + this.quoteName(fieldName) + `: ${typeStr};\n\n`;
- this.attrbuitesstr += this.addAttributesMain(this.quoteName(fieldName),typeStr,space[2],wroteAutoIncrement,wroteTimestamp);
- return str;
- }
- /**
- * 添加属性
- * @param {*} table
- * @param {*} field
- */
- addAttributesHeader(entityName,mainStr) {
- let str = `\nexport interface ${entityName}Attributes {\n`;
- str += (mainStr + "}\n");
- return str;
- }
- /**
- * 生成字段属性
- * @param {*} entityName
- * @param {*} fileName
- * @param {*} typeStr
- * @param {*} indexspace
- */
- addAttributesMain(fileName,typeStr,indexspace,iswroteAutoIncrement = false,wroteTimestamp = false) {
- let str = indexspace + fileName +"?:" + typeStr +"\n";
- return str;
- }
- // 添加索引
- addIndexes(table) {
- const indexes = this.indexes[table];
- const space = this.space;
- let str = "";
- if (indexes && indexes.length) {
- str += space[2] + "indexes: [\n";
- indexes.forEach(idx => {
- str += space[3] + "{\n";
- if (idx.name) {
- str += space[4] + `name: "${idx.name}",\n`;
- }
- if (idx.unique) {
- str += space[4] + "unique: true,\n";
- }
- if (idx.type) {
- if (['UNIQUE', 'FULLTEXT', 'SPATIAL'].includes(idx.type)) {
- str += space[4] + `type: "${idx.type}",\n`;
- }
- else {
- str += space[4] + `using: "${idx.type}",\n`;
- }
- }
- str += space[4] + `fields: [\n`;
- idx.fields.forEach(ff => {
- str += space[5] + `{ name: "${ff.attribute}"`;
- if (ff.collate) {
- str += `, collate: "${ff.collate}"`;
- }
- if (ff.length) {
- str += `, length: ${ff.length}`;
- }
- if (ff.order && ff.order !== "ASC") {
- str += `, order: "${ff.order}"`;
- }
- str += " },\n";
- });
- str += space[4] + "]\n";
- str += space[3] + "},\n";
- });
- str += space[2] + "],\n";
- }
- return str;
- }
- getFieldType(fieldObj, attr) {
- let typeStr = 'number';
- const attrValue = fieldObj[attr];
- if (!attrValue.toLowerCase) {
- console.log("attrValue", attr, attrValue);
- return attrValue;
- }
- const type = attrValue.toLowerCase();
- let typematch = null;
- if (type === "boolean" || type === "bit(1)" || type === "bit" || type === "tinyint(1)") {
- typeStr = 'boolean';
- }
- else if (typematch = type.match(/^(bigint|smallint|mediumint|tinyint|int)/)) {
- typeStr = 'number';
- }
- else if (type === 'nvarchar(max)' || type === 'varchar(max)') {
- typeStr = 'string';
- }
- else if (type.match(/n?varchar|string|varying/)) {
- typeStr = 'string';
- }
- else if (type.match(/^n?char/)) {
- typeStr = 'string';
- }
- else if (type.match(/text$/)) {
- typeStr = 'string';
- }
- else if (type === "date") {
- typeStr = 'string';
- }
- else if (type.match(/^(date|timestamp|year)/)) {
- typeStr = 'string';
- }
- else if (type.match(/^(time)/)) {
- typeStr = 'string';
- }
- else if (type.match(/^(float|float4)/)) {
- typeStr = 'number';
- }
- else if (type.match(/^(decimal|numeric)/)) {
- typeStr = 'number';
- }
- else if (type.match(/^money/)) {
- typeStr = 'number';
- }
- else if (type.match(/^smallmoney/)) {
- typeStr = 'number';
- }
- else if (type.match(/^(float8|double)/)) {
- typeStr = 'number';
- }
- else if (type.match(/^uuid|uniqueidentifier/)) {
- typeStr = 'string';
- }
- else if (type.match(/^jsonb/)) {
- typeStr = 'string';
- }
- else if (type.match(/^json/)) {
- typeStr = 'string';
- }
- return typeStr;
- }
- // 从字段中获取sequelize类型
- getSqType(fieldObj, attr) {
- let typeStr = '';
- const attrValue = fieldObj[attr];
- if (!attrValue.toLowerCase) {
- console.log("attrValue", attr, attrValue);
- return attrValue;
- }
- const type = attrValue.toLowerCase();
- const length = type.match(/\(\d+\)/);
- const precision = type.match(/\(\d+,\d+\)/);
- let val = null;
- let typematch = null;
- if (type === "boolean" || type === "bit(1)" || type === "bit" || type === "tinyint(1)") {
- val = 'DataType.BOOLEAN';
- // postgres range types
- }
- else if (type === "numrange") {
- val = 'DataType.RANGE(DataType.DECIMAL)';
- }
- else if (type === "int4range") {
- val = 'DataType.RANGE(DataType.INTEGER)';
- }
- else if (type === "int8range") {
- val = 'DataType.RANGE(DataType.BIGINT)';
- }
- else if (type === "daterange") {
- val = 'DataType.RANGE(DataType.DATEONLY)';
- }
- else if (type === "tsrange" || type === "tstzrange") {
- val = 'DataType.RANGE(DataType.DATE)';
- }
- else if (typematch = type.match(/^(bigint|smallint|mediumint|tinyint|int)/)) {
- // integer subtypes
- val = 'DataType.' + (typematch[0] === 'int' ? 'INTEGER' : typematch[0].toUpperCase());
- if (/unsigned/i.test(type)) {
- val += '.UNSIGNED';
- }
- if (/zerofill/i.test(type)) {
- val += '.ZEROFILL';
- }
- }
- else if (type === 'nvarchar(max)' || type === 'varchar(max)') {
- val = 'DataType.TEXT';
- }
- else if (type.match(/n?varchar|string|varying/)) {
- val = 'DataType.STRING' + (!lodash_1.default.isNull(length) ? length : '');
- }
- else if (type.match(/^n?char/)) {
- val = 'DataType.CHAR' + (!lodash_1.default.isNull(length) ? length : '');
- }
- else if (type.match(/^real/)) {
- val = 'DataType.REAL';
- }
- else if (type.match(/text$/)) {
- val = 'DataType.TEXT' + (!lodash_1.default.isNull(length) ? length : '');
- }
- else if (type === "date") {
- val = 'DataType.DATEONLY';
- }
- else if (type.match(/^(date|timestamp|year)/)) {
- val = 'DataType.DATE' + (!lodash_1.default.isNull(length) ? length : '');
- }
- else if (type.match(/^(time)/)) {
- val = 'DataType.TIME';
- }
- else if (type.match(/^(float|float4)/)) {
- val = 'DataType.FLOAT' + (!lodash_1.default.isNull(precision) ? precision : '');
- }
- else if (type.match(/^(decimal|numeric)/)) {
- val = 'DataType.DECIMAL' + (!lodash_1.default.isNull(precision) ? precision : '');
- }
- else if (type.match(/^money/)) {
- val = 'DataType.DECIMAL(19,4)';
- }
- else if (type.match(/^smallmoney/)) {
- val = 'DataType.DECIMAL(10,4)';
- }
- else if (type.match(/^(float8|double)/)) {
- val = 'DataType.DOUBLE' + (!lodash_1.default.isNull(precision) ? precision : '');
- }
- else if (type.match(/^uuid|uniqueidentifier/)) {
- val = 'DataType.UUID';
- }
- else if (type.match(/^jsonb/)) {
- val = 'DataType.JSONB';
- }
- else if (type.match(/^json/)) {
- val = 'DataType.JSON';
- }
- else if (type.match(/^geometry/)) {
- const gtype = fieldObj.elementType ? `(${fieldObj.elementType})` : '';
- val = `DataType.GEOMETRY${gtype}`;
- }
- else if (type.match(/^geography/)) {
- const gtype = fieldObj.elementType ? `(${fieldObj.elementType})` : '';
- val = `DataType.GEOGRAPHY${gtype}`;
- }
- else if (type.match(/^array/)) {
- const eltype = this.getSqType(fieldObj, "elementType");
- val = `DataType.ARRAY(${eltype})`;
- }
- else if (type.match(/(binary|image|blob|bytea)/)) {
- val = 'DataType.BLOB';
- }
- else if (type.match(/^hstore/)) {
- val = 'DataType.HSTORE';
- }
- else if (type.match(/^inet/)) {
- val = 'DataType.INET';
- }
- else if (type.match(/^cidr/)) {
- val = 'DataType.CIDR';
- }
- else if (type.match(/^oid/)) {
- val = 'DataType.INTEGER';
- }
- else if (type.match(/^macaddr/)) {
- val = 'DataType.MACADDR';
- }
- else if (type.match(/^enum(\(.*\))?$/)) {
- const enumValues = this.getEnumValues(fieldObj);
- val = `DataType.ENUM(${enumValues})`;
- }
- return val;
- }
- getTypeScriptPrimaryKeys(table) {
- const fields = lodash_1.default.keys(this.tables[table]);
- return fields.filter((field) => {
- const fieldObj = this.tables[table][field];
- return fieldObj['primaryKey'];
- });
- }
- getTypeScriptCreationOptionalFields(table) {
- const fields = lodash_1.default.keys(this.tables[table]);
- return fields.filter((field) => {
- const fieldObj = this.tables[table][field];
- return fieldObj.allowNull || (!!fieldObj.defaultValue || fieldObj.defaultValue === "") || fieldObj.autoIncrement
- || this.isTimestampField(field);
- });
- }
- /** Add schema to table so it will match the relation data. Fixes mysql problem. */
- addSchemaForRelations(table) {
- if (!table.includes('.') && !this.relations.some(rel => rel.childTable === table)) {
- // if no tables match the given table, then assume we need to fix the schema
- const first = this.relations.find(rel => !!rel.childTable);
- if (first) {
- const [schemaName, tableName] = (0, types_1.qNameSplit)(first.childTable);
- if (schemaName) {
- table = (0, types_1.qNameJoin)(schemaName, table);
- }
- }
- }
- return table;
- }
- addTypeScriptAssociationMixins(table) {
- const sp = this.space[1];
- const needed = {};
- let str = '';
- table = this.addSchemaForRelations(table);
- this.relations.forEach(rel => {
- var _a, _b, _c;
- var _d, _e;
- if (!rel.isM2M) {
- if (rel.childTable === table) {
- // current table is a child that belongsTo parent
- const pparent = lodash_1.default.upperFirst(rel.parentProp);
- str += `${sp}// ${rel.childModel} belongsTo ${rel.parentModel} via ${rel.parentId}\n`;
- str += `${sp}${rel.parentProp}!: ${rel.parentModel};\n`;
- str += `${sp}get${pparent}!: Sequelize.BelongsToGetAssociationMixin<${rel.parentModel}>;\n`;
- str += `${sp}set${pparent}!: Sequelize.BelongsToSetAssociationMixin<${rel.parentModel}, ${rel.parentModel}Id>;\n`;
- str += `${sp}create${pparent}!: Sequelize.BelongsToCreateAssociationMixin<${rel.parentModel}>;\n`;
- (_a = needed[_d = rel.parentTable]) !== null && _a !== void 0 ? _a : (needed[_d] = new Set());
- needed[rel.parentTable].add(rel.parentModel);
- needed[rel.parentTable].add(rel.parentModel + 'Id');
- }
- else if (rel.parentTable === table) {
- (_b = needed[_e = rel.childTable]) !== null && _b !== void 0 ? _b : (needed[_e] = new Set());
- const pchild = lodash_1.default.upperFirst(rel.childProp);
- if (rel.isOne) {
- // const hasModelSingular = singularize(hasModel);
- str += `${sp}// ${rel.parentModel} hasOne ${rel.childModel} via ${rel.parentId}\n`;
- str += `${sp}${rel.childProp}!: ${rel.childModel};\n`;
- str += `${sp}get${pchild}!: Sequelize.HasOneGetAssociationMixin<${rel.childModel}>;\n`;
- str += `${sp}set${pchild}!: Sequelize.HasOneSetAssociationMixin<${rel.childModel}, ${rel.childModel}Id>;\n`;
- str += `${sp}create${pchild}!: Sequelize.HasOneCreateAssociationMixin<${rel.childModel}>;\n`;
- needed[rel.childTable].add(rel.childModel);
- needed[rel.childTable].add(`${rel.childModel}Id`);
- needed[rel.childTable].add(`${rel.childModel}CreationAttributes`);
- }
- else {
- const hasModel = rel.childModel;
- const sing = lodash_1.default.upperFirst((0, types_1.singularize)(rel.childProp));
- const lur = (0, types_1.pluralize)(rel.childProp);
- const plur = lodash_1.default.upperFirst(lur);
- str += `${sp}// ${rel.parentModel} hasMany ${rel.childModel} via ${rel.parentId}\n`;
- str += `${sp}${lur}!: ${rel.childModel}[];\n`;
- str += `${sp}get${plur}!: Sequelize.HasManyGetAssociationsMixin<${hasModel}>;\n`;
- str += `${sp}set${plur}!: Sequelize.HasManySetAssociationsMixin<${hasModel}, ${hasModel}Id>;\n`;
- str += `${sp}add${sing}!: Sequelize.HasManyAddAssociationMixin<${hasModel}, ${hasModel}Id>;\n`;
- str += `${sp}add${plur}!: Sequelize.HasManyAddAssociationsMixin<${hasModel}, ${hasModel}Id>;\n`;
- str += `${sp}create${sing}!: Sequelize.HasManyCreateAssociationMixin<${hasModel}>;\n`;
- str += `${sp}remove${sing}!: Sequelize.HasManyRemoveAssociationMixin<${hasModel}, ${hasModel}Id>;\n`;
- str += `${sp}remove${plur}!: Sequelize.HasManyRemoveAssociationsMixin<${hasModel}, ${hasModel}Id>;\n`;
- str += `${sp}has${sing}!: Sequelize.HasManyHasAssociationMixin<${hasModel}, ${hasModel}Id>;\n`;
- str += `${sp}has${plur}!: Sequelize.HasManyHasAssociationsMixin<${hasModel}, ${hasModel}Id>;\n`;
- str += `${sp}count${plur}!: Sequelize.HasManyCountAssociationsMixin;\n`;
- needed[rel.childTable].add(hasModel);
- needed[rel.childTable].add(`${hasModel}Id`);
- }
- }
- }
- else {
- // rel.isM2M
- if (rel.parentTable === table) {
- // many-to-many
- const isParent = (rel.parentTable === table);
- const thisModel = isParent ? rel.parentModel : rel.childModel;
- const otherModel = isParent ? rel.childModel : rel.parentModel;
- const otherModelSingular = lodash_1.default.upperFirst((0, types_1.singularize)(isParent ? rel.childProp : rel.parentProp));
- const lotherModelPlural = (0, types_1.pluralize)(isParent ? rel.childProp : rel.parentProp);
- const otherModelPlural = lodash_1.default.upperFirst(lotherModelPlural);
- const otherTable = isParent ? rel.childTable : rel.parentTable;
- str += `${sp}// ${thisModel} belongsToMany ${otherModel} via ${rel.parentId} and ${rel.childId}\n`;
- str += `${sp}${lotherModelPlural}!: ${otherModel}[];\n`;
- str += `${sp}get${otherModelPlural}!: Sequelize.BelongsToManyGetAssociationsMixin<${otherModel}>;\n`;
- str += `${sp}set${otherModelPlural}!: Sequelize.BelongsToManySetAssociationsMixin<${otherModel}, ${otherModel}Id>;\n`;
- str += `${sp}add${otherModelSingular}!: Sequelize.BelongsToManyAddAssociationMixin<${otherModel}, ${otherModel}Id>;\n`;
- str += `${sp}add${otherModelPlural}!: Sequelize.BelongsToManyAddAssociationsMixin<${otherModel}, ${otherModel}Id>;\n`;
- str += `${sp}create${otherModelSingular}!: Sequelize.BelongsToManyCreateAssociationMixin<${otherModel}>;\n`;
- str += `${sp}remove${otherModelSingular}!: Sequelize.BelongsToManyRemoveAssociationMixin<${otherModel}, ${otherModel}Id>;\n`;
- str += `${sp}remove${otherModelPlural}!: Sequelize.BelongsToManyRemoveAssociationsMixin<${otherModel}, ${otherModel}Id>;\n`;
- str += `${sp}has${otherModelSingular}!: Sequelize.BelongsToManyHasAssociationMixin<${otherModel}, ${otherModel}Id>;\n`;
- str += `${sp}has${otherModelPlural}!: Sequelize.BelongsToManyHasAssociationsMixin<${otherModel}, ${otherModel}Id>;\n`;
- str += `${sp}count${otherModelPlural}!: Sequelize.BelongsToManyCountAssociationsMixin;\n`;
- (_c = needed[otherTable]) !== null && _c !== void 0 ? _c : (needed[otherTable] = new Set());
- needed[otherTable].add(otherModel);
- needed[otherTable].add(`${otherModel}Id`);
- }
- }
- });
- if (needed[table]) {
- delete needed[table]; // don't add import for self
- }
- return { needed, str };
- }
- addTypeScriptFields(table, isInterface) {
- const sp = this.space[1];
- const fields = lodash_1.default.keys(this.tables[table]);
- const notNull = isInterface ? '' : '!';
- let str = '';
- fields.forEach(field => {
- if (!this.options.skipFields || !this.options.skipFields.includes(field)) {
- const name = this.quoteName((0, types_1.recase)(this.options.caseProp, field));
- const isOptional = this.getTypeScriptFieldOptional(table, field);
- str += `${sp}${name}${isOptional ? '?' : notNull}: ${this.getTypeScriptType(table, field)};\n`;
- }
- });
- return str;
- }
- getTypeScriptFieldOptional(table, field) {
- const fieldObj = this.tables[table][field];
- return fieldObj.allowNull;
- }
- getTypeScriptType(table, field) {
- const fieldObj = this.tables[table][field];
- return this.getTypeScriptFieldType(fieldObj, "type");
- }
- getTypeScriptFieldType(fieldObj, attr) {
- const rawFieldType = fieldObj[attr] || '';
- const fieldType = String(rawFieldType).toLowerCase();
- let jsType;
- if (this.isArray(fieldType)) {
- const eltype = this.getTypeScriptFieldType(fieldObj, "elementType");
- jsType = eltype + '[]';
- }
- else if (this.isNumber(fieldType)) {
- jsType = 'number';
- }
- else if (this.isBoolean(fieldType)) {
- jsType = 'boolean';
- }
- else if (this.isDate(fieldType)) {
- jsType = 'Date';
- }
- else if (this.isString(fieldType)) {
- jsType = 'string';
- }
- else if (this.isEnum(fieldType)) {
- const values = this.getEnumValues(fieldObj);
- jsType = values.join(' | ');
- }
- else if (this.isJSON(fieldType)) {
- jsType = 'object';
- }
- else {
- console.log(`Missing TypeScript type: ${fieldType || fieldObj['type']}`);
- jsType = 'any';
- }
- return jsType;
- }
- getEnumValues(fieldObj) {
- if (fieldObj.special) {
- // postgres
- return fieldObj.special.map((v) => `"${v}"`);
- }
- else {
- // mysql
- return fieldObj.type.substring(5, fieldObj.type.length - 1).split(',');
- }
- }
- isTimestampField(field) {
- const additional = this.options.additional;
- if (additional.timestamps === false) {
- return false;
- }
- return ((!additional.createdAt && (0, types_1.recase)('c', field) === 'createdAt') || additional.createdAt === field)
- || ((!additional.updatedAt && (0, types_1.recase)('c', field) === 'updatedAt') || additional.updatedAt === field);
- }
- isParanoidField(field) {
- const additional = this.options.additional;
- if (additional.timestamps === false || additional.paranoid === false) {
- return false;
- }
- return ((!additional.deletedAt && (0, types_1.recase)('c', field) === 'deletedAt') || additional.deletedAt === field);
- }
- isIgnoredField(field) {
- return (this.options.skipFields && this.options.skipFields.includes(field));
- }
- escapeSpecial(val) {
- if (typeof (val) !== "string") {
- return val;
- }
- return val
- .replace(/[\\]/g, '\\\\')
- .replace(/[\"]/g, '\\"')
- .replace(/[\/]/g, '\\/')
- .replace(/[\b]/g, '\\b')
- .replace(/[\f]/g, '\\f')
- .replace(/[\n]/g, '\\n')
- .replace(/[\r]/g, '\\r')
- .replace(/[\t]/g, '\\t');
- }
- /** Quote the name if it is not a valid identifier */
- quoteName(name) {
- return (/^[$A-Z_][0-9A-Z_$]*$/i.test(name) ? name : "'" + name + "'");
- }
- isNumber(fieldType) {
- return /^(smallint|mediumint|tinyint|int|bigint|float|money|smallmoney|double|decimal|numeric|real|oid)/.test(fieldType);
- }
- isBoolean(fieldType) {
- return /^(boolean|bit)/.test(fieldType);
- }
- isDate(fieldType) {
- return /^(datetime|timestamp)/.test(fieldType);
- }
- isString(fieldType) {
- return /^(char|nchar|string|varying|varchar|nvarchar|text|longtext|mediumtext|tinytext|ntext|uuid|uniqueidentifier|date|time|inet|cidr|macaddr)/.test(fieldType);
- }
- isArray(fieldType) {
- return /(^array)|(range$)/.test(fieldType);
- }
- isEnum(fieldType) {
- return /^(enum)/.test(fieldType);
- }
- isJSON(fieldType) {
- return /^(json|jsonb)/.test(fieldType);
- }
- }
- exports.AutoGenerator = AutoGenerator;
- //# sourceMappingURL=auto-generator.js.map
|