power-di
Version:
A lightweight Dependency Injection library. Using es6 and other features, remove unnecessary concepts, easy and convenient to use.
234 lines • 10.4 kB
JavaScript
;
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.before = void 0;
// tslint:disable
var path = require("path");
var fs = require("fs");
var ts = require("typescript");
var util_1 = require("./util");
console.log('[power-di] load transformer: class metadata.');
function transformer(program, config) {
var typeChecker = program.getTypeChecker();
return {
before: function (ctx) {
return function (sourceFile) {
return (0, util_1.walker)(sourceFile, ctx, before(ctx, sourceFile, typeChecker, config));
};
},
};
}
exports.default = transformer;
function before(ctx, sf, typeChecker, config) {
var pkg = findPkg(sf.fileName);
if (!pkg) {
console.log('no pkg', sf.fileName);
}
return function (node) {
var _a, _b, _c, _d, _e, _f;
if (!pkg) {
return node;
}
if (!ts.isDecorator(node)) {
return node;
}
// 处理注入 type
var injectDecorators = ((_a = config === null || config === void 0 ? void 0 : config.decoratorNames) === null || _a === void 0 ? void 0 : _a.inject) ||
((_c = (_b = pkg['power-di']) === null || _b === void 0 ? void 0 : _b.decoratorNames) === null || _c === void 0 ? void 0 : _c.inject) || [
'inject',
'getContributions',
'getExtensions',
'getPlugins',
];
if (injectDecorators.includes("".concat(getDecoratorName(node)))) {
return processInject(ctx, node, sf, typeChecker);
}
// 处理 class
var classDecorators = ((_d = config === null || config === void 0 ? void 0 : config.decoratorNames) === null || _d === void 0 ? void 0 : _d.class) ||
((_f = (_e = pkg['power-di']) === null || _e === void 0 ? void 0 : _e.decoratorNames) === null || _f === void 0 ? void 0 : _f.class) || [
'classInfo',
'injectable',
'contribution',
'extension',
'plugin',
];
if (classDecorators.includes("".concat(getDecoratorName(node)))) {
return processClassInfo(ctx, node, pkg, sf, typeChecker);
}
return node;
};
}
exports.before = before;
function processClassInfo(ctx, node, pkg, sourceFile, typeChecker) {
var _a;
var clsNode = node.parent;
if (!ts.isClassDeclaration(clsNode) || !ts.isCallExpression(node.expression)) {
return node;
}
var decoratorFactory = node.expression;
if (decoratorFactory.arguments &&
decoratorFactory.arguments[0] &&
!ts.isObjectLiteralExpression(decoratorFactory.arguments[0])) {
console.warn('[power-di] class metadata transformer fail!', "@".concat(getDecoratorName(node), " of class [").concat(clsNode.name.escapedText, "] param is not a ObjectLiteral."));
return node;
}
var oldArg = decoratorFactory.arguments.length && decoratorFactory.arguments[0];
var oldArgObj = oldArg && ts.isObjectLiteralExpression(oldArg) && oldArg;
var impls = !hasField(oldArgObj, 'implements') &&
((_a = clsNode.heritageClauses) === null || _a === void 0 ? void 0 : _a.find(function (hc) { return hc.token === ts.SyntaxKind.ImplementsKeyword; }));
impls &&
impls.types.forEach(function (typeNode) {
var _a, _b, _c;
var type = typeChecker.getTypeFromTypeNode(typeNode);
var symbol = type.getSymbol();
fixedImport(ctx, (symbol === null || symbol === void 0 ? void 0 : symbol.name) ||
((_a = typeNode.getText) === null || _a === void 0 ? void 0 : _a.call(typeNode)) ||
((_c = (_b = typeNode.expression).getText) === null || _c === void 0 ? void 0 : _c.call(_b)) ||
typeNode.expression.escapedText, sourceFile);
});
var f = ctx.factory;
var info = [
f.createPropertyAssignment('pkg', f.createStringLiteral(pkg.name)),
f.createPropertyAssignment('version', f.createStringLiteral(pkg.version)),
impls &&
f.createPropertyAssignment('implements', f.createArrayLiteralExpression(impls.types.map(function (type) { return type.expression; }))),
].filter(function (s) { return s; });
var config = oldArgObj
? f.updateObjectLiteralExpression(oldArgObj, f.createNodeArray(__spreadArray(__spreadArray([], info, true), oldArgObj.properties.filter(function (p) {
return p.name &&
ts.isIdentifier(p.name) &&
!['pkg', 'version', impls ? 'implements' : undefined]
.filter(function (s) { return s; })
.includes("".concat(p.name.escapedText));
}), true)))
: f.createObjectLiteralExpression(f.createNodeArray(info), false);
return f.updateDecorator(node, f.updateCallExpression(decoratorFactory, decoratorFactory.expression, decoratorFactory.typeArguments, [config]));
}
function processInject(ctx, node, sourceFile, typeChecker) {
var _a, _b, _c, _d, _e, _f;
var propertyNode = node.parent;
if (!ts.isPropertyDeclaration(propertyNode) || !ts.isCallExpression(node.expression)) {
return node;
}
var decoratorFactory = node.expression;
if (decoratorFactory.arguments &&
decoratorFactory.arguments[0] &&
!ts.isObjectLiteralExpression(decoratorFactory.arguments[0])) {
console.warn('[power-di] class metadata transformer fail!', "@".concat(getDecoratorName(node), " of class [").concat((_b = (_a = propertyNode.name).getText) === null || _b === void 0 ? void 0 : _b.call(_a), "] param is not a ObjectLiteral."));
return node;
}
var oldArg = decoratorFactory.arguments.length && decoratorFactory.arguments[0];
var oldArgObj = oldArg && ts.isObjectLiteralExpression(oldArg) && oldArg;
var refType = propertyNode.type
? ts.isTypeReferenceNode(propertyNode.type)
? propertyNode.type
: ts.isArrayTypeNode(propertyNode.type)
? ts.isTypeReferenceNode(propertyNode.type.elementType)
? propertyNode.type.elementType
: undefined
: undefined
: undefined;
if (!refType) {
return node;
}
var identifier = refType.typeName;
if (identifier.escapedText === 'Array') {
identifier = (_c = refType.typeArguments[0]) === null || _c === void 0 ? void 0 : _c.typeName;
if (!identifier) {
console.warn('[power-di] class metadata transformer fail!', getDecoratorName(node), (_e = (_d = propertyNode.name).getText) === null || _e === void 0 ? void 0 : _e.call(_d), (_f = refType.getText) === null || _f === void 0 ? void 0 : _f.call(refType));
return node;
}
}
fixedImport(ctx, identifier.escapedText, sourceFile);
var f = ctx.factory;
var info = [
f.createPropertyAssignment('type', identifier),
propertyNode.questionToken && f.createPropertyAssignment('optional', f.createTrue()),
].filter(function (s) {
if (!s) {
return false;
}
if (!oldArgObj) {
return true;
}
return !oldArgObj.properties.some(function (p) {
return ts.isIdentifier(p.name) &&
ts.isIdentifier(s.name) &&
p.name.escapedText === s.name.escapedText;
});
});
var config = oldArgObj
? f.updateObjectLiteralExpression(oldArgObj, f.createNodeArray(__spreadArray(__spreadArray([], info, true), oldArgObj.properties, true)))
: f.createObjectLiteralExpression(f.createNodeArray(info), false);
return f.updateDecorator(node, f.updateCallExpression(decoratorFactory, decoratorFactory.expression, decoratorFactory.typeArguments, [config]));
}
var pkgCache = [];
function findPkg(filePath) {
if (filePath === '/') {
return;
}
var parsed = path.parse(filePath);
var cache = pkgCache
.sort(function (a, b) { return b.path.length - a.path.length; })
.find(function (pc) { return parsed.dir === pc.path; });
if (cache) {
return cache.pkg;
}
var pkgPath = path.join(parsed.dir, 'package.json');
if (!fs.existsSync(pkgPath)) {
return findPkg(parsed.dir);
}
var pkgData = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
pkgCache.push({ path: parsed.dir, pkg: pkgData });
return pkgData;
}
function getDecoratorName(node) {
if (!node) {
return '';
}
return ts.isIdentifier(node.expression)
? node.expression.escapedText
: ts.isCallExpression(node.expression) && ts.isIdentifier(node.expression.expression)
? node.expression.expression.escapedText
: '';
}
function getField(config, fieldName) {
var prop = config &&
ts.isObjectLiteralExpression(config) &&
config.properties.find(function (p) {
return p.name && ts.isIdentifier(p.name) && p.name.escapedText === fieldName;
});
return prop && ts.isPropertyAssignment(prop) && prop;
}
function hasField(config, fieldName) {
return !!getField(config, fieldName);
}
function fixedImport(ctx, escapedText, sourceFile) {
if (!escapedText) {
console.warn('fixedImport no escapedText!', sourceFile.fileName);
return;
}
// IFoo<IBar> => IFoo
escapedText = "".concat(escapedText).split('<')[0];
sourceFile.statements
.filter(function (n) { return ts.isImportDeclaration(n); })
.forEach(function (im) {
var _a, _b;
var nb = (_a = im.importClause) === null || _a === void 0 ? void 0 : _a.namedBindings;
var el = (_b = nb === null || nb === void 0 ? void 0 : nb.elements) === null || _b === void 0 ? void 0 : _b.find(function (el) {
return el.name.escapedText === escapedText;
});
if (el) {
im.flags = im.flags | ts.NodeFlags.Synthesized;
}
});
}
//# sourceMappingURL=classMetadata.js.map