mirror of https://github.com/abpframework/abp.git
2 changed files with 131 additions and 0 deletions
@ -0,0 +1,130 @@ |
|||
import { eImportKeyword } from '../enums'; |
|||
import { |
|||
Action, |
|||
Body, |
|||
Controller, |
|||
Import, |
|||
Method, |
|||
Parameter, |
|||
ReturnValue, |
|||
Service, |
|||
Signature, |
|||
} from '../models'; |
|||
import { parseNamespace } from './namespace'; |
|||
import { dir } from './text'; |
|||
|
|||
export function createControllerToServiceMapper(solution: string, apiName: string) { |
|||
const mapActionToMethod = createActionToMethodMapper(solution); |
|||
|
|||
return (controller: Controller) => { |
|||
const actions = Object.values(controller.actions); |
|||
const imports = actions.reduce(createActionToImportsReducer(solution), []); |
|||
const methods = actions.map(mapActionToMethod); |
|||
const name = controller.controllerName; |
|||
const namespace = parseNamespace(solution, controller.type); |
|||
return new Service({ apiName, imports, methods, name, namespace }); |
|||
}; |
|||
} |
|||
|
|||
export function createActionToImportsReducer(solution: string) { |
|||
const mapTypeDefToImport = createTypeDefToImportMapper(solution); |
|||
|
|||
return (imports: Import[], action: Action) => { |
|||
const typeDefs = [action.returnValue, ...action.parametersOnMethod]; |
|||
typeDefs.forEach(typeDef => { |
|||
const def = mapTypeDefToImport(typeDef); |
|||
if (!def) return; |
|||
|
|||
const existingImport = imports.find( |
|||
({ keyword, path }) => keyword === def.keyword && path === def.path, |
|||
); |
|||
if (!existingImport) return imports.push(def); |
|||
|
|||
existingImport.specifiers = [ |
|||
...new Set([...existingImport.specifiers, ...def.specifiers]), |
|||
].sort(); |
|||
}); |
|||
return imports; |
|||
}; |
|||
} |
|||
|
|||
export function createTypeDefToImportMapper(solution: string) { |
|||
const adaptType = createTypeAdapter(solution); |
|||
|
|||
return ({ type, typeSimple }: ReturnValue) => { |
|||
if (type.startsWith('System')) return; |
|||
const namespace = parseNamespace(solution, type); |
|||
const path = type.startsWith('Volo.Abp.Application.Dtos') |
|||
? '@volo/abp.ng.core' |
|||
: `@shared/models/${dir(namespace)}`; |
|||
const specifier = adaptType(typeSimple.split('<')[0]); |
|||
return new Import({ keyword: eImportKeyword.Type, path, specifiers: [specifier] }); |
|||
}; |
|||
} |
|||
|
|||
export function createActionToMethodMapper(solution: string) { |
|||
const mapActionToBody = createActionToBodyMapper(solution); |
|||
const mapActionToSignature = createActionToSignatureMapper(solution); |
|||
|
|||
return (action: Action) => { |
|||
const body = mapActionToBody(action); |
|||
const signature = mapActionToSignature(action); |
|||
return new Method({ body, signature }); |
|||
}; |
|||
} |
|||
|
|||
export function createActionToBodyMapper(solution: string) { |
|||
const adaptType = createTypeAdapter(solution); |
|||
|
|||
return ({ httpMethod, parameters, returnValue, url }: Action) => { |
|||
const responseType = adaptType(returnValue.typeSimple); |
|||
const body = new Body({ method: httpMethod, responseType, url }); |
|||
|
|||
parameters.forEach(body.registerActionParameter); |
|||
|
|||
return body; |
|||
}; |
|||
} |
|||
|
|||
export function createActionToSignatureMapper(solution: string) { |
|||
const adaptType = createTypeAdapter(solution); |
|||
|
|||
return (action: Action) => { |
|||
const signature = new Signature({ name: getMethodNameFromAction(action) }); |
|||
|
|||
signature.parameters = action.parametersOnMethod.map(p => { |
|||
const type = adaptType(p.typeSimple); |
|||
const parameter = new Parameter({ name: p.name, type }); |
|||
if (p.defaultValue) parameter.default = ` = ${p.defaultValue}`; |
|||
else if (p.isOptional) parameter.optional = '?'; |
|||
return parameter; |
|||
}); |
|||
|
|||
return signature; |
|||
}; |
|||
} |
|||
|
|||
function getMethodNameFromAction(action: Action): string { |
|||
return action.uniqueName.split('Async')[0]; |
|||
} |
|||
|
|||
function createTypeAdapter(solution: string) { |
|||
const optionalRegex = /\?/g; |
|||
const solutionRegex = new RegExp(solution.replace(/\./g, `\.`) + `\.`); |
|||
const voloRegex = /^Volo\.(Abp\.?)(Application\.?)/; |
|||
|
|||
return (typeSimple: string) => { |
|||
if (typeSimple === 'System.Void') return 'void'; |
|||
|
|||
return typeSimple |
|||
.replace(/>+$/, '') |
|||
.split('<') |
|||
.reduceRight((acc, type) => { |
|||
type = type.replace(voloRegex, ''); |
|||
type = type.replace(solutionRegex, ''); |
|||
type = type.replace(optionalRegex, ''); |
|||
type = type.split('.').pop()!; |
|||
return acc ? `${type}<${acc}>` : type; |
|||
}, ''); |
|||
}; |
|||
} |
|||
Loading…
Reference in new issue