@lcap/nasl 3.8.3-beta.4 → 3.8.3-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/common/BaseNode.d.ts +9 -4
- package/out/common/BaseNode.js +73 -18
- package/out/common/BaseNode.js.map +1 -1
- package/out/common/utils.d.ts +5 -1
- package/out/common/utils.js +188 -6
- package/out/common/utils.js.map +1 -1
- package/out/concepts/App__.js +17 -13
- package/out/concepts/App__.js.map +1 -1
- package/out/concepts/AuthLogicForCallInterface__.js +2 -50
- package/out/concepts/AuthLogicForCallInterface__.js.map +1 -1
- package/out/concepts/BusinessComponent__.js +2 -42
- package/out/concepts/BusinessComponent__.js.map +1 -1
- package/out/concepts/BusinessLogic__.js +2 -50
- package/out/concepts/BusinessLogic__.js.map +1 -1
- package/out/concepts/CallFunction__.d.ts +1 -1
- package/out/concepts/CallFunction__.js +1 -1
- package/out/concepts/CallLogic__.js +2 -2
- package/out/concepts/CallLogic__.js.map +1 -1
- package/out/concepts/Identifier__.d.ts +2 -0
- package/out/concepts/Identifier__.js +51 -5
- package/out/concepts/Identifier__.js.map +1 -1
- package/out/concepts/Logic__.js +6 -101
- package/out/concepts/Logic__.js.map +1 -1
- package/out/concepts/MemberExpression__.d.ts +1 -1
- package/out/concepts/MemberExpression__.js +15 -3
- package/out/concepts/MemberExpression__.js.map +1 -1
- package/out/concepts/OqlQueryComponent__.d.ts +0 -1
- package/out/concepts/OqlQueryComponent__.js +0 -70
- package/out/concepts/OqlQueryComponent__.js.map +1 -1
- package/out/concepts/OverriddenLogic__.js +2 -50
- package/out/concepts/OverriddenLogic__.js.map +1 -1
- package/out/concepts/ProcessElementV2__.js +4 -0
- package/out/concepts/ProcessElementV2__.js.map +1 -1
- package/out/concepts/ProcessElement__.js +4 -0
- package/out/concepts/ProcessElement__.js.map +1 -1
- package/out/concepts/ProcessV2__.js +4 -0
- package/out/concepts/ProcessV2__.js.map +1 -1
- package/out/concepts/Process__.js +4 -0
- package/out/concepts/Process__.js.map +1 -1
- package/out/concepts/SubLogic__.js +5 -50
- package/out/concepts/SubLogic__.js.map +1 -1
- package/out/concepts/TypeAnnotation__.js +1 -1
- package/out/concepts/TypeAnnotation__.js.map +1 -1
- package/out/concepts/View__.js +10 -49
- package/out/concepts/View__.js.map +1 -1
- package/out/generator/genBundleFiles.js +5 -5
- package/out/generator/permission.js +21 -5
- package/out/generator/permission.js.map +1 -1
- package/out/generator/release-body/body.js.map +1 -1
- package/out/natural/transformTS2UI.js +5 -5
- package/out/natural/transformTS2UI.js.map +1 -1
- package/out/natural/transforms/transform2LogicItem.js +5 -5
- package/out/natural/transforms/transform2LogicItem.js.map +1 -1
- package/out/server/naslServer.js +20 -2
- package/out/server/naslServer.js.map +1 -1
- package/out/server/semanticData.d.ts +32 -0
- package/out/server/semanticData.js +371 -0
- package/out/server/semanticData.js.map +1 -0
- package/out/service/logic/api.d.ts +9 -0
- package/out/service/logic/api.js +6 -0
- package/out/service/logic/api.js.map +1 -1
- package/out/templator/block2nasl/viewMergeBlock.js +2 -1
- package/out/templator/block2nasl/viewMergeBlock.js.map +1 -1
- package/package.json +1 -1
- package/sandbox/stdlib/nasl.collection.ts +3 -3
- package/src/common/BaseNode.ts +106 -36
- package/src/common/utils.ts +227 -5
- package/src/concepts/App__.ts +17 -13
- package/src/concepts/AuthLogicForCallInterface__.ts +3 -56
- package/src/concepts/BusinessComponent__.ts +6 -51
- package/src/concepts/BusinessLogic__.ts +4 -56
- package/src/concepts/CallFunction__.ts +1 -1
- package/src/concepts/CallLogic__.ts +8 -4
- package/src/concepts/Identifier__.ts +57 -6
- package/src/concepts/Logic__.ts +9 -111
- package/src/concepts/MemberExpression__.ts +21 -7
- package/src/concepts/OqlQueryComponent__.ts +1 -74
- package/src/concepts/OverriddenLogic__.ts +4 -56
- package/src/concepts/ProcessElementV2__.ts +4 -0
- package/src/concepts/ProcessElement__.ts +4 -0
- package/src/concepts/ProcessV2__.ts +5 -0
- package/src/concepts/Process__.ts +4 -0
- package/src/concepts/SubLogic__.ts +6 -56
- package/src/concepts/TypeAnnotation__.ts +1 -1
- package/src/concepts/View__.ts +14 -54
- package/src/generator/genBundleFiles.ts +5 -5
- package/src/generator/permission.ts +23 -5
- package/src/generator/release-body/body.ts +0 -1
- package/src/natural/transformTS2UI.ts +5 -5
- package/src/natural/transforms/transform2LogicItem.ts +5 -5
- package/src/server/naslServer.ts +26 -2
- package/src/server/semanticData.ts +447 -0
- package/src/service/logic/api.js +6 -0
- package/src/templator/block2nasl/viewMergeBlock.ts +2 -1
- package/src/translator/utils.ts +1 -1
- package/test/concepts/logic/__snapshots__/toEmbeddedTS.spec.ts.snap +182 -0
- package/test/concepts/logic/constant.ts +5 -0
- package/test/concepts/logic/fixtures/variable-host-call-logic-member-expression.json +267 -0
- package/test/concepts/logic/fixtures/variable-host-call-logic-nested-member-expression copy.json +457 -0
- package/test/concepts/logic/fixtures/variable-host-call-logic-with-handle-error-member-expression.json +267 -0
- package/test/concepts/logic/toEmbeddedTS.spec.ts +15 -0
package/src/common/BaseNode.ts
CHANGED
|
@@ -20,6 +20,8 @@ export function setActionable(value: boolean) {
|
|
|
20
20
|
actionable = value;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
import { varScopeCtx } from '../server/semanticData';
|
|
24
|
+
|
|
23
25
|
const patchCompose = (node: BaseNode, type = 'add') => {
|
|
24
26
|
if (node?.composedBy) {
|
|
25
27
|
const app = (node as any)?.app;
|
|
@@ -942,7 +944,7 @@ export class BaseNode extends EventEmitter {
|
|
|
942
944
|
}
|
|
943
945
|
|
|
944
946
|
get app() {
|
|
945
|
-
return this.getAncestor('App') as App;
|
|
947
|
+
return varScopeCtx.isFirstScreen ? varScopeCtx.app : this.getAncestor('App') as App;
|
|
946
948
|
}
|
|
947
949
|
|
|
948
950
|
/**
|
|
@@ -1435,13 +1437,9 @@ export class BaseNode extends EventEmitter {
|
|
|
1435
1437
|
* @description 与`traverseChildren`不同,此方法会过滤掉非节点值
|
|
1436
1438
|
*/
|
|
1437
1439
|
*traverseChildrenGenerator(cb: (node: types.SyntaxNode) => (void | Generator<any, any, any>)) {
|
|
1438
|
-
const isNode = (node: unknown): node is types.SyntaxNode => {
|
|
1439
|
-
return Boolean(node) && typeof node === 'object' && ('concept' in node) && typeof (node as any).concept === 'string';
|
|
1440
|
-
};
|
|
1441
|
-
|
|
1442
1440
|
function* traverse(node: BaseNode): Generator<any, any, any> {
|
|
1443
|
-
if (
|
|
1444
|
-
const result = cb(node);
|
|
1441
|
+
if (asserts.isBaseNode(node)) {
|
|
1442
|
+
const result = cb(node as types.SyntaxNode);
|
|
1445
1443
|
|
|
1446
1444
|
if (utils.isGenerator(result)) {
|
|
1447
1445
|
yield* result;
|
|
@@ -1486,50 +1484,122 @@ export class BaseNode extends EventEmitter {
|
|
|
1486
1484
|
* @description 严格迭代所有子节点!排除属性!
|
|
1487
1485
|
*/
|
|
1488
1486
|
traverseStrictChildren(cb: (el: types.SyntaxNode) => void, whitelist?: string[]): void {
|
|
1489
|
-
|
|
1490
|
-
if (
|
|
1491
|
-
|
|
1487
|
+
function traverse(node: any) {
|
|
1488
|
+
if (!node) {
|
|
1489
|
+
return;
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
if (asserts.isBaseNode(node)) {
|
|
1493
|
+
cb(node as types.SyntaxNode);
|
|
1492
1494
|
}
|
|
1493
|
-
|
|
1495
|
+
|
|
1496
|
+
const propertyMap = getConceptPropertyMap(node?.concept);
|
|
1497
|
+
|
|
1498
|
+
if (!propertyMap) {
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
const keys = (whitelist && whitelist.length > 0)
|
|
1503
|
+
? Array.from(propertyMap.keys()).concat(whitelist)
|
|
1504
|
+
: propertyMap.keys();
|
|
1505
|
+
|
|
1506
|
+
for (const property of keys) {
|
|
1507
|
+
const prop = node[property as keyof BaseNode];
|
|
1508
|
+
|
|
1509
|
+
if (!prop) {
|
|
1510
|
+
continue;
|
|
1511
|
+
}
|
|
1512
|
+
else if (Array.isArray(prop)) {
|
|
1513
|
+
for (const child of prop) {
|
|
1514
|
+
traverse(child);
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
else {
|
|
1518
|
+
traverse(prop);
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
traverse(this);
|
|
1494
1524
|
}
|
|
1495
1525
|
|
|
1496
|
-
|
|
1526
|
+
/**
|
|
1497
1527
|
* 迭代所有子节点
|
|
1498
1528
|
*
|
|
1499
|
-
* @description
|
|
1529
|
+
* @description 严格迭代所有子节点!排除属性!条件满足时整个遍历全部终止!
|
|
1500
1530
|
*/
|
|
1501
|
-
|
|
1502
|
-
|
|
1531
|
+
traverseStrictChildrenStopWhen(cb: (el: types.SyntaxNode) => void, setStopFlag: (el: types.SyntaxNode) => boolean, whitelist?: string[]): void {
|
|
1532
|
+
let shouldStop = false;
|
|
1503
1533
|
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
}
|
|
1534
|
+
function __traverse(node: any) {
|
|
1535
|
+
if (asserts.isBaseNode(node)) {
|
|
1536
|
+
cb(node as types.SyntaxNode);
|
|
1537
|
+
}
|
|
1509
1538
|
|
|
1510
|
-
|
|
1511
|
-
if (shouldStop) {
|
|
1512
|
-
return;
|
|
1513
|
-
}
|
|
1539
|
+
shouldStop = shouldStop || setStopFlag(node);
|
|
1514
1540
|
|
|
1515
|
-
|
|
1516
|
-
|
|
1541
|
+
if (shouldStop) {
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1517
1544
|
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1545
|
+
const propertyMap = getConceptPropertyMap(node?.concept);
|
|
1546
|
+
if (!propertyMap) return;
|
|
1547
|
+
|
|
1548
|
+
const propertyKeys = [...propertyMap.keys()];
|
|
1549
|
+
if (Array.isArray(whitelist) && whitelist.length) {
|
|
1550
|
+
propertyKeys.push(...whitelist);
|
|
1551
|
+
}
|
|
1552
|
+
for (const property of propertyKeys) {
|
|
1553
|
+
const child = node[property as keyof BaseNode];
|
|
1554
|
+
if (!child) continue;
|
|
1555
|
+
else if (Array.isArray(child)) child?.forEach?.((node: types.SyntaxNode) => __traverse(node));
|
|
1556
|
+
else __traverse(child);
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
__traverse(this);
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
/**
|
|
1564
|
+
* 迭代所有子节点
|
|
1565
|
+
* @description 严格迭代所有子节点,排除属性;多函数特化版本,不做额外检查
|
|
1566
|
+
*/
|
|
1567
|
+
*traverseStrictChildrenDoMultiTasks(
|
|
1568
|
+
tasks: Array<(_: BaseNode) => Generator<any, any, any>>,
|
|
1569
|
+
cleanups: Array<(_: BaseNode) => Generator<any, any, any>>): Generator<any, any, any> {
|
|
1570
|
+
|
|
1571
|
+
function __traverse(nd: BaseNode) {
|
|
1572
|
+
if (!asserts.isBaseNode(nd)) {
|
|
1573
|
+
return;
|
|
1574
|
+
}
|
|
1575
|
+
tasks.forEach(task => utils.runGeneratorSync(task(nd)));
|
|
1576
|
+
|
|
1577
|
+
const props = getConceptPropertyMap(nd?.concept)?.keys();
|
|
1578
|
+
if (!props) {
|
|
1579
|
+
cleanups.forEach(task => utils.runGeneratorSync(task(nd)));
|
|
1580
|
+
return;
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
for (const p of props) {
|
|
1584
|
+
const child = nd[p as keyof BaseNode];
|
|
1585
|
+
if (!child) {
|
|
1586
|
+
continue;
|
|
1587
|
+
} else if (Array.isArray(child)) {
|
|
1588
|
+
child?.forEach?.((node: types.SyntaxNode) => {
|
|
1589
|
+
__traverse(node);
|
|
1590
|
+
});
|
|
1591
|
+
} else {
|
|
1592
|
+
__traverse(child);
|
|
1527
1593
|
}
|
|
1528
1594
|
}
|
|
1529
1595
|
|
|
1530
|
-
|
|
1596
|
+
cleanups.forEach(task => utils.runGeneratorSync(task(nd)));
|
|
1531
1597
|
}
|
|
1532
1598
|
|
|
1599
|
+
__traverse(this);
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
|
|
1533
1603
|
/**
|
|
1534
1604
|
* 获取当前节点在nasl标注节点上的节点
|
|
1535
1605
|
*/
|
package/src/common/utils.ts
CHANGED
|
@@ -1,17 +1,239 @@
|
|
|
1
|
+
import type { AxiosInstance } from 'axios';
|
|
1
2
|
import type { types } from '../concepts';
|
|
3
|
+
import EntityProperty from '../concepts/EntityProperty__';
|
|
4
|
+
import Entity from '../concepts/Entity__';
|
|
5
|
+
import OqlQueryComponent from '../concepts/OqlQueryComponent__';
|
|
6
|
+
import api from '../service/logic/api';
|
|
7
|
+
import { naslOQLCacheStore } from '../utils/language-cache/nasl';
|
|
2
8
|
|
|
3
|
-
|
|
4
|
-
|
|
9
|
+
type OQLEmbeddedTSRequestPayload = {
|
|
10
|
+
appId: 'myAppId';
|
|
11
|
+
oqlIdentifier: 'myoqlIdentifier';
|
|
12
|
+
dataSourceName: string;
|
|
13
|
+
oql: string;
|
|
14
|
+
ideVersion: string;
|
|
15
|
+
dataSourceNasl: any[];
|
|
16
|
+
typeScriptStartLine: 1;
|
|
17
|
+
typeScriptStartLineColumn: 1;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type PayloadWithCacheKey = {
|
|
21
|
+
payload: OQLEmbeddedTSRequestPayload | null;
|
|
22
|
+
cacheKey: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function preparePayloadAndCacheKey(oql: OqlQueryComponent): PayloadWithCacheKey {
|
|
26
|
+
if (oql.code) {
|
|
27
|
+
let dataSourceNasl = oql.app.findNodeByCompleteName(oql.dataSource)?.toJSON();
|
|
28
|
+
if (dataSourceNasl) {
|
|
29
|
+
dataSourceNasl = {
|
|
30
|
+
concept: 'DataSource',
|
|
31
|
+
entities: (dataSourceNasl.entities = dataSourceNasl.entities?.map((entity: Entity) => {
|
|
32
|
+
return {
|
|
33
|
+
name: entity.name,
|
|
34
|
+
concept: entity.concept,
|
|
35
|
+
tableName: entity.tableName,
|
|
36
|
+
properties: entity.properties?.map((prop: EntityProperty) => {
|
|
37
|
+
return {
|
|
38
|
+
name: prop.name,
|
|
39
|
+
concept: prop.concept,
|
|
40
|
+
columnName: prop.columnName,
|
|
41
|
+
};
|
|
42
|
+
}),
|
|
43
|
+
};
|
|
44
|
+
})),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const payload: OQLEmbeddedTSRequestPayload = {
|
|
48
|
+
appId: 'myAppId',
|
|
49
|
+
oqlIdentifier: 'myoqlIdentifier',
|
|
50
|
+
dataSourceName: oql.dataSource,
|
|
51
|
+
oql: oql.code,
|
|
52
|
+
ideVersion: oql.app.ideVersion,
|
|
53
|
+
dataSourceNasl,
|
|
54
|
+
typeScriptStartLine: 1,
|
|
55
|
+
typeScriptStartLineColumn: 1,
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
cacheKey: JSON.stringify(payload),
|
|
59
|
+
payload: payload,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
cacheKey: '',
|
|
64
|
+
payload: null,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type RequestedEmbeddedTS = {
|
|
69
|
+
typescript: string;
|
|
70
|
+
lexicalErrorCode: number;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// 从服务端获取 SQL -> TS 的翻译和 sourceMap
|
|
74
|
+
export async function requestEmbeddedTS(this: OqlQueryComponent): Promise<void> {
|
|
75
|
+
const { http, logger } = this.rootNode.naslServer;
|
|
76
|
+
|
|
77
|
+
if (this.code) {
|
|
78
|
+
let dataSourceNasl = this.app.findNodeByCompleteName(this.dataSource)?.toJSON();
|
|
79
|
+
if (dataSourceNasl) {
|
|
80
|
+
dataSourceNasl = {
|
|
81
|
+
concept: 'DataSource',
|
|
82
|
+
entities: (dataSourceNasl.entities = dataSourceNasl.entities?.map((entity: Entity) => {
|
|
83
|
+
return {
|
|
84
|
+
name: entity.name,
|
|
85
|
+
concept: entity.concept,
|
|
86
|
+
tableName: entity.tableName,
|
|
87
|
+
properties: entity.properties?.map((prop: EntityProperty) => {
|
|
88
|
+
return {
|
|
89
|
+
name: prop.name,
|
|
90
|
+
concept: prop.concept,
|
|
91
|
+
columnName: prop.columnName,
|
|
92
|
+
};
|
|
93
|
+
}),
|
|
94
|
+
};
|
|
95
|
+
})),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const queryWithCache = async () => {
|
|
100
|
+
const params = {
|
|
101
|
+
appId: 'myAppId',
|
|
102
|
+
oqlIdentifier: 'myoqlIdentifier',
|
|
103
|
+
dataSourceName: this.dataSource,
|
|
104
|
+
oql: this.code,
|
|
105
|
+
ideVersion: this.app.ideVersion,
|
|
106
|
+
dataSourceNasl,
|
|
107
|
+
typeScriptStartLine: 1,
|
|
108
|
+
typeScriptStartLineColumn: 1,
|
|
109
|
+
};
|
|
110
|
+
const key = JSON.stringify(params);
|
|
111
|
+
let res = null;
|
|
112
|
+
let canUseCache = false;
|
|
113
|
+
try {
|
|
114
|
+
res = await naslOQLCacheStore.getItem(key);
|
|
115
|
+
canUseCache = true;
|
|
116
|
+
} catch (error) {}
|
|
117
|
+
if (res !== null) {
|
|
118
|
+
return res;
|
|
119
|
+
}
|
|
120
|
+
return http.post(api.queryDebugTypescript.url.path, params).then(async ({ data }) => {
|
|
121
|
+
if (canUseCache) {
|
|
122
|
+
try {
|
|
123
|
+
await naslOQLCacheStore.setItem(key, data);
|
|
124
|
+
} catch (error) {}
|
|
125
|
+
}
|
|
126
|
+
return data;
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
return queryWithCache()
|
|
131
|
+
.then((data: any) => {
|
|
132
|
+
this.codeSourceMap = data.result ?? { typescript: '', lexicalErrorCode: 1001 };
|
|
133
|
+
})
|
|
134
|
+
.catch((err) => {
|
|
135
|
+
logger.error('Oql 请求失败', err.toString());
|
|
136
|
+
this.codeSourceMap = { typescript: '', lexicalErrorCode: 1001 };
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
this.codeSourceMap = { typescript: '', lexicalErrorCode: 1001 };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function makeCachedBatchRequest(
|
|
143
|
+
http: AxiosInstance,
|
|
144
|
+
payloadWithCacheKeyList: PayloadWithCacheKey[]
|
|
145
|
+
): Promise<(RequestedEmbeddedTS | null)[]> {
|
|
146
|
+
const itemsWithIndex = payloadWithCacheKeyList.map((item, index) => {
|
|
147
|
+
return { item, index };
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const cacheTest = await Promise.all(
|
|
151
|
+
itemsWithIndex.map(async ({ item, index }) => {
|
|
152
|
+
const cached: RequestedEmbeddedTS | null = await naslOQLCacheStore.getItem(item.cacheKey);
|
|
153
|
+
return { item, index, cached };
|
|
154
|
+
})
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
const notCachedList = cacheTest.filter((x) => !x.cached);
|
|
158
|
+
const cachedList = cacheTest.filter((x) => x.cached);
|
|
159
|
+
|
|
160
|
+
const resultContainer = Array.from<RequestedEmbeddedTS | null>({
|
|
161
|
+
length: payloadWithCacheKeyList.length,
|
|
162
|
+
}).fill(null);
|
|
163
|
+
|
|
164
|
+
for (const { cached, index } of cachedList) {
|
|
165
|
+
resultContainer[index] = cached;
|
|
166
|
+
}
|
|
167
|
+
const paramList = notCachedList.map((x) => x.item.payload);
|
|
168
|
+
const tempResultList: (RequestedEmbeddedTS | null)[] = paramList.length
|
|
169
|
+
? await http
|
|
170
|
+
.post(api.queryDebugTypescriptBatch.url.path, paramList)
|
|
171
|
+
.then((x) => x.data.result)
|
|
172
|
+
.then(async (resultList: (RequestedEmbeddedTS | null)[]) => {
|
|
173
|
+
await Promise.all(
|
|
174
|
+
resultList.map((res, index) => {
|
|
175
|
+
const payload = notCachedList[index];
|
|
176
|
+
resultContainer[payload.index] = res;
|
|
177
|
+
return naslOQLCacheStore.setItem(payload.item.cacheKey, res);
|
|
178
|
+
})
|
|
179
|
+
);
|
|
180
|
+
return resultList;
|
|
181
|
+
})
|
|
182
|
+
: [];
|
|
183
|
+
if (tempResultList.length !== paramList.length) {
|
|
184
|
+
throw new Error('返回的数据长度不一致');
|
|
185
|
+
}
|
|
186
|
+
return resultContainer;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// 从服务端获取 SQL -> TS 的翻译和 sourceMap
|
|
190
|
+
export async function requestEmbeddedTSBatch(
|
|
191
|
+
http: AxiosInstance,
|
|
192
|
+
oqlList: OqlQueryComponent[]
|
|
193
|
+
): Promise<void> {
|
|
194
|
+
const paramList = oqlList.map((oql) => {
|
|
195
|
+
const { cacheKey, payload } = preparePayloadAndCacheKey(oql);
|
|
196
|
+
return { oql, cacheKey, payload };
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
return makeCachedBatchRequest(http, paramList)
|
|
200
|
+
.then((data) => {
|
|
201
|
+
if (data.length !== oqlList.length) {
|
|
202
|
+
throw new Error('返回的数据长度不一致');
|
|
203
|
+
}
|
|
204
|
+
data.forEach((item, index) => {
|
|
205
|
+
const targetOql = oqlList[index];
|
|
206
|
+
targetOql.codeSourceMap = item ?? { typescript: '', lexicalErrorCode: 1001 };
|
|
207
|
+
});
|
|
208
|
+
})
|
|
209
|
+
.catch((err) => {
|
|
210
|
+
// TODO wudengke logger
|
|
211
|
+
console.error('Oql 请求失败', err.toString());
|
|
212
|
+
console.error(err);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export async function waitOqlQueryComponentChildrenFinish(node: types.SyntaxNode) {
|
|
217
|
+
const oqlList: OqlQueryComponent[] = [];
|
|
5
218
|
|
|
6
219
|
node.traverseStrictChildren((el) => {
|
|
7
220
|
if (el.concept === 'OqlQueryComponent') {
|
|
8
221
|
if (!el.codeSourceMap) {
|
|
9
|
-
|
|
222
|
+
oqlList.push(el);
|
|
10
223
|
}
|
|
11
224
|
}
|
|
12
225
|
});
|
|
13
226
|
|
|
14
|
-
if (
|
|
15
|
-
|
|
227
|
+
if (oqlList.length > 0) {
|
|
228
|
+
const http =
|
|
229
|
+
node.rootNode?.naslServer.http ??
|
|
230
|
+
// @ts-expect-error
|
|
231
|
+
// 若是App节点
|
|
232
|
+
node?.naslServer.http;
|
|
233
|
+
if (http) {
|
|
234
|
+
return requestEmbeddedTSBatch(http, oqlList);
|
|
235
|
+
} else {
|
|
236
|
+
throw new Error('http client 不存在');
|
|
237
|
+
}
|
|
16
238
|
}
|
|
17
239
|
}
|
package/src/concepts/App__.ts
CHANGED
|
@@ -3839,23 +3839,24 @@ export class App extends BaseNode {
|
|
|
3839
3839
|
deleteCompose(path: string[]) {
|
|
3840
3840
|
if (!Array.isArray(path)) return;
|
|
3841
3841
|
let compose = this.composeCache;
|
|
3842
|
-
|
|
3843
|
-
const delNodes = (_compose: composeCacheType) => {
|
|
3842
|
+
const delNodes = (_compose: composeCacheType, key: string) => {
|
|
3844
3843
|
if (_compose?.nodes) {
|
|
3845
3844
|
for (const key in _compose) {
|
|
3846
|
-
|
|
3847
|
-
|
|
3845
|
+
// 只有form和table层级触发删除
|
|
3846
|
+
if (key !== 'nodes' && key !== 'saveModalForm') {
|
|
3847
|
+
delNodes(_compose[key], key);
|
|
3848
3848
|
}
|
|
3849
3849
|
}
|
|
3850
3850
|
const arr = [..._compose.nodes] || [];
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
}
|
|
3858
|
-
|
|
3851
|
+
// table内的saveModalForm.nodes也在table层级一起删除,避免先删父后删子的情况
|
|
3852
|
+
if (_compose.hasOwnProperty('saveModalForm')) {
|
|
3853
|
+
arr.push(..._compose.saveModalForm.nodes);
|
|
3854
|
+
}
|
|
3855
|
+
// 按照路径长度,粗粒度处理好父子关系后,再删除节点
|
|
3856
|
+
const triggerNode = arr
|
|
3857
|
+
.map((item, index) => ({ nodePath: item?.nodePath, index }))
|
|
3858
|
+
.sort((a, b) => b.nodePath.length - a.nodePath.length)
|
|
3859
|
+
.map((item) => arr[item.index]);
|
|
3859
3860
|
|
|
3860
3861
|
triggerNode.forEach((node) => {
|
|
3861
3862
|
node && node.delete();
|
|
@@ -3867,10 +3868,13 @@ export class App extends BaseNode {
|
|
|
3867
3868
|
|
|
3868
3869
|
this.emit('collect:start', {
|
|
3869
3870
|
actionMsg: '删除同一分组节点',
|
|
3871
|
+
extra: {
|
|
3872
|
+
isCustomDesigner: true,
|
|
3873
|
+
},
|
|
3870
3874
|
});
|
|
3871
3875
|
path.forEach((key, index) => {
|
|
3872
3876
|
if (index === path.length - 1) {
|
|
3873
|
-
delNodes(compose?.[key]);
|
|
3877
|
+
delNodes(compose?.[key], key);
|
|
3874
3878
|
} else {
|
|
3875
3879
|
compose = compose[key];
|
|
3876
3880
|
}
|
|
@@ -42,6 +42,7 @@ import * as asserts from './utils/asserts';
|
|
|
42
42
|
|
|
43
43
|
import Param from './Param__';
|
|
44
44
|
import AuthLogic from './AuthLogic__';
|
|
45
|
+
import { reCollectTyInferCtx } from '../server/semanticData';
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
48
|
* 调用接口的鉴权逻辑
|
|
@@ -352,61 +353,7 @@ export class AuthLogicForCallInterface extends AuthLogic {
|
|
|
352
353
|
// 需要类型推导的局部变量/返回值需要调整申明顺序
|
|
353
354
|
const advanceMap: Map<Return | Variable, Assignment | BatchAssignment> = new Map();
|
|
354
355
|
const callFunctionAdvanceMap: Map<Return | Variable, CallFunction> = new Map();
|
|
355
|
-
yield*
|
|
356
|
-
if (
|
|
357
|
-
el &&
|
|
358
|
-
// 批量赋值
|
|
359
|
-
(asserts.isBatchAssignment(el) ||
|
|
360
|
-
// 赋值
|
|
361
|
-
(asserts.isAssignment(el) && el.left?.name) ||
|
|
362
|
-
// 内置函数对集合类型的推导
|
|
363
|
-
(asserts.isCallFunction(el) && el.derivablecollection?.name))
|
|
364
|
-
) {
|
|
365
|
-
if (el?.getAncestor('SubLogic')) {
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
if (asserts.isAssignment(el)) {
|
|
369
|
-
const advanceVar = self.variables?.find(
|
|
370
|
-
(variable) => !variable.typeAnnotation && el.left?.name === variable.name,
|
|
371
|
-
);
|
|
372
|
-
if (advanceVar && !advanceMap.get(advanceVar)) {
|
|
373
|
-
advanceMap.set(advanceVar, el);
|
|
374
|
-
}
|
|
375
|
-
const advanceRn = self.returns?.find((ret) => !ret.typeAnnotation && el.left?.name === ret.name);
|
|
376
|
-
if (advanceRn && !advanceMap.get(advanceRn)) {
|
|
377
|
-
advanceMap.set(advanceRn, el);
|
|
378
|
-
}
|
|
379
|
-
} else if (asserts.isCallFunction(el)) {
|
|
380
|
-
// 需要被推导的集合
|
|
381
|
-
const expression = el.derivablecollection;
|
|
382
|
-
// 宽泛意义上的变量(变量+出参)
|
|
383
|
-
const advanceVar = [...(self.variables || []), ...(self.returns || [])].find((variable) => {
|
|
384
|
-
return !variable.typeAnnotation && expression?.name === variable.name;
|
|
385
|
-
});
|
|
386
|
-
if (advanceVar && !callFunctionAdvanceMap.get(advanceVar)) {
|
|
387
|
-
callFunctionAdvanceMap.set(advanceVar, el);
|
|
388
|
-
}
|
|
389
|
-
} else if (asserts.isBatchAssignment(el)) {
|
|
390
|
-
yield* wrapForEach(el.assignmentLines, function* warpForEachGenerator({ leftIndex }) {
|
|
391
|
-
const leftCode =
|
|
392
|
-
leftIndex.length === 1
|
|
393
|
-
? yield* el.left.expression.toEmbeddedTS(shiftState(state, code, { inline: true }))
|
|
394
|
-
: yield* el.left.members[leftIndex[1]]?.toEmbeddedTS(shiftState(state, code, { inline: true })) ??
|
|
395
|
-
returnOrigin('');
|
|
396
|
-
const advanceVar = self.variables?.find(
|
|
397
|
-
(variable) => !variable.typeAnnotation && leftCode === variable.name,
|
|
398
|
-
);
|
|
399
|
-
if (advanceVar && !advanceMap.get(advanceVar)) {
|
|
400
|
-
advanceMap.set(advanceVar, el);
|
|
401
|
-
}
|
|
402
|
-
const advanceRn = self.returns?.find((ret) => !ret.typeAnnotation && leftCode === ret.name);
|
|
403
|
-
if (advanceRn && !advanceMap.get(advanceRn)) {
|
|
404
|
-
advanceMap.set(advanceRn, el);
|
|
405
|
-
}
|
|
406
|
-
});
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
});
|
|
356
|
+
yield* reCollectTyInferCtx(advanceMap, callFunctionAdvanceMap, self);
|
|
410
357
|
code += '{\n';
|
|
411
358
|
// 用于虚拟节点的查找引用
|
|
412
359
|
if (Array.isArray(self.virtualParams)) {
|
|
@@ -551,7 +498,7 @@ export class AuthLogicForCallInterface extends AuthLogic {
|
|
|
551
498
|
&& itemNode.typeAnnotation?.typeKind === 'anonymousStructure'
|
|
552
499
|
)
|
|
553
500
|
|| (
|
|
554
|
-
(asserts.isNewList(itemNode) || asserts.isNewMap(itemNode))
|
|
501
|
+
(asserts.isNewList(itemNode) || asserts.isNewMap(itemNode))
|
|
555
502
|
&& !(itemNode?.typeAnnotation)
|
|
556
503
|
)
|
|
557
504
|
) {
|
|
@@ -46,6 +46,7 @@ import Variable from './Variable__';
|
|
|
46
46
|
import BindEvent from './BindEvent__';
|
|
47
47
|
import BusinessLogic from './BusinessLogic__';
|
|
48
48
|
import ViewElement from './ViewElement__';
|
|
49
|
+
import { reCollectTyInferCtx } from '../server/semanticData';
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
52
|
* 业务组件
|
|
@@ -1999,53 +2000,7 @@ export class BusinessComponent extends BaseNode {
|
|
|
1999
2000
|
|
|
2000
2001
|
const advanceMap: Map<Variable, Assignment | BatchAssignment> = new Map();
|
|
2001
2002
|
const callFunctionAdvanceMap: Map<Variable, CallFunction> = new Map();
|
|
2002
|
-
yield*
|
|
2003
|
-
if (
|
|
2004
|
-
el &&
|
|
2005
|
-
// 批量赋值
|
|
2006
|
-
(asserts.isBatchAssignment(el) ||
|
|
2007
|
-
// 赋值
|
|
2008
|
-
(asserts.isAssignment(el) && el.left?.name) ||
|
|
2009
|
-
// 内置函数对集合类型的推导
|
|
2010
|
-
(asserts.isCallFunction(el) && el.derivablecollection?.name))
|
|
2011
|
-
) {
|
|
2012
|
-
if (el?.getAncestor('SubLogic')) {
|
|
2013
|
-
return;
|
|
2014
|
-
}
|
|
2015
|
-
if (asserts.isAssignment(el)) {
|
|
2016
|
-
const advanceVar = self.variables?.find(
|
|
2017
|
-
(variable) => !variable.typeAnnotation && el.left?.name === variable.name,
|
|
2018
|
-
);
|
|
2019
|
-
if (advanceVar && !advanceMap.get(advanceVar)) {
|
|
2020
|
-
advanceMap.set(advanceVar, el);
|
|
2021
|
-
}
|
|
2022
|
-
} else if (asserts.isCallFunction(el)) {
|
|
2023
|
-
// 需要被推导的集合
|
|
2024
|
-
const expression = el.derivablecollection;
|
|
2025
|
-
const advanceVar = self.variables?.find((variable) => {
|
|
2026
|
-
return !variable.typeAnnotation && expression?.name === variable.name;
|
|
2027
|
-
});
|
|
2028
|
-
if (advanceVar && !callFunctionAdvanceMap.get(advanceVar)) {
|
|
2029
|
-
callFunctionAdvanceMap.set(advanceVar, el);
|
|
2030
|
-
}
|
|
2031
|
-
} else if (asserts.isBatchAssignment(el)) {
|
|
2032
|
-
yield* wrapForEach(el.assignmentLines, function* warpForEachGenerator({ leftIndex }) {
|
|
2033
|
-
const leftCode =
|
|
2034
|
-
leftIndex.length === 1
|
|
2035
|
-
? yield* el.left?.expression?.toEmbeddedTS(shiftState(state, code, { inline: true })) ??
|
|
2036
|
-
returnOrigin('')
|
|
2037
|
-
: yield* el.left?.members[leftIndex[1]]?.toEmbeddedTS(shiftState(state, code, { inline: true })) ??
|
|
2038
|
-
returnOrigin('');
|
|
2039
|
-
const advanceVar = self.variables?.find(
|
|
2040
|
-
(variable) => !variable.typeAnnotation && leftCode === variable.name,
|
|
2041
|
-
);
|
|
2042
|
-
if (advanceVar && !advanceMap.get(advanceVar)) {
|
|
2043
|
-
advanceMap.set(advanceVar, el);
|
|
2044
|
-
}
|
|
2045
|
-
});
|
|
2046
|
-
}
|
|
2047
|
-
}
|
|
2048
|
-
});
|
|
2003
|
+
yield* reCollectTyInferCtx(advanceMap, callFunctionAdvanceMap, self);
|
|
2049
2004
|
|
|
2050
2005
|
// 用来储存默认值翻译结构是__IDENTIFIER__或者__IDENTIFIER__()的节点
|
|
2051
2006
|
const IDENTIFIERMAP = new Set<Variable>();
|
|
@@ -2155,7 +2110,7 @@ export class BusinessComponent extends BaseNode {
|
|
|
2155
2110
|
&& itemNode.typeAnnotation?.typeKind === 'anonymousStructure'
|
|
2156
2111
|
)
|
|
2157
2112
|
|| (
|
|
2158
|
-
(asserts.isNewList(itemNode) || asserts.isNewMap(itemNode))
|
|
2113
|
+
(asserts.isNewList(itemNode) || asserts.isNewMap(itemNode))
|
|
2159
2114
|
&& !(itemNode?.typeAnnotation)
|
|
2160
2115
|
)
|
|
2161
2116
|
) {
|
|
@@ -2523,11 +2478,11 @@ export class BusinessComponent extends BaseNode {
|
|
|
2523
2478
|
@withSourceMap()
|
|
2524
2479
|
toTextualNASL(state = createCompilerState()): string {
|
|
2525
2480
|
let code = '';
|
|
2526
|
-
|
|
2481
|
+
|
|
2527
2482
|
code += createDecoratorCode(state, this, ['title', 'description']);
|
|
2528
2483
|
|
|
2529
2484
|
code += `viewComponent ${this.name}`;
|
|
2530
|
-
|
|
2485
|
+
|
|
2531
2486
|
code += `(\n`;
|
|
2532
2487
|
this.params.forEach((param, index) => {
|
|
2533
2488
|
code += param.toTextualNASL(shiftState(state, code, { tabSize: state.tabSize + 1 }));
|
|
@@ -2551,7 +2506,7 @@ export class BusinessComponent extends BaseNode {
|
|
|
2551
2506
|
code += '\n';
|
|
2552
2507
|
});
|
|
2553
2508
|
if (this.logics.length) code += '\n';
|
|
2554
|
-
|
|
2509
|
+
|
|
2555
2510
|
code += this.elements[0].toTextualNASL(shiftState(state, code, { tabSize: state.tabSize + 1 }));
|
|
2556
2511
|
|
|
2557
2512
|
code += `\n${indent(state.tabSize)}}`;
|