@lcap/nasl
Version:
NetEase Application Specific Language
330 lines • 15.4 kB
JavaScript
"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