adminizer 4.7.0-build.224 → 5.0.0-build.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 (307) hide show
  1. package/Readme.md +2 -1
  2. package/assets/add-De0wyF0A.js +1 -0
  3. package/assets/add-group-CMWybgIR.js +1 -0
  4. package/assets/add-user-BxP23daH.js +1 -0
  5. package/assets/app-CtWuWD5N.css +1 -0
  6. package/assets/app-layout-GYMU2HO1.js +1 -0
  7. package/assets/app.js +45 -50
  8. package/assets/catalog-tImW1BnS.js +6 -0
  9. package/assets/controls/chunks/_commonjsHelpers-C6fGbg64.js +6 -0
  10. package/assets/controls/chunks/index-CjiZ2FIa.js +93 -0
  11. package/assets/controls/chunks/jsx-runtime-jIxVPx5o.js +31 -0
  12. package/assets/controls/chunks/use-appearance-CFLOwiSX.js +38 -0
  13. package/assets/controls/chunks/use-window-size-BXgBKW65.js +19 -0
  14. package/assets/controls/chunks/vanilla-picker-Dg97NL4h.js +529 -0
  15. package/assets/controls/ckeditor.es.js +83683 -0
  16. package/assets/controls/handsontable.css +1 -0
  17. package/assets/controls/handsontable.es.js +70585 -0
  18. package/assets/controls/jsoneditor.css +1 -0
  19. package/assets/controls/jsoneditor.es.js +42082 -0
  20. package/assets/controls/leaflet.css +1 -0
  21. package/assets/controls/leaflet.es.js +10299 -0
  22. package/assets/controls/monaco.es.js +618 -0
  23. package/assets/controls/toast-ui.css +1 -0
  24. package/assets/controls/toast-ui.es.js +41797 -0
  25. package/assets/dashboard-CQ4atH3N.js +3 -0
  26. package/assets/debounce-BMmXVQ06.js +1 -0
  27. package/assets/history-BileQPEi.js +1 -0
  28. package/assets/init-user-8aUohVDq.js +1 -0
  29. package/assets/list-Pz_5mfSq.js +4 -0
  30. package/assets/login-CO4laf6m.js +1 -0
  31. package/assets/manifest.json +66 -602
  32. package/assets/media-manager-BDbpSSjH.js +6 -0
  33. package/assets/media-manager-BZPjl98I.css +1 -0
  34. package/assets/module-CQiOdgZN.js +1 -0
  35. package/assets/notification-BIyv1smE.js +20 -0
  36. package/assets/register-DBYIMXGQ.js +1 -0
  37. package/assets/ru-rYKdQbWF.js +1 -0
  38. package/assets/use-appearance-_EbbjHTh.js +1 -0
  39. package/assets/user-filters-list-Aq8CvCeh.js +1 -0
  40. package/assets/welcome-DxhWYzUL.js +1 -0
  41. package/controllers/add.d.ts +1 -1
  42. package/controllers/addGroup.js +3 -3
  43. package/controllers/addUser.js +3 -3
  44. package/controllers/catalog/Catalog.d.ts +1 -1
  45. package/controllers/catalog/Catalog.js +2 -1
  46. package/controllers/catalog/FrontendCatalogAdapter.d.ts +2 -12
  47. package/controllers/catalog/FrontendCatalogAdapter.js +3 -16
  48. package/controllers/catalog/FrontentCatalogAdapter.d.ts +2 -12
  49. package/controllers/catalog/FrontentCatalogAdapter.js +0 -16
  50. package/controllers/edit.js +6 -11
  51. package/controllers/editGroup.d.ts +1 -1
  52. package/controllers/editGroup.js +3 -3
  53. package/controllers/editUser.d.ts +1 -1
  54. package/controllers/editUser.js +3 -3
  55. package/controllers/feed.js +1 -1
  56. package/controllers/filter-fields/columns.js +1 -1
  57. package/controllers/filter-fields/getAllUserFilters.js +2 -2
  58. package/controllers/filter-fields/groups.js +2 -2
  59. package/controllers/filter-fields/savedFilters.js +1 -1
  60. package/controllers/history-actions/HistoryController.js +1 -1
  61. package/controllers/initUser.js +2 -2
  62. package/controllers/list.d.ts +1 -1
  63. package/controllers/login.d.ts +1 -1
  64. package/controllers/login.js +3 -3
  65. package/controllers/media-manager/ThumbController.js +2 -2
  66. package/controllers/media-manager/mediaManagerApi.js +13 -15
  67. package/controllers/register.d.ts +1 -1
  68. package/controllers/register.js +5 -5
  69. package/controllers/remove.d.ts +1 -1
  70. package/controllers/userApiKey.js +2 -2
  71. package/controllers/view.d.ts +1 -1
  72. package/controllers/view.js +5 -5
  73. package/controllers/widgets/Action.js +5 -2
  74. package/controllers/widgets/filterInfo.js +1 -1
  75. package/files/favicon.png +0 -0
  76. package/helpers/accessRightsHelper.d.ts +6 -4
  77. package/helpers/accessRightsHelper.js +13 -0
  78. package/helpers/diffHelpers.js +1 -1
  79. package/helpers/fieldsHelper.d.ts +1 -1
  80. package/helpers/fieldsHelper.js +8 -4
  81. package/helpers/filterDatetimeHelper.d.ts +1 -1
  82. package/helpers/inertiaAddHelper.d.ts +6 -5
  83. package/helpers/inertiaAddHelper.js +45 -37
  84. package/helpers/inertiaAutHelper.js +5 -5
  85. package/helpers/inertiaGroupHelper.d.ts +4 -4
  86. package/helpers/inertiaMenuHelper.js +1 -1
  87. package/helpers/inertiaUserHelper.d.ts +3 -3
  88. package/helpers/inertiaUserHelper.js +1 -1
  89. package/helpers/menuHelper.d.ts +2 -2
  90. package/index.d.ts +19 -6
  91. package/index.js +19 -6
  92. package/interfaces/adminpanelConfig.d.ts +10 -33
  93. package/interfaces/global.d.ts +10 -15
  94. package/interfaces/listQueryBuilder.d.ts +1 -1
  95. package/lib/Adminizer.d.ts +25 -2
  96. package/lib/Adminizer.js +124 -50
  97. package/lib/DataAccessor.d.ts +9 -5
  98. package/lib/DataAccessor.js +89 -42
  99. package/lib/access-rights/AccessRightsHandler.d.ts +17 -0
  100. package/lib/access-rights/AccessRightsHandler.js +63 -0
  101. package/lib/ai-assistant/AbstractAiModelService.d.ts +5 -8
  102. package/lib/ai-assistant/AbstractAiModelService.js +3 -14
  103. package/lib/ai-assistant/AiAssistantHandler.d.ts +2 -2
  104. package/lib/app-manager/AdminizerApp.d.ts +228 -0
  105. package/lib/app-manager/AdminizerApp.js +17 -0
  106. package/lib/app-manager/AppManager.d.ts +18 -0
  107. package/lib/app-manager/AppManager.js +537 -0
  108. package/lib/app-manager/AssetHandler.d.ts +17 -0
  109. package/lib/app-manager/AssetHandler.js +67 -0
  110. package/lib/app-manager/ConfigLayerHandler.d.ts +18 -0
  111. package/lib/app-manager/ConfigLayerHandler.js +119 -0
  112. package/lib/app-manager/ControllerHandler.d.ts +25 -0
  113. package/lib/app-manager/ControllerHandler.js +140 -0
  114. package/lib/catalog/AbstractCatalog.d.ts +28 -19
  115. package/lib/catalog/AbstractCatalog.js +41 -10
  116. package/lib/catalog/CatalogHandler.d.ts +13 -0
  117. package/lib/catalog/CatalogHandler.js +48 -2
  118. package/lib/catalog/CatalogTemplateComponentHandler.d.ts +23 -0
  119. package/lib/catalog/CatalogTemplateComponentHandler.js +59 -0
  120. package/lib/controls/Control.d.ts +17 -0
  121. package/lib/controls/Control.js +1 -0
  122. package/lib/controls/ControlsHandler.d.ts +5 -6
  123. package/lib/controls/ControlsHandler.js +0 -13
  124. package/lib/controls/codeEditor/MonacoEditor.d.ts +3 -4
  125. package/lib/controls/codeEditor/MonacoEditor.js +13 -8
  126. package/lib/controls/geojsoneditor/GeoEditor.d.ts +3 -4
  127. package/lib/controls/geojsoneditor/GeoEditor.js +14 -9
  128. package/lib/controls/jsoneditor/JsonEditor.d.ts +5 -6
  129. package/lib/controls/jsoneditor/JsonEditor.js +14 -13
  130. package/lib/controls/markdown/ToastUiEditor.d.ts +5 -6
  131. package/lib/controls/markdown/ToastUiEditor.js +14 -13
  132. package/lib/controls/table/Handsontable.d.ts +5 -6
  133. package/lib/controls/table/Handsontable.js +14 -13
  134. package/lib/controls/wysiwyg/CKeditor.d.ts +5 -6
  135. package/lib/controls/wysiwyg/CKeditor.js +14 -13
  136. package/lib/filters/ConditionValidator.d.ts +1 -1
  137. package/lib/filters/FilterService.d.ts +18 -18
  138. package/lib/filters/FilterService.js +11 -11
  139. package/lib/history-actions/AbstractHistoryAdapter.d.ts +14 -14
  140. package/lib/history-actions/AbstractHistoryAdapter.js +5 -6
  141. package/lib/history-actions/DefaultHistoryAdapter.d.ts +7 -7
  142. package/lib/history-actions/DefaultHistoryAdapter.js +2 -2
  143. package/lib/list-query-builder/ListQueryBuilder.d.ts +1 -1
  144. package/lib/media-manager/AbstractMediaManager.d.ts +14 -3
  145. package/lib/media-manager/AbstractMediaManager.js +16 -5
  146. package/lib/media-manager/MediaManagerHandler.d.ts +3 -0
  147. package/lib/media-manager/MediaManagerHandler.js +30 -5
  148. package/lib/media-manager/Thumb.js +7 -13
  149. package/lib/media-manager/helpers/MediaManagerHelper.d.ts +6 -4
  150. package/lib/media-manager/helpers/MediaManagerHelper.js +18 -18
  151. package/lib/model/AbstractModel.d.ts +9 -5
  152. package/lib/model/AbstractModel.js +9 -13
  153. package/lib/model/InternalModelAccessFactory.js +9 -10
  154. package/lib/model/ModelHandler.d.ts +45 -7
  155. package/lib/model/ModelHandler.js +168 -11
  156. package/lib/model/adapter/sequelize.d.ts +2 -4
  157. package/lib/model/adapter/sequelize.js +16 -193
  158. package/lib/model/adapter/typeorm.d.ts +2 -4
  159. package/lib/model/adapter/typeorm.js +2 -35
  160. package/lib/notifications/AbstractNotificationService.d.ts +9 -9
  161. package/lib/notifications/AbstractNotificationService.js +8 -8
  162. package/lib/notifications/GeneralNotificationService.js +1 -1
  163. package/lib/notifications/SystemNotificationService.js +1 -1
  164. package/lib/ui-i18n/uiTranslationKeys.d.ts +1 -1
  165. package/lib/ui-i18n/uiTranslationKeys.js +1 -0
  166. package/lib/widgets/abstractCustom.d.ts +5 -2
  167. package/lib/widgets/abstractCustom.js +4 -0
  168. package/lib/widgets/widgetHandler.d.ts +5 -2
  169. package/lib/widgets/widgetHandler.js +60 -14
  170. package/models/{FilterAP.d.ts → Filter.d.ts} +4 -70
  171. package/models/Filter.js +1 -0
  172. package/models/FilterColumn.d.ts +10 -0
  173. package/models/FilterColumn.js +1 -0
  174. package/models/Group.d.ts +8 -0
  175. package/models/Group.js +1 -0
  176. package/models/HistoryActions.d.ts +14 -0
  177. package/models/HistoryActions.js +1 -0
  178. package/models/MediaManagerAP.d.ts +2 -54
  179. package/models/MediaManagerAP.js +1 -51
  180. package/models/MediaManagerAssociationsAP.d.ts +1 -35
  181. package/models/MediaManagerAssociationsAP.js +1 -33
  182. package/models/MediaManagerMetaAP.d.ts +2 -30
  183. package/models/MediaManagerMetaAP.js +1 -27
  184. package/models/Notification.d.ts +13 -0
  185. package/models/Notification.js +1 -0
  186. package/models/User.d.ts +23 -0
  187. package/models/User.js +1 -0
  188. package/models/UserNotification.d.ts +7 -0
  189. package/models/UserNotification.js +1 -0
  190. package/package.json +25 -30
  191. package/services/FeedService.d.ts +5 -5
  192. package/services/FeedService.js +1 -1
  193. package/system/Router.js +2 -10
  194. package/system/bindAccessRights.js +1 -1
  195. package/system/bindAuthorization.js +2 -2
  196. package/system/bindControls.js +7 -6
  197. package/system/bindDashboardWidgets.js +3 -2
  198. package/system/bindDev.js +1 -1
  199. package/system/bindHistory.d.ts +1 -1
  200. package/system/bindHistory.js +1 -1
  201. package/system/bindInertia.js +0 -6
  202. package/system/bindMediaManager.js +4 -17
  203. package/system/bindNotifications.d.ts +1 -1
  204. package/system/bindNotifications.js +1 -1
  205. package/system/bindReqFunctions.d.ts +1 -0
  206. package/system/bindReqFunctions.js +20 -3
  207. package/system/buildInternalModelAccess.js +2 -15
  208. package/system/defaults.js +5 -10
  209. package/system/systemModelContracts.d.ts +22 -0
  210. package/system/systemModelContracts.js +155 -0
  211. package/system/validateSystemModels.d.ts +2 -0
  212. package/system/validateSystemModels.js +101 -0
  213. package/translations/ar.json +2 -1
  214. package/translations/cn.json +2 -1
  215. package/translations/de.json +2 -1
  216. package/translations/en.json +1 -0
  217. package/translations/es.json +2 -1
  218. package/translations/fr.json +2 -1
  219. package/translations/hi.json +2 -1
  220. package/translations/jp.json +2 -1
  221. package/translations/ko.json +2 -1
  222. package/translations/pt.json +2 -1
  223. package/translations/ru.json +2 -1
  224. package/translations/ua.json +2 -1
  225. package/translations/uz.json +2 -1
  226. package/translations/vi.json +2 -1
  227. package/assets/RelationDialogStack-DhThUMep.js +0 -20
  228. package/assets/add-group-L8lMigab.js +0 -1
  229. package/assets/add-group-form-o7F6t6qW.js +0 -1
  230. package/assets/add-user-BE4-TNJw.js +0 -1
  231. package/assets/add-user-form-BP_8TjxN.js +0 -1
  232. package/assets/add-w398ZkhF.js +0 -1
  233. package/assets/app-C7J5ccrI.css +0 -1
  234. package/assets/app-layout-Bg455MIY.js +0 -1
  235. package/assets/app-shell-BT2kF0We.js +0 -1
  236. package/assets/app-sidebar-CZfPUXck.js +0 -1
  237. package/assets/app-sidebar-header-UVcKhNm6.js +0 -1
  238. package/assets/breadcrumbs-CrqIBT84.js +0 -1
  239. package/assets/catalog-btkCCwiv.js +0 -6
  240. package/assets/dashboard-Bvasc1cr.js +0 -3
  241. package/assets/date-picker-kxQWOxHk.js +0 -1
  242. package/assets/del-modal-C39LR5aQ.js +0 -1
  243. package/assets/dynamic-controls-DyPP5sTC.js +0 -1
  244. package/assets/geo-json-CGNQFl6J.js +0 -1
  245. package/assets/handsontable-Dv59QFH5.js +0 -336
  246. package/assets/history-DwKR8MPu.js +0 -1
  247. package/assets/home-BrtAkCRj.js +0 -2
  248. package/assets/icon-DpUVVHmK.js +0 -1
  249. package/assets/init-user-8PiKR1zX.js +0 -1
  250. package/assets/input-error-Cbt-Y3Fj.js +0 -1
  251. package/assets/jsoneditor-CiPXPMho.js +0 -3869
  252. package/assets/list-DGsL_qii.js +0 -4
  253. package/assets/login-Br_FcBU_.js +0 -1
  254. package/assets/material-icon-DOkM71fv.js +0 -1
  255. package/assets/module-EgfgIEhF.js +0 -1
  256. package/assets/monaco-ompgKQ3_.js +0 -11
  257. package/assets/nav-footer-DzLwfBAE.js +0 -1
  258. package/assets/nav-main-CSEbjYgs.js +0 -1
  259. package/assets/nav-user-DJ0hfhfH.js +0 -1
  260. package/assets/notification-B19ZLro7.js +0 -20
  261. package/assets/pagination-render-8GvJxq55.js +0 -1
  262. package/assets/register-CZzIeT2G.js +0 -1
  263. package/assets/ru-1NdRIQNV.js +0 -1
  264. package/assets/theme-switcher-CBbEj1u-.js +0 -1
  265. package/assets/toast-editor-DwVqd1rz.js +0 -668
  266. package/assets/user-filters-list-7Im79QyS.js +0 -1
  267. package/assets/user-info-YiU17Mmy.js +0 -1
  268. package/assets/user-menu-content-gdpNF5-8.js +0 -1
  269. package/assets/vanilla-picker-B3LgXoKV.js +0 -2
  270. package/assets/vendor-l0sNRNKZ.js +0 -1
  271. package/assets/welcome-nT0eFWHb.js +0 -1
  272. package/controllers/navigation/edit.d.ts +0 -1
  273. package/controllers/navigation/edit.js +0 -8
  274. package/lib/ai-assistant/DummyAiModelService.d.ts +0 -8
  275. package/lib/ai-assistant/DummyAiModelService.js +0 -14
  276. package/lib/ai-assistant/OpenAiModelService.d.ts +0 -24
  277. package/lib/ai-assistant/OpenAiModelService.js +0 -184
  278. package/lib/catalog/Navigation.d.ts +0 -49
  279. package/lib/catalog/Navigation.js +0 -492
  280. package/lib/controls/AbstractControls.d.ts +0 -30
  281. package/lib/controls/AbstractControls.js +0 -14
  282. package/lib/media-manager/DefaultMediaManager.d.ts +0 -20
  283. package/lib/media-manager/DefaultMediaManager.js +0 -127
  284. package/lib/media-manager/Items.d.ts +0 -50
  285. package/lib/media-manager/Items.js +0 -296
  286. package/models/FilterAP.js +0 -68
  287. package/models/FilterColumnAP.d.ts +0 -32
  288. package/models/FilterColumnAP.js +0 -21
  289. package/models/GroupAP.d.ts +0 -31
  290. package/models/GroupAP.js +0 -22
  291. package/models/HistoryActionsAP.d.ts +0 -56
  292. package/models/HistoryActionsAP.js +0 -42
  293. package/models/NavigationAP.d.ts +0 -22
  294. package/models/NavigationAP.js +0 -16
  295. package/models/NotificationAP.d.ts +0 -44
  296. package/models/NotificationAP.js +0 -30
  297. package/models/UserAP.d.ts +0 -81
  298. package/models/UserAP.js +0 -57
  299. package/models/UserNotificationAP.d.ts +0 -26
  300. package/models/UserNotificationAP.js +0 -18
  301. package/system/bindAiAssistant.d.ts +0 -2
  302. package/system/bindAiAssistant.js +0 -30
  303. package/system/bindModels.d.ts +0 -2
  304. package/system/bindModels.js +0 -48
  305. package/system/bindNavigation.d.ts +0 -2
  306. package/system/bindNavigation.js +0 -38
  307. /package/assets/{RelationDialogStack-B00Ot5qS.css → controls/ckeditor.css} +0 -0
@@ -0,0 +1,119 @@
1
+ function cloneConfigValue(value) {
2
+ if (Array.isArray(value)) {
3
+ return value.map((item) => cloneConfigValue(item));
4
+ }
5
+ if (isPlainObject(value)) {
6
+ const cloned = {};
7
+ for (const [key, nestedValue] of Object.entries(value)) {
8
+ cloned[key] = cloneConfigValue(nestedValue);
9
+ }
10
+ return cloned;
11
+ }
12
+ return value;
13
+ }
14
+ function isPlainObject(value) {
15
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
16
+ return false;
17
+ }
18
+ const prototype = Object.getPrototypeOf(value);
19
+ return prototype === Object.prototype || prototype === null;
20
+ }
21
+ function hasStringId(value) {
22
+ return isPlainObject(value) && typeof value.id === "string";
23
+ }
24
+ function mergeArrays(base, patch) {
25
+ if (!patch.length) {
26
+ return cloneConfigValue(base);
27
+ }
28
+ const shouldMergeById = patch.every(hasStringId);
29
+ if (!shouldMergeById) {
30
+ return [...cloneConfigValue(base), ...cloneConfigValue(patch)];
31
+ }
32
+ const merged = cloneConfigValue(base);
33
+ for (const patchItem of patch) {
34
+ const index = merged.findIndex((item) => hasStringId(item) && item.id === patchItem.id);
35
+ if (index === -1) {
36
+ merged.push(cloneConfigValue(patchItem));
37
+ }
38
+ else {
39
+ merged[index] = mergeConfigValues(merged[index], patchItem);
40
+ }
41
+ }
42
+ return merged;
43
+ }
44
+ function mergeConfigValues(base, patch) {
45
+ if (patch === undefined) {
46
+ return cloneConfigValue(base);
47
+ }
48
+ if (Array.isArray(patch)) {
49
+ return mergeArrays(Array.isArray(base) ? base : [], patch);
50
+ }
51
+ if (isPlainObject(patch)) {
52
+ const merged = isPlainObject(base) ? cloneConfigValue(base) : {};
53
+ for (const [key, value] of Object.entries(patch)) {
54
+ merged[key] = mergeConfigValues(merged[key], value);
55
+ }
56
+ return merged;
57
+ }
58
+ return patch;
59
+ }
60
+ export class ConfigLayerHandler {
61
+ adminizer;
62
+ baseConfig;
63
+ layers = new Map();
64
+ constructor(adminizer) {
65
+ this.adminizer = adminizer;
66
+ }
67
+ register(appName, layerId, patch) {
68
+ const id = this.getLayerId(appName, layerId);
69
+ if (this.layers.has(id)) {
70
+ throw new Error(`Config layer "${id}" is already registered`);
71
+ }
72
+ if (!this.adminizer.config) {
73
+ throw new Error("Adminizer config must be initialized before registering app config layers");
74
+ }
75
+ if (!this.baseConfig) {
76
+ this.baseConfig = cloneConfigValue(this.adminizer.config);
77
+ }
78
+ this.layers.set(id, {
79
+ id,
80
+ appName,
81
+ patch: cloneConfigValue(patch),
82
+ });
83
+ this.rebuildConfig();
84
+ this.adminizer.emitter.emit("app:config:registered", {
85
+ appName,
86
+ resourceId: id,
87
+ });
88
+ return id;
89
+ }
90
+ unregister(id) {
91
+ const layer = this.layers.get(id);
92
+ if (!layer) {
93
+ return;
94
+ }
95
+ this.layers.delete(id);
96
+ this.rebuildConfig();
97
+ this.adminizer.emitter.emit("app:config:unregistered", {
98
+ appName: layer.appName,
99
+ resourceId: id,
100
+ });
101
+ }
102
+ getByApp(appName) {
103
+ return Array.from(this.layers.values()).filter((layer) => layer.appName === appName);
104
+ }
105
+ rebuildConfig() {
106
+ if (!this.baseConfig) {
107
+ return;
108
+ }
109
+ const rebuilt = Array.from(this.layers.values()).reduce((config, layer) => mergeConfigValues(config, layer.patch), cloneConfigValue(this.baseConfig));
110
+ const targetConfig = this.adminizer.config;
111
+ for (const key of Object.keys(targetConfig)) {
112
+ delete targetConfig[key];
113
+ }
114
+ Object.assign(this.adminizer.config, rebuilt);
115
+ }
116
+ getLayerId(appName, layerId) {
117
+ return `${appName}:${layerId}`;
118
+ }
119
+ }
@@ -0,0 +1,25 @@
1
+ import type { Adminizer } from "../Adminizer";
2
+ import type { AppController, AppControllerMethod } from "./AdminizerApp";
3
+ interface ControllerRecord {
4
+ id: string;
5
+ appName: string;
6
+ method: AppControllerMethod;
7
+ path: string;
8
+ enabled: boolean;
9
+ }
10
+ export declare class ControllerHandler {
11
+ private adminizer;
12
+ private controllers;
13
+ constructor(adminizer: Adminizer);
14
+ register(appName: string, controller: AppController): string;
15
+ disable(id: string): void;
16
+ enable(id: string): void;
17
+ unregister(id: string): void;
18
+ getByApp(appName: string): ControllerRecord[];
19
+ private getControllerId;
20
+ private resolveRoute;
21
+ private resolvePolicies;
22
+ private bindRoute;
23
+ private removeRoute;
24
+ }
25
+ export {};
@@ -0,0 +1,140 @@
1
+ import { bindWithMiddlewares } from "../../system/routePolicies.js";
2
+ import { requireAdmin, requireAnyPermission, requireAuthAPI, requireAuthEnabled, requireAuthUI, requirePermission, } from "../../policies/authPolicies.js";
3
+ export class ControllerHandler {
4
+ adminizer;
5
+ controllers = new Map();
6
+ constructor(adminizer) {
7
+ this.adminizer = adminizer;
8
+ }
9
+ register(appName, controller) {
10
+ const id = this.getControllerId(appName, controller);
11
+ if (this.controllers.has(id)) {
12
+ throw new Error(`Controller "${id}" is already registered`);
13
+ }
14
+ const fullPath = this.resolveRoute(controller.route);
15
+ const record = {
16
+ id,
17
+ appName,
18
+ method: controller.method,
19
+ path: fullPath,
20
+ enabled: true,
21
+ };
22
+ const middleware = bindWithMiddlewares(this.adminizer, this.adminizer.config.middlewares ?? [], (req, res, next) => {
23
+ if (!record.enabled) {
24
+ return next();
25
+ }
26
+ req.runtime = this.adminizer.appManager.createRuntime(appName);
27
+ return controller.middleware(req, res, next);
28
+ }, this.resolvePolicies(controller.policies));
29
+ this.bindRoute(controller.method, fullPath, middleware);
30
+ this.controllers.set(id, record);
31
+ this.adminizer.emitter.emit("app:controller:registered", {
32
+ appName,
33
+ resourceId: id,
34
+ route: fullPath,
35
+ method: controller.method,
36
+ policies: controller.policies ?? [],
37
+ });
38
+ return fullPath;
39
+ }
40
+ disable(id) {
41
+ const record = this.controllers.get(id);
42
+ if (!record) {
43
+ return;
44
+ }
45
+ record.enabled = false;
46
+ this.adminizer.emitter.emit("app:controller:disabled", {
47
+ appName: record.appName,
48
+ resourceId: id,
49
+ route: record.path,
50
+ method: record.method,
51
+ });
52
+ }
53
+ enable(id) {
54
+ const record = this.controllers.get(id);
55
+ if (!record) {
56
+ return;
57
+ }
58
+ record.enabled = true;
59
+ this.adminizer.emitter.emit("app:controller:enabled", {
60
+ appName: record.appName,
61
+ resourceId: id,
62
+ route: record.path,
63
+ method: record.method,
64
+ });
65
+ }
66
+ unregister(id) {
67
+ const record = this.controllers.get(id);
68
+ if (!record) {
69
+ return;
70
+ }
71
+ this.removeRoute(record.path, record.method);
72
+ this.controllers.delete(id);
73
+ this.adminizer.emitter.emit("app:controller:unregistered", {
74
+ appName: record.appName,
75
+ resourceId: id,
76
+ route: record.path,
77
+ method: record.method,
78
+ });
79
+ }
80
+ getByApp(appName) {
81
+ return Array.from(this.controllers.values()).filter((record) => record.appName === appName);
82
+ }
83
+ getControllerId(appName, controller) {
84
+ return `${appName}:${controller.id ?? `${controller.method}:${controller.route}`}`;
85
+ }
86
+ resolveRoute(route) {
87
+ const routePrefix = this.adminizer.config.routePrefix.replace(/\/+$/, "");
88
+ const routePath = route.startsWith("/") ? route : `/${route}`;
89
+ return `${routePrefix}${routePath}`;
90
+ }
91
+ resolvePolicies(policies = []) {
92
+ return policies.map((policy) => {
93
+ switch (policy.type) {
94
+ case "auth":
95
+ return policy.mode === "api" ? requireAuthAPI() : requireAuthUI();
96
+ case "auth-enabled":
97
+ return requireAuthEnabled();
98
+ case "admin":
99
+ return requireAdmin({ mode: policy.mode });
100
+ case "permission":
101
+ return requirePermission(policy.token, { mode: policy.mode });
102
+ case "any-permission":
103
+ return requireAnyPermission(policy.tokens, { mode: policy.mode });
104
+ }
105
+ });
106
+ }
107
+ bindRoute(method, route, middleware) {
108
+ switch (method) {
109
+ case "get":
110
+ this.adminizer.app.get(route, middleware);
111
+ break;
112
+ case "post":
113
+ this.adminizer.app.post(route, middleware);
114
+ break;
115
+ case "put":
116
+ this.adminizer.app.put(route, middleware);
117
+ break;
118
+ case "patch":
119
+ this.adminizer.app.patch(route, middleware);
120
+ break;
121
+ case "delete":
122
+ this.adminizer.app.delete(route, middleware);
123
+ break;
124
+ case "all":
125
+ this.adminizer.app.all(route, middleware);
126
+ break;
127
+ }
128
+ }
129
+ removeRoute(path, method) {
130
+ const app = this.adminizer.app;
131
+ const router = app.router ?? app._router;
132
+ if (!Array.isArray(router?.stack)) {
133
+ return;
134
+ }
135
+ const index = router.stack.findIndex((layer) => layer.route?.path === path && layer.route?.methods?.[method]);
136
+ if (index !== -1) {
137
+ router.stack.splice(index, 1);
138
+ }
139
+ }
140
+ }
@@ -1,5 +1,6 @@
1
1
  import { Adminizer } from "../Adminizer";
2
- import { StorageServices } from "./Navigation";
2
+ export interface CatalogStorageServices {
3
+ }
3
4
  /**
4
5
  * Interface `Item` describes the data that the UI will operate on
5
6
  * This is a common interface for all data that is linked to the catalog
@@ -8,7 +9,7 @@ import { StorageServices } from "./Navigation";
8
9
  export interface Item {
9
10
  id: string | number;
10
11
  name: string;
11
- parentId: string | number;
12
+ parentId: string | number | null;
12
13
  /**
13
14
  *
14
15
  */
@@ -21,11 +22,15 @@ export interface Item {
21
22
  export type _Item_ = {
22
23
  [key: string]: boolean | string | number | object;
23
24
  };
25
+ export interface CatalogTemplate<TData = any> {
26
+ type: string;
27
+ data: TData;
28
+ }
24
29
  /**
25
30
  * General Item structure that will be available for all elements, including groups
26
31
  */
27
32
  export declare abstract class BaseItem<T extends Item> {
28
- storageServices?: StorageServices;
33
+ storageServices?: CatalogStorageServices;
29
34
  abstract readonly type: string;
30
35
  /**
31
36
  * Used for infer T
@@ -91,10 +96,7 @@ export declare abstract class BaseItem<T extends Item> {
91
96
  * get add template
92
97
  * @param req
93
98
  */
94
- abstract getAddTemplate(req: ReqType): Promise<{
95
- type: 'component' | 'navigation.group' | 'navigation.link' | 'model' | 'model.link';
96
- data: any;
97
- }>;
99
+ abstract getAddTemplate(req: ReqType): Promise<CatalogTemplate>;
98
100
  /**
99
101
  * get edit template
100
102
  * @param id
@@ -102,10 +104,7 @@ export declare abstract class BaseItem<T extends Item> {
102
104
  * @param req
103
105
  * @param modelId
104
106
  */
105
- abstract getEditTemplate(id: string | number, catalogId: string, req: ReqType, modelId?: string | number): Promise<{
106
- type: 'component' | 'navigation.group' | 'navigation.link' | 'model' | 'model.link';
107
- data: any;
108
- }>;
107
+ abstract getEditTemplate(id: string | number, catalogId: string, req: ReqType, modelId?: string | number): Promise<CatalogTemplate>;
109
108
  _getChilds(parentId: string | number, catalogId: string, req?: ReqType): Promise<Item[]>;
110
109
  abstract getChilds(parentId: string | number, catalogId: string, req?: ReqType): Promise<Item[]>;
111
110
  abstract search(s: string, catalogId: string, req?: ReqType): Promise<T[]>;
@@ -205,7 +204,22 @@ export declare abstract class AbstractCatalog {
205
204
  * if pass null as parentId this root
206
205
  */
207
206
  getChilds(parentId: string | number, byItemType?: string, req?: ReqType): Promise<Item[]>;
207
+ /**
208
+ * Registers the catalog access right through the legacy Adminizer API.
209
+ *
210
+ * @deprecated Starting with Adminizer v6, register access rights through
211
+ * `ctx.accessRight(...)` in the app's `setup` method.
212
+ * @param adminizer Adminizer instance used for legacy access-right registration.
213
+ */
208
214
  private _bindAccessRight;
215
+ /**
216
+ * @deprecated The `adminizer` parameter is deprecated and will be removed in
217
+ * Adminizer v6. Register the catalog through `AppManager` using
218
+ * `ctx.catalog(...)`, and register its access rights using
219
+ * `ctx.accessRight(...)`.
220
+ * @param adminizer Adminizer instance used by the legacy registration flow.
221
+ * @param items Catalog item types.
222
+ */
209
223
  protected constructor(adminizer: Adminizer, items: BaseItem<any>[]);
210
224
  setId(id: string): void;
211
225
  /**
@@ -214,6 +228,7 @@ export declare abstract class AbstractCatalog {
214
228
  */
215
229
  getIdList(): Promise<string[]>;
216
230
  getItemType(type: string): BaseItem<Item>;
231
+ private requireItemType;
217
232
  getGroupType(): BaseItem<Item>;
218
233
  additemTypes<T extends BaseItem<any>>(itemType: T): void;
219
234
  /**
@@ -231,19 +246,13 @@ export declare abstract class AbstractCatalog {
231
246
  * @param req
232
247
  * @param modelId
233
248
  */
234
- getEditTemplate(item: Item, id: string | number, req: ReqType, modelId?: string | number): Promise<{
235
- type: "component" | "navigation.group" | "navigation.link" | "model" | "model.link";
236
- data: any;
237
- }>;
249
+ getEditTemplate(item: Item, id: string | number, req: ReqType, modelId?: string | number): Promise<CatalogTemplate<any>>;
238
250
  /**
239
251
  * Get add template from an item type
240
252
  * @param item
241
253
  * @param req
242
254
  */
243
- getAddTemplate(item: Item, req: ReqType): Promise<{
244
- type: "component" | "navigation.group" | "navigation.link" | "model" | "model.link";
245
- data: any;
246
- }>;
255
+ getAddTemplate(item: Item, req: ReqType): Promise<CatalogTemplate<any>>;
247
256
  addActionHandler(actionHandler: ActionHandler): void;
248
257
  /**
249
258
  * Method for getting group elements
@@ -98,6 +98,13 @@ export class AbstractCatalog {
98
98
  return result.sort((a, b) => a.sortOrder - b.sortOrder);
99
99
  }
100
100
  }
101
+ /**
102
+ * Registers the catalog access right through the legacy Adminizer API.
103
+ *
104
+ * @deprecated Starting with Adminizer v6, register access rights through
105
+ * `ctx.accessRight(...)` in the app's `setup` method.
106
+ * @param adminizer Adminizer instance used for legacy access-right registration.
107
+ */
101
108
  _bindAccessRight(adminizer) {
102
109
  setTimeout(() => {
103
110
  const postfix = this.id ? `${this.slug}-${this.id}` : `${this.slug}`;
@@ -109,6 +116,14 @@ export class AbstractCatalog {
109
116
  });
110
117
  }, 100);
111
118
  }
119
+ /**
120
+ * @deprecated The `adminizer` parameter is deprecated and will be removed in
121
+ * Adminizer v6. Register the catalog through `AppManager` using
122
+ * `ctx.catalog(...)`, and register its access rights using
123
+ * `ctx.accessRight(...)`.
124
+ * @param adminizer Adminizer instance used by the legacy registration flow.
125
+ * @param items Catalog item types.
126
+ */
112
127
  constructor(adminizer, items) {
113
128
  for (const item of items) {
114
129
  this.additemTypes(item);
@@ -128,6 +143,13 @@ export class AbstractCatalog {
128
143
  getItemType(type) {
129
144
  return this.itemTypes.find((it) => it.type === type);
130
145
  }
146
+ requireItemType(type) {
147
+ const itemType = this.getItemType(type);
148
+ if (!itemType) {
149
+ throw new Error(`Catalog item type \`${String(type)}\` was not found in catalog \`${this.slug}\``);
150
+ }
151
+ return itemType;
152
+ }
131
153
  getGroupType() {
132
154
  return this.itemTypes.find((it) => it.isGroup === true);
133
155
  }
@@ -142,13 +164,13 @@ export class AbstractCatalog {
142
164
  * Get an element
143
165
  */
144
166
  async find(item, req) {
145
- return await this.getItemType(item.type)?._find(item.id, this.id, req);
167
+ return await this.requireItemType(item.type)._find(item.id, this.id, req);
146
168
  }
147
169
  /**
148
170
  * Removing an element
149
171
  */
150
172
  async deleteItem(type, id, req) {
151
- await this.getItemType(type)?.deleteItem(id, this.id, req);
173
+ await this.requireItemType(type).deleteItem(id, this.id, req);
152
174
  }
153
175
  /**
154
176
  * Get edit template from an item type
@@ -158,7 +180,7 @@ export class AbstractCatalog {
158
180
  * @param modelId
159
181
  */
160
182
  getEditTemplate(item, id, req, modelId) {
161
- return this.getItemType(item.type)?.getEditTemplate(id, this.id, req, modelId);
183
+ return this.requireItemType(item.type).getEditTemplate(id, this.id, req, modelId);
162
184
  }
163
185
  /**
164
186
  * Get add template from an item type
@@ -166,7 +188,7 @@ export class AbstractCatalog {
166
188
  * @param req
167
189
  */
168
190
  getAddTemplate(item, req) {
169
- return this.getItemType(item.type)?.getAddTemplate(req);
191
+ return this.requireItemType(item.type).getAddTemplate(req);
170
192
  }
171
193
  addActionHandler(actionHandler) {
172
194
  if (actionHandler.selectedItemTypes.length > 0) {
@@ -232,12 +254,18 @@ export class AbstractCatalog {
232
254
  * @param req
233
255
  */
234
256
  async createItem(data, req) {
235
- const promise = this.getItemType(data.type)?.create(data, this.id, req);
236
- return await promise;
257
+ const result = await this.requireItemType(data.type).create(data, this.id, req);
258
+ if (!result) {
259
+ throw new Error(`Catalog item type \`${data.type}\` did not return created item`);
260
+ }
261
+ return result;
237
262
  }
238
263
  async updateItem(id, type, data, req) {
239
- const promise = this.getItemType(type)?.update(id, data, this.id, req);
240
- return await promise;
264
+ const result = await this.requireItemType(type).update(id, data, this.id, req);
265
+ if (!result) {
266
+ throw new Error(`Catalog item type \`${type}\` did not return updated item`);
267
+ }
268
+ return result;
241
269
  }
242
270
  /**
243
271
  * To update all items in the tree after updating the model
@@ -247,8 +275,11 @@ export class AbstractCatalog {
247
275
  * @param req
248
276
  */
249
277
  async updateModelItems(modelId, type, data, req) {
250
- const promise = this.getItemType(type)?.updateModelItems(modelId, data, this.id, req);
251
- return await promise;
278
+ const result = await this.requireItemType(type).updateModelItems(modelId, data, this.id, req);
279
+ if (!result) {
280
+ throw new Error(`Catalog item type \`${type}\` did not return updated model item`);
281
+ }
282
+ return result;
252
283
  }
253
284
  /**
254
285
  * Method for getting group elements
@@ -1,7 +1,20 @@
1
1
  import { AbstractCatalog } from "./AbstractCatalog";
2
+ export interface CatalogRecord {
3
+ id: string;
4
+ appName: string;
5
+ catalog: AbstractCatalog;
6
+ enabled: boolean;
7
+ }
2
8
  export declare class CatalogHandler {
3
9
  private catalog;
10
+ private records;
4
11
  add(catalog: AbstractCatalog): AbstractCatalog;
5
12
  getAll(): AbstractCatalog[];
6
13
  getCatalog(slug: string): AbstractCatalog;
14
+ register(appName: string, catalog: AbstractCatalog): string;
15
+ unregister(id: string): void;
16
+ disable(id: string): void;
17
+ enable(id: string): void;
18
+ getByApp(appName: string): CatalogRecord[];
19
+ private getRecordId;
7
20
  }
@@ -1,13 +1,59 @@
1
1
  export class CatalogHandler {
2
2
  catalog = [];
3
+ records = new Map();
3
4
  add(catalog) {
4
5
  this.catalog.push(catalog);
5
6
  return catalog;
6
7
  }
7
8
  getAll() {
8
- return this.catalog;
9
+ return [
10
+ ...this.catalog,
11
+ ...Array.from(this.records.values())
12
+ .filter((record) => record.enabled)
13
+ .map((record) => record.catalog)
14
+ ];
9
15
  }
10
16
  getCatalog(slug) {
11
- return this.catalog.find((catalog) => catalog.slug === slug);
17
+ return this.getAll().find((catalog) => catalog.slug === slug);
18
+ }
19
+ register(appName, catalog) {
20
+ const id = this.getRecordId(appName, catalog);
21
+ if (this.records.has(id)) {
22
+ throw new Error(`Catalog "${id}" is already registered`);
23
+ }
24
+ const existingCatalog = this.getCatalog(catalog.slug);
25
+ if (existingCatalog) {
26
+ throw new Error(`Catalog with slug "${catalog.slug}" is already registered`);
27
+ }
28
+ this.records.set(id, {
29
+ id,
30
+ appName,
31
+ catalog,
32
+ enabled: true,
33
+ });
34
+ return id;
35
+ }
36
+ unregister(id) {
37
+ this.records.delete(id);
38
+ }
39
+ disable(id) {
40
+ const record = this.records.get(id);
41
+ if (!record) {
42
+ return;
43
+ }
44
+ record.enabled = false;
45
+ }
46
+ enable(id) {
47
+ const record = this.records.get(id);
48
+ if (!record) {
49
+ return;
50
+ }
51
+ record.enabled = true;
52
+ }
53
+ getByApp(appName) {
54
+ return Array.from(this.records.values()).filter((record) => record.appName === appName);
55
+ }
56
+ getRecordId(appName, catalog) {
57
+ return `${appName}:${catalog.slug}`;
12
58
  }
13
59
  }
@@ -0,0 +1,23 @@
1
+ export interface CatalogTemplateComponentResource {
2
+ id: string;
3
+ type: string;
4
+ component: string;
5
+ exportName?: string;
6
+ }
7
+ export interface CatalogTemplateComponentRecord extends CatalogTemplateComponentResource {
8
+ id: string;
9
+ appName: string;
10
+ catalog: string;
11
+ enabled: boolean;
12
+ }
13
+ export declare class CatalogTemplateComponentHandler {
14
+ private records;
15
+ register(appName: string, catalog: string, resource: CatalogTemplateComponentResource): string;
16
+ unregister(id: string): void;
17
+ disable(id: string): void;
18
+ enable(id: string): void;
19
+ getAll(): CatalogTemplateComponentRecord[];
20
+ getByApp(appName: string): CatalogTemplateComponentRecord[];
21
+ getByCatalog(catalog: string): CatalogTemplateComponentRecord[];
22
+ getByType(type: string, catalog: string): CatalogTemplateComponentRecord | undefined;
23
+ }
@@ -0,0 +1,59 @@
1
+ function normalizeType(type) {
2
+ return type.toLowerCase();
3
+ }
4
+ function normalizeCatalog(catalog) {
5
+ return catalog.toLowerCase();
6
+ }
7
+ export class CatalogTemplateComponentHandler {
8
+ records = new Map();
9
+ register(appName, catalog, resource) {
10
+ const normalizedCatalog = normalizeCatalog(catalog);
11
+ const id = `${appName}:${normalizedCatalog}:${resource.id}`;
12
+ if (this.records.has(id)) {
13
+ throw new Error(`Catalog template component "${id}" is already registered`);
14
+ }
15
+ const existing = this.getByType(resource.type, normalizedCatalog);
16
+ if (existing) {
17
+ throw new Error(`Catalog template component for type "${resource.type}" is already registered in catalog "${normalizedCatalog}"`);
18
+ }
19
+ this.records.set(id, {
20
+ ...resource,
21
+ id,
22
+ appName,
23
+ type: normalizeType(resource.type),
24
+ catalog: normalizedCatalog,
25
+ enabled: true,
26
+ });
27
+ return id;
28
+ }
29
+ unregister(id) {
30
+ this.records.delete(id);
31
+ }
32
+ disable(id) {
33
+ const record = this.records.get(id);
34
+ if (record) {
35
+ record.enabled = false;
36
+ }
37
+ }
38
+ enable(id) {
39
+ const record = this.records.get(id);
40
+ if (record) {
41
+ record.enabled = true;
42
+ }
43
+ }
44
+ getAll() {
45
+ return Array.from(this.records.values()).filter((record) => record.enabled);
46
+ }
47
+ getByApp(appName) {
48
+ return Array.from(this.records.values()).filter((record) => record.appName === appName);
49
+ }
50
+ getByCatalog(catalog) {
51
+ const normalizedCatalog = normalizeCatalog(catalog);
52
+ return this.getAll().filter((record) => record.catalog === normalizedCatalog);
53
+ }
54
+ getByType(type, catalog) {
55
+ const normalizedType = normalizeType(type);
56
+ const normalizedCatalog = normalizeCatalog(catalog);
57
+ return this.getAll().find((record) => record.type === normalizedType && record.catalog === normalizedCatalog);
58
+ }
59
+ }
@@ -0,0 +1,17 @@
1
+ export type ControlType = 'wysiwyg' | 'jsonEditor' | 'geoJson' | 'markdown' | 'table' | 'codeEditor';
2
+ export interface Path {
3
+ jsPath: {
4
+ dev: string;
5
+ production: string;
6
+ };
7
+ cssPath: string;
8
+ }
9
+ export type Config = Record<string, string | string[] | object | number | boolean>;
10
+ export interface Control {
11
+ readonly name: string;
12
+ readonly type: ControlType;
13
+ getConfig(): Config | undefined;
14
+ getJsPath(): string | undefined;
15
+ getCssPath(): string | undefined;
16
+ getName(): string;
17
+ }