@odata2ts/odata2ts
Version:
Flexible generator to produce various TypeScript artefacts (from simple model interfaces to complete odata clients) from OData metadata files
200 lines • 8.86 kB
JavaScript
import { __awaiter } from "tslib";
import * as path from "path";
import { mkdirp } from "mkdirp";
import { Project } from "ts-morph";
import { firstCharLowerCase } from "xml2js/lib/processors.js";
import { ImportContainer } from "../generator/ImportContainer.js";
import { FileHandler } from "./FileHandler.js";
import { createFormatter } from "./formatter/index.js";
import { loadTsMorphCompilerOptions } from "./TsMorphHelper.js";
export function createProjectManager(outputDir, emitMode, namingHelper, dataModel, options) {
return __awaiter(this, void 0, void 0, function* () {
const { usePrettier = false, tsConfigPath = "tsconfig.json" } = options;
const formatter = usePrettier ? yield createFormatter(outputDir, usePrettier) : undefined;
const compilerOpts = yield loadTsMorphCompilerOptions(tsConfigPath, emitMode, outputDir);
const pm = new ProjectManager(outputDir, emitMode, namingHelper, dataModel, formatter, compilerOpts, Object.assign({ usePrettier,
tsConfigPath }, options));
yield pm.init();
return pm;
});
}
export class ProjectManager {
constructor(outputDir, emitMode, namingHelper, dataModel, formatter, compilerOptions, options) {
this.outputDir = outputDir;
this.emitMode = emitMode;
this.namingHelper = namingHelper;
this.dataModel = dataModel;
this.formatter = formatter;
this.options = options;
// Create ts-morph project
this.project = new Project({
// manipulationSettings: this.formatter.getSettings(),
skipAddingFilesFromTsConfig: true,
compilerOptions,
});
if (options.noOutput) {
this.cachedFiles = new Map();
}
}
getDataModel() {
return this.dataModel;
}
/**
* Only filled when noOutput=true
*/
getCachedFiles() {
return this.cachedFiles;
}
writeFile(fileHandler) {
return __awaiter(this, void 0, void 0, function* () {
if (this.options.noOutput) {
yield fileHandler.write(this.emitMode, true);
this.cachedFiles.set(fileHandler.getFullFilePath(), fileHandler.getFile());
return;
}
return fileHandler.write(this.emitMode);
});
}
createFile(name, reservedNames, additionalPath = "", forceTypeChecking = false) {
const fileName = path.join(this.outputDir, additionalPath, `${name}.ts`);
const imports = new ImportContainer(additionalPath, name, this.dataModel, this.namingHelper.getFileNames(), !!this.options.bundledFileGeneration, reservedNames);
return new FileHandler(additionalPath, name, this.project.createSourceFile(fileName), imports, this.formatter, forceTypeChecking || !!this.options.allowTypeChecking);
}
init() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.options.bundledFileGeneration) {
// ensure folder for each model: we do this at this point for performance reasons
yield Promise.all(this.dataModel.getModelTypes().map((mt) => mkdirp(path.join(this.outputDir, mt.folderPath))));
}
});
}
initModels() {
if (this.options.bundledFileGeneration) {
// collect reserved names, that is names of classes we're going to create => imports must take them into account
const reservedWords = this.dataModel.getModelTypes().reduce((collector, model) => {
var _a;
const asEntityType = model;
collector.push(model.modelName);
if (asEntityType.editableName) {
collector.push(asEntityType.editableName);
}
if ((_a = asEntityType.id) === null || _a === void 0 ? void 0 : _a.modelName) {
collector.push(asEntityType.id.modelName);
}
this.dataModel.getAllEntityOperations(model.fqName).forEach((op) => {
if (op.parameters.length) {
collector.push(op.paramsModelName);
}
});
return collector;
}, []);
this.dataModel.getUnboundOperationTypes().forEach((op) => {
if (op.parameters.length) {
reservedWords.push(op.paramsModelName);
}
});
this.mainModelFile = this.createFile(this.namingHelper.getFileNames().model, reservedWords);
}
}
finalizeModels() {
return __awaiter(this, void 0, void 0, function* () {
if (this.mainModelFile &&
(this.options.bundledFileGeneration || this.mainModelFile.getFile().getFullText().length)) {
yield this.writeFile(this.mainModelFile);
}
});
}
initQObjects() {
if (this.options.bundledFileGeneration) {
// collect reserved names, that is names of classes we're going to create => imports must take them into account
const reservedWords = this.dataModel.getModelTypes().reduce((collector, model) => {
var _a;
const asEntityType = model;
if (asEntityType.qName) {
collector.push(asEntityType.qName, firstCharLowerCase(asEntityType.qName));
}
if ((_a = asEntityType.id) === null || _a === void 0 ? void 0 : _a.qName) {
collector.push(asEntityType.id.qName);
}
this.dataModel.getAllEntityOperations(model.fqName).forEach((op) => {
collector.push(op.qName);
});
return collector;
}, []);
this.dataModel.getUnboundOperationTypes().forEach((op) => {
reservedWords.push(op.qName);
});
this.mainQFile = this.createFile(this.namingHelper.getFileNames().qObject, reservedWords);
}
}
finalizeQObjects() {
return __awaiter(this, void 0, void 0, function* () {
if (this.mainQFile && (this.options.bundledFileGeneration || this.mainQFile.getFile().getFullText().length)) {
yield this.writeFile(this.mainQFile);
}
});
}
initServices() {
const mainServiceName = this.namingHelper.getMainServiceName();
const reservedNames = [mainServiceName];
if (this.options.bundledFileGeneration) {
[...this.dataModel.getEntityTypes(), ...this.dataModel.getComplexTypes()].reduce((collector, model) => {
collector.push(model.serviceName, model.serviceCollectionName);
return collector;
}, reservedNames);
}
this.mainServiceFile = this.createFile(mainServiceName, reservedNames);
}
finalizeServices() {
return __awaiter(this, void 0, void 0, function* () {
if (this.mainServiceFile) {
yield this.writeFile(this.mainServiceFile);
}
});
}
getMainServiceFile() {
return this.mainServiceFile;
}
createOrGetMainModelFile(reservedNames) {
if (!this.mainModelFile) {
this.mainModelFile = this.createFile(this.namingHelper.getFileNames().model, reservedNames, "", true);
}
return this.mainModelFile;
}
createOrGetMainQObjectFile(reservedNames) {
if (!this.mainQFile) {
this.mainQFile = this.createFile(this.namingHelper.getFileNames().qObject, reservedNames);
}
return this.mainQFile;
}
createOrGetModelFile(folderPath, name, reservedNames) {
if (this.mainModelFile) {
return this.mainModelFile;
}
// model files always allow for type checking
return this.createFile(name, reservedNames, folderPath, true);
}
createOrGetQObjectFile(folderPath, name, reservedNames) {
if (this.mainQFile) {
return this.mainQFile;
}
return this.createFile(name, reservedNames, folderPath);
}
createOrGetServiceFile(folderPath, name, reservedNames) {
if (this.options.bundledFileGeneration) {
return this.mainServiceFile;
}
return this.createFile(name, reservedNames, folderPath);
}
finalizeFile(file) {
return __awaiter(this, void 0, void 0, function* () {
// write individual files in unbundled mode & if this is not one of the main files on root level
if (!this.options.bundledFileGeneration &&
file.path !== "" &&
!Object.values(this.namingHelper.getFileNames()).includes(file.fileName)) {
yield this.writeFile(file);
}
});
}
}
//# sourceMappingURL=ProjectManager.js.map