UNPKG

@lcap/nasl

Version:

NetEase Application Specific Language

330 lines 15.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.backtracking = exports.tracking = exports.IGNORE_PROPERTY = exports.TRACK_TYPE = void 0; const nasl_concepts_1 = require("@lcap/nasl-concepts"); exports.TRACK_TYPE = { PLAIN: 'plain', PROPERTY: 'property', ARRAY: 'array', ARRAY_NO_FURTHER: 'array_no_further', CALLEE: 'callee', CALLEE_TEMPLATE: 'callee_template', MODULE: 'module', ROLE_TEMPLATE: 'role_template', PROPERTY_TEMPLATE: 'property_template', // INTERNAL: 'internal' }; const ENTITY_AS_NAME = 'entityAsName'; const BACKTACKING_PROPERTY_NS = { NAMESPACE: 'namespace', TYPE_NAMESPACE: 'typeNamespace', CALLEE_NAMESPACE: 'calleeNamespace', ENTITY_NAMESPACE: 'entityNamespace', RELATION_NAMESPACE: 'relationNamespace', }; const BACKTACKING_PROPERTY = { NAMESPACE: 'name', TYPE_NAMESPACE: 'typeName', CALLEE_NAMESPACE: 'calleeName', ENTITY_NAMESPACE: 'entityName', RELATION_NAMESPACE: 'relationEntity', }; const BACKTRACKING_MODULE_COMPONENT = 'tag'; function getRelatedProperyName(nspropertyname) { switch (nspropertyname) { case BACKTACKING_PROPERTY_NS.NAMESPACE: return BACKTACKING_PROPERTY.NAMESPACE; case BACKTACKING_PROPERTY_NS.TYPE_NAMESPACE: return BACKTACKING_PROPERTY.TYPE_NAMESPACE; case BACKTACKING_PROPERTY_NS.CALLEE_NAMESPACE: return BACKTACKING_PROPERTY.CALLEE_NAMESPACE; case BACKTACKING_PROPERTY_NS.ENTITY_NAMESPACE: return BACKTACKING_PROPERTY.ENTITY_NAMESPACE; case BACKTACKING_PROPERTY_NS.RELATION_NAMESPACE: return BACKTACKING_PROPERTY.RELATION_NAMESPACE; } return ''; } const TRACKING_ONLY_ONE_LAYER = ['DataSource']; const BACKTRACKING_IGNORE_NAMESPACE = [ 'nasl.core', '', // ... ]; // eslint-disable-next-line camelcase function isBACKTRACKING_IGNORE_NAMESPACE(ns) { // 组件的名称应该不会被覆盖改变 return ns.startsWith('nasl') || ns.startsWith('elements'); } exports.IGNORE_PROPERTY = [ 'uuid', // View 属性 'origin', // Entity 属性 'changedTime', 'branchName', 'appId', 'isIndex', // 'tableName', // 'columnName', ]; const ROLE_PROPERTY = 'bindRoles'; // const UPPER_CONCEPT = [ // 'Entity', // 'Structure', // 'Enum', // 'Logic', // 'Interface', // 'View', // 'Process', // 'Role', // ]; function tracking(node, startNode, callback) { const { propertyMap } = (0, nasl_concepts_1.getConceptMeta)(node.concept); for (const p of propertyMap) { // console.log(p) const [propertyName, _data] = p; const { objectRef } = _data; // console.log(propertyName) if (exports.IGNORE_PROPERTY.includes(propertyName)) { if (propertyName === 'origin') { callback(exports.TRACK_TYPE.PLAIN, 'origin', 'ide'); } continue; } const isOnlyOneLayerTracking = TRACKING_ONLY_ONE_LAYER.includes(node.concept); const property = node[propertyName]; if (Array.isArray(property)) { if (property.length > 0) { if (property[0] instanceof nasl_concepts_1.BaseNode) { if (!isOnlyOneLayerTracking) { property.forEach((p) => { callback(exports.TRACK_TYPE.ARRAY, propertyName, p); }); } else { property.forEach((p) => { callback(exports.TRACK_TYPE.ARRAY_NO_FURTHER, propertyName, p); }); } } else { if (ROLE_PROPERTY === propertyName) { const rootNode = node.rootNode; const metaNodes = []; property.forEach((rname) => { const targetRole = rootNode.roles.find((r) => r.name === rname); if (targetRole) { metaNodes.push(targetRole); } }); callback(exports.TRACK_TYPE.ROLE_TEMPLATE, propertyName, property, { rootNode: node, metaNodes, }); } else { callback(exports.TRACK_TYPE.PLAIN, propertyName, property); } } } } else { let relatedPropertyName; let rootNode; let ns; switch (propertyName) { case BACKTACKING_PROPERTY_NS.NAMESPACE: // relatedPropertyName = getRelatedProperyName(propertyName); // console.log(relatedPropertyName); // break; case BACKTACKING_PROPERTY_NS.TYPE_NAMESPACE: // relatedPropertyName = BACKTACKING_PROPERTY.TYPE_NAMESPACE case BACKTACKING_PROPERTY_NS.CALLEE_NAMESPACE: // relatedPropertyName = BACKTACKING_PROPERTY.CALLEE_NAMESPACE case BACKTACKING_PROPERTY_NS.ENTITY_NAMESPACE: // relatedPropertyName = BACKTACKING_PROPERTY.ENTITY_NAMESPACE case BACKTACKING_PROPERTY_NS.RELATION_NAMESPACE: // relatedPropertyName = BACKTACKING_PROPERTY.RELATION_NAMESPACE relatedPropertyName = getRelatedProperyName(propertyName); rootNode = node.rootNode; ns = node[propertyName]; if (!ns || !node[relatedPropertyName]) { callback(exports.TRACK_TYPE.PLAIN, propertyName, property); callback(exports.TRACK_TYPE.PLAIN, relatedPropertyName, node[relatedPropertyName]); break; } // console.log(node, propertyName) if (isBACKTRACKING_IGNORE_NAMESPACE(ns)) { callback(exports.TRACK_TYPE.PLAIN, propertyName, property); callback(exports.TRACK_TYPE.PLAIN, relatedPropertyName, node[relatedPropertyName]); } else { const calleeN = node[relatedPropertyName]; const r1 = /app\.processes\.([^.]+)\.logics/.exec(ns); const r2 = /app\.processes\.([^.]+)\.elements\.([^.]+)\.logics/.exec(ns); if (r1 || r2) { // Process 处理 if (r2) { const nodeName = r2[1]; const subNodename = r2[2]; if (subNodename) { // 目前只有 userTask const process = rootNode.processes.find((p) => p.name === nodeName); if (process) { const usertask = process.elements.find((e) => e.name === subNodename); if (usertask) { callback(exports.TRACK_TYPE.CALLEE_TEMPLATE, propertyName, node[propertyName], { rootNode: process, metaNodes: [process, usertask], nstemplate: `function(meta, meta2){ return "app.processes" + meta.name + ".elements." + meta2.name + ".logics"; }`, nametemplate: `function(meta, meta2){ return "complete"; }`, relatedPropertyName, AppPropertyName: 'processes', }); break; } } } } else if (r1) { const nodeName = r1[1]; const process = rootNode.processes.find((p) => p.name === nodeName); if (/launch/.test(calleeN) && process) { // const prefix = /(launch|complete).+/.exec(calleeN)[1]; callback(exports.TRACK_TYPE.CALLEE_TEMPLATE, propertyName, node[propertyName], { rootNode: process, metaNodes: [process], nstemplate: `function(meta){ return "app.processes" + meta.name + ".logics"; }`, nametemplate: `function(){ return "${calleeN}"; }`, relatedPropertyName, AppPropertyName: 'processes', }); break; } } } const r3 = /app\.dataSources\.([^.]+)\.entities\.([^.]+)\.logics/.exec(ns); if (r3) { const datasourceName = r3[1]; const entityName = r3[2]; if (/get|create|update|delete|createOrUpdate|updateBy|deleteBy|batchCreate|batchUpdate|batchDelete|import/.test(calleeN)) { // const prefix = /(get|create|update|delete|batchCreate|batchUpdate|batchDelete|import)/.exec(calleeN)[1]; const datasource = rootNode.dataSources.find((d) => d.name === datasourceName); if (datasource) { const entity = datasource.entities.find((e) => e.name === entityName); callback(exports.TRACK_TYPE.CALLEE_TEMPLATE, propertyName, node[propertyName], { rootNode: datasource, metaNodes: [datasource, entity], nstemplate: `function(meta, meta2){ return "app.dataSources." + meta.name + ".entities." + meta2.name + ".logics"; }`, nametemplate: `function(){ return "${calleeN}"; }`, relatedPropertyName, AppPropertyName: 'dataSources', }); break; } } } const nsPath = `${ns}.${calleeN}`; const calleeNode = getNodeByNodeCallee(rootNode, nsPath); if (calleeNode) { backtracking({ node, startNode, calleeNode, propertyName, relatedPropertyName, }, callback); } } break; case BACKTACKING_PROPERTY.TYPE_NAMESPACE: case BACKTACKING_PROPERTY.CALLEE_NAMESPACE: case BACKTACKING_PROPERTY.ENTITY_NAMESPACE: case BACKTACKING_PROPERTY.RELATION_NAMESPACE: break; case ENTITY_AS_NAME: // 现在还不存在 asName 先直接当 Entity 名称来用。 callback(exports.TRACK_TYPE.PROPERTY_TEMPLATE, propertyName, property, { getRelatedVar: () => { const queryCom = node.getAncestor('CallQueryComponent'); const entityNamespace = queryCom?.from?.entityNamespace; if (queryCom && entityNamespace && property) { const rootNode = queryCom.rootNode; const entity = getNodeByNodeCallee(rootNode, `${entityNamespace}.${property}`); return entity; } return null; }, relatedProperty: 'name', }); break; case BACKTRACKING_MODULE_COMPONENT: // 条件 break 一定要放到最后 if (node.concept === 'ViewElement') { const componentDependencies = node.frontend?.componentDependencies || []; const tag = node[propertyName]; const dep = componentDependencies.find((c) => c.name === tag); if (dep) { callback(exports.TRACK_TYPE.PLAIN, propertyName, tag); callback(exports.TRACK_TYPE.MODULE, undefined, dep); break; } } default: if (property !== undefined) { if (objectRef && property !== null) { callback(exports.TRACK_TYPE.PROPERTY, propertyName, property); } else { callback(exports.TRACK_TYPE.PLAIN, propertyName, property); } } break; } } } } exports.tracking = tracking; function getAppPropertyName(node) { const { propertyMap } = (0, nasl_concepts_1.getConceptMeta)('App'); const concept = node.concept; for (const item of propertyMap) { const [key, meta] = item; if (meta.objectRef === concept) { return key; } } return undefined; } function backtracking({ node, startNode, calleeNode, propertyName, relatedPropertyName }, callback) { const m = calleeNode.getAncestor('Module'); if (m) { callback(exports.TRACK_TYPE.PLAIN, propertyName, node[propertyName]); callback(exports.TRACK_TYPE.PLAIN, relatedPropertyName, node[relatedPropertyName]); callback(exports.TRACK_TYPE.MODULE, undefined, m); return; } const approot = calleeNode.rootNode; // 向上查找到顶层,然后向下构造 template let t = calleeNode; let AppPropertyName; while (t) { const pnode = t.parentNode; if (pnode === approot) { AppPropertyName = getAppPropertyName(t); } if (pnode !== approot && pnode !== startNode) { t = pnode; } else { break; } } callback(exports.TRACK_TYPE.CALLEE, propertyName, node[propertyName], { rootNode: t, calleeNode, relatedPropertyName, AppPropertyName, }); } exports.backtracking = backtracking; //# sourceMappingURL=utils.js.map