@lcap/nasl 3.8.0-beta.6 → 3.8.0-beta.7

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.
Files changed (206) hide show
  1. package/.mocharc.js +1 -0
  2. package/out/common/BaseNode.d.ts +19 -3
  3. package/out/common/BaseNode.js +85 -7
  4. package/out/common/BaseNode.js.map +1 -1
  5. package/out/concepts/AbstractInterface__.js.map +1 -1
  6. package/out/concepts/Annotation__.js +1 -1
  7. package/out/concepts/Annotation__.js.map +1 -1
  8. package/out/concepts/App__.d.ts +3 -0
  9. package/out/concepts/App__.js +964 -4
  10. package/out/concepts/App__.js.map +1 -1
  11. package/out/concepts/Argument__.js +3 -3
  12. package/out/concepts/Argument__.js.map +1 -1
  13. package/out/concepts/BatchAssignment__.d.ts +1 -1
  14. package/out/concepts/BatchAssignment__.js +2 -2
  15. package/out/concepts/BatchAssignment__.js.map +1 -1
  16. package/out/concepts/BindAttribute__.js +3 -4
  17. package/out/concepts/BindAttribute__.js.map +1 -1
  18. package/out/concepts/BindDirective__.js +3 -4
  19. package/out/concepts/BindDirective__.js.map +1 -1
  20. package/out/concepts/BusinessComponent__.d.ts +2 -0
  21. package/out/concepts/BusinessComponent__.js +48 -0
  22. package/out/concepts/BusinessComponent__.js.map +1 -1
  23. package/out/concepts/BusinessLogic__.d.ts +1 -0
  24. package/out/concepts/BusinessLogic__.js +10 -0
  25. package/out/concepts/BusinessLogic__.js.map +1 -1
  26. package/out/concepts/CallEvent__.d.ts +2 -0
  27. package/out/concepts/CallEvent__.js +75 -0
  28. package/out/concepts/CallEvent__.js.map +1 -1
  29. package/out/concepts/CallInterface__.d.ts +1 -0
  30. package/out/concepts/CallInterface__.js +26 -15
  31. package/out/concepts/CallInterface__.js.map +1 -1
  32. package/out/concepts/CallLogic__.d.ts +4 -0
  33. package/out/concepts/CallLogic__.js +59 -3
  34. package/out/concepts/CallLogic__.js.map +1 -1
  35. package/out/concepts/Entity__.d.ts +3 -3
  36. package/out/concepts/Entity__.js +4 -0
  37. package/out/concepts/Entity__.js.map +1 -1
  38. package/out/concepts/Event__.d.ts +2 -0
  39. package/out/concepts/Event__.js +30 -0
  40. package/out/concepts/Event__.js.map +1 -1
  41. package/out/concepts/FrontendType__.d.ts +2 -0
  42. package/out/concepts/FrontendType__.js +32 -0
  43. package/out/concepts/FrontendType__.js.map +1 -1
  44. package/out/concepts/Frontend__.d.ts +2 -0
  45. package/out/concepts/Frontend__.js +48 -0
  46. package/out/concepts/Frontend__.js.map +1 -1
  47. package/out/concepts/IfStatement__.js +6 -6
  48. package/out/concepts/IfStatement__.js.map +1 -1
  49. package/out/concepts/InterfaceParam__.d.ts +1 -0
  50. package/out/concepts/InterfaceParam__.js +23 -4
  51. package/out/concepts/InterfaceParam__.js.map +1 -1
  52. package/out/concepts/Interface__.d.ts +2 -1
  53. package/out/concepts/Interface__.js +29 -5
  54. package/out/concepts/Interface__.js.map +1 -1
  55. package/out/concepts/JSBlock__.d.ts +1 -0
  56. package/out/concepts/JSBlock__.js +6 -0
  57. package/out/concepts/JSBlock__.js.map +1 -1
  58. package/out/concepts/LogicDeclaration__.d.ts +1 -0
  59. package/out/concepts/LogicDeclaration__.js +58 -7
  60. package/out/concepts/LogicDeclaration__.js.map +1 -1
  61. package/out/concepts/Logic__.js +32 -22
  62. package/out/concepts/Logic__.js.map +1 -1
  63. package/out/concepts/MatchCase__.js +1 -2
  64. package/out/concepts/MatchCase__.js.map +1 -1
  65. package/out/concepts/Match__.js +3 -18
  66. package/out/concepts/Match__.js.map +1 -1
  67. package/out/concepts/MemberExpression__.js +1 -1
  68. package/out/concepts/MemberExpression__.js.map +1 -1
  69. package/out/concepts/Module__.d.ts +2 -0
  70. package/out/concepts/Module__.js +64 -0
  71. package/out/concepts/Module__.js.map +1 -1
  72. package/out/concepts/NewComposite__.d.ts +1 -1
  73. package/out/concepts/NewComposite__.js +2 -2
  74. package/out/concepts/NewComposite__.js.map +1 -1
  75. package/out/concepts/Paginate__.d.ts +1 -0
  76. package/out/concepts/Paginate__.js +15 -7
  77. package/out/concepts/Paginate__.js.map +1 -1
  78. package/out/concepts/QueryFromExpression__.js +2 -2
  79. package/out/concepts/QueryFromExpression__.js.map +1 -1
  80. package/out/concepts/StringLiteral__.js +3 -4
  81. package/out/concepts/StringLiteral__.js.map +1 -1
  82. package/out/concepts/TypeAnnotation__.js +1 -0
  83. package/out/concepts/TypeAnnotation__.js.map +1 -1
  84. package/out/concepts/ViewElement__.d.ts +2 -0
  85. package/out/concepts/ViewElement__.js +8 -5
  86. package/out/concepts/ViewElement__.js.map +1 -1
  87. package/out/concepts/View__.d.ts +1 -0
  88. package/out/concepts/View__.js +55 -1
  89. package/out/concepts/View__.js.map +1 -1
  90. package/out/generator/genBundleFiles.js +14 -11
  91. package/out/generator/genBundleFiles.js.map +1 -1
  92. package/out/generator/genHash.d.ts +2 -2
  93. package/out/generator/genHash.js +30 -30
  94. package/out/generator/genHash.js.map +1 -1
  95. package/out/generator/permission.d.ts +8 -1
  96. package/out/generator/permission.js +321 -23
  97. package/out/generator/permission.js.map +1 -1
  98. package/out/generator/release-body/body.js +18 -4
  99. package/out/generator/release-body/body.js.map +1 -1
  100. package/out/generator/release-body/data.js +6 -2
  101. package/out/generator/release-body/data.js.map +1 -1
  102. package/out/generator/release-body/utils.js +3 -3
  103. package/out/generator/release-body/utils.js.map +1 -1
  104. package/out/generator/release-body/validation.js +2 -2
  105. package/out/generator/release-body/validation.js.map +1 -1
  106. package/out/index.d.ts +1 -1
  107. package/out/index.js.map +1 -1
  108. package/out/natural/genNaturalTS.d.ts +2 -2
  109. package/out/natural/genNaturalTS.js +7 -7
  110. package/out/natural/genNaturalTS.js.map +1 -1
  111. package/out/natural/getContext/index.d.ts +1 -1
  112. package/out/natural/getContext/index.js +15 -9
  113. package/out/natural/getContext/index.js.map +1 -1
  114. package/out/natural/transformTS2UI.js +30 -11
  115. package/out/natural/transformTS2UI.js.map +1 -1
  116. package/out/natural/transformTSCode.js +30 -11
  117. package/out/natural/transformTSCode.js.map +1 -1
  118. package/out/server/entity2LogicNamespace.d.ts +2 -2
  119. package/out/server/entity2LogicNamespace.js +321 -310
  120. package/out/server/entity2LogicNamespace.js.map +1 -1
  121. package/out/server/extendBaseNode.js +25 -0
  122. package/out/server/extendBaseNode.js.map +1 -1
  123. package/out/server/naslServer.d.ts +1 -1
  124. package/out/server/naslServer.js +23 -16
  125. package/out/server/naslServer.js.map +1 -1
  126. package/out/server/translator.js +12 -0
  127. package/out/server/translator.js.map +1 -1
  128. package/out/templator/genCreateBlock.js +3 -3
  129. package/out/templator/genCreateBlock.js.map +1 -1
  130. package/out/templator/genCurdEditMultipleKeyBlock.js +2 -2
  131. package/out/templator/genCurdEditMultipleKeyBlock.js.map +1 -1
  132. package/out/templator/genCurdMultipleKeyBlock.js +4 -4
  133. package/out/templator/genCurdMultipleKeyBlock.js.map +1 -1
  134. package/out/templator/genEditTableBlock.js +1 -1
  135. package/out/templator/genEditTableBlock.js.map +1 -1
  136. package/out/templator/genGetBlock.js.map +1 -1
  137. package/out/templator/genGridViewBlock.js.map +1 -1
  138. package/out/templator/genSelectBlock.js.map +1 -1
  139. package/out/templator/genTableBlock.js.map +1 -1
  140. package/out/templator/genUpdateBlock.js +3 -3
  141. package/out/templator/genUpdateBlock.js.map +1 -1
  142. package/out/templator/utils.js +1 -1
  143. package/out/templator/utils.js.map +1 -1
  144. package/package.json +5 -5
  145. package/src/common/BaseNode.ts +91 -11
  146. package/src/concepts/AbstractInterface__.ts +1 -0
  147. package/src/concepts/Annotation__.ts +1 -1
  148. package/src/concepts/App__.ts +104 -4
  149. package/src/concepts/Argument__.ts +3 -3
  150. package/src/concepts/BatchAssignment__.ts +2 -2
  151. package/src/concepts/BindAttribute__.ts +3 -4
  152. package/src/concepts/BindDirective__.ts +3 -4
  153. package/src/concepts/BusinessComponent__.ts +54 -1
  154. package/src/concepts/BusinessLogic__.ts +10 -1
  155. package/src/concepts/CallEvent__.ts +66 -0
  156. package/src/concepts/CallInterface__.ts +21 -9
  157. package/src/concepts/CallLogic__.ts +59 -3
  158. package/src/concepts/Entity__.ts +7 -1
  159. package/src/concepts/Event__.ts +32 -0
  160. package/src/concepts/FrontendType__.ts +34 -1
  161. package/src/concepts/Frontend__.ts +51 -0
  162. package/src/concepts/IfStatement__.ts +6 -6
  163. package/src/concepts/InterfaceParam__.ts +23 -4
  164. package/src/concepts/Interface__.ts +29 -5
  165. package/src/concepts/JSBlock__.ts +5 -0
  166. package/src/concepts/LogicDeclaration__.ts +65 -7
  167. package/src/concepts/Logic__.ts +34 -25
  168. package/src/concepts/MatchCase__.ts +1 -2
  169. package/src/concepts/Match__.ts +3 -21
  170. package/src/concepts/MemberExpression__.ts +1 -1
  171. package/src/concepts/Module__.ts +75 -0
  172. package/src/concepts/NewComposite__.ts +2 -2
  173. package/src/concepts/Paginate__.ts +14 -7
  174. package/src/concepts/QueryFromExpression__.ts +2 -2
  175. package/src/concepts/StringLiteral__.ts +3 -4
  176. package/src/concepts/TypeAnnotation__.ts +1 -0
  177. package/src/concepts/ViewElement__.ts +9 -5
  178. package/src/concepts/View__.ts +56 -1
  179. package/src/generator/genBundleFiles.ts +14 -11
  180. package/src/generator/genHash.ts +32 -6
  181. package/src/generator/permission.ts +333 -23
  182. package/src/generator/release-body/body.ts +24 -5
  183. package/src/generator/release-body/data.ts +7 -2
  184. package/src/generator/release-body/utils.ts +3 -3
  185. package/src/generator/release-body/validation.ts +1 -1
  186. package/src/index.ts +13 -1
  187. package/src/natural/genNaturalTS.ts +9 -7
  188. package/src/natural/getContext/index.ts +17 -11
  189. package/src/natural/transformTS2UI.ts +28 -11
  190. package/src/natural/transformTSCode.ts +28 -11
  191. package/src/server/entity2LogicNamespace.ts +13 -1
  192. package/src/server/extendBaseNode.ts +31 -0
  193. package/src/server/naslServer.ts +32 -23
  194. package/src/server/translator.ts +15 -0
  195. package/src/templator/genCreateBlock.ts +4 -4
  196. package/src/templator/genCurdEditMultipleKeyBlock.ts +2 -2
  197. package/src/templator/genCurdMultipleKeyBlock.ts +7 -7
  198. package/src/templator/genEditTableBlock.ts +4 -4
  199. package/src/templator/genGetBlock.ts +1 -1
  200. package/src/templator/genGridViewBlock.ts +2 -2
  201. package/src/templator/genSelectBlock.ts +3 -3
  202. package/src/templator/genTableBlock.ts +2 -2
  203. package/src/templator/genUpdateBlock.ts +6 -6
  204. package/src/templator/utils.ts +1 -1
  205. package/test/concepts/string-literal/__snapshots__/toVue.spec.ts.snap +1 -1
  206. package/test/concepts/view-element/__snapshots__/toVue.spec.ts.snap +6 -2
@@ -15,6 +15,8 @@ import {
15
15
  BindStyle,
16
16
  BindDirective,
17
17
  Connector,
18
+ Identifier,
19
+ Event,
18
20
  } from '../concepts';
19
21
  import { processToTreeFragment } from '../server/process2LogicNamespace';
20
22
 
@@ -145,14 +147,14 @@ function removeRedundantResourceData(resources: ResourceNode[][]) {
145
147
  resources.sort((a, b) => wm.get(a).length - wm.get(b).length);
146
148
 
147
149
  const res: ResourceNode[][] = [];
148
- const hashs: string[] = [];
150
+ const hashes: string[] = [];
149
151
 
150
152
  for (const resource of resources) {
151
153
  const hash = wm.get(resource);
152
- if (hashs.some((h) => hash.endsWith(h))) continue;
154
+ if (hashes.some((h) => hash.endsWith(h))) continue;
153
155
 
154
156
  res.push(resource);
155
- hashs.push(hash);
157
+ hashes.push(hash);
156
158
  }
157
159
  return res;
158
160
  }
@@ -278,7 +280,7 @@ function checkUploadAuth(uploaders: Map<string, ViewElement[]>) {
278
280
  // 如果开启控制权限-component,没开启权限-page
279
281
  uploaders.forEach((value, key) => {
280
282
  const authValue: ResourceNode[] = [];
281
- value.map((node) => {
283
+ value.forEach((node) => {
282
284
  if (node instanceof ViewElement && node.view) {
283
285
  const path = node.auth ? node.authPath : `${node.view.path}`;
284
286
  const type = node.auth ? 'component' : 'page';
@@ -290,25 +292,29 @@ function checkUploadAuth(uploaders: Map<string, ViewElement[]>) {
290
292
  });
291
293
  return res;
292
294
  }
293
- function checkPageAndUploadAuth(uploaders: Map<string, ViewElement[]>, key: string) {
294
- let flag: number = -1;
295
- flag = uploaders.get(key)?.findIndex((node) => {
296
- if (node.getAncestor('View') instanceof View) {
295
+
296
+ function checkPageAndUploadAuth(uploaders: Map<string, ViewElement[]>, key: string): boolean {
297
+ let flag: boolean = false;
298
+
299
+ uploaders.get(key).forEach((node) => {
300
+ if (node.view instanceof View) {
297
301
  // 当前页面未开启权限且文件上传组件也未开启权限
298
- if (!(node.getAncestor('View') as View).auth && node instanceof ViewElement && !node.auth) {
299
- return true;
302
+ if (!node.view.auth && node instanceof ViewElement && !node.auth) {
303
+ flag = true;
300
304
  }
301
305
  } else if (node.getAncestor('BusinessComponent')) {
302
- return true;
306
+ flag = true;
303
307
  }
304
308
  });
309
+
305
310
  return flag;
306
311
  }
312
+
307
313
  function convertArray(arr: ResourceNode[]) {
308
314
  return arr.map((item: any) => [item]);
309
315
  }
310
- export async function genPermissionData(app: App) {
311
- // console.time('xxx');
316
+
317
+ export async function genPermissionDataOld(app: App) {
312
318
  openCache();
313
319
  const logicPageResourceDtoList: { [key: string]: ResourceNode[][]; } = {};
314
320
  const { logics, processLogics } = getAllLogics(app);
@@ -316,31 +322,335 @@ export async function genPermissionData(app: App) {
316
322
  for (const logic of [...logics, ...processLogics]) {
317
323
  const resources = await findResourcesOfLogic(logic, uploaders);
318
324
  if (resources.length === 0) continue;
319
- const service = logics.includes(logic) ? logic.toService() : (logic.toProcessService() as { url: { method: string; path: string; }; });
325
+ const service = logics.includes(logic)
326
+ ? logic.toService()
327
+ : (logic.toProcessService() as { url: { method: string; path: string; }; });
320
328
  const key = `${service.url.path}:${service.url.method}`;
321
329
  logicPageResourceDtoList[key] = resources;
322
330
  }
323
- const authValue = checkUploadAuth(uploaders);
324
- if (authValue?.length) {
325
- authValue.forEach((item) => {
331
+ const authVals = checkUploadAuth(uploaders);
332
+ if (authVals?.length) {
333
+ authVals.forEach((item) => {
326
334
  const { key, authValue } = item;
327
335
  if (key.startsWith('/upload' || '/api/')) {
328
- logicPageResourceDtoList[`${key}:POST`] = checkPageAndUploadAuth(uploaders, key) !== -1 ? [[]] : convertArray(authValue);
336
+ logicPageResourceDtoList[`${key}:POST`] = checkPageAndUploadAuth(uploaders, key) ? [[]] : convertArray(authValue);
329
337
  }
330
338
  });
331
339
  }
332
340
  logicPageResourceDtoList['/upload/download_files:POST'] = callLogicUploadList;
333
341
  closeCache();
334
- // console.timeEnd('xxx');
335
342
  return logicPageResourceDtoList;
336
343
  }
344
+
345
+
346
+
347
+ function generateServiceKey(logic : Logic, kind : 'server' | 'process') {
348
+ let service : { url: { method: string; path: string; }};
349
+ if (kind === 'server') {
350
+ service = logic.toService()
351
+ } else if (kind === 'process') {
352
+ service = (logic.toProcessService() as { url: { method: string; path: string; }; })
353
+ } else {
354
+ throw new Error('Invalid service key kind')
355
+ }
356
+ const key = `${service.url.path}:${service.url.method}`;
357
+ return key;
358
+ }
359
+
360
+ function createArrayOnAdd<K, V>(k : K, v : V, m: Map<K, Array<V>>) {
361
+ if (m.get(k)) {
362
+ m.get(k).push(v);
363
+ } else {
364
+ m.set(k, [v]);
365
+ }
366
+ }
367
+
368
+ // 需要区分:前端逻辑、后端逻辑、流程逻辑
369
+ // 需要的信息:后端逻辑、流程逻辑的 service path;逻辑调用到其定义的映射;
370
+ // 流程逻辑 call 的 getCallNode() 每次都不同
371
+ // 表单验证 $refs.validate 的定义缺少 calleewholeKey 且访问时会抛异常
372
+ // 不跳过 playground 草稿区内容:赫基有用到 JS代码块,在代码块里调用逻辑。JS代码块里的引用没有识别出来。但恰巧在草稿区的东西,提供了引用关系。赫基项目,删除了草稿区的东西会导致401。
373
+ export function genPermissionData(app: App): { [key: string]: ResourceNode[][]; } {
374
+ type TraverseCtx = { viewElement : ViewElement, viewElements: Set<ViewElement>, thisLogic : Logic, bindEvent : BindEvent, event : Event, view : View};
375
+ type LogicCtx = { view : View, viewElements : Set<ViewElement> }
376
+ type FrontendLogicCtx = { view : View, viewElements : Set<ViewElement>, thisLogic : Logic }
377
+
378
+ function clearCtx(ctx: TraverseCtx) {
379
+ ctx.viewElement = null;
380
+ ctx.viewElements = new Set();
381
+ ctx.thisLogic = null;
382
+ ctx.bindEvent = null;
383
+ ctx.event = null;
384
+ ctx.view = null;
385
+ }
386
+ const { logics : tmpLogics, processLogics : tmpProcessLogics } = getAllLogics(app);
387
+
388
+ // 调用后端逻辑的Map
389
+ const backendLogicCallCtx : Map<string, Array<LogicCtx>> = new Map();
390
+
391
+ // 调用前端逻辑的Map
392
+ const frontendLogicCallCtx: Array<FrontendLogicCtx> = [];
393
+
394
+ // from calleeWholeKey to Logic,消除流程逻辑每次找到的定义都是即时演算生成的,地址不同的问题。
395
+ const frontNdCache = new Map<string, Logic>();
396
+ const processNdCache = new Map<string, Logic>();
397
+ const serverNdCache = new Map<string, Logic>();
398
+
399
+ tmpProcessLogics.forEach(l => processNdCache.set(l.calleewholeKey, l));
400
+ tmpLogics.forEach(l => serverNdCache.set(l.calleewholeKey, l));
401
+
402
+ // 上传组件
403
+ const uploaders = new Map<string, Array<ViewElement>>();
404
+ const callLogicUploadList = new Map<string, any>();
405
+ let callLogicUploadFlag = false;
406
+
407
+ const defToCalls : Map<Logic, Array<CallLogic>> = new Map();
408
+ app.frontendTypes.forEach((frontendType) => {
409
+ frontendType.traverseChildrenWithContext((nd, ctx : TraverseCtx) => {
410
+ switch (nd.concept) {
411
+ case 'ViewElement': {
412
+ ctx.thisLogic = null;
413
+ ctx.viewElement = nd;
414
+ ctx.viewElements = new Set(ctx.viewElements); // if use ctx.viewElements.add(node) directly, will encounter a SEVERE slow down. For example, 3s vs 12s
415
+ ctx.viewElements.add(nd);
416
+ // collect uploaders
417
+ if (nd.tag?.includes('uploader')) {
418
+ const urlAttr = nd.bindAttrs.find((item : BindAttribute) => item.name === 'url');
419
+ const url = urlAttr?.value;
420
+ if (url) {
421
+ if (!uploaders.has(url)) uploaders.set(url, [nd]);
422
+ else uploaders.get(url).push(nd);
423
+ }
424
+ }
425
+ break;
426
+ }
427
+ case 'BindEvent': ctx.bindEvent = nd; break;
428
+ case 'Event': ctx.event = nd; break;
429
+ case 'CallLogic': {
430
+ const { thisLogic, event, bindEvent, view, viewElement, viewElements } = ctx;
431
+ createArrayOnAdd(thisLogic, nd, defToCalls);
432
+ if (viewElement || bindEvent || event) {
433
+ const [kind, logicDecl] = (nd as CallLogic).getCallNodeUsingCache(frontNdCache, serverNdCache, processNdCache);
434
+ switch (kind) {
435
+ case 'server': {
436
+ const key = generateServiceKey(logicDecl, 'server');
437
+ createArrayOnAdd(key, { view, viewElements }, backendLogicCallCtx);
438
+ break;
439
+ }
440
+ case 'process': {
441
+ const key = generateServiceKey(logicDecl, 'process');
442
+ createArrayOnAdd(key, { view, viewElements }, backendLogicCallCtx);
443
+ break;
444
+ }
445
+ case 'front': {
446
+ frontendLogicCallCtx.push({ view, viewElements, thisLogic: logicDecl });
447
+ break;
448
+ }
449
+ default: throw new Error('Invalid logic kind');
450
+ }
451
+ }
452
+
453
+ // 收集 callLogicUploadList
454
+ if (nd?.calleeName?.includes('downloadFile') && nd?.calleeNamespace === 'nasl.io' && !callLogicUploadFlag) {
455
+ // ViewElement 权限优先
456
+ if (viewElement instanceof ViewElement && viewElement?.auth) {
457
+ callLogicUploadList.set(viewElement?.authPath, [{
458
+ type: 'component',
459
+ path: viewElement?.authPath
460
+ }]);
461
+ } else if (view instanceof View && view?.auth) {
462
+ callLogicUploadList.set(view?.authPath, [{
463
+ type: 'page',
464
+ path: view?.authPath
465
+ }]);
466
+ } else {
467
+ // 如果开启权限和未开启权限都有,以未开启权限为准,清空 map,设置为 [[]]
468
+ callLogicUploadFlag = true;
469
+ callLogicUploadList.clear()
470
+ }
471
+ }
472
+ break;
473
+ }
474
+ case 'BindAttribute': {
475
+ if (nd.name === 'dataSource'
476
+ && nd.type === 'dynamic'
477
+ && nd.expression instanceof Identifier
478
+ && (ctx.view) // View | BusinessComponent
479
+ ) {
480
+ const viewLogics = ctx.view.logics; // Array<Logic> | Array<BusinessLogic>
481
+ const identName = nd.expression.name;
482
+ const logic = viewLogics.find((viewLogic : any) => {
483
+ return viewLogic?.name === identName;
484
+ });
485
+ if (logic) {
486
+ const { viewElements, view } = ctx;
487
+ frontendLogicCallCtx.push({ viewElements, view, thisLogic: logic });
488
+ }
489
+ }
490
+ break;
491
+ }
492
+ case 'Logic': ctx.thisLogic = nd; break;
493
+ case 'BusinessLogic': ctx.thisLogic = nd; break;
494
+ case 'View': clearCtx(ctx); ctx.view = nd; break;
495
+ case 'Identifier': {
496
+ // 参数选了函数名。高阶函数。
497
+ if (nd?.namespace === "app.logics") {
498
+ const key = `/api/lcplogics/${nd.name}:POST`;
499
+ createArrayOnAdd(key, { view: ctx.view, viewElements: ctx.viewElements }, backendLogicCallCtx);
500
+ }
501
+ // 草稿区也可能有这种 concept 是 Identifier 的调用
502
+ if (ctx?.view) {
503
+ const viewLogics = ctx.view.logics; // Array<Logic> | Array<BusinessLogic>
504
+ const identName = nd.name;
505
+ const logic = viewLogics.find((viewLogic : any) => {
506
+ return viewLogic?.name === identName;
507
+ });
508
+ if (logic) {
509
+ const { viewElements, view } = ctx;
510
+ frontendLogicCallCtx.push({ viewElements, view, thisLogic: logic });
511
+ }
512
+ }
513
+ break;
514
+ }
515
+ case 'BusinessComponent': clearCtx(ctx); ctx.view = nd; break;
516
+ default: break;
517
+ }
518
+ });
519
+ });
520
+
521
+ frontendLogicCallCtx.forEach(({ view, viewElements, thisLogic }) => {
522
+ const findCallBackendLogic = ([kind, l] : ['process' | 'server' | 'front', Logic]) => {
523
+ if (!l) {
524
+ return;
525
+ }
526
+ switch (kind) {
527
+ case 'server': {
528
+ const key = generateServiceKey(l, 'server');
529
+ createArrayOnAdd(key, { view, viewElements }, backendLogicCallCtx);
530
+ break;
531
+ }
532
+ case 'process': {
533
+ const key = generateServiceKey(l, 'process');
534
+ createArrayOnAdd(key, { view, viewElements }, backendLogicCallCtx);
535
+ break;
536
+ }
537
+ case 'front': {
538
+ const lgcCalls : Array<CallLogic> = defToCalls.get(l);
539
+ lgcCalls?.forEach( call => findCallBackendLogic(call.getCallNodeUsingCache(frontNdCache, serverNdCache, processNdCache)));
540
+ break;
541
+ }
542
+ default: {
543
+ throw new Error('Invalid logic kind in frontendLogicCallCtx');
544
+ }
545
+ }
546
+ };
547
+ findCallBackendLogic(['front', thisLogic]);
548
+ });
549
+
550
+ const logicPageResourceDtoList: { [key: string]: ResourceNode[][]; } = {};
551
+ backendLogicCallCtx.forEach((ctx, key) => {
552
+ const resources: ResourceNode[][] = [];
553
+ ctx?.forEach(({ viewElements, view }) => {
554
+ const pathInfos: Array<ResourceNode> = [];
555
+ viewElements?.forEach((viewElement) => {
556
+ if (viewElement?.auth) {
557
+ pathInfos.push({
558
+ path: viewElement?.authPath,
559
+ type: 'component',
560
+ });
561
+ }
562
+ });
563
+ let viewIter : BaseNode = view;
564
+ while (viewIter) {
565
+ if (viewIter instanceof View && viewIter.auth) {
566
+ pathInfos.push({
567
+ path: viewIter.authPath,
568
+ type: 'page',
569
+ });
570
+ }
571
+ viewIter = viewIter.parentNode;
572
+ }
573
+ resources.push(pathInfos);
574
+ });
575
+ logicPageResourceDtoList[key] = optimizeResourceData(resources);
576
+ });
577
+
578
+ const authVals = checkUploadAuth(uploaders);
579
+ if (authVals?.length) {
580
+ authVals.forEach((item) => {
581
+ const { key, authValue } = item;
582
+ if (key.startsWith('/upload' || '/api/')) {
583
+ logicPageResourceDtoList[`${key}:POST`] =
584
+ checkPageAndUploadAuth(uploaders, key) ? [[]] : convertArray(authValue);
585
+ }
586
+ });
587
+ }
588
+ logicPageResourceDtoList['/upload/download_files:POST'] =
589
+ callLogicUploadList.size === 0 ? [[]] : Array.from(callLogicUploadList.values());
590
+
591
+ return logicPageResourceDtoList;
592
+ }
593
+
337
594
  export function genLogicAuthFlag(app: App) {
338
595
  let flag = false;
339
- app.traverseChildren((node) => {
340
- if (flag) return;
341
-
596
+ app.traverseStrictChildrenStopWhen((node) => {
342
597
  if ((node instanceof View || node instanceof ViewElement) && node.auth) flag = true;
343
- });
598
+ }, (nd) => (nd instanceof View || nd instanceof ViewElement) && Boolean(nd.auth), []);
344
599
 
345
600
  return flag;
346
601
  }
602
+
603
+
604
+ function compareResourceNode(a: ResourceNode, b: ResourceNode) {
605
+ if (a.path < b.path) {
606
+ return -1;
607
+ }
608
+ if (a.path > b.path) {
609
+ return 1;
610
+ }
611
+ if (a.type < b.type) {
612
+ return -1;
613
+ }
614
+ if (a.type > b.type) {
615
+ return 1;
616
+ }
617
+ return 0;
618
+ }
619
+
620
+ function compareResourceNodeList(a: Array<ResourceNode>, b: Array<ResourceNode>) {
621
+ a.sort(compareResourceNode);
622
+ b.sort(compareResourceNode);
623
+ for (let i = 0; i < a.length; i++) {
624
+ const result = compareResourceNode(a[i], b[i]);
625
+ if (result !== 0) {
626
+ return result;
627
+ }
628
+ }
629
+ return 0;
630
+ }
631
+
632
+ export function sortResourceDtoMap<K>(m : Map<K, Array<Array<ResourceNode>>>){
633
+ const keys = Array.from(m.keys()).sort();
634
+ const sortedMap = new Map<K,Array<Array<ResourceNode>>>();
635
+ keys.forEach((key) => {
636
+ sortedMap.set(key, m.get(key).sort(compareResourceNodeList));
637
+ });
638
+
639
+ keys.forEach((key) => {
640
+ sortedMap.get(key).forEach((item) => {
641
+ item.sort(compareResourceNode);
642
+ });
643
+ });
644
+ return sortedMap;
645
+ }
646
+
647
+ export async function testWithOldPermissionResult(app: App, newRes : { [key: string]: ResourceNode[][]; }) {
648
+ const newResMap = sortResourceDtoMap(new Map(Object.entries(newRes)));
649
+ console.log('newResMap', newResMap)
650
+ const oldRes : { [key: string]: ResourceNode[][]; } = await genPermissionDataOld(app);
651
+ const oldResMap = sortResourceDtoMap(new Map(Object.entries(oldRes)));
652
+ console.log('oldResMap', oldResMap)
653
+
654
+ console.log("oldLogicPageResourceDtoListMap === newLogicPageResourceDtoListMap?",
655
+ JSON.stringify(Array.from(newResMap.entries())) === JSON.stringify(Array.from(oldResMap.entries())));
656
+ }
@@ -6,7 +6,7 @@ import {
6
6
  import { genFrontendBundleFiles } from '../genBundleFiles';
7
7
  import { InternalReleaseData } from './internal';
8
8
  import { replaceAssetUrl, getAuthReport, getFrontendByTypes, findAllReportIdList, getProcessFormDefinitions } from './utils';
9
- import { genPermissionData, genLogicAuthFlag } from '../permission';
9
+ import { genPermissionDataOld, genPermissionData, genLogicAuthFlag, testWithOldPermissionResult } from '../permission';
10
10
  import { getCallLogicData } from './validation';
11
11
 
12
12
  import * as utils from '../../utils';
@@ -80,7 +80,7 @@ export async function getNaslAnnotatedJSON(app: App, opt: InternalReleaseData) {
80
80
 
81
81
  try {
82
82
  NaslAnnotatedJSON = await app.naslServer.getNaslAnnotatedJSON(app, true);
83
- await opt.logPublishFunc?.('语言', '获取类型标注成功');
83
+ await opt.logPublishFunc?.('语言', '获取全量类型标注成功');
84
84
 
85
85
  // // 打印传给服务端的 nasl,为了服务端排查问题方便
86
86
  // if (globalThis.window) {
@@ -165,6 +165,8 @@ export async function getNaslAnnotatedJSON(app: App, opt: InternalReleaseData) {
165
165
  }
166
166
  });
167
167
 
168
+ await opt.logPublishFunc?.('资源', '前端静态资源替换完成');
169
+
168
170
  return {
169
171
  name: 'nasl-annotated.json',
170
172
  content: JSON.stringify(NaslAnnotatedJSON),
@@ -203,12 +205,16 @@ async function getFrontendBundleFiles(app: App, opt: InternalReleaseData) {
203
205
  return files;
204
206
  }
205
207
 
208
+
206
209
  async function mergeBodyData(app: App, opt: InternalReleaseData) {
207
210
  await utils.delay(500);
208
211
 
209
212
  const authReport: ReturnType<typeof getAuthReport> = getAuthReport(app, opt.frontends);
210
213
  await opt.logPublishFunc?.('权限', '分析权限数据成功!');
211
- const logicPageResourceDtoList = await genPermissionData(app);
214
+ const logicPageResourceDtoList = genPermissionData(app);
215
+
216
+ // 与老板逻辑权限数据对比
217
+ // await testWithOldPermissionResult(app, logicPageResourceDtoList);
212
218
  const allFrontends = getFrontendByTypes(app?.frontendTypes);
213
219
  const releaseFrontends = allFrontends.map((frontend: Frontend) => ({
214
220
  name: frontend.name,
@@ -217,6 +223,8 @@ async function mergeBodyData(app: App, opt: InternalReleaseData) {
217
223
  selected: opt.frontends.includes(frontend),
218
224
  title: frontend.title,
219
225
  }));
226
+ const callbackLogicsName = app.getExtensionsCallbackLogics()
227
+
220
228
  const body = {
221
229
  ...authReport, // 如果发布需要上报权限,导出源码不需要
222
230
  logicPageResourceDtoList,
@@ -228,7 +236,7 @@ async function mergeBodyData(app: App, opt: InternalReleaseData) {
228
236
  branchId: opt.branchId,
229
237
  replicas: opt.replicas,
230
238
  appSpecification: opt.appSpecification,
231
- callbackLogicsName: app.getExtensionsCallbackLogics(),
239
+ callbackLogicsName,
232
240
  frontends: releaseFrontends,
233
241
  callLogicValidations: {},
234
242
  files: [] as Array<{ name: string; content: string }>,
@@ -242,14 +250,25 @@ async function mergeBodyData(app: App, opt: InternalReleaseData) {
242
250
  }
243
251
 
244
252
  export async function genReleaseBody(app: App, opt: InternalReleaseData) {
253
+ console.time('--backend--');
254
+ console.time('mergeBodyData');
245
255
  const body = await mergeBodyData(app, opt);
256
+ console.timeEnd('mergeBodyData');
246
257
  const callLogicValidations = await getCallLogicData(app, opt.validations);
258
+ console.timeEnd('--backend--');
259
+
260
+ console.time('--frontend--');
261
+ console.time('getNaslAnnotatedJSON');
247
262
  const annotationFile = await getNaslAnnotatedJSON(app, opt);
263
+ console.timeEnd('getNaslAnnotatedJSON');
264
+ console.time('getFrontendBundleFiles');
248
265
  const files = opt.ignoreFiles ? [] : await getFrontendBundleFiles(app, opt);
266
+ console.timeEnd('getFrontendBundleFiles');
267
+ console.timeEnd('--frontend--');
249
268
 
250
269
  files.push(annotationFile);
251
270
 
252
- // nodejs 环境下某些情况下字符会发生错误,需要转译
271
+ // nodejs 环境下的极速开发模式,在某些情况下字符会发生错误,需要转译
253
272
  if (utils.isNode) {
254
273
  files.forEach((file) => {
255
274
  file.name = encodeURIComponent(file.name);
@@ -18,7 +18,8 @@ import { Logger, File } from '../../utils';
18
18
  export async function getReleaseData(app: App, data: ReleaseData, naslServer: NaslServer, inputLogger?: Logger) {
19
19
  const { http, logger: defaultLogger } = naslServer;
20
20
  const logger = inputLogger ?? defaultLogger;
21
- defaultLogger.time('前端构建');
21
+ console.time('all');
22
+ console.time('request');
22
23
  const appInfo = await getAppInfo(http, data);
23
24
  await logger.info('构建环境', '获取环境信息成功');
24
25
  const { version, fullVersion, dependencies } = await getVersionDetail(http, app);
@@ -77,7 +78,9 @@ export async function getReleaseData(app: App, data: ReleaseData, naslServer: Na
77
78
  await logger.info('生成器', '服务端验证数据获取成功');
78
79
  }
79
80
  }
81
+ console.timeEnd('request');
80
82
 
83
+ console.time('前端构建');
81
84
  await logger.info('构建环境', '构建环境完成,开始拼装发布数据');
82
85
 
83
86
  const releaseBody = await genReleaseBody(app, {
@@ -86,7 +89,9 @@ export async function getReleaseData(app: App, data: ReleaseData, naslServer: Na
86
89
  });
87
90
 
88
91
  await logger.info('前端生成器', '应用发布数据准备完成');
89
- defaultLogger.timeEnd('前端构建');
92
+ console.timeEnd('前端构建');
93
+
94
+ console.timeEnd('all');
90
95
 
91
96
  return releaseBody;
92
97
  }
@@ -80,7 +80,7 @@ export function getAuthReport(app: App, frontends: Array<Frontend>) {
80
80
  * 获取页面中所有 分析报告组件 的reportId
81
81
  */
82
82
  export function findAllReportIdList(app: App, frontends: Array<Frontend>) {
83
- const reportIds: string[] = [];
83
+ const reportIds: Set<string> = new Set();
84
84
 
85
85
  frontends.forEach((frontend) => {
86
86
  frontend.views.forEach((view) => loop(view));
@@ -90,7 +90,7 @@ export function findAllReportIdList(app: App, frontends: Array<Frontend>) {
90
90
  if (root.concept === 'ViewElement') {
91
91
  root.bindAttrs.forEach((attr) => {
92
92
  if (attr.name === 'reportId') {
93
- reportIds.push(JSON.parse(attr.value || '{}').id);
93
+ reportIds.add(JSON.parse(attr.value || '{}').id);
94
94
  }
95
95
  });
96
96
  }
@@ -101,7 +101,7 @@ export function findAllReportIdList(app: App, frontends: Array<Frontend>) {
101
101
  root.elements.forEach((item) => loop(item));
102
102
  }
103
103
  }
104
- return [...new Set(reportIds)].filter(Boolean);
104
+ return Array.from(reportIds).filter(Boolean);
105
105
  }
106
106
 
107
107
  export function replaceAssetUrl(
@@ -31,9 +31,9 @@ export async function getCallLogicData(app: App, validations: InputServerValidat
31
31
 
32
32
  nasl.traverseStrictChildren((node) => {
33
33
  if (
34
- 'uuid' in node &&
35
34
  node.concept === 'CallLogic' &&
36
35
  node.validation &&
36
+ 'uuid' in node &&
37
37
  map.has(node.uuid)
38
38
  ) {
39
39
  const data = map.get(node.uuid)!;
package/src/index.ts CHANGED
@@ -8,7 +8,19 @@ export * as utils from './utils';
8
8
  export * from './config';
9
9
  export * from './eventBus';
10
10
  export * as breakpoint from './breakpoint';
11
- export { getOperationRecords, operationRecordInfoMap, doOperationRecord, operationRecordQuery, operationRecordPlayback, loadApp, loadAppSync, handleApp, batchAction, batchQuery, mountDatabaseTypes } from './service/storage/init';
11
+ export {
12
+ getOperationRecords,
13
+ operationRecordInfoMap,
14
+ doOperationRecord,
15
+ operationRecordQuery,
16
+ operationRecordPlayback,
17
+ loadApp,
18
+ loadAppSync,
19
+ handleApp,
20
+ batchAction,
21
+ batchQuery,
22
+ mountDatabaseTypes,
23
+ } from './service/storage/init';
12
24
  export { createService } from './service/creator';
13
25
  export { stepRecorder } from './manager/stepRecorder';
14
26
  export * from './natural';
@@ -36,11 +36,12 @@ export function genNaturalTSContextForLogic(
36
36
  app: App,
37
37
  currentNode?: BaseNode,
38
38
  focusedNodePath?: string,
39
- requiredIndexes?: string[]
39
+ requiredIndexes?: string[],
40
+ experimental?: boolean
40
41
  ) {
41
42
  const frontend = currentNode?.getAncestor('Frontend') as Frontend;
42
43
  const logicType = currentNode?.parentNode?.concept === 'App' ? 'global_logic' : 'view_logic';
43
- const state = createCompilerState();
44
+ const state = createCompilerState('', { descriptionComment: true });
44
45
 
45
46
  let code = '';
46
47
  code += '### [1] 标准库\n';
@@ -98,7 +99,7 @@ export function genNaturalTSContextForLogic(
98
99
 
99
100
  if (focusedNodePath) {
100
101
  code += '\n### 当前逻辑上下文\n';
101
- code += getCurrentNodeContext(currentNode, focusedNodePath).code;
102
+ code += getCurrentNodeContext(currentNode, focusedNodePath, experimental).code;
102
103
  }
103
104
  return code;
104
105
  }
@@ -113,7 +114,7 @@ export function genNaturalTSContextForUI(
113
114
  material?: { basicMaterials: { json: any; tsDeclaration: string; }, extensionMaterials: { name: string; title: string; description: string; tsDescription: string; }[]; },
114
115
  ) {
115
116
  const frontend = currentNode.getAncestor('Frontend') as Frontend;
116
- const state = createCompilerState();
117
+ const state = createCompilerState('', { descriptionComment: true });
117
118
 
118
119
  let code = '';
119
120
  code += '### [1] 标准库\n';
@@ -168,11 +169,12 @@ export function genNaturalTSContextForUI(
168
169
  export function genNaturalTSContextJSONForLogic(
169
170
  app: App,
170
171
  currentNode?: BaseNode,
171
- focusedNodePath?: string
172
+ focusedNodePath?: string,
173
+ experimental?: boolean
172
174
  ) {
173
175
  const frontend = currentNode?.getAncestor('Frontend') as Frontend;
174
176
  const logicType = currentNode?.parentNode?.concept === 'App' ? 'global_logic' : 'view_logic';
175
- const state = createCompilerState();
177
+ const state = createCompilerState('', { descriptionComment: true });
176
178
 
177
179
  const { naslCore } = getNaslCore(logicType);
178
180
  const { naslUtil } = getNaslUtil();
@@ -190,7 +192,7 @@ export function genNaturalTSContextJSONForLogic(
190
192
  state
191
193
  );
192
194
  const { views } = getFrontendViews(frontend, state, currentNode, false);
193
- const { currentLogic } = getCurrentNodeContext(currentNode, focusedNodePath);
195
+ const { currentLogic } = getCurrentNodeContext(currentNode, focusedNodePath, experimental);
194
196
 
195
197
  return {
196
198
  naslCore,