@travetto/app
Version:
Application registration/management and run support.
78 lines (66 loc) • 2.2 kB
text/typescript
import ts from 'typescript';
import {
TransformerState, DecoratorMeta, CoreUtil, DecoratorUtil, AfterClass
} from '@travetto/transformer';
import { SchemaTransformUtil } from '@travetto/schema/support/transform-util';
/**
* Converts classes with `@Application` to auto register with the `ApplicationRegistry`
*/
export class ApplicationTransformer {
/**
* On presence of `@Application`
*/
('Application')
static registerAppMethod(state: TransformerState, node: ts.ClassDeclaration, dm?: DecoratorMeta): typeof node {
const dec = dm?.dec;
if (!dec || !ts.isCallExpression(dec.expression)) { // If not valid
return node;
}
// Find runnable method
const runMethod = node.members
.find((x): x is ts.MethodDeclaration =>
ts.isMethodDeclaration(x) && x.name!.getText() === 'run'
);
if (!runMethod) {
return node;
}
const declArgs = [...dec.expression.arguments];
// Name only, need a config object
if (declArgs.length === 0) {
declArgs.push(state.fromLiteral({}));
}
// Track start point
declArgs[1] = state.extendObjectLiteral(declArgs[1], {
ident: '@Application', // Brand for searching
start: CoreUtil.getRangeOf(state.source, node)?.start,
codeStart: CoreUtil.getRangeOf(state.source, runMethod.body?.statements[0])?.start,
});
// Compute new declaration
const newDec = state.factory.createDecorator(
state.factory.createCallExpression(
dec.expression.expression,
dec.expression.typeArguments,
[...declArgs]
)
);
const members = node.members.map(x => ts.isMethodDeclaration(x) && x === runMethod ?
state.factory.updateMethodDeclaration(
x,
x.modifiers,
x.asteriskToken,
x.name,
x.questionToken,
x.typeParameters,
x.parameters.map(y => SchemaTransformUtil.computeField(state, y)),
x.type,
x.body
) : x);
return state.factory.updateClassDeclaration(node,
DecoratorUtil.spliceDecorators(node, dec, [newDec]),
node.name,
node.typeParameters,
node.heritageClauses,
members
);
}
}