UNPKG

@lcap/builder

Version:
225 lines (224 loc) 11.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const logger_1 = __importDefault(require("../utils/logger")); const babel_utils_1 = require("../utils/babel-utils"); const ts2nasl_1 = require("../ts2nasl"); function transformFunc2NaslLogic(node) { if (node.type !== 'ExportNamedDeclaration' || !node.declaration || node.declaration.type !== 'FunctionDeclaration' || !node.leadingComments || node.leadingComments.findIndex((c) => c.value.includes('@NaslLogic')) === -1) { return null; } const logicComment = { title: '', description: '', type: '', params: {}, typeParams: {}, returns: '', }; node.leadingComments.forEach((block) => { if (!block.value.includes('@NaslLogic')) { return; } block.value.split('\n').forEach((text) => { switch (true) { case text.includes('@title '): logicComment.title = (text.split('@title ')[1] || '').trim(); break; case text.includes('@description '): logicComment.description = (text.split('@description ')[1] || '').trim(); break; case text.includes('@desc '): logicComment.description = (text.split('@desc ')[1] || '').trim(); break; case text.includes('@type '): const typeKind = (text.split('@type ')[1] || '').trim(); if (['both', 'pc', 'h5'].indexOf(typeKind) === -1) { logicComment.type = 'pc'; } else { logicComment.type = typeKind; } break; case text.includes('@typeParam '): const tempTypeText = text.substring(text.indexOf('@typeParam ') + '@typeParam '.length); const [typeName, ...typeValue] = tempTypeText.split(' '); if (typeValue.length === 0) { break; } logicComment.typeParams[typeName] = typeValue.join(''); break; case text.includes('@param '): const tempText = text.substring(text.indexOf('@param ') + '@param '.length); const [name, ...value] = tempText.split(' '); if (value.length === 0) { break; } logicComment.params[name] = value.join(''); break; case text.includes('@returns '): logicComment.returns = (text.split('@returns ')[1] || '').trim(); break; case text.includes('@return '): logicComment.returns = (text.split('@return ')[1] || '').trim(); break; default: break; } }); }); const logic = { concept: 'Logic', name: node.declaration.id ? node.declaration.id.name : '', title: logicComment.title, description: logicComment.description, triggerType: '', cron: '', overridable: false, variables: [], body: [], typeParams: [], params: [], returns: [], playground: [], }; if (node.declaration.typeParameters && node.declaration.typeParameters.type === 'TSTypeParameterDeclaration' && node.declaration.typeParameters.params && node.declaration.typeParameters.params.length > 0) { logic.typeParams = node.declaration.typeParameters.params.map((t) => { if (t.constraint || t.default) { const errorMsg = `解析逻辑失败 ${logic.name} ${(0, babel_utils_1.getNodeCode)(t)}, 泛型不支持使用 extends 或 = 等表达式`; logger_1.default.error(errorMsg); throw new Error(errorMsg); } return { concept: 'TypeParam', name: t.name, displayName: logicComment.typeParams[t.name] || '', }; }); } try { const typeNames = logic.typeParams.map((t) => t.name); if (node.declaration.params && node.declaration.params.length > 0) { node.declaration.params.forEach((param) => { let name; let typeAnnotation; let defaultValue; let spread = false; if (param.type === 'Identifier' && param.typeAnnotation && param.typeAnnotation.type === 'TSTypeAnnotation') { typeAnnotation = (0, ts2nasl_1.transformTsType2Nasl)(param.typeAnnotation.typeAnnotation, typeNames); name = param.name; } else if (param.type === 'RestElement' && param.argument.type === 'Identifier' && param.typeAnnotation && param.typeAnnotation.type === 'TSTypeAnnotation') { if (param.typeAnnotation.typeAnnotation.type === 'TSTypeReference' && ((param.typeAnnotation.typeAnnotation.typeName.type === 'TSQualifiedName' && param.typeAnnotation.typeAnnotation.typeName.right.name === 'List') || (param.typeAnnotation.typeAnnotation.typeName.type === 'Identifier' && param.typeAnnotation.typeAnnotation.typeName.name === 'Array')) && param.typeAnnotation.typeAnnotation.typeParameters && param.typeAnnotation.typeAnnotation.typeParameters.params && param.typeAnnotation.typeAnnotation.typeParameters.params.length > 0) { typeAnnotation = (0, ts2nasl_1.transformTsType2Nasl)(param.typeAnnotation.typeAnnotation.typeParameters.params[0], typeNames); } else if (param.typeAnnotation.typeAnnotation.type === 'TSArrayType') { typeAnnotation = (0, ts2nasl_1.transformTsType2Nasl)(param.typeAnnotation.typeAnnotation.elementType, typeNames); } else { typeAnnotation = (0, ts2nasl_1.transformTsType2Nasl)(param.typeAnnotation.typeAnnotation, typeNames); } name = param.argument.name; spread = true; } else if (param.type === 'AssignmentPattern' && param.left.type === 'Identifier' && param.left.typeAnnotation && param.left.typeAnnotation.type === 'TSTypeAnnotation') { name = param.left.name; typeAnnotation = (0, ts2nasl_1.transformTsType2Nasl)(param.left.typeAnnotation.typeAnnotation, typeNames); defaultValue = { concept: 'DefaultValue', expression: (0, ts2nasl_1.transformExpression2nasl)(param.right), playground: [], }; } if (name && typeAnnotation) { const p = { concept: 'Param', name, description: logicComment.params[name], typeAnnotation, spread, }; if (defaultValue) { p.defaultValue = defaultValue; } else if (param.optional) { p.defaultValue = { concept: 'DefaultValue', expression: typeAnnotation.typeKind === 'function' ? { concept: 'SubLogic', name: '', params: (typeAnnotation.typeArguments || []).map((arg, index) => ({ concept: 'Param', name: `param${index + 1}`, description: '', typeAnnotation: arg, })), returns: (typeAnnotation.returnType || []).map((t, i) => ({ concept: 'Return', name: `result${i > 0 ? `_${i}` : ''}`, description: '', typeAnnotation: t, })), variables: [], playground: [], body: [ { concept: 'Start', }, { concept: 'End', }, ], } : { concept: 'NullLiteral', }, playground: [], }; } logic.params.push(p); return; } const errorMsg = `解析逻辑失败 ${name} ${(0, babel_utils_1.getNodeCode)(param)}, 参数不支持解析,请检查类型是否使用 @nasl/types`; logger_1.default.error(errorMsg); throw new Error(errorMsg); }); } if (node.declaration.returnType && node.declaration.returnType.type === 'TSTypeAnnotation') { const hasSubLogic = logic.params.findIndex((p) => p.typeAnnotation && p.typeAnnotation.typeKind === 'function') !== -1; const { typeAnnotation: tsType } = node.declaration.returnType; if (hasSubLogic && (tsType.type !== 'TSTypeReference' || tsType.typeName.type !== 'Identifier' || tsType.typeName.name !== 'Promise')) { const errorMsg = `解析逻辑失败 ${logic.name}, 该逻辑含有高阶函数(用函数作为参数),返回值类型强制需要为 Promise!`; logger_1.default.error(errorMsg); throw new Error(errorMsg); } const returnType = (0, ts2nasl_1.transformTsType2Nasl)(tsType, typeNames); if (returnType) { logic.returns.push({ concept: 'Return', name: 'result', description: logicComment.returns, typeAnnotation: returnType, }); } } } catch (e) { logger_1.default.error(`解析逻辑失败 ${logic.name}: ${e.message}`); throw e; } return Object.assign(Object.assign({}, logic), { type: logicComment.type }); } exports.default = transformFunc2NaslLogic;