@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/CHANGELOG.md +7 -0
- package/dist/index.d.ts +17 -10
- package/dist/index.js +569 -282
- package/dist/index.mjs +545 -266
- package/package.json +1 -1
- package/src/mock/mock-menu.service.ts +63 -28
- package/src/mock/mock-page.service.ts +133 -54
- package/src/mock/mock.service.ts +120 -45
- package/src/remote/remote.service.ts +14 -9
- package/src/static/static.service.ts +67 -50
- package/src/store/store.handler.ts +140 -8
- package/src/store/store.ts +3 -2
package/dist/index.mjs
CHANGED
|
@@ -154,66 +154,6 @@ async function mockApiDelete(url, options = {}) {
|
|
|
154
154
|
// src/store/store.handler.ts
|
|
155
155
|
import { asEquatable, qsDeserialize } from "@websolutespa/bom-core";
|
|
156
156
|
|
|
157
|
-
// src/store/store.ts
|
|
158
|
-
var StoreStrategy = /* @__PURE__ */ ((StoreStrategy2) => {
|
|
159
|
-
StoreStrategy2["Api"] = "api";
|
|
160
|
-
StoreStrategy2["Data"] = "data";
|
|
161
|
-
StoreStrategy2["Mock"] = "mock";
|
|
162
|
-
return StoreStrategy2;
|
|
163
|
-
})(StoreStrategy || {});
|
|
164
|
-
function getStoreStrategy() {
|
|
165
|
-
let storeStrategy2 = "mock" /* Mock */;
|
|
166
|
-
if (process && process.env.STORE_STRATEGY) {
|
|
167
|
-
storeStrategy2 = process.env.STORE_STRATEGY;
|
|
168
|
-
}
|
|
169
|
-
return storeStrategy2;
|
|
170
|
-
}
|
|
171
|
-
var storeStrategy = getStoreStrategy();
|
|
172
|
-
var ENV_COLLECTIONS = process.env.COLLECTIONS ? process.env.COLLECTIONS.split(",") : [];
|
|
173
|
-
var MOCK_COLLECTIONS = process.env.MOCKS ? process.env.MOCKS.split(",") : [];
|
|
174
|
-
var STATIC_COLLECTIONS = [];
|
|
175
|
-
var KNOWN_COLLECTIONS = [
|
|
176
|
-
"category",
|
|
177
|
-
"label",
|
|
178
|
-
"locale",
|
|
179
|
-
"market",
|
|
180
|
-
"menu",
|
|
181
|
-
"template",
|
|
182
|
-
"page",
|
|
183
|
-
"redirect",
|
|
184
|
-
"route",
|
|
185
|
-
...STATIC_COLLECTIONS
|
|
186
|
-
];
|
|
187
|
-
var COLLECTIONS = [...ENV_COLLECTIONS, ...KNOWN_COLLECTIONS];
|
|
188
|
-
|
|
189
|
-
// src/mock/mock.store.ts
|
|
190
|
-
import { isDevelopment } from "@websolutespa/bom-core";
|
|
191
|
-
|
|
192
|
-
// src/fs/fs.service.ts
|
|
193
|
-
import * as fs from "fs";
|
|
194
|
-
async function fsRead(pathname, option) {
|
|
195
|
-
try {
|
|
196
|
-
const data = await fs.promises.readFile(pathname, option?.encoding || "utf8");
|
|
197
|
-
return data || void 0;
|
|
198
|
-
} catch (error) {
|
|
199
|
-
console.log("fsRead.error", error, pathname);
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
async function fsReadJson(pathname) {
|
|
204
|
-
try {
|
|
205
|
-
const data = await fsRead(pathname);
|
|
206
|
-
if (data) {
|
|
207
|
-
return JSON.parse(data);
|
|
208
|
-
} else {
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
} catch (error) {
|
|
212
|
-
console.log("fsReadJson.error", error, pathname);
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
157
|
// src/static/static.ts
|
|
218
158
|
var staticCollections = [{
|
|
219
159
|
src: "https://actarian.github.io/cms-i18n-react/api/continent.json",
|
|
@@ -417,15 +357,177 @@ var staticCollections = [{
|
|
|
417
357
|
]
|
|
418
358
|
}];
|
|
419
359
|
|
|
360
|
+
// src/store/store.ts
|
|
361
|
+
var StoreStrategy = /* @__PURE__ */ ((StoreStrategy2) => {
|
|
362
|
+
StoreStrategy2["Api"] = "api";
|
|
363
|
+
StoreStrategy2["Data"] = "data";
|
|
364
|
+
StoreStrategy2["Mock"] = "mock";
|
|
365
|
+
return StoreStrategy2;
|
|
366
|
+
})(StoreStrategy || {});
|
|
367
|
+
function getStoreStrategy() {
|
|
368
|
+
let storeStrategy2 = "mock" /* Mock */;
|
|
369
|
+
if (process && process.env.STORE_STRATEGY) {
|
|
370
|
+
storeStrategy2 = process.env.STORE_STRATEGY;
|
|
371
|
+
}
|
|
372
|
+
return storeStrategy2;
|
|
373
|
+
}
|
|
374
|
+
var storeStrategy = getStoreStrategy();
|
|
375
|
+
var ENV_COLLECTIONS = process.env.COLLECTIONS ? process.env.COLLECTIONS.split(",") : [];
|
|
376
|
+
var MOCK_COLLECTIONS = process.env.MOCKS ? process.env.MOCKS.split(",") : [];
|
|
377
|
+
var STATIC_COLLECTIONS = staticCollections.map((x) => x.slug);
|
|
378
|
+
var KNOWN_COLLECTIONS = [
|
|
379
|
+
"category",
|
|
380
|
+
"label",
|
|
381
|
+
"locale",
|
|
382
|
+
"market",
|
|
383
|
+
"menu",
|
|
384
|
+
"template",
|
|
385
|
+
"redirect",
|
|
386
|
+
"route",
|
|
387
|
+
...STATIC_COLLECTIONS
|
|
388
|
+
];
|
|
389
|
+
var COLLECTIONS = [...ENV_COLLECTIONS, ...KNOWN_COLLECTIONS];
|
|
390
|
+
|
|
391
|
+
// src/mock/mock.store.ts
|
|
392
|
+
import { isDevelopment } from "@websolutespa/bom-core";
|
|
393
|
+
|
|
394
|
+
// src/fs/fs.service.ts
|
|
395
|
+
import * as fs from "fs";
|
|
396
|
+
async function fsRead(pathname, option) {
|
|
397
|
+
try {
|
|
398
|
+
const data = await fs.promises.readFile(pathname, option?.encoding || "utf8");
|
|
399
|
+
return data || void 0;
|
|
400
|
+
} catch (error) {
|
|
401
|
+
console.log("fsRead.error", error, pathname);
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
async function fsReadJson(pathname) {
|
|
406
|
+
try {
|
|
407
|
+
const data = await fsRead(pathname);
|
|
408
|
+
if (data) {
|
|
409
|
+
return JSON.parse(data);
|
|
410
|
+
} else {
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
} catch (error) {
|
|
414
|
+
console.log("fsReadJson.error", error, pathname);
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
420
419
|
// src/static/static.service.ts
|
|
421
|
-
import { JsonService, httpGet
|
|
422
|
-
|
|
420
|
+
import { JsonService as JsonService2, httpGet } from "@websolutespa/bom-core";
|
|
421
|
+
|
|
422
|
+
// src/mock/mock.service.ts
|
|
423
|
+
import { cloneItem, isArray, isObject, isUnresolvedRelation, JsonService, localizeItem } from "@websolutespa/bom-core";
|
|
424
|
+
var MOCK_SERVICE_DEFAULT_DEPTH = 2;
|
|
425
|
+
var MockService = class extends JsonService {
|
|
426
|
+
constructor(items, store) {
|
|
427
|
+
super(items);
|
|
428
|
+
this.store = store;
|
|
429
|
+
}
|
|
430
|
+
async decorateOne_(item, params = {}) {
|
|
431
|
+
let decoratedItem = await localizeItem_(item, params);
|
|
432
|
+
decoratedItem = await decorateRelation_(this.store, decoratedItem, {
|
|
433
|
+
market: params.market,
|
|
434
|
+
locale: params.locale,
|
|
435
|
+
depth: params.depth != null ? params.depth : MOCK_SERVICE_DEFAULT_DEPTH
|
|
436
|
+
});
|
|
437
|
+
return decoratedItem;
|
|
438
|
+
}
|
|
439
|
+
async decorateMany_(items, params = {}) {
|
|
440
|
+
let decoratedItems = await localizeItems_(items, params);
|
|
441
|
+
decoratedItems = await decorateRelations_(this.store, decoratedItems, {
|
|
442
|
+
market: params.market,
|
|
443
|
+
locale: params.locale,
|
|
444
|
+
depth: params.depth != null ? params.depth : MOCK_SERVICE_DEFAULT_DEPTH
|
|
445
|
+
});
|
|
446
|
+
return decoratedItems;
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
async function localizeItem_(item, params = {}) {
|
|
450
|
+
if (params.locale) {
|
|
451
|
+
return localizeItem(item, params.locale);
|
|
452
|
+
} else {
|
|
453
|
+
return cloneItem(item);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
async function localizeItems_(items, params = {}) {
|
|
457
|
+
const decoratedItems = [];
|
|
458
|
+
for (const item of items) {
|
|
459
|
+
const decoratedItem = params.locale ? localizeItem(item, params.locale) : cloneItem(item);
|
|
460
|
+
decoratedItems.push(decoratedItem);
|
|
461
|
+
}
|
|
462
|
+
return decoratedItems;
|
|
463
|
+
}
|
|
464
|
+
function collectRelations_(item, relations = []) {
|
|
465
|
+
if (isObject(item)) {
|
|
466
|
+
Object.entries(item).forEach(([key, value]) => {
|
|
467
|
+
if (key === "relation" && isUnresolvedRelation(value)) {
|
|
468
|
+
if (value.relationTo !== item.schema || value.value !== item.id) {
|
|
469
|
+
relations.push(value);
|
|
470
|
+
}
|
|
471
|
+
} else if (isArray(value)) {
|
|
472
|
+
value.forEach((x) => collectRelations_(x, relations));
|
|
473
|
+
} else if (isObject(value)) {
|
|
474
|
+
collectRelations_(value, relations);
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
return relations;
|
|
479
|
+
}
|
|
480
|
+
async function decorateRelation_(store, item, params = {}) {
|
|
481
|
+
const depth = params.depth != null ? params.depth : MOCK_SERVICE_DEFAULT_DEPTH;
|
|
482
|
+
if (depth === 0) {
|
|
483
|
+
return item;
|
|
484
|
+
}
|
|
485
|
+
const relations = collectRelations_(item);
|
|
486
|
+
for (const relation of relations) {
|
|
487
|
+
const isMany = Array.isArray(relation.value);
|
|
488
|
+
const items = await store[relation.relationTo].findMany({
|
|
489
|
+
...params,
|
|
490
|
+
where: {
|
|
491
|
+
id: { in: isMany ? relation.value : [relation.value] }
|
|
492
|
+
},
|
|
493
|
+
depth: depth - 1
|
|
494
|
+
});
|
|
495
|
+
if (isMany) {
|
|
496
|
+
relation.value = items;
|
|
497
|
+
} else {
|
|
498
|
+
relation.value = items.length ? items[0] : void 0;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return item;
|
|
502
|
+
}
|
|
503
|
+
async function decorateRelations_(store, items, params = {}) {
|
|
504
|
+
for (const item of items) {
|
|
505
|
+
await decorateRelation_(store, item, params);
|
|
506
|
+
}
|
|
507
|
+
return items;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// src/static/static.service.ts
|
|
511
|
+
var StaticService = class extends JsonService2 {
|
|
423
512
|
constructor(config, store) {
|
|
424
513
|
super([]);
|
|
425
514
|
this.loaded = false;
|
|
426
515
|
this.config = config;
|
|
427
516
|
this.store = store;
|
|
428
517
|
}
|
|
518
|
+
mapItems_(items, map) {
|
|
519
|
+
if (typeof map === "object") {
|
|
520
|
+
items = items.map((x) => {
|
|
521
|
+
const item = {};
|
|
522
|
+
Object.entries(x).forEach(([k, v]) => {
|
|
523
|
+
const key = map[k] || k;
|
|
524
|
+
item[key] = v;
|
|
525
|
+
});
|
|
526
|
+
return item;
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
return items;
|
|
530
|
+
}
|
|
429
531
|
async getItems() {
|
|
430
532
|
let items = this.items;
|
|
431
533
|
if (this.loaded && items) {
|
|
@@ -451,163 +553,121 @@ var StaticService = class extends JsonService {
|
|
|
451
553
|
return items;
|
|
452
554
|
}
|
|
453
555
|
}
|
|
454
|
-
async
|
|
455
|
-
let
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
item = await this.relatedItems_(item, this.config.fields);
|
|
463
|
-
}
|
|
464
|
-
return this.decorator_(item, params);
|
|
465
|
-
} else {
|
|
466
|
-
console.log("StaticService.findOne.notfound", id, params);
|
|
467
|
-
return void 0;
|
|
468
|
-
}
|
|
556
|
+
async decorateOne_(item, params = {}) {
|
|
557
|
+
let decoratedItem = await localizeItem_(item, params);
|
|
558
|
+
decoratedItem = await decorateStaticRelation_(this.store, this.config.fields, decoratedItem, {
|
|
559
|
+
market: params.market,
|
|
560
|
+
locale: params.locale,
|
|
561
|
+
depth: params.depth
|
|
562
|
+
});
|
|
563
|
+
return decoratedItem;
|
|
469
564
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
return item;
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
return items;
|
|
565
|
+
async decorateMany_(items, params = {}) {
|
|
566
|
+
let decoratedItems = await localizeItems_(items, params);
|
|
567
|
+
decoratedItems = await decorateStaticRelations_(this.store, this.config.fields, decoratedItems, {
|
|
568
|
+
market: params.market,
|
|
569
|
+
locale: params.locale,
|
|
570
|
+
depth: params.depth
|
|
571
|
+
});
|
|
572
|
+
return decoratedItems;
|
|
482
573
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
574
|
+
};
|
|
575
|
+
async function decorateStaticRelation_(store, fields, item, params = {}) {
|
|
576
|
+
const depth = params.depth != null ? params.depth : MOCK_SERVICE_DEFAULT_DEPTH;
|
|
577
|
+
if (depth === 0) {
|
|
578
|
+
return item;
|
|
579
|
+
}
|
|
580
|
+
const decoratedItem = { ...item };
|
|
581
|
+
for (const field of fields) {
|
|
582
|
+
if (field.type === "relationship" && typeof field.relationTo === "string") {
|
|
583
|
+
const name = field.name;
|
|
584
|
+
const value = item[name];
|
|
585
|
+
const ids = field.hasMany ? value : [value];
|
|
586
|
+
const items = await store[field.relationTo].findMany({
|
|
587
|
+
where: {
|
|
588
|
+
id: { in: ids }
|
|
589
|
+
},
|
|
590
|
+
depth: depth - 1,
|
|
591
|
+
locale: params.locale
|
|
592
|
+
});
|
|
593
|
+
if (field.hasMany) {
|
|
594
|
+
decoratedItem[name] = items;
|
|
595
|
+
} else {
|
|
596
|
+
decoratedItem[name] = items.length ? items[0] : void 0;
|
|
497
597
|
}
|
|
498
598
|
}
|
|
499
|
-
return x;
|
|
500
599
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
600
|
+
return decoratedItem;
|
|
601
|
+
}
|
|
602
|
+
async function decorateStaticRelations_(store, fields, items, params = {}) {
|
|
603
|
+
const decoratedItems = [];
|
|
604
|
+
for (const item of items) {
|
|
605
|
+
const decoratedItem = await decorateStaticRelation_(store, fields, item, params);
|
|
606
|
+
decoratedItems.push(decoratedItem);
|
|
506
607
|
}
|
|
507
|
-
|
|
608
|
+
return decoratedItems;
|
|
609
|
+
}
|
|
508
610
|
|
|
509
611
|
// src/mock/mock-menu.service.ts
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
// src/mock/mock.service.ts
|
|
515
|
-
import { JsonService as JsonService2, localizeItem as localizeItem2 } from "@websolutespa/bom-core";
|
|
516
|
-
var MockService = class extends JsonService2 {
|
|
517
|
-
constructor(items, store) {
|
|
518
|
-
super(items);
|
|
519
|
-
this.store = store;
|
|
520
|
-
}
|
|
521
|
-
// !!! todo handle relations
|
|
612
|
+
var MAX_INT = 1e12;
|
|
613
|
+
var UID = 0;
|
|
614
|
+
var MockMenuService = class extends MockService {
|
|
522
615
|
/*
|
|
523
|
-
|
|
524
|
-
console.log('
|
|
616
|
+
async findOne<B extends T = T>(id: IEquatable, params: QueryParams = {}): Promise<B | undefined> {
|
|
617
|
+
// console.log('MockMenuService.findOne', id, params);
|
|
525
618
|
let item = await super.findOne<B>(id, params);
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
}
|
|
619
|
+
if (item && params.market && params.locale) {
|
|
620
|
+
item = await decorateMenu_(this.store, (item as any), {
|
|
621
|
+
market: params.market,
|
|
622
|
+
locale: params.locale,
|
|
623
|
+
}) as any;
|
|
531
624
|
}
|
|
532
625
|
return item;
|
|
533
626
|
}
|
|
534
627
|
|
|
535
|
-
|
|
536
|
-
// console.log('
|
|
628
|
+
async findMany<B extends T = T>(params: QueryParams = {}): Promise<B[]> {
|
|
629
|
+
// console.log('MockMenuService.findMany', params);
|
|
537
630
|
let items = await super.findMany<B>(params);
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
631
|
+
if (params.market && params.locale) {
|
|
632
|
+
items = await decorateMenus_(this.store, (items as any[]), {
|
|
633
|
+
market: params.market,
|
|
634
|
+
locale: params.locale,
|
|
635
|
+
}) as any[];
|
|
541
636
|
}
|
|
542
637
|
return items;
|
|
543
638
|
}
|
|
544
639
|
|
|
545
|
-
|
|
546
|
-
// console.log('
|
|
640
|
+
async findPaged<B extends T = T>(params: QueryParams = {}): Promise<{ docs: B[]; } & Pagination> {
|
|
641
|
+
// console.log('MockMenuService.findPaged', params);
|
|
547
642
|
const pagination = await super.findPaged<B>(params);
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
643
|
+
if (params.market && params.locale) {
|
|
644
|
+
pagination.docs = await decorateMenus_(this.store, (pagination.docs as any[]), {
|
|
645
|
+
market: params.market,
|
|
646
|
+
locale: params.locale,
|
|
647
|
+
}) as any[];
|
|
551
648
|
}
|
|
552
649
|
return pagination;
|
|
553
650
|
}
|
|
554
|
-
|
|
555
|
-
protected async relatedItems_<B extends T = T>(item: B): Promise<B> {
|
|
556
|
-
const x = { ...item };
|
|
557
|
-
Object.entries(item).forEach(([k, v]) => {
|
|
558
|
-
if (isRelation(v)) {
|
|
559
|
-
console.log(k, v);
|
|
560
|
-
}
|
|
561
|
-
});
|
|
562
|
-
return x;
|
|
563
|
-
}
|
|
564
651
|
*/
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
return localizeItem2(item, params.locale);
|
|
568
|
-
} else {
|
|
569
|
-
return item;
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
};
|
|
573
|
-
function isObject(item) {
|
|
574
|
-
return item !== null && typeof item === "object";
|
|
575
|
-
}
|
|
576
|
-
function isRelation(item) {
|
|
577
|
-
return isObject(item) && typeof item.relationTo === "string" && item.value !== void 0;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// src/mock/mock-menu.service.ts
|
|
581
|
-
var MAX_INT = 1e12;
|
|
582
|
-
var UID = 0;
|
|
583
|
-
var MockMenuService = class extends MockService {
|
|
584
|
-
async findOne(id, params = {}) {
|
|
585
|
-
let item = await super.findOne(id, params);
|
|
586
|
-
if (item && params.market && params.locale) {
|
|
587
|
-
item = await decorateMenu(this.store, item, params.market, params.locale);
|
|
588
|
-
}
|
|
589
|
-
return item;
|
|
590
|
-
}
|
|
591
|
-
async findMany(params = {}) {
|
|
592
|
-
let items = await super.findMany(params);
|
|
652
|
+
async decorateOne_(item, params = {}) {
|
|
653
|
+
let decoratedItem = await localizeItem_(item, params);
|
|
593
654
|
if (params.market && params.locale) {
|
|
594
|
-
|
|
655
|
+
decoratedItem = await decorateMenu_(this.store, decoratedItem, {
|
|
656
|
+
market: params.market,
|
|
657
|
+
locale: params.locale
|
|
658
|
+
});
|
|
595
659
|
}
|
|
596
|
-
return
|
|
660
|
+
return decoratedItem;
|
|
597
661
|
}
|
|
598
|
-
async
|
|
599
|
-
|
|
662
|
+
async decorateMany_(items, params = {}) {
|
|
663
|
+
let decoratedItems = await localizeItems_(items, params);
|
|
600
664
|
if (params.market && params.locale) {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
decorator_(item, params = {}) {
|
|
606
|
-
if (params.locale) {
|
|
607
|
-
return localizeItem3(item, params.locale);
|
|
608
|
-
} else {
|
|
609
|
-
return item;
|
|
665
|
+
decoratedItems = await decorateMenus_(this.store, decoratedItems, {
|
|
666
|
+
market: params.market,
|
|
667
|
+
locale: params.locale
|
|
668
|
+
});
|
|
610
669
|
}
|
|
670
|
+
return decoratedItems;
|
|
611
671
|
}
|
|
612
672
|
};
|
|
613
673
|
async function collectPages(store, items, params = {}) {
|
|
@@ -620,15 +680,15 @@ async function collectPages(store, items, params = {}) {
|
|
|
620
680
|
if (value) {
|
|
621
681
|
const routes = await store.route.findMany({
|
|
622
682
|
where: {
|
|
683
|
+
...params.market ? { market: { equals: params.market } } : {},
|
|
684
|
+
...params.locale ? { locale: { equals: params.locale } } : {},
|
|
623
685
|
page: {
|
|
624
686
|
equals: item.page.value
|
|
625
687
|
},
|
|
626
688
|
schema: {
|
|
627
689
|
equals: item.page.relationTo
|
|
628
690
|
}
|
|
629
|
-
}
|
|
630
|
-
market: params.market,
|
|
631
|
-
locale: params.locale
|
|
691
|
+
}
|
|
632
692
|
});
|
|
633
693
|
const page = {
|
|
634
694
|
...value,
|
|
@@ -646,31 +706,31 @@ async function collectPages(store, items, params = {}) {
|
|
|
646
706
|
}
|
|
647
707
|
}
|
|
648
708
|
}
|
|
649
|
-
async function
|
|
709
|
+
async function decorateMenu_(store, item, params) {
|
|
650
710
|
const items = item.items || [];
|
|
651
711
|
const decoratedItem = {
|
|
652
712
|
id: item.id,
|
|
653
713
|
items: []
|
|
654
714
|
};
|
|
655
|
-
const categories = await store.category.findMany(
|
|
715
|
+
const categories = await store.category.findMany(params);
|
|
656
716
|
const routes = await store.route.findMany({
|
|
717
|
+
...params,
|
|
657
718
|
where: {
|
|
658
|
-
market: {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
locale: {
|
|
662
|
-
equals: locale
|
|
663
|
-
}
|
|
664
|
-
},
|
|
665
|
-
market,
|
|
666
|
-
locale
|
|
719
|
+
...params.market ? { market: { equals: params.market } } : {},
|
|
720
|
+
...params.locale ? { locale: { equals: params.locale } } : {}
|
|
721
|
+
}
|
|
667
722
|
});
|
|
668
|
-
await collectPages(store, items,
|
|
669
|
-
decoratedItem.items = items.filter((x) => hasMarket(x, market)).map((x) => decorateMenuItem(x, categories, routes, market));
|
|
723
|
+
await collectPages(store, items, params);
|
|
724
|
+
decoratedItem.items = items.filter((x) => hasMarket(x, params.market)).map((x) => decorateMenuItem(x, categories, routes, params.market));
|
|
670
725
|
return decoratedItem;
|
|
671
726
|
}
|
|
672
|
-
async function
|
|
673
|
-
|
|
727
|
+
async function decorateMenus_(store, items, params) {
|
|
728
|
+
const decoratedItems = [];
|
|
729
|
+
for (const item of items) {
|
|
730
|
+
const decoratedItem = await decorateMenu_(store, item, params);
|
|
731
|
+
decoratedItems.push(decoratedItem);
|
|
732
|
+
}
|
|
733
|
+
return decoratedItems;
|
|
674
734
|
}
|
|
675
735
|
function decorateMenuCategory(item, categories, routes, market, depth = 0) {
|
|
676
736
|
const decoratedItem = {
|
|
@@ -762,7 +822,9 @@ function decorateMenuLink(item, categories, routes, market) {
|
|
|
762
822
|
}
|
|
763
823
|
function decorateMenuPage(item, categories, routes, market) {
|
|
764
824
|
const items = item.items || [];
|
|
765
|
-
const route = routes.find(
|
|
825
|
+
const route = routes.find(
|
|
826
|
+
(x) => x.schema === item.page.relationTo && x.page === item.page.value.id
|
|
827
|
+
);
|
|
766
828
|
const decoratedItem = {
|
|
767
829
|
id: item.id || "",
|
|
768
830
|
type: item.type,
|
|
@@ -807,66 +869,144 @@ function hasMarket(item, market) {
|
|
|
807
869
|
}
|
|
808
870
|
|
|
809
871
|
// src/mock/mock-page.service.ts
|
|
810
|
-
import {
|
|
872
|
+
import { isArray as isArray2, isObject as isObject2, isUndecoratedNav } from "@websolutespa/bom-core";
|
|
811
873
|
var MockPageService = class extends MockService {
|
|
812
|
-
async
|
|
813
|
-
let
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
874
|
+
async decorateOne_(item, params = {}) {
|
|
875
|
+
let decoratedItem = await localizeItem_(item, params);
|
|
876
|
+
decoratedItem = await decorateHref_(this.store, decoratedItem, params);
|
|
877
|
+
decoratedItem = await decorateNav_(this.store, decoratedItem, params);
|
|
878
|
+
decoratedItem = await decorateRelation_(this.store, decoratedItem, {
|
|
879
|
+
market: params.market,
|
|
880
|
+
locale: params.locale,
|
|
881
|
+
depth: params.depth
|
|
882
|
+
});
|
|
883
|
+
return decoratedItem;
|
|
884
|
+
}
|
|
885
|
+
async decorateMany_(items, params = {}) {
|
|
886
|
+
let decoratedItems = await localizeItems_(items, params);
|
|
887
|
+
decoratedItems = await decorateHrefs_(this.store, decoratedItems, params);
|
|
888
|
+
decoratedItems = await decorateNavs_(this.store, decoratedItems, params);
|
|
889
|
+
decoratedItems = await decorateRelations_(this.store, decoratedItems, {
|
|
890
|
+
market: params.market,
|
|
891
|
+
locale: params.locale,
|
|
892
|
+
depth: params.depth
|
|
893
|
+
});
|
|
894
|
+
return decoratedItems;
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
async function decorateHref_(store, item, params = {}) {
|
|
898
|
+
if (params.market && params.locale) {
|
|
899
|
+
const routes = await store.route.findMany({
|
|
900
|
+
where: {
|
|
901
|
+
market: {
|
|
902
|
+
equals: params.market
|
|
903
|
+
},
|
|
904
|
+
locale: {
|
|
905
|
+
equals: params.locale
|
|
906
|
+
},
|
|
907
|
+
schema: {
|
|
908
|
+
equals: item.schema
|
|
909
|
+
},
|
|
910
|
+
page: {
|
|
911
|
+
equals: item.id
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
const href = routes.length ? routes[0].id : null;
|
|
916
|
+
return { ...item, href };
|
|
917
|
+
} else {
|
|
817
918
|
return item;
|
|
818
919
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
920
|
+
}
|
|
921
|
+
async function decorateHrefs_(store, items, params = {}) {
|
|
922
|
+
if (params.market && params.locale) {
|
|
923
|
+
const routes = await store.route.findMany({
|
|
924
|
+
where: {
|
|
925
|
+
market: {
|
|
926
|
+
equals: params.market
|
|
927
|
+
},
|
|
928
|
+
locale: {
|
|
929
|
+
equals: params.locale
|
|
930
|
+
}
|
|
931
|
+
/*
|
|
932
|
+
...(params.market ? { market: { equals: params.market } } : {}),
|
|
933
|
+
...(params.locale ? { locale: { equals: params.locale } } : {}),
|
|
934
|
+
*/
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
return items.map((item) => {
|
|
938
|
+
const route = routes.find(
|
|
939
|
+
(x) => x.schema === item.schema && x.page === item.id
|
|
940
|
+
);
|
|
941
|
+
const href = route ? route.id : null;
|
|
942
|
+
return { ...item, href };
|
|
943
|
+
});
|
|
944
|
+
} else {
|
|
824
945
|
return items;
|
|
825
946
|
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
947
|
+
}
|
|
948
|
+
async function decorateNav_(store, item, params = {}, routes) {
|
|
949
|
+
if (!routes) {
|
|
950
|
+
routes = await store.route.findMany({
|
|
951
|
+
where: {
|
|
952
|
+
...params.market ? { market: { equals: params.market } } : {},
|
|
953
|
+
...params.locale ? { locale: { equals: params.locale } } : {}
|
|
954
|
+
}
|
|
955
|
+
});
|
|
832
956
|
}
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
return item;
|
|
838
|
-
}
|
|
957
|
+
const navs = collectNavs_(item);
|
|
958
|
+
for (const nav of navs) {
|
|
959
|
+
const decoratedNav = decorateNav__(nav, routes);
|
|
960
|
+
nav.nav = decoratedNav.nav;
|
|
839
961
|
}
|
|
840
|
-
|
|
841
|
-
|
|
962
|
+
return item;
|
|
963
|
+
}
|
|
964
|
+
async function decorateNavs_(store, items, params = {}) {
|
|
842
965
|
const routes = await store.route.findMany({
|
|
966
|
+
...params,
|
|
843
967
|
where: {
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
},
|
|
847
|
-
page: {
|
|
848
|
-
equals: item.id
|
|
849
|
-
},
|
|
850
|
-
market: {
|
|
851
|
-
equals: market
|
|
852
|
-
},
|
|
853
|
-
locale: {
|
|
854
|
-
equals: locale
|
|
855
|
-
}
|
|
968
|
+
...params.market ? { market: { equals: params.market } } : {},
|
|
969
|
+
...params.locale ? { locale: { equals: params.locale } } : {}
|
|
856
970
|
}
|
|
857
971
|
});
|
|
858
|
-
const
|
|
859
|
-
|
|
972
|
+
for (const item of items) {
|
|
973
|
+
await decorateNav_(store, item, params, routes);
|
|
974
|
+
}
|
|
975
|
+
return items;
|
|
976
|
+
}
|
|
977
|
+
function collectNavs_(item, navs = []) {
|
|
978
|
+
if (isUndecoratedNav(item)) {
|
|
979
|
+
navs.push(item);
|
|
980
|
+
}
|
|
981
|
+
if (isArray2(item)) {
|
|
982
|
+
item.forEach((x) => collectNavs_(x, navs));
|
|
983
|
+
} else if (isObject2(item)) {
|
|
984
|
+
Object.values(item).forEach((value) => {
|
|
985
|
+
collectNavs_(value, navs);
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
return navs;
|
|
860
989
|
}
|
|
861
|
-
|
|
862
|
-
const
|
|
863
|
-
|
|
990
|
+
function decorateNav__(item, routes) {
|
|
991
|
+
const { nav, ...undecorated } = item;
|
|
992
|
+
if (nav !== void 0) {
|
|
993
|
+
const decorated = { ...undecorated };
|
|
864
994
|
const route = routes.find(
|
|
865
|
-
(x) => x.
|
|
995
|
+
(x) => x.page === nav.page.value && x.schema === nav.page.relationTo
|
|
866
996
|
);
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
997
|
+
if (route) {
|
|
998
|
+
decorated.nav = {
|
|
999
|
+
type: "page",
|
|
1000
|
+
id: route.id,
|
|
1001
|
+
href: route.id,
|
|
1002
|
+
title: route.title,
|
|
1003
|
+
page: nav.page.value,
|
|
1004
|
+
schema: nav.page.relationTo
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
return decorated;
|
|
1008
|
+
}
|
|
1009
|
+
return undecorated;
|
|
870
1010
|
}
|
|
871
1011
|
|
|
872
1012
|
// src/mock/mock.store.ts
|
|
@@ -979,7 +1119,7 @@ var RemoteService = class {
|
|
|
979
1119
|
const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
|
|
980
1120
|
const item = await remoteApiGet(url);
|
|
981
1121
|
if (item) {
|
|
982
|
-
return this.
|
|
1122
|
+
return await this.decorateOne_(item, params);
|
|
983
1123
|
}
|
|
984
1124
|
return;
|
|
985
1125
|
}
|
|
@@ -991,7 +1131,7 @@ var RemoteService = class {
|
|
|
991
1131
|
const url = `/${this.key}${search}`;
|
|
992
1132
|
const response = await remoteApiGet(url);
|
|
993
1133
|
const items = Array.isArray(response.docs) ? response.docs : response;
|
|
994
|
-
return
|
|
1134
|
+
return await this.decorateMany_(items, params);
|
|
995
1135
|
}
|
|
996
1136
|
async findPaged(params = {}) {
|
|
997
1137
|
params.richText = String(params.richText) === "true" ? true : false;
|
|
@@ -1001,19 +1141,22 @@ var RemoteService = class {
|
|
|
1001
1141
|
const url = `/${this.key}${search}`;
|
|
1002
1142
|
const response = await remoteApiGet(url);
|
|
1003
1143
|
let items = response.docs;
|
|
1004
|
-
items =
|
|
1144
|
+
items = await this.decorateMany_(items, params);
|
|
1005
1145
|
return { ...response, docs: items };
|
|
1006
1146
|
}
|
|
1147
|
+
// !!! todo params
|
|
1007
1148
|
async create(payload) {
|
|
1008
1149
|
const url = `/${this.key}`;
|
|
1009
1150
|
const item = await remoteApiPost(url, payload);
|
|
1010
|
-
return this.
|
|
1151
|
+
return await this.decorateOne_(item, {});
|
|
1011
1152
|
}
|
|
1153
|
+
// !!! todo params
|
|
1012
1154
|
async update(payload) {
|
|
1013
1155
|
const url = `/${this.key}`;
|
|
1014
1156
|
const item = await remoteApiPut(url, payload);
|
|
1015
|
-
return this.
|
|
1157
|
+
return await this.decorateOne_(item, {});
|
|
1016
1158
|
}
|
|
1159
|
+
// !!! todo params
|
|
1017
1160
|
async delete(id) {
|
|
1018
1161
|
const params = {
|
|
1019
1162
|
where: {
|
|
@@ -1026,12 +1169,14 @@ var RemoteService = class {
|
|
|
1026
1169
|
const search = query ? `?${query}` : "";
|
|
1027
1170
|
const url = `/${this.key}${search}`;
|
|
1028
1171
|
const item = await remoteApiDelete(url);
|
|
1029
|
-
return this.
|
|
1172
|
+
return await this.decorateOne_(item, {});
|
|
1030
1173
|
}
|
|
1031
|
-
|
|
1032
|
-
decorator_(item, params = {}) {
|
|
1174
|
+
async decorateOne_(item, params = {}) {
|
|
1033
1175
|
return item;
|
|
1034
1176
|
}
|
|
1177
|
+
async decorateMany_(items, params = {}) {
|
|
1178
|
+
return items;
|
|
1179
|
+
}
|
|
1035
1180
|
};
|
|
1036
1181
|
|
|
1037
1182
|
// src/remote/remote.store.ts
|
|
@@ -1179,7 +1324,6 @@ function collectionPatch(storePromise) {
|
|
|
1179
1324
|
return response.status(405).send("method not allowed");
|
|
1180
1325
|
}
|
|
1181
1326
|
const collection = collections[0];
|
|
1182
|
-
const id = collections[1];
|
|
1183
1327
|
const store = await storePromise();
|
|
1184
1328
|
const service = store[collection];
|
|
1185
1329
|
if (!service) {
|
|
@@ -1309,6 +1453,135 @@ async function routePost(store, request, response) {
|
|
|
1309
1453
|
return response.status(400).send("bad request");
|
|
1310
1454
|
}
|
|
1311
1455
|
}
|
|
1456
|
+
function storeIndexHandler() {
|
|
1457
|
+
return apiHandler({
|
|
1458
|
+
get: async (request, response) => {
|
|
1459
|
+
try {
|
|
1460
|
+
if (!Array.isArray(COLLECTIONS) || COLLECTIONS?.length === 0) {
|
|
1461
|
+
console.error("apiHome.collectionGet", "collections not found", COLLECTIONS);
|
|
1462
|
+
return response.status(405).send("method not allowed");
|
|
1463
|
+
}
|
|
1464
|
+
response.setHeader("Content-Type", "text/html; charset=UTF-8");
|
|
1465
|
+
response.setHeader("X-Frame-Options", "SAMEORIGIN");
|
|
1466
|
+
response.setHeader("X-Robots-Tag", "noindex, follow");
|
|
1467
|
+
return response.status(200).send(`
|
|
1468
|
+
<html>
|
|
1469
|
+
<head>
|
|
1470
|
+
<title>REST Api</title>
|
|
1471
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
1472
|
+
<style type="text/css">
|
|
1473
|
+
html {
|
|
1474
|
+
padding: 0;
|
|
1475
|
+
background: #09090A;
|
|
1476
|
+
color: #fefefe;
|
|
1477
|
+
}
|
|
1478
|
+
body {
|
|
1479
|
+
padding: 15px;
|
|
1480
|
+
font-family: Inter,-apple-system,'Helvetica Neue','Segoe UI',Roboto,Arial,'Noto Sans',sans-serif;
|
|
1481
|
+
font-size: 13px;
|
|
1482
|
+
background: #09090A;
|
|
1483
|
+
color: #fefefe;
|
|
1484
|
+
}
|
|
1485
|
+
.container {
|
|
1486
|
+
margin: 0 auto;
|
|
1487
|
+
max-width: 1280px;
|
|
1488
|
+
}
|
|
1489
|
+
a {
|
|
1490
|
+
color: #fefefe;
|
|
1491
|
+
text-decoration: none;
|
|
1492
|
+
}
|
|
1493
|
+
a:visited {
|
|
1494
|
+
color: #9e9e9e;
|
|
1495
|
+
}
|
|
1496
|
+
a:hover {
|
|
1497
|
+
text-decoration: underline;
|
|
1498
|
+
}
|
|
1499
|
+
table {
|
|
1500
|
+
width: 100%;
|
|
1501
|
+
margin: 10px 0;
|
|
1502
|
+
border: none;
|
|
1503
|
+
border-collapse: collapse;
|
|
1504
|
+
}
|
|
1505
|
+
td,
|
|
1506
|
+
th {
|
|
1507
|
+
text-align: left;
|
|
1508
|
+
font-size: 12px;
|
|
1509
|
+
padding: 3px;
|
|
1510
|
+
}
|
|
1511
|
+
th:not(:last-child),
|
|
1512
|
+
td:not(:last-child) {
|
|
1513
|
+
padding-right: 30px;
|
|
1514
|
+
}
|
|
1515
|
+
thead th {
|
|
1516
|
+
border-bottom: 1px solid #0e0e0f;
|
|
1517
|
+
}
|
|
1518
|
+
#table tr:nth-child(odd) td {
|
|
1519
|
+
background-color: #0e0e0f;
|
|
1520
|
+
}
|
|
1521
|
+
#table tbody tr:hover td {
|
|
1522
|
+
background-color: #1A1A1B;
|
|
1523
|
+
}
|
|
1524
|
+
#table tbody tr:hover td,
|
|
1525
|
+
#table tbody tr:hover td a {
|
|
1526
|
+
color: #fefefe;
|
|
1527
|
+
}
|
|
1528
|
+
.wysiwyg {
|
|
1529
|
+
margin: 0;
|
|
1530
|
+
padding: 0 0 10px 0;
|
|
1531
|
+
line-height: 1.2em;
|
|
1532
|
+
}
|
|
1533
|
+
.wysiwyg a {
|
|
1534
|
+
color: #00ea4e;
|
|
1535
|
+
font-weight: 600;
|
|
1536
|
+
}
|
|
1537
|
+
.wysiwyg a:visited {
|
|
1538
|
+
color: #00ea4e;
|
|
1539
|
+
}
|
|
1540
|
+
</style>
|
|
1541
|
+
</head>
|
|
1542
|
+
<body>
|
|
1543
|
+
<div class="container">
|
|
1544
|
+
<h1>REST API</h1>
|
|
1545
|
+
<p class="wysiwyg">
|
|
1546
|
+
This is the REST Api generated by <a href="https://github.com/websolutespa/bom" target="_blank" rel="noopener">Mixer</a>.
|
|
1547
|
+
</p>
|
|
1548
|
+
<p class="wysiwyg">
|
|
1549
|
+
It contains a list of all the generic local api CRUD handlers of Mixer app. <br />
|
|
1550
|
+
All methods should be called with market and locale parameters.
|
|
1551
|
+
</p>
|
|
1552
|
+
<table id="table" cellpadding="3">
|
|
1553
|
+
<thead>
|
|
1554
|
+
<tr>
|
|
1555
|
+
<th width="150px">Method</th>
|
|
1556
|
+
<th width="150px">Collection</th>
|
|
1557
|
+
<th>Endpoint</th>
|
|
1558
|
+
</tr>
|
|
1559
|
+
</thead>
|
|
1560
|
+
<tbody>
|
|
1561
|
+
${COLLECTIONS.map((c) => `
|
|
1562
|
+
<tr>
|
|
1563
|
+
<td>GET, POST, PATCH</td>
|
|
1564
|
+
<td>${c}</td>
|
|
1565
|
+
<td><a href="/api/${c}?market={market}&locale={locale}">/api/${c}</a></td>
|
|
1566
|
+
</tr>
|
|
1567
|
+
<tr>
|
|
1568
|
+
<td>GET, DELETE</td>
|
|
1569
|
+
<td>${c}</td>
|
|
1570
|
+
<td><a href="/api/${c}/{id}?market={market}&locale={locale}">/api/${c}/{id}</a></td>
|
|
1571
|
+
</tr>
|
|
1572
|
+
`).join("\n")}
|
|
1573
|
+
</tbody>
|
|
1574
|
+
</table>
|
|
1575
|
+
</div>
|
|
1576
|
+
</body>
|
|
1577
|
+
`);
|
|
1578
|
+
} catch (error) {
|
|
1579
|
+
console.error("storeHandler.collectionGet.error", "500", error);
|
|
1580
|
+
throw error;
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1312
1585
|
|
|
1313
1586
|
// src/mock/mock.handler.ts
|
|
1314
1587
|
function mockHandler() {
|
|
@@ -1336,6 +1609,7 @@ export {
|
|
|
1336
1609
|
COLLECTIONS,
|
|
1337
1610
|
KNOWN_COLLECTIONS,
|
|
1338
1611
|
MOCK_COLLECTIONS,
|
|
1612
|
+
MOCK_SERVICE_DEFAULT_DEPTH,
|
|
1339
1613
|
MockService,
|
|
1340
1614
|
RemoteService,
|
|
1341
1615
|
STATIC_COLLECTIONS,
|
|
@@ -1346,6 +1620,10 @@ export {
|
|
|
1346
1620
|
collectionGet,
|
|
1347
1621
|
collectionPatch,
|
|
1348
1622
|
collectionPost,
|
|
1623
|
+
decorateRelation_,
|
|
1624
|
+
decorateRelations_,
|
|
1625
|
+
decorateStaticRelation_,
|
|
1626
|
+
decorateStaticRelations_,
|
|
1349
1627
|
defaultApiRequestOptions,
|
|
1350
1628
|
errorHandler,
|
|
1351
1629
|
fromCache,
|
|
@@ -1356,8 +1634,6 @@ export {
|
|
|
1356
1634
|
getStore,
|
|
1357
1635
|
isApiRequest,
|
|
1358
1636
|
isNextRequest,
|
|
1359
|
-
isObject,
|
|
1360
|
-
isRelation,
|
|
1361
1637
|
isStaticRequest,
|
|
1362
1638
|
localApiDelete,
|
|
1363
1639
|
localApiFetch,
|
|
@@ -1365,6 +1641,8 @@ export {
|
|
|
1365
1641
|
localApiPatch,
|
|
1366
1642
|
localApiPost,
|
|
1367
1643
|
localApiPut,
|
|
1644
|
+
localizeItem_,
|
|
1645
|
+
localizeItems_,
|
|
1368
1646
|
mockApiDelete,
|
|
1369
1647
|
mockApiFetch,
|
|
1370
1648
|
mockApiGet,
|
|
@@ -1386,5 +1664,6 @@ export {
|
|
|
1386
1664
|
storeApiPost,
|
|
1387
1665
|
storeApiPut,
|
|
1388
1666
|
storeHandler,
|
|
1667
|
+
storeIndexHandler,
|
|
1389
1668
|
storeStrategy
|
|
1390
1669
|
};
|