adminizer 4.1.0-commit.d8a06d3 → 4.1.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 (253) hide show
  1. package/Readme.md +46 -0
  2. package/assets/{VanillaJSONEditor-D-Lx670g.js → VanillaJSONEditor-DfRefswH.js} +104 -104
  3. package/assets/add-CJ1-zeA1.js +1 -0
  4. package/assets/add-form-CbNl0wdS.js +1 -0
  5. package/assets/add-group-form-Bt_Dx9wm.js +1 -0
  6. package/assets/add-group-pIFJV5qL.js +1 -0
  7. package/assets/add-user-D2US8hL_.js +1 -0
  8. package/assets/add-user-form-Bt8Jy6S2.js +1 -0
  9. package/assets/{app-WTooYWC3.css → app-B6cCPfWk.css} +1 -1
  10. package/assets/app-layout-B86jl9bH.js +1 -0
  11. package/assets/app-shell-CiGyzQ0C.js +1 -0
  12. package/assets/app-sidebar-Bz-SRwBg.js +1 -0
  13. package/assets/app-sidebar-header-7CNCx7Rs.js +11 -0
  14. package/assets/app.js +45 -37
  15. package/assets/breadcrumbs-_jhtTcOi.js +1 -0
  16. package/assets/catalog-CON6moaA.js +16 -0
  17. package/assets/catalog-Cc6Mk9sX.css +1 -0
  18. package/assets/checkbox-CQdZw5mb.js +1 -0
  19. package/assets/dashboard-es9ZT8qk.js +3 -0
  20. package/assets/{date-picker-DI1cCO7K.js → date-picker-Dz-d-YWX.js} +2 -2
  21. package/assets/debounce-qdyXyOeG.js +1 -0
  22. package/assets/del-modal-D0mrZvki.js +11 -0
  23. package/assets/dialog-stack-BiMbfm58.js +1 -0
  24. package/assets/dropdown-menu-BSBcRiXx.js +1 -0
  25. package/assets/{field-renderer-DVHZF6HS.js → field-renderer-B6hFAeiU.js} +3 -3
  26. package/assets/form-Buslty7y.js +1 -0
  27. package/assets/form-aqiRmPix.js +1 -0
  28. package/assets/{geo-json-BjiyTtMu.js → geo-json-BKmYmu3d.js} +2 -2
  29. package/assets/{handsontable-4mjU_b0n.js → handsontable-B8xVeMAQ.js} +5 -5
  30. package/assets/home-Dr72Jk-w.js +2 -0
  31. package/assets/icon-B-a7xg54.js +1 -0
  32. package/assets/index-B68_akQe.js +1 -0
  33. package/assets/index-B7-xTDyy.js +1 -0
  34. package/assets/index-BJFFlCSo.js +1 -0
  35. package/assets/{index-Cw5o84pO.js → index-BOuMo_nl.js} +3 -3
  36. package/assets/index-BzOcGsBq.js +1 -0
  37. package/assets/index-CFbQ2Rv0.js +1 -0
  38. package/assets/{index-D5ir9iUV.js → index-Cq31rrfZ.js} +1 -1
  39. package/assets/{index-Cgp8OfuI.js → index-D5UDXTFs.js} +1 -1
  40. package/assets/index-oxIQWAdI.js +41 -0
  41. package/assets/init-user-5H689LP0.js +1 -0
  42. package/assets/input-CSJjrf2i.js +1 -0
  43. package/assets/input-error-CK92Shhm.js +1 -0
  44. package/assets/label-Muj0-Efy.js +1 -0
  45. package/assets/list-Cvh7zbyG.js +1 -0
  46. package/assets/list-table-Bs_vbQiV.js +52 -0
  47. package/assets/login-DliJrjMQ.js +6 -0
  48. package/assets/manifest.json +575 -673
  49. package/assets/material-icon-BRS58Qpk.js +1 -0
  50. package/assets/module-CjG21VCT.js +1 -0
  51. package/assets/{monaco-editor-CJs0_GlD.js → monaco-editor-9fDiyfuW.js} +2 -2
  52. package/assets/{multi-select-BvRpAW8r.js → multi-select-CMQIJ0JT.js} +2 -2
  53. package/assets/nav-footer-IGMn9NiE.js +1 -0
  54. package/assets/nav-main-DBE4rMiZ.js +1 -0
  55. package/assets/nav-user-CjyLRyq-.js +1 -0
  56. package/assets/pagination-render-DUAq2klc.js +1 -0
  57. package/assets/popover-C_cww-4_.js +1 -0
  58. package/assets/register-UzQn3J0g.js +1 -0
  59. package/assets/{select-BWepUw-9.js → select-DzBno-dc.js} +2 -2
  60. package/assets/{sidebar-CAHsHdjM.js → sidebar-Dc4iqfu-.js} +2 -2
  61. package/assets/skeleton-Dkmj2o2Z.js +1 -0
  62. package/assets/sonner-De1t71Gj.js +1 -0
  63. package/assets/{toast-editor-CMK7QtF1.js → toast-editor-1Pul3oMs.js} +2 -2
  64. package/assets/tooltip-CwPrC-HD.js +1 -0
  65. package/assets/use-appearance-J8J2w43p.js +1 -0
  66. package/assets/use-window-size-DLSEoR6e.js +1 -0
  67. package/assets/{user-info-DFrmpJ4y.js → user-info-8RyDk7qh.js} +2 -2
  68. package/assets/user-menu-content-CpxTLH56.js +6 -0
  69. package/assets/welcome-BYKI6yO-.js +1 -0
  70. package/controllers/add.js +8 -8
  71. package/controllers/catalog/Catalog.d.ts +1 -1
  72. package/controllers/catalog/Catalog.js +40 -35
  73. package/controllers/catalog/FrontentCatalogAdapter.d.ts +36 -26
  74. package/controllers/catalog/FrontentCatalogAdapter.js +71 -72
  75. package/controllers/edit.js +8 -11
  76. package/controllers/list.js +2 -2
  77. package/controllers/login.js +16 -7
  78. package/controllers/navigation/edit.js +1 -1
  79. package/controllers/remove.js +1 -1
  80. package/controllers/view.js +1 -1
  81. package/helpers/JsUtils.d.ts +1 -0
  82. package/helpers/JsUtils.js +3 -0
  83. package/helpers/accessRightsHelper.d.ts +3 -0
  84. package/helpers/accessRightsHelper.js +27 -4
  85. package/helpers/controllerHelper.js +39 -18
  86. package/helpers/fieldsHelper.d.ts +3 -2
  87. package/helpers/fieldsHelper.js +5 -1
  88. package/helpers/inertiaAddHelper.d.ts +4 -5
  89. package/helpers/inertiaAddHelper.js +25 -7
  90. package/helpers/inertiaFromHelper.js +1 -1
  91. package/helpers/inertiaMenuHelper.d.ts +1 -1
  92. package/helpers/inertiaMenuHelper.js +1 -1
  93. package/helpers/menuHelper.d.ts +8 -3
  94. package/helpers/menuHelper.js +26 -17
  95. package/index.d.ts +2 -6
  96. package/index.js +5 -6
  97. package/interfaces/adminpanelConfig.d.ts +35 -30
  98. package/interfaces/global.d.ts +5 -2
  99. package/interfaces/types.d.ts +1 -1
  100. package/lib/Adminizer.d.ts +9 -3
  101. package/lib/Adminizer.js +32 -16
  102. package/lib/media-manager/Items.js +0 -3
  103. package/lib/requestProcessor.js +10 -3
  104. package/lib/v4/DataAccessor.d.ts +3 -1
  105. package/lib/v4/DataAccessor.js +43 -18
  106. package/lib/v4/I18n.js +2 -0
  107. package/lib/{catalog → v4/catalog}/AbstractCatalog.d.ts +89 -60
  108. package/lib/{catalog → v4/catalog}/AbstractCatalog.js +59 -54
  109. package/lib/v4/catalog/Navigation.d.ts +43 -0
  110. package/lib/v4/catalog/Navigation.js +457 -0
  111. package/lib/{controls → v4/controls}/AbstractControls.d.ts +1 -1
  112. package/lib/{controls → v4/controls}/codeEditor/MonacoEditor.d.ts +1 -1
  113. package/lib/{controls → v4/controls}/geojsoneditor/GeoEditor.d.ts +1 -1
  114. package/lib/{controls → v4/controls}/jsoneditor/JsonEditor.d.ts +1 -1
  115. package/lib/{controls → v4/controls}/markdown/ToastUiEditor.d.ts +1 -1
  116. package/lib/{controls → v4/controls}/table/Handsontable.d.ts +1 -1
  117. package/lib/{controls → v4/controls}/wysiwyg/CKeditor.d.ts +1 -1
  118. package/lib/{datatable → v4/datatable}/NodeTable.d.ts +3 -3
  119. package/lib/{datatable → v4/datatable}/NodeTable.js +8 -5
  120. package/lib/v4/model/AbstractModel.d.ts +5 -1
  121. package/lib/v4/model/AbstractModel.js +2 -1
  122. package/lib/v4/model/ModelHandler.js +1 -3
  123. package/lib/v4/model/adapter/sequelize.d.ts +8 -0
  124. package/lib/v4/model/adapter/sequelize.js +274 -133
  125. package/lib/v4/model/adapter/waterline.js +5 -2
  126. package/lib/{widgets → v4/widgets}/abstractLink.d.ts +1 -1
  127. package/lib/{widgets → v4/widgets}/abstractWidgetBase.d.ts +1 -1
  128. package/lib/{widgets → v4/widgets}/widgetHandler.d.ts +11 -4
  129. package/lib/{widgets → v4/widgets}/widgetHandler.js +1 -1
  130. package/models/NavigationAP.d.ts +2 -3
  131. package/models/NavigationAP.js +5 -6
  132. package/models/UserAP.d.ts +2 -3
  133. package/package.json +17 -6
  134. package/system/Router.js +8 -11
  135. package/system/bindAccessRights.js +0 -4
  136. package/system/bindControls.js +6 -6
  137. package/system/bindDev.js +1 -0
  138. package/system/bindInertia.js +9 -4
  139. package/system/bindMediaManager.js +0 -1
  140. package/system/bindModels.js +9 -6
  141. package/system/bindNavigation.d.ts +2 -0
  142. package/system/bindNavigation.js +42 -42
  143. package/system/bindReqFunctions.js +0 -1
  144. package/system/defaults.js +13 -6
  145. package/translations/ar.json +70 -1
  146. package/translations/cn.json +70 -1
  147. package/translations/de.json +71 -3
  148. package/translations/en.json +70 -102
  149. package/translations/es.json +70 -1
  150. package/translations/fr.json +70 -1
  151. package/translations/hi.json +70 -1
  152. package/translations/jp.json +70 -1
  153. package/translations/ko.json +70 -1
  154. package/translations/pt.json +70 -1
  155. package/translations/ru.json +71 -103
  156. package/translations/ua.json +70 -1
  157. package/translations/uz.json +72 -0
  158. package/translations/vi.json +70 -1
  159. package/assets/add-BP_u3Tjl.js +0 -1
  160. package/assets/add-form-nffmiYTh.js +0 -1
  161. package/assets/add-group-D4vcHlm-.js +0 -1
  162. package/assets/add-group-form-gNJW11-q.js +0 -1
  163. package/assets/add-user-DWh3Nas0.js +0 -1
  164. package/assets/add-user-form-BJ0FsZYJ.js +0 -1
  165. package/assets/app-layout-DYsRFUuP.js +0 -1
  166. package/assets/app-shell-Dd9Eknik.js +0 -1
  167. package/assets/app-sidebar-BOmu6-Sl.js +0 -1
  168. package/assets/app-sidebar-header-CoXSzWxk.js +0 -11
  169. package/assets/breadcrumbs-BmAq4fHT.js +0 -1
  170. package/assets/button-C9B_5Jf_.js +0 -1
  171. package/assets/checkbox-Fg27sL_1.js +0 -1
  172. package/assets/compiler-runtime-hB6dAw2d.js +0 -9
  173. package/assets/dashboard-BACj996r.js +0 -3
  174. package/assets/dropdown-menu-Bhj17ENm.js +0 -1
  175. package/assets/form-BgWdwvz1.js +0 -1
  176. package/assets/form-DgtErfln.js +0 -1
  177. package/assets/home-CHntBHJa.js +0 -2
  178. package/assets/icon-Dt0vBgDO.js +0 -1
  179. package/assets/index-B8BS9wMC.js +0 -1
  180. package/assets/index-BC0yfOHo.js +0 -1
  181. package/assets/index-BKCgnGj_.js +0 -1
  182. package/assets/index-BbXEMx9n.js +0 -1
  183. package/assets/index-BykbU6Ee.js +0 -41
  184. package/assets/index-CaJgc5EZ.js +0 -1
  185. package/assets/index-DrWfGwtf.js +0 -1
  186. package/assets/init-user-JfCKJ5Ce.js +0 -1
  187. package/assets/input-CvRbIbk4.js +0 -1
  188. package/assets/input-error-DMK7cAt7.js +0 -1
  189. package/assets/label-CSLFe9Bz.js +0 -1
  190. package/assets/list-B2Oa5O_Q.js +0 -1
  191. package/assets/list-table-DA9MhywL.js +0 -62
  192. package/assets/login-DQwGtdis.js +0 -6
  193. package/assets/material-icon-BJg8o_fs.js +0 -1
  194. package/assets/module-DWXp59Vg.js +0 -1
  195. package/assets/nav-footer-Bs4dmN1d.js +0 -1
  196. package/assets/nav-main-Bq3IMk4C.js +0 -1
  197. package/assets/nav-user-CbB22J5O.js +0 -1
  198. package/assets/pagination-render-DuXDDbC_.js +0 -1
  199. package/assets/popover-DtoGI2b1.js +0 -1
  200. package/assets/register-BSogVF0h.js +0 -1
  201. package/assets/skeleton-COOcAA8f.js +0 -1
  202. package/assets/sonner-BI0IFOQN.js +0 -1
  203. package/assets/tooltip-DHwpLKOI.js +0 -1
  204. package/assets/use-appearance-DRfIqTgw.js +0 -1
  205. package/assets/use-window-size-h0Sh_NvX.js +0 -1
  206. package/assets/user-menu-content-DPXQdERj.js +0 -6
  207. package/assets/utils-DjqsqOe8.js +0 -1
  208. package/assets/welcome-B4WCIXKf.js +0 -1
  209. package/controllers/processInstallFinalize.d.ts +0 -1
  210. package/controllers/processInstallFinalize.js +0 -16
  211. package/controllers/processInstallStep.d.ts +0 -0
  212. package/controllers/processInstallStep.js +0 -122
  213. package/lib/catalog/Navigation.d.ts +0 -0
  214. package/lib/catalog/Navigation.js +0 -532
  215. package/lib/installStepper/InstallStepAbstract.d.ts +0 -52
  216. package/lib/installStepper/InstallStepAbstract.js +0 -69
  217. package/lib/installStepper/finalizeStep.d.ts +0 -21
  218. package/lib/installStepper/finalizeStep.js +0 -48
  219. package/lib/installStepper/installStepper.d.ts +0 -40
  220. package/lib/installStepper/installStepper.js +0 -195
  221. package/models/MediaManagerAP.d.ts +0 -62
  222. package/models/MediaManagerAP.js +0 -45
  223. package/models/MediaManagerAssociationsAP.d.ts +0 -38
  224. package/models/MediaManagerAssociationsAP.js +0 -27
  225. package/models/MediaManagerMetaAP.d.ts +0 -30
  226. package/models/MediaManagerMetaAP.js +0 -21
  227. package/system/bindInstallStepper.d.ts +0 -2
  228. package/system/bindInstallStepper.js +0 -23
  229. /package/lib/{catalog → v4/catalog}/CatalogHandler.d.ts +0 -0
  230. /package/lib/{catalog → v4/catalog}/CatalogHandler.js +0 -0
  231. /package/lib/{controls → v4/controls}/AbstractControls.js +0 -0
  232. /package/lib/{controls → v4/controls}/ControlsHandler.d.ts +0 -0
  233. /package/lib/{controls → v4/controls}/ControlsHandler.js +0 -0
  234. /package/lib/{controls → v4/controls}/codeEditor/MonacoEditor.js +0 -0
  235. /package/lib/{controls → v4/controls}/geojsoneditor/GeoEditor.js +0 -0
  236. /package/lib/{controls → v4/controls}/jsoneditor/JsonEditor.js +0 -0
  237. /package/lib/{controls → v4/controls}/markdown/ToastUiEditor.js +0 -0
  238. /package/lib/{controls → v4/controls}/table/Handsontable.js +0 -0
  239. /package/lib/{controls → v4/controls}/wysiwyg/CKeditor.js +0 -0
  240. /package/lib/{inertia → v4/inertia}/flash.d.ts +0 -0
  241. /package/lib/{inertia → v4/inertia}/flash.js +0 -0
  242. /package/lib/{inertia → v4/inertia}/inertiaAdapter.d.ts +0 -0
  243. /package/lib/{inertia → v4/inertia}/inertiaAdapter.js +0 -0
  244. /package/lib/{widgets → v4/widgets}/abstractAction.d.ts +0 -0
  245. /package/lib/{widgets → v4/widgets}/abstractAction.js +0 -0
  246. /package/lib/{widgets → v4/widgets}/abstractCustom.d.ts +0 -0
  247. /package/lib/{widgets → v4/widgets}/abstractCustom.js +0 -0
  248. /package/lib/{widgets → v4/widgets}/abstractInfo.d.ts +0 -0
  249. /package/lib/{widgets → v4/widgets}/abstractInfo.js +0 -0
  250. /package/lib/{widgets → v4/widgets}/abstractLink.js +0 -0
  251. /package/lib/{widgets → v4/widgets}/abstractSwitch.d.ts +0 -0
  252. /package/lib/{widgets → v4/widgets}/abstractSwitch.js +0 -0
  253. /package/lib/{widgets → v4/widgets}/abstractWidgetBase.js +0 -0
package/lib/Adminizer.js CHANGED
@@ -3,13 +3,12 @@ import cookieParser from 'cookie-parser';
3
3
  import * as path from "path";
4
4
  import winston from "winston";
5
5
  import EventEmitter from 'events';
6
- import chalk from 'chalk';
7
6
  import PolicyManager from "./v4/PolicyManager";
8
7
  import Router from "./../system/Router";
9
8
  import bindAssets from "../system/bindAssets";
10
9
  import bindDev from "../system/bindDev";
11
10
  import bindDashboardWidgets from "../system/bindDashboardWidgets";
12
- // import bindNavigation from "../system/bindNavigation";
11
+ import bindNavigation from "../system/bindNavigation";
13
12
  // import bindMediaManager from "../system/bindMediaManager";
14
13
  import bindAccessRights from "../system/bindAccessRights";
15
14
  import bindAuthorization from "../system/bindAuthorization";
@@ -17,20 +16,26 @@ import bindModels from "../system/bindModels";
17
16
  import bindForms from "../system/bindForms";
18
17
  import bindTranslations from "../system/bindTranslations";
19
18
  import { ModelHandler } from "./v4/model/ModelHandler";
20
- import { WidgetHandler } from "./widgets/widgetHandler";
19
+ import { WidgetHandler } from "./v4/widgets/widgetHandler";
21
20
  import { AccessRightsHelper } from "../helpers/accessRightsHelper";
22
21
  import bindReqFunctions from "../system/bindReqFunctions";
23
22
  import { ConfigHelper } from "../helpers/configHelper";
24
23
  import { I18n } from "./v4/I18n";
25
24
  import { getDefaultConfig } from "../system/defaults";
26
25
  import bindExpressUtils from "../system/bindExpressUtils";
27
- import { createServer as createViteServer } from 'vite';
28
26
  import { bindInertia } from "../system/bindInertia";
29
27
  import { MenuHelper } from "../helpers/menuHelper";
30
28
  import { bindControls } from "../system/bindControls";
31
- import { ControlsHandler } from "./controls/ControlsHandler";
29
+ import { ControlsHandler } from "./v4/controls/ControlsHandler";
32
30
  import { v4 as uuid } from "uuid";
33
31
  export class Adminizer {
32
+ // Preconfigures
33
+ /**
34
+ * If you convey this default Middleware, it will add it to the very top of the router,
35
+ * and will contact each request
36
+ */
37
+ defaultMiddleware;
38
+ // Instances
34
39
  app;
35
40
  config;
36
41
  _emitter;
@@ -43,9 +48,10 @@ export class Adminizer {
43
48
  widgetHandler;
44
49
  vite;
45
50
  controlsHandler;
51
+ // Constants
46
52
  jwtSecret = process.env.JWT_SECRET ?? uuid();
47
53
  static logger = winston.createLogger({
48
- level: "info",
54
+ level: process.env.LOG_LEVEL ?? "debug",
49
55
  format: winston.format.combine(winston.format.timestamp(), winston.format.printf(({ timestamp, level, message, ...meta }) => {
50
56
  const metaString = Object.keys(meta).length ? JSON.stringify(meta) : "";
51
57
  return `[${timestamp}] ${level.toUpperCase()}: ${message} ${metaString}`;
@@ -80,19 +86,23 @@ export class Adminizer {
80
86
  * @protected
81
87
  */
82
88
  async viteMiddleware() {
83
- // Create a Vite server in middleware mode
89
+ const { createServer: createViteServer } = await import('vite');
90
+ const chalk = (await import('chalk')).default;
84
91
  this.vite = await createViteServer({
85
- server: { middlewareMode: true }, // Enable middleware mode
86
- appType: 'custom', // Specify the application type
92
+ server: { middlewareMode: true },
93
+ appType: 'custom',
87
94
  });
88
- // Use Vite Middleware
89
95
  this.app.use(this.vite.middlewares);
96
+ // eslint-disable-next-line no-console
90
97
  console.log(chalk.green.bold('Vite is running in development mode!') +
91
98
  chalk.blue('\nAccess your app at http://localhost:3000'));
92
99
  }
93
100
  async init(config) {
94
101
  // set cookie parser
95
102
  this.app.use(cookieParser());
103
+ if (!config || Object.keys(config).length === 0) {
104
+ Adminizer.log.warn(`Adminizer init > Adminizer config is emtpy`);
105
+ }
96
106
  // Set vite middleware
97
107
  const isViteDev = process.env.VITE_ENV === "dev";
98
108
  if (isViteDev)
@@ -123,26 +133,29 @@ export class Adminizer {
123
133
  }
124
134
  };
125
135
  this.modelHandler = new ModelHandler();
136
+ // TODO: 'hot reload' unbind models & unbind forms
126
137
  await bindModels(this);
127
138
  await bindForms(this);
128
139
  this.config.rootPath = path.resolve(import.meta.dirname + "/..");
129
140
  this.policyManager = new PolicyManager(this);
130
141
  await this.policyManager.loadPolicies();
142
+ // TODO: 'hot reload' problem with deleting access right tokens
131
143
  this.accessRightsHelper = new AccessRightsHelper(this);
144
+ // Helpers go to construtor
132
145
  this.configHelper = new ConfigHelper(this);
133
146
  this.menuHelper = new MenuHelper(this.config);
134
147
  this.widgetHandler = new WidgetHandler(this);
135
148
  bindExpressUtils(this.app);
136
149
  bindReqFunctions(this);
137
- // add install stepper policy to check unfilled settings
138
- // bindInstallStepper(this); // TODO It is necessary to provide an opportunity to be inserted by an intermediary after authorization, but before the admin panel, in order to block the user from managing the Installstepper's admin panel.
139
150
  // Bind assets
140
151
  bindAssets(this.app, this.config.routePrefix);
141
- if ((process.env.DEV && process.env.NODE_ENV !== 'production') || process.env.ADMINPANEL_FORCE_BIND_DEV === "TRUE") {
142
- bindDev(this);
152
+ if (!process.env.VITEST) {
153
+ if ((process.env.DEV && process.env.NODE_ENV !== 'production') || process.env.ADMINPANEL_FORCE_BIND_DEV === "TRUE") {
154
+ bindDev(this);
155
+ }
143
156
  }
144
157
  await bindDashboardWidgets(this);
145
- // bindNavigation(this);
158
+ bindNavigation(this);
146
159
  // bindMediaManager(this);
147
160
  await bindAccessRights(this);
148
161
  if (I18n.appendLocale) {
@@ -180,7 +193,7 @@ export class Adminizer {
180
193
  this.logger.error(`${error.message}\nStack: ${error.stack}`);
181
194
  }
182
195
  else {
183
- this.logger.error(args.join(" "));
196
+ this.logger.error(args.join(" ") + "\n" + new Error().stack);
184
197
  }
185
198
  },
186
199
  debug: (...args) => this.logger.debug(args.join(" ")),
@@ -188,4 +201,7 @@ export class Adminizer {
188
201
  silly: (...args) => this.logger.silly(args.join(" ")),
189
202
  };
190
203
  }
204
+ get defaultConfig() {
205
+ return getDefaultConfig();
206
+ }
191
207
  }
@@ -324,12 +324,9 @@
324
324
  // try {
325
325
  // await fs.promises.access(file);
326
326
  // await fs.promises.unlink(file);
327
- // console.log('The file was successfully deleted');
328
327
  // } catch (err) {
329
328
  // if (err.code === 'ENOENT') {
330
- // console.log('The file does not exist');
331
329
  // } else if (err.code === 'EPERM') {
332
- // console.log('You do not have permission to delete this file');
333
330
  // } else {
334
331
  // console.error(`An error occurred: ${err}`);
335
332
  // }
@@ -1,3 +1,4 @@
1
+ import { isObject } from "../helpers/JsUtils";
1
2
  import { Adminizer } from "./Adminizer";
2
3
  /**
3
4
  * Default helper that will contain all methods
@@ -29,11 +30,17 @@ export class RequestProcessor {
29
30
  }
30
31
  for (let key in postParams) {
31
32
  let field = fields[key];
32
- if (field.model.type === 'boolean') {
33
- postParams[key] = ['true', '1', 'yes', "TRUE", "on"].includes(postParams[key].toString().toLowerCase());
34
- continue;
33
+ if (key === 'sort') {
34
+ console.log(fields[key], key, postParams[key]);
35
35
  }
36
+ // if (field.model.type === 'boolean') {
37
+ // postParams[key] = ['true', '1', 'yes', "TRUE", "on"].includes(postParams[key].toString().toLowerCase());
38
+ // continue;
39
+ // }
36
40
  if (field.model.type === 'number') {
41
+ if (isObject(field.config) && field.config.type === "boolean" && typeof postParams[key] === "boolean") {
42
+ postParams[key] = postParams[key] ? 1 : 0;
43
+ }
37
44
  postParams[key] = parseFloat(postParams[key]);
38
45
  }
39
46
  if (field.model.type === 'json') {
@@ -4,6 +4,7 @@
4
4
  import { Entity } from "../../interfaces/types";
5
5
  import { ActionType } from "../../interfaces/adminpanelConfig";
6
6
  import { Fields } from "../../helpers/fieldsHelper";
7
+ import { Adminizer } from "../Adminizer";
7
8
  import { UserAP } from "models/UserAP";
8
9
  export declare class DataAccessor {
9
10
  private readonly adminizer;
@@ -11,7 +12,8 @@ export declare class DataAccessor {
11
12
  entity: Entity;
12
13
  action: ActionType;
13
14
  private fields;
14
- constructor(req: ReqType, entity: Entity, action: ActionType);
15
+ private actionVerb;
16
+ constructor(adminizer: Adminizer, user: UserAP, entity: Entity, action: ActionType);
15
17
  /**
16
18
  * Retrieves the fields for the given entity based on action type,
17
19
  * taking into account access rights and configuration settings.
@@ -1,16 +1,19 @@
1
1
  import { ControllerHelper } from "../../helpers/controllerHelper";
2
2
  import { Adminizer } from "../Adminizer";
3
+ import { isObject } from "../../helpers/JsUtils";
3
4
  export class DataAccessor {
4
5
  adminizer;
5
6
  user;
6
7
  entity;
7
8
  action;
8
9
  fields = null;
9
- constructor(req, entity, action) {
10
- this.adminizer = req.adminizer;
11
- this.user = req.user;
10
+ actionVerb;
11
+ constructor(adminizer, user, entity, action) {
12
+ this.adminizer = adminizer;
13
+ this.user = user;
12
14
  this.entity = entity;
13
15
  this.action = action;
16
+ this.actionVerb = getTokenAction(this.action);
14
17
  }
15
18
  /**
16
19
  * Retrieves the fields for the given entity based on action type,
@@ -28,8 +31,17 @@ export class DataAccessor {
28
31
  const actionConfig = ControllerHelper.findActionConfig(this.entity, this.action);
29
32
  const fieldsConfig = this.entity.config?.fields || {};
30
33
  const modelAttributes = this.entity.model.attributes;
34
+ const tokenId = `${this.actionVerb}-${this.entity.model.modelname}-${this.entity.type}`;
35
+ if (!this.adminizer.accessRightsHelper.hasPermission(tokenId, this.user)) {
36
+ Adminizer.log.debug(`getFieldsConfig > No access rights to ${this.actionVerb} ${this.entity.type}: ${this.entity.model.modelname}`);
37
+ return undefined;
38
+ }
31
39
  const result = {};
32
40
  Object.entries(modelAttributes).forEach(([key, modelField]) => {
41
+ // The fields that are recorded separately from the connection in some ORMs, because they are processed at the level above them.
42
+ if (modelAttributes[key].primaryKeyForAssociation === true) {
43
+ return undefined;
44
+ }
33
45
  // Checks for short type in Waterline: fieldName: 'string'
34
46
  if (typeof modelField === "string") {
35
47
  modelField = { type: modelField };
@@ -45,6 +57,7 @@ export class DataAccessor {
45
57
  }
46
58
  // Getting base field config
47
59
  let fldConfig = { key: key, title: key };
60
+ let associatedModelConfig = undefined;
48
61
  /** Combine the field configuration from global and action-specific configs
49
62
  * (now combine it before check, earlier was opposite).
50
63
  * Action-specific config should overwrite the global one */
@@ -66,42 +79,52 @@ export class DataAccessor {
66
79
  let populatedModelFieldsConfig = {};
67
80
  if (modelField.type === "association" || modelField.type === "association-many") {
68
81
  const modelName = modelField.model || modelField.collection;
82
+ const tokenId = `read-${modelName}-${this.entity.type}`;
83
+ if (!this.adminizer.accessRightsHelper.hasPermission(tokenId, this.user)) {
84
+ Adminizer.log.silly(`No access rights to ${this.entity.type}: ${this.entity.model.modelname}`);
85
+ return undefined;
86
+ }
69
87
  if (modelName) {
70
- const Model = this.adminizer.modelHandler.model.get(modelName);
71
- if (Model) {
88
+ const model = this.adminizer.modelHandler.model.get(modelName);
89
+ if (model) {
72
90
  populatedModelFieldsConfig = this.getAssociatedFieldsConfig(modelName);
91
+ let _modelConfig = this.adminizer.config.models[modelName];
92
+ if (!isObject(_modelConfig))
93
+ throw `type error: model config of ${modelName} is ${typeof (this.adminizer.config.models[modelName])} expected object`;
94
+ associatedModelConfig = _modelConfig;
73
95
  }
74
96
  else {
75
- Adminizer.log.error(`Model not found: ${modelName}`);
97
+ Adminizer.log.error(`DataAccessor > getFieldsConfig > Model not found: ${modelName} when ${key}`);
76
98
  }
77
99
  }
78
100
  }
79
101
  // Set required and type attributes
80
- fldConfig.required = Boolean(fldConfig.required || modelField.required);
102
+ fldConfig.required = Boolean(fldConfig.required ?? modelField.required);
81
103
  // Default type for field. Could be fetched form config file or file model if not defined in config file.
82
104
  fldConfig.type = (fldConfig.type || modelField.type).toLowerCase();
83
105
  // Normalize final configuration
84
106
  fldConfig = this.adminizer.configHelper.normalizeFieldConfig(this.adminizer, fldConfig, key, modelField);
85
107
  // Add new field to result set
86
- result[key] = { config: fldConfig, model: modelField, populated: populatedModelFieldsConfig };
108
+ result[key] = { config: fldConfig, model: modelField, populated: populatedModelFieldsConfig, modelConfig: associatedModelConfig };
87
109
  });
88
110
  this.fields = result;
89
111
  return result;
90
112
  }
91
113
  getAssociatedFieldsConfig(modelName) {
92
- const Model = this.adminizer.modelHandler.model.get(modelName);
93
- if (!Model || !this.adminizer.config.models[modelName] || typeof this.adminizer.config.models[modelName] === "boolean") {
114
+ const model = this.adminizer.modelHandler.model.get(modelName);
115
+ if (!model || !this.adminizer.config.models[modelName] || typeof this.adminizer.config.models[modelName] === "boolean") {
94
116
  return undefined;
95
117
  }
96
118
  // Check if user has access to the associated model
97
- const actionVerb = getTokenAction(this.action);
98
- const tokenId = `${actionVerb}-${modelName}-${this.entity.type}`;
119
+ const tokenId = `read-${modelName}-${this.entity.type}`;
99
120
  if (!this.adminizer.accessRightsHelper.hasPermission(tokenId, this.user)) {
100
- Adminizer.log.warn(`No access rights to ${this.entity.type}: ${modelName}`);
121
+ Adminizer.log.debug(`getAssociatedFieldsConfig > No access rights to ${this.actionVerb} ${this.entity.type}: ${modelName}`);
101
122
  return undefined;
102
123
  }
103
124
  const associatedFields = {};
104
125
  const modelConfig = this.adminizer.config.models[modelName];
126
+ if (!isObject(modelConfig))
127
+ throw `Type error ModelConfig should is object`;
105
128
  // Get the main fields configuration
106
129
  const fieldsConfig = modelConfig.fields || {};
107
130
  // Merge action-specific fields configuration if it exists
@@ -129,7 +152,7 @@ export class DataAccessor {
129
152
  }
130
153
  const mergedFieldsConfig = { ...fieldsConfig, ...actionSpecificConfig };
131
154
  // Loop through model attributes and apply access checks
132
- Object.entries(Model.attributes).forEach(([key, modelField]) => {
155
+ Object.entries(model.attributes).forEach(([key, modelField]) => {
133
156
  const fieldConfig = mergedFieldsConfig[key];
134
157
  // Creating a basic config
135
158
  let fldConfig = { key: key, title: key };
@@ -146,6 +169,7 @@ export class DataAccessor {
146
169
  config: fldConfig,
147
170
  model: modelField,
148
171
  populated: undefined, // set undefined for already populated fields
172
+ modelConfig: undefined
149
173
  };
150
174
  });
151
175
  return associatedFields;
@@ -327,7 +351,7 @@ export class DataAccessor {
327
351
  throw new Error(`No intermediate record found in model "${intermediateRelation.model}" associated with user ID "${this.user.id}"`);
328
352
  }
329
353
  // Ensure there is only one associated intermediate record
330
- const intermediateRecordCount = await intermediateModel.count({ [via]: this.user.id });
354
+ const intermediateRecordCount = await intermediateModel.count({ [via]: this.user.id }, this);
331
355
  if (intermediateRecordCount > 1) {
332
356
  throw new Error(`Multiple intermediate records found in model "${intermediateRelation.model}" associated with user ID "${this.user.id}". ` +
333
357
  `Expected only one`);
@@ -363,10 +387,11 @@ export class DataAccessor {
363
387
  const relation = modelAttributes[accessField];
364
388
  if (relation && ['userap', 'groupap'].includes(relation.model.toLowerCase())) {
365
389
  if (relation.model.toLowerCase() === 'userap') {
366
- updatedRecord[accessField] = this.user.id;
390
+ if (!this.user.isAdministrator) {
391
+ updatedRecord[accessField] = this.user.id;
392
+ }
367
393
  }
368
394
  else if (relation.model.toLowerCase() === 'groupap') {
369
- // Works only for users with only one group, later it can be resolved with group weight
370
395
  const userGroups = this.user.groups || [];
371
396
  if (userGroups.length === 1) {
372
397
  updatedRecord[accessField] = userGroups[0].id;
@@ -409,7 +434,7 @@ export class DataAccessor {
409
434
  throw new Error(`No intermediate record found in model "${intermediateRelation.model}" linking user "${this.user.id}" to the main record`);
410
435
  }
411
436
  // Ensure there is only one associated intermediate record
412
- const intermediateRecordCount = await intermediateModel.count({ [via]: this.user.id });
437
+ const intermediateRecordCount = await intermediateModel.count({ [via]: this.user.id }, this);
413
438
  if (intermediateRecordCount > 1) {
414
439
  throw new Error(`Multiple intermediate records found in model "${intermediateRelation.model}" associated with user ID "${this.user.id}". ` +
415
440
  `Expected only one`);
package/lib/v4/I18n.js CHANGED
@@ -104,7 +104,9 @@ export class I18n {
104
104
  return;
105
105
  const file = this.locateFile(locale);
106
106
  const tmpFile = `${file}.tmp`;
107
+ const dir = path.dirname(file);
107
108
  try {
109
+ fs.mkdirSync(dir, { recursive: true });
108
110
  fs.writeFileSync(tmpFile, JSON.stringify(I18n.locales[locale], null, this.indent), "utf8");
109
111
  fs.renameSync(tmpFile, file);
110
112
  }
@@ -1,5 +1,4 @@
1
- import { JSONSchema4 } from "json-schema";
2
- import { Adminizer } from "../Adminizer";
1
+ import { Adminizer } from "../../Adminizer";
3
2
  /**
4
3
  * Interface `Item` describes the data that the UI will operate on
5
4
  * This is a common interface for all data that is linked to the catalog
@@ -8,7 +7,10 @@ import { Adminizer } from "../Adminizer";
8
7
  export interface Item {
9
8
  id: string | number;
10
9
  name: string;
11
- parentId: string | number | null;
10
+ parentId: string | number;
11
+ /**
12
+ *
13
+ */
12
14
  childs?: Item[];
13
15
  sortOrder: number;
14
16
  icon: string;
@@ -20,8 +22,6 @@ export type _Item_ = {
20
22
  };
21
23
  /**
22
24
  * General Item structure that will be available for all elements, including groups
23
- *
24
- *
25
25
  */
26
26
  export declare abstract class BaseItem<T extends Item> {
27
27
  abstract readonly type: string;
@@ -30,6 +30,7 @@ export declare abstract class BaseItem<T extends Item> {
30
30
  * I haven't found an easier way to extract this type that goes into generic
31
31
  * If you know how to open PR
32
32
  * */
33
+ abstract adminizer: Adminizer;
33
34
  /**
34
35
  * Catalog name
35
36
  */
@@ -50,46 +51,62 @@ export declare abstract class BaseItem<T extends Item> {
50
51
  * Array of all global contexts, which will appear for all elements
51
52
  */
52
53
  readonly actionHandlers: ActionHandler[];
54
+ /**
55
+ * Adds the context menu processor
56
+ */
53
57
  addActionHandler(contextHandler: ActionHandler): void;
54
58
  /**
55
59
  * Adds the required fields
56
60
  * @param item
57
61
  */
58
62
  _enrich(item: T): void;
59
- _find(itemId: string | number, catalogId: string): Promise<T>;
60
- abstract find(itemId: string | number, catalogId: string): Promise<T>;
63
+ _find(itemId: string | number, catalogId: string, req?: ReqType): Promise<T>;
64
+ abstract find(itemId: string | number, catalogId: string, req?: ReqType): Promise<T>;
61
65
  /**
62
66
  * Is false because default value Group is added
63
67
  */
64
- abstract update(itemId: string | number, data: T, catalogId: string): Promise<T>;
68
+ abstract update(itemId: string | number, data: T, catalogId: string, req?: ReqType): Promise<T>;
65
69
  /**
66
70
  *
67
- * @param itemId
71
+ * @param modelId
68
72
  * @param data
69
73
  * @param catalogId
74
+ * @param req
70
75
  */
71
- abstract updateModelItems(modelId: string | number, data: any, catalogId: string): Promise<T>;
76
+ abstract updateModelItems(modelId: string | number, data: any, catalogId: string, req?: ReqType): Promise<T>;
72
77
  /**
73
- * For custom HTML
74
- * @param itemId
78
+ * Create catalog
75
79
  * @param data
80
+ * @param catalogId
81
+ * @param req
76
82
  */
77
- abstract create(data: T, catalogId: string): Promise<T>;
83
+ abstract create(data: T, catalogId: string, req?: ReqType): Promise<T>;
78
84
  /**
79
85
  * delete element
80
86
  */
81
- abstract deleteItem(itemId: string | number, catalogId: string): Promise<void>;
82
- abstract getAddHTML(req: ReqType): Promise<{
83
- type: 'link' | 'html' | 'jsonForm';
84
- data: string;
87
+ abstract deleteItem(itemId: string | number, catalogId: string, req?: ReqType): Promise<void>;
88
+ /**
89
+ * get add template
90
+ * @param req
91
+ */
92
+ abstract getAddTemplate(req: ReqType): Promise<{
93
+ type: 'component' | 'navigation.group' | 'navigation.link' | 'model';
94
+ data: any;
85
95
  }>;
86
- abstract getEditHTML(id: string | number, catalogId: string, req: ReqType, modelId?: string | number): Promise<{
87
- type: 'link' | 'html' | 'jsonForm';
88
- data: string;
96
+ /**
97
+ * get edit template
98
+ * @param id
99
+ * @param catalogId
100
+ * @param req
101
+ * @param modelId
102
+ */
103
+ abstract getEditTemplate(id: string | number, catalogId: string, req: ReqType, modelId?: string | number): Promise<{
104
+ type: 'component' | 'navigation.group' | 'navigation.link' | 'model';
105
+ data: any;
89
106
  }>;
90
- _getChilds(parentId: string | number | null, catalogId: string): Promise<Item[]>;
91
- abstract getChilds(parentId: string | number | null, catalogId: string): Promise<Item[]>;
92
- abstract search(s: string, catalogId: string): Promise<T[]>;
107
+ _getChilds(parentId: string | number, catalogId: string, req?: ReqType): Promise<Item[]>;
108
+ abstract getChilds(parentId: string | number, catalogId: string, req?: ReqType): Promise<Item[]>;
109
+ abstract search(s: string, catalogId: string, req?: ReqType): Promise<T[]>;
93
110
  }
94
111
  export declare abstract class AbstractGroup<T extends Item> extends BaseItem<T> {
95
112
  readonly type: string;
@@ -104,7 +121,7 @@ export declare abstract class ActionHandler {
104
121
  * Three actions are possible, without configuration, configuration via pop-up, and just external action
105
122
  * For the first two, a handler is provided, but the third type of action simply calls the HTML in the popup; the controller will be implemented externally
106
123
  * */
107
- abstract readonly type: "basic" | "json-forms" | "external" | "link" | "partial";
124
+ abstract readonly type: "basic" | "external" | "link";
108
125
  /**
109
126
  * Will be shown in the context menu section
110
127
  */
@@ -113,16 +130,10 @@ export declare abstract class ActionHandler {
113
130
  * Will be shown in the toolbox section
114
131
  */
115
132
  abstract readonly displayTool: boolean;
116
- /** (!*1)
117
- * Only for json-forms
118
- * ref: https://jsonforms.io/docs
119
- */
120
- abstract readonly uiSchema: any;
121
- abstract readonly jsonSchema: JSONSchema4;
122
133
  /**
123
- * For "json-forms" | "external"
134
+ * For "external"
124
135
  */
125
- abstract getPopUpHTML(data?: any): Promise<string>;
136
+ abstract getPopUpTemplate(req?: ReqType): Promise<string>;
126
137
  /**
127
138
  * Only for link type
128
139
  */
@@ -141,18 +152,19 @@ export declare abstract class ActionHandler {
141
152
  * Implementation of a method that will do something with elements.
142
153
  * there's really not much you can do with the context menu
143
154
  * @param items
144
- * @param config
155
+ * @param data
156
+ * @param req
145
157
  */
146
- abstract handler(items: Item[], data?: any): Promise<void>;
158
+ abstract handler(items: Item[], data?: any, req?: ReqType): Promise<void | string>;
147
159
  }
148
160
  /**
149
161
  *
150
- Abstract
151
- ____ _ _____ _ _ ___ ____
152
- / ___| / \|_ _|/ \ | | / _ \ / ___|
162
+ Abstract
163
+ ____ _ _____ _ _ ___ ____
164
+ / ___| / \|_ _|/ \ | | / _ \ / ___|
153
165
  | | / _ \ | | / _ \ | | | | | | | _
154
166
  | |___ / ___ \| |/ ___ \| |__| |_| | |_| |
155
- \____/_/ \_|_/_/ \_|_____\___/ \____|
167
+ \____/_/ \_|_/_/ \_|_____\___/ \____|
156
168
 
157
169
 
158
170
  */
@@ -190,12 +202,13 @@ export declare abstract class AbstractCatalog {
190
202
  * Method for getting childs elements
191
203
  * if pass null as parentId this root
192
204
  */
193
- getChilds(parentId: string | number | null, byItemType?: string): Promise<Item[]>;
205
+ getChilds(parentId: string | number, byItemType?: string, req?: ReqType): Promise<Item[]>;
194
206
  private _bindAccessRight;
195
207
  protected constructor(adminizer: Adminizer, items: BaseItem<any>[]);
196
208
  setId(id: string): void;
197
209
  /**
198
210
  * Gettind id list method
211
+ * @info This is a dummy method, please make realization in sub class
199
212
  */
200
213
  getIdList(): Promise<string[]>;
201
214
  getItemType(type: string): BaseItem<Item>;
@@ -204,62 +217,78 @@ export declare abstract class AbstractCatalog {
204
217
  /**
205
218
  * Get an element
206
219
  */
207
- find(item: Item): Promise<Item>;
220
+ find(item: Item, req?: ReqType): Promise<Item>;
208
221
  /**
209
222
  * Removing an element
210
223
  */
211
- deleteItem(type: string, id: string | number): void;
224
+ deleteItem(type: string, id: string | number, req?: ReqType): Promise<void>;
212
225
  /**
213
- * Receives HTML to update an element for projection into a popup
226
+ * Get edit template from an item type
227
+ * @param item
228
+ * @param id
229
+ * @param req
230
+ * @param modelId
214
231
  */
215
- getEditHTML(item: Item, id: string | number, req: ReqType, modelId?: string | number): Promise<{
216
- type: "link" | "html" | "jsonForm";
217
- data: string;
232
+ getEditTemplate(item: Item, id: string | number, req: ReqType, modelId?: string | number): Promise<{
233
+ type: "component" | "navigation.group" | "navigation.link" | "model";
234
+ data: any;
218
235
  }>;
219
236
  /**
220
- * Receives HTML to create an element for projection into a popup
237
+ * Get add template from an item type
238
+ * @param item
239
+ * @param req
221
240
  */
222
- getAddHTML(item: Item, req: ReqType): Promise<{
223
- type: "link" | "html" | "jsonForm";
224
- data: string;
241
+ getAddTemplate(item: Item, req: ReqType): Promise<{
242
+ type: "component" | "navigation.group" | "navigation.link" | "model";
243
+ data: any;
225
244
  }>;
226
245
  addActionHandler(actionHandler: ActionHandler): void;
227
246
  /**
228
247
  * Method for getting group elements
229
248
  * If there are several Items, then the global ones will be obtained
230
249
  */
231
- getActions(items?: Item[]): Promise<ActionHandler[]>;
250
+ getActions(items?: Item[]): ActionHandler[];
232
251
  /**
233
- * Implements search and execution of a specific action.handler
252
+ * Implements search and execution of a specific action handler
234
253
  */
235
- handleAction(actionId: string, items?: Item[], config?: any): Promise<void>;
254
+ handleAction(actionId: string, items?: Item[], data?: any, req?: ReqType): Promise<void | string>;
236
255
  /**
237
256
  * Only For a Link action
238
257
  * @param actionId
239
258
  */
240
259
  getLink(actionId: string): Promise<string>;
241
260
  /**
242
- * For Extermal and JsonForms actions
261
+ * For Extermal and actions
243
262
  * @param actionId
263
+ * @param req
244
264
  */
245
- getPopUpHTML(actionId: string): Promise<string>;
265
+ getPopUpTemplate(actionId: string, req?: ReqType): Promise<string>;
246
266
  /**
247
267
  *
248
268
  * @param data
269
+ * @param req
249
270
  */
250
- createItem<T extends Item>(data: T): Promise<T>;
251
- updateItem<T extends Item>(id: string | number, type: string, data: T): Promise<T>;
271
+ createItem<T extends Item>(data: T, req?: ReqType): Promise<T>;
272
+ updateItem<T extends Item>(id: string | number, type: string, data: T, req?: ReqType): Promise<T>;
252
273
  /**
253
274
  * To update all items in the tree after updating the model
254
- * @param id
275
+ * @param modelId
255
276
  * @param type
256
277
  * @param data
278
+ * @param req
257
279
  */
258
- updateModelItems<T extends Item>(modelId: string | number, type: string, data: T): Promise<T>;
280
+ updateModelItems<T extends Item>(modelId: string | number, type: string, data: T, req?: ReqType): Promise<T>;
259
281
  /**
260
282
  * Method for getting group elements
261
283
  */
262
- getitemTypes(): BaseItem<Item>[];
263
- search<T extends Item>(s: string, hasExtras?: boolean): Promise<T[]>;
284
+ getitemTypes(): {
285
+ type: string;
286
+ name: string;
287
+ isGroup: boolean;
288
+ allowedRoot: boolean;
289
+ icon: string;
290
+ actionHandlers: ActionHandler[];
291
+ }[];
292
+ search<T extends Item>(s: string, hasExtras?: boolean, req?: ReqType): Promise<T[]>;
264
293
  static buildTree(items: Item[]): Item[];
265
294
  }