@websolutespa/bom-mixer-store 1.8.0 → 1.8.2

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,17 @@
1
1
  # @websolutespa/bom-mixer-store
2
2
 
3
+ ## 1.8.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Modified: getRemoteStoreStaticBuild_
8
+
9
+ ## 1.8.1
10
+
11
+ ### Patch Changes
12
+
13
+ - 15ad595: Modified: getRemoteApiRequestOptions added user Bearer
14
+
3
15
  ## 1.8.0
4
16
 
5
17
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -4,10 +4,10 @@ import { NextRequest } from 'next/server';
4
4
  import * as _websolutespa_bom_mixer_store from '@websolutespa/bom-mixer-store';
5
5
 
6
6
  type ApiRequestOptions = FetchRequestOptions;
7
- /**
8
- * !!! todo: evaluate authenticated end user bearer
9
- */
10
7
  declare function getLocalApiRequestOptions(): ApiRequestOptions;
8
+ declare const REMOTE_API_SESSION: {
9
+ token: string | null;
10
+ };
11
11
  declare function getRemoteApiRequestOptions(): ApiRequestOptions;
12
12
 
13
13
  type ICrudMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | string;
@@ -242,4 +242,4 @@ declare function getStore<T extends IStore>(): Promise<T>;
242
242
 
243
243
  declare function varsHandler(): _websolutespa_bom_mixer_store.IHandler<any>;
244
244
 
245
- export { ApiRequestOptions, BuildStrategy, COLLECTIONS, IApiHandler, ICrudMethod, IField, IHandler, IPageResolvedRelation, KNOWN_COLLECTIONS, MAX_INT, MOCK_COLLECTIONS, MapTo, MockMenuService, MockPageService, MockService, NextPhase, RemoteMenuService, RemotePageService, RemoteService, RemoteServiceStrategy, SERVICE_DEFAULT_DEPTH, STATIC_COLLECTIONS, StaticService, StaticServiceConfig, StaticServiceSrc, StoreStrategy, apiHandler, buildStrategy, collectionDelete, collectionGet, collectionPatch, collectionPost, decorateCategories_, decorateCategory_, decorateHref_, decorateHrefs_, decorateLocalizable_, decorateLocalizables_, decorateMenu_, decorateMenus_, decorateNav_, decorateNavs_, decorateRelation_, decorateRelations_, decorateSchema_, decorateSchemas_, decorateStaticRelation_, decorateStaticRelations_, errorHandler, findRoute, fromCache, getLocalApiRequestOptions, getLocalApiUrl, getMockStore, getMockStoreFromData_, getRemoteApiRequestOptions, getRemoteApiUrl, getRemoteStore, getStore, isApiRequest, isNextRequest, isStaticRequest, localApiDelete, localApiFetch, localApiGet, localApiPatch, localApiPost, localApiPut, mockApiDelete, mockApiFetch, mockApiGet, mockApiPatch, mockApiPost, mockApiPut, mockHandler, nextPhase, optimizeMany_, optimizeOne_, remoteApiDelete, remoteApiFetch, remoteApiGet, remoteApiPatch, remoteApiPost, remoteApiPut, routePost, staticCollections, storeApiDelete, storeApiGet, storeApiPatch, storeApiPost, storeApiPut, storeCacheDuration, storeHandler, storeIndexHandler, storeStrategy, varsHandler };
245
+ export { ApiRequestOptions, BuildStrategy, COLLECTIONS, IApiHandler, ICrudMethod, IField, IHandler, IPageResolvedRelation, KNOWN_COLLECTIONS, MAX_INT, MOCK_COLLECTIONS, MapTo, MockMenuService, MockPageService, MockService, NextPhase, REMOTE_API_SESSION, RemoteMenuService, RemotePageService, RemoteService, RemoteServiceStrategy, SERVICE_DEFAULT_DEPTH, STATIC_COLLECTIONS, StaticService, StaticServiceConfig, StaticServiceSrc, StoreStrategy, apiHandler, buildStrategy, collectionDelete, collectionGet, collectionPatch, collectionPost, decorateCategories_, decorateCategory_, decorateHref_, decorateHrefs_, decorateLocalizable_, decorateLocalizables_, decorateMenu_, decorateMenus_, decorateNav_, decorateNavs_, decorateRelation_, decorateRelations_, decorateSchema_, decorateSchemas_, decorateStaticRelation_, decorateStaticRelations_, errorHandler, findRoute, fromCache, getLocalApiRequestOptions, getLocalApiUrl, getMockStore, getMockStoreFromData_, getRemoteApiRequestOptions, getRemoteApiUrl, getRemoteStore, getStore, isApiRequest, isNextRequest, isStaticRequest, localApiDelete, localApiFetch, localApiGet, localApiPatch, localApiPost, localApiPut, mockApiDelete, mockApiFetch, mockApiGet, mockApiPatch, mockApiPost, mockApiPut, mockHandler, nextPhase, optimizeMany_, optimizeOne_, remoteApiDelete, remoteApiFetch, remoteApiGet, remoteApiPatch, remoteApiPost, remoteApiPut, routePost, staticCollections, storeApiDelete, storeApiGet, storeApiPatch, storeApiPost, storeApiPut, storeCacheDuration, storeHandler, storeIndexHandler, storeStrategy, varsHandler };
package/dist/index.js CHANGED
@@ -39,6 +39,7 @@ __export(src_exports, {
39
39
  MockPageService: () => MockPageService,
40
40
  MockService: () => MockService,
41
41
  NextPhase: () => NextPhase,
42
+ REMOTE_API_SESSION: () => REMOTE_API_SESSION,
42
43
  RemoteMenuService: () => RemoteMenuService,
43
44
  RemotePageService: () => RemotePageService,
44
45
  RemoteService: () => RemoteService,
@@ -126,20 +127,26 @@ function getLocalApiRequestOptions() {
126
127
  headers: {}
127
128
  };
128
129
  }
130
+ var REMOTE_API_SESSION = {
131
+ token: null
132
+ };
129
133
  function getRemoteApiRequestOptions() {
130
- return {
131
- // mode: 'cors',
132
- headers: {
133
- /**
134
- * guest user api key (users)
135
- */
136
- Authorization: `users API-Key ${process.env.STORE_API_KEY}`
137
- /**
138
- * authenticated end user bearer (end_users)
139
- */
140
- // Authorization: `Bearer ${bearer}`,
141
- }
142
- };
134
+ if (REMOTE_API_SESSION.token) {
135
+ return {
136
+ // mode: 'cors',
137
+ headers: {
138
+ Authorization: `Bearer ${REMOTE_API_SESSION.token}`
139
+ // Authorization: `JWT ${REMOTE_API_SESSION.token}`,
140
+ }
141
+ };
142
+ } else {
143
+ return {
144
+ // mode: 'cors',
145
+ headers: {
146
+ Authorization: `users API-Key ${process.env.STORE_API_KEY}`
147
+ }
148
+ };
149
+ }
143
150
  }
144
151
 
145
152
  // src/api/api.handler.ts
@@ -512,7 +519,7 @@ async function decorateNav_(store, item, params = {}, routes) {
512
519
  const navs = collectNavs_(item);
513
520
  for (const nav of navs) {
514
521
  const decoratedNav = decorateNav__(nav, routes);
515
- nav.nav = decoratedNav.nav;
522
+ Object.assign(nav, decoratedNav);
516
523
  }
517
524
  return item;
518
525
  }
@@ -542,14 +549,13 @@ function collectNavs_(item, navs = []) {
542
549
  return navs;
543
550
  }
544
551
  function decorateNav__(item, routes) {
545
- const { nav, ...undecorated } = item;
546
- if (nav !== void 0) {
547
- const decorated = { ...undecorated };
552
+ let decoratedNav = item;
553
+ if (item !== void 0) {
548
554
  const route = routes.find(
549
- (x) => x.page === nav.page.value && x.schema === nav.page.relationTo
555
+ (x) => x.page === item.page.value && x.schema === item.page.relationTo
550
556
  );
551
557
  if (route) {
552
- decorated.nav = {
558
+ decoratedNav = {
553
559
  type: "page",
554
560
  id: route.page,
555
561
  href: route.id,
@@ -558,9 +564,8 @@ function decorateNav__(item, routes) {
558
564
  schema: route.schema
559
565
  };
560
566
  }
561
- return decorated;
562
567
  }
563
- return undecorated;
568
+ return decoratedNav;
564
569
  }
565
570
 
566
571
  // src/decorators/optimize.ts
@@ -1429,6 +1434,9 @@ function getRemoteApiUrl(pathname) {
1429
1434
  return url;
1430
1435
  }
1431
1436
  async function remoteApiFetch(pathname, options = {}) {
1437
+ if (import_bom_core12.isBrowser) {
1438
+ throw "Unauthorized: remote api cannot be fetched client side";
1439
+ }
1432
1440
  const url = getRemoteApiUrl(pathname);
1433
1441
  const apiOptions = (0, import_bom_core12.merge)({ ...getRemoteApiRequestOptions() }, options);
1434
1442
  console.log("remoteApiFetch", apiOptions.method, url);
@@ -1472,9 +1480,13 @@ var RemoteService = class {
1472
1480
  const query = (0, import_bom_core13.qsSerialize)(params);
1473
1481
  const search = query ? `?${query}` : "";
1474
1482
  const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
1475
- const item = await remoteApiGet(url);
1476
- if (item) {
1477
- return await this.decorateOne_(item, params);
1483
+ try {
1484
+ const item = await remoteApiGet(url);
1485
+ if (item) {
1486
+ return await this.decorateOne_(item, params);
1487
+ }
1488
+ } catch (error) {
1489
+ console.log("RemoteService", this.key, "findOne.error");
1478
1490
  }
1479
1491
  return;
1480
1492
  }
@@ -1504,13 +1516,15 @@ var RemoteService = class {
1504
1516
  // !!! todo params
1505
1517
  async create(payload) {
1506
1518
  const url = `/${this.key}`;
1507
- const item = await remoteApiPost(url, payload);
1519
+ const result = await remoteApiPost(url, payload);
1520
+ const item = result.doc ? result.doc : result;
1508
1521
  return await this.decorateOne_(item, {});
1509
1522
  }
1510
1523
  // !!! todo params
1511
1524
  async update(payload) {
1512
1525
  const url = `/${this.key}`;
1513
- const item = await remoteApiPut(url, payload);
1526
+ const result = await remoteApiPut(url, payload);
1527
+ const item = result.doc ? result.doc : result;
1514
1528
  return await this.decorateOne_(item, {});
1515
1529
  }
1516
1530
  // !!! todo params
@@ -1634,17 +1648,14 @@ async function getRemoteStore_() {
1634
1648
  async function getRemoteStoreStaticBuild_() {
1635
1649
  return fromCache(async () => {
1636
1650
  console.log("getRemoteStoreStaticBuild_");
1637
- const store = {};
1651
+ let store = {};
1638
1652
  const url = "/store";
1639
1653
  const json = await remoteApiGet(url);
1640
1654
  if (json != null) {
1641
- const collections = Object.keys(json);
1642
- collections.sort();
1643
- collections.forEach((key) => {
1644
- if (json[key]) {
1645
- store[key] = new MockService(json[key], store);
1646
- }
1647
- });
1655
+ const data = Object.fromEntries(
1656
+ COLLECTIONS.map((key) => [key, json[key] || []])
1657
+ );
1658
+ store = getMockStoreFromData_(data);
1648
1659
  }
1649
1660
  return store;
1650
1661
  }, "STORE_BUILD_");
@@ -2172,7 +2183,7 @@ function newRouteLink(category, route, locale) {
2172
2183
  const href = route && route.id ? route.id.toString() : "/";
2173
2184
  const id = route?.page || category.id;
2174
2185
  const media = category.media || route?.media;
2175
- const schema = route?.schema || category?.schema || "unknown";
2186
+ const schema = route?.template || route?.schema || category?.schema || "unknown";
2176
2187
  const title = (0, import_bom_core15.localize)(category.title || route?.title || "untitled", locale);
2177
2188
  const routeLink = {
2178
2189
  category: category.id,
@@ -2201,7 +2212,7 @@ async function getLayout(market, locale) {
2201
2212
  return object;
2202
2213
  }, {});
2203
2214
  const topLevelHrefs = flatTopLevelRoutes.reduce((object, routeLink) => {
2204
- if (routeLink.href && !object[routeLink.schema] || routeLink.schema === routeLink.category) {
2215
+ if (routeLink.href && (!object[routeLink.schema] || routeLink.schema === routeLink.category)) {
2205
2216
  object[routeLink.schema] = routeLink.href;
2206
2217
  }
2207
2218
  return object;
@@ -2376,6 +2387,7 @@ function varsHandler() {
2376
2387
  MockPageService,
2377
2388
  MockService,
2378
2389
  NextPhase,
2390
+ REMOTE_API_SESSION,
2379
2391
  RemoteMenuService,
2380
2392
  RemotePageService,
2381
2393
  RemoteService,
package/dist/index.mjs CHANGED
@@ -12,20 +12,26 @@ function getLocalApiRequestOptions() {
12
12
  headers: {}
13
13
  };
14
14
  }
15
+ var REMOTE_API_SESSION = {
16
+ token: null
17
+ };
15
18
  function getRemoteApiRequestOptions() {
16
- return {
17
- // mode: 'cors',
18
- headers: {
19
- /**
20
- * guest user api key (users)
21
- */
22
- Authorization: `users API-Key ${process.env.STORE_API_KEY}`
23
- /**
24
- * authenticated end user bearer (end_users)
25
- */
26
- // Authorization: `Bearer ${bearer}`,
27
- }
28
- };
19
+ if (REMOTE_API_SESSION.token) {
20
+ return {
21
+ // mode: 'cors',
22
+ headers: {
23
+ Authorization: `Bearer ${REMOTE_API_SESSION.token}`
24
+ // Authorization: `JWT ${REMOTE_API_SESSION.token}`,
25
+ }
26
+ };
27
+ } else {
28
+ return {
29
+ // mode: 'cors',
30
+ headers: {
31
+ Authorization: `users API-Key ${process.env.STORE_API_KEY}`
32
+ }
33
+ };
34
+ }
29
35
  }
30
36
 
31
37
  // src/api/api.handler.ts
@@ -408,7 +414,7 @@ async function decorateNav_(store, item, params = {}, routes) {
408
414
  const navs = collectNavs_(item);
409
415
  for (const nav of navs) {
410
416
  const decoratedNav = decorateNav__(nav, routes);
411
- nav.nav = decoratedNav.nav;
417
+ Object.assign(nav, decoratedNav);
412
418
  }
413
419
  return item;
414
420
  }
@@ -438,14 +444,13 @@ function collectNavs_(item, navs = []) {
438
444
  return navs;
439
445
  }
440
446
  function decorateNav__(item, routes) {
441
- const { nav, ...undecorated } = item;
442
- if (nav !== void 0) {
443
- const decorated = { ...undecorated };
447
+ let decoratedNav = item;
448
+ if (item !== void 0) {
444
449
  const route = routes.find(
445
- (x) => x.page === nav.page.value && x.schema === nav.page.relationTo
450
+ (x) => x.page === item.page.value && x.schema === item.page.relationTo
446
451
  );
447
452
  if (route) {
448
- decorated.nav = {
453
+ decoratedNav = {
449
454
  type: "page",
450
455
  id: route.page,
451
456
  href: route.id,
@@ -454,9 +459,8 @@ function decorateNav__(item, routes) {
454
459
  schema: route.schema
455
460
  };
456
461
  }
457
- return decorated;
458
462
  }
459
- return undecorated;
463
+ return decoratedNav;
460
464
  }
461
465
 
462
466
  // src/decorators/optimize.ts
@@ -1325,6 +1329,9 @@ function getRemoteApiUrl(pathname) {
1325
1329
  return url;
1326
1330
  }
1327
1331
  async function remoteApiFetch(pathname, options = {}) {
1332
+ if (isBrowser3) {
1333
+ throw "Unauthorized: remote api cannot be fetched client side";
1334
+ }
1328
1335
  const url = getRemoteApiUrl(pathname);
1329
1336
  const apiOptions = merge3({ ...getRemoteApiRequestOptions() }, options);
1330
1337
  console.log("remoteApiFetch", apiOptions.method, url);
@@ -1368,9 +1375,13 @@ var RemoteService = class {
1368
1375
  const query = qsSerialize2(params);
1369
1376
  const search = query ? `?${query}` : "";
1370
1377
  const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
1371
- const item = await remoteApiGet(url);
1372
- if (item) {
1373
- return await this.decorateOne_(item, params);
1378
+ try {
1379
+ const item = await remoteApiGet(url);
1380
+ if (item) {
1381
+ return await this.decorateOne_(item, params);
1382
+ }
1383
+ } catch (error) {
1384
+ console.log("RemoteService", this.key, "findOne.error");
1374
1385
  }
1375
1386
  return;
1376
1387
  }
@@ -1400,13 +1411,15 @@ var RemoteService = class {
1400
1411
  // !!! todo params
1401
1412
  async create(payload) {
1402
1413
  const url = `/${this.key}`;
1403
- const item = await remoteApiPost(url, payload);
1414
+ const result = await remoteApiPost(url, payload);
1415
+ const item = result.doc ? result.doc : result;
1404
1416
  return await this.decorateOne_(item, {});
1405
1417
  }
1406
1418
  // !!! todo params
1407
1419
  async update(payload) {
1408
1420
  const url = `/${this.key}`;
1409
- const item = await remoteApiPut(url, payload);
1421
+ const result = await remoteApiPut(url, payload);
1422
+ const item = result.doc ? result.doc : result;
1410
1423
  return await this.decorateOne_(item, {});
1411
1424
  }
1412
1425
  // !!! todo params
@@ -1530,17 +1543,14 @@ async function getRemoteStore_() {
1530
1543
  async function getRemoteStoreStaticBuild_() {
1531
1544
  return fromCache(async () => {
1532
1545
  console.log("getRemoteStoreStaticBuild_");
1533
- const store = {};
1546
+ let store = {};
1534
1547
  const url = "/store";
1535
1548
  const json = await remoteApiGet(url);
1536
1549
  if (json != null) {
1537
- const collections = Object.keys(json);
1538
- collections.sort();
1539
- collections.forEach((key) => {
1540
- if (json[key]) {
1541
- store[key] = new MockService(json[key], store);
1542
- }
1543
- });
1550
+ const data = Object.fromEntries(
1551
+ COLLECTIONS.map((key) => [key, json[key] || []])
1552
+ );
1553
+ store = getMockStoreFromData_(data);
1544
1554
  }
1545
1555
  return store;
1546
1556
  }, "STORE_BUILD_");
@@ -2068,7 +2078,7 @@ function newRouteLink(category, route, locale) {
2068
2078
  const href = route && route.id ? route.id.toString() : "/";
2069
2079
  const id = route?.page || category.id;
2070
2080
  const media = category.media || route?.media;
2071
- const schema = route?.schema || category?.schema || "unknown";
2081
+ const schema = route?.template || route?.schema || category?.schema || "unknown";
2072
2082
  const title = localize(category.title || route?.title || "untitled", locale);
2073
2083
  const routeLink = {
2074
2084
  category: category.id,
@@ -2097,7 +2107,7 @@ async function getLayout(market, locale) {
2097
2107
  return object;
2098
2108
  }, {});
2099
2109
  const topLevelHrefs = flatTopLevelRoutes.reduce((object, routeLink) => {
2100
- if (routeLink.href && !object[routeLink.schema] || routeLink.schema === routeLink.category) {
2110
+ if (routeLink.href && (!object[routeLink.schema] || routeLink.schema === routeLink.category)) {
2101
2111
  object[routeLink.schema] = routeLink.href;
2102
2112
  }
2103
2113
  return object;
@@ -2271,6 +2281,7 @@ export {
2271
2281
  MockPageService,
2272
2282
  MockService,
2273
2283
  NextPhase,
2284
+ REMOTE_API_SESSION,
2274
2285
  RemoteMenuService,
2275
2286
  RemotePageService,
2276
2287
  RemoteService,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@websolutespa/bom-mixer-store",
3
- "version": "1.8.0",
3
+ "version": "1.8.2",
4
4
  "description": "Mixer Store module of the BOM Repository",
5
5
  "keywords": [
6
6
  "bom",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "peerDependencies": {
29
29
  "@websolutespa/bom-core": "*",
30
- "iron-session": ">= 6.2.1",
30
+ "iron-session": ">= 8.0.3",
31
31
  "next": ">= 14.1.4"
32
32
  },
33
33
  "devDependencies": {
package/src/api/api.ts CHANGED
@@ -2,10 +2,6 @@ import { FetchRequestOptions } from '@websolutespa/bom-core';
2
2
 
3
3
  export type ApiRequestOptions = FetchRequestOptions;
4
4
 
5
- /**
6
- * !!! todo: evaluate authenticated end user bearer
7
- */
8
-
9
5
  export function getLocalApiRequestOptions(): ApiRequestOptions {
10
6
  return {
11
7
  headers: {
@@ -13,18 +9,31 @@ export function getLocalApiRequestOptions(): ApiRequestOptions {
13
9
  };
14
10
  }
15
11
 
12
+ export const REMOTE_API_SESSION: { token: string | null } = {
13
+ token: null,
14
+ };
15
+
16
16
  export function getRemoteApiRequestOptions(): ApiRequestOptions {
17
- return {
18
- // mode: 'cors',
19
- headers: {
20
- /**
21
- * guest user api key (users)
22
- */
23
- Authorization: `users API-Key ${process.env.STORE_API_KEY}`,
24
- /**
25
- * authenticated end user bearer (end_users)
26
- */
27
- // Authorization: `Bearer ${bearer}`,
28
- },
29
- };
17
+ if (REMOTE_API_SESSION.token) {
18
+ /**
19
+ * authenticated end user JWT token bearer (end_users)
20
+ */
21
+ return {
22
+ // mode: 'cors',
23
+ headers: {
24
+ Authorization: `Bearer ${REMOTE_API_SESSION.token}`,
25
+ // Authorization: `JWT ${REMOTE_API_SESSION.token}`,
26
+ },
27
+ };
28
+ } else {
29
+ /**
30
+ * guest user api key (users)
31
+ */
32
+ return {
33
+ // mode: 'cors',
34
+ headers: {
35
+ Authorization: `users API-Key ${process.env.STORE_API_KEY}`,
36
+ },
37
+ };
38
+ }
30
39
  }
@@ -1,4 +1,4 @@
1
- import { IDecoratedNav, IEquatable, IMenuPage, IRoute, ISchema, IStore, IUndecoratedNav, QueryParams, isArray, isObject, isUndecoratedNav } from '@websolutespa/bom-core';
1
+ import { IDecoratedNav, IEquatable, IRoute, ISchema, IStore, IUndecoratedNav, QueryParams, isArray, isObject, isUndecoratedNav } from '@websolutespa/bom-core';
2
2
 
3
3
  export async function decorateNav_<T extends ISchema = ISchema>(store: IStore, item: T, params: QueryParams = {}, routes?: IRoute[]): Promise<T> {
4
4
  if (!routes) {
@@ -12,7 +12,8 @@ export async function decorateNav_<T extends ISchema = ISchema>(store: IStore, i
12
12
  const navs = collectNavs_(item);
13
13
  for (const nav of navs) {
14
14
  const decoratedNav = decorateNav__(nav, routes);
15
- (nav as IDecoratedNav<T>).nav = decoratedNav.nav;
15
+ Object.assign(nav, decoratedNav);
16
+ // (nav as IDecoratedNav<T>).nav = decoratedNav.nav;
16
17
  }
17
18
  return item;
18
19
  }
@@ -31,8 +32,8 @@ export async function decorateNavs_<T extends ISchema = ISchema>(store: IStore,
31
32
  }
32
33
 
33
34
  // collecting navs recursively
34
- function collectNavs_<T>(item: unknown, navs: IUndecoratedNav<T>[] = []): IUndecoratedNav<T>[] {
35
- if (isUndecoratedNav<T>(item)) {
35
+ function collectNavs_(item: unknown, navs: IUndecoratedNav[] = []): IUndecoratedNav[] {
36
+ if (isUndecoratedNav(item)) {
36
37
  navs.push(item);
37
38
  }
38
39
  // console.log(item, isUndecoratedNav<T>(item));
@@ -46,16 +47,15 @@ function collectNavs_<T>(item: unknown, navs: IUndecoratedNav<T>[] = []): IUndec
46
47
  return navs;
47
48
  }
48
49
 
49
- function decorateNav__<T>(item: IUndecoratedNav<T>, routes: IRoute[]): IDecoratedNav<T> {
50
- const { nav, ...undecorated } = item;
51
- if (nav !== undefined) {
52
- const decorated = { ...undecorated } as { nav?: IMenuPage };
50
+ function decorateNav__(item: IUndecoratedNav, routes: IRoute[]): IDecoratedNav {
51
+ let decoratedNav = item as unknown as IDecoratedNav;
52
+ if (item !== undefined) {
53
53
  const route = routes.find(x =>
54
- x.page === (nav.page.value as unknown as IEquatable) &&
55
- x.schema === nav.page.relationTo
54
+ x.page === (item.page.value as unknown as IEquatable) &&
55
+ x.schema === item.page.relationTo
56
56
  );
57
57
  if (route) {
58
- decorated.nav = {
58
+ decoratedNav = {
59
59
  type: 'page',
60
60
  id: route.page,
61
61
  href: route.id,
@@ -64,7 +64,6 @@ function decorateNav__<T>(item: IUndecoratedNav<T>, routes: IRoute[]): IDecorate
64
64
  schema: route.schema,
65
65
  };
66
66
  }
67
- return decorated as IDecoratedNav<T>;
68
67
  }
69
- return undecorated as IDecoratedNav<T>;
68
+ return decoratedNav;
70
69
  }
package/src/index.ts CHANGED
@@ -10,7 +10,6 @@ export * from './mock/mock.api';
10
10
  export * from './mock/mock.handler';
11
11
  export * from './mock/mock.service';
12
12
  export * from './mock/mock.store';
13
- // export * from './session/session.handler';
14
13
  export * from './remote/remote-menu.service';
15
14
  export * from './remote/remote-page.service';
16
15
  export * from './remote/remote.api';
@@ -17,9 +17,13 @@ export function getRemoteApiUrl(pathname: string): string {
17
17
  }
18
18
 
19
19
  export async function remoteApiFetch<T = unknown>(pathname: string, options: ApiRequestOptions = {}): Promise<T> {
20
+ if (isBrowser) {
21
+ throw 'Unauthorized: remote api cannot be fetched client side';
22
+ }
20
23
  const url = getRemoteApiUrl(pathname);
21
24
  const apiOptions = merge({ ...getRemoteApiRequestOptions() }, options);
22
25
  console.log('remoteApiFetch', apiOptions.method, url);
26
+ // console.log('remoteApiFetch', 'Authorization', apiOptions.headers?.Authorization);
23
27
  const apiResponse = await httpFetch(url, apiOptions);
24
28
  return apiResponse;
25
29
  }
@@ -32,9 +32,13 @@ export class RemoteService<T extends IEntity = IEntity> implements IQuerable<T>
32
32
  const search = query ? `?${query}` : '';
33
33
  const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
34
34
  // console.log('RemoteService', this.key, 'findOne', url);
35
- const item = await remoteApiGet<B>(url);
36
- if (item) {
37
- return await this.decorateOne_(item, params);
35
+ try {
36
+ const item = await remoteApiGet<B>(url);
37
+ if (item) {
38
+ return await this.decorateOne_(item, params);
39
+ }
40
+ } catch (error) {
41
+ console.log('RemoteService', this.key, 'findOne.error');
38
42
  }
39
43
  return;
40
44
  }
@@ -70,7 +74,8 @@ export class RemoteService<T extends IEntity = IEntity> implements IQuerable<T>
70
74
  async create<B extends T = T>(payload: Omit<B, 'id'>): Promise<B> {
71
75
  const url = `/${this.key}`;
72
76
  // console.log('RemoteService', this.key, 'create', url);
73
- const item = await remoteApiPost<B>(url, payload);
77
+ const result = await remoteApiPost<B | { doc: B }>(url, payload);
78
+ const item = (result.doc ? result.doc : result) as B;
74
79
  return await this.decorateOne_(item, {});
75
80
  }
76
81
 
@@ -78,7 +83,8 @@ export class RemoteService<T extends IEntity = IEntity> implements IQuerable<T>
78
83
  async update<B extends T = T>(payload: Partial<B>): Promise<B> {
79
84
  const url = `/${this.key}`;
80
85
  // console.log('RemoteService', this.key, 'update', url);
81
- const item = await remoteApiPut<B>(url, payload);
86
+ const result = await remoteApiPut<B | { doc: B }>(url, payload);
87
+ const item = (result.doc ? result.doc : result) as B;
82
88
  return await this.decorateOne_(item, {});
83
89
  }
84
90
 
@@ -1,7 +1,6 @@
1
1
  import { IMemoryStore, IQuerable, IStore } from '@websolutespa/bom-core';
2
2
  import { fromCache } from '../cache/cache.service';
3
3
  import { CachedService } from '../cached/cached.service';
4
- import { MockService } from '../mock/mock.service';
5
4
  import { getMockStore, getMockStoreFromData_ } from '../mock/mock.store';
6
5
  import { BuildStrategy, COLLECTIONS, KNOWN_COLLECTIONS, MOCK_COLLECTIONS, NextPhase, StoreStrategy, buildStrategy, nextPhase, storeStrategy } from '../store/store';
7
6
  import { RemoteMenuService } from './remote-menu.service';
@@ -49,17 +48,14 @@ async function getRemoteStore_<T extends IStore>(): Promise<T> {
49
48
  async function getRemoteStoreStaticBuild_<T extends IStore>(): Promise<T> {
50
49
  return fromCache<T>(async () => {
51
50
  console.log('getRemoteStoreStaticBuild_');
52
- const store: IStore = {};
51
+ let store: IStore = {};
53
52
  const url = '/store';
54
53
  const json = await remoteApiGet<IMemoryStore>(url);
55
54
  if (json != null) {
56
- const collections = Object.keys(json);
57
- collections.sort();
58
- collections.forEach(key => {
59
- if (json[key]) {
60
- store[key] = new MockService(json[key], store);
61
- }
62
- });
55
+ const data = Object.fromEntries(
56
+ COLLECTIONS.map(key => ([key, json[key] || []]))
57
+ );
58
+ store = getMockStoreFromData_(data);
63
59
  }
64
60
  return store as T;
65
61
  }, 'STORE_BUILD_');
@@ -13,13 +13,13 @@ const getFilteredEnv = (env: Record<string, unknown>): Record<string, unknown> =
13
13
  ));
14
14
  entries.sort();
15
15
  return Object.fromEntries(entries);
16
- }
16
+ };
17
17
 
18
18
  const sortKeys = (object?: Record<string, unknown>): Record<string, unknown> => {
19
19
  const entries = Object.entries(object || {});
20
20
  entries.sort();
21
21
  return Object.fromEntries(entries);
22
- }
22
+ };
23
23
 
24
24
  export function varsHandler() {
25
25
  return apiHandler({
@@ -43,7 +43,7 @@ export function varsHandler() {
43
43
  headers: { ...sortKeys(request.headers) },
44
44
  env: { ...getFilteredEnv(process.env) },
45
45
  layout: { ...sortKeys(layout) },
46
- }
46
+ };
47
47
  if (!(request.headers.accept?.includes('text/html'))) {
48
48
  return response.status(200).json(info);
49
49
  }
@@ -1,61 +0,0 @@
1
- import { httpDelete, httpGet, httpPost } from '@websolutespa/bom-core';
2
- import { apiHandler } from '@websolutespa/bom-mixer-store';
3
- import { IronSessionOptions } from 'iron-session/edge';
4
- import { withIronSessionApiRoute } from 'iron-session/next';
5
- import { NextApiRequest, NextApiResponse } from 'next';
6
- import { StateStorage } from 'zustand/middleware';
7
-
8
- function sessionGet(request: NextApiRequest, response: NextApiResponse<string | null>) {
9
- const { key } = request.query;
10
- const session: { [key: string]: string | null } = request.session as any;
11
- if (session[key as string]) {
12
- response.status(200).json(session[key as string]);
13
- } else {
14
- response.status(200).json(null);
15
- }
16
- }
17
-
18
- async function sessionPost(request: NextApiRequest, response: NextApiResponse<null>) {
19
- const { key } = request.query;
20
- const body = request.body;
21
- const session: { [key: string]: string | null } = request.session as any;
22
- // console.log('body', body);
23
- session[key as string] = body.value;
24
- // console.log('session', session);
25
- await request.session.save();
26
- response.status(200).json(null);
27
- }
28
-
29
- async function sessionDelete(request: NextApiRequest, response: NextApiResponse<null>) {
30
- const { key } = request.query;
31
- const session: { [key: string]: string | null } = request.session as any;
32
- session[key as string] = null;
33
- await request.session.save();
34
- response.status(200).json(null);
35
- }
36
-
37
- export type ISessionHandler = (request: NextApiRequest, response: NextApiResponse) => Promise<void>;
38
-
39
- export function sessionHandler<T extends {}>(sessionOptions: IronSessionOptions) {
40
- return apiHandler({
41
- get: withIronSessionApiRoute(sessionGet, sessionOptions) as ISessionHandler,
42
- post: withIronSessionApiRoute(sessionPost, sessionOptions) as ISessionHandler,
43
- delete: withIronSessionApiRoute(sessionDelete, sessionOptions) as ISessionHandler,
44
- });
45
- }
46
-
47
- export const IronSessionStorage: StateStorage = {
48
- getItem: async (name: string) => {
49
- const value = await httpGet(`/api/__session/${name}`);
50
- // console.log('IronSessionStorage.getItem', name, value);
51
- return value;
52
- },
53
- setItem: async (name: string, value: string) => {
54
- // console.log('IronSessionStorage.setItem', name, { cart: value });
55
- await httpPost(`/api/__session/${name}`, { value });
56
- },
57
- removeItem: async (name: string) => {
58
- // console.log('IronSessionStorage.removeItem', name);
59
- await httpDelete(`/api/__session/${name}`);
60
- },
61
- };