@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.
141 lines (140 loc) • 5.74 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AssociationsParser = void 0;
const fs_1 = __importDefault(require("fs"));
const cardinalities = new Set([
'1:1',
'1:N',
'N:N'
]);
const validateRow = (row) => {
const [cardinality, leftkey, rightKey, leftTable, rightTable, joinTable, leftAlias, rightAlias] = row;
if (!cardinalities.has(cardinality)) {
throw new Error(`Invalid cardinality: must be one of (${Array.from(cardinalities).join(', ')}). Received ${cardinality}`);
}
if (!leftkey || !leftkey.length) {
throw new Error(`Missing required leftKey in association row`);
}
if (!rightKey || !rightKey.length) {
throw new Error(`Missing required rightKey in association row`);
}
if (!leftTable || !leftTable.length) {
throw new Error(`Missing required leftTable in association row`);
}
if (!rightTable || !rightTable.length) {
throw new Error(`Missing required rightTable in association row`);
}
if (cardinality === 'N:N' && (!joinTable || !joinTable.length)) {
throw new Error(`Association N:N requires a joinTable in the association row`);
}
// Validate aliases are not empty strings if provided
if (leftAlias !== undefined && leftAlias.length === 0) {
throw new Error(`Left alias cannot be empty string. Use undefined or omit the field instead.`);
}
if (rightAlias !== undefined && rightAlias.length === 0) {
throw new Error(`Right alias cannot be empty string. Use undefined or omit the field instead.`);
}
};
/**
* @class AssociationsParser
*/
class AssociationsParser {
/**
* Parse associations file
* @param {string} path
* @returns {IAssociationsParsed}
*/
static parse(path) {
// Return cached value if already set
if (this.associationsMetadata) {
return this.associationsMetadata;
}
const associationsMetadata = {};
const lines = fs_1.default.readFileSync(path)
.toString()
.split('\n')
.filter(line => line.length); // Filter empty lines
for (const line of lines) {
const row = line
.split(',')
.map((t, i) => i === 0 ? t.toUpperCase() : t) // Capitalize cardinality
.map(t => t.trim());
validateRow(row);
const [cardinality, leftKey, rightKey, leftModel, rightModel, joinModel, leftAlias, rightAlias] = row;
const [leftCardinality, rightCardinality] = cardinality.split(':');
// Add entry for left table
if (!associationsMetadata[leftModel]) {
associationsMetadata[leftModel] = {
foreignKeys: [],
associations: [],
};
}
// Add entry for right table
if (!associationsMetadata[rightModel]) {
associationsMetadata[rightModel] = {
foreignKeys: [],
associations: [],
};
}
// 1:1 and 1:N association
if (cardinality !== 'N:N') {
// Left model association (HasOne/HasMany)
associationsMetadata[leftModel].associations.push({
associationName: rightCardinality === '1' ? 'HasOne' : 'HasMany',
targetModel: rightModel,
sourceKey: leftKey,
...(leftAlias && { alias: leftAlias })
});
// Right model association (BelongsTo)
associationsMetadata[rightModel].associations.push({
associationName: 'BelongsTo',
targetModel: leftModel,
...(rightAlias && { alias: rightAlias })
});
associationsMetadata[rightModel].foreignKeys.push({
name: rightKey,
targetModel: leftModel,
});
}
// N:N association
else {
// Add entry for join table
if (!associationsMetadata[joinModel]) {
associationsMetadata[joinModel] = {
foreignKeys: [],
associations: [],
};
}
// Left model BelongsToMany association
associationsMetadata[leftModel].associations.push({
associationName: 'BelongsToMany',
targetModel: rightModel,
joinModel: joinModel,
...(leftAlias && { alias: leftAlias })
});
// Right model BelongsToMany association
associationsMetadata[rightModel].associations.push({
associationName: 'BelongsToMany',
targetModel: leftModel,
joinModel: joinModel,
...(rightAlias && { alias: rightAlias })
});
associationsMetadata[joinModel].foreignKeys.push({
name: leftKey,
targetModel: leftModel
});
associationsMetadata[joinModel].foreignKeys.push({
name: rightKey,
targetModel: rightModel
});
}
}
// Cache result
this.associationsMetadata = associationsMetadata;
return this.associationsMetadata;
}
}
exports.AssociationsParser = AssociationsParser;