adminforth 1.3.41 → 1.3.43

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.
@@ -24,6 +24,36 @@ try {
24
24
  catch (e) {
25
25
  TMP_DIR = '/tmp';
26
26
  }
27
+ function findHomePage(menuItem) {
28
+ for (const item of menuItem) {
29
+ if (item.homepage) {
30
+ return item;
31
+ }
32
+ if (item.children) {
33
+ const found = findHomePage(item.children);
34
+ if (found) {
35
+ return found;
36
+ }
37
+ }
38
+ }
39
+ return undefined;
40
+ }
41
+ function findFirstMenuItemWithResource(menuItem) {
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ for (const item of menuItem) {
44
+ if (item.path || item.resourceId) {
45
+ return item;
46
+ }
47
+ if (item.children) {
48
+ const found = yield findFirstMenuItemWithResource(item.children);
49
+ if (found) {
50
+ return found;
51
+ }
52
+ }
53
+ }
54
+ return undefined;
55
+ });
56
+ }
27
57
  const execAsync = promisify(exec);
28
58
  function hashify(obj) {
29
59
  return crypto.createHash('sha256').update(JSON.stringify(obj)).digest('hex');
@@ -128,7 +158,7 @@ class CodeInjector {
128
158
  }
129
159
  prepareSources(_a) {
130
160
  return __awaiter(this, arguments, void 0, function* ({ filesUpdated }) {
131
- var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
161
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
132
162
  // check SPA_TMP_PATH exists and create if not
133
163
  try {
134
164
  yield fs.promises.access(CodeInjector.SPA_TMP_PATH, fs.constants.F_OK);
@@ -377,12 +407,17 @@ class CodeInjector {
377
407
  `${this.adminforth.baseUrlSlashed}assets/favicon.png`);
378
408
  yield fs.promises.writeFile(indexHtmlPath, indexHtmlContent);
379
409
  /* generate custom routes */
380
- const homepageMenuItem = this.adminforth.config.menu.find((mi) => mi.homepage);
381
- let childrenHomePageMenuItem = this.adminforth.config.menu.find((mi) => { var _a; return mi.children && ((_a = mi.children) === null || _a === void 0 ? void 0 : _a.find((mi) => mi.homepage)); });
382
- let childrenHomepage = (_j = childrenHomePageMenuItem === null || childrenHomePageMenuItem === void 0 ? void 0 : childrenHomePageMenuItem.children) === null || _j === void 0 ? void 0 : _j.find((mi) => mi.homepage);
383
- let homePagePath = (homepageMenuItem === null || homepageMenuItem === void 0 ? void 0 : homepageMenuItem.path) || `/resource/${childrenHomepage === null || childrenHomepage === void 0 ? void 0 : childrenHomepage.resourceId}`;
410
+ let homepageMenuItem = findHomePage(this.adminforth.config.menu);
411
+ if (!homepageMenuItem) {
412
+ // find first item with path or resourceId. If we face a menu item with children earlier then path/resourceId, we should search in children
413
+ homepageMenuItem = yield findFirstMenuItemWithResource(this.adminforth.config.menu);
414
+ }
415
+ if (!homepageMenuItem) {
416
+ throw new Error('No homepage found in menu and no menu item with path/resourceId found. AdminForth can not generate routes');
417
+ }
418
+ let homePagePath = homepageMenuItem.path || `/resource/${homepageMenuItem.resourceId}`;
384
419
  if (!homePagePath) {
385
- homePagePath = ((_k = this.adminforth.config.menu.filter((mi) => mi.path)[0]) === null || _k === void 0 ? void 0 : _k.path) || `/resource/${(_l = this.adminforth.config.menu.filter((mi) => mi.children)[0]) === null || _l === void 0 ? void 0 : _l.resourceId}`;
420
+ homePagePath = ((_j = this.adminforth.config.menu.filter((mi) => mi.path)[0]) === null || _j === void 0 ? void 0 : _j.path) || `/resource/${(_k = this.adminforth.config.menu.filter((mi) => mi.children)[0]) === null || _k === void 0 ? void 0 : _k.resourceId}`;
386
421
  }
387
422
  routes += `{
388
423
  path: '/',
@@ -399,7 +434,7 @@ class CodeInjector {
399
434
  /* customPackageLock */
400
435
  let usersLockHash = '';
401
436
  let usersPackages = [];
402
- if ((_m = this.adminforth.config.customization) === null || _m === void 0 ? void 0 : _m.customComponentsDir) {
437
+ if ((_l = this.adminforth.config.customization) === null || _l === void 0 ? void 0 : _l.customComponentsDir) {
403
438
  [usersLockHash, usersPackages] = yield this.packagesFromNpm(this.adminforth.config.customization.customComponentsDir);
404
439
  }
405
440
  const pluginPackages = [];
@@ -176,6 +176,15 @@ export default class ConfigValidator {
176
176
  }
177
177
  col.showIn = col.showIn || Object.values(AdminForthResourcePages);
178
178
  if (col.foreignResource) {
179
+ if (!col.foreignResource.resourceId) {
180
+ errors.push(`Resource "${res.resourceId}" column "${col.name}" has foreignResource without resourceId`);
181
+ }
182
+ const resource = this.config.resources.find((r) => r.resourceId === col.foreignResource.resourceId);
183
+ if (!resource) {
184
+ const similar = suggestIfTypo(this.config.resources.map((r) => r.resourceId), col.foreignResource.resourceId);
185
+ errors.push(`Resource "${res.resourceId}" column "${col.name}" has foreignResource resourceId which is not in resources: "${col.foreignResource.resourceId}".
186
+ ${similar ? `Did you mean "${similar}" instead of "${col.foreignResource.resourceId}"?` : ''}`);
187
+ }
179
188
  const befHook = (_b = (_a = col.foreignResource.hooks) === null || _a === void 0 ? void 0 : _a.dropdownList) === null || _b === void 0 ? void 0 : _b.beforeDatasourceRequest;
180
189
  if (befHook) {
181
190
  if (!Array.isArray(befHook)) {
@@ -356,7 +365,9 @@ export default class ConfigValidator {
356
365
  errors.push(`Menu item with type 'resource' must have resourceId : ${JSON.stringify(item)}`);
357
366
  }
358
367
  if (item.resourceId && !this.config.resources.find((res) => res.resourceId === item.resourceId)) {
359
- errors.push(`Menu item with type 'resourceId' has resourceId which is not in resources: ${JSON.stringify(item)}`);
368
+ const similar = suggestIfTypo(this.config.resources.map((res) => res.resourceId), item.resourceId);
369
+ errors.push(`Menu item with type 'resourceId' has resourceId which is not in resources: "${JSON.stringify(item)}".
370
+ ${similar ? `Did you mean "${similar}" instead of "${item.resourceId}"?` : ''}`);
360
371
  }
361
372
  if (item.type === 'component' && !item.component) {
362
373
  errors.push(`Menu item with type 'component' must have component : ${JSON.stringify(item)}`);
@@ -8,7 +8,7 @@ import path from 'path';
8
8
  import { promisify } from 'util';
9
9
  import AdminForth from '../index.js';
10
10
  import { ADMIN_FORTH_ABSOLUTE_PATH, getComponentNameFromPath, transformObject, deepMerge } from './utils.js';
11
- import { ICodeInjector } from '../types/AdminForthConfig.js';
11
+ import { AdminForthConfigMenuItem, ICodeInjector } from '../types/AdminForthConfig.js';
12
12
  import { StylesGenerator } from './styleGenerator.js';
13
13
  import { title } from 'process';
14
14
 
@@ -22,6 +22,35 @@ try {
22
22
  }
23
23
 
24
24
 
25
+ function findHomePage(menuItem: AdminForthConfigMenuItem[]): AdminForthConfigMenuItem | undefined {
26
+ for (const item of menuItem) {
27
+ if (item.homepage) {
28
+ return item;
29
+ }
30
+ if (item.children) {
31
+ const found = findHomePage(item.children);
32
+ if (found) {
33
+ return found;
34
+ }
35
+ }
36
+ }
37
+ return undefined;
38
+ }
39
+ async function findFirstMenuItemWithResource(menuItem: AdminForthConfigMenuItem[]): Promise<AdminForthConfigMenuItem | undefined> {
40
+ for (const item of menuItem) {
41
+ if (item.path || item.resourceId) {
42
+ return item;
43
+ }
44
+ if (item.children) {
45
+ const found = await findFirstMenuItemWithResource(item.children);
46
+ if (found) {
47
+ return found;
48
+ }
49
+ }
50
+ }
51
+ return undefined;
52
+ }
53
+
25
54
  const execAsync = promisify(exec);
26
55
 
27
56
  function hashify(obj) {
@@ -429,10 +458,18 @@ class CodeInjector implements ICodeInjector {
429
458
 
430
459
 
431
460
  /* generate custom routes */
432
- const homepageMenuItem = this.adminforth.config.menu.find((mi)=>mi.homepage);
433
- let childrenHomePageMenuItem = this.adminforth.config.menu.find((mi)=>mi.children && mi.children?.find((mi)=>mi.homepage));
434
- let childrenHomepage = childrenHomePageMenuItem?.children?.find((mi)=>mi.homepage)
435
- let homePagePath = homepageMenuItem?.path || `/resource/${childrenHomepage?.resourceId}`;
461
+
462
+
463
+ let homepageMenuItem: AdminForthConfigMenuItem = findHomePage(this.adminforth.config.menu);
464
+ if (!homepageMenuItem) {
465
+ // find first item with path or resourceId. If we face a menu item with children earlier then path/resourceId, we should search in children
466
+ homepageMenuItem = await findFirstMenuItemWithResource(this.adminforth.config.menu);
467
+ }
468
+ if (!homepageMenuItem) {
469
+ throw new Error('No homepage found in menu and no menu item with path/resourceId found. AdminForth can not generate routes');
470
+ }
471
+
472
+ let homePagePath = homepageMenuItem.path || `/resource/${homepageMenuItem.resourceId}`;
436
473
  if (!homePagePath) {
437
474
  homePagePath=this.adminforth.config.menu.filter((mi)=>mi.path)[0]?.path || `/resource/${this.adminforth.config.menu.filter((mi)=>mi.children)[0]?.resourceId}` ;
438
475
  }
@@ -195,6 +195,16 @@ export default class ConfigValidator implements IConfigValidator {
195
195
  col.showIn = col.showIn || Object.values(AdminForthResourcePages);
196
196
 
197
197
  if (col.foreignResource) {
198
+
199
+ if (!col.foreignResource.resourceId) {
200
+ errors.push(`Resource "${res.resourceId}" column "${col.name}" has foreignResource without resourceId`);
201
+ }
202
+ const resource = this.config.resources.find((r) => r.resourceId === col.foreignResource.resourceId);
203
+ if (!resource) {
204
+ const similar = suggestIfTypo(this.config.resources.map((r) => r.resourceId), col.foreignResource.resourceId);
205
+ errors.push(`Resource "${res.resourceId}" column "${col.name}" has foreignResource resourceId which is not in resources: "${col.foreignResource.resourceId}".
206
+ ${similar ? `Did you mean "${similar}" instead of "${col.foreignResource.resourceId}"?` : ''}`);
207
+ }
198
208
  const befHook = col.foreignResource.hooks?.dropdownList?.beforeDatasourceRequest;
199
209
  if (befHook) {
200
210
  if (!Array.isArray(befHook)) {
@@ -413,7 +423,9 @@ export default class ConfigValidator implements IConfigValidator {
413
423
  }
414
424
 
415
425
  if (item.resourceId && !this.config.resources.find((res) => res.resourceId === item.resourceId)) {
416
- errors.push(`Menu item with type 'resourceId' has resourceId which is not in resources: ${JSON.stringify(item)}`);
426
+ const similar = suggestIfTypo(this.config.resources.map((res) => res.resourceId), item.resourceId);
427
+ errors.push(`Menu item with type 'resourceId' has resourceId which is not in resources: "${JSON.stringify(item)}".
428
+ ${similar ? `Did you mean "${similar}" instead of "${item.resourceId}"?` : ''}`);
417
429
  }
418
430
 
419
431
  if (item.type === 'component' && !item.component) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.3.41",
3
+ "version": "1.3.43",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",