UNPKG

@adocasts.com/dto

Version:

Easily make and generate DTOs from Lucid Models

107 lines (106 loc) 4.21 kB
import string from '@adonisjs/core/helpers/string'; import UtilService from './util_service.js'; export class ImportService { /** * Get grouped import statements from generated entity type information * @param entity Either a DtoInfo or ValidatorInfo object */ static getImportStatements(entity, modelFileLines) { const imports = []; const importLines = this.#getImportFileLines(modelFileLines); for (let property of entity.properties) { // get imports for relationship DTOs for (let item of property.typeRaw) { if (item.isRelationship && item.dto) { imports.push({ name: item.dto, namespace: '#dtos/' + string.snakeCase(item.dto).replace('_dto', ''), isDefault: true, }); } } const importMatch = this.#findImportLineMatch(property, importLines); if (importMatch) { imports.push(importMatch); } } // don't try to import the entity we're generating const nonSelfReferencingImports = imports.filter((imp) => imp.name !== entity.className); // join default and named imports into a single import statement for the namespace return this.#buildImportStatements(nonSelfReferencingImports); } static #buildImportStatements(imports) { const groups = this.#getGroupedImportNamespaces(imports); return Object.values(groups).map((items) => { const defaultImport = items.find((item) => item.isDefault)?.name; const namedImports = items .filter((item) => !item.isDefault) .map((item) => item.name) .join(', '); const names = [defaultImport, namedImports && `{ ${namedImports} }`] .filter(Boolean) .join(', '); return `import ${names} from '${items[0].namespace}'`; }); } /** * groups imports by namespace * @param imports * @private */ static #getGroupedImportNamespaces(imports) { return imports.reduce((groups, item) => { const group = groups[item.namespace] || []; if (!group.some((map) => map.name === item.name)) { group.push(item); } groups[item.namespace] = group; return groups; }, {}); } static #getImportFileLines(fileLines) { const lines = fileLines.filter((line) => line.startsWith('import ')); return lines.map((line) => { const part = line.replace('import ', '').replace('type ', '').split('from ').at(0); const namespace = line.split('from ').at(1) || ''; const [defaultPart = '', namedPart = ''] = part?.split('{') || []; const names = namedPart .split('}') .at(0) ?.split(',') .map((name) => name.trim()) || []; return { name: UtilService.cleanDefinition(defaultPart), names: names.filter((name) => name !== ''), namespace, line, }; }); } static #findImportLineMatch(property, lines) { const types = property.type.split('|').map((type) => type.trim()); const defaultMatch = lines.find((line) => types.includes(line.name)); if (defaultMatch) { return { name: defaultMatch.name, namespace: UtilService.cleanDefinition(defaultMatch.namespace), isDefault: true, }; } let namedMatch; for (const line of lines) { const name = line.names.find((item) => types.includes(item)); if (!name) continue; namedMatch = { name, namespace: line.namespace }; break; } if (!namedMatch) return; return { name: namedMatch.name, namespace: UtilService.cleanDefinition(namedMatch.namespace), isDefault: false, }; } }