feat: handle enum imports in schematics

pull/5137/head
Arman Ozak 5 years ago
parent 7d272958ba
commit 198ea436af

@ -15,10 +15,11 @@ export default function(params: GenerateProxySchema) {
const targetPath = buildDefaultPath(target.definition); const targetPath = buildDefaultPath(target.definition);
const readApiDefinition = createApiDefinitionReader(`${targetPath}/shared/api-definition.json`); const readApiDefinition = createApiDefinitionReader(`${targetPath}/shared/api-definition.json`);
const data = readApiDefinition(tree); const data = readApiDefinition(tree);
const types = data.types;
const definition = data.modules[moduleName]; const definition = data.modules[moduleName];
if (!definition) throw new SchematicsException(interpolate(Exception.InvalidModule, 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 controllers = Object.values(definition.controllers || {});
const serviceImports: Record<string, string[]> = {}; const serviceImports: Record<string, string[]> = {};
@ -43,7 +44,7 @@ export default function(params: GenerateProxySchema) {
), ),
); );
const mapImportRefsToModel = createImportRefsToModelMapper(solution, data.types); const mapImportRefsToModel = createImportRefsToModelMapper(solution, types);
const createModelFiles = chain( const createModelFiles = chain(
Object.values(serviceImports).map(refs => { Object.values(serviceImports).map(refs => {

@ -73,3 +73,8 @@ export interface TypeDef {
type: string; type: string;
typeSimple: string; typeSimple: string;
} }
export interface TypeWithEnum {
isEnum: boolean;
type: string;
}

@ -1,5 +1,5 @@
import { strings } from '@angular-devkit/core'; 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 { sortImports } from './import';
import { parseNamespace } from './namespace'; import { parseNamespace } from './namespace';
import { relativePathToModel } from './path'; import { relativePathToModel } from './path';
@ -73,12 +73,12 @@ export function createImportRefToImportReducerCreator(
return (imports: Import[], importRef: string) => return (imports: Import[], importRef: string) =>
reduceTypesToImport( reduceTypesToImport(
imports, imports,
mergeBaseTypeWithProperties(types[importRef]).reduce((typeNames: string[], type) => { mergeBaseTypeWithProperties(types[importRef]).reduce((acc: TypeWithEnum[], typeName) => {
parseGenerics(type) parseGenerics(typeName)
.toGenerics() .toGenerics()
.forEach(t => typeNames.push(t)); .forEach(type => acc.push({ type, isEnum: types[type]?.isEnum }));
return typeNames; return acc;
}, []), }, []),
); );
}; };

@ -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) { export function relativePathToModel(namespace: string, modelNamespace: string) {
const repeats = namespace ? namespace.split('.').length : 0; const repeats = namespace ? namespace.split('.').length : 0;
@ -6,6 +12,10 @@ export function relativePathToModel(namespace: string, modelNamespace: string) {
return removeTrailingSlash(path); return removeTrailingSlash(path);
} }
function removeDoubleSlash(path: string) {
return path.replace(/\/{2,}/g, '');
}
function removeTrailingSlash(path: string) { function removeTrailingSlash(path: string) {
return path.replace(/\/+$/, ''); return path.replace(/\/+$/, '');
} }

@ -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 { sortImports } from './import';
import { parseNamespace } from './namespace'; import { parseNamespace } from './namespace';
import { parseGenerics } from './tree'; 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(', '); 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<string, Type>,
apiName: string,
) {
const mapActionToMethod = createActionToMethodMapper(solution); const mapActionToMethod = createActionToMethodMapper(solution);
return (controller: Controller) => { return (controller: Controller) => {
const name = controller.controllerName; const name = controller.controllerName;
const namespace = parseNamespace(solution, controller.type); const namespace = parseNamespace(solution, controller.type);
const actions = Object.values(controller.actions); 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: '@abp/ng.core', specifiers: ['RestService'] }));
imports.push(new Import({ path: '@angular/core', specifiers: ['Injectable'] })); imports.push(new Import({ path: '@angular/core', specifiers: ['Injectable'] }));
sortImports(imports); sortImports(imports);
@ -75,18 +90,22 @@ function getMethodNameFromAction(action: Action): string {
return action.uniqueName.split('Async')[0]; return action.uniqueName.split('Async')[0];
} }
function createActionToImportsReducer(solution: string, namespace: string) { function createActionToImportsReducer(
solution: string,
types: Record<string, Type>,
namespace: string,
) {
const mapTypesToImports = createTypesToImportsReducer(solution, namespace); const mapTypesToImports = createTypesToImportsReducer(solution, namespace);
return (imports: Import[], { parametersOnMethod, returnValue }: Action) => return (imports: Import[], { parametersOnMethod, returnValue }: Action) =>
mapTypesToImports( mapTypesToImports(
imports, imports,
[returnValue, ...parametersOnMethod].reduce((types: string[], { type }) => { [returnValue, ...parametersOnMethod].reduce((acc: TypeWithEnum[], param) => {
parseGenerics(type) parseGenerics(param.type)
.toGenerics() .toGenerics()
.forEach(t => types.push(t)); .forEach(type => acc.push({ type, isEnum: types[type]?.isEnum }));
return types; return acc;
}, []), }, []),
); );
} }

@ -1,9 +1,9 @@
import { strings } from '@angular-devkit/core'; import { strings } from '@angular-devkit/core';
import { SYSTEM_TYPES } from '../constants'; import { SYSTEM_TYPES } from '../constants';
import { eImportKeyword } from '../enums'; import { eImportKeyword } from '../enums';
import { Import } from '../models'; import { Import, TypeWithEnum } from '../models';
import { parseNamespace } from './namespace'; import { parseNamespace } from './namespace';
import { relativePathToModel } from './path'; import { relativePathToEnum, relativePathToModel } from './path';
import { parseGenerics } from './tree'; import { parseGenerics } from './tree';
export function createTypeSimplifier(solution: string) { export function createTypeSimplifier(solution: string) {
@ -53,9 +53,9 @@ export function removeTypeModifiers(type: string) {
export function createTypesToImportsReducer(solution: string, namespace: string) { export function createTypesToImportsReducer(solution: string, namespace: string) {
const mapTypeToImport = createTypeToImportMapper(solution, namespace); const mapTypeToImport = createTypeToImportMapper(solution, namespace);
return (imports: Import[], types: string[]) => { return (imports: Import[], types: TypeWithEnum[]) => {
types.forEach(type => { types.forEach(({ type, isEnum }) => {
const newImport = mapTypeToImport(type); const newImport = mapTypeToImport(type, isEnum);
if (!newImport) return; if (!newImport) return;
const existingImport = imports.find( const existingImport = imports.find(
@ -76,15 +76,17 @@ export function createTypesToImportsReducer(solution: string, namespace: string)
export function createTypeToImportMapper(solution: string, namespace: string) { export function createTypeToImportMapper(solution: string, namespace: string) {
const adaptType = createTypeAdapter(solution); const adaptType = createTypeAdapter(solution);
return (type: string) => { return (type: string, isEnum: boolean) => {
if (!type || type.startsWith('System')) return; if (!type || type.startsWith('System')) return;
const modelNamespace = parseNamespace(solution, type); const modelNamespace = parseNamespace(solution, type);
const refs = [type];
const specifiers = [adaptType(type.split('<')[0])];
const path = type.startsWith('Volo.Abp.Application.Dtos') const path = type.startsWith('Volo.Abp.Application.Dtos')
? '@abp/ng.core' ? '@abp/ng.core'
: isEnum
? relativePathToEnum(namespace, modelNamespace, specifiers[0])
: relativePathToModel(namespace, modelNamespace); : relativePathToModel(namespace, modelNamespace);
const refs = [type];
const specifiers = [adaptType(type.split('<')[0])];
return new Import({ keyword: eImportKeyword.Type, path, refs, specifiers }); return new Import({ keyword: eImportKeyword.Type, path, refs, specifiers });
}; };

Loading…
Cancel
Save