@websolutespa/bom-mixer-store 1.7.8 → 1.8.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @websolutespa/bom-mixer-store
2
2
 
3
+ ## 1.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - f8a1d97: Modified: extracted all website sample components & features
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [f8a1d97]
12
+ - @websolutespa/bom-core@1.8.0
13
+
14
+ ## 1.7.9
15
+
16
+ ### Patch Changes
17
+
18
+ - Added: MenuCategory strategy
19
+ - Updated dependencies
20
+ - @websolutespa/bom-core@1.7.16
21
+
3
22
  ## 1.7.8
4
23
 
5
24
  ### Patch Changes
package/dist/index.js CHANGED
@@ -370,26 +370,44 @@ function collectUndecoratedPages(items, undecoratedPages = []) {
370
370
  return undecoratedPages;
371
371
  }
372
372
  var MAX_INT = 1e12;
373
- function decorateMenuCategory_(item, categories, routes, market, depth = 0) {
374
- const decoratedItem = {
375
- abstract: item.abstract,
376
- category: "",
377
- customClass: item.customClass,
373
+ function makeCategoryMenuItem_(item, category) {
374
+ const id = item.id || (0, import_bom_core3.uuidv4)();
375
+ const title = item.title || category.title || "";
376
+ const abstract = item.abstract || void 0;
377
+ const customClass = item.customClass || void 0;
378
+ const media = item.media || category.media;
379
+ const items = [];
380
+ return category.isHidden ? {
381
+ type: "group",
382
+ id,
383
+ title,
384
+ abstract,
385
+ media,
386
+ customClass,
387
+ items
388
+ } : {
389
+ type: "category",
390
+ category: category.id,
391
+ id,
378
392
  href: "",
379
- id: item.id || (0, import_bom_core3.uuidv4)(),
380
- items: [],
381
- title: "",
382
- type: item.type
393
+ title,
394
+ abstract,
395
+ media,
396
+ customClass,
397
+ items
383
398
  };
384
- const category = (0, import_bom_core3.findCategoryInCategories)(categories, item.category);
399
+ }
400
+ function decorateMenuCategory_(item, categories, routes, market, depth = 0) {
401
+ const strategy = item.strategy || import_bom_core3.MenuCategoryStrategy.Default;
402
+ const categoryId = (0, import_bom_core3.asCategoryId)(item.category);
403
+ const category = categoryId ? categories.find((x) => x.id === categoryId) : void 0;
385
404
  if (category) {
386
- decoratedItem.category = category.id;
387
- decoratedItem.title = item.title || category.title || "";
388
- decoratedItem.media = item.media || category.media;
389
- const route = (0, import_bom_core3.findRouteOfCategory)(routes, category.id);
390
- if (route) {
391
- decoratedItem.href = route.id;
392
- } else {
405
+ const decoratedItem = makeCategoryMenuItem_(item, category);
406
+ if (!category.isHidden) {
407
+ const route = routes.find((route2) => route2.isDefault && route2.resolvedCategory === category.id);
408
+ if (route) {
409
+ decoratedItem.href = route.id;
410
+ }
393
411
  }
394
412
  let maxDepth = item.maxDepth;
395
413
  if (typeof maxDepth === "number") {
@@ -398,33 +416,55 @@ function decorateMenuCategory_(item, categories, routes, market, depth = 0) {
398
416
  }
399
417
  maxDepth--;
400
418
  }
401
- const childCategories = (0, import_bom_core3.findChildCategories)(categories, category.id).filter((x) => Boolean(x.isHidden) === false);
402
- if (childCategories.length) {
403
- childCategories.sort((a, b) => {
404
- return (a.order || MAX_INT) - (b.order || MAX_INT);
405
- });
406
- decoratedItem.items = childCategories.map((c) => decorateMenuCategory_({
407
- id: c.id,
408
- type: "category",
409
- category: c.id,
410
- maxDepth,
411
- items: []
412
- }, categories, routes, market, depth + 1));
413
- }
414
- const childRoutes = (0, import_bom_core3.findRoutesOfCategory)(routes, category.id, false);
419
+ const childCategories = (category.id ? categories.filter((x) => (0, import_bom_core3.asCategoryId)(x.category) === category.id) : []).filter((x) => {
420
+ switch (strategy) {
421
+ case import_bom_core3.MenuCategoryStrategy.ExcludeHidden:
422
+ return Boolean(x.isHidden) === false;
423
+ case import_bom_core3.MenuCategoryStrategy.Default:
424
+ return true;
425
+ }
426
+ });
427
+ childCategories.sort((a, b) => {
428
+ return (a.order || MAX_INT) - (b.order || MAX_INT);
429
+ });
430
+ const subStrategy = strategy;
431
+ const childCategoryItems = childCategories.map((c) => decorateMenuCategory_({
432
+ id: c.id,
433
+ type: "category",
434
+ category: c.id,
435
+ maxDepth,
436
+ strategy: subStrategy,
437
+ // dispatch sub strategy
438
+ items: []
439
+ }, categories, routes, market, depth + 1));
440
+ const childRoutes = routes.filter((route) => {
441
+ switch (strategy) {
442
+ case import_bom_core3.MenuCategoryStrategy.ExcludeHidden:
443
+ return route.resolvedCategory === category.id && Boolean(route.isDefault) === false;
444
+ case import_bom_core3.MenuCategoryStrategy.Default:
445
+ return route.category === category.id && (category.isHidden || Boolean(route.isDefault) === false);
446
+ }
447
+ });
415
448
  childRoutes.sort((a, b) => {
416
449
  return (a.order || MAX_INT) - (b.order || MAX_INT);
417
450
  });
451
+ const childRouteItems = childRoutes.map((x) => decorateMenuRoute_(x));
418
452
  decoratedItem.items = [
419
- ...decoratedItem.items || [],
420
- ...childRoutes.map((x) => decorateMenuRoute_(x))
421
- ];
453
+ ...childCategoryItems,
454
+ ...childRouteItems
455
+ ].filter((x) => Boolean(x));
456
+ return decoratedItem;
422
457
  }
423
- return decoratedItem;
458
+ return {
459
+ id: item.id || (0, import_bom_core3.uuidv4)(),
460
+ type: "group",
461
+ title: item.title || "",
462
+ items: []
463
+ };
424
464
  }
425
465
  function decorateMenuRoute_(item) {
426
466
  const decoratedItem = {
427
- id: item.page,
467
+ id: (0, import_bom_core3.uuidv4)(),
428
468
  type: "route",
429
469
  title: item.title,
430
470
  href: item.id,
@@ -436,7 +476,9 @@ function decorateMenuRoute_(item) {
436
476
  return decoratedItem;
437
477
  }
438
478
  async function decorateMenuPage_(item, routes, store, params = {}) {
439
- const id = (0, import_bom_core3.isEquatable)(item.page.value) ? item.page.value : item.page.value.id;
479
+ const values = Array.isArray(item.page.value) ? item.page.value : [item.page.value];
480
+ const value = values[0];
481
+ const id = (0, import_bom_core3.isEquatable)(value) ? value : value.id;
440
482
  const route = routes.find(
441
483
  (x) => x.schema === item.page.relationTo && x.page === id
442
484
  );
@@ -522,17 +564,12 @@ function decorateNav__(item, routes) {
522
564
  }
523
565
 
524
566
  // src/decorators/optimize.ts
525
- var import_bom_core5 = require("@websolutespa/bom-core");
526
567
  async function optimizeOne_(item) {
527
568
  const validEntries = Object.entries(item).filter(([key, value]) => {
528
569
  switch (key) {
529
570
  case "components":
530
571
  case "meta":
531
572
  return false;
532
- default:
533
- if ((0, import_bom_core5.isUnresolvedRelation)(value) || Array.isArray(value) && value.reduce((p, c) => p && (0, import_bom_core5.isUnresolvedRelation)(c), true)) {
534
- return false;
535
- }
536
573
  }
537
574
  return true;
538
575
  });
@@ -548,7 +585,7 @@ async function optimizeMany_(items) {
548
585
  }
549
586
 
550
587
  // src/decorators/relation.ts
551
- var import_bom_core6 = require("@websolutespa/bom-core");
588
+ var import_bom_core5 = require("@websolutespa/bom-core");
552
589
  var SERVICE_DEFAULT_DEPTH = 3;
553
590
  async function decorateRelation_(store, item, params = {}) {
554
591
  const depth = params.depth != null ? params.depth : SERVICE_DEFAULT_DEPTH;
@@ -565,7 +602,7 @@ async function decorateRelations_(store, items, params = {}) {
565
602
  return items;
566
603
  }
567
604
  async function collectRelations_(context, item, relations = []) {
568
- if ((0, import_bom_core6.isUnresolvedRelation)(item)) {
605
+ if ((0, import_bom_core5.isUnresolvedRelation)(item)) {
569
606
  const index = relations.findIndex(
570
607
  (x) => x.relationTo === item.relationTo && x.value === item.value
571
608
  );
@@ -594,13 +631,13 @@ async function collectRelations_(context, item, relations = []) {
594
631
  } else {
595
632
  return relations[index].resolvedValue;
596
633
  }
597
- } else if ((0, import_bom_core6.isArray)(item)) {
634
+ } else if ((0, import_bom_core5.isArray)(item)) {
598
635
  const items = [];
599
636
  for (let i = 0; i < item.length; i++) {
600
637
  items[i] = await collectRelations_(context, item[i], relations);
601
638
  }
602
639
  return items;
603
- } else if ((0, import_bom_core6.isObject)(item)) {
640
+ } else if ((0, import_bom_core5.isObject)(item)) {
604
641
  for (const [key, value] of Object.entries(item)) {
605
642
  item[key] = await collectRelations_(context, value, relations);
606
643
  }
@@ -619,12 +656,12 @@ async function decorateSchemas_(store, items, schema) {
619
656
  }
620
657
 
621
658
  // src/local/local.api.ts
622
- var import_bom_core7 = require("@websolutespa/bom-core");
659
+ var import_bom_core6 = require("@websolutespa/bom-core");
623
660
  var API_URL = process.env.NEXT_PUBLIC_URL === "https://" ? process.env.NEXT_PUBLIC_MOCK_FALLBACK_URL : process.env.NEXT_PUBLIC_URL;
624
661
  var API_BASE = process.env.NEXT_PUBLIC_API || "/api";
625
662
  function getLocalApiUrl(pathname) {
626
- let url = `${import_bom_core7.isBrowser ? window.location.origin : API_URL}${API_BASE}${pathname}`;
627
- url = import_bom_core7.isBrowser ? url : url.replace("://localhost", "://127.0.0.1");
663
+ let url = `${import_bom_core6.isBrowser ? window.location.origin : API_URL}${API_BASE}${pathname}`;
664
+ url = import_bom_core6.isBrowser ? url : url.replace("://localhost", "://127.0.0.1");
628
665
  return url;
629
666
  }
630
667
  async function localApiFetch(pathname, options = {}, serviceOptions) {
@@ -633,9 +670,9 @@ async function localApiFetch(pathname, options = {}, serviceOptions) {
633
670
  url.searchParams.append("locale", serviceOptions.locale);
634
671
  url.searchParams.append("market", serviceOptions.market);
635
672
  }
636
- const apiOptions = (0, import_bom_core7.merge)({ ...getLocalApiRequestOptions() }, options);
673
+ const apiOptions = (0, import_bom_core6.merge)({ ...getLocalApiRequestOptions() }, options);
637
674
  console.log("localApiFetch", apiOptions.method, url.href);
638
- const apiResponse = await (0, import_bom_core7.httpFetch)(url.href, apiOptions);
675
+ const apiResponse = await (0, import_bom_core6.httpFetch)(url.href, apiOptions);
639
676
  return apiResponse;
640
677
  }
641
678
  async function localApiGet(url, options = {}, serviceOptions) {
@@ -674,8 +711,8 @@ function isApiRequest(request) {
674
711
  }
675
712
 
676
713
  // src/mock/mock.service.ts
677
- var import_bom_core8 = require("@websolutespa/bom-core");
678
- var MockService = class extends import_bom_core8.JsonService {
714
+ var import_bom_core7 = require("@websolutespa/bom-core");
715
+ var MockService = class extends import_bom_core7.JsonService {
679
716
  constructor(items, store) {
680
717
  super(items);
681
718
  this.store = store;
@@ -755,24 +792,29 @@ var MockPageService = class extends MockService {
755
792
  decoratedItems = await decorateCategories_(store, decoratedItems, params);
756
793
  decoratedItems = await decorateLocalizables_(decoratedItems, params);
757
794
  decoratedItems = await decorateHrefs_(store, decoratedItems, params);
795
+ decoratedItems = await decorateRelations_(store, decoratedItems, {
796
+ market: params.market,
797
+ locale: params.locale,
798
+ depth: params.depth
799
+ });
758
800
  return decoratedItems;
759
801
  }
760
802
  };
761
803
 
762
804
  // src/mock/mock.api.ts
763
- var import_bom_core9 = require("@websolutespa/bom-core");
805
+ var import_bom_core8 = require("@websolutespa/bom-core");
764
806
  var API_URL2 = process.env.NEXT_PUBLIC_URL;
765
807
  var API_BASE3 = process.env.NEXT_PUBLIC_API || "/api";
766
808
  function getMockApiUrl(pathname) {
767
809
  let url = `${API_URL2}${API_BASE3}/_mock${pathname}`;
768
- url = import_bom_core9.isBrowser ? url : url.replace("://localhost", "://127.0.0.1");
810
+ url = import_bom_core8.isBrowser ? url : url.replace("://localhost", "://127.0.0.1");
769
811
  return url;
770
812
  }
771
813
  async function mockApiFetch(pathname, options = {}) {
772
814
  const url = getMockApiUrl(pathname);
773
- const apiOptions = (0, import_bom_core9.merge)({ ...getLocalApiRequestOptions() }, options);
815
+ const apiOptions = (0, import_bom_core8.merge)({ ...getLocalApiRequestOptions() }, options);
774
816
  console.log("mockApiFetch", apiOptions.method, url);
775
- const apiResponse = await (0, import_bom_core9.httpFetch)(url, apiOptions);
817
+ const apiResponse = await (0, import_bom_core8.httpFetch)(url, apiOptions);
776
818
  return apiResponse;
777
819
  }
778
820
  async function mockApiGet(url, options = {}) {
@@ -792,7 +834,7 @@ async function mockApiDelete(url, options = {}) {
792
834
  }
793
835
 
794
836
  // src/store/store.handler.ts
795
- var import_bom_core15 = require("@websolutespa/bom-core");
837
+ var import_bom_core14 = require("@websolutespa/bom-core");
796
838
 
797
839
  // src/static/static.ts
798
840
  var staticCollections = [{
@@ -865,6 +907,28 @@ var staticCollections = [{
865
907
  type: "text"
866
908
  }
867
909
  ]
910
+ }, {
911
+ src: "https://actarian.github.io/cms-i18n-react/api/language.json",
912
+ slug: "i18n_country_zone",
913
+ fields: [
914
+ {
915
+ name: "id",
916
+ type: "text"
917
+ },
918
+ {
919
+ name: "name",
920
+ type: "text",
921
+ localized: true
922
+ },
923
+ {
924
+ name: "englishName",
925
+ type: "text"
926
+ },
927
+ {
928
+ name: "nativeName",
929
+ type: "text"
930
+ }
931
+ ]
868
932
  }, {
869
933
  src: "https://actarian.github.io/cms-i18n-react/api/municipality.json",
870
934
  slug: "i18n_municipality",
@@ -1067,7 +1131,7 @@ var KNOWN_COLLECTIONS = [
1067
1131
  var COLLECTIONS = [...ENV_COLLECTIONS, ...KNOWN_COLLECTIONS];
1068
1132
 
1069
1133
  // src/mock/mock.store.ts
1070
- var import_bom_core11 = require("@websolutespa/bom-core");
1134
+ var import_bom_core10 = require("@websolutespa/bom-core");
1071
1135
 
1072
1136
  // src/fs/fs.service.ts
1073
1137
  var fs = __toESM(require("fs"));
@@ -1095,8 +1159,8 @@ async function fsReadJson(pathname) {
1095
1159
  }
1096
1160
 
1097
1161
  // src/static/static.service.ts
1098
- var import_bom_core10 = require("@websolutespa/bom-core");
1099
- var StaticService = class extends import_bom_core10.JsonService {
1162
+ var import_bom_core9 = require("@websolutespa/bom-core");
1163
+ var StaticService = class extends import_bom_core9.JsonService {
1100
1164
  constructor(config, store) {
1101
1165
  super([]);
1102
1166
  this.loaded = false;
@@ -1124,7 +1188,7 @@ var StaticService = class extends import_bom_core10.JsonService {
1124
1188
  const config = this.config;
1125
1189
  const src = config.src;
1126
1190
  if (typeof src === "string") {
1127
- const response = await (0, import_bom_core10.httpGet)(src, {});
1191
+ const response = await (0, import_bom_core9.httpGet)(src, {});
1128
1192
  items = response.items;
1129
1193
  } else if (typeof src === "function") {
1130
1194
  if (src instanceof Promise) {
@@ -1240,7 +1304,7 @@ function getMockStoreFromData_(data) {
1240
1304
  return store;
1241
1305
  }
1242
1306
  async function getStoreData_() {
1243
- if (import_bom_core11.isDevelopment) {
1307
+ if (import_bom_core10.isDevelopment) {
1244
1308
  const path = require("path");
1245
1309
  const pathname = path.join(process.cwd(), ".mixer", "store.json");
1246
1310
  return await fsReadJson(pathname) || {};
@@ -1256,17 +1320,17 @@ async function getMockStore_() {
1256
1320
  }
1257
1321
  async function getMockStore() {
1258
1322
  return fromCache(async () => {
1259
- if (!import_bom_core11.isDevelopment) {
1323
+ if (!import_bom_core10.isDevelopment) {
1260
1324
  console.warn("getMockStore");
1261
1325
  }
1262
1326
  const store = await getMockStore_();
1263
1327
  return store;
1264
- }, import_bom_core11.isDevelopment ? void 0 : "STORE_MOCK_");
1328
+ }, import_bom_core10.isDevelopment ? void 0 : "STORE_MOCK_");
1265
1329
  }
1266
1330
 
1267
1331
  // src/cached/cached.service.ts
1268
- var import_bom_core12 = require("@websolutespa/bom-core");
1269
- var CachedService = class extends import_bom_core12.JsonService {
1332
+ var import_bom_core11 = require("@websolutespa/bom-core");
1333
+ var CachedService = class extends import_bom_core11.JsonService {
1270
1334
  constructor(service, options = {}) {
1271
1335
  super([]);
1272
1336
  this.cache_ = /* @__PURE__ */ new Map();
@@ -1305,7 +1369,7 @@ var CachedService = class extends import_bom_core12.JsonService {
1305
1369
  });
1306
1370
  }
1307
1371
  async findOne(id, params = {}) {
1308
- const serializedParams = (0, import_bom_core12.qsSerialize)(params);
1372
+ const serializedParams = (0, import_bom_core11.qsSerialize)(params);
1309
1373
  const key = `findOne[${id}]?${serializedParams}`;
1310
1374
  return await this.fromCache_(async () => {
1311
1375
  return await this.service_.findOne(id, params);
@@ -1314,7 +1378,7 @@ var CachedService = class extends import_bom_core12.JsonService {
1314
1378
  async findMany(params = {}) {
1315
1379
  if (storeStrategy === "decoratedApi" /* DecoratedApi */) {
1316
1380
  const { market, locale, ...otherParams } = params;
1317
- const serializedParams = (0, import_bom_core12.qsSerialize)({ market, locale });
1381
+ const serializedParams = (0, import_bom_core11.qsSerialize)({ market, locale });
1318
1382
  const key = `findMany?${serializedParams}`;
1319
1383
  let items = await this.fromCache_(async () => {
1320
1384
  return await this.service_.findMany({ market, locale });
@@ -1327,7 +1391,7 @@ var CachedService = class extends import_bom_core12.JsonService {
1327
1391
  }
1328
1392
  return items;
1329
1393
  } else {
1330
- const serializedParams = (0, import_bom_core12.qsSerialize)(params);
1394
+ const serializedParams = (0, import_bom_core11.qsSerialize)(params);
1331
1395
  const key = `findMany?${serializedParams}`;
1332
1396
  return await this.fromCache_(async () => {
1333
1397
  return await this.service_.findMany(params);
@@ -1335,7 +1399,7 @@ var CachedService = class extends import_bom_core12.JsonService {
1335
1399
  }
1336
1400
  }
1337
1401
  async findPaged(params = {}) {
1338
- const serializedParams = (0, import_bom_core12.qsSerialize)(params);
1402
+ const serializedParams = (0, import_bom_core11.qsSerialize)(params);
1339
1403
  const key = `findPaged?${serializedParams}`;
1340
1404
  return await this.fromCache_(async () => {
1341
1405
  return await this.service_.findPaged(params);
@@ -1353,22 +1417,22 @@ var CachedService = class extends import_bom_core12.JsonService {
1353
1417
  };
1354
1418
 
1355
1419
  // src/remote/remote.service.ts
1356
- var import_bom_core14 = require("@websolutespa/bom-core");
1420
+ var import_bom_core13 = require("@websolutespa/bom-core");
1357
1421
 
1358
1422
  // src/remote/remote.api.ts
1359
- var import_bom_core13 = require("@websolutespa/bom-core");
1423
+ var import_bom_core12 = require("@websolutespa/bom-core");
1360
1424
  var API_URL3 = process.env.STORE_URL;
1361
1425
  var API_BASE4 = process.env.STORE_API || "/api";
1362
1426
  function getRemoteApiUrl(pathname) {
1363
1427
  let url = `${API_URL3}${API_BASE4}${pathname}`;
1364
- url = import_bom_core13.isBrowser ? url : url.replace("://localhost", "://127.0.0.1");
1428
+ url = import_bom_core12.isBrowser ? url : url.replace("://localhost", "://127.0.0.1");
1365
1429
  return url;
1366
1430
  }
1367
1431
  async function remoteApiFetch(pathname, options = {}) {
1368
1432
  const url = getRemoteApiUrl(pathname);
1369
- const apiOptions = (0, import_bom_core13.merge)({ ...getRemoteApiRequestOptions() }, options);
1433
+ const apiOptions = (0, import_bom_core12.merge)({ ...getRemoteApiRequestOptions() }, options);
1370
1434
  console.log("remoteApiFetch", apiOptions.method, url);
1371
- const apiResponse = await (0, import_bom_core13.httpFetch)(url, apiOptions);
1435
+ const apiResponse = await (0, import_bom_core12.httpFetch)(url, apiOptions);
1372
1436
  return apiResponse;
1373
1437
  }
1374
1438
  async function remoteApiGet(url, options = {}) {
@@ -1405,7 +1469,7 @@ var RemoteService = class {
1405
1469
  async findOne(id, params = {}) {
1406
1470
  params.richText = String(params.richText) === "true" ? true : false;
1407
1471
  params.draft = RemoteServiceStrategy.draft;
1408
- const query = (0, import_bom_core14.qsSerialize)(params);
1472
+ const query = (0, import_bom_core13.qsSerialize)(params);
1409
1473
  const search = query ? `?${query}` : "";
1410
1474
  const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
1411
1475
  const item = await remoteApiGet(url);
@@ -1418,7 +1482,7 @@ var RemoteService = class {
1418
1482
  params.richText = String(params.richText) === "true" ? true : false;
1419
1483
  params.draft = RemoteServiceStrategy.draft;
1420
1484
  params.pagination = false;
1421
- const query = (0, import_bom_core14.qsSerialize)(params);
1485
+ const query = (0, import_bom_core13.qsSerialize)(params);
1422
1486
  const search = query ? `?${query}` : "";
1423
1487
  const url = `/${this.key}${search}`;
1424
1488
  const response = await remoteApiGet(url);
@@ -1429,7 +1493,7 @@ var RemoteService = class {
1429
1493
  params.richText = String(params.richText) === "true" ? true : false;
1430
1494
  params.draft = RemoteServiceStrategy.draft;
1431
1495
  params.pagination = true;
1432
- const query = (0, import_bom_core14.qsSerialize)(params);
1496
+ const query = (0, import_bom_core13.qsSerialize)(params);
1433
1497
  const search = query ? `?${query}` : "";
1434
1498
  const url = `/${this.key}${search}`;
1435
1499
  const response = await remoteApiGet(url);
@@ -1458,7 +1522,7 @@ var RemoteService = class {
1458
1522
  }
1459
1523
  }
1460
1524
  };
1461
- const query = (0, import_bom_core14.qsSerialize)(params);
1525
+ const query = (0, import_bom_core13.qsSerialize)(params);
1462
1526
  const search = query ? `?${query}` : "";
1463
1527
  const url = `/${this.key}${search}`;
1464
1528
  const item = await remoteApiDelete(url);
@@ -1638,7 +1702,7 @@ function collectionGet(storePromise) {
1638
1702
  const collection = collections[0];
1639
1703
  const id = collections[1];
1640
1704
  const qs = Object.entries(query).map((kv) => kv.join("=")).join("&");
1641
- const params = (0, import_bom_core15.qsDeserialize)(qs);
1705
+ const params = (0, import_bom_core14.qsDeserialize)(qs);
1642
1706
  if (!COLLECTIONS.includes(collection)) {
1643
1707
  console.error("storeHandler.collectionGet", "method not allowed", collection);
1644
1708
  return response.status(405).send("method not allowed");
@@ -1650,7 +1714,7 @@ function collectionGet(storePromise) {
1650
1714
  return response.status(405).send("method not allowed");
1651
1715
  }
1652
1716
  if (id) {
1653
- const item = await service.findOne((0, import_bom_core15.asEquatable)(id), params);
1717
+ const item = await service.findOne((0, import_bom_core14.asEquatable)(id), params);
1654
1718
  if (item) {
1655
1719
  return response.status(200).json(item);
1656
1720
  } else {
@@ -1770,8 +1834,8 @@ function storeIndexHandler() {
1770
1834
  return apiHandler({
1771
1835
  get: async (request, response) => {
1772
1836
  try {
1773
- const market = import_bom_core15.defaultMarket;
1774
- const locale = import_bom_core15.defaultLocale;
1837
+ const market = import_bom_core14.defaultMarket;
1838
+ const locale = import_bom_core14.defaultLocale;
1775
1839
  if (!Array.isArray(COLLECTIONS) || COLLECTIONS?.length === 0) {
1776
1840
  console.error("apiHome.collectionGet", "collections not found", COLLECTIONS);
1777
1841
  return response.status(405).send("method not allowed");
@@ -2038,10 +2102,38 @@ async function storeApiDelete(url, options = {}) {
2038
2102
  }
2039
2103
 
2040
2104
  // src/vars/vars.handler.ts
2041
- var import_bom_core17 = require("@websolutespa/bom-core");
2105
+ var import_bom_core16 = require("@websolutespa/bom-core");
2106
+
2107
+ // ../models/src/label/label.service.ts
2108
+ async function getLabels(params = {}) {
2109
+ const store = await getStore();
2110
+ const items = await store.label.findMany(params);
2111
+ return items;
2112
+ }
2113
+
2114
+ // ../models/src/locale/locale.service.ts
2115
+ async function getLocales(params = {}) {
2116
+ const store = await getStore();
2117
+ const items = await store.locale.findMany(params);
2118
+ return items;
2119
+ }
2120
+
2121
+ // ../models/src/market/market.service.ts
2122
+ async function getMarkets(params = {}) {
2123
+ const store = await getStore();
2124
+ const items = await store.market.findMany(params);
2125
+ return items;
2126
+ }
2127
+
2128
+ // ../models/src/menu/menu.service.ts
2129
+ async function getMenus(params = {}) {
2130
+ const store = await getStore();
2131
+ const items = await store.menu.findMany(params);
2132
+ return items;
2133
+ }
2042
2134
 
2043
2135
  // ../models/src/route/route.service.ts
2044
- var import_bom_core16 = require("@websolutespa/bom-core");
2136
+ var import_bom_core15 = require("@websolutespa/bom-core");
2045
2137
  async function getRouteLinkTree(market, locale) {
2046
2138
  const store = await getStore();
2047
2139
  const routes = await store.route.findMany({
@@ -2054,8 +2146,8 @@ async function getRouteLinkTree(market, locale) {
2054
2146
  }
2055
2147
  }
2056
2148
  });
2057
- const categories = await store.category.findMany();
2058
- const rootCategory = (0, import_bom_core16.getRootCategory)(categories);
2149
+ const categories = await store.category.findMany({ market, locale });
2150
+ const rootCategory = (0, import_bom_core15.getRootCategory)(categories);
2059
2151
  if (rootCategory) {
2060
2152
  const root = categoryToRouteLink(routes, categories, rootCategory, locale);
2061
2153
  return root;
@@ -2063,13 +2155,13 @@ async function getRouteLinkTree(market, locale) {
2063
2155
  return void 0;
2064
2156
  }
2065
2157
  function categoryToRouteLink(routes, categories, category, locale) {
2066
- const route = (0, import_bom_core16.findRouteOfCategory)(routes, category.id);
2158
+ const route = (0, import_bom_core15.findRouteOfCategory)(routes, category.id);
2067
2159
  if (!route) {
2068
2160
  return void 0;
2069
2161
  }
2070
- const rootCategory = (0, import_bom_core16.getRootCategory)(categories);
2162
+ const rootCategory = (0, import_bom_core15.getRootCategory)(categories);
2071
2163
  const childCategories = categories.filter((x) => {
2072
- const parentId = (0, import_bom_core16.asCategoryId)(x.category);
2164
+ const parentId = (0, import_bom_core15.asCategoryId)(x.category);
2073
2165
  return rootCategory && rootCategory.id === category.id ? x.id !== rootCategory.id && (parentId === category.id || !parentId) : parentId === category.id;
2074
2166
  });
2075
2167
  const routeLink = newRouteLink(category, route, locale);
@@ -2081,7 +2173,7 @@ function newRouteLink(category, route, locale) {
2081
2173
  const id = route?.page || category.id;
2082
2174
  const media = category.media || route?.media;
2083
2175
  const schema = route?.schema || category?.schema || "unknown";
2084
- const title = (0, import_bom_core16.localize)(category.title || route?.title || "untitled", locale);
2176
+ const title = (0, import_bom_core15.localize)(category.title || route?.title || "untitled", locale);
2085
2177
  const routeLink = {
2086
2178
  category: category.id,
2087
2179
  href,
@@ -2094,34 +2186,6 @@ function newRouteLink(category, route, locale) {
2094
2186
  return routeLink;
2095
2187
  }
2096
2188
 
2097
- // ../models/src/label/label.service.ts
2098
- async function getLabels(params = {}) {
2099
- const store = await getStore();
2100
- const items = await store.label.findMany(params);
2101
- return items;
2102
- }
2103
-
2104
- // ../models/src/locale/locale.service.ts
2105
- async function getLocales(params = {}) {
2106
- const store = await getStore();
2107
- const items = await store.locale.findMany(params);
2108
- return items;
2109
- }
2110
-
2111
- // ../models/src/market/market.service.ts
2112
- async function getMarkets(params = {}) {
2113
- const store = await getStore();
2114
- const items = await store.market.findMany(params);
2115
- return items;
2116
- }
2117
-
2118
- // ../models/src/menu/menu.service.ts
2119
- async function getMenus(params = {}) {
2120
- const store = await getStore();
2121
- const items = await store.menu.findMany(params);
2122
- return items;
2123
- }
2124
-
2125
2189
  // ../models/src/layout/layout.service.ts
2126
2190
  async function getLayout(market, locale) {
2127
2191
  const markets = await getMarkets({ locale });
@@ -2131,11 +2195,13 @@ async function getLayout(market, locale) {
2131
2195
  const firstLevelRoutes = tree?.items || [];
2132
2196
  const flatTopLevelRoutes = tree ? [tree, ...firstLevelRoutes] : [];
2133
2197
  const topLevelRoutes = flatTopLevelRoutes.reduce((object, routeLink) => {
2134
- object[routeLink.schema] = routeLink;
2198
+ if (!object[routeLink.schema] || routeLink.schema === routeLink.category) {
2199
+ object[routeLink.schema] = routeLink;
2200
+ }
2135
2201
  return object;
2136
2202
  }, {});
2137
2203
  const topLevelHrefs = flatTopLevelRoutes.reduce((object, routeLink) => {
2138
- if (routeLink.href) {
2204
+ if (routeLink.href && !object[routeLink.schema] || routeLink.schema === routeLink.category) {
2139
2205
  object[routeLink.schema] = routeLink.href;
2140
2206
  }
2141
2207
  return object;
@@ -2184,10 +2250,10 @@ function varsHandler() {
2184
2250
  const { locale = defaultLocale3, market = defaultMaket } = request.query || {};
2185
2251
  const layout = typeof locale === "string" && typeof market === "string" ? await getLayout(market, locale) : void 0;
2186
2252
  const info = {
2187
- production: import_bom_core17.isProduction,
2188
- development: import_bom_core17.isDevelopment,
2189
- origin: (0, import_bom_core17.getOrigin)(request.headers),
2190
- host: (0, import_bom_core17.getHost)(request.headers),
2253
+ production: import_bom_core16.isProduction,
2254
+ development: import_bom_core16.isDevelopment,
2255
+ origin: (0, import_bom_core16.getOrigin)(request.headers),
2256
+ host: (0, import_bom_core16.getHost)(request.headers),
2191
2257
  headers: { ...sortKeys(request.headers) },
2192
2258
  env: { ...getFilteredEnv(process.env) },
2193
2259
  layout: { ...sortKeys(layout) }
package/dist/index.mjs CHANGED
@@ -182,10 +182,11 @@ async function decorateLocalizables_(items, params = {}) {
182
182
 
183
183
  // src/decorators/menu.ts
184
184
  import {
185
+ MenuCategoryStrategy,
186
+ asCategoryId,
185
187
  findCategoryInCategories,
186
188
  findChildCategories,
187
189
  findRouteOfCategory as findRouteOfCategory2,
188
- findRoutesOfCategory,
189
190
  isEquatable,
190
191
  isUndecoratedMenuCategory,
191
192
  isUndecoratedMenuPage,
@@ -265,26 +266,44 @@ function collectUndecoratedPages(items, undecoratedPages = []) {
265
266
  return undecoratedPages;
266
267
  }
267
268
  var MAX_INT = 1e12;
268
- function decorateMenuCategory_(item, categories, routes, market, depth = 0) {
269
- const decoratedItem = {
270
- abstract: item.abstract,
271
- category: "",
272
- customClass: item.customClass,
269
+ function makeCategoryMenuItem_(item, category) {
270
+ const id = item.id || uuidv4();
271
+ const title = item.title || category.title || "";
272
+ const abstract = item.abstract || void 0;
273
+ const customClass = item.customClass || void 0;
274
+ const media = item.media || category.media;
275
+ const items = [];
276
+ return category.isHidden ? {
277
+ type: "group",
278
+ id,
279
+ title,
280
+ abstract,
281
+ media,
282
+ customClass,
283
+ items
284
+ } : {
285
+ type: "category",
286
+ category: category.id,
287
+ id,
273
288
  href: "",
274
- id: item.id || uuidv4(),
275
- items: [],
276
- title: "",
277
- type: item.type
289
+ title,
290
+ abstract,
291
+ media,
292
+ customClass,
293
+ items
278
294
  };
279
- const category = findCategoryInCategories(categories, item.category);
295
+ }
296
+ function decorateMenuCategory_(item, categories, routes, market, depth = 0) {
297
+ const strategy = item.strategy || MenuCategoryStrategy.Default;
298
+ const categoryId = asCategoryId(item.category);
299
+ const category = categoryId ? categories.find((x) => x.id === categoryId) : void 0;
280
300
  if (category) {
281
- decoratedItem.category = category.id;
282
- decoratedItem.title = item.title || category.title || "";
283
- decoratedItem.media = item.media || category.media;
284
- const route = findRouteOfCategory2(routes, category.id);
285
- if (route) {
286
- decoratedItem.href = route.id;
287
- } else {
301
+ const decoratedItem = makeCategoryMenuItem_(item, category);
302
+ if (!category.isHidden) {
303
+ const route = routes.find((route2) => route2.isDefault && route2.resolvedCategory === category.id);
304
+ if (route) {
305
+ decoratedItem.href = route.id;
306
+ }
288
307
  }
289
308
  let maxDepth = item.maxDepth;
290
309
  if (typeof maxDepth === "number") {
@@ -293,33 +312,55 @@ function decorateMenuCategory_(item, categories, routes, market, depth = 0) {
293
312
  }
294
313
  maxDepth--;
295
314
  }
296
- const childCategories = findChildCategories(categories, category.id).filter((x) => Boolean(x.isHidden) === false);
297
- if (childCategories.length) {
298
- childCategories.sort((a, b) => {
299
- return (a.order || MAX_INT) - (b.order || MAX_INT);
300
- });
301
- decoratedItem.items = childCategories.map((c) => decorateMenuCategory_({
302
- id: c.id,
303
- type: "category",
304
- category: c.id,
305
- maxDepth,
306
- items: []
307
- }, categories, routes, market, depth + 1));
308
- }
309
- const childRoutes = findRoutesOfCategory(routes, category.id, false);
315
+ const childCategories = (category.id ? categories.filter((x) => asCategoryId(x.category) === category.id) : []).filter((x) => {
316
+ switch (strategy) {
317
+ case MenuCategoryStrategy.ExcludeHidden:
318
+ return Boolean(x.isHidden) === false;
319
+ case MenuCategoryStrategy.Default:
320
+ return true;
321
+ }
322
+ });
323
+ childCategories.sort((a, b) => {
324
+ return (a.order || MAX_INT) - (b.order || MAX_INT);
325
+ });
326
+ const subStrategy = strategy;
327
+ const childCategoryItems = childCategories.map((c) => decorateMenuCategory_({
328
+ id: c.id,
329
+ type: "category",
330
+ category: c.id,
331
+ maxDepth,
332
+ strategy: subStrategy,
333
+ // dispatch sub strategy
334
+ items: []
335
+ }, categories, routes, market, depth + 1));
336
+ const childRoutes = routes.filter((route) => {
337
+ switch (strategy) {
338
+ case MenuCategoryStrategy.ExcludeHidden:
339
+ return route.resolvedCategory === category.id && Boolean(route.isDefault) === false;
340
+ case MenuCategoryStrategy.Default:
341
+ return route.category === category.id && (category.isHidden || Boolean(route.isDefault) === false);
342
+ }
343
+ });
310
344
  childRoutes.sort((a, b) => {
311
345
  return (a.order || MAX_INT) - (b.order || MAX_INT);
312
346
  });
347
+ const childRouteItems = childRoutes.map((x) => decorateMenuRoute_(x));
313
348
  decoratedItem.items = [
314
- ...decoratedItem.items || [],
315
- ...childRoutes.map((x) => decorateMenuRoute_(x))
316
- ];
349
+ ...childCategoryItems,
350
+ ...childRouteItems
351
+ ].filter((x) => Boolean(x));
352
+ return decoratedItem;
317
353
  }
318
- return decoratedItem;
354
+ return {
355
+ id: item.id || uuidv4(),
356
+ type: "group",
357
+ title: item.title || "",
358
+ items: []
359
+ };
319
360
  }
320
361
  function decorateMenuRoute_(item) {
321
362
  const decoratedItem = {
322
- id: item.page,
363
+ id: uuidv4(),
323
364
  type: "route",
324
365
  title: item.title,
325
366
  href: item.id,
@@ -331,7 +372,9 @@ function decorateMenuRoute_(item) {
331
372
  return decoratedItem;
332
373
  }
333
374
  async function decorateMenuPage_(item, routes, store, params = {}) {
334
- const id = isEquatable(item.page.value) ? item.page.value : item.page.value.id;
375
+ const values = Array.isArray(item.page.value) ? item.page.value : [item.page.value];
376
+ const value = values[0];
377
+ const id = isEquatable(value) ? value : value.id;
335
378
  const route = routes.find(
336
379
  (x) => x.schema === item.page.relationTo && x.page === id
337
380
  );
@@ -417,17 +460,12 @@ function decorateNav__(item, routes) {
417
460
  }
418
461
 
419
462
  // src/decorators/optimize.ts
420
- import { isUnresolvedRelation } from "@websolutespa/bom-core";
421
463
  async function optimizeOne_(item) {
422
464
  const validEntries = Object.entries(item).filter(([key, value]) => {
423
465
  switch (key) {
424
466
  case "components":
425
467
  case "meta":
426
468
  return false;
427
- default:
428
- if (isUnresolvedRelation(value) || Array.isArray(value) && value.reduce((p, c) => p && isUnresolvedRelation(c), true)) {
429
- return false;
430
- }
431
469
  }
432
470
  return true;
433
471
  });
@@ -443,7 +481,7 @@ async function optimizeMany_(items) {
443
481
  }
444
482
 
445
483
  // src/decorators/relation.ts
446
- import { isArray as isArray2, isObject as isObject2, isUnresolvedRelation as isUnresolvedRelation2 } from "@websolutespa/bom-core";
484
+ import { isArray as isArray2, isObject as isObject2, isUnresolvedRelation } from "@websolutespa/bom-core";
447
485
  var SERVICE_DEFAULT_DEPTH = 3;
448
486
  async function decorateRelation_(store, item, params = {}) {
449
487
  const depth = params.depth != null ? params.depth : SERVICE_DEFAULT_DEPTH;
@@ -460,7 +498,7 @@ async function decorateRelations_(store, items, params = {}) {
460
498
  return items;
461
499
  }
462
500
  async function collectRelations_(context, item, relations = []) {
463
- if (isUnresolvedRelation2(item)) {
501
+ if (isUnresolvedRelation(item)) {
464
502
  const index = relations.findIndex(
465
503
  (x) => x.relationTo === item.relationTo && x.value === item.value
466
504
  );
@@ -650,6 +688,11 @@ var MockPageService = class extends MockService {
650
688
  decoratedItems = await decorateCategories_(store, decoratedItems, params);
651
689
  decoratedItems = await decorateLocalizables_(decoratedItems, params);
652
690
  decoratedItems = await decorateHrefs_(store, decoratedItems, params);
691
+ decoratedItems = await decorateRelations_(store, decoratedItems, {
692
+ market: params.market,
693
+ locale: params.locale,
694
+ depth: params.depth
695
+ });
653
696
  return decoratedItems;
654
697
  }
655
698
  };
@@ -760,6 +803,28 @@ var staticCollections = [{
760
803
  type: "text"
761
804
  }
762
805
  ]
806
+ }, {
807
+ src: "https://actarian.github.io/cms-i18n-react/api/language.json",
808
+ slug: "i18n_country_zone",
809
+ fields: [
810
+ {
811
+ name: "id",
812
+ type: "text"
813
+ },
814
+ {
815
+ name: "name",
816
+ type: "text",
817
+ localized: true
818
+ },
819
+ {
820
+ name: "englishName",
821
+ type: "text"
822
+ },
823
+ {
824
+ name: "nativeName",
825
+ type: "text"
826
+ }
827
+ ]
763
828
  }, {
764
829
  src: "https://actarian.github.io/cms-i18n-react/api/municipality.json",
765
830
  slug: "i18n_municipality",
@@ -1935,8 +2000,36 @@ async function storeApiDelete(url, options = {}) {
1935
2000
  // src/vars/vars.handler.ts
1936
2001
  import { getHost, getOrigin, isDevelopment as isDevelopment2, isProduction } from "@websolutespa/bom-core";
1937
2002
 
2003
+ // ../models/src/label/label.service.ts
2004
+ async function getLabels(params = {}) {
2005
+ const store = await getStore();
2006
+ const items = await store.label.findMany(params);
2007
+ return items;
2008
+ }
2009
+
2010
+ // ../models/src/locale/locale.service.ts
2011
+ async function getLocales(params = {}) {
2012
+ const store = await getStore();
2013
+ const items = await store.locale.findMany(params);
2014
+ return items;
2015
+ }
2016
+
2017
+ // ../models/src/market/market.service.ts
2018
+ async function getMarkets(params = {}) {
2019
+ const store = await getStore();
2020
+ const items = await store.market.findMany(params);
2021
+ return items;
2022
+ }
2023
+
2024
+ // ../models/src/menu/menu.service.ts
2025
+ async function getMenus(params = {}) {
2026
+ const store = await getStore();
2027
+ const items = await store.menu.findMany(params);
2028
+ return items;
2029
+ }
2030
+
1938
2031
  // ../models/src/route/route.service.ts
1939
- import { asCategoryId, defaultLocale as defaultLocale2, defaultMarket as defaultMarket2, findRouteOfCategory as findRouteOfCategory3, getRootCategory, localize } from "@websolutespa/bom-core";
2032
+ import { asCategoryId as asCategoryId2, defaultLocale as defaultLocale2, defaultMarket as defaultMarket2, findRouteOfCategory as findRouteOfCategory3, getRootCategory, localize } from "@websolutespa/bom-core";
1940
2033
  async function getRouteLinkTree(market, locale) {
1941
2034
  const store = await getStore();
1942
2035
  const routes = await store.route.findMany({
@@ -1949,7 +2042,7 @@ async function getRouteLinkTree(market, locale) {
1949
2042
  }
1950
2043
  }
1951
2044
  });
1952
- const categories = await store.category.findMany();
2045
+ const categories = await store.category.findMany({ market, locale });
1953
2046
  const rootCategory = getRootCategory(categories);
1954
2047
  if (rootCategory) {
1955
2048
  const root = categoryToRouteLink(routes, categories, rootCategory, locale);
@@ -1964,7 +2057,7 @@ function categoryToRouteLink(routes, categories, category, locale) {
1964
2057
  }
1965
2058
  const rootCategory = getRootCategory(categories);
1966
2059
  const childCategories = categories.filter((x) => {
1967
- const parentId = asCategoryId(x.category);
2060
+ const parentId = asCategoryId2(x.category);
1968
2061
  return rootCategory && rootCategory.id === category.id ? x.id !== rootCategory.id && (parentId === category.id || !parentId) : parentId === category.id;
1969
2062
  });
1970
2063
  const routeLink = newRouteLink(category, route, locale);
@@ -1989,34 +2082,6 @@ function newRouteLink(category, route, locale) {
1989
2082
  return routeLink;
1990
2083
  }
1991
2084
 
1992
- // ../models/src/label/label.service.ts
1993
- async function getLabels(params = {}) {
1994
- const store = await getStore();
1995
- const items = await store.label.findMany(params);
1996
- return items;
1997
- }
1998
-
1999
- // ../models/src/locale/locale.service.ts
2000
- async function getLocales(params = {}) {
2001
- const store = await getStore();
2002
- const items = await store.locale.findMany(params);
2003
- return items;
2004
- }
2005
-
2006
- // ../models/src/market/market.service.ts
2007
- async function getMarkets(params = {}) {
2008
- const store = await getStore();
2009
- const items = await store.market.findMany(params);
2010
- return items;
2011
- }
2012
-
2013
- // ../models/src/menu/menu.service.ts
2014
- async function getMenus(params = {}) {
2015
- const store = await getStore();
2016
- const items = await store.menu.findMany(params);
2017
- return items;
2018
- }
2019
-
2020
2085
  // ../models/src/layout/layout.service.ts
2021
2086
  async function getLayout(market, locale) {
2022
2087
  const markets = await getMarkets({ locale });
@@ -2026,11 +2091,13 @@ async function getLayout(market, locale) {
2026
2091
  const firstLevelRoutes = tree?.items || [];
2027
2092
  const flatTopLevelRoutes = tree ? [tree, ...firstLevelRoutes] : [];
2028
2093
  const topLevelRoutes = flatTopLevelRoutes.reduce((object, routeLink) => {
2029
- object[routeLink.schema] = routeLink;
2094
+ if (!object[routeLink.schema] || routeLink.schema === routeLink.category) {
2095
+ object[routeLink.schema] = routeLink;
2096
+ }
2030
2097
  return object;
2031
2098
  }, {});
2032
2099
  const topLevelHrefs = flatTopLevelRoutes.reduce((object, routeLink) => {
2033
- if (routeLink.href) {
2100
+ if (routeLink.href && !object[routeLink.schema] || routeLink.schema === routeLink.category) {
2034
2101
  object[routeLink.schema] = routeLink.href;
2035
2102
  }
2036
2103
  return object;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@websolutespa/bom-mixer-store",
3
- "version": "1.7.8",
3
+ "version": "1.8.0",
4
4
  "description": "Mixer Store module of the BOM Repository",
5
5
  "keywords": [
6
6
  "bom",
@@ -1,9 +1,11 @@
1
1
  import {
2
- ICategorized, ICategory, IMenu, IMenuCategory, IMenuItem, IMenuPage, IMenuRoute, IRoute, IStore,
3
- IUndecoratedMenu, IUndecoratedMenuCategory, IUndecoratedMenuItem, IUndecoratedMenuPage, QueryParams,
2
+ ICategorized, ICategory, IMenu, IMenuCategory, IMenuGroup, IMenuItem, IMenuPage, IMenuRoute, IRoute, IStore,
3
+ IUndecoratedMenu, IUndecoratedMenuCategory, IUndecoratedMenuItem, IUndecoratedMenuPage, MenuCategoryStrategy, QueryParams,
4
+ asCategoryId,
4
5
  findCategoryInCategories,
5
6
  findChildCategories,
6
- findRouteOfCategory, findRoutesOfCategory, isEquatable, isUndecoratedMenuCategory, isUndecoratedMenuPage,
7
+ findRouteOfCategory,
8
+ isEquatable, isUndecoratedMenuCategory, isUndecoratedMenuPage,
7
9
  uuidv4
8
10
  } from '@websolutespa/bom-core';
9
11
 
@@ -91,12 +93,125 @@ function collectUndecoratedPages(items: IUndecoratedMenuItem[], undecoratedPages
91
93
 
92
94
  export const MAX_INT = 1000000000000; // 9007199254740991
93
95
 
96
+ function makeCategoryMenuItem_(item: IUndecoratedMenuCategory, category: ICategory): IMenuCategory | IMenuGroup {
97
+ const id = item.id || uuidv4();
98
+ const title = item.title || category.title || '';
99
+ const abstract = item.abstract || undefined;
100
+ const customClass = item.customClass || undefined;
101
+ const media = item.media || category.media;
102
+ const items: IMenuItem[] = [];
103
+ return category.isHidden ?
104
+ {
105
+ type: 'group',
106
+ id,
107
+ title,
108
+ abstract,
109
+ media,
110
+ customClass,
111
+ items,
112
+ } : {
113
+ type: 'category',
114
+ category: category.id,
115
+ id,
116
+ href: '',
117
+ title,
118
+ abstract,
119
+ media,
120
+ customClass,
121
+ items,
122
+ };
123
+ }
124
+
94
125
  function decorateMenuCategory_(
95
126
  item: IUndecoratedMenuCategory,
96
127
  categories: ICategory[],
97
128
  routes: IRoute[],
98
129
  market: string,
99
130
  depth: number = 0
131
+ ): IMenuItem | undefined {
132
+ const strategy = item.strategy || MenuCategoryStrategy.Default;
133
+ const categoryId = asCategoryId(item.category);
134
+ // find category
135
+ const category = categoryId ? categories.find(x => x.id === categoryId) : undefined;
136
+ if (category) {
137
+ const decoratedItem = makeCategoryMenuItem_(item, category);
138
+ if (!category.isHidden) {
139
+ const route = routes.find((route: IRoute) => route.isDefault && route.resolvedCategory === category.id);
140
+ if (route) {
141
+ (decoratedItem as IMenuCategory).href = route.id;
142
+ }
143
+ }
144
+ // checking for max depth recursion
145
+ let maxDepth = item.maxDepth;
146
+ if (typeof maxDepth === 'number') {
147
+ if (depth > maxDepth) {
148
+ return decoratedItem;
149
+ }
150
+ maxDepth--;
151
+ }
152
+ // search child categories
153
+ const childCategories = (category.id ?
154
+ categories.filter(x => asCategoryId(x.category) === category.id) : []
155
+ ).filter(x => {
156
+ switch (strategy) {
157
+ case MenuCategoryStrategy.ExcludeHidden:
158
+ return Boolean(x.isHidden) === false;
159
+ case MenuCategoryStrategy.Default:
160
+ return true;
161
+ }
162
+ });
163
+ // sort child categories
164
+ childCategories.sort((a, b) => {
165
+ return (a.order || MAX_INT) - (b.order || MAX_INT);
166
+ });
167
+ // define sub strategy (!!! todo)
168
+ const subStrategy = strategy;
169
+ // decorate child categories
170
+ const childCategoryItems = childCategories.map(c => decorateMenuCategory_({
171
+ id: c.id,
172
+ type: 'category',
173
+ category: c.id,
174
+ maxDepth,
175
+ strategy: subStrategy, // dispatch sub strategy
176
+ items: [],
177
+ } as IUndecoratedMenuCategory, categories, routes, market, depth + 1));
178
+ // find child routes
179
+ const childRoutes = routes.filter((route: IRoute) => {
180
+ switch (strategy) {
181
+ case MenuCategoryStrategy.ExcludeHidden:
182
+ return route.resolvedCategory === category.id && Boolean(route.isDefault) === false;
183
+ case MenuCategoryStrategy.Default:
184
+ return route.category === category.id && (category.isHidden || Boolean(route.isDefault) === false);
185
+ }
186
+ });
187
+ // sort child routes
188
+ childRoutes.sort((a, b) => {
189
+ return (a.order || MAX_INT) - (b.order || MAX_INT);
190
+ });
191
+ // decorate child routes
192
+ const childRouteItems: IMenuItem[] = childRoutes.map(x => decorateMenuRoute_(x));
193
+ // filter items
194
+ decoratedItem.items = [
195
+ ...childCategoryItems,
196
+ ...childRouteItems,
197
+ ].filter(x => Boolean(x)) as IMenuItem[];
198
+ return decoratedItem;
199
+ }
200
+ // return unresolved category as group
201
+ return {
202
+ id: item.id || uuidv4(),
203
+ type: 'group',
204
+ title: item.title || '',
205
+ items: [],
206
+ };
207
+ }
208
+
209
+ function decorateMenuCategoryWithHiddenSubCategories_(
210
+ item: IUndecoratedMenuCategory,
211
+ categories: ICategory[],
212
+ routes: IRoute[],
213
+ market: string,
214
+ depth: number = 0
100
215
  ): IMenuItem {
101
216
  const decoratedItem: IMenuCategory = {
102
217
  abstract: item.abstract,
@@ -108,6 +223,10 @@ function decorateMenuCategory_(
108
223
  title: '',
109
224
  type: item.type,
110
225
  };
226
+ /*
227
+ const categoryId = asCategoryId(item.category);
228
+ const category = categoryId ? categories.find(x => x.id === categoryId) : undefined;
229
+ */
111
230
  const category = findCategoryInCategories(categories, item.category);
112
231
  if (category) {
113
232
  // assigning category id
@@ -133,22 +252,59 @@ function decorateMenuCategory_(
133
252
  maxDepth--;
134
253
  }
135
254
  // search child categories
136
- const childCategories = findChildCategories(categories, category.id).filter(x => Boolean(x.isHidden) === false);
255
+ const childCategories = findChildCategories(categories, category.id);
137
256
  if (childCategories.length) {
138
257
  // sort child categories
139
258
  childCategories.sort((a, b) => {
140
259
  return (a.order || MAX_INT) - (b.order || MAX_INT);
141
260
  });
142
- decoratedItem.items = childCategories.map(c => decorateMenuCategory_({
143
- id: c.id,
144
- type: 'category',
145
- category: c.id,
146
- maxDepth,
147
- items: [],
148
- } as IUndecoratedMenuCategory, categories, routes, market, depth + 1));
261
+ decoratedItem.items = childCategories.map(c => {
262
+ const menuCategory = decorateMenuCategoryWithHiddenSubCategories_({
263
+ id: c.id,
264
+ type: 'category',
265
+ category: c.id,
266
+ maxDepth,
267
+ items: [],
268
+ } as IUndecoratedMenuCategory, categories, routes, market, depth + 1);
269
+ if (c.isHidden) {
270
+ const group: IMenuGroup = {
271
+ id: c.id,
272
+ type: 'group',
273
+ title: c.title,
274
+ items: [
275
+ ...(menuCategory.items || []),
276
+ ],
277
+ };
278
+ // find child routes
279
+ // const childRoutes = findRoutesOfCategory(routes, c.id, false);
280
+ const childRoutes = routes.filter((route: IRoute) =>
281
+ route.category === c.id &&
282
+ Boolean(route.isDefault) === false
283
+ );
284
+ // sort child routes
285
+ childRoutes.sort((a, b) => {
286
+ return (a.order || MAX_INT) - (b.order || MAX_INT);
287
+ });
288
+ const routeLinks = childRoutes.map(x => decorateMenuRoute_(x));
289
+ group.items?.push(...routeLinks);
290
+ return group;
291
+ } else {
292
+ return decorateMenuCategoryWithHiddenSubCategories_({
293
+ id: c.id,
294
+ type: 'category',
295
+ category: c.id,
296
+ maxDepth,
297
+ items: [],
298
+ } as IUndecoratedMenuCategory, categories, routes, market, depth + 1);
299
+ }
300
+ });
149
301
  }
150
302
  // find child routes
151
- const childRoutes = findRoutesOfCategory(routes, category.id, false);
303
+ // const childRoutes = findRoutesOfCategory(routes, category.id, false);
304
+ const childRoutes = routes.filter((route: IRoute) =>
305
+ route.category === category.id &&
306
+ Boolean(route.isDefault) === false
307
+ );
152
308
  // console.log('childRoutes', childRoutes, category.id);
153
309
  // sort child routes
154
310
  childRoutes.sort((a, b) => {
@@ -158,6 +314,7 @@ function decorateMenuCategory_(
158
314
  ...(decoratedItem.items || []),
159
315
  ...childRoutes.map(x => decorateMenuRoute_(x)),
160
316
  ];
317
+
161
318
  }
162
319
  return decoratedItem;
163
320
  }
@@ -166,7 +323,7 @@ function decorateMenuRoute_(
166
323
  item: IRoute
167
324
  ): IMenuItem {
168
325
  const decoratedItem: IMenuRoute = {
169
- id: item.page,
326
+ id: uuidv4(),
170
327
  type: 'route',
171
328
  title: item.title,
172
329
  href: item.id,
@@ -184,7 +341,9 @@ async function decorateMenuPage_(
184
341
  store: IStore,
185
342
  params: QueryParams = {}
186
343
  ): Promise<IMenuItem> {
187
- const id = (isEquatable(item.page.value) ? item.page.value : item.page.value.id);
344
+ const values = Array.isArray(item.page.value) ? item.page.value : [item.page.value];
345
+ const value = values[0]; // !!!
346
+ const id = isEquatable(value) ? value : value.id;
188
347
  const route = routes.find(x =>
189
348
  x.schema === item.page.relationTo &&
190
349
  x.page === id
@@ -1,4 +1,4 @@
1
- import { ICategorized, isUnresolvedRelation } from '@websolutespa/bom-core';
1
+ import { ICategorized } from '@websolutespa/bom-core';
2
2
 
3
3
  export async function optimizeOne_<T extends ICategorized = ICategorized>(item: T): Promise<T> {
4
4
  const validEntries = Object.entries(item).filter(([key, value]) => {
@@ -6,6 +6,7 @@ export async function optimizeOne_<T extends ICategorized = ICategorized>(item:
6
6
  case 'components':
7
7
  case 'meta':
8
8
  return false;
9
+ /*
9
10
  default:
10
11
  if (
11
12
  isUnresolvedRelation(value) ||
@@ -16,6 +17,7 @@ export async function optimizeOne_<T extends ICategorized = ICategorized>(item:
16
17
  ) {
17
18
  return false;
18
19
  }
20
+ */
19
21
  }
20
22
  return true;
21
23
  });
@@ -1,5 +1,5 @@
1
1
  import { ICategorized, QueryParams } from '@websolutespa/bom-core';
2
- import { decorateCategories_, decorateCategory_, decorateHref_, decorateHrefs_, decorateLocalizable_, decorateLocalizables_, decorateNav_, decorateRelation_, optimizeMany_ } from '../decorators';
2
+ import { decorateCategories_, decorateCategory_, decorateHref_, decorateHrefs_, decorateLocalizable_, decorateLocalizables_, decorateNav_, decorateRelation_, decorateRelations_, optimizeMany_ } from '../decorators';
3
3
  import { MockService } from './mock.service';
4
4
 
5
5
  export class MockPageService<T extends ICategorized = ICategorized> extends MockService<T> {
@@ -26,14 +26,14 @@ export class MockPageService<T extends ICategorized = ICategorized> extends Mock
26
26
  decoratedItems = await decorateCategories_<B>(store, decoratedItems, params);
27
27
  decoratedItems = await decorateLocalizables_<B>(decoratedItems, params);
28
28
  decoratedItems = await decorateHrefs_<B>(store, decoratedItems, params);
29
- /*
30
- // !!! optimization for index listing
31
- decoratedItems = await decorateNavs_<B>(store, decoratedItems, params);
32
29
  decoratedItems = await decorateRelations_<B>(store, decoratedItems, {
33
30
  market: params.market,
34
31
  locale: params.locale,
35
32
  depth: params.depth,
36
33
  });
34
+ /*
35
+ // !!! optimization for index listing
36
+ decoratedItems = await decorateNavs_<B>(store, decoratedItems, params);
37
37
  */
38
38
  return decoratedItems;
39
39
  }
@@ -90,6 +90,28 @@ export const staticCollections: StaticServiceConfig[] = [{
90
90
  type: 'text',
91
91
  },
92
92
  ],
93
+ }, {
94
+ src: 'https://actarian.github.io/cms-i18n-react/api/language.json',
95
+ slug: 'i18n_country_zone',
96
+ fields: [
97
+ {
98
+ name: 'id',
99
+ type: 'text',
100
+ },
101
+ {
102
+ name: 'name',
103
+ type: 'text',
104
+ localized: true,
105
+ },
106
+ {
107
+ name: 'englishName',
108
+ type: 'text',
109
+ },
110
+ {
111
+ name: 'nativeName',
112
+ type: 'text',
113
+ },
114
+ ],
93
115
  }, {
94
116
  src: 'https://actarian.github.io/cms-i18n-react/api/municipality.json',
95
117
  slug: 'i18n_municipality',