@websolutespa/bom-mixer-store 1.2.2 → 1.3.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/dist/index.js CHANGED
@@ -33,6 +33,7 @@ __export(src_exports, {
33
33
  COLLECTIONS: () => COLLECTIONS,
34
34
  KNOWN_COLLECTIONS: () => KNOWN_COLLECTIONS,
35
35
  MOCK_COLLECTIONS: () => MOCK_COLLECTIONS,
36
+ MOCK_SERVICE_DEFAULT_DEPTH: () => MOCK_SERVICE_DEFAULT_DEPTH,
36
37
  MockService: () => MockService,
37
38
  RemoteService: () => RemoteService,
38
39
  STATIC_COLLECTIONS: () => STATIC_COLLECTIONS,
@@ -43,6 +44,10 @@ __export(src_exports, {
43
44
  collectionGet: () => collectionGet,
44
45
  collectionPatch: () => collectionPatch,
45
46
  collectionPost: () => collectionPost,
47
+ decorateRelation_: () => decorateRelation_,
48
+ decorateRelations_: () => decorateRelations_,
49
+ decorateStaticRelation_: () => decorateStaticRelation_,
50
+ decorateStaticRelations_: () => decorateStaticRelations_,
46
51
  defaultApiRequestOptions: () => defaultApiRequestOptions,
47
52
  errorHandler: () => errorHandler,
48
53
  fromCache: () => fromCache,
@@ -53,8 +58,6 @@ __export(src_exports, {
53
58
  getStore: () => getStore,
54
59
  isApiRequest: () => isApiRequest,
55
60
  isNextRequest: () => isNextRequest,
56
- isObject: () => isObject,
57
- isRelation: () => isRelation,
58
61
  isStaticRequest: () => isStaticRequest,
59
62
  localApiDelete: () => localApiDelete,
60
63
  localApiFetch: () => localApiFetch,
@@ -62,6 +65,8 @@ __export(src_exports, {
62
65
  localApiPatch: () => localApiPatch,
63
66
  localApiPost: () => localApiPost,
64
67
  localApiPut: () => localApiPut,
68
+ localizeItem_: () => localizeItem_,
69
+ localizeItems_: () => localizeItems_,
65
70
  mockApiDelete: () => mockApiDelete,
66
71
  mockApiFetch: () => mockApiFetch,
67
72
  mockApiGet: () => mockApiGet,
@@ -83,6 +88,7 @@ __export(src_exports, {
83
88
  storeApiPost: () => storeApiPost,
84
89
  storeApiPut: () => storeApiPut,
85
90
  storeHandler: () => storeHandler,
91
+ storeIndexHandler: () => storeIndexHandler,
86
92
  storeStrategy: () => storeStrategy
87
93
  });
88
94
  module.exports = __toCommonJS(src_exports);
@@ -233,67 +239,7 @@ async function mockApiDelete(url, options = {}) {
233
239
  }
234
240
 
235
241
  // src/store/store.handler.ts
236
- var import_bom_core11 = require("@websolutespa/bom-core");
237
-
238
- // src/store/store.ts
239
- var StoreStrategy = /* @__PURE__ */ ((StoreStrategy2) => {
240
- StoreStrategy2["Api"] = "api";
241
- StoreStrategy2["Data"] = "data";
242
- StoreStrategy2["Mock"] = "mock";
243
- return StoreStrategy2;
244
- })(StoreStrategy || {});
245
- function getStoreStrategy() {
246
- let storeStrategy2 = "mock" /* Mock */;
247
- if (process && process.env.STORE_STRATEGY) {
248
- storeStrategy2 = process.env.STORE_STRATEGY;
249
- }
250
- return storeStrategy2;
251
- }
252
- var storeStrategy = getStoreStrategy();
253
- var ENV_COLLECTIONS = process.env.COLLECTIONS ? process.env.COLLECTIONS.split(",") : [];
254
- var MOCK_COLLECTIONS = process.env.MOCKS ? process.env.MOCKS.split(",") : [];
255
- var STATIC_COLLECTIONS = [];
256
- var KNOWN_COLLECTIONS = [
257
- "category",
258
- "label",
259
- "locale",
260
- "market",
261
- "menu",
262
- "template",
263
- "page",
264
- "redirect",
265
- "route",
266
- ...STATIC_COLLECTIONS
267
- ];
268
- var COLLECTIONS = [...ENV_COLLECTIONS, ...KNOWN_COLLECTIONS];
269
-
270
- // src/mock/mock.store.ts
271
- var import_bom_core7 = require("@websolutespa/bom-core");
272
-
273
- // src/fs/fs.service.ts
274
- var fs = __toESM(require("fs"));
275
- async function fsRead(pathname, option) {
276
- try {
277
- const data = await fs.promises.readFile(pathname, option?.encoding || "utf8");
278
- return data || void 0;
279
- } catch (error) {
280
- console.log("fsRead.error", error, pathname);
281
- return;
282
- }
283
- }
284
- async function fsReadJson(pathname) {
285
- try {
286
- const data = await fsRead(pathname);
287
- if (data) {
288
- return JSON.parse(data);
289
- } else {
290
- return;
291
- }
292
- } catch (error) {
293
- console.log("fsReadJson.error", error, pathname);
294
- return;
295
- }
296
- }
242
+ var import_bom_core10 = require("@websolutespa/bom-core");
297
243
 
298
244
  // src/static/static.ts
299
245
  var staticCollections = [{
@@ -498,15 +444,177 @@ var staticCollections = [{
498
444
  ]
499
445
  }];
500
446
 
447
+ // src/store/store.ts
448
+ var StoreStrategy = /* @__PURE__ */ ((StoreStrategy2) => {
449
+ StoreStrategy2["Api"] = "api";
450
+ StoreStrategy2["Data"] = "data";
451
+ StoreStrategy2["Mock"] = "mock";
452
+ return StoreStrategy2;
453
+ })(StoreStrategy || {});
454
+ function getStoreStrategy() {
455
+ let storeStrategy2 = "mock" /* Mock */;
456
+ if (process && process.env.STORE_STRATEGY) {
457
+ storeStrategy2 = process.env.STORE_STRATEGY;
458
+ }
459
+ return storeStrategy2;
460
+ }
461
+ var storeStrategy = getStoreStrategy();
462
+ var ENV_COLLECTIONS = process.env.COLLECTIONS ? process.env.COLLECTIONS.split(",") : [];
463
+ var MOCK_COLLECTIONS = process.env.MOCKS ? process.env.MOCKS.split(",") : [];
464
+ var STATIC_COLLECTIONS = staticCollections.map((x) => x.slug);
465
+ var KNOWN_COLLECTIONS = [
466
+ "category",
467
+ "label",
468
+ "locale",
469
+ "market",
470
+ "menu",
471
+ "template",
472
+ "redirect",
473
+ "route",
474
+ ...STATIC_COLLECTIONS
475
+ ];
476
+ var COLLECTIONS = [...ENV_COLLECTIONS, ...KNOWN_COLLECTIONS];
477
+
478
+ // src/mock/mock.store.ts
479
+ var import_bom_core6 = require("@websolutespa/bom-core");
480
+
481
+ // src/fs/fs.service.ts
482
+ var fs = __toESM(require("fs"));
483
+ async function fsRead(pathname, option) {
484
+ try {
485
+ const data = await fs.promises.readFile(pathname, option?.encoding || "utf8");
486
+ return data || void 0;
487
+ } catch (error) {
488
+ console.log("fsRead.error", error, pathname);
489
+ return;
490
+ }
491
+ }
492
+ async function fsReadJson(pathname) {
493
+ try {
494
+ const data = await fsRead(pathname);
495
+ if (data) {
496
+ return JSON.parse(data);
497
+ } else {
498
+ return;
499
+ }
500
+ } catch (error) {
501
+ console.log("fsReadJson.error", error, pathname);
502
+ return;
503
+ }
504
+ }
505
+
501
506
  // src/static/static.service.ts
507
+ var import_bom_core4 = require("@websolutespa/bom-core");
508
+
509
+ // src/mock/mock.service.ts
502
510
  var import_bom_core3 = require("@websolutespa/bom-core");
503
- var StaticService = class extends import_bom_core3.JsonService {
511
+ var MOCK_SERVICE_DEFAULT_DEPTH = 2;
512
+ var MockService = class extends import_bom_core3.JsonService {
513
+ constructor(items, store) {
514
+ super(items);
515
+ this.store = store;
516
+ }
517
+ async decorateOne_(item, params = {}) {
518
+ let decoratedItem = await localizeItem_(item, params);
519
+ decoratedItem = await decorateRelation_(this.store, decoratedItem, {
520
+ market: params.market,
521
+ locale: params.locale,
522
+ depth: params.depth != null ? params.depth : MOCK_SERVICE_DEFAULT_DEPTH
523
+ });
524
+ return decoratedItem;
525
+ }
526
+ async decorateMany_(items, params = {}) {
527
+ let decoratedItems = await localizeItems_(items, params);
528
+ decoratedItems = await decorateRelations_(this.store, decoratedItems, {
529
+ market: params.market,
530
+ locale: params.locale,
531
+ depth: params.depth != null ? params.depth : MOCK_SERVICE_DEFAULT_DEPTH
532
+ });
533
+ return decoratedItems;
534
+ }
535
+ };
536
+ async function localizeItem_(item, params = {}) {
537
+ if (params.locale) {
538
+ return (0, import_bom_core3.localizeItem)(item, params.locale);
539
+ } else {
540
+ return (0, import_bom_core3.cloneItem)(item);
541
+ }
542
+ }
543
+ async function localizeItems_(items, params = {}) {
544
+ const decoratedItems = [];
545
+ for (const item of items) {
546
+ const decoratedItem = params.locale ? (0, import_bom_core3.localizeItem)(item, params.locale) : (0, import_bom_core3.cloneItem)(item);
547
+ decoratedItems.push(decoratedItem);
548
+ }
549
+ return decoratedItems;
550
+ }
551
+ function collectRelations_(item, relations = []) {
552
+ if ((0, import_bom_core3.isObject)(item)) {
553
+ Object.entries(item).forEach(([key, value]) => {
554
+ if (key === "relation" && (0, import_bom_core3.isUnresolvedRelation)(value)) {
555
+ if (value.relationTo !== item.schema || value.value !== item.id) {
556
+ relations.push(value);
557
+ }
558
+ } else if ((0, import_bom_core3.isArray)(value)) {
559
+ value.forEach((x) => collectRelations_(x, relations));
560
+ } else if ((0, import_bom_core3.isObject)(value)) {
561
+ collectRelations_(value, relations);
562
+ }
563
+ });
564
+ }
565
+ return relations;
566
+ }
567
+ async function decorateRelation_(store, item, params = {}) {
568
+ const depth = params.depth != null ? params.depth : MOCK_SERVICE_DEFAULT_DEPTH;
569
+ if (depth === 0) {
570
+ return item;
571
+ }
572
+ const relations = collectRelations_(item);
573
+ for (const relation of relations) {
574
+ const isMany = Array.isArray(relation.value);
575
+ const items = await store[relation.relationTo].findMany({
576
+ ...params,
577
+ where: {
578
+ id: { in: isMany ? relation.value : [relation.value] }
579
+ },
580
+ depth: depth - 1
581
+ });
582
+ if (isMany) {
583
+ relation.value = items;
584
+ } else {
585
+ relation.value = items.length ? items[0] : void 0;
586
+ }
587
+ }
588
+ return item;
589
+ }
590
+ async function decorateRelations_(store, items, params = {}) {
591
+ for (const item of items) {
592
+ await decorateRelation_(store, item, params);
593
+ }
594
+ return items;
595
+ }
596
+
597
+ // src/static/static.service.ts
598
+ var StaticService = class extends import_bom_core4.JsonService {
504
599
  constructor(config, store) {
505
600
  super([]);
506
601
  this.loaded = false;
507
602
  this.config = config;
508
603
  this.store = store;
509
604
  }
605
+ mapItems_(items, map) {
606
+ if (typeof map === "object") {
607
+ items = items.map((x) => {
608
+ const item = {};
609
+ Object.entries(x).forEach(([k, v]) => {
610
+ const key = map[k] || k;
611
+ item[key] = v;
612
+ });
613
+ return item;
614
+ });
615
+ }
616
+ return items;
617
+ }
510
618
  async getItems() {
511
619
  let items = this.items;
512
620
  if (this.loaded && items) {
@@ -515,7 +623,7 @@ var StaticService = class extends import_bom_core3.JsonService {
515
623
  const config = this.config;
516
624
  const src = config.src;
517
625
  if (typeof src === "string") {
518
- const response = await (0, import_bom_core3.httpGet)(src, {});
626
+ const response = await (0, import_bom_core4.httpGet)(src, {});
519
627
  items = response.items;
520
628
  } else if (typeof src === "function") {
521
629
  if (src instanceof Promise) {
@@ -532,161 +640,121 @@ var StaticService = class extends import_bom_core3.JsonService {
532
640
  return items;
533
641
  }
534
642
  }
535
- async findOne(id, params = {}) {
536
- let items = await this.getItems();
537
- params.where = params.where || {};
538
- params.where.id = params.where.id || { equals: id };
539
- items = this.whereItems_(items, params.where);
540
- if (items.length > 0) {
541
- let item = items[0];
542
- if (params.depth !== 0) {
543
- item = await this.relatedItems_(item, this.config.fields);
544
- }
545
- return this.decorator_(item, params);
546
- } else {
547
- console.log("StaticService.findOne.notfound", id, params);
548
- return void 0;
549
- }
643
+ async decorateOne_(item, params = {}) {
644
+ let decoratedItem = await localizeItem_(item, params);
645
+ decoratedItem = await decorateStaticRelation_(this.store, this.config.fields, decoratedItem, {
646
+ market: params.market,
647
+ locale: params.locale,
648
+ depth: params.depth
649
+ });
650
+ return decoratedItem;
550
651
  }
551
- mapItems_(items, map) {
552
- if (typeof map === "object") {
553
- items = items.map((x) => {
554
- const item = {};
555
- Object.entries(x).forEach(([k, v]) => {
556
- const key = map[k] || k;
557
- item[key] = v;
558
- });
559
- return item;
560
- });
561
- }
562
- return items;
652
+ async decorateMany_(items, params = {}) {
653
+ let decoratedItems = await localizeItems_(items, params);
654
+ decoratedItems = await decorateStaticRelations_(this.store, this.config.fields, decoratedItems, {
655
+ market: params.market,
656
+ locale: params.locale,
657
+ depth: params.depth
658
+ });
659
+ return decoratedItems;
563
660
  }
564
- // !!! todo make recursive by depth with traverse
565
- async relatedItems_(item, fields, locale = "en") {
566
- const x = { ...item };
567
- for (const field of fields) {
568
- if (field.type === "relationship" && typeof field.relationTo === "string") {
569
- const name = field.name;
570
- const items = await this.store[field.relationTo].findMany();
571
- if (field.hasMany) {
572
- const ids = x[name];
573
- x[name] = items.filter((x2) => ids.indexOf(x2.id) !== -1);
574
- } else {
575
- const id = x[name];
576
- x[name] = items.find((x2) => x2.id === id) || id;
577
- }
661
+ };
662
+ async function decorateStaticRelation_(store, fields, item, params = {}) {
663
+ const depth = params.depth != null ? params.depth : MOCK_SERVICE_DEFAULT_DEPTH;
664
+ if (depth === 0) {
665
+ return item;
666
+ }
667
+ const decoratedItem = { ...item };
668
+ for (const field of fields) {
669
+ if (field.type === "relationship" && typeof field.relationTo === "string") {
670
+ const name = field.name;
671
+ const value = item[name];
672
+ const ids = field.hasMany ? value : [value];
673
+ const items = await store[field.relationTo].findMany({
674
+ where: {
675
+ id: { in: ids }
676
+ },
677
+ depth: depth - 1,
678
+ locale: params.locale
679
+ });
680
+ if (field.hasMany) {
681
+ decoratedItem[name] = items;
682
+ } else {
683
+ decoratedItem[name] = items.length ? items[0] : void 0;
578
684
  }
579
685
  }
580
- return x;
581
686
  }
582
- decorator_(item, params = {}) {
583
- if (params.locale) {
584
- item = (0, import_bom_core3.localizeItem)(item, params.locale);
585
- }
586
- return item;
687
+ return decoratedItem;
688
+ }
689
+ async function decorateStaticRelations_(store, fields, items, params = {}) {
690
+ const decoratedItems = [];
691
+ for (const item of items) {
692
+ const decoratedItem = await decorateStaticRelation_(store, fields, item, params);
693
+ decoratedItems.push(decoratedItem);
587
694
  }
588
- };
695
+ return decoratedItems;
696
+ }
589
697
 
590
698
  // src/mock/mock-menu.service.ts
591
- var import_bom_core5 = require("@websolutespa/bom-core");
592
-
593
- // src/mock/mock.service.ts
594
- var import_bom_core4 = require("@websolutespa/bom-core");
595
- var MockService = class extends import_bom_core4.JsonService {
596
- constructor(items, store) {
597
- super(items);
598
- this.store = store;
599
- }
600
- // !!! todo handle relations
699
+ var MAX_INT = 1e12;
700
+ var UID = 0;
701
+ var MockMenuService = class extends MockService {
601
702
  /*
602
- override async findOne<B extends T = T>(id: IEquatable, params: QueryParams = {}): Promise<B | undefined> {
603
- console.log('MockService.findOne', id, params);
703
+ async findOne<B extends T = T>(id: IEquatable, params: QueryParams = {}): Promise<B | undefined> {
704
+ // console.log('MockMenuService.findOne', id, params);
604
705
  let item = await super.findOne<B>(id, params);
605
- // relations
606
- if (item) {
607
- if (params.depth !== 0) {
608
- item = await this.relatedItems_(item);
609
- }
706
+ if (item && params.market && params.locale) {
707
+ item = await decorateMenu_(this.store, (item as any), {
708
+ market: params.market,
709
+ locale: params.locale,
710
+ }) as any;
610
711
  }
611
712
  return item;
612
713
  }
613
714
 
614
- override async findMany<B extends T = T>(params: QueryParams = {}): Promise<B[]> {
615
- // console.log('MockService.findMany', params);
715
+ async findMany<B extends T = T>(params: QueryParams = {}): Promise<B[]> {
716
+ // console.log('MockMenuService.findMany', params);
616
717
  let items = await super.findMany<B>(params);
617
- // relations
618
- if (params.depth !== 0) {
619
- items = await Promise.all(items.map(x => this.relatedItems_(x)));
718
+ if (params.market && params.locale) {
719
+ items = await decorateMenus_(this.store, (items as any[]), {
720
+ market: params.market,
721
+ locale: params.locale,
722
+ }) as any[];
620
723
  }
621
724
  return items;
622
725
  }
623
726
 
624
- override async findPaged<B extends T = T>(params: QueryParams = {}): Promise<{ docs: B[]; } & Pagination> {
625
- // console.log('MockService.findPaged', params);
727
+ async findPaged<B extends T = T>(params: QueryParams = {}): Promise<{ docs: B[]; } & Pagination> {
728
+ // console.log('MockMenuService.findPaged', params);
626
729
  const pagination = await super.findPaged<B>(params);
627
- // relations
628
- if (params.depth !== 0) {
629
- pagination.docs = await Promise.all(pagination.docs.map(x => this.relatedItems_(x)));
730
+ if (params.market && params.locale) {
731
+ pagination.docs = await decorateMenus_(this.store, (pagination.docs as any[]), {
732
+ market: params.market,
733
+ locale: params.locale,
734
+ }) as any[];
630
735
  }
631
736
  return pagination;
632
737
  }
633
-
634
- protected async relatedItems_<B extends T = T>(item: B): Promise<B> {
635
- const x = { ...item };
636
- Object.entries(item).forEach(([k, v]) => {
637
- if (isRelation(v)) {
638
- console.log(k, v);
639
- }
640
- });
641
- return x;
642
- }
643
738
  */
644
- decorator_(item, params = {}) {
645
- if (params.locale) {
646
- return (0, import_bom_core4.localizeItem)(item, params.locale);
647
- } else {
648
- return item;
649
- }
650
- }
651
- };
652
- function isObject(item) {
653
- return item !== null && typeof item === "object";
654
- }
655
- function isRelation(item) {
656
- return isObject(item) && typeof item.relationTo === "string" && item.value !== void 0;
657
- }
658
-
659
- // src/mock/mock-menu.service.ts
660
- var MAX_INT = 1e12;
661
- var UID = 0;
662
- var MockMenuService = class extends MockService {
663
- async findOne(id, params = {}) {
664
- let item = await super.findOne(id, params);
665
- if (item && params.market && params.locale) {
666
- item = await decorateMenu(this.store, item, params.market, params.locale);
667
- }
668
- return item;
669
- }
670
- async findMany(params = {}) {
671
- let items = await super.findMany(params);
739
+ async decorateOne_(item, params = {}) {
740
+ let decoratedItem = await localizeItem_(item, params);
672
741
  if (params.market && params.locale) {
673
- items = await decorateMenus(this.store, items, params.market, params.locale);
742
+ decoratedItem = await decorateMenu_(this.store, decoratedItem, {
743
+ market: params.market,
744
+ locale: params.locale
745
+ });
674
746
  }
675
- return items;
747
+ return decoratedItem;
676
748
  }
677
- async findPaged(params = {}) {
678
- const pagination = await super.findPaged(params);
749
+ async decorateMany_(items, params = {}) {
750
+ let decoratedItems = await localizeItems_(items, params);
679
751
  if (params.market && params.locale) {
680
- pagination.docs = await decorateMenus(this.store, pagination.docs, params.market, params.locale);
681
- }
682
- return pagination;
683
- }
684
- decorator_(item, params = {}) {
685
- if (params.locale) {
686
- return (0, import_bom_core5.localizeItem)(item, params.locale);
687
- } else {
688
- return item;
752
+ decoratedItems = await decorateMenus_(this.store, decoratedItems, {
753
+ market: params.market,
754
+ locale: params.locale
755
+ });
689
756
  }
757
+ return decoratedItems;
690
758
  }
691
759
  };
692
760
  async function collectPages(store, items, params = {}) {
@@ -699,15 +767,15 @@ async function collectPages(store, items, params = {}) {
699
767
  if (value) {
700
768
  const routes = await store.route.findMany({
701
769
  where: {
770
+ ...params.market ? { market: { equals: params.market } } : {},
771
+ ...params.locale ? { locale: { equals: params.locale } } : {},
702
772
  page: {
703
773
  equals: item.page.value
704
774
  },
705
775
  schema: {
706
776
  equals: item.page.relationTo
707
777
  }
708
- },
709
- market: params.market,
710
- locale: params.locale
778
+ }
711
779
  });
712
780
  const page = {
713
781
  ...value,
@@ -725,31 +793,31 @@ async function collectPages(store, items, params = {}) {
725
793
  }
726
794
  }
727
795
  }
728
- async function decorateMenu(store, item, market = "ww", locale = "en") {
796
+ async function decorateMenu_(store, item, params) {
729
797
  const items = item.items || [];
730
798
  const decoratedItem = {
731
799
  id: item.id,
732
800
  items: []
733
801
  };
734
- const categories = await store.category.findMany({ market, locale });
802
+ const categories = await store.category.findMany(params);
735
803
  const routes = await store.route.findMany({
804
+ ...params,
736
805
  where: {
737
- market: {
738
- equals: market
739
- },
740
- locale: {
741
- equals: locale
742
- }
743
- },
744
- market,
745
- locale
806
+ ...params.market ? { market: { equals: params.market } } : {},
807
+ ...params.locale ? { locale: { equals: params.locale } } : {}
808
+ }
746
809
  });
747
- await collectPages(store, items, { market, locale });
748
- decoratedItem.items = items.filter((x) => hasMarket(x, market)).map((x) => decorateMenuItem(x, categories, routes, market));
810
+ await collectPages(store, items, params);
811
+ decoratedItem.items = items.filter((x) => hasMarket(x, params.market)).map((x) => decorateMenuItem(x, categories, routes, params.market));
749
812
  return decoratedItem;
750
813
  }
751
- async function decorateMenus(store, items, market = "ww", locale = "en") {
752
- return await Promise.all(items.map((x) => decorateMenu(store, x, market, locale)));
814
+ async function decorateMenus_(store, items, params) {
815
+ const decoratedItems = [];
816
+ for (const item of items) {
817
+ const decoratedItem = await decorateMenu_(store, item, params);
818
+ decoratedItems.push(decoratedItem);
819
+ }
820
+ return decoratedItems;
753
821
  }
754
822
  function decorateMenuCategory(item, categories, routes, market, depth = 0) {
755
823
  const decoratedItem = {
@@ -841,7 +909,9 @@ function decorateMenuLink(item, categories, routes, market) {
841
909
  }
842
910
  function decorateMenuPage(item, categories, routes, market) {
843
911
  const items = item.items || [];
844
- const route = routes.find((x) => x.schema === item.page.relationTo && x.page === item.page.value.id);
912
+ const route = routes.find(
913
+ (x) => x.schema === item.page.relationTo && x.page === item.page.value.id
914
+ );
845
915
  const decoratedItem = {
846
916
  id: item.id || "",
847
917
  type: item.type,
@@ -886,66 +956,144 @@ function hasMarket(item, market) {
886
956
  }
887
957
 
888
958
  // src/mock/mock-page.service.ts
889
- var import_bom_core6 = require("@websolutespa/bom-core");
959
+ var import_bom_core5 = require("@websolutespa/bom-core");
890
960
  var MockPageService = class extends MockService {
891
- async findOne(id, params = {}) {
892
- let item = await super.findOne(id, params);
893
- if (item && params.market && params.locale) {
894
- item = await decorateHref(this.store, item, params.market, params.locale);
895
- }
961
+ async decorateOne_(item, params = {}) {
962
+ let decoratedItem = await localizeItem_(item, params);
963
+ decoratedItem = await decorateHref_(this.store, decoratedItem, params);
964
+ decoratedItem = await decorateNav_(this.store, decoratedItem, params);
965
+ decoratedItem = await decorateRelation_(this.store, decoratedItem, {
966
+ market: params.market,
967
+ locale: params.locale,
968
+ depth: params.depth
969
+ });
970
+ return decoratedItem;
971
+ }
972
+ async decorateMany_(items, params = {}) {
973
+ let decoratedItems = await localizeItems_(items, params);
974
+ decoratedItems = await decorateHrefs_(this.store, decoratedItems, params);
975
+ decoratedItems = await decorateNavs_(this.store, decoratedItems, params);
976
+ decoratedItems = await decorateRelations_(this.store, decoratedItems, {
977
+ market: params.market,
978
+ locale: params.locale,
979
+ depth: params.depth
980
+ });
981
+ return decoratedItems;
982
+ }
983
+ };
984
+ async function decorateHref_(store, item, params = {}) {
985
+ if (params.market && params.locale) {
986
+ const routes = await store.route.findMany({
987
+ where: {
988
+ market: {
989
+ equals: params.market
990
+ },
991
+ locale: {
992
+ equals: params.locale
993
+ },
994
+ schema: {
995
+ equals: item.schema
996
+ },
997
+ page: {
998
+ equals: item.id
999
+ }
1000
+ }
1001
+ });
1002
+ const href = routes.length ? routes[0].id : null;
1003
+ return { ...item, href };
1004
+ } else {
896
1005
  return item;
897
1006
  }
898
- async findMany(params = {}) {
899
- let items = await super.findMany(params);
900
- if (params.market && params.locale) {
901
- items = await decorateHrefs(this.store, items, params.market, params.locale);
902
- }
1007
+ }
1008
+ async function decorateHrefs_(store, items, params = {}) {
1009
+ if (params.market && params.locale) {
1010
+ const routes = await store.route.findMany({
1011
+ where: {
1012
+ market: {
1013
+ equals: params.market
1014
+ },
1015
+ locale: {
1016
+ equals: params.locale
1017
+ }
1018
+ /*
1019
+ ...(params.market ? { market: { equals: params.market } } : {}),
1020
+ ...(params.locale ? { locale: { equals: params.locale } } : {}),
1021
+ */
1022
+ }
1023
+ });
1024
+ return items.map((item) => {
1025
+ const route = routes.find(
1026
+ (x) => x.schema === item.schema && x.page === item.id
1027
+ );
1028
+ const href = route ? route.id : null;
1029
+ return { ...item, href };
1030
+ });
1031
+ } else {
903
1032
  return items;
904
1033
  }
905
- async findPaged(params = {}) {
906
- const pagination = await super.findPaged(params);
907
- if (params.market && params.locale) {
908
- pagination.docs = await decorateHrefs(this.store, pagination.docs, params.market, params.locale);
909
- }
910
- return pagination;
1034
+ }
1035
+ async function decorateNav_(store, item, params = {}, routes) {
1036
+ if (!routes) {
1037
+ routes = await store.route.findMany({
1038
+ where: {
1039
+ ...params.market ? { market: { equals: params.market } } : {},
1040
+ ...params.locale ? { locale: { equals: params.locale } } : {}
1041
+ }
1042
+ });
911
1043
  }
912
- decorator_(item, params = {}) {
913
- if (params.locale) {
914
- return (0, import_bom_core6.localizeItem)(item, params.locale);
915
- } else {
916
- return item;
917
- }
1044
+ const navs = collectNavs_(item);
1045
+ for (const nav of navs) {
1046
+ const decoratedNav = decorateNav__(nav, routes);
1047
+ nav.nav = decoratedNav.nav;
918
1048
  }
919
- };
920
- async function decorateHref(store, item, market = "ww", locale = "en") {
1049
+ return item;
1050
+ }
1051
+ async function decorateNavs_(store, items, params = {}) {
921
1052
  const routes = await store.route.findMany({
1053
+ ...params,
922
1054
  where: {
923
- schema: {
924
- equals: item.schema
925
- },
926
- page: {
927
- equals: item.id
928
- },
929
- market: {
930
- equals: market
931
- },
932
- locale: {
933
- equals: locale
934
- }
1055
+ ...params.market ? { market: { equals: params.market } } : {},
1056
+ ...params.locale ? { locale: { equals: params.locale } } : {}
935
1057
  }
936
1058
  });
937
- const href = routes.length ? routes[0].id : null;
938
- return { ...item, href };
1059
+ for (const item of items) {
1060
+ await decorateNav_(store, item, params, routes);
1061
+ }
1062
+ return items;
939
1063
  }
940
- async function decorateHrefs(store, items, market = "ww", locale = "en") {
941
- const routes = await store.route.findMany();
942
- return items.map((item) => {
1064
+ function collectNavs_(item, navs = []) {
1065
+ if ((0, import_bom_core5.isUndecoratedNav)(item)) {
1066
+ navs.push(item);
1067
+ }
1068
+ if ((0, import_bom_core5.isArray)(item)) {
1069
+ item.forEach((x) => collectNavs_(x, navs));
1070
+ } else if ((0, import_bom_core5.isObject)(item)) {
1071
+ Object.values(item).forEach((value) => {
1072
+ collectNavs_(value, navs);
1073
+ });
1074
+ }
1075
+ return navs;
1076
+ }
1077
+ function decorateNav__(item, routes) {
1078
+ const { nav, ...undecorated } = item;
1079
+ if (nav !== void 0) {
1080
+ const decorated = { ...undecorated };
943
1081
  const route = routes.find(
944
- (x) => x.schema === item.schema && x.page === item.id && x.market === market && x.locale === locale
1082
+ (x) => x.page === nav.page.value && x.schema === nav.page.relationTo
945
1083
  );
946
- const href = route ? route.id : null;
947
- return { ...item, href };
948
- });
1084
+ if (route) {
1085
+ decorated.nav = {
1086
+ type: "page",
1087
+ id: route.id,
1088
+ href: route.id,
1089
+ title: route.title,
1090
+ page: nav.page.value,
1091
+ schema: nav.page.relationTo
1092
+ };
1093
+ }
1094
+ return decorated;
1095
+ }
1096
+ return undecorated;
949
1097
  }
950
1098
 
951
1099
  // src/mock/mock.store.ts
@@ -985,7 +1133,7 @@ function getMockStoreFromData_(data) {
985
1133
  return store;
986
1134
  }
987
1135
  async function getStoreData_() {
988
- if (import_bom_core7.isDevelopment) {
1136
+ if (import_bom_core6.isDevelopment) {
989
1137
  const path = require("path");
990
1138
  const pathname = path.join(process.cwd(), ".mixer", "store.json");
991
1139
  return await fsReadJson(pathname) || {};
@@ -1004,26 +1152,26 @@ async function getMockStore() {
1004
1152
  console.log("getMockStore");
1005
1153
  const store = await getMockStore_();
1006
1154
  return store;
1007
- }, import_bom_core7.isDevelopment ? void 0 : "STORE_MOCK_");
1155
+ }, import_bom_core6.isDevelopment ? void 0 : "STORE_MOCK_");
1008
1156
  }
1009
1157
 
1010
1158
  // src/remote/remote.store.ts
1011
- var import_bom_core10 = require("@websolutespa/bom-core");
1159
+ var import_bom_core9 = require("@websolutespa/bom-core");
1012
1160
 
1013
1161
  // src/remote/remote.api.ts
1014
- var import_bom_core8 = require("@websolutespa/bom-core");
1162
+ var import_bom_core7 = require("@websolutespa/bom-core");
1015
1163
  var API_URL3 = process.env.STORE_URL;
1016
1164
  var API_BASE4 = process.env.STORE_API || "/api";
1017
1165
  function getRemoteApiUrl(pathname) {
1018
1166
  let url = `${API_URL3}${API_BASE4}${pathname}`;
1019
- url = import_bom_core8.isBrowser ? url : url.replace("://localhost", "://127.0.0.1");
1167
+ url = import_bom_core7.isBrowser ? url : url.replace("://localhost", "://127.0.0.1");
1020
1168
  console.log("getRemoteApiUrl", url);
1021
1169
  return url;
1022
1170
  }
1023
1171
  async function remoteApiFetch(pathname, options = {}) {
1024
1172
  const url = getRemoteApiUrl(pathname);
1025
- const apiOptions = (0, import_bom_core8.merge)({ ...getDefaultApiRequestOptions() }, options);
1026
- const apiResponse = await (0, import_bom_core8.httpFetch)(url, apiOptions);
1173
+ const apiOptions = (0, import_bom_core7.merge)({ ...getDefaultApiRequestOptions() }, options);
1174
+ const apiResponse = await (0, import_bom_core7.httpFetch)(url, apiOptions);
1027
1175
  return apiResponse;
1028
1176
  }
1029
1177
  async function remoteApiGet(url, options = {}) {
@@ -1043,7 +1191,7 @@ async function remoteApiDelete(url, options = {}) {
1043
1191
  }
1044
1192
 
1045
1193
  // src/remote/remote.service.ts
1046
- var import_bom_core9 = require("@websolutespa/bom-core");
1194
+ var import_bom_core8 = require("@websolutespa/bom-core");
1047
1195
  var RemoteService = class {
1048
1196
  constructor(key) {
1049
1197
  if (!key) {
@@ -1053,46 +1201,49 @@ var RemoteService = class {
1053
1201
  }
1054
1202
  async findOne(id, params = {}) {
1055
1203
  params.richText = String(params.richText) === "true" ? true : false;
1056
- const query = (0, import_bom_core9.qsSerialize)(params);
1204
+ const query = (0, import_bom_core8.qsSerialize)(params);
1057
1205
  const search = query ? `?${query}` : "";
1058
1206
  const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
1059
1207
  const item = await remoteApiGet(url);
1060
1208
  if (item) {
1061
- return this.decorator_(item, params);
1209
+ return await this.decorateOne_(item, params);
1062
1210
  }
1063
1211
  return;
1064
1212
  }
1065
1213
  async findMany(params = {}) {
1066
1214
  params.richText = String(params.richText) === "true" ? true : false;
1067
1215
  params.pagination = false;
1068
- const query = (0, import_bom_core9.qsSerialize)(params);
1216
+ const query = (0, import_bom_core8.qsSerialize)(params);
1069
1217
  const search = query ? `?${query}` : "";
1070
1218
  const url = `/${this.key}${search}`;
1071
1219
  const response = await remoteApiGet(url);
1072
1220
  const items = Array.isArray(response.docs) ? response.docs : response;
1073
- return items.map((x) => this.decorator_(x, params));
1221
+ return await this.decorateMany_(items, params);
1074
1222
  }
1075
1223
  async findPaged(params = {}) {
1076
1224
  params.richText = String(params.richText) === "true" ? true : false;
1077
1225
  params.pagination = true;
1078
- const query = (0, import_bom_core9.qsSerialize)(params);
1226
+ const query = (0, import_bom_core8.qsSerialize)(params);
1079
1227
  const search = query ? `?${query}` : "";
1080
1228
  const url = `/${this.key}${search}`;
1081
1229
  const response = await remoteApiGet(url);
1082
1230
  let items = response.docs;
1083
- items = items.map((x) => this.decorator_(x, params));
1231
+ items = await this.decorateMany_(items, params);
1084
1232
  return { ...response, docs: items };
1085
1233
  }
1234
+ // !!! todo params
1086
1235
  async create(payload) {
1087
1236
  const url = `/${this.key}`;
1088
1237
  const item = await remoteApiPost(url, payload);
1089
- return this.decorator_(item);
1238
+ return await this.decorateOne_(item, {});
1090
1239
  }
1240
+ // !!! todo params
1091
1241
  async update(payload) {
1092
1242
  const url = `/${this.key}`;
1093
1243
  const item = await remoteApiPut(url, payload);
1094
- return this.decorator_(item);
1244
+ return await this.decorateOne_(item, {});
1095
1245
  }
1246
+ // !!! todo params
1096
1247
  async delete(id) {
1097
1248
  const params = {
1098
1249
  where: {
@@ -1101,16 +1252,18 @@ var RemoteService = class {
1101
1252
  }
1102
1253
  }
1103
1254
  };
1104
- const query = (0, import_bom_core9.qsSerialize)(params);
1255
+ const query = (0, import_bom_core8.qsSerialize)(params);
1105
1256
  const search = query ? `?${query}` : "";
1106
1257
  const url = `/${this.key}${search}`;
1107
1258
  const item = await remoteApiDelete(url);
1108
- return this.decorator_(item);
1259
+ return await this.decorateOne_(item, {});
1109
1260
  }
1110
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1111
- decorator_(item, params = {}) {
1261
+ async decorateOne_(item, params = {}) {
1112
1262
  return item;
1113
1263
  }
1264
+ async decorateMany_(items, params = {}) {
1265
+ return items;
1266
+ }
1114
1267
  };
1115
1268
 
1116
1269
  // src/remote/remote.store.ts
@@ -1135,7 +1288,7 @@ async function getRemoteStore_() {
1135
1288
  }
1136
1289
  });
1137
1290
  return store;
1138
- }, import_bom_core10.isDevelopment ? void 0 : "STORE_RUNTIME_");
1291
+ }, import_bom_core9.isDevelopment ? void 0 : "STORE_RUNTIME_");
1139
1292
  }
1140
1293
  async function getRemoteStoreProductionBuild_() {
1141
1294
  return fromCache(async () => {
@@ -1193,7 +1346,7 @@ function collectionGet(storePromise) {
1193
1346
  const collection = collections[0];
1194
1347
  const id = collections[1];
1195
1348
  const qs = Object.entries(query).map((kv) => kv.join("=")).join("&");
1196
- const params = (0, import_bom_core11.qsDeserialize)(qs);
1349
+ const params = (0, import_bom_core10.qsDeserialize)(qs);
1197
1350
  if (!COLLECTIONS.includes(collection)) {
1198
1351
  console.error("storeHandler.collectionGet", "method not allowed", collection);
1199
1352
  return response.status(405).send("method not allowed");
@@ -1205,7 +1358,7 @@ function collectionGet(storePromise) {
1205
1358
  return response.status(405).send("method not allowed");
1206
1359
  }
1207
1360
  if (id) {
1208
- const item = await service.findOne((0, import_bom_core11.asEquatable)(id), params);
1361
+ const item = await service.findOne((0, import_bom_core10.asEquatable)(id), params);
1209
1362
  if (item) {
1210
1363
  return response.status(200).json(item);
1211
1364
  } else {
@@ -1258,7 +1411,6 @@ function collectionPatch(storePromise) {
1258
1411
  return response.status(405).send("method not allowed");
1259
1412
  }
1260
1413
  const collection = collections[0];
1261
- const id = collections[1];
1262
1414
  const store = await storePromise();
1263
1415
  const service = store[collection];
1264
1416
  if (!service) {
@@ -1388,6 +1540,135 @@ async function routePost(store, request, response) {
1388
1540
  return response.status(400).send("bad request");
1389
1541
  }
1390
1542
  }
1543
+ function storeIndexHandler() {
1544
+ return apiHandler({
1545
+ get: async (request, response) => {
1546
+ try {
1547
+ if (!Array.isArray(COLLECTIONS) || COLLECTIONS?.length === 0) {
1548
+ console.error("apiHome.collectionGet", "collections not found", COLLECTIONS);
1549
+ return response.status(405).send("method not allowed");
1550
+ }
1551
+ response.setHeader("Content-Type", "text/html; charset=UTF-8");
1552
+ response.setHeader("X-Frame-Options", "SAMEORIGIN");
1553
+ response.setHeader("X-Robots-Tag", "noindex, follow");
1554
+ return response.status(200).send(`
1555
+ <html>
1556
+ <head>
1557
+ <title>REST Api</title>
1558
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1559
+ <style type="text/css">
1560
+ html {
1561
+ padding: 0;
1562
+ background: #09090A;
1563
+ color: #fefefe;
1564
+ }
1565
+ body {
1566
+ padding: 15px;
1567
+ font-family: Inter,-apple-system,'Helvetica Neue','Segoe UI',Roboto,Arial,'Noto Sans',sans-serif;
1568
+ font-size: 13px;
1569
+ background: #09090A;
1570
+ color: #fefefe;
1571
+ }
1572
+ .container {
1573
+ margin: 0 auto;
1574
+ max-width: 1280px;
1575
+ }
1576
+ a {
1577
+ color: #fefefe;
1578
+ text-decoration: none;
1579
+ }
1580
+ a:visited {
1581
+ color: #9e9e9e;
1582
+ }
1583
+ a:hover {
1584
+ text-decoration: underline;
1585
+ }
1586
+ table {
1587
+ width: 100%;
1588
+ margin: 10px 0;
1589
+ border: none;
1590
+ border-collapse: collapse;
1591
+ }
1592
+ td,
1593
+ th {
1594
+ text-align: left;
1595
+ font-size: 12px;
1596
+ padding: 3px;
1597
+ }
1598
+ th:not(:last-child),
1599
+ td:not(:last-child) {
1600
+ padding-right: 30px;
1601
+ }
1602
+ thead th {
1603
+ border-bottom: 1px solid #0e0e0f;
1604
+ }
1605
+ #table tr:nth-child(odd) td {
1606
+ background-color: #0e0e0f;
1607
+ }
1608
+ #table tbody tr:hover td {
1609
+ background-color: #1A1A1B;
1610
+ }
1611
+ #table tbody tr:hover td,
1612
+ #table tbody tr:hover td a {
1613
+ color: #fefefe;
1614
+ }
1615
+ .wysiwyg {
1616
+ margin: 0;
1617
+ padding: 0 0 10px 0;
1618
+ line-height: 1.2em;
1619
+ }
1620
+ .wysiwyg a {
1621
+ color: #00ea4e;
1622
+ font-weight: 600;
1623
+ }
1624
+ .wysiwyg a:visited {
1625
+ color: #00ea4e;
1626
+ }
1627
+ </style>
1628
+ </head>
1629
+ <body>
1630
+ <div class="container">
1631
+ <h1>REST API</h1>
1632
+ <p class="wysiwyg">
1633
+ This is the REST Api generated by <a href="https://github.com/websolutespa/bom" target="_blank" rel="noopener">Mixer</a>.
1634
+ </p>
1635
+ <p class="wysiwyg">
1636
+ It contains a list of all the generic local api CRUD handlers of Mixer app. <br />
1637
+ All methods should be called with market and locale parameters.
1638
+ </p>
1639
+ <table id="table" cellpadding="3">
1640
+ <thead>
1641
+ <tr>
1642
+ <th width="150px">Method</th>
1643
+ <th width="150px">Collection</th>
1644
+ <th>Endpoint</th>
1645
+ </tr>
1646
+ </thead>
1647
+ <tbody>
1648
+ ${COLLECTIONS.map((c) => `
1649
+ <tr>
1650
+ <td>GET, POST, PATCH</td>
1651
+ <td>${c}</td>
1652
+ <td><a href="/api/${c}?market={market}&locale={locale}">/api/${c}</a></td>
1653
+ </tr>
1654
+ <tr>
1655
+ <td>GET, DELETE</td>
1656
+ <td>${c}</td>
1657
+ <td><a href="/api/${c}/{id}?market={market}&locale={locale}">/api/${c}/{id}</a></td>
1658
+ </tr>
1659
+ `).join("\n")}
1660
+ </tbody>
1661
+ </table>
1662
+ </div>
1663
+ </body>
1664
+ `);
1665
+ } catch (error) {
1666
+ console.error("storeHandler.collectionGet.error", "500", error);
1667
+ throw error;
1668
+ }
1669
+ }
1670
+ });
1671
+ }
1391
1672
 
1392
1673
  // src/mock/mock.handler.ts
1393
1674
  function mockHandler() {
@@ -1416,6 +1697,7 @@ async function storeApiDelete(url, options = {}) {
1416
1697
  COLLECTIONS,
1417
1698
  KNOWN_COLLECTIONS,
1418
1699
  MOCK_COLLECTIONS,
1700
+ MOCK_SERVICE_DEFAULT_DEPTH,
1419
1701
  MockService,
1420
1702
  RemoteService,
1421
1703
  STATIC_COLLECTIONS,
@@ -1426,6 +1708,10 @@ async function storeApiDelete(url, options = {}) {
1426
1708
  collectionGet,
1427
1709
  collectionPatch,
1428
1710
  collectionPost,
1711
+ decorateRelation_,
1712
+ decorateRelations_,
1713
+ decorateStaticRelation_,
1714
+ decorateStaticRelations_,
1429
1715
  defaultApiRequestOptions,
1430
1716
  errorHandler,
1431
1717
  fromCache,
@@ -1436,8 +1722,6 @@ async function storeApiDelete(url, options = {}) {
1436
1722
  getStore,
1437
1723
  isApiRequest,
1438
1724
  isNextRequest,
1439
- isObject,
1440
- isRelation,
1441
1725
  isStaticRequest,
1442
1726
  localApiDelete,
1443
1727
  localApiFetch,
@@ -1445,6 +1729,8 @@ async function storeApiDelete(url, options = {}) {
1445
1729
  localApiPatch,
1446
1730
  localApiPost,
1447
1731
  localApiPut,
1732
+ localizeItem_,
1733
+ localizeItems_,
1448
1734
  mockApiDelete,
1449
1735
  mockApiFetch,
1450
1736
  mockApiGet,
@@ -1466,5 +1752,6 @@ async function storeApiDelete(url, options = {}) {
1466
1752
  storeApiPost,
1467
1753
  storeApiPut,
1468
1754
  storeHandler,
1755
+ storeIndexHandler,
1469
1756
  storeStrategy
1470
1757
  });