diff --git a/npm/ng-packs/packages/schematics/src/commands/api/index.ts b/npm/ng-packs/packages/schematics/src/commands/api/index.ts index fa599adc71..652ec60189 100644 --- a/npm/ng-packs/packages/schematics/src/commands/api/index.ts +++ b/npm/ng-packs/packages/schematics/src/commands/api/index.ts @@ -15,10 +15,11 @@ export default function(params: GenerateProxySchema) { const targetPath = buildDefaultPath(target.definition); const readApiDefinition = createApiDefinitionReader(`${targetPath}/shared/api-definition.json`); const data = readApiDefinition(tree); + const types = data.types; const definition = data.modules[moduleName]; if (!definition) throw new SchematicsException(interpolate(Exception.InvalidModule, moduleName)); - const mapControllerToService = createControllerToServiceMapper(solution, definition.remoteServiceName); + const mapControllerToService = createControllerToServiceMapper(solution, types, definition.remoteServiceName); const controllers = Object.values(definition.controllers || {}); const serviceImports: Record = {}; @@ -43,7 +44,7 @@ export default function(params: GenerateProxySchema) { ), ); - const mapImportRefsToModel = createImportRefsToModelMapper(solution, data.types); + const mapImportRefsToModel = createImportRefsToModelMapper(solution, types); const createModelFiles = chain( Object.values(serviceImports).map(refs => { diff --git a/npm/ng-packs/packages/schematics/src/models/api-definition.ts b/npm/ng-packs/packages/schematics/src/models/api-definition.ts index 96f40de644..3b75f266e7 100644 --- a/npm/ng-packs/packages/schematics/src/models/api-definition.ts +++ b/npm/ng-packs/packages/schematics/src/models/api-definition.ts @@ -73,3 +73,8 @@ export interface TypeDef { type: string; typeSimple: string; } + +export interface TypeWithEnum { + isEnum: boolean; + type: string; +} diff --git a/npm/ng-packs/packages/schematics/src/utils/model.ts b/npm/ng-packs/packages/schematics/src/utils/model.ts index 9078f422b7..a8676ce639 100644 --- a/npm/ng-packs/packages/schematics/src/utils/model.ts +++ b/npm/ng-packs/packages/schematics/src/utils/model.ts @@ -1,5 +1,5 @@ import { strings } from '@angular-devkit/core'; -import { Import, Interface, Model, Property, Type } from '../models'; +import { Import, Interface, Model, Property, Type, TypeWithEnum } from '../models'; import { sortImports } from './import'; import { parseNamespace } from './namespace'; import { relativePathToModel } from './path'; @@ -73,12 +73,12 @@ export function createImportRefToImportReducerCreator( return (imports: Import[], importRef: string) => reduceTypesToImport( imports, - mergeBaseTypeWithProperties(types[importRef]).reduce((typeNames: string[], type) => { - parseGenerics(type) + mergeBaseTypeWithProperties(types[importRef]).reduce((acc: TypeWithEnum[], typeName) => { + parseGenerics(typeName) .toGenerics() - .forEach(t => typeNames.push(t)); + .forEach(type => acc.push({ type, isEnum: types[type]?.isEnum })); - return typeNames; + return acc; }, []), ); }; diff --git a/npm/ng-packs/packages/schematics/src/utils/path.ts b/npm/ng-packs/packages/schematics/src/utils/path.ts index 5b84ea168b..d040ac0bdd 100644 --- a/npm/ng-packs/packages/schematics/src/utils/path.ts +++ b/npm/ng-packs/packages/schematics/src/utils/path.ts @@ -1,4 +1,10 @@ -import { dir } from './text'; +import { dir, kebab } from './text'; + +export function relativePathToEnum(namespace: string, enumNamespace: string, enumName: string) { + const repeats = namespace ? namespace.split('.').length : 0; + const path = '..' + '/..'.repeat(repeats) + '/enums/' + dir(enumNamespace) + kebab(enumName); + return removeDoubleSlash(path); +} export function relativePathToModel(namespace: string, modelNamespace: string) { const repeats = namespace ? namespace.split('.').length : 0; @@ -6,6 +12,10 @@ export function relativePathToModel(namespace: string, modelNamespace: string) { return removeTrailingSlash(path); } +function removeDoubleSlash(path: string) { + return path.replace(/\/{2,}/g, ''); +} + function removeTrailingSlash(path: string) { return path.replace(/\/+$/, ''); } diff --git a/npm/ng-packs/packages/schematics/src/utils/service.ts b/npm/ng-packs/packages/schematics/src/utils/service.ts index 5fc2e18e36..57d8c97e0c 100644 --- a/npm/ng-packs/packages/schematics/src/utils/service.ts +++ b/npm/ng-packs/packages/schematics/src/utils/service.ts @@ -1,4 +1,15 @@ -import { Action, Body, Controller, Import, Method, Property, Service, Signature } from '../models'; +import { + Action, + Body, + Controller, + Import, + Method, + Property, + Service, + Signature, + Type, + TypeWithEnum, +} from '../models'; import { sortImports } from './import'; import { parseNamespace } from './namespace'; import { parseGenerics } from './tree'; @@ -8,14 +19,18 @@ export function serializeParameters(parameters: Property[]) { return parameters.map(p => p.name + p.optional + ': ' + p.type + p.default, '').join(', '); } -export function createControllerToServiceMapper(solution: string, apiName: string) { +export function createControllerToServiceMapper( + solution: string, + types: Record, + apiName: string, +) { const mapActionToMethod = createActionToMethodMapper(solution); return (controller: Controller) => { const name = controller.controllerName; const namespace = parseNamespace(solution, controller.type); const actions = Object.values(controller.actions); - const imports = actions.reduce(createActionToImportsReducer(solution, namespace), []); + const imports = actions.reduce(createActionToImportsReducer(solution, types, namespace), []); imports.push(new Import({ path: '@abp/ng.core', specifiers: ['RestService'] })); imports.push(new Import({ path: '@angular/core', specifiers: ['Injectable'] })); sortImports(imports); @@ -75,18 +90,22 @@ function getMethodNameFromAction(action: Action): string { return action.uniqueName.split('Async')[0]; } -function createActionToImportsReducer(solution: string, namespace: string) { +function createActionToImportsReducer( + solution: string, + types: Record, + namespace: string, +) { const mapTypesToImports = createTypesToImportsReducer(solution, namespace); return (imports: Import[], { parametersOnMethod, returnValue }: Action) => mapTypesToImports( imports, - [returnValue, ...parametersOnMethod].reduce((types: string[], { type }) => { - parseGenerics(type) + [returnValue, ...parametersOnMethod].reduce((acc: TypeWithEnum[], param) => { + parseGenerics(param.type) .toGenerics() - .forEach(t => types.push(t)); + .forEach(type => acc.push({ type, isEnum: types[type]?.isEnum })); - return types; + return acc; }, []), ); } diff --git a/npm/ng-packs/packages/schematics/src/utils/type.ts b/npm/ng-packs/packages/schematics/src/utils/type.ts index d82dd001bc..ebae7c802b 100644 --- a/npm/ng-packs/packages/schematics/src/utils/type.ts +++ b/npm/ng-packs/packages/schematics/src/utils/type.ts @@ -1,9 +1,9 @@ import { strings } from '@angular-devkit/core'; import { SYSTEM_TYPES } from '../constants'; import { eImportKeyword } from '../enums'; -import { Import } from '../models'; +import { Import, TypeWithEnum } from '../models'; import { parseNamespace } from './namespace'; -import { relativePathToModel } from './path'; +import { relativePathToEnum, relativePathToModel } from './path'; import { parseGenerics } from './tree'; export function createTypeSimplifier(solution: string) { @@ -53,9 +53,9 @@ export function removeTypeModifiers(type: string) { export function createTypesToImportsReducer(solution: string, namespace: string) { const mapTypeToImport = createTypeToImportMapper(solution, namespace); - return (imports: Import[], types: string[]) => { - types.forEach(type => { - const newImport = mapTypeToImport(type); + return (imports: Import[], types: TypeWithEnum[]) => { + types.forEach(({ type, isEnum }) => { + const newImport = mapTypeToImport(type, isEnum); if (!newImport) return; const existingImport = imports.find( @@ -76,15 +76,17 @@ export function createTypesToImportsReducer(solution: string, namespace: string) export function createTypeToImportMapper(solution: string, namespace: string) { const adaptType = createTypeAdapter(solution); - return (type: string) => { + return (type: string, isEnum: boolean) => { if (!type || type.startsWith('System')) return; const modelNamespace = parseNamespace(solution, type); + const refs = [type]; + const specifiers = [adaptType(type.split('<')[0])]; const path = type.startsWith('Volo.Abp.Application.Dtos') ? '@abp/ng.core' + : isEnum + ? relativePathToEnum(namespace, modelNamespace, specifiers[0]) : relativePathToModel(namespace, modelNamespace); - const refs = [type]; - const specifiers = [adaptType(type.split('<')[0])]; return new Import({ keyword: eImportKeyword.Type, path, refs, specifiers }); };