UNPKG

@odata2ts/odata2ts

Version:

Flexible generator to produce various TypeScript artefacts (from simple model interfaces to complete odata clients) from OData metadata files

213 lines 9.59 kB
import path from "path"; import { ODataVersions } from "@odata2ts/odata-core"; import { ClientApiImports, CoreImports, LIB_MODULES, ServiceImports, VERSIONED_CORE_IMPORTS, VERSIONED_SERVICE_IMPORTS, } from "./import/ImportObjects.js"; import { ImportedNameValidator } from "./ImportedNameValidator.js"; /** * Handles all the import statements for a given file. * * Features a renaming mechanism, so that when the import name conflicts with an existing import a new * name is generated and returned. * * Map<string,string> */ export class ImportContainer { constructor(path, fileName, dataModel, mainFileNames, bundledFileGeneration, reservedNames) { this.path = path; this.fileName = fileName; this.dataModel = dataModel; this.mainFileNames = mainFileNames; this.bundledFileGeneration = bundledFileGeneration; this.reservedNames = reservedNames; // mapping of a custom defined type to a primitive type this.customTypes = { regular: new Map(), typeOnly: new Map(), }; // imports to generated artefacts this.internalImports = { regular: new Map(), typeOnly: new Map(), }; this.libs = { core: { regular: new Map(), typeOnly: new Map() }, qObject: { regular: new Map(), typeOnly: new Map() }, clientApi: { regular: new Map(), typeOnly: new Map() }, service: { regular: new Map(), typeOnly: new Map() }, }; this.importedNameValidator = new ImportedNameValidator(reservedNames); } addCoreLib(odataVersion, coreLib) { const isVersioned = VERSIONED_CORE_IMPORTS.includes(coreLib); const name = CoreImports[coreLib] + (isVersioned ? ODataVersions[odataVersion] : ""); const importName = this.importedNameValidator.validateName(LIB_MODULES.core, name); // TODO: currently only types are imported, however enums could potentially be imported too this.libs.core.typeOnly.set(name, importName); return importName; } addFromQObject(name, typeOnlyImport = false) { const importName = this.importedNameValidator.validateName(LIB_MODULES.qObject, name); const imports = this.libs.qObject; if (typeOnlyImport) { if (!imports.regular.has(name)) { imports.typeOnly.set(name, importName); } } else { if (imports.typeOnly.has(name)) { imports.typeOnly.delete(name); } imports.regular.set(name, importName); } return importName; } addQObject(qObject) { return this.addFromQObject(qObject); } addQObjectType(qObject) { return this.addFromQObject(qObject, true); } addClientApi(clientApi) { const name = ClientApiImports[clientApi]; const importName = this.importedNameValidator.validateName(LIB_MODULES.clientApi, name); // complete client api consists only of types this.libs.clientApi.typeOnly.set(name, importName); return importName; } addServiceObject(odataVersion, serviceObject) { const isVersioned = VERSIONED_SERVICE_IMPORTS.includes(serviceObject); const name = ServiceImports[serviceObject] + (isVersioned ? ODataVersions[odataVersion] : ""); const importName = this.importedNameValidator.validateName(LIB_MODULES.service, name); // only regular imports for the service package this.libs.service.regular.set(name, importName); return importName; } // TODO: make sure that regular imports win over additional typeOnly imports addCustomType(moduleName, typeName, isTypeOnly = false) { const importName = this.importedNameValidator.validateName(moduleName, typeName); const imports = isTypeOnly ? this.customTypes.typeOnly : this.customTypes.regular; let importList = imports.get(moduleName); if (!importList) { importList = new Map(); imports.set(moduleName, importList); } importList.set(typeName, importName); return importName; } pathAndFile(filePath, fileName) { return filePath ? `${filePath}/${fileName}` : fileName; } isDifferentFile(filePath, fileName) { return this.pathAndFile(this.path, this.fileName) !== this.pathAndFile(filePath, fileName); } addGeneratedImport(folderPath, fileName, name, isTypeOnly = false) { var _a, _b, _c; // imports are only relevant for different files if (!this.isDifferentFile(folderPath, fileName)) { return name; } const moduleName = this.pathAndFile(folderPath, fileName); const importName = this.importedNameValidator.validateName(moduleName, name); const imports = isTypeOnly ? this.internalImports.typeOnly : this.internalImports.regular; if (isTypeOnly && ((_a = this.internalImports.regular.get(moduleName)) === null || _a === void 0 ? void 0 : _a.has(name))) { return importName; } if (!isTypeOnly && ((_b = this.internalImports.typeOnly.get(moduleName)) === null || _b === void 0 ? void 0 : _b.has(name))) { (_c = this.internalImports.typeOnly.get(moduleName)) === null || _c === void 0 ? void 0 : _c.delete(name); } const importList = imports.get(moduleName) || new Map(); importList.set(name, importName); imports.set(moduleName, importList); return importName; } addGeneratedModel(fqName, name, isTypeOnly = true) { if (this.bundledFileGeneration) { return this.addGeneratedImport("", this.mainFileNames.model, name, isTypeOnly); } else { const model = this.dataModel.getModel(fqName); if (!model && fqName !== "") { throw new Error(`Cannot find model by its fully qualified name: ${fqName}!`); } const folderPath = model ? model.folderPath : ""; const modelName = model ? model.modelName : this.mainFileNames.model; return this.addGeneratedImport(folderPath, modelName, name, isTypeOnly); } } addGeneratedQObject(fqName, name, isTypeOnly = false) { if (this.bundledFileGeneration) { return this.addGeneratedImport("", this.mainFileNames.qObject, name, isTypeOnly); } else { const model = this.dataModel.getModel(fqName); if (!model && fqName !== "") { throw new Error(`Cannot find q-object by its fully qualified name: ${fqName}!`); } const folderPath = model ? model.folderPath : ""; const qName = model ? model.qName : this.mainFileNames.qObject; return this.addGeneratedImport(folderPath, qName, name, isTypeOnly); } } addGeneratedService(fqName, name) { if (this.bundledFileGeneration) { return this.addGeneratedImport("", this.mainFileNames.service, name); } else { const model = this.dataModel.getModel(fqName); return this.addGeneratedImport(model.folderPath, model.serviceName, name); } } createImportDecl(module, toImport, isTypeOnly = false) { return { namedImports: this.getNamedImports(toImport), moduleSpecifier: module, isTypeOnly, }; } getImportDeclarations() { return [ ...Object.entries(this.libs).reduce((result, [moduleName, toImport]) => { const module = LIB_MODULES[moduleName]; if (toImport.typeOnly.size) { result.push(this.createImportDecl(module, toImport.typeOnly, true)); } if (toImport.regular.size) { result.push(this.createImportDecl(module, toImport.regular)); } return result; }, []), ...[...this.customTypes.typeOnly] .filter(([moduleName, toImport]) => toImport.size > 0) .map(([moduleName, toImport]) => { return this.createImportDecl(moduleName, toImport, true); }), ...[...this.customTypes.regular] .filter(([moduleName, toImport]) => toImport.size > 0) .map(([moduleName, toImport]) => { return this.createImportDecl(moduleName, toImport); }), ...[...this.internalImports.typeOnly] .filter(([_, toImport]) => toImport.size > 0) .map(([key, toImport]) => { const module = this.getModuleSpecifier(key); return this.createImportDecl(module, toImport, true); }), ...[...this.internalImports.regular] .filter(([_, toImport]) => toImport.size > 0) .map(([key, toImport]) => { const module = this.getModuleSpecifier(key); return this.createImportDecl(module, toImport); }), ]; } getNamedImports(toImport) { return [...toImport.entries()].map(([name, alias]) => ({ name, alias: alias !== name ? alias : undefined, })); } getModuleSpecifier(filePath) { const relativePath = path.relative(this.path, filePath).replaceAll(path.sep, "/"); return !relativePath.startsWith(".") ? "./" + relativePath : relativePath; } } //# sourceMappingURL=ImportContainer.js.map