UNPKG

@compas/code-gen

Version:

Generate various boring parts of your server

109 lines (92 loc) 2.61 kB
import { AppError, isNil } from "@compas/stdlib"; /** * Collect and format JS imports. We only support ES module style imports for now. */ export class JavascriptImportCollector { /** * Resolve and type the import collector for JS files. * * @param {import("../file/context.js").GenerateFile}file * @returns {JavascriptImportCollector} */ static getImportCollector(file, typeImports = false) { if (typeImports) { if ( isNil(file.typeImportCollector) || !(file.typeImportCollector instanceof JavascriptImportCollector) ) { throw AppError.serverError({ message: `File is created without a type import collector.`, }); } return file.typeImportCollector; } if ( isNil(file.importCollector) || !(file.importCollector instanceof JavascriptImportCollector) ) { throw AppError.serverError({ message: `File is created without an import collector.`, }); } return file.importCollector; } constructor(isTypeImports = false) { /** * @private */ this.isTypeImports = isTypeImports; /** * @private * @type {Map<string, Set<string>>} */ this.destructuredImports = new Map(); /** * @private * @type {Set<string>} */ this.rawImports = new Set(); } /** * Use a destructure import * * @param {string} path * @param {string} symbol */ destructure(path, symbol) { if (!this.destructuredImports.has(path)) { this.destructuredImports.set(path, new Set()); } this.destructuredImports.get(path)?.add(symbol); } /** * Add a raw import. These are deduplicated, before writing. * * @param {string} importString */ raw(importString) { this.rawImports.add(importString); } toString() { const result = [...this.rawImports]; // Sort the destructure imports, so even without any post formatting it looks pretty // good. const destructureKeys = [...this.destructuredImports.keys()].sort(); for (const key of destructureKeys) { const symbols = [ ...(this.destructuredImports.get(key)?.values() ?? []), ].sort(); const isMultiline = symbols.length > 3; if (isMultiline) { result.push( `import${this.isTypeImports ? " type" : ""} {\n ${symbols.join(",\n ")},\n} from "${key}";`, ); } else { result.push( `import${this.isTypeImports ? " type" : ""} { ${symbols.join(", ")} } from "${key}";`, ); } } return result.join("\n"); } }