UNPKG

@ainc/script

Version:

Script compiler for typescript

196 lines 7.16 kB
/** ***************************************** * Created by edonet@163.com * Created on 2021-08-14 11:03:15 ***************************************** */ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.transformer = void 0; /** ***************************************** * 加载依赖 ***************************************** */ const ts = require("typescript"); /** ***************************************** * 获取工厂 ***************************************** */ const factory = ts.factory; /** ***************************************** * 判断是否为入口文件 ***************************************** */ function isMainFile(path) { return path.endsWith('index.ts') || path.endsWith('index.js'); } /** ***************************************** * 判断标识值 ***************************************** */ function isIdentifierValueOf(node, value) { return ts.isIdentifier(node) && node.text === value; } /** ***************************************** * 判断是否为载入函数 ***************************************** */ function isRequireCallExpression(node) { return node ? ts.isCallExpression(node) && isIdentifierValueOf(node.expression, 'require') : false; } /** ***************************************** * 判断是否为导出标识 ***************************************** */ function isExportIdentifier(node) { return ts.isIdentifier(node) && ts.isExportDeclaration(getOriginalNode(node)); } /** ***************************************** * 获取源节点 ***************************************** */ function getOriginalNode(node) { return node.original ? getOriginalNode(node.original) : node; } /** ***************************************** * 创建函数调用声明 ***************************************** */ function createCallExpression(name, args) { return factory.createCallExpression(name, [], args || []); } /** ***************************************** * 创建匿名函数表达式 ***************************************** */ function createAnonymousFunctionExpression(statements) { return factory.createFunctionExpression(undefined, undefined, undefined, [], [], undefined, factory.createBlock(statements, false)); } /** ***************************************** * 创建懒加载函数表达式 ***************************************** */ function createLazyRequireFunctionExpression(name, call) { const moduleId = factory.createIdentifier('__exports'); const moduleDecl = factory.createVariableDeclaration(moduleId, undefined, undefined, call); // 创建函数 return createAnonymousFunctionExpression([ factory.createVariableStatement(undefined, factory.createVariableDeclarationList([moduleDecl], ts.NodeFlags.None)), factory.createExpressionStatement(factory.createBinaryExpression(name, factory.createToken(ts.SyntaxKind.EqualsToken), createAnonymousFunctionExpression([factory.createReturnStatement(moduleId)]))), factory.createReturnStatement(moduleId), ]); } /** ***************************************** * 创建属性定义声明 ***************************************** */ function createObjectDefinePropertyExpression(target, prop, initializer) { return factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier('Object'), factory.createIdentifier('defineProperty')), undefined, [ target, factory.createStringLiteral(prop), factory.createObjectLiteralExpression([ factory.createPropertyAssignment(factory.createIdentifier('enumerable'), factory.createTrue()), factory.createPropertyAssignment(factory.createIdentifier('get'), initializer), ], false), ]); } /** ***************************************** * 转换文件内容 ***************************************** */ function transformSourceFile(sourceFile, context) { const moduleSymbols = new Set(); // 访问文件子节点 function visitNode(node) { // 处理载入标识 if (ts.isIdentifier(node) && moduleSymbols.has(node)) { return createCallExpression(node); } // 返回节点 return ts.visitEachChild(node, visitNode, context); } // 访问变量声明 function visitVariableDeclaration(node) { // 判断非声明语句 if (!ts.isVariableDeclaration(node)) { return ts.visitEachChild(node, visitVariableDeclaration, context); } // 获取初始初化声明 const call = node.initializer; const name = node.name; // 判断非载入函数初始化 if (!call || !isRequireCallExpression(call) || !isExportIdentifier(name)) { return ts.visitEachChild(node, visitNode, context); } // 添加标识 moduleSymbols.add(name); // 替换声明节点 return factory.updateVariableDeclaration(node, name, node.exclamationToken, node.type, createLazyRequireFunctionExpression(name, call)); } // 访问赋值表达式 function visitBinaryExpression(node) { // 判断非载入函数初始化 if (!ts.isBinaryExpression(node) || !isRequireCallExpression(node.right)) { return ts.visitEachChild(node, visitNode, context); } // 获取表达式值 const expr = node.left; const call = node.right; // 判断非导出属性 if (!ts.isPropertyAccessExpression(expr) || !isIdentifierValueOf(expr.expression, 'exports')) { return ts.visitEachChild(node, visitNode, context); } // 创建赋值语句 return createObjectDefinePropertyExpression(expr.expression, expr.name.text, createAnonymousFunctionExpression([factory.createReturnStatement(call)])); } // 访问文件子节点 function visitSourceFile(node) { // 处理载入函数 if (ts.isVariableStatement(node)) { return ts.visitEachChild(node, visitVariableDeclaration, context); } // 处理二元表达式 if (ts.isExpressionStatement(node)) { return ts.visitEachChild(node, visitBinaryExpression, context); } // 处理载入标识 if (moduleSymbols.size) { return ts.visitEachChild(node, visitNode, context); } // 返回节点 return node; } // 访问节点 return ts.visitEachChild(sourceFile, visitSourceFile, context); } /** ***************************************** * 转换器 ***************************************** */ function transformer(context) { const { target, module: moduleKind } = context.getCompilerOptions(); const isCommonJS = !moduleKind || moduleKind === ts.ModuleKind.CommonJS; // 不做处理 if (!target || !isCommonJS) { return sourceFile => sourceFile; } // 转换文件节点 return (sourceFile) => { return isMainFile(sourceFile.fileName) ? transformSourceFile(sourceFile, context) : sourceFile; }; } exports.transformer = transformer; //# sourceMappingURL=module-export-transformer.js.map