@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 +12 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +48 -36
- package/dist/index.mjs +47 -36
- package/package.json +2 -2
- package/src/api/api.ts +26 -17
- package/src/decorators/nav.ts +12 -13
- package/src/index.ts +0 -1
- package/src/remote/remote.api.ts +4 -0
- package/src/remote/remote.service.ts +11 -5
- package/src/remote/remote.store.ts +5 -9
- package/src/vars/vars.handler.ts +3 -3
- package/src/session/session.handler.ts +0 -61
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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
546
|
-
if (
|
|
547
|
-
const decorated = { ...undecorated };
|
|
552
|
+
let decoratedNav = item;
|
|
553
|
+
if (item !== void 0) {
|
|
548
554
|
const route = routes.find(
|
|
549
|
-
(x) => x.page ===
|
|
555
|
+
(x) => x.page === item.page.value && x.schema === item.page.relationTo
|
|
550
556
|
);
|
|
551
557
|
if (route) {
|
|
552
|
-
|
|
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
|
|
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
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
1651
|
+
let store = {};
|
|
1638
1652
|
const url = "/store";
|
|
1639
1653
|
const json = await remoteApiGet(url);
|
|
1640
1654
|
if (json != null) {
|
|
1641
|
-
const
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
442
|
-
if (
|
|
443
|
-
const decorated = { ...undecorated };
|
|
447
|
+
let decoratedNav = item;
|
|
448
|
+
if (item !== void 0) {
|
|
444
449
|
const route = routes.find(
|
|
445
|
-
(x) => x.page ===
|
|
450
|
+
(x) => x.page === item.page.value && x.schema === item.page.relationTo
|
|
446
451
|
);
|
|
447
452
|
if (route) {
|
|
448
|
-
|
|
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
|
|
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
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
1546
|
+
let store = {};
|
|
1534
1547
|
const url = "/store";
|
|
1535
1548
|
const json = await remoteApiGet(url);
|
|
1536
1549
|
if (json != null) {
|
|
1537
|
-
const
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
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.
|
|
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": ">=
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
}
|
package/src/decorators/nav.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IDecoratedNav, IEquatable,
|
|
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
|
|
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_
|
|
35
|
-
if (isUndecoratedNav
|
|
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__
|
|
50
|
-
|
|
51
|
-
if (
|
|
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 === (
|
|
55
|
-
x.schema ===
|
|
54
|
+
x.page === (item.page.value as unknown as IEquatable) &&
|
|
55
|
+
x.schema === item.page.relationTo
|
|
56
56
|
);
|
|
57
57
|
if (route) {
|
|
58
|
-
|
|
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
|
|
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';
|
package/src/remote/remote.api.ts
CHANGED
|
@@ -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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
51
|
+
let store: IStore = {};
|
|
53
52
|
const url = '/store';
|
|
54
53
|
const json = await remoteApiGet<IMemoryStore>(url);
|
|
55
54
|
if (json != null) {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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_');
|
package/src/vars/vars.handler.ts
CHANGED
|
@@ -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
|
-
};
|