UNPKG

@lcap/nasl

Version:

NetEase Application Specific Language

430 lines 18.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getNodeRelationTypes = exports.getRelationTypesFromTypeAnnotation = exports.genAIUID = exports.replaceId = exports.deduceTypeAll = exports.deduceType = exports.handleReNameJSON = exports.getUnImportedModulesForLogic = exports.getUsedModule = exports.getLogicType = void 0; const utils = __importStar(require("../utils")); const translator_1 = require("../translator"); const nasl_concepts_1 = require("@lcap/nasl-concepts"); // 获取当前逻辑的类型 const getLogicType = (activeLogic) => { const { parentNode } = activeLogic || {}; let logicType = 'global_logic'; if (parentNode?.concept === 'View') { logicType = 'view_logic'; } else if (parentNode?.concept === 'BindEvent') { logicType = 'event_logic'; } if (activeLogic?.concept === 'BusinessLogic') { logicType = 'business_Logic'; } return logicType; }; exports.getLogicType = getLogicType; // 获取所有未使用的 module const getUsedModule = (json) => { const useModule = []; const conceptMap = ['CallInterface', 'CallConnector', 'CallLogic']; utils.traverse(({ node }) => { if (conceptMap.includes(node.concept)) { if (/(apis\.|connector\.|extensions\.)/.test(node.calleeNamespace)) { const symbol = node.calleeNamespace.match(/(\w+)(?=\.)|(\w+$)/g)[1]; const item = { symbol, key: symbol, node, }; useModule.push(item); } } if (node.concept === 'ViewElement' && node?.tag) { const symbol = utils.kebab2Camel(node.tag); const item = { symbol, key: symbol, node, }; useModule.push(item); } }, { node: json }, { mode: 'anyObject' }); return useModule; }; exports.getUsedModule = getUsedModule; /** * 根据生成的 NASL JSON,获取未导入的模块 * @param json: 当前生成的 NASL JSON * @param app: 当前应用 * @param material: 召回的所有 Module * @returns 需要导入的所有 Module 信息,包含 category、symbol、version */ const getUnImportedModulesForLogic = (json, app, material) => { const useModule = (0, exports.getUsedModule)(json); const needImportModule = { interfaces: new Map(), connectors: new Map(), reNameConnectors: new Map(), library: new Map(), extensionMaterials: new Map(), needImportConnector: false, }; useModule.forEach((item) => { if (item.node.concept === 'CallInterface') { // 从app.interfaceDependencies中找到对应的接口 const interfaceNode = app.interfaceDependencies?.find((node) => node.name === item.symbol); if (!interfaceNode) { const curDep = material?.moduleInterfaces?.find((node) => node.name === item.symbol); item.category = 'interface'; const key = `${item.symbol}-${item?.node?.calleeName}`; item.key = key; item.title = curDep?.title || ''; needImportModule.interfaces.set(key, item); } } else if (item.node.concept === 'CallConnector') { item.category = 'connector'; const connectorNode = app.connectorDependencies?.find((node) => node.name === item.symbol); // 如果 连接器 不存在,则需要导入并初始化连接 if (!connectorNode) { item.operator = 'importAndInit'; const curDep = material?.connectors?.find((node) => node.name === item.symbol); if (curDep) { item.version = curDep?.version; item.title = curDep?.title; item.provider = curDep?.provider || '资产中心'; needImportModule.needImportConnector = true; needImportModule.connectors.set(item.symbol, item); } } else { item.version = connectorNode.version; item.title = connectorNode?.title; // 查找连接 const connection = app.connections?.find((conn) => conn.connector.name === item.symbol); // 如果 连接器 已存在,且连接已经被初始化过,需要修改生成 logic 中的名字,utils.traverse 修改 // 如果 连接器 已存在,且连接未被初始化过,则需要初始化连接 if (connection) { item.operator = 'rename'; const oldName = item.node.calleeConnectionName; if (connection.name !== oldName) { item.rename = { newName: connection.name, oldName }; needImportModule.reNameConnectors.set(item.symbol, item); } } else { item.operator = 'init'; needImportModule.connectors.set(item.symbol, item); } } } else if (item.node.concept === 'CallLogic') { // 从app.logicDependencies中找到对应的逻辑 item.category = 'library'; const logicNode = app.dependencies?.find((node) => node.name === item.symbol); if (!logicNode) { const curDep = material?.dependencies?.find((node) => node.name === item.symbol); if (curDep) { item.version = curDep?.version; item.title = curDep?.title; item.provider = curDep?.provider || '资产中心'; needImportModule.library.set(item.symbol, item); } } } else if (item.node.concept === 'ViewElement') { const name = utils.kebab2Camel(item.node.tag); const module = material?.extensionMaterials?.find((node) => utils.kebab2Camel(node.name) === name); const imported = app.dependencies?.find((node) => node.name === module?.libraryName); if (module && module.libraryName && !imported) { const { libraryName } = module; item.category = 'library'; item.key = `${libraryName}-${name}`; item.symbol = libraryName; const curDep = material?.dependencies?.find((node) => node.name === item.symbol); if (curDep) { item.version = curDep?.version; item.title = curDep?.title; item.provider = curDep?.provider || ''; needImportModule.extensionMaterials.set(name, item); } } } }); needImportModule.interfaces = Array.from(needImportModule.interfaces.values()); needImportModule.connectors = Array.from(needImportModule.connectors.values()); needImportModule.reNameConnectors = Array.from(needImportModule.reNameConnectors.values()); needImportModule.library = Array.from(needImportModule.library.values()); needImportModule.extensionMaterials = Array.from(needImportModule.extensionMaterials.values()); return needImportModule; }; exports.getUnImportedModulesForLogic = getUnImportedModulesForLogic; // rename - 遍历重命名 需要返回新的 json const handleReNameJSON = (renameNodes, json) => { if (renameNodes.length > 0) { utils.traverse(({ node }) => { if (node.concept === 'CallConnector') { const curItem = renameNodes.find((item) => item?.rename.oldName === node.calleeConnectionName); if (curItem) { node.calleeConnectionName = curItem.rename.newName; } } }, { node: json }, { mode: 'anyObject' }); } return json; }; exports.handleReNameJSON = handleReNameJSON; /** * 找到当前节点所使用的当前逻辑、服务端逻辑、组件相关的推导类型 * @param app: 当前应用 * @returns 推导类型集合 */ const deduceType = async (app, activeDesignerNode) => { const typeMap = {}; const { logics } = app; const state = (0, translator_1.createCompilerState)('', { descriptionComment: true, needNamespace: true }); logics.forEach((logic) => { if (logic?.returns?.length && !logic.name.startsWith('LCAP')) { const ret = logic.returns[0]; const typeAnnotation = ret?.typeAnnotation || ret?.__TypeAnnotation; if (typeAnnotation) typeMap[ret.nodePath] = typeAnnotation.toNaturalTS(state); } }); const params = activeDesignerNode?.params.concat(activeDesignerNode?.virtualParams || []); if (params?.length) { let code = ''; params?.forEach((param, index) => { let curCode = ''; if (param.name === 'event') curCode += ''; else curCode += param.toNaturalTS(state); if (curCode && index !== params.length - 1) curCode += ', '; code += curCode; }); if (code) typeMap[activeDesignerNode.nodePath] = code; } const variables = activeDesignerNode?.variables || []; if (variables?.length) { variables?.forEach((variable) => { typeMap[variable.nodePath] = variable.toNaturalTS(state); }); } const view = activeDesignerNode?.concept === 'View' ? activeDesignerNode?.elements?.[0] : activeDesignerNode.getAncestor('View')?.elements?.[0]; if (view) { const dataSchemaMap = {}; utils.traverse(({ node }) => { if (node.concept === 'ViewElement') { const dataSchema = node.bindAttrs.find((_) => _.name === 'dataSchema'); if (dataSchema) dataSchemaMap[dataSchema.nodePath] = node; } }, { node: view }); await Promise.all(Object.entries(dataSchemaMap).map(async ([nodePath, node]) => { if (app.naslServer?.getDataSchemaStructureOrTypeAnnotation) { const res = await app.naslServer?.getDataSchemaStructureOrTypeAnnotation(node); if (res) { const dataSchemaTs = res.toNaturalTS(state); typeMap[nodePath] = dataSchemaTs; } } })); } return { typeMap }; }; exports.deduceType = deduceType; /** * 组合所有的可推导类型 * @param app: 当前应用 * @returns 推导类型集合 */ const deduceTypeAll = async (app) => { const typeMap = {}; const { logics } = app; const state = (0, translator_1.createCompilerState)('', { descriptionComment: true, needNamespace: true }); logics.forEach((logic) => { if (logic?.returns?.length && !logic.name.startsWith('LCAP')) { const ret = logic.returns[0]; const typeAnnotation = ret?.typeAnnotation || ret?.__TypeAnnotation; if (typeAnnotation) typeMap[ret.nodePath] = typeAnnotation.toNaturalTS(state); const variables = logic?.variables || []; if (variables?.length) { variables?.forEach((variable) => { typeMap[variable.nodePath] = variable.toNaturalTS(state); }); } } }); const dataSchemaMap = {}; utils.traverse(({ node }) => { if (node?.concept === 'ViewElement') { const dataSchema = node.bindAttrs.find((_) => _.name === 'dataSchema'); if (dataSchema) dataSchemaMap[dataSchema.nodePath] = node; } if (node?.concept === 'Logic' && node?.parentNode?.concept === 'BindEvent') { const params = node?.params.concat(node?.virtualParams || []); if (params?.length) { let code = ''; params?.forEach((param, index) => { let curCode = ''; if (param.name === 'event') curCode += ''; else curCode += param.toNaturalTS(state); if (curCode && index !== params.length - 1) curCode += ', '; code += curCode; }); if (code) typeMap[node.nodePath] = code; } } }, { node: app }, { mode: 'onlyArray' }); await Promise.all(Object.entries(dataSchemaMap).map(async ([nodePath, node]) => { if (app.naslServer?.getDataSchemaStructureOrTypeAnnotation) { const res = await app.naslServer?.getDataSchemaStructureOrTypeAnnotation(node); if (res) { const dataSchemaTs = res.toNaturalTS(state); typeMap[nodePath] = dataSchemaTs; } } })); return { typeMapAll: typeMap }; }; exports.deduceTypeAll = deduceTypeAll; // 更改id const replaceId = (node) => { utils.traverse(({ node }) => { if (node.hasOwnProperty('id') && node?.concept !== 'TypeAnnotation') { const hash = utils.uuidv4().replace(/-/g, ''); node.id = hash; } }, { node }, { mode: 'onlyArray', depthFirst: true }); return node; }; exports.replaceId = replaceId; // 根据 sessionId 生成 _aiUID const genAIUID = (node, sessionId, num) => { let temp = node.elements; if (node.concept === 'View') { node.elements = []; } const hash = utils.uuidv4().replace(/-/g, '').slice(0, 4); let number = num ?? 0; utils.traverse(({ node }) => { if (node.hasOwnProperty('_aiUID')) { const uuid = `${sessionId}_${hash}_${number}`; node._aiUID = uuid; number += 1; } }, { node }, { mode: 'anyObject', depthFirst: true }); node.elements = temp; return { node, number }; }; exports.genAIUID = genAIUID; /** * 获取关系类型 * @typeAnnotation 类型注解 * @returns RelationType[] */ const getRelationTypesFromTypeAnnotation = (typeAnnotation) => { const nodeRelationTypes = []; const processedTypes = new Set(); (0, nasl_concepts_1.fastTraverseNaslObject)(typeAnnotation, (node) => { if (node?.concept === 'TypeAnnotation' && node?.typeKind === 'reference') { let key = `${node?.typeNamespace}.${node?.typeName}`; if (key.startsWith('connector.')) { key = 'connectors.' + key.slice('connector.'.length); } // 检查是否已经处理过这个类型 if (!processedTypes.has(key)) { processedTypes.add(key); nodeRelationTypes.push(key); } } }); return nodeRelationTypes; }; exports.getRelationTypesFromTypeAnnotation = getRelationTypesFromTypeAnnotation; /** * 获取 nasl 节点关联的所有自定义类型 * @param app: nasl json 实例化版 * @param node: 节点 实例化版 * @param weight: 权重 */ const getNodeRelationTypes = (app, node, weight = 1) => { const relationMap = new Map(); const incrementRelation = (type, increment = 1) => { relationMap.set(type, (relationMap.get(type) || 0) + increment); }; const processedAnnotations = new Set(); const processTypeAnnotation = (annotation) => { const annotationId = annotation?.id || annotation?.nodePath; if (processedAnnotations.has(annotationId)) { return; } processedAnnotations.add(annotationId); const types = (0, exports.getRelationTypesFromTypeAnnotation)(annotation); for (const type of types) { incrementRelation(type); if (type?.includes('.entities.') || type?.includes('.structures.')) { let findType = type.replace(/^connectors\./, 'connector.'); const newNode = app.findNodeByCompleteName(findType); if (newNode) { const newRelationTypes = (0, exports.getNodeRelationTypes)(app, newNode, weight * 0.5); for (const relationType of newRelationTypes) { incrementRelation(relationType.name, relationType.score / weight); } } } } }; if (node.concept === 'Logic' || node.concept === 'Interface') { const variables = [...(node.params || []), ...(node.returns || []), ...(node.variables || [])]; for (const item of variables) { const typeAnnotation = item?.typeAnnotation || item?.__TypeAnnotation; if (typeAnnotation) { processTypeAnnotation(typeAnnotation); } } } else { const types = (0, exports.getRelationTypesFromTypeAnnotation)(node); for (const type of types) { incrementRelation(type); } } return Array.from(relationMap.entries(), ([name, count]) => ({ name, score: count * weight, })); }; exports.getNodeRelationTypes = getNodeRelationTypes; //# sourceMappingURL=tools.js.map