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

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 (217) 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 +3 -3
  15. package/out/concepts/BatchAssignment__.js.map +1 -1
  16. package/out/concepts/BindAttribute__.js +5 -6
  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 +3 -3
  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 +10 -7
  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 +61 -51
  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/getUILib.js +9 -5
  112. package/out/natural/getContext/getUILib.js.map +1 -1
  113. package/out/natural/getContext/index.d.ts +1 -1
  114. package/out/natural/getContext/index.js +15 -9
  115. package/out/natural/getContext/index.js.map +1 -1
  116. package/out/natural/transformTS2UI.js +30 -11
  117. package/out/natural/transformTS2UI.js.map +1 -1
  118. package/out/natural/transformTSCode.js +30 -11
  119. package/out/natural/transformTSCode.js.map +1 -1
  120. package/out/server/entity2LogicNamespace.d.ts +2 -2
  121. package/out/server/entity2LogicNamespace.js +321 -310
  122. package/out/server/entity2LogicNamespace.js.map +1 -1
  123. package/out/server/extendBaseNode.js +29 -18
  124. package/out/server/extendBaseNode.js.map +1 -1
  125. package/out/server/naslServer.d.ts +1 -1
  126. package/out/server/naslServer.js +32 -18
  127. package/out/server/naslServer.js.map +1 -1
  128. package/out/server/translator.js +12 -0
  129. package/out/server/translator.js.map +1 -1
  130. package/out/service/storage/init.d.ts +2 -0
  131. package/out/service/storage/init.js +20 -1
  132. package/out/service/storage/init.js.map +1 -1
  133. package/out/templator/genCreateBlock.js +3 -3
  134. package/out/templator/genCreateBlock.js.map +1 -1
  135. package/out/templator/genCurdEditMultipleKeyBlock.js +2 -2
  136. package/out/templator/genCurdEditMultipleKeyBlock.js.map +1 -1
  137. package/out/templator/genCurdMultipleKeyBlock.js +4 -4
  138. package/out/templator/genCurdMultipleKeyBlock.js.map +1 -1
  139. package/out/templator/genEditTableBlock.js +1 -1
  140. package/out/templator/genEditTableBlock.js.map +1 -1
  141. package/out/templator/genGetBlock.js.map +1 -1
  142. package/out/templator/genGridViewBlock.js.map +1 -1
  143. package/out/templator/genSelectBlock.js.map +1 -1
  144. package/out/templator/genTableBlock.js.map +1 -1
  145. package/out/templator/genUpdateBlock.js +3 -3
  146. package/out/templator/genUpdateBlock.js.map +1 -1
  147. package/out/templator/utils.js +1 -1
  148. package/out/templator/utils.js.map +1 -1
  149. package/package.json +5 -5
  150. package/sandbox/stdlib/nasl.util.ts +4 -1
  151. package/src/common/BaseNode.ts +91 -11
  152. package/src/concepts/AbstractInterface__.ts +1 -0
  153. package/src/concepts/Annotation__.ts +1 -1
  154. package/src/concepts/App__.ts +104 -4
  155. package/src/concepts/Argument__.ts +3 -3
  156. package/src/concepts/BatchAssignment__.ts +3 -3
  157. package/src/concepts/BindAttribute__.ts +5 -6
  158. package/src/concepts/BindDirective__.ts +3 -4
  159. package/src/concepts/BusinessComponent__.ts +54 -1
  160. package/src/concepts/BusinessLogic__.ts +10 -1
  161. package/src/concepts/CallEvent__.ts +66 -0
  162. package/src/concepts/CallInterface__.ts +21 -9
  163. package/src/concepts/CallLogic__.ts +59 -3
  164. package/src/concepts/Entity__.ts +7 -1
  165. package/src/concepts/Event__.ts +32 -0
  166. package/src/concepts/FrontendType__.ts +34 -1
  167. package/src/concepts/Frontend__.ts +51 -0
  168. package/src/concepts/IfStatement__.ts +6 -6
  169. package/src/concepts/InterfaceParam__.ts +23 -4
  170. package/src/concepts/Interface__.ts +29 -5
  171. package/src/concepts/JSBlock__.ts +5 -0
  172. package/src/concepts/LogicDeclaration__.ts +65 -7
  173. package/src/concepts/Logic__.ts +34 -25
  174. package/src/concepts/MatchCase__.ts +1 -2
  175. package/src/concepts/Match__.ts +3 -21
  176. package/src/concepts/MemberExpression__.ts +1 -1
  177. package/src/concepts/Module__.ts +75 -0
  178. package/src/concepts/NewComposite__.ts +3 -3
  179. package/src/concepts/Paginate__.ts +14 -7
  180. package/src/concepts/QueryFromExpression__.ts +2 -2
  181. package/src/concepts/StringLiteral__.ts +3 -4
  182. package/src/concepts/TypeAnnotation__.ts +1 -0
  183. package/src/concepts/ViewElement__.ts +11 -7
  184. package/src/concepts/View__.ts +56 -1
  185. package/src/generator/genBundleFiles.ts +67 -54
  186. package/src/generator/genHash.ts +32 -6
  187. package/src/generator/permission.ts +333 -23
  188. package/src/generator/release-body/body.ts +24 -5
  189. package/src/generator/release-body/data.ts +7 -2
  190. package/src/generator/release-body/utils.ts +3 -3
  191. package/src/generator/release-body/validation.ts +1 -1
  192. package/src/index.ts +13 -1
  193. package/src/natural/genNaturalTS.ts +9 -7
  194. package/src/natural/getContext/getUILib.ts +9 -5
  195. package/src/natural/getContext/index.ts +17 -11
  196. package/src/natural/transformTS2UI.ts +28 -11
  197. package/src/natural/transformTSCode.ts +28 -11
  198. package/src/server/entity2LogicNamespace.ts +13 -1
  199. package/src/server/extendBaseNode.ts +32 -22
  200. package/src/server/naslServer.ts +42 -25
  201. package/src/server/translator.ts +15 -0
  202. package/src/service/storage/init.ts +26 -0
  203. package/src/templator/genCreateBlock.ts +4 -4
  204. package/src/templator/genCurdEditMultipleKeyBlock.ts +2 -2
  205. package/src/templator/genCurdMultipleKeyBlock.ts +7 -7
  206. package/src/templator/genEditTableBlock.ts +4 -4
  207. package/src/templator/genGetBlock.ts +1 -1
  208. package/src/templator/genGridViewBlock.ts +2 -2
  209. package/src/templator/genSelectBlock.ts +3 -3
  210. package/src/templator/genTableBlock.ts +2 -2
  211. package/src/templator/genUpdateBlock.ts +6 -6
  212. package/src/templator/utils.ts +1 -1
  213. package/test/concepts/call-logic/__snapshots__/getQuickInfoOffset.spec.ts.snap +1 -1
  214. package/test/concepts/call-logic/__snapshots__/toEmbeddedTS.spec.ts.snap +1 -1
  215. package/test/concepts/string-literal/__snapshots__/toVue.spec.ts.snap +1 -1
  216. package/test/concepts/view-element/__snapshots__/toEmbeddedTS.spec.ts.snap +75 -75
  217. package/test/concepts/view-element/__snapshots__/toVue.spec.ts.snap +6 -2
@@ -176,7 +176,6 @@ function genRouteFiles(routes: Route[], defaultRoute: string,config?: any) {
176
176
  // 生成路由文件列表
177
177
  const routeFiles: any[] = [];
178
178
  function routeToFile(route: Route) {
179
- console.log(route, 'route');
180
179
  if (route?.component?.script) {
181
180
  const content = genExportComponetCode(route.component);
182
181
  const lazyPath = getCompletePath(null, content, config);
@@ -236,6 +235,7 @@ export function genBundleFiles(app: App, frontend: Frontend, config: Config) {
236
235
  try {
237
236
  config?.debug && genBreakpoints(app);
238
237
  app.curDeployEnv = config.env
238
+ console.time('toVueOptions');
239
239
 
240
240
  utils.traverse(
241
241
  (current) => {
@@ -252,6 +252,7 @@ export function genBundleFiles(app: App, frontend: Frontend, config: Config) {
252
252
  } as View,
253
253
  }
254
254
  );
255
+ console.timeEnd('toVueOptions');
255
256
 
256
257
  businessComponents.forEach((businessComponent) => {
257
258
  const frontendI18nEnabled = frontend?.i18nInfo?.enabled
@@ -543,8 +544,16 @@ export function genBundleFiles(app: App, frontend: Frontend, config: Config) {
543
544
  } else if(window.parent.isGlobalScaleTop) {
544
545
  // 点击跳转到外部页面时,通知顶层页面
545
546
  document.body.addEventListener('click', (e) => {
546
- if(e.target.href){
547
- parent.location.href = e.target.href;
547
+ if(!e.target.href) return;
548
+ if(typeof e.target.href !== 'string') return;
549
+ if(e.target.tagName !== 'A') return;
550
+ try {
551
+ const url = new URL(e.target.href);
552
+ if(url.host !== location.host){
553
+ parent.location.href = e.target.href;
554
+ }
555
+ } catch(err) {
556
+ console.error(err);
548
557
  }
549
558
  });
550
559
  }
@@ -618,8 +627,8 @@ export function genBundleFiles(app: App, frontend: Frontend, config: Config) {
618
627
  }
619
628
  return response.text();
620
629
  }).then(function(scriptText) {
621
- var func = new Function(scriptText);
622
- var result = func();
630
+ var func = new Function('importComponent', scriptText);
631
+ var result = func(window.importComponent);
623
632
  return result;
624
633
  })
625
634
  .catch(error => {
@@ -879,9 +888,7 @@ export function genBundleFiles(app: App, frontend: Frontend, config: Config) {
879
888
 
880
889
 
881
890
 
882
- console.time('genHash')
883
891
  let bundleMinPath = completePath + getCompletePath(getBundleFileName(), content, config);
884
- console.timeEnd('genHash');
885
892
 
886
893
  const otherJsList = (frontend as any)?.appletsConfig?.enable ? ['//res.wx.qq.com/open/js/jweixin-1.3.2.js'] : [];
887
894
 
@@ -1018,45 +1025,7 @@ export function genBundleFiles(app: App, frontend: Frontend, config: Config) {
1018
1025
  },
1019
1026
  ...routerFiles,
1020
1027
  ];
1021
- const assets = config.assets;
1022
- // 导出源码才处理
1023
- if (config.isExport && Array.isArray(assets) && assets.length) {
1024
- function replaceContentFilePath(content: string) {
1025
- const assetsMap = config.assetsMap;
1026
- // 正则
1027
- const regex = utils.transAssetsToRegx(assets, 'fileUrl');
1028
- content = content.replace(regex, (url) => {
1029
- const asset: Asset = utils.getAssetFromAssetsMap(assetsMap, url);
1030
- if (asset) {
1031
- const basePath = frontend?.basePath;
1032
- const assetName = asset.name;
1033
- const assetDir = basePath ? `${basePath}/assets/${assetName}` : `/assets/${assetName}`;
1034
- let path = assetDir;
1035
- const sysPrefixPath = frontend?.app?.sysPrefixPath;
1036
- if (sysPrefixPath) {
1037
- path = `${sysPrefixPath}${assetDir}`;
1038
- }
1039
- globalConfig.assets.push({
1040
- path: assetDir,
1041
- isDir: false,
1042
- url,
1043
- });
1044
- const encodeAssetName = encodeURIComponent(assetName);
1045
- let encodeAssetDir = basePath ? `${basePath}/assets/${encodeAssetName}` : `/assets/${encodeAssetName}`;
1046
- if (sysPrefixPath) {
1047
- encodeAssetDir = `${sysPrefixPath}${encodeAssetDir}`;
1048
- }
1049
- return encodeAssetDir;
1050
- }
1051
- return url;
1052
- });
1053
- return content;
1054
- }
1055
- outputs.forEach((output) => {
1056
- output.content = replaceContentFilePath(output.content || '');
1057
- })
1058
- }
1059
- console.log('outputs', outputs)
1028
+ processAssetsInOutputs(outputs, frontend, config);
1060
1029
  return outputs;
1061
1030
  }
1062
1031
 
@@ -1067,11 +1036,11 @@ export async function genFrontendBundleFiles(app: App, frontends: Array<Frontend
1067
1036
  for (const frontend of frontends) {
1068
1037
  if(frontend.frameworkKind === 'react'){
1069
1038
  const files: {path: string, content: string}[] = await compileNASLToReactDist(app, frontend, config as any);
1070
- result.push(
1071
- ...files.map((x) => {
1072
- return { name: x.path, content: x.content };
1073
- })
1074
- );
1039
+ const outputs = files.map((x) => {
1040
+ return { name: x.path, content: x.content };
1041
+ });
1042
+ processAssetsInOutputs(outputs, frontend, config);
1043
+ result.push(...outputs);
1075
1044
  }else{
1076
1045
  const data = await genBundleFiles(app, frontend, config);
1077
1046
  result.push(...data);
@@ -1143,7 +1112,6 @@ export function getOneFiles(options: { view: View; action: string; cacheRouterDa
1143
1112
  }
1144
1113
  currentView = currentView.parentNode;
1145
1114
  }
1146
- console.log(currentRoute);
1147
1115
 
1148
1116
  function addOrUpdateRoute(routes: Route[], newRoute: Route) {
1149
1117
  const existingRoute = routes.find((route) => route.path === newRoute.path);
@@ -1181,7 +1149,6 @@ export function getOneFiles(options: { view: View; action: string; cacheRouterDa
1181
1149
  } else {
1182
1150
  addOrUpdateRoute(cacheRouters, currentRoute);
1183
1151
  }
1184
- console.log(cacheRouters, 111);
1185
1152
  const routerFiles = genRouteFiles(cacheRouters, null);
1186
1153
  const completePath = `${cacheRouterData.baseUrl}${frontend.basePath || ''}/`;
1187
1154
  const outputs = routerFiles;
@@ -1195,6 +1162,52 @@ export function getOneFiles(options: { view: View; action: string; cacheRouterDa
1195
1162
  item.ideVersion = cacheRouterData.ideVersion;
1196
1163
  }
1197
1164
  });
1198
- console.log('outputs: ', outputs);
1199
1165
  return outputs;
1200
1166
  }
1167
+
1168
+ function processAssetsInOutputs(
1169
+ outputs: { name: string; content: string }[],
1170
+ frontend: Frontend,
1171
+ config: Config
1172
+ ) {
1173
+ const assets = config.assets;
1174
+ // 导出源码才处理
1175
+ if (config.isExport && Array.isArray(assets) && assets.length) {
1176
+ function replaceContentFilePath(content: string) {
1177
+ const assetsMap = config.assetsMap;
1178
+ // 正则
1179
+ const regex = utils.transAssetsToRegx(assets, 'fileUrl');
1180
+ content = content.replace(regex, (url) => {
1181
+ const asset: Asset = utils.getAssetFromAssetsMap(assetsMap, url);
1182
+ if (asset) {
1183
+ const basePath = frontend?.basePath;
1184
+ const assetName = asset.name;
1185
+ const assetDir = basePath ? `${basePath}/assets/${assetName}` : `/assets/${assetName}`;
1186
+ let path = assetDir;
1187
+ const sysPrefixPath = frontend?.app?.sysPrefixPath;
1188
+ if (sysPrefixPath) {
1189
+ path = `${sysPrefixPath}${assetDir}`;
1190
+ }
1191
+ globalConfig.assets.push({
1192
+ path: assetDir,
1193
+ isDir: false,
1194
+ url,
1195
+ });
1196
+ const encodeAssetName = encodeURIComponent(assetName);
1197
+ let encodeAssetDir = basePath
1198
+ ? `${basePath}/assets/${encodeAssetName}`
1199
+ : `/assets/${encodeAssetName}`;
1200
+ if (sysPrefixPath) {
1201
+ encodeAssetDir = `${sysPrefixPath}${encodeAssetDir}`;
1202
+ }
1203
+ return encodeAssetDir;
1204
+ }
1205
+ return url;
1206
+ });
1207
+ return content;
1208
+ }
1209
+ outputs.forEach((output) => {
1210
+ output.content = replaceContentFilePath(output.content || '');
1211
+ });
1212
+ }
1213
+ }
@@ -1,13 +1,39 @@
1
- import * as crypto from 'crypto';
1
+ // cyrb53 (c) 2018 bryc (github.com/bryc). License: Public domain. Attribution appreciated.
2
+ // A fast and simple 64-bit (or 53-bit) string hash function with decent collision resistance.
3
+ // Largely inspired by MurmurHash2/3, but with a focus on speed/simplicity.
4
+ // See https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript/52171480#52171480
5
+ // https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js
6
+ const cyrb64 = (str : string, seed = 0) => {
7
+ let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
8
+ for(let i = 0, ch; i < str.length; i++) {
9
+ ch = str.charCodeAt(i);
10
+ h1 = Math.imul(h1 ^ ch, 2654435761);
11
+ h2 = Math.imul(h2 ^ ch, 1597334677);
12
+ }
13
+ h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);
14
+ h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);
15
+ h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);
16
+ h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);
17
+ // For a single 53-bit numeric return value we could return
18
+ // 4294967296 * (2097151 & h2) + (h1 >>> 0);
19
+ // but we instead return the full 64-bit value:
20
+ return [h2>>>0, h1>>>0];
21
+ };
22
+
23
+ // An improved, *insecure* 64-bit hash that's short, fast, and has no dependencies.
24
+ // Output is always 14 characters.
25
+ const cyrb64Hash = (str : string, seed = 0) => {
26
+ const [h2, h1] = cyrb64(str, seed);
27
+ return h2.toString(36).padStart(7, '0') + h1.toString(36).padStart(7, '0');
28
+ }
29
+
2
30
 
3
31
  /**
4
32
  *
5
33
  * @param 文件内容 content
6
- * @returns MD5 hash8位
34
+ * @returns cyrb64 hash,取前 8
7
35
  */
8
- export function genHash(content: string) {
9
- const hash = crypto.createHash('md5').update(content, 'utf8').digest('hex');
10
- return hash.slice(0, 8);
11
- }
36
+
37
+ export const genHash = (str : string) => cyrb64Hash(str, 0).slice(0, 8);
12
38
 
13
39
  export default genHash;
@@ -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
+ }