@lcap/nasl
Version:
NetEase Application Specific Language
430 lines • 18.3 kB
JavaScript
;
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