UNPKG

entity-baker

Version:

Generates simple and powerful entity classes for ORM systems, like Doctrine and/or Entity Framework.

377 lines 14.2 kB
"use strict"; /** * This file is part of the node-entity-baker distribution. * Copyright (c) Marcel Joachim Kloubert. * * node-entity-baker is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, version 3. * * node-entity-baker is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const eb_lib_doctrine = require("./doctrine"); const eb_lib_ef = require("./ef"); const eb_lib_ef_core = require("./efcore"); const eb_lib_helpers = require("./helpers"); const Enumerable = require("node-enumerable"); const Path = require("path"); /** * List of known frameworks. */ var EntityFramework; (function (EntityFramework) { /** * Doctrine (PHP) */ EntityFramework[EntityFramework["Doctrine"] = 1] = "Doctrine"; /** * Microsoft's Entity Framework */ EntityFramework[EntityFramework["EntityFramework"] = 2] = "EntityFramework"; /** * Microsoft's Entity Framework Core */ EntityFramework[EntityFramework["EntityFrameworkCore"] = 3] = "EntityFrameworkCore"; })(EntityFramework = exports.EntityFramework || (exports.EntityFramework = {})); /** * The default name of an entity file. */ exports.DEFAULT_ENTITY_FILE = 'entities.json'; // data types exports.TYPE__DEFAULT = ''; exports.TYPE_BIGINT = 'bigint'; exports.TYPE_BIN = 'bin'; exports.TYPE_BINARY = 'binary'; exports.TYPE_BLOB = 'blob'; exports.TYPE_BOOL = 'bool'; exports.TYPE_BOOLEAN = 'boolean'; exports.TYPE_DATE = 'date'; exports.TYPE_DATETIME = 'datetime'; exports.TYPE_DATETIME_TZ = 'datetimetz'; exports.TYPE_FLOAT = 'float'; exports.TYPE_DECIMAL = 'decimal'; exports.TYPE_GUID = 'guid'; exports.TYPE_INT = 'int'; exports.TYPE_INT16 = 'int16'; exports.TYPE_INT32 = 'int32'; exports.TYPE_INTEGER = 'integer'; exports.TYPE_INT64 = 'int64'; exports.TYPE_JSON = 'json'; exports.TYPE_SMALLINT = 'smallint'; exports.TYPE_STR = 'str'; exports.TYPE_STRING = 'string'; exports.TYPE_TEXT = 'text'; exports.TYPE_TIME = 'time'; exports.TYPE_UINT16 = 'int16'; exports.TYPE_UINT32 = 'int32'; exports.TYPE_UINT64 = 'int64'; exports.TYPE_UUID = 'uuid'; /** * An entity compiler. */ class EntityCompiler { /** * Initializes a new instance of that class. * * @param {EntityCompilerOptions} [options] Options for compilation operations. */ constructor(options) { this.options = options; if (!this.options) { this.options = {}; } } /** * Compiles entities. * * @return {Promise<EntityCompilerResult>} The promise with the result. */ compile() { return __awaiter(this, void 0, void 0, function* () { const RESULT = {}; let cwd = eb_lib_helpers.toStringSafe(this.options.cwd); if (eb_lib_helpers.isEmptyString(cwd)) { cwd = process.cwd(); } if (!Path.isAbsolute(cwd)) { cwd = Path.join(process.cwd(), cwd); } cwd = Path.resolve(cwd); let outDir = eb_lib_helpers.toStringSafe(this.options.outDir); if (eb_lib_helpers.isEmptyString(cwd)) { outDir = cwd; } if (!Path.isAbsolute(outDir)) { outDir = Path.join(cwd, outDir); } outDir = Path.resolve(outDir); const FILE = this.options.file; if (eb_lib_helpers.isObj(FILE)) { const NAMESPACE = eb_lib_helpers.toStringSafe(FILE['namespace']).split('.').map(x => { return x.trim(); }).filter(x => { return '' !== x; }); const ENTITIES = FILE.entities; if (eb_lib_helpers.isObj(ENTITIES)) { let callbacks = this.options.callbacks; if (!callbacks) { callbacks = {}; } yield this.compileEntities(NAMESPACE, ENTITIES, callbacks, outDir); } } return RESULT; }); } /** * Compiles entities. * * @param {string[]} ns The namespace without dots. * @param {EntityDescriptions} entities The entities. * @param {CompilerCallbacks} callbacks Callbacks. * @param {string} outDir The output directory. */ compileEntities(ns, entities, callbacks, outDir) { return __awaiter(this, void 0, void 0, function* () { for (const E in entities) { if (callbacks.onBeforeGenerateClass) { yield Promise.resolve(callbacks.onBeforeGenerateClass(E, this.options.target)); } let err; try { const CLASS_NAME = parseForClass(E); if (false === CLASS_NAME) { throw new Error(`The class name '${E}' is invalid!`); } const ENTITY_CLASS = entities[E]; if (!eb_lib_helpers.isObj(ENTITY_CLASS)) { continue; } const COLUMNS = {}; if (eb_lib_helpers.isObj(ENTITY_CLASS.columns)) { for (const C in ENTITY_CLASS.columns) { const COLUMN_NAME = parseForClass(C); if (false === COLUMN_NAME) { throw new Error(`The column name '${C}' is invalid!`); } if (eb_lib_helpers.isObj(COLUMNS[COLUMN_NAME])) { throw new Error(`The column '${COLUMN_NAME}' has already been defined!`); } let colEntry = ENTITY_CLASS.columns[C]; if (!eb_lib_helpers.isObj(colEntry)) { colEntry = { type: eb_lib_helpers.normalizeString(colEntry), }; } COLUMNS[COLUMN_NAME] = colEntry; } } const METHODS = {}; for (const C in COLUMNS) { let wordsOfColumn = eb_lib_helpers.replaceAll(C, '_', ' '); wordsOfColumn = eb_lib_helpers.replaceAll(C, '-', ' '); wordsOfColumn = eb_lib_helpers.replaceAll(C, "\t", ' '); const WORDS = Enumerable.from(wordsOfColumn.split(' ')).select(w => { return w.trim(); }).where(w => { return '' !== w; }).select(w => { return w[0].toUpperCase() + w.substr(1).trim(); }).toArray(); METHODS[C] = WORDS.join(''); } let generator; let generatorThisArg = this; const TARGET = this.options.target; switch (TARGET) { case EntityFramework.Doctrine: generator = eb_lib_doctrine.generateClassForDoctrine; break; case EntityFramework.EntityFramework: generator = eb_lib_ef.generateClassForEntityFramework; break; case EntityFramework.EntityFrameworkCore: generator = eb_lib_ef_core.generateClassForEntityFrameworkCore; break; } if (!generator) { throw new Error(`Target ${eb_lib_helpers.toStringSafe(TARGET)} is not supported!`); } const CTX = { columnNames: Object.keys(COLUMNS).sort((x, y) => { return eb_lib_helpers.compareValuesBy(x, y, c => { return eb_lib_helpers.normalizeString(c); }); }), columns: COLUMNS, entity: ENTITY_CLASS, methods: METHODS, name: CLASS_NAME, 'namespace': ns, options: this.options, outDir: outDir, }; yield Promise.resolve(generator.apply(generatorThisArg, [CTX])); } catch (e) { err = e; } finally { if (callbacks.onClassGenerated) { yield Promise.resolve(callbacks.onClassGenerated(err, E, this.options.target)); } } } }); } } exports.EntityCompiler = EntityCompiler; /** * Compiles entities. * * @param {EntityCompilerOptions} [opts] Options for the operation. * * @return {Promise<EntityCompilerResult>} The promise with the result. */ function compile(opts) { return __awaiter(this, void 0, void 0, function* () { const COMPILER = new EntityCompiler(opts); return yield COMPILER.compile(); }); } exports.compile = compile; /** * Parses a value for a class or for use in a class. * * @param {any} val The input value. * * @return {string|false} The parsed name or (false) if invalid. */ function parseForClass(val) { val = eb_lib_helpers.toStringSafe(val).trim(); if (/^([a-z|A-Z|0-9|_]+)$/i.test(val) && !/^([0-9]+)/i.test(val)) { return val; } return false; } exports.parseForClass = parseForClass; /** * Converts a data type from a entity file to a CLR type. * * @param {string} type The entity type. * @param {Function} canBeNull The function that provides if value can be (null) or not. * @param {Function} isID The function that provides if value is an ID value or not. * * @return {string} The CLR type. */ function toClrType(type, canBeNull, isID) { type = eb_lib_helpers.normalizeString(type); switch (type) { case exports.TYPE_BIGINT: case exports.TYPE_INT64: type = 'long'; break; case exports.TYPE_BIN: case exports.TYPE_BINARY: case exports.TYPE_BLOB: type = 'byte[]'; break; case exports.TYPE_BOOL: case exports.TYPE_BOOLEAN: type = 'bool'; break; case exports.TYPE_DATE: case exports.TYPE_DATETIME: type = 'global::System.DateTime'; break; case exports.TYPE_DATETIME_TZ: type = 'global::System.DateTimeOffset'; break; case exports.TYPE_DECIMAL: type = 'decimal'; break; case exports.TYPE_FLOAT: type = 'float'; break; case exports.TYPE_GUID: case exports.TYPE_UUID: type = 'global::System.Guid'; break; case exports.TYPE_INT: case exports.TYPE_INT32: case exports.TYPE_INTEGER: type = 'int'; break; case exports.TYPE_INT16: case exports.TYPE_SMALLINT: type = 'short'; break; case exports.TYPE_JSON: type = 'dynamic'; break; case exports.TYPE_STR: case exports.TYPE_STRING: case exports.TYPE_TEXT: type = 'string'; break; case exports.TYPE_TIME: type = 'System.TimeSpan'; break; case exports.TYPE_UINT16: type = 'ushort'; break; case exports.TYPE_UINT32: type = 'uint'; break; case exports.TYPE_UINT64: type = 'ulong'; break; case exports.TYPE__DEFAULT: type = 'string'; if (isID()) { type = 'int'; } break; default: throw new Error(`The data type '${type}' is not supported by CLR!`); } if (canBeNull()) { switch (type) { case 'bool': case 'decimal': case 'float': case 'int': case 'long': case 'short': case 'ushort': case 'uint': case 'ulong': case 'global::System.DateTime': case 'global::System.DateTimeOffset': case 'global::System.Guid': case 'System.TimeSpan': type += '?'; break; } } return type; } exports.toClrType = toClrType; //# sourceMappingURL=compiler.js.map