@next-core/easyops-runtime 0.2.0 → 0.3.1

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 (73) hide show
  1. package/dist/cjs/auth.js +2 -3
  2. package/dist/cjs/auth.js.map +1 -1
  3. package/dist/cjs/checkInstalledApps.js.map +1 -1
  4. package/dist/cjs/checkPermissions.js +101 -0
  5. package/dist/cjs/checkPermissions.js.map +1 -0
  6. package/dist/cjs/flowApi/CollectContracts.js.map +1 -1
  7. package/dist/cjs/flowApi/FlowApi.js.map +1 -1
  8. package/dist/cjs/flowApi/FlowApiProvider.js.map +1 -1
  9. package/dist/cjs/index.js +12 -8
  10. package/dist/cjs/index.js.map +1 -1
  11. package/dist/cjs/menu/computeMenuData.js +36 -0
  12. package/dist/cjs/menu/computeMenuData.js.map +1 -0
  13. package/dist/cjs/menu/constants.js +13 -0
  14. package/dist/cjs/menu/constants.js.map +1 -0
  15. package/dist/cjs/menu/fetchMenuById.js +102 -0
  16. package/dist/cjs/menu/fetchMenuById.js.map +1 -0
  17. package/dist/cjs/menu/fetchMenuTitle.js +37 -0
  18. package/dist/cjs/menu/fetchMenuTitle.js.map +1 -0
  19. package/dist/cjs/menu/getMenusOfStandaloneApp.js +26 -0
  20. package/dist/cjs/menu/getMenusOfStandaloneApp.js.map +1 -0
  21. package/dist/cjs/menu/index.js +19 -0
  22. package/dist/cjs/menu/index.js.map +1 -0
  23. package/dist/cjs/menu/interfaces.js +4 -0
  24. package/dist/cjs/menu/interfaces.js.map +1 -0
  25. package/dist/cjs/menu/loadDynamicMenuItems.js +27 -0
  26. package/dist/cjs/menu/loadDynamicMenuItems.js.map +1 -0
  27. package/dist/cjs/menu/mergeMenu.js +73 -0
  28. package/dist/cjs/menu/mergeMenu.js.map +1 -0
  29. package/dist/cjs/menu/reorderMenuItems.js +20 -0
  30. package/dist/cjs/menu/reorderMenuItems.js.map +1 -0
  31. package/dist/esm/auth.js +2 -3
  32. package/dist/esm/auth.js.map +1 -1
  33. package/dist/esm/checkInstalledApps.js.map +1 -1
  34. package/dist/esm/checkPermissions.js +106 -0
  35. package/dist/esm/checkPermissions.js.map +1 -0
  36. package/dist/esm/flowApi/CollectContracts.js.map +1 -1
  37. package/dist/esm/flowApi/FlowApi.js.map +1 -1
  38. package/dist/esm/flowApi/FlowApiProvider.js.map +1 -1
  39. package/dist/esm/index.js +9 -1
  40. package/dist/esm/index.js.map +1 -1
  41. package/dist/esm/menu/computeMenuData.js +37 -0
  42. package/dist/esm/menu/computeMenuData.js.map +1 -0
  43. package/dist/esm/menu/constants.js +4 -0
  44. package/dist/esm/menu/constants.js.map +1 -0
  45. package/dist/esm/menu/fetchMenuById.js +104 -0
  46. package/dist/esm/menu/fetchMenuById.js.map +1 -0
  47. package/dist/esm/menu/fetchMenuTitle.js +38 -0
  48. package/dist/esm/menu/fetchMenuTitle.js.map +1 -0
  49. package/dist/esm/menu/getMenusOfStandaloneApp.js +18 -0
  50. package/dist/esm/menu/getMenusOfStandaloneApp.js.map +1 -0
  51. package/dist/esm/menu/index.js +2 -0
  52. package/dist/esm/menu/index.js.map +1 -0
  53. package/dist/esm/menu/interfaces.js +8 -0
  54. package/dist/esm/menu/interfaces.js.map +1 -0
  55. package/dist/esm/menu/loadDynamicMenuItems.js +27 -0
  56. package/dist/esm/menu/loadDynamicMenuItems.js.map +1 -0
  57. package/dist/esm/menu/mergeMenu.js +77 -0
  58. package/dist/esm/menu/mergeMenu.js.map +1 -0
  59. package/dist/esm/menu/reorderMenuItems.js +14 -0
  60. package/dist/esm/menu/reorderMenuItems.js.map +1 -0
  61. package/dist/types/checkPermissions.d.ts +16 -0
  62. package/dist/types/index.d.ts +7 -1
  63. package/dist/types/menu/computeMenuData.d.ts +6 -0
  64. package/dist/types/menu/constants.d.ts +3 -0
  65. package/dist/types/menu/fetchMenuById.d.ts +3 -0
  66. package/dist/types/menu/fetchMenuTitle.d.ts +2 -0
  67. package/dist/types/menu/getMenusOfStandaloneApp.d.ts +2 -0
  68. package/dist/types/menu/index.d.ts +1 -0
  69. package/dist/types/menu/interfaces.d.ts +77 -0
  70. package/dist/types/menu/loadDynamicMenuItems.d.ts +2 -0
  71. package/dist/types/menu/mergeMenu.d.ts +2 -0
  72. package/dist/types/menu/reorderMenuItems.d.ts +2 -0
  73. package/package.json +8 -7
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","names":["symbolAppId","Symbol","symbolMenuI18nNamespace","symbolOverrideApp"],"sources":["../../../src/menu/constants.ts"],"sourcesContent":["export const symbolAppId = Symbol(\"appId\");\nexport const symbolMenuI18nNamespace = Symbol(\"menuI18nNamespace\");\nexport const symbolOverrideApp = Symbol(\"overrideApp\");\n"],"mappings":"AAAA,OAAO,IAAMA,WAAW,GAAGC,MAAM,CAAC,OAAO,CAAC;AAC1C,OAAO,IAAMC,uBAAuB,GAAGD,MAAM,CAAC,mBAAmB,CAAC;AAClE,OAAO,IAAME,iBAAiB,GAAGF,MAAM,CAAC,aAAa,CAAC"}
@@ -0,0 +1,104 @@
1
+ import _objectSpread from "@babel/runtime/helpers/objectSpread2";
2
+ import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
4
+ var _excluded = ["items", "app"];
5
+ import { InstanceApi_postSearch } from "@next-api-sdk/cmdb-sdk";
6
+ import { pick } from "lodash";
7
+ import { checkIfOfComputed } from "@next-core/runtime";
8
+ import { mergeMenu } from "./mergeMenu.js";
9
+ import { reorderMenuItems } from "./reorderMenuItems.js";
10
+ import { computeMenuItems, computeMenuData } from "./computeMenuData.js";
11
+ import { fetchMenuTitle } from "./fetchMenuTitle.js";
12
+ import { getMenusOfStandaloneApp } from "./getMenusOfStandaloneApp.js";
13
+ import { preCheckPermissionsForAny } from "../checkPermissions.js";
14
+ var menuPromises = new Map();
15
+ var menuCache = new Map();
16
+ export function getMenuById(menuId) {
17
+ return menuCache.get(menuId);
18
+ }
19
+ export function fetchMenuById(menuId, runtimeContext, helpers) {
20
+ var promise = menuPromises.get(menuId);
21
+ if (!promise) {
22
+ promise = _fetchMenuById(menuId, runtimeContext, helpers);
23
+ }
24
+ return promise;
25
+ }
26
+ function _fetchMenuById(_x, _x2, _x3) {
27
+ return _fetchMenuById2.apply(this, arguments);
28
+ }
29
+ function _fetchMenuById2() {
30
+ _fetchMenuById2 = _asyncToGenerator(function* (menuId, runtimeContext, helpers) {
31
+ var menuList = window.STANDALONE_MICRO_APPS ? getMenusOfStandaloneApp(menuId, runtimeContext.app.id, helpers) : (yield InstanceApi_postSearch("EASYOPS_STORYBOARD_MENU", {
32
+ page: 1,
33
+ page_size: 200,
34
+ fields: {
35
+ menuId: true,
36
+ title: true,
37
+ icon: true,
38
+ link: true,
39
+ titleDataSource: true,
40
+ defaultCollapsed: true,
41
+ defaultCollapsedBreakpoint: true,
42
+ type: true,
43
+ injectMenuGroupId: true,
44
+ dynamicItems: true,
45
+ itemsResolve: true,
46
+ items: true,
47
+ i18n: true,
48
+ "items.children": true,
49
+ "app.appId": true
50
+ },
51
+ query: {
52
+ menuId: {
53
+ $eq: menuId
54
+ },
55
+ app: {
56
+ $size: {
57
+ $gt: 0
58
+ }
59
+ }
60
+ }
61
+ })).list;
62
+ var menuData = yield mergeMenu(menuList, runtimeContext, helpers);
63
+ if (!menuData) {
64
+ throw new Error("Menu not found: ".concat(menuId));
65
+ }
66
+ reorderMenuItems(menuData);
67
+ var {
68
+ items,
69
+ app
70
+ } = menuData,
71
+ restMenuData = _objectWithoutProperties(menuData, _excluded);
72
+ var newRuntimeContext = _objectSpread(_objectSpread({}, runtimeContext), {}, {
73
+ pendingPermissionsPreCheck: [...runtimeContext.pendingPermissionsPreCheck, preCheckPermissionsForAny([items, restMenuData])]
74
+ });
75
+ delete newRuntimeContext.tplStateStoreId;
76
+ delete newRuntimeContext.forEachItem;
77
+ var rootAppId = app[0].appId;
78
+ var [computedMenuData, computedMenuItems] = yield Promise.all([computeMenuData(restMenuData, rootAppId, newRuntimeContext, helpers), computeMenuItems(items, newRuntimeContext, helpers)]);
79
+ var finalMenuData = _objectSpread(_objectSpread({
80
+ title: yield fetchMenuTitle(computedMenuData)
81
+ }, pick(computedMenuData, ["icon", "link", "defaultCollapsed", "defaultCollapsedBreakpoint"])), {}, {
82
+ menuItems: computedMenuItems.filter(checkIfOfComputed).map(item => {
83
+ var _item$children;
84
+ var children = (_item$children = item.children) === null || _item$children === void 0 ? void 0 : _item$children.filter(checkIfOfComputed);
85
+ return item.type === "group" ? {
86
+ type: "group",
87
+ title: item.text,
88
+ items: children
89
+ } : children !== null && children !== void 0 && children.length ? {
90
+ type: "subMenu",
91
+ title: item.text,
92
+ icon: item.icon,
93
+ items: children,
94
+ defaultExpanded: item.defaultExpanded
95
+ } : item;
96
+ })
97
+ });
98
+
99
+ // Todo(steve): reconsider the menu cache strategy
100
+ menuCache.set(menuId, finalMenuData);
101
+ });
102
+ return _fetchMenuById2.apply(this, arguments);
103
+ }
104
+ //# sourceMappingURL=fetchMenuById.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetchMenuById.js","names":["InstanceApi_postSearch","pick","checkIfOfComputed","mergeMenu","reorderMenuItems","computeMenuItems","computeMenuData","fetchMenuTitle","getMenusOfStandaloneApp","preCheckPermissionsForAny","menuPromises","Map","menuCache","getMenuById","menuId","get","fetchMenuById","runtimeContext","helpers","promise","_fetchMenuById","_x","_x2","_x3","_fetchMenuById2","apply","arguments","_asyncToGenerator","menuList","window","STANDALONE_MICRO_APPS","app","id","page","page_size","fields","title","icon","link","titleDataSource","defaultCollapsed","defaultCollapsedBreakpoint","type","injectMenuGroupId","dynamicItems","itemsResolve","items","i18n","query","$eq","$size","$gt","list","menuData","Error","concat","restMenuData","_objectWithoutProperties","_excluded","newRuntimeContext","_objectSpread","pendingPermissionsPreCheck","tplStateStoreId","forEachItem","rootAppId","appId","computedMenuData","computedMenuItems","Promise","all","finalMenuData","menuItems","filter","map","item","_item$children","children","text","length","defaultExpanded","set"],"sources":["../../../src/menu/fetchMenuById.ts"],"sourcesContent":["import { InstanceApi_postSearch } from \"@next-api-sdk/cmdb-sdk\";\nimport { pick } from \"lodash\";\nimport { checkIfOfComputed } from \"@next-core/runtime\";\nimport { mergeMenu } from \"./mergeMenu.js\";\nimport { reorderMenuItems } from \"./reorderMenuItems.js\";\nimport type {\n MenuRawData,\n RuntimeContext,\n RuntimeHelpers,\n} from \"./interfaces.js\";\nimport { computeMenuItems, computeMenuData } from \"./computeMenuData.js\";\nimport { fetchMenuTitle } from \"./fetchMenuTitle.js\";\nimport { getMenusOfStandaloneApp } from \"./getMenusOfStandaloneApp.js\";\nimport { preCheckPermissionsForAny } from \"../checkPermissions.js\";\n\nconst menuPromises = new Map<string, Promise<void>>();\n\nconst menuCache = new Map<string, unknown>();\n\nexport function getMenuById(menuId: string) {\n return menuCache.get(menuId);\n}\n\nexport function fetchMenuById(\n menuId: string,\n runtimeContext: RuntimeContext,\n helpers: RuntimeHelpers\n) {\n let promise = menuPromises.get(menuId);\n if (!promise) {\n promise = _fetchMenuById(menuId, runtimeContext, helpers);\n }\n return promise;\n}\n\nasync function _fetchMenuById(\n menuId: string,\n runtimeContext: RuntimeContext,\n helpers: RuntimeHelpers\n) {\n const menuList = window.STANDALONE_MICRO_APPS\n ? getMenusOfStandaloneApp(menuId, runtimeContext.app.id, helpers)\n : ((\n await InstanceApi_postSearch(\"EASYOPS_STORYBOARD_MENU\", {\n page: 1,\n page_size: 200,\n fields: {\n menuId: true,\n title: true,\n icon: true,\n link: true,\n titleDataSource: true,\n defaultCollapsed: true,\n defaultCollapsedBreakpoint: true,\n type: true,\n injectMenuGroupId: true,\n dynamicItems: true,\n itemsResolve: true,\n items: true,\n i18n: true,\n \"items.children\": true,\n \"app.appId\": true,\n },\n query: {\n menuId: {\n $eq: menuId,\n },\n app: {\n $size: {\n $gt: 0,\n },\n },\n },\n })\n ).list as MenuRawData[]);\n\n const menuData = await mergeMenu(menuList, runtimeContext, helpers);\n if (!menuData) {\n throw new Error(`Menu not found: ${menuId}`);\n }\n\n reorderMenuItems(menuData);\n\n const { items, app, ...restMenuData } = menuData;\n const newRuntimeContext: RuntimeContext = {\n ...runtimeContext,\n pendingPermissionsPreCheck: [\n ...runtimeContext.pendingPermissionsPreCheck,\n preCheckPermissionsForAny([items, restMenuData]),\n ],\n };\n delete newRuntimeContext.tplStateStoreId;\n delete newRuntimeContext.forEachItem;\n const rootAppId = app[0].appId;\n\n const [computedMenuData, computedMenuItems] = await Promise.all([\n computeMenuData(restMenuData, rootAppId, newRuntimeContext, helpers),\n computeMenuItems(items, newRuntimeContext, helpers),\n ]);\n\n const finalMenuData = {\n title: await fetchMenuTitle(computedMenuData),\n ...pick(computedMenuData, [\n \"icon\",\n \"link\",\n \"defaultCollapsed\",\n \"defaultCollapsedBreakpoint\",\n ]),\n menuItems: computedMenuItems.filter(checkIfOfComputed).map((item) => {\n const children = item.children?.filter(checkIfOfComputed);\n return item.type === \"group\"\n ? {\n type: \"group\",\n title: item.text,\n items: children,\n }\n : children?.length\n ? {\n type: \"subMenu\",\n title: item.text,\n icon: item.icon,\n items: children,\n defaultExpanded: item.defaultExpanded,\n }\n : item;\n }),\n };\n\n // Todo(steve): reconsider the menu cache strategy\n menuCache.set(menuId, finalMenuData);\n}\n"],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ import { isEmpty } from "lodash";
3
+ import { InstanceApi_getDetail } from "@next-api-sdk/cmdb-sdk";
4
+ var menuTitleCache = new Map();
5
+ export function fetchMenuTitle(_x) {
6
+ return _fetchMenuTitle.apply(this, arguments);
7
+ }
8
+ function _fetchMenuTitle() {
9
+ _fetchMenuTitle = _asyncToGenerator(function* (menuData) {
10
+ if (menuData.title || isEmpty(menuData.titleDataSource)) {
11
+ return menuData.title;
12
+ }
13
+ var cacheKey = JSON.stringify(menuData.titleDataSource);
14
+ if (menuTitleCache.has(cacheKey)) {
15
+ return menuTitleCache.get(cacheKey);
16
+ }
17
+ var {
18
+ objectId,
19
+ instanceId,
20
+ attributeId
21
+ } = menuData.titleDataSource;
22
+ var attr = attributeId !== null && attributeId !== void 0 ? attributeId : "name";
23
+ var instanceData = yield InstanceApi_getDetail(objectId, instanceId, {
24
+ fields: attr
25
+ });
26
+ var title;
27
+ if (attributeId === "#showKey" && Array.isArray(instanceData[attr])) {
28
+ var [primary, ...rest] = instanceData[attr];
29
+ title = rest.length > 0 ? "".concat(primary, "(").concat(rest.join(","), ")") : String(primary);
30
+ } else {
31
+ title = String(instanceData[attr]);
32
+ }
33
+ menuTitleCache.set(cacheKey, title);
34
+ return title;
35
+ });
36
+ return _fetchMenuTitle.apply(this, arguments);
37
+ }
38
+ //# sourceMappingURL=fetchMenuTitle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetchMenuTitle.js","names":["isEmpty","InstanceApi_getDetail","menuTitleCache","Map","fetchMenuTitle","_x","_fetchMenuTitle","apply","arguments","_asyncToGenerator","menuData","title","titleDataSource","cacheKey","JSON","stringify","has","get","objectId","instanceId","attributeId","attr","instanceData","fields","Array","isArray","primary","rest","length","concat","join","String","set"],"sources":["../../../src/menu/fetchMenuTitle.ts"],"sourcesContent":["import { isEmpty } from \"lodash\";\nimport { InstanceApi_getDetail } from \"@next-api-sdk/cmdb-sdk\";\nimport type { MenuRawData } from \"./interfaces.js\";\n\nconst menuTitleCache = new Map<string, string>();\n\nexport async function fetchMenuTitle(\n menuData: Pick<MenuRawData, \"title\" | \"titleDataSource\">\n) {\n if (menuData.title || isEmpty(menuData.titleDataSource)) {\n return menuData.title;\n }\n const cacheKey = JSON.stringify(menuData.titleDataSource);\n if (menuTitleCache.has(cacheKey)) {\n return menuTitleCache.get(cacheKey);\n }\n const { objectId, instanceId, attributeId } = menuData.titleDataSource;\n const attr = attributeId ?? \"name\";\n const instanceData = await InstanceApi_getDetail(objectId, instanceId, {\n fields: attr,\n });\n let title: string;\n if (attributeId === \"#showKey\" && Array.isArray(instanceData[attr])) {\n const [primary, ...rest] = instanceData[attr];\n title = rest.length > 0 ? `${primary}(${rest.join(\",\")})` : String(primary);\n } else {\n title = String(instanceData[attr]);\n }\n menuTitleCache.set(cacheKey, title);\n return title;\n}\n"],"mappings":";AAAA,SAASA,OAAO,QAAQ,QAAQ;AAChC,SAASC,qBAAqB,QAAQ,wBAAwB;AAG9D,IAAMC,cAAc,GAAG,IAAIC,GAAG,CAAiB,CAAC;AAEhD,gBAAsBC,cAAcA,CAAAC,EAAA;EAAA,OAAAC,eAAA,CAAAC,KAAA,OAAAC,SAAA;AAAA;AAwBnC,SAAAF,gBAAA;EAAAA,eAAA,GAAAG,iBAAA,CAxBM,WACLC,QAAwD,EACxD;IACA,IAAIA,QAAQ,CAACC,KAAK,IAAIX,OAAO,CAACU,QAAQ,CAACE,eAAe,CAAC,EAAE;MACvD,OAAOF,QAAQ,CAACC,KAAK;IACvB;IACA,IAAME,QAAQ,GAAGC,IAAI,CAACC,SAAS,CAACL,QAAQ,CAACE,eAAe,CAAC;IACzD,IAAIV,cAAc,CAACc,GAAG,CAACH,QAAQ,CAAC,EAAE;MAChC,OAAOX,cAAc,CAACe,GAAG,CAACJ,QAAQ,CAAC;IACrC;IACA,IAAM;MAAEK,QAAQ;MAAEC,UAAU;MAAEC;IAAY,CAAC,GAAGV,QAAQ,CAACE,eAAe;IACtE,IAAMS,IAAI,GAAGD,WAAW,aAAXA,WAAW,cAAXA,WAAW,GAAI,MAAM;IAClC,IAAME,YAAY,SAASrB,qBAAqB,CAACiB,QAAQ,EAAEC,UAAU,EAAE;MACrEI,MAAM,EAAEF;IACV,CAAC,CAAC;IACF,IAAIV,KAAa;IACjB,IAAIS,WAAW,KAAK,UAAU,IAAII,KAAK,CAACC,OAAO,CAACH,YAAY,CAACD,IAAI,CAAC,CAAC,EAAE;MACnE,IAAM,CAACK,OAAO,EAAE,GAAGC,IAAI,CAAC,GAAGL,YAAY,CAACD,IAAI,CAAC;MAC7CV,KAAK,GAAGgB,IAAI,CAACC,MAAM,GAAG,CAAC,MAAAC,MAAA,CAAMH,OAAO,OAAAG,MAAA,CAAIF,IAAI,CAACG,IAAI,CAAC,GAAG,CAAC,SAAMC,MAAM,CAACL,OAAO,CAAC;IAC7E,CAAC,MAAM;MACLf,KAAK,GAAGoB,MAAM,CAACT,YAAY,CAACD,IAAI,CAAC,CAAC;IACpC;IACAnB,cAAc,CAAC8B,GAAG,CAACnB,QAAQ,EAAEF,KAAK,CAAC;IACnC,OAAOA,KAAK;EACd,CAAC;EAAA,OAAAL,eAAA,CAAAC,KAAA,OAAAC,SAAA;AAAA"}
@@ -0,0 +1,18 @@
1
+ import _objectSpread from "@babel/runtime/helpers/objectSpread2";
2
+ export function getMenusOfStandaloneApp(menuId, appId, helpers) {
3
+ var _ref, _storyboard$meta$inje, _storyboard$meta, _storyboard$meta2;
4
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
5
+ var storyboard = helpers.getStoryboardByAppId(appId);
6
+ var menus = (_ref = (_storyboard$meta$inje = (_storyboard$meta = storyboard.meta) === null || _storyboard$meta === void 0 ? void 0 : _storyboard$meta.injectMenus) !== null && _storyboard$meta$inje !== void 0 ? _storyboard$meta$inje : (_storyboard$meta2 = storyboard.meta) === null || _storyboard$meta2 === void 0 ? void 0 : _storyboard$meta2.menus) !== null && _ref !== void 0 ? _ref : [];
7
+ return menus.filter(menu => menu.menuId === menuId).map(menu => {
8
+ var _menu$app, _menu$app$;
9
+ return _objectSpread(_objectSpread({}, menu), (_menu$app = menu.app) !== null && _menu$app !== void 0 && (_menu$app$ = _menu$app[0]) !== null && _menu$app$ !== void 0 && _menu$app$.appId ? {} : {
10
+ app: [{
11
+ appId
12
+ }]
13
+ });
14
+ });
15
+
16
+ // Todo: maybe: fetch menus from STANDALONE_MENU@EASYOPS
17
+ }
18
+ //# sourceMappingURL=getMenusOfStandaloneApp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getMenusOfStandaloneApp.js","names":["getMenusOfStandaloneApp","menuId","appId","helpers","_ref","_storyboard$meta$inje","_storyboard$meta","_storyboard$meta2","storyboard","getStoryboardByAppId","menus","meta","injectMenus","filter","menu","map","_menu$app","_menu$app$","_objectSpread","app"],"sources":["../../../src/menu/getMenusOfStandaloneApp.ts"],"sourcesContent":["import { MenuRawData, RuntimeHelpers } from \"./interfaces.js\";\n\nexport function getMenusOfStandaloneApp(\n menuId: string,\n appId: string,\n helpers: RuntimeHelpers\n): MenuRawData[] {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const storyboard = helpers.getStoryboardByAppId(appId)!;\n const menus = (storyboard.meta?.injectMenus ??\n storyboard.meta?.menus ??\n []) as MenuRawData[];\n\n return menus\n .filter((menu) => menu.menuId === menuId)\n .map((menu) => ({\n ...menu,\n ...(menu.app?.[0]?.appId ? {} : { app: [{ appId }] }),\n }));\n\n // Todo: maybe: fetch menus from STANDALONE_MENU@EASYOPS\n}\n"],"mappings":";AAEA,OAAO,SAASA,uBAAuBA,CACrCC,MAAc,EACdC,KAAa,EACbC,OAAuB,EACR;EAAA,IAAAC,IAAA,EAAAC,qBAAA,EAAAC,gBAAA,EAAAC,iBAAA;EACf;EACA,IAAMC,UAAU,GAAGL,OAAO,CAACM,oBAAoB,CAACP,KAAK,CAAE;EACvD,IAAMQ,KAAK,IAAAN,IAAA,IAAAC,qBAAA,IAAAC,gBAAA,GAAIE,UAAU,CAACG,IAAI,cAAAL,gBAAA,uBAAfA,gBAAA,CAAiBM,WAAW,cAAAP,qBAAA,cAAAA,qBAAA,IAAAE,iBAAA,GACzCC,UAAU,CAACG,IAAI,cAAAJ,iBAAA,uBAAfA,iBAAA,CAAiBG,KAAK,cAAAN,IAAA,cAAAA,IAAA,GACtB,EAAoB;EAEtB,OAAOM,KAAK,CACTG,MAAM,CAAEC,IAAI,IAAKA,IAAI,CAACb,MAAM,KAAKA,MAAM,CAAC,CACxCc,GAAG,CAAED,IAAI;IAAA,IAAAE,SAAA,EAAAC,UAAA;IAAA,OAAAC,aAAA,CAAAA,aAAA,KACLJ,IAAI,GACH,CAAAE,SAAA,GAAAF,IAAI,CAACK,GAAG,cAAAH,SAAA,gBAAAC,UAAA,GAARD,SAAA,CAAW,CAAC,CAAC,cAAAC,UAAA,eAAbA,UAAA,CAAef,KAAK,GAAG,CAAC,CAAC,GAAG;MAAEiB,GAAG,EAAE,CAAC;QAAEjB;MAAM,CAAC;IAAE,CAAC;EAAA,CACpD,CAAC;;EAEL;AACF"}
@@ -0,0 +1,2 @@
1
+ export { getMenuById, fetchMenuById } from "./fetchMenuById.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["getMenuById","fetchMenuById"],"sources":["../../../src/menu/index.ts"],"sourcesContent":["export { getMenuById, fetchMenuById } from \"./fetchMenuById.js\";\n"],"mappings":"AAAA,SAASA,WAAW,EAAEC,aAAa,QAAQ,oBAAoB"}
@@ -0,0 +1,8 @@
1
+ import { symbolAppId, symbolMenuI18nNamespace, symbolOverrideApp } from "./constants.js";
2
+
3
+ /** 原始菜单数据。 */
4
+
5
+ /** 原始菜单项数据。 */
6
+
7
+ /** 侧边栏基本菜单项的配置。 */
8
+ //# sourceMappingURL=interfaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.js","names":["symbolAppId","symbolMenuI18nNamespace","symbolOverrideApp"],"sources":["../../../src/menu/interfaces.ts"],"sourcesContent":["import type { MetaI18n, MicroApp, ResolveConf } from \"@next-core/types\";\nimport type {\n RuntimeHooksMenuHelpers,\n __secret_internals,\n} from \"@next-core/runtime\";\nimport {\n symbolAppId,\n symbolMenuI18nNamespace,\n symbolOverrideApp,\n} from \"./constants.js\";\n\nexport type RuntimeContext = __secret_internals.RuntimeContext;\n\nexport type RuntimeHelpers = RuntimeHooksMenuHelpers;\n\n/** 原始菜单数据。 */\nexport interface MenuRawData {\n menuId: string;\n title: string;\n app: [\n {\n appId: string;\n }\n ];\n icon?: unknown;\n link?: string;\n titleDataSource?: TitleDataSource;\n items?: MenuItemRawData[];\n type?: \"main\" | \"inject\";\n injectMenuGroupId?: string;\n defaultCollapsed?: boolean;\n defaultCollapsedBreakpoint?: number;\n dynamicItems?: boolean;\n itemsResolve?: ResolveConf;\n i18n?: MetaI18n;\n overrideApp?: MicroApp;\n}\n\n/** 原始菜单项数据。 */\nexport type MenuItemRawData = Omit<SidebarMenuSimpleItem, \"type\"> & {\n children?: MenuItemRawData[];\n type?: \"default\" | \"group\";\n sort?: number;\n if?: string | boolean;\n defaultExpanded?: boolean;\n groupId?: string;\n};\n\ninterface TitleDataSource {\n objectId: string;\n instanceId: string;\n attributeId?: string;\n}\n\n/** 侧边栏基本菜单项的配置。 */\nexport interface SidebarMenuSimpleItem {\n /** 菜单项文本。 */\n text: string;\n\n /** 菜单项对应的系统内地址。 */\n // to?: LocationDescriptor;\n to?: unknown;\n\n /** 菜单项对应的外部链接地址。 */\n href?: string;\n\n /** 菜单项的图标。 */\n // icon?: MenuIcon;\n icon?: unknown;\n\n /** 菜单项链接打开的目标。 */\n target?: string;\n\n type?: \"default\";\n\n /** 高亮菜单项时是否使用精确匹配来对比当前地址和菜单项地址。 */\n exact?: boolean;\n\n /** 设置额外包含的匹配高亮菜单项的地址列表。 */\n activeIncludes?: string[];\n\n /** 设置需要被排除的匹配高亮菜单项的地址列表。 */\n activeExcludes?: string[];\n\n /** 设置匹配高亮菜单项时是否还对 search 参数进行比较。 */\n activeMatchSearch?: boolean;\n\n /** @internal */\n key?: string;\n}\n\nexport interface RuntimeMenuItemRawData extends MenuItemRawData {\n children?: RuntimeMenuItemRawData[];\n [symbolAppId]: string;\n [symbolMenuI18nNamespace]?: string;\n [symbolOverrideApp]?: MicroApp;\n}\n\nexport interface RuntimeMenuRawData extends MenuRawData {\n items: RuntimeMenuItemRawData[];\n // [symbolShouldCache]?: boolean;\n [symbolMenuI18nNamespace]?: string;\n [symbolOverrideApp]?: MicroApp;\n}\n"],"mappings":"AAKA,SACEA,WAAW,EACXC,uBAAuB,EACvBC,iBAAiB,QACZ,gBAAgB;;AAMvB;;AAuBA;;AAgBA"}
@@ -0,0 +1,27 @@
1
+ import _objectSpread from "@babel/runtime/helpers/objectSpread2";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+ export function loadDynamicMenuItems(_x, _x2, _x3, _x4) {
4
+ return _loadDynamicMenuItems.apply(this, arguments);
5
+ }
6
+ function _loadDynamicMenuItems() {
7
+ _loadDynamicMenuItems = _asyncToGenerator(function* (menu, runtimeContext, menuWithI18n, helpers) {
8
+ if (menu.dynamicItems && menu.itemsResolve) {
9
+ var overrideAppId = menu.app[0].appId;
10
+ var newRuntimeContext = runtimeContext;
11
+ if (overrideAppId !== runtimeContext.app.id) {
12
+ var _helpers$getStoryboar;
13
+ var overrideApp = window.STANDALONE_MICRO_APPS ? menu.overrideApp : (_helpers$getStoryboar = helpers.getStoryboardByAppId(overrideAppId)) === null || _helpers$getStoryboar === void 0 ? void 0 : _helpers$getStoryboar.app;
14
+ newRuntimeContext = _objectSpread(_objectSpread({}, runtimeContext), {}, {
15
+ overrideApp,
16
+ appendI18nNamespace: menuWithI18n.get(menu)
17
+ });
18
+ }
19
+ var resolved = yield helpers.resolveData(_objectSpread({
20
+ transform: "items"
21
+ }, menu.itemsResolve), newRuntimeContext);
22
+ menu.items = resolved.items;
23
+ }
24
+ });
25
+ return _loadDynamicMenuItems.apply(this, arguments);
26
+ }
27
+ //# sourceMappingURL=loadDynamicMenuItems.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadDynamicMenuItems.js","names":["loadDynamicMenuItems","_x","_x2","_x3","_x4","_loadDynamicMenuItems","apply","arguments","_asyncToGenerator","menu","runtimeContext","menuWithI18n","helpers","dynamicItems","itemsResolve","overrideAppId","app","appId","newRuntimeContext","id","_helpers$getStoryboar","overrideApp","window","STANDALONE_MICRO_APPS","getStoryboardByAppId","_objectSpread","appendI18nNamespace","get","resolved","resolveData","transform","items"],"sources":["../../../src/menu/loadDynamicMenuItems.ts"],"sourcesContent":["import type {\n RuntimeContext,\n MenuItemRawData,\n MenuRawData,\n RuntimeHelpers,\n} from \"./interfaces.js\";\n\nexport async function loadDynamicMenuItems(\n menu: MenuRawData,\n runtimeContext: RuntimeContext,\n menuWithI18n: WeakMap<MenuRawData, string>,\n helpers: RuntimeHelpers\n): Promise<void> {\n if (menu.dynamicItems && menu.itemsResolve) {\n const overrideAppId = menu.app[0].appId;\n let newRuntimeContext = runtimeContext;\n if (overrideAppId !== runtimeContext.app.id) {\n const overrideApp = window.STANDALONE_MICRO_APPS\n ? menu.overrideApp\n : helpers.getStoryboardByAppId(overrideAppId)?.app;\n newRuntimeContext = {\n ...runtimeContext,\n overrideApp,\n appendI18nNamespace: menuWithI18n.get(menu),\n };\n }\n const resolved = (await helpers.resolveData(\n {\n transform: \"items\",\n ...menu.itemsResolve,\n },\n newRuntimeContext\n )) as { items: MenuItemRawData[] };\n menu.items = resolved.items;\n }\n}\n"],"mappings":";;AAOA,gBAAsBA,oBAAoBA,CAAAC,EAAA,EAAAC,GAAA,EAAAC,GAAA,EAAAC,GAAA;EAAA,OAAAC,qBAAA,CAAAC,KAAA,OAAAC,SAAA;AAAA;AA4BzC,SAAAF,sBAAA;EAAAA,qBAAA,GAAAG,iBAAA,CA5BM,WACLC,IAAiB,EACjBC,cAA8B,EAC9BC,YAA0C,EAC1CC,OAAuB,EACR;IACf,IAAIH,IAAI,CAACI,YAAY,IAAIJ,IAAI,CAACK,YAAY,EAAE;MAC1C,IAAMC,aAAa,GAAGN,IAAI,CAACO,GAAG,CAAC,CAAC,CAAC,CAACC,KAAK;MACvC,IAAIC,iBAAiB,GAAGR,cAAc;MACtC,IAAIK,aAAa,KAAKL,cAAc,CAACM,GAAG,CAACG,EAAE,EAAE;QAAA,IAAAC,qBAAA;QAC3C,IAAMC,WAAW,GAAGC,MAAM,CAACC,qBAAqB,GAC5Cd,IAAI,CAACY,WAAW,IAAAD,qBAAA,GAChBR,OAAO,CAACY,oBAAoB,CAACT,aAAa,CAAC,cAAAK,qBAAA,uBAA3CA,qBAAA,CAA6CJ,GAAG;QACpDE,iBAAiB,GAAAO,aAAA,CAAAA,aAAA,KACZf,cAAc;UACjBW,WAAW;UACXK,mBAAmB,EAAEf,YAAY,CAACgB,GAAG,CAAClB,IAAI;QAAC,EAC5C;MACH;MACA,IAAMmB,QAAQ,SAAUhB,OAAO,CAACiB,WAAW,CAAAJ,aAAA;QAEvCK,SAAS,EAAE;MAAO,GACfrB,IAAI,CAACK,YAAY,GAEtBI,iBACF,CAAkC;MAClCT,IAAI,CAACsB,KAAK,GAAGH,QAAQ,CAACG,KAAK;IAC7B;EACF,CAAC;EAAA,OAAA1B,qBAAA,CAAAC,KAAA,OAAAC,SAAA;AAAA"}
@@ -0,0 +1,77 @@
1
+ import _objectSpread from "@babel/runtime/helpers/objectSpread2";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+ import { i18n } from "@next-core/i18n";
4
+ import { symbolAppId, symbolMenuI18nNamespace, symbolOverrideApp } from "./constants.js";
5
+ import { loadDynamicMenuItems } from "./loadDynamicMenuItems.js";
6
+ export function mergeMenu(_x, _x2, _x3) {
7
+ return _mergeMenu.apply(this, arguments);
8
+ }
9
+ function _mergeMenu() {
10
+ _mergeMenu = _asyncToGenerator(function* (menuList, runtimeContext, helpers) {
11
+ var mainMenu = menuList.find(menu => menu.type !== "inject");
12
+ if (!mainMenu) {
13
+ return undefined;
14
+ }
15
+ var validMenuList = [];
16
+ var injectWithMenus = new Map();
17
+ var menuWithI18n = new WeakMap();
18
+ var _loop = function* () {
19
+ if (menu.i18n) {
20
+ var menuI18nNamespace = "menu/".concat(menu.menuId, "~").concat(menu.app[0].appId, "+").concat(menu.instanceId);
21
+ // Support any language in `menu.i18n`.
22
+ Object.entries(menu.i18n).forEach(_ref => {
23
+ var [lang, resources] = _ref;
24
+ i18n.addResourceBundle(lang, menuI18nNamespace, resources);
25
+ });
26
+ menuWithI18n.set(menu, menuI18nNamespace);
27
+ }
28
+ };
29
+ for (var menu of menuList) {
30
+ yield* _loop();
31
+ }
32
+ yield Promise.all(menuList.map(menu => loadDynamicMenuItems(menu, runtimeContext, menuWithI18n, helpers)));
33
+ for (var _menu of menuList) {
34
+ var _menu$items;
35
+ if ((_menu$items = _menu.items) !== null && _menu$items !== void 0 && _menu$items.length) {
36
+ if (_menu.type === "inject" && _menu.injectMenuGroupId) {
37
+ var injectingMenus = injectWithMenus.get(_menu.injectMenuGroupId);
38
+ if (!injectingMenus) {
39
+ injectingMenus = [];
40
+ injectWithMenus.set(_menu.injectMenuGroupId, injectingMenus);
41
+ }
42
+ injectingMenus.push(_menu);
43
+ } else {
44
+ validMenuList.push(_menu);
45
+ }
46
+ }
47
+ }
48
+ return _objectSpread(_objectSpread({}, mainMenu), {}, {
49
+ items: validMenuList.flatMap(menu =>
50
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
51
+ processGroupInject(menu.items, menu, injectWithMenus, menuWithI18n)),
52
+ [symbolMenuI18nNamespace]: menuWithI18n.get(mainMenu),
53
+ [symbolOverrideApp]: mainMenu.overrideApp
54
+ });
55
+ });
56
+ return _mergeMenu.apply(this, arguments);
57
+ }
58
+ function processGroupInject(items, menu, injectWithMenus, menuWithI18n) {
59
+ return items === null || items === void 0 ? void 0 : items.map(item => {
60
+ var _processGroupInject;
61
+ var foundInjectingMenus = item.groupId && injectWithMenus.get(item.groupId);
62
+ if (foundInjectingMenus) {
63
+ // Each menu to be injected with should be injected only once.
64
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
65
+ injectWithMenus.delete(item.groupId);
66
+ }
67
+ return _objectSpread(_objectSpread({}, item), {}, {
68
+ children: ((_processGroupInject = processGroupInject(item.children, menu, injectWithMenus, menuWithI18n)) !== null && _processGroupInject !== void 0 ? _processGroupInject : []).concat(foundInjectingMenus ? foundInjectingMenus.flatMap(injectingMenu =>
69
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
70
+ processGroupInject(injectingMenu.items, injectingMenu, injectWithMenus, menuWithI18n)) : []),
71
+ [symbolAppId]: menu.app[0].appId,
72
+ [symbolMenuI18nNamespace]: menuWithI18n.get(menu),
73
+ [symbolOverrideApp]: menu.overrideApp
74
+ });
75
+ });
76
+ }
77
+ //# sourceMappingURL=mergeMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeMenu.js","names":["i18n","symbolAppId","symbolMenuI18nNamespace","symbolOverrideApp","loadDynamicMenuItems","mergeMenu","_x","_x2","_x3","_mergeMenu","apply","arguments","_asyncToGenerator","menuList","runtimeContext","helpers","mainMenu","find","menu","type","undefined","validMenuList","injectWithMenus","Map","menuWithI18n","WeakMap","_loop","menuI18nNamespace","concat","menuId","app","appId","instanceId","Object","entries","forEach","_ref","lang","resources","addResourceBundle","set","Promise","all","map","_menu$items","items","length","injectMenuGroupId","injectingMenus","get","push","_objectSpread","flatMap","processGroupInject","overrideApp","item","_processGroupInject","foundInjectingMenus","groupId","delete","children","injectingMenu"],"sources":["../../../src/menu/mergeMenu.ts"],"sourcesContent":["import { i18n } from \"@next-core/i18n\";\nimport {\n symbolAppId,\n symbolMenuI18nNamespace,\n symbolOverrideApp,\n} from \"./constants.js\";\nimport type {\n RuntimeContext,\n MenuItemRawData,\n MenuRawData,\n RuntimeMenuItemRawData,\n RuntimeMenuRawData,\n RuntimeHelpers,\n} from \"./interfaces.js\";\nimport { loadDynamicMenuItems } from \"./loadDynamicMenuItems.js\";\n\nexport async function mergeMenu(\n menuList: MenuRawData[],\n runtimeContext: RuntimeContext,\n helpers: RuntimeHelpers\n): Promise<RuntimeMenuRawData | undefined> {\n const mainMenu = menuList.find((menu) => menu.type !== \"inject\");\n if (!mainMenu) {\n return undefined;\n }\n const validMenuList: MenuRawData[] = [];\n const injectWithMenus = new Map<string, MenuRawData[]>();\n const menuWithI18n = new WeakMap<MenuRawData, string>();\n\n for (const menu of menuList) {\n if (menu.i18n) {\n const menuI18nNamespace = `menu/${menu.menuId}~${menu.app[0].appId}+${\n (menu as { instanceId?: string }).instanceId\n }`;\n // Support any language in `menu.i18n`.\n Object.entries(menu.i18n).forEach(([lang, resources]) => {\n i18n.addResourceBundle(lang, menuI18nNamespace, resources);\n });\n menuWithI18n.set(menu, menuI18nNamespace);\n }\n }\n\n await Promise.all(\n menuList.map((menu) =>\n loadDynamicMenuItems(menu, runtimeContext, menuWithI18n, helpers)\n )\n );\n\n for (const menu of menuList) {\n if (menu.items?.length) {\n if (menu.type === \"inject\" && menu.injectMenuGroupId) {\n let injectingMenus = injectWithMenus.get(menu.injectMenuGroupId);\n if (!injectingMenus) {\n injectingMenus = [];\n injectWithMenus.set(menu.injectMenuGroupId, injectingMenus);\n }\n injectingMenus.push(menu);\n } else {\n validMenuList.push(menu);\n }\n }\n }\n\n return {\n ...mainMenu,\n items: validMenuList.flatMap(\n (menu) =>\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n processGroupInject(menu.items, menu, injectWithMenus, menuWithI18n)!\n ),\n [symbolMenuI18nNamespace]: menuWithI18n.get(mainMenu),\n [symbolOverrideApp]: mainMenu.overrideApp,\n };\n}\n\nfunction processGroupInject(\n items: MenuItemRawData[] | undefined,\n menu: MenuRawData,\n injectWithMenus: Map<string, MenuRawData[]>,\n menuWithI18n: WeakMap<MenuRawData, string>\n): RuntimeMenuItemRawData[] | undefined {\n return items?.map((item) => {\n const foundInjectingMenus =\n item.groupId && injectWithMenus.get(item.groupId);\n if (foundInjectingMenus) {\n // Each menu to be injected with should be injected only once.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n injectWithMenus.delete(item.groupId!);\n }\n return {\n ...item,\n children: (\n processGroupInject(\n item.children,\n menu,\n injectWithMenus,\n menuWithI18n\n ) ?? ([] as RuntimeMenuItemRawData[])\n ).concat(\n foundInjectingMenus\n ? foundInjectingMenus.flatMap(\n (injectingMenu) =>\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n processGroupInject(\n injectingMenu.items,\n injectingMenu,\n injectWithMenus,\n menuWithI18n\n )!\n )\n : ([] as RuntimeMenuItemRawData[])\n ),\n [symbolAppId]: menu.app[0].appId,\n [symbolMenuI18nNamespace]: menuWithI18n.get(menu),\n [symbolOverrideApp]: menu.overrideApp,\n };\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import _objectSpread from "@babel/runtime/helpers/objectSpread2";
2
+ import { sortBy } from "lodash";
3
+ export function reorderMenuItems(menuData) {
4
+ menuData.items = sortMenuItems(menuData.items).map(item => _objectSpread(_objectSpread({}, item), {}, {
5
+ children: sortMenuItems(item.children)
6
+ }));
7
+ }
8
+ function sortMenuItems(list) {
9
+ return sortBy(list, item => {
10
+ var _item$sort;
11
+ return (_item$sort = item.sort) !== null && _item$sort !== void 0 ? _item$sort : -Infinity;
12
+ });
13
+ }
14
+ //# sourceMappingURL=reorderMenuItems.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reorderMenuItems.js","names":["sortBy","reorderMenuItems","menuData","items","sortMenuItems","map","item","_objectSpread","children","list","_item$sort","sort","Infinity"],"sources":["../../../src/menu/reorderMenuItems.ts"],"sourcesContent":["import { sortBy } from \"lodash\";\nimport { MenuItemRawData, MenuRawData } from \"./interfaces.js\";\n\nexport function reorderMenuItems(menuData: MenuRawData): void {\n menuData.items = sortMenuItems(menuData.items).map((item) => ({\n ...item,\n children: sortMenuItems(item.children) as MenuItemRawData[],\n }));\n}\n\nfunction sortMenuItems(list: MenuItemRawData[] | undefined): MenuItemRawData[] {\n return sortBy(list, (item) => item.sort ?? -Infinity);\n}\n"],"mappings":";AAAA,SAASA,MAAM,QAAQ,QAAQ;AAG/B,OAAO,SAASC,gBAAgBA,CAACC,QAAqB,EAAQ;EAC5DA,QAAQ,CAACC,KAAK,GAAGC,aAAa,CAACF,QAAQ,CAACC,KAAK,CAAC,CAACE,GAAG,CAAEC,IAAI,IAAAC,aAAA,CAAAA,aAAA,KACnDD,IAAI;IACPE,QAAQ,EAAEJ,aAAa,CAACE,IAAI,CAACE,QAAQ;EAAsB,EAC3D,CAAC;AACL;AAEA,SAASJ,aAAaA,CAACK,IAAmC,EAAqB;EAC7E,OAAOT,MAAM,CAACS,IAAI,EAAGH,IAAI;IAAA,IAAAI,UAAA;IAAA,QAAAA,UAAA,GAAKJ,IAAI,CAACK,IAAI,cAAAD,UAAA,cAAAA,UAAA,GAAI,CAACE,QAAQ;EAAA,EAAC;AACvD"}
@@ -0,0 +1,16 @@
1
+ import type { BrickConf, RouteConf, Storyboard } from "@next-core/types";
2
+ export declare function preCheckPermissions(storyboard: Storyboard): Promise<void> | undefined;
3
+ export declare function preCheckPermissionsForBrickOrRoute(container: BrickConf | RouteConf, asyncComputeRealValue: (value: unknown) => Promise<unknown>): Promise<void>;
4
+ export declare function preCheckPermissionsForAny(data: unknown): Promise<void> | undefined;
5
+ export declare function validatePermissions(usedActions: string[]): Promise<void>;
6
+ /**
7
+ * Check the current logged-in user whether to have all
8
+ * permissions of actions passed to it.
9
+ *
10
+ * @param actions - Required permission actions.
11
+ */
12
+ export declare function checkPermissions(...actions: string[]): boolean;
13
+ /**
14
+ * Reset permission pre-checks after logged-out.
15
+ */
16
+ export declare function resetPermissionPreChecks(): void;
@@ -1,4 +1,10 @@
1
- export { PermissionApi_validatePermissions as validatePermissions } from "@next-api-sdk/micro-app-sdk";
1
+ import { checkPermissions as _checkPermissions, preCheckPermissions, preCheckPermissionsForBrickOrRoute } from "./checkPermissions.js";
2
2
  export * as checkInstalledApps from "./checkInstalledApps.js";
3
3
  export * as flowApi from "./flowApi/index.js";
4
4
  export * as auth from "./auth.js";
5
+ export * as menu from "./menu/index.js";
6
+ export declare const checkPermissions: Readonly<{
7
+ checkPermissions: typeof _checkPermissions;
8
+ preCheckPermissions: typeof preCheckPermissions;
9
+ preCheckPermissionsForBrickOrRoute: typeof preCheckPermissionsForBrickOrRoute;
10
+ }>;
@@ -0,0 +1,6 @@
1
+ import type { RuntimeContext, RuntimeHelpers, RuntimeMenuItemRawData, RuntimeMenuRawData } from "./interfaces.js";
2
+ type RuntimeMenuRestRawData = Omit<RuntimeMenuRawData, "app" | "items">;
3
+ type RuntimeMenuItemRestRawData = Omit<RuntimeMenuItemRawData, "children">;
4
+ export declare function computeMenuData<T extends RuntimeMenuRestRawData | RuntimeMenuItemRestRawData>(data: T, overrideAppId: string, runtimeContext: RuntimeContext, helpers: RuntimeHelpers): Promise<T>;
5
+ export declare function computeMenuItems(items: RuntimeMenuItemRawData[], runtimeContext: RuntimeContext, helpers: RuntimeHelpers): Promise<RuntimeMenuItemRawData[]>;
6
+ export {};
@@ -0,0 +1,3 @@
1
+ export declare const symbolAppId: unique symbol;
2
+ export declare const symbolMenuI18nNamespace: unique symbol;
3
+ export declare const symbolOverrideApp: unique symbol;
@@ -0,0 +1,3 @@
1
+ import type { RuntimeContext, RuntimeHelpers } from "./interfaces.js";
2
+ export declare function getMenuById(menuId: string): unknown;
3
+ export declare function fetchMenuById(menuId: string, runtimeContext: RuntimeContext, helpers: RuntimeHelpers): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { MenuRawData } from "./interfaces.js";
2
+ export declare function fetchMenuTitle(menuData: Pick<MenuRawData, "title" | "titleDataSource">): Promise<string | undefined>;
@@ -0,0 +1,2 @@
1
+ import { MenuRawData, RuntimeHelpers } from "./interfaces.js";
2
+ export declare function getMenusOfStandaloneApp(menuId: string, appId: string, helpers: RuntimeHelpers): MenuRawData[];
@@ -0,0 +1 @@
1
+ export { getMenuById, fetchMenuById } from "./fetchMenuById.js";
@@ -0,0 +1,77 @@
1
+ import type { MetaI18n, MicroApp, ResolveConf } from "@next-core/types";
2
+ import type { RuntimeHooksMenuHelpers, __secret_internals } from "@next-core/runtime";
3
+ import { symbolAppId, symbolMenuI18nNamespace, symbolOverrideApp } from "./constants.js";
4
+ export type RuntimeContext = __secret_internals.RuntimeContext;
5
+ export type RuntimeHelpers = RuntimeHooksMenuHelpers;
6
+ /** 原始菜单数据。 */
7
+ export interface MenuRawData {
8
+ menuId: string;
9
+ title: string;
10
+ app: [
11
+ {
12
+ appId: string;
13
+ }
14
+ ];
15
+ icon?: unknown;
16
+ link?: string;
17
+ titleDataSource?: TitleDataSource;
18
+ items?: MenuItemRawData[];
19
+ type?: "main" | "inject";
20
+ injectMenuGroupId?: string;
21
+ defaultCollapsed?: boolean;
22
+ defaultCollapsedBreakpoint?: number;
23
+ dynamicItems?: boolean;
24
+ itemsResolve?: ResolveConf;
25
+ i18n?: MetaI18n;
26
+ overrideApp?: MicroApp;
27
+ }
28
+ /** 原始菜单项数据。 */
29
+ export type MenuItemRawData = Omit<SidebarMenuSimpleItem, "type"> & {
30
+ children?: MenuItemRawData[];
31
+ type?: "default" | "group";
32
+ sort?: number;
33
+ if?: string | boolean;
34
+ defaultExpanded?: boolean;
35
+ groupId?: string;
36
+ };
37
+ interface TitleDataSource {
38
+ objectId: string;
39
+ instanceId: string;
40
+ attributeId?: string;
41
+ }
42
+ /** 侧边栏基本菜单项的配置。 */
43
+ export interface SidebarMenuSimpleItem {
44
+ /** 菜单项文本。 */
45
+ text: string;
46
+ /** 菜单项对应的系统内地址。 */
47
+ to?: unknown;
48
+ /** 菜单项对应的外部链接地址。 */
49
+ href?: string;
50
+ /** 菜单项的图标。 */
51
+ icon?: unknown;
52
+ /** 菜单项链接打开的目标。 */
53
+ target?: string;
54
+ type?: "default";
55
+ /** 高亮菜单项时是否使用精确匹配来对比当前地址和菜单项地址。 */
56
+ exact?: boolean;
57
+ /** 设置额外包含的匹配高亮菜单项的地址列表。 */
58
+ activeIncludes?: string[];
59
+ /** 设置需要被排除的匹配高亮菜单项的地址列表。 */
60
+ activeExcludes?: string[];
61
+ /** 设置匹配高亮菜单项时是否还对 search 参数进行比较。 */
62
+ activeMatchSearch?: boolean;
63
+ /** @internal */
64
+ key?: string;
65
+ }
66
+ export interface RuntimeMenuItemRawData extends MenuItemRawData {
67
+ children?: RuntimeMenuItemRawData[];
68
+ [symbolAppId]: string;
69
+ [symbolMenuI18nNamespace]?: string;
70
+ [symbolOverrideApp]?: MicroApp;
71
+ }
72
+ export interface RuntimeMenuRawData extends MenuRawData {
73
+ items: RuntimeMenuItemRawData[];
74
+ [symbolMenuI18nNamespace]?: string;
75
+ [symbolOverrideApp]?: MicroApp;
76
+ }
77
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { RuntimeContext, MenuRawData, RuntimeHelpers } from "./interfaces.js";
2
+ export declare function loadDynamicMenuItems(menu: MenuRawData, runtimeContext: RuntimeContext, menuWithI18n: WeakMap<MenuRawData, string>, helpers: RuntimeHelpers): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { RuntimeContext, MenuRawData, RuntimeMenuRawData, RuntimeHelpers } from "./interfaces.js";
2
+ export declare function mergeMenu(menuList: MenuRawData[], runtimeContext: RuntimeContext, helpers: RuntimeHelpers): Promise<RuntimeMenuRawData | undefined>;
@@ -0,0 +1,2 @@
1
+ import { MenuRawData } from "./interfaces.js";
2
+ export declare function reorderMenuItems(menuData: MenuRawData): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@next-core/easyops-runtime",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "homepage": "https://github.com/easyops-cn/next-core/tree/v3/packages/easyops-runtime",
5
5
  "license": "GPL-3.0",
6
6
  "repository": {
@@ -41,18 +41,19 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@next-api-sdk/api-gateway-sdk": "^1.1.0",
44
+ "@next-api-sdk/cmdb-sdk": "^1.1.0",
44
45
  "@next-api-sdk/micro-app-sdk": "^1.1.0",
45
46
  "@next-api-sdk/micro-app-standalone-sdk": "^1.1.0",
46
- "@next-core/http": "^1.0.5",
47
- "@next-core/runtime": "^1.11.1",
47
+ "@next-core/http": "^1.0.6",
48
+ "@next-core/runtime": "^1.12.1",
48
49
  "@next-core/types": "^1.3.0",
49
- "@next-core/utils": "^1.5.1",
50
+ "@next-core/utils": "^1.5.2",
50
51
  "js-yaml": "^3.14.1",
51
52
  "lodash": "^4.17.21"
52
53
  },
53
54
  "devDependencies": {
54
- "@next-core/build-next-libs": "^1.0.4",
55
- "@next-core/test-next": "^1.0.5"
55
+ "@next-core/build-next-libs": "^1.0.5",
56
+ "@next-core/test-next": "^1.0.6"
56
57
  },
57
- "gitHead": "1e7d86481659627d233451f5dadafdc471e97ec8"
58
+ "gitHead": "d8ed3d57b38b9626e70cbb84e61542cc3c269556"
58
59
  }