@jsindos/sequelize-typescript-generator
Version:
Automatically generates typescript models compatible with sequelize-typescript library (https://www.npmjs.com/package/sequelize-typescript) directly from your source database.
261 lines (260 loc) • 10.1 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateArgs = exports.buildDialect = exports.buildConfig = exports.parseCase = exports.error = exports.aliasesMap = exports.defaultOutputDir = void 0;
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const Dialect_1 = require("../dialects/Dialect");
const dialects_1 = require("../dialects");
const IConfig_1 = require("../config/IConfig");
exports.defaultOutputDir = 'output-models';
exports.aliasesMap = {
HOST: 'host',
PORT: 'port',
DATABASE: 'database',
DIALECT: 'dialect',
SCHEMA: 'schema',
USERNAME: 'username',
PASSWORD: 'password',
TABLES: 'tables',
SKIP_TABLES: 'skip-tables',
OUTPUT_DIR: 'out-dir',
OUTPUT_DIR_CLEAN: 'clean',
INDICES: 'indices',
TIMESTAMPS: 'timestamps',
CASE: 'case',
STORAGE: 'storage',
LINT_FILE: 'lint-file',
SSL: 'ssl',
PROTOCOL: 'protocol',
ASSOCIATIONS_FILE: 'associations-file',
ENABLE_SEQUELIZE_LOGS: 'logs',
DIALECT_OPTIONS: 'dialect-options',
DIALECT_OPTIONS_FILE: 'dialect-options-file',
DISABLE_STRICT: 'no-strict',
DISABLE_VIEWS: 'no-views',
};
/**
* Diplay error message and exit
* @param {string} msg
* @returns {void}
*/
const error = (msg) => {
console.error('[ValidationError]', msg);
process.exit(1);
};
exports.error = error;
/**
* Parse case argument
* @param {string} arg
* @returns { TransformCase | TransformMap }
*/
const parseCase = (arg) => {
if (arg.includes(':')) {
const tokens = arg.split(':');
const modelCase = tokens[0].toUpperCase();
const columnCase = tokens[1].toUpperCase();
return {
[IConfig_1.TransformTarget.MODEL]: modelCase,
[IConfig_1.TransformTarget.COLUMN]: columnCase
};
}
return arg.toUpperCase();
};
exports.parseCase = parseCase;
/**
* Parse dialect options from json string
* @param {string} json
* @returns {object} Dialect options object
*/
const buildDialectOptionsFromString = (json) => {
let parsed;
try {
parsed = JSON.parse(json);
}
catch (err) {
console.error(`Invalid json for argument --dialect-options`, err);
process.exit(1);
}
return parsed;
};
/**
* Parse dialect options from json file
* @param {string} path
* @returns {object} Dialect options object
*/
const buildDialectOptionsFromFile = (path) => {
let content;
let parsed;
try {
content = fs_1.default.readFileSync(path).toString();
}
catch (err) {
(0, exports.error)(`Argument -f [--dialect-options-file] '${path}' is not a valid path`);
}
try {
parsed = JSON.parse(content);
}
catch (err) {
console.error(`Invalid json for argument --dialect-options`, err);
process.exit(1);
}
return parsed;
};
/**
* Build config object from parsed arguments
* @param { [key: string]: any } argv
* Returns {IConfig}
*/
const buildConfig = (argv) => {
var _a;
const config = {
connection: {
dialect: argv[exports.aliasesMap.DIALECT],
...argv[exports.aliasesMap.HOST] && { host: argv[exports.aliasesMap.HOST] },
...argv[exports.aliasesMap.PORT] && { port: argv[exports.aliasesMap.PORT] },
...argv[exports.aliasesMap.DATABASE] && { database: argv[exports.aliasesMap.DATABASE] },
...argv[exports.aliasesMap.USERNAME] && { username: argv[exports.aliasesMap.USERNAME] },
...argv[exports.aliasesMap.PASSWORD] && { password: argv[exports.aliasesMap.PASSWORD] },
...argv[exports.aliasesMap.SSL] && { ssl: true },
...argv[exports.aliasesMap.PROTOCOL] && { protocol: argv[exports.aliasesMap.PROTOCOL] },
...argv[exports.aliasesMap.DIALECT] === 'mariadb' && { dialectOptions: {
timezone: 'Etc/GMT-3',
}
},
...argv[exports.aliasesMap.DIALECT] === 'sqlite' && {
storage: (_a = argv[exports.aliasesMap.STORAGE]) !== null && _a !== void 0 ? _a : 'memory',
},
...argv[exports.aliasesMap.DIALECT_OPTIONS_FILE] && {
dialectOptions: buildDialectOptionsFromFile(argv[exports.aliasesMap.DIALECT_OPTIONS_FILE]),
},
...argv[exports.aliasesMap.DIALECT_OPTIONS] && {
dialectOptions: buildDialectOptionsFromString(argv[exports.aliasesMap.DIALECT_OPTIONS]),
},
logQueryParameters: true,
logging: argv[exports.aliasesMap.ENABLE_SEQUELIZE_LOGS],
},
metadata: {
...argv[exports.aliasesMap.SCHEMA] && { schema: argv[exports.aliasesMap.SCHEMA] },
...argv[exports.aliasesMap.TABLES] && {
tables: argv[exports.aliasesMap.TABLES]
.split(',')
.map(tableName => tableName.toLowerCase())
},
...argv[exports.aliasesMap.SKIP_TABLES] && {
skipTables: argv[exports.aliasesMap.SKIP_TABLES]
.split(',')
.map(tableName => tableName.toLowerCase())
},
indices: !!argv[exports.aliasesMap.INDICES],
timestamps: !!argv[exports.aliasesMap.TIMESTAMPS],
...argv[exports.aliasesMap.CASE] && { case: (0, exports.parseCase)(argv[exports.aliasesMap.CASE]) },
...argv[exports.aliasesMap.ASSOCIATIONS_FILE] && { associationsFile: argv[exports.aliasesMap.ASSOCIATIONS_FILE] },
noViews: !!argv[exports.aliasesMap.DISABLE_VIEWS],
},
output: {
outDir: argv[exports.aliasesMap.OUTPUT_DIR] ?
path_1.default.isAbsolute(argv[exports.aliasesMap.OUTPUT_DIR]) ?
argv[exports.aliasesMap.OUTPUT_DIR]
: path_1.default.join(process.cwd(), argv[exports.aliasesMap.OUTPUT_DIR])
: path_1.default.join(process.cwd(), exports.defaultOutputDir),
clean: !!argv[exports.aliasesMap.OUTPUT_DIR_CLEAN],
},
strict: !(!!argv[exports.aliasesMap.DISABLE_STRICT]),
...argv[exports.aliasesMap.LINT_FILE] && {
lintOptions: {
configFile: argv[exports.aliasesMap.LINT_FILE],
fix: true,
}
},
};
return config;
};
exports.buildConfig = buildConfig;
/**
* Build dialect object from parsed arguments
* @param { [key: string]: any } argv
* Returns {Dialect}
*/
const buildDialect = (argv) => {
let dialect;
switch (argv[exports.aliasesMap.DIALECT]) {
case 'postgres':
dialect = new dialects_1.DialectPostgres();
break;
case 'mysql':
dialect = new dialects_1.DialectMySQL();
break;
case 'mariadb':
dialect = new dialects_1.DialectMariaDB();
break;
case 'sqlite':
dialect = new dialects_1.DialectSQLite();
break;
case 'mssql':
dialect = new dialects_1.DialectMSSQL();
break;
default:
(0, exports.error)(`Unknown dialect ${argv[exports.aliasesMap.DIALECT]}`);
}
return dialect;
};
exports.buildDialect = buildDialect;
/**
* Validate arguments
* @param { [key: string]: any } argv
* @returns {void}
*/
const validateArgs = (argv) => {
// Validate dialect
if (!Dialect_1.Dialect.dialects.has(argv[exports.aliasesMap.DIALECT])) {
(0, exports.error)(`Required argument -D <dialect> must be one of (${Array.from(Dialect_1.Dialect.dialects).join(', ')})`);
}
// Validate database
if (argv[exports.aliasesMap.DIALECT] !== 'sqlite' && !argv[exports.aliasesMap.DATABASE]) {
(0, exports.error)(`Argument -d [database] is required for dialect ${argv[exports.aliasesMap.DIALECT]}`);
}
// Validate port
if (argv[exports.aliasesMap.PORT] && (!Number.isInteger(argv[exports.aliasesMap.PORT]) || argv[exports.aliasesMap.PORT] <= 0)) {
(0, exports.error)(`Argument -p [port] must be a positive integer (${argv[exports.aliasesMap.PORT]})`);
}
// Validate case
if (argv[exports.aliasesMap.CASE]) {
if (argv[exports.aliasesMap.CASE].includes(':')) {
const tokens = argv[exports.aliasesMap.CASE].split(':');
const modelCase = tokens[0].toUpperCase();
const columnCase = tokens[1].toUpperCase();
if (!IConfig_1.TransformCases.has(modelCase)) {
(0, exports.error)(`Unknown case '${modelCase}': must be one of (${Array.from(IConfig_1.TransformCases).join(', ').toLowerCase()})`);
}
if (!IConfig_1.TransformCases.has(columnCase)) {
(0, exports.error)(`Unknown case '${columnCase}': must be one of (${Array.from(IConfig_1.TransformCases).join(', ').toLowerCase()})`);
}
}
else if (!IConfig_1.TransformCases.has(argv[exports.aliasesMap.CASE].toUpperCase())) {
(0, exports.error)(`Argument -c [case] must be one of (${Array.from(IConfig_1.TransformCases).join(', ').toLowerCase()})`);
}
}
// Validate lint file
if (argv[exports.aliasesMap.LINT_FILE]) {
try {
fs_1.default.accessSync(argv[exports.aliasesMap.LINT_FILE]);
}
catch (err) {
(0, exports.error)(`Argument -L [lint-file] '${argv[exports.aliasesMap.LINT_FILE]}' is not a valid path`);
}
}
// Validate associations file
if (argv[exports.aliasesMap.ASSOCIATIONS_FILE]) {
try {
fs_1.default.accessSync(argv[exports.aliasesMap.ASSOCIATIONS_FILE]);
}
catch (err) {
(0, exports.error)(`Argument -a [associations-file] '${argv[exports.aliasesMap.ASSOCIATIONS_FILE]}' is not a valid path`);
}
}
// TODO Validate schema if dialect is postgres ?
};
exports.validateArgs = validateArgs;