@websolutespa/bom-mixer-store 1.8.4 → 1.8.5

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,10 +1,18 @@
1
1
  # @websolutespa/bom-mixer-store
2
2
 
3
+ ## 1.8.5
4
+
5
+ ### Patch Changes
6
+
7
+ - Modified: IQuerable
8
+ - Updated dependencies
9
+ - @websolutespa/bom-core@1.8.12
10
+
3
11
  ## 1.8.4
4
12
 
5
13
  ### Patch Changes
6
14
 
7
- - Modified: decorateCategory_
15
+ - Modified: decorateCategory\_
8
16
  - Updated dependencies
9
17
  - @websolutespa/bom-core@1.8.11
10
18
 
@@ -12,7 +20,7 @@
12
20
 
13
21
  ### Patch Changes
14
22
 
15
- - Removed: optimizeMany_
23
+ - Removed: optimizeMany\_
16
24
 
17
25
  ## 1.8.2
18
26
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { FetchRequestOptions, IEquatable, ICategory, IStore, QueryParams, ICategorized, IRoute, ISchema, IUndecoratedMenu, IMenu, IEntity, JsonService, IMemoryStore, IQuerable, IPagedResult } from '@websolutespa/bom-core';
2
2
  import { NextApiRequest, NextApiResponse } from 'next';
3
3
  import { NextRequest } from 'next/server';
4
- import * as _websolutespa_bom_mixer_store from '@websolutespa/bom-mixer-store';
5
4
 
6
5
  type ApiRequestOptions = FetchRequestOptions;
7
6
  declare function getLocalApiRequestOptions(): ApiRequestOptions;
@@ -146,11 +145,15 @@ declare class RemoteService<T extends IEntity = IEntity> implements IQuerable<T>
146
145
  key: string;
147
146
  store: IStore;
148
147
  constructor(key: string, store: IStore);
149
- findOne<B extends T = T>(id: IEquatable, params?: QueryParams): Promise<B | undefined>;
148
+ findOne<B extends T = T>(id: IEquatable, params?: Omit<QueryParams, 'where'>): Promise<B | undefined>;
150
149
  findMany<B extends T = T>(params?: QueryParams): Promise<B[]>;
151
150
  findPaged<B extends T = T>(params?: QueryParams): Promise<IPagedResult<B>>;
152
- create<B extends T = T>(payload: Omit<B, 'id'>): Promise<B>;
153
- update<B extends T = T>(payload: Partial<B>): Promise<B>;
151
+ create<B extends T = T>(payload: Omit<B, 'id'>, params?: QueryParams): Promise<B>;
152
+ updateOne<B extends T = T>(id: IEquatable, payload: Partial<B>, params?: Omit<QueryParams, 'where'>): Promise<B>;
153
+ updateMany<B extends T = T>(payload: Partial<B>, params?: QueryParams): Promise<B[]>;
154
+ deleteOne<B extends T = T>(id: IEquatable, params?: Omit<QueryParams, 'where'>): Promise<B | undefined>;
155
+ deleteMany<B extends T = T>(params?: QueryParams): Promise<B[]>;
156
+ update<B extends T = T>(payload: Partial<B>, params?: QueryParams): Promise<B>;
154
157
  delete<B extends T = T>(id: IEquatable): Promise<B | undefined>;
155
158
  protected decorateOne_<B extends T = T>(item: B, params?: QueryParams): Promise<B>;
156
159
  protected decorateMany_<B extends T = T>(items: B[], params?: QueryParams): Promise<B[]>;
@@ -250,6 +253,6 @@ declare function findRoute(store: IStore, pathname: string, href: string, hrefBe
250
253
 
251
254
  declare function getStore<T extends IStore>(): Promise<T>;
252
255
 
253
- declare function varsHandler(): _websolutespa_bom_mixer_store.IHandler<any>;
256
+ declare function varsHandler(): IHandler<any>;
254
257
 
255
258
  export { ApiRequestOptions, BuildStrategy, COLLECTIONS, DEFAULT_DEPTH, IApiHandler, ICrudMethod, IField, IHandler, IPageResolvedRelation, KNOWN_COLLECTIONS, MAX_INT, MOCK_COLLECTIONS, MapTo, MockMenuService, MockPageService, MockService, NextPhase, REMOTE_API_SESSION, RemoteMenuService, RemotePageService, RemoteService, RemoteServiceStrategy, STATIC_COLLECTIONS, StaticService, StaticServiceConfig, StaticServiceSrc, StoreStrategy, apiHandler, buildStrategy, collectCategory_, 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
@@ -1433,6 +1433,19 @@ var CachedService = class extends import_bom_core11.JsonService {
1433
1433
  async create(payload) {
1434
1434
  return await this.service_.create(payload);
1435
1435
  }
1436
+ async updateOne(id, payload, params = {}) {
1437
+ return await this.service_.updateOne(id, payload, params);
1438
+ }
1439
+ async updateMany(payload, params = {}) {
1440
+ return await this.service_.updateMany(payload, params);
1441
+ }
1442
+ async deleteOne(id, params = {}) {
1443
+ return await this.service_.deleteOne(id, params);
1444
+ }
1445
+ async deleteMany(params = {}) {
1446
+ return await this.service_.deleteMany(params);
1447
+ }
1448
+ // !!! old
1436
1449
  async update(payload) {
1437
1450
  return await this.service_.update(payload);
1438
1451
  }
@@ -1518,7 +1531,7 @@ var RemoteService = class {
1518
1531
  const search = query ? `?${query}` : "";
1519
1532
  const url = `/${this.key}${search}`;
1520
1533
  const response = await remoteApiGet(url);
1521
- const items = Array.isArray(response.docs) ? response.docs : response;
1534
+ const items = Array.isArray(response) ? response : response.docs;
1522
1535
  return await this.decorateMany_(items, params);
1523
1536
  }
1524
1537
  async findPaged(params = {}) {
@@ -1533,21 +1546,60 @@ var RemoteService = class {
1533
1546
  items = await this.decorateMany_(items, params);
1534
1547
  return { ...response, docs: items };
1535
1548
  }
1536
- // !!! todo params
1537
- async create(payload) {
1538
- const url = `/${this.key}`;
1549
+ async create(payload, params = {}) {
1550
+ params.richText = String(params.richText) === "true" ? true : false;
1551
+ params.draft = RemoteServiceStrategy.draft;
1552
+ const query = (0, import_bom_core13.qsSerialize)(params);
1553
+ const search = query ? `?${query}` : "";
1554
+ const url = `/${this.key}${search}`;
1539
1555
  const result = await remoteApiPost(url, payload);
1540
1556
  const item = result.doc ? result.doc : result;
1541
1557
  return await this.decorateOne_(item, {});
1542
1558
  }
1543
- // !!! todo params
1544
- async update(payload) {
1559
+ async updateOne(id, payload, params = {}) {
1560
+ const query = (0, import_bom_core13.qsSerialize)(params);
1561
+ const search = query ? `?${query}` : "";
1562
+ const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
1563
+ const result = await remoteApiPatch(url, payload);
1564
+ const item = result.doc ? result.doc : result;
1565
+ return await this.decorateOne_(item, {});
1566
+ }
1567
+ async updateMany(payload, params = {}) {
1568
+ params.richText = String(params.richText) === "true" ? true : false;
1569
+ params.draft = RemoteServiceStrategy.draft;
1570
+ params.pagination = false;
1571
+ const query = (0, import_bom_core13.qsSerialize)(params);
1572
+ const search = query ? `?${query}` : "";
1573
+ const url = `/${this.key}${search}`;
1574
+ const response = await remoteApiPatch(url, payload);
1575
+ const items = Array.isArray(response) ? response : response.docs;
1576
+ return await this.decorateMany_(items, params);
1577
+ }
1578
+ async deleteOne(id, params = {}) {
1579
+ const query = (0, import_bom_core13.qsSerialize)(params);
1580
+ const search = query ? `?${query}` : "";
1581
+ const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
1582
+ const item = await remoteApiDelete(url);
1583
+ return await this.decorateOne_(item, {});
1584
+ }
1585
+ async deleteMany(params = {}) {
1586
+ params.richText = String(params.richText) === "true" ? true : false;
1587
+ params.draft = RemoteServiceStrategy.draft;
1588
+ params.pagination = false;
1589
+ const query = (0, import_bom_core13.qsSerialize)(params);
1590
+ const search = query ? `?${query}` : "";
1591
+ const url = `/${this.key}${search}`;
1592
+ const response = await remoteApiDelete(url);
1593
+ const items = Array.isArray(response) ? response : response.docs;
1594
+ return await this.decorateMany_(items, params);
1595
+ }
1596
+ // !!! old
1597
+ async update(payload, params = {}) {
1545
1598
  const url = `/${this.key}`;
1546
- const result = await remoteApiPut(url, payload);
1599
+ const result = await remoteApiPatch(url, payload);
1547
1600
  const item = result.doc ? result.doc : result;
1548
1601
  return await this.decorateOne_(item, {});
1549
1602
  }
1550
- // !!! todo params
1551
1603
  async delete(id) {
1552
1604
  const params = {
1553
1605
  where: {
@@ -1790,19 +1842,40 @@ function collectionPost(storePromise) {
1790
1842
  function collectionPatch(storePromise) {
1791
1843
  return async (request, response) => {
1792
1844
  try {
1793
- const params = request.query;
1794
- const { collections, ...query } = params;
1845
+ const { collections, ...query } = request.query;
1846
+ if (!Array.isArray(collections) || collections?.length === 0) {
1847
+ console.error("storeHandler.collectionUpdate", "method not allowed", collections);
1848
+ return response.status(405).send("method not allowed");
1849
+ }
1795
1850
  if (!Array.isArray(collections) || collections.length !== 2) {
1796
1851
  console.error("method not allowed", collections);
1797
1852
  return response.status(405).send("method not allowed");
1798
1853
  }
1799
1854
  const collection = collections[0];
1855
+ const id = collections[1];
1856
+ const qs = Object.entries(query).map((kv) => kv.join("=")).join("&");
1857
+ const params = (0, import_bom_core14.qsDeserialize)(qs);
1858
+ if (!COLLECTIONS.includes(collection)) {
1859
+ console.error("storeHandler.collectionUpdate", "method not allowed", collection);
1860
+ return response.status(405).send("method not allowed");
1861
+ }
1800
1862
  const store = await storePromise();
1801
1863
  const service = store[collection];
1802
1864
  if (!service) {
1803
- console.error("method not allowed", collection);
1865
+ console.error("storeHandler.collectionUpdate", "method not allowed", collection);
1804
1866
  return response.status(405).send("method not allowed");
1805
1867
  }
1868
+ if (id) {
1869
+ const item = await service.updateOne((0, import_bom_core14.asEquatable)(id), params);
1870
+ if (item) {
1871
+ return response.status(200).json(item);
1872
+ } else {
1873
+ return response.status(404).send("not found");
1874
+ }
1875
+ } else {
1876
+ const items = await service.updateMany(params);
1877
+ return response.status(200).json(items);
1878
+ }
1806
1879
  } catch (error) {
1807
1880
  console.error("storeHandler.error.500", error);
1808
1881
  throw error;
@@ -1812,20 +1885,40 @@ function collectionPatch(storePromise) {
1812
1885
  function collectionDelete(storePromise) {
1813
1886
  return async (request, response) => {
1814
1887
  try {
1815
- const params = request.query;
1816
- const { collections, ...query } = params;
1888
+ const { collections, ...query } = request.query;
1889
+ if (!Array.isArray(collections) || collections?.length === 0) {
1890
+ console.error("storeHandler.collectionDelete", "method not allowed", collections);
1891
+ return response.status(405).send("method not allowed");
1892
+ }
1817
1893
  if (!Array.isArray(collections) || collections.length !== 2) {
1818
1894
  console.error("method not allowed", collections);
1819
1895
  return response.status(405).send("method not allowed");
1820
1896
  }
1821
1897
  const collection = collections[0];
1822
1898
  const id = collections[1];
1899
+ const qs = Object.entries(query).map((kv) => kv.join("=")).join("&");
1900
+ const params = (0, import_bom_core14.qsDeserialize)(qs);
1901
+ if (!COLLECTIONS.includes(collection)) {
1902
+ console.error("storeHandler.collectionDelete", "method not allowed", collection);
1903
+ return response.status(405).send("method not allowed");
1904
+ }
1823
1905
  const store = await storePromise();
1824
1906
  const service = store[collection];
1825
1907
  if (!service) {
1826
- console.error("method not allowed", collection);
1908
+ console.error("storeHandler.collectionDelete", "method not allowed", collection);
1827
1909
  return response.status(405).send("method not allowed");
1828
1910
  }
1911
+ if (id) {
1912
+ const item = await service.deleteOne((0, import_bom_core14.asEquatable)(id), params);
1913
+ if (item) {
1914
+ return response.status(200).json(item);
1915
+ } else {
1916
+ return response.status(404).send("not found");
1917
+ }
1918
+ } else {
1919
+ const items = await service.deleteMany(params);
1920
+ return response.status(200).json(items);
1921
+ }
1829
1922
  } catch (error) {
1830
1923
  console.error("storeHandler.error.500", error);
1831
1924
  throw error;
package/dist/index.mjs CHANGED
@@ -1327,6 +1327,19 @@ var CachedService = class extends JsonService3 {
1327
1327
  async create(payload) {
1328
1328
  return await this.service_.create(payload);
1329
1329
  }
1330
+ async updateOne(id, payload, params = {}) {
1331
+ return await this.service_.updateOne(id, payload, params);
1332
+ }
1333
+ async updateMany(payload, params = {}) {
1334
+ return await this.service_.updateMany(payload, params);
1335
+ }
1336
+ async deleteOne(id, params = {}) {
1337
+ return await this.service_.deleteOne(id, params);
1338
+ }
1339
+ async deleteMany(params = {}) {
1340
+ return await this.service_.deleteMany(params);
1341
+ }
1342
+ // !!! old
1330
1343
  async update(payload) {
1331
1344
  return await this.service_.update(payload);
1332
1345
  }
@@ -1412,7 +1425,7 @@ var RemoteService = class {
1412
1425
  const search = query ? `?${query}` : "";
1413
1426
  const url = `/${this.key}${search}`;
1414
1427
  const response = await remoteApiGet(url);
1415
- const items = Array.isArray(response.docs) ? response.docs : response;
1428
+ const items = Array.isArray(response) ? response : response.docs;
1416
1429
  return await this.decorateMany_(items, params);
1417
1430
  }
1418
1431
  async findPaged(params = {}) {
@@ -1427,21 +1440,60 @@ var RemoteService = class {
1427
1440
  items = await this.decorateMany_(items, params);
1428
1441
  return { ...response, docs: items };
1429
1442
  }
1430
- // !!! todo params
1431
- async create(payload) {
1432
- const url = `/${this.key}`;
1443
+ async create(payload, params = {}) {
1444
+ params.richText = String(params.richText) === "true" ? true : false;
1445
+ params.draft = RemoteServiceStrategy.draft;
1446
+ const query = qsSerialize2(params);
1447
+ const search = query ? `?${query}` : "";
1448
+ const url = `/${this.key}${search}`;
1433
1449
  const result = await remoteApiPost(url, payload);
1434
1450
  const item = result.doc ? result.doc : result;
1435
1451
  return await this.decorateOne_(item, {});
1436
1452
  }
1437
- // !!! todo params
1438
- async update(payload) {
1453
+ async updateOne(id, payload, params = {}) {
1454
+ const query = qsSerialize2(params);
1455
+ const search = query ? `?${query}` : "";
1456
+ const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
1457
+ const result = await remoteApiPatch(url, payload);
1458
+ const item = result.doc ? result.doc : result;
1459
+ return await this.decorateOne_(item, {});
1460
+ }
1461
+ async updateMany(payload, params = {}) {
1462
+ params.richText = String(params.richText) === "true" ? true : false;
1463
+ params.draft = RemoteServiceStrategy.draft;
1464
+ params.pagination = false;
1465
+ const query = qsSerialize2(params);
1466
+ const search = query ? `?${query}` : "";
1467
+ const url = `/${this.key}${search}`;
1468
+ const response = await remoteApiPatch(url, payload);
1469
+ const items = Array.isArray(response) ? response : response.docs;
1470
+ return await this.decorateMany_(items, params);
1471
+ }
1472
+ async deleteOne(id, params = {}) {
1473
+ const query = qsSerialize2(params);
1474
+ const search = query ? `?${query}` : "";
1475
+ const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
1476
+ const item = await remoteApiDelete(url);
1477
+ return await this.decorateOne_(item, {});
1478
+ }
1479
+ async deleteMany(params = {}) {
1480
+ params.richText = String(params.richText) === "true" ? true : false;
1481
+ params.draft = RemoteServiceStrategy.draft;
1482
+ params.pagination = false;
1483
+ const query = qsSerialize2(params);
1484
+ const search = query ? `?${query}` : "";
1485
+ const url = `/${this.key}${search}`;
1486
+ const response = await remoteApiDelete(url);
1487
+ const items = Array.isArray(response) ? response : response.docs;
1488
+ return await this.decorateMany_(items, params);
1489
+ }
1490
+ // !!! old
1491
+ async update(payload, params = {}) {
1439
1492
  const url = `/${this.key}`;
1440
- const result = await remoteApiPut(url, payload);
1493
+ const result = await remoteApiPatch(url, payload);
1441
1494
  const item = result.doc ? result.doc : result;
1442
1495
  return await this.decorateOne_(item, {});
1443
1496
  }
1444
- // !!! todo params
1445
1497
  async delete(id) {
1446
1498
  const params = {
1447
1499
  where: {
@@ -1684,19 +1736,40 @@ function collectionPost(storePromise) {
1684
1736
  function collectionPatch(storePromise) {
1685
1737
  return async (request, response) => {
1686
1738
  try {
1687
- const params = request.query;
1688
- const { collections, ...query } = params;
1739
+ const { collections, ...query } = request.query;
1740
+ if (!Array.isArray(collections) || collections?.length === 0) {
1741
+ console.error("storeHandler.collectionUpdate", "method not allowed", collections);
1742
+ return response.status(405).send("method not allowed");
1743
+ }
1689
1744
  if (!Array.isArray(collections) || collections.length !== 2) {
1690
1745
  console.error("method not allowed", collections);
1691
1746
  return response.status(405).send("method not allowed");
1692
1747
  }
1693
1748
  const collection = collections[0];
1749
+ const id = collections[1];
1750
+ const qs = Object.entries(query).map((kv) => kv.join("=")).join("&");
1751
+ const params = qsDeserialize(qs);
1752
+ if (!COLLECTIONS.includes(collection)) {
1753
+ console.error("storeHandler.collectionUpdate", "method not allowed", collection);
1754
+ return response.status(405).send("method not allowed");
1755
+ }
1694
1756
  const store = await storePromise();
1695
1757
  const service = store[collection];
1696
1758
  if (!service) {
1697
- console.error("method not allowed", collection);
1759
+ console.error("storeHandler.collectionUpdate", "method not allowed", collection);
1698
1760
  return response.status(405).send("method not allowed");
1699
1761
  }
1762
+ if (id) {
1763
+ const item = await service.updateOne(asEquatable(id), params);
1764
+ if (item) {
1765
+ return response.status(200).json(item);
1766
+ } else {
1767
+ return response.status(404).send("not found");
1768
+ }
1769
+ } else {
1770
+ const items = await service.updateMany(params);
1771
+ return response.status(200).json(items);
1772
+ }
1700
1773
  } catch (error) {
1701
1774
  console.error("storeHandler.error.500", error);
1702
1775
  throw error;
@@ -1706,20 +1779,40 @@ function collectionPatch(storePromise) {
1706
1779
  function collectionDelete(storePromise) {
1707
1780
  return async (request, response) => {
1708
1781
  try {
1709
- const params = request.query;
1710
- const { collections, ...query } = params;
1782
+ const { collections, ...query } = request.query;
1783
+ if (!Array.isArray(collections) || collections?.length === 0) {
1784
+ console.error("storeHandler.collectionDelete", "method not allowed", collections);
1785
+ return response.status(405).send("method not allowed");
1786
+ }
1711
1787
  if (!Array.isArray(collections) || collections.length !== 2) {
1712
1788
  console.error("method not allowed", collections);
1713
1789
  return response.status(405).send("method not allowed");
1714
1790
  }
1715
1791
  const collection = collections[0];
1716
1792
  const id = collections[1];
1793
+ const qs = Object.entries(query).map((kv) => kv.join("=")).join("&");
1794
+ const params = qsDeserialize(qs);
1795
+ if (!COLLECTIONS.includes(collection)) {
1796
+ console.error("storeHandler.collectionDelete", "method not allowed", collection);
1797
+ return response.status(405).send("method not allowed");
1798
+ }
1717
1799
  const store = await storePromise();
1718
1800
  const service = store[collection];
1719
1801
  if (!service) {
1720
- console.error("method not allowed", collection);
1802
+ console.error("storeHandler.collectionDelete", "method not allowed", collection);
1721
1803
  return response.status(405).send("method not allowed");
1722
1804
  }
1805
+ if (id) {
1806
+ const item = await service.deleteOne(asEquatable(id), params);
1807
+ if (item) {
1808
+ return response.status(200).json(item);
1809
+ } else {
1810
+ return response.status(404).send("not found");
1811
+ }
1812
+ } else {
1813
+ const items = await service.deleteMany(params);
1814
+ return response.status(200).json(items);
1815
+ }
1723
1816
  } catch (error) {
1724
1817
  console.error("storeHandler.error.500", error);
1725
1818
  throw error;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@websolutespa/bom-mixer-store",
3
- "version": "1.8.4",
3
+ "version": "1.8.5",
4
4
  "description": "Mixer Store module of the BOM Repository",
5
5
  "keywords": [
6
6
  "bom",
package/src/api/api.ts CHANGED
@@ -15,9 +15,7 @@ export const REMOTE_API_SESSION: { token: string | null } = {
15
15
 
16
16
  export function getRemoteApiRequestOptions(): ApiRequestOptions {
17
17
  if (REMOTE_API_SESSION.token) {
18
- /**
19
- * authenticated end user JWT token bearer (end_users)
20
- */
18
+ // authenticated end user JWT token bearer (end_users)
21
19
  return {
22
20
  // mode: 'cors',
23
21
  headers: {
@@ -26,9 +24,7 @@ export function getRemoteApiRequestOptions(): ApiRequestOptions {
26
24
  },
27
25
  };
28
26
  } else {
29
- /**
30
- * guest user api key (users)
31
- */
27
+ // guest user api key (users)
32
28
  return {
33
29
  // mode: 'cors',
34
30
  headers: {
@@ -37,3 +33,43 @@ export function getRemoteApiRequestOptions(): ApiRequestOptions {
37
33
  };
38
34
  }
39
35
  }
36
+
37
+ /*
38
+ export async function getRemoteApiRequestOptions(): Promise<ApiRequestOptions> {
39
+ if (REMOTE_API_SESSION.token) {
40
+ // authenticated end user JWT token bearer (end_users)
41
+ return {
42
+ // mode: 'cors',
43
+ headers: {
44
+ Authorization: `Bearer ${REMOTE_API_SESSION.token}`,
45
+ // Authorization: `JWT ${REMOTE_API_SESSION.token}`,
46
+ },
47
+ };
48
+ } else {
49
+ // guest user api key (users)
50
+ return {
51
+ // mode: 'cors',
52
+ headers: {
53
+ Authorization: `users API-Key ${process.env.STORE_API_KEY}`,
54
+ },
55
+ };
56
+ }
57
+ }
58
+ */
59
+
60
+ /*
61
+ const session = await getSession<T>(request, response);
62
+ // console.log('getAuth.session', session);
63
+ if (session.token && session.exp && session.exp > Math.floor(new Date().getTime() / 1000)) {
64
+ REMOTE_API_SESSION.token = session.token;
65
+ } else {
66
+ session.token = undefined;
67
+ session.exp = undefined;
68
+ await session.save();
69
+ session.destroy();
70
+ REMOTE_API_SESSION.token = null;
71
+ }
72
+ return session;
73
+ */
74
+
75
+
@@ -104,6 +104,24 @@ export class CachedService<T extends IEntity = IEntity> extends JsonService<T> {
104
104
  return await this.service_.create(payload);
105
105
  }
106
106
 
107
+ async updateOne<B extends T = T>(id: IEquatable, payload: Partial<B>, params: Omit<QueryParams, 'where'> = {}): Promise<B> {
108
+ return await this.service_.updateOne(id, payload, params);
109
+ }
110
+
111
+ async updateMany<B extends T = T>(payload: Partial<B>, params: QueryParams = {}): Promise<B[]> {
112
+ return await this.service_.updateMany(payload, params);
113
+ }
114
+
115
+ async deleteOne<B extends T = T>(id: IEquatable, params: Omit<QueryParams, 'where'> = {}): Promise<B | undefined> {
116
+ return await this.service_.deleteOne(id, params);
117
+ }
118
+
119
+ async deleteMany<B extends T = T>(params: QueryParams = {}): Promise<B[]> {
120
+ return await this.service_.deleteMany(params);
121
+ }
122
+
123
+ // !!! old
124
+
107
125
  async update<B extends T = T>(payload: Partial<B>): Promise<B> {
108
126
  return await this.service_.update(payload);
109
127
  }
@@ -1,6 +1,6 @@
1
1
  import { IEntity, IEquatable, IPagedResult, IQuerable, IStore, qsSerialize, QueryParams } from '@websolutespa/bom-core';
2
2
  import { decorateSchema_, decorateSchemas_ } from '../decorators';
3
- import { remoteApiDelete, remoteApiGet, remoteApiPost, remoteApiPut } from './remote.api';
3
+ import { remoteApiDelete, remoteApiGet, remoteApiPatch, remoteApiPost } from './remote.api';
4
4
 
5
5
  export const RemoteServiceStrategy = {
6
6
  draft: false,
@@ -25,7 +25,7 @@ export class RemoteService<T extends IEntity = IEntity> implements IQuerable<T>
25
25
  this.store = store;
26
26
  }
27
27
 
28
- async findOne<B extends T = T>(id: IEquatable, params: QueryParams = {}): Promise<B | undefined> {
28
+ async findOne<B extends T = T>(id: IEquatable, params: Omit<QueryParams, 'where'> = {}): Promise<B | undefined> {
29
29
  params.richText = String(params.richText) === 'true' ? true : false;
30
30
  params.draft = RemoteServiceStrategy.draft;
31
31
  const query = qsSerialize(params);
@@ -51,8 +51,8 @@ export class RemoteService<T extends IEntity = IEntity> implements IQuerable<T>
51
51
  const search = query ? `?${query}` : '';
52
52
  const url = `/${this.key}${search}`;
53
53
  // console.log('RemoteService', this.key, 'findMany', url);
54
- const response = await remoteApiGet(url) as any; // !!! todo pagination<B[]> | B[]
55
- const items: B[] = Array.isArray(response.docs) ? response.docs : response;
54
+ const response = await remoteApiGet<B[] | { docs: B[] }>(url);
55
+ const items: B[] = Array.isArray(response) ? response : response.docs;
56
56
  return await this.decorateMany_(items, params);
57
57
  }
58
58
 
@@ -70,25 +70,73 @@ export class RemoteService<T extends IEntity = IEntity> implements IQuerable<T>
70
70
  return { ...response, docs: items };
71
71
  }
72
72
 
73
- // !!! todo params
74
- async create<B extends T = T>(payload: Omit<B, 'id'>): Promise<B> {
75
- const url = `/${this.key}`;
73
+ async create<B extends T = T>(payload: Omit<B, 'id'>, params: QueryParams = {}): Promise<B> {
74
+ params.richText = String(params.richText) === 'true' ? true : false;
75
+ params.draft = RemoteServiceStrategy.draft;
76
+ const query = qsSerialize(params);
77
+ const search = query ? `?${query}` : '';
78
+ const url = `/${this.key}${search}`;
76
79
  // console.log('RemoteService', this.key, 'create', url);
77
80
  const result = await remoteApiPost<B | { doc: B }>(url, payload);
78
81
  const item = (result.doc ? result.doc : result) as B;
79
82
  return await this.decorateOne_(item, {});
80
83
  }
81
84
 
82
- // !!! todo params
83
- async update<B extends T = T>(payload: Partial<B>): Promise<B> {
85
+ async updateOne<B extends T = T>(id: IEquatable, payload: Partial<B>, params: Omit<QueryParams, 'where'> = {}): Promise<B> {
86
+ const query = qsSerialize(params);
87
+ const search = query ? `?${query}` : '';
88
+ const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
89
+ // console.log('RemoteService', this.key, 'updateOne', url);
90
+ const result = await remoteApiPatch<B | { doc: B }>(url, payload);
91
+ const item = (result.doc ? result.doc : result) as B;
92
+ return await this.decorateOne_(item, {});
93
+ }
94
+
95
+ async updateMany<B extends T = T>(payload: Partial<B>, params: QueryParams = {}): Promise<B[]> {
96
+ params.richText = String(params.richText) === 'true' ? true : false;
97
+ params.draft = RemoteServiceStrategy.draft;
98
+ params.pagination = false;
99
+ const query = qsSerialize(params);
100
+ const search = query ? `?${query}` : '';
101
+ const url = `/${this.key}${search}`;
102
+ // console.log('RemoteService', this.key, 'updateMany', url);
103
+ const response = await remoteApiPatch<B[] | { docs: B[] }>(url, payload);
104
+ const items: B[] = Array.isArray(response) ? response : response.docs;
105
+ return await this.decorateMany_(items, params);
106
+ }
107
+
108
+ async deleteOne<B extends T = T>(id: IEquatable, params: Omit<QueryParams, 'where'> = {}): Promise<B | undefined> {
109
+ const query = qsSerialize(params);
110
+ const search = query ? `?${query}` : '';
111
+ const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
112
+ // console.log('RemoteService', this.key, 'deleteOne', url);
113
+ const item = await remoteApiDelete<B>(url);
114
+ return await this.decorateOne_(item, {});
115
+ }
116
+
117
+ async deleteMany<B extends T = T>(params: QueryParams = {}): Promise<B[]> {
118
+ params.richText = String(params.richText) === 'true' ? true : false;
119
+ params.draft = RemoteServiceStrategy.draft;
120
+ params.pagination = false;
121
+ const query = qsSerialize(params);
122
+ const search = query ? `?${query}` : '';
123
+ const url = `/${this.key}${search}`;
124
+ // console.log('RemoteService', this.key, 'deleteMany', url);
125
+ const response = await remoteApiDelete<B[] | { docs: B[] }>(url);
126
+ const items: B[] = Array.isArray(response) ? response : response.docs;
127
+ return await this.decorateMany_(items, params);
128
+ }
129
+
130
+ // !!! old
131
+
132
+ async update<B extends T = T>(payload: Partial<B>, params: QueryParams = {}): Promise<B> {
84
133
  const url = `/${this.key}`;
85
134
  // console.log('RemoteService', this.key, 'update', url);
86
- const result = await remoteApiPut<B | { doc: B }>(url, payload);
135
+ const result = await remoteApiPatch<B | { doc: B }>(url, payload);
87
136
  const item = (result.doc ? result.doc : result) as B;
88
137
  return await this.decorateOne_(item, {});
89
138
  }
90
139
 
91
- // !!! todo params
92
140
  async delete<B extends T = T>(id: IEquatable): Promise<B | undefined> {
93
141
  const params = {
94
142
  where: {
@@ -0,0 +1,25 @@
1
+
2
+ import { isDevelopment } from '@websolutespa/bom-core';
3
+ import * as http from 'http';
4
+ import { getIronSession, IronSession, SessionOptions } from 'iron-session';
5
+
6
+ export async function getSession<T extends object = Record<string, any>>(
7
+ request: (http.IncomingMessage | Request & { cookies: any }),
8
+ response?: Response | http.ServerResponse
9
+ ): Promise<IronSession<T>> {
10
+ const COOKIE_NAME = 'websolutespa-next-js';
11
+ const COOKIE_PASSWORD = process.env.SECRET_COOKIE_PASSWORD as string || 'SECRET_COOKIE_PASSWORD_32_CHARS_LONG';
12
+ const sessionOptions: SessionOptions = {
13
+ cookieName: COOKIE_NAME,
14
+ // secure: true should be used in production (HTTPS) but can't be used in development (HTTP)
15
+ cookieOptions: {
16
+ secure: !isDevelopment,
17
+ },
18
+ password: COOKIE_PASSWORD,
19
+ };
20
+ const session =
21
+ 'cookies' in request ?
22
+ await getIronSession<T>(request.cookies, sessionOptions) :
23
+ await getIronSession<T>(request, response, sessionOptions);
24
+ return session;
25
+ }
@@ -102,20 +102,45 @@ export function collectionPost<T extends IStore>(storePromise: () => Promise<T>)
102
102
  export function collectionPatch<T extends IStore>(storePromise: () => Promise<T>) {
103
103
  return async (request: NextApiRequest, response: NextApiResponse) => {
104
104
  try {
105
- const params = request.query;
106
- const { collections, ...query } = params;
105
+ const { collections, ...query } = request.query;
106
+ // console.log('query', query);
107
+ if (!Array.isArray(collections) || collections?.length === 0) {
108
+ console.error('storeHandler.collectionUpdate', 'method not allowed', collections);
109
+ return response.status(405).send('method not allowed');
110
+ }
107
111
  if (!Array.isArray(collections) || collections.length !== 2) {
108
112
  console.error('method not allowed', collections);
109
113
  return response.status(405).send('method not allowed');
110
114
  }
111
115
  const collection: string = collections[0];
116
+ const id: string = collections[1];
117
+ const qs = Object.entries(query).map(kv => kv.join('=')).join('&');
118
+ const params = qsDeserialize(qs);
119
+ // console.log('params', params);
120
+ if (!COLLECTIONS.includes(collection)) {
121
+ console.error('storeHandler.collectionUpdate', 'method not allowed', collection);
122
+ return response.status(405).send('method not allowed');
123
+ }
112
124
  const store = await storePromise();
113
125
  const service = store[collection];
114
126
  if (!service) {
115
- console.error('method not allowed', collection);
127
+ console.error('storeHandler.collectionUpdate', 'method not allowed', collection);
116
128
  return response.status(405).send('method not allowed');
117
129
  }
118
- // !!! todo patch update
130
+ // update a specific document by id
131
+ if (id) {
132
+ // console.log('storeHandler.collectionUpdate', collection, id, params);
133
+ const item = await service.updateOne(asEquatable(id), params);
134
+ if (item) {
135
+ return response.status(200).json(item);
136
+ } else {
137
+ return response.status(404).send('not found');
138
+ }
139
+ } else {
140
+ // console.log('storeHandler.collectionUpdate', collection, params);
141
+ const items = await service.updateMany(params);
142
+ return response.status(200).json(items);
143
+ }
119
144
  } catch (error: any) {
120
145
  console.error('storeHandler.error.500', error);
121
146
  throw error;
@@ -127,21 +152,45 @@ export function collectionPatch<T extends IStore>(storePromise: () => Promise<T>
127
152
  export function collectionDelete<T extends IStore>(storePromise: () => Promise<T>) {
128
153
  return async (request: NextApiRequest, response: NextApiResponse) => {
129
154
  try {
130
- const params = request.query;
131
- const { collections, ...query } = params;
155
+ const { collections, ...query } = request.query;
156
+ // console.log('query', query);
157
+ if (!Array.isArray(collections) || collections?.length === 0) {
158
+ console.error('storeHandler.collectionDelete', 'method not allowed', collections);
159
+ return response.status(405).send('method not allowed');
160
+ }
132
161
  if (!Array.isArray(collections) || collections.length !== 2) {
133
162
  console.error('method not allowed', collections);
134
163
  return response.status(405).send('method not allowed');
135
164
  }
136
165
  const collection: string = collections[0];
137
166
  const id: string = collections[1];
167
+ const qs = Object.entries(query).map(kv => kv.join('=')).join('&');
168
+ const params = qsDeserialize(qs);
169
+ // console.log('params', params);
170
+ if (!COLLECTIONS.includes(collection)) {
171
+ console.error('storeHandler.collectionDelete', 'method not allowed', collection);
172
+ return response.status(405).send('method not allowed');
173
+ }
138
174
  const store = await storePromise();
139
175
  const service = store[collection];
140
176
  if (!service) {
141
- console.error('method not allowed', collection);
177
+ console.error('storeHandler.collectionDelete', 'method not allowed', collection);
142
178
  return response.status(405).send('method not allowed');
143
179
  }
144
- // !!! todo delete
180
+ // delete a specific document by id
181
+ if (id) {
182
+ // console.log('storeHandler.collectionDelete', collection, id, params);
183
+ const item = await service.deleteOne(asEquatable(id), params);
184
+ if (item) {
185
+ return response.status(200).json(item);
186
+ } else {
187
+ return response.status(404).send('not found');
188
+ }
189
+ } else {
190
+ // console.log('storeHandler.collectionDelete', collection, params);
191
+ const items = await service.deleteMany(params);
192
+ return response.status(200).json(items);
193
+ }
145
194
  } catch (error: any) {
146
195
  console.error('storeHandler.error.500', error);
147
196
  throw error;
@@ -1,7 +1,7 @@
1
1
  import { getHost, getOrigin, isDevelopment, isProduction } from '@websolutespa/bom-core';
2
2
  import { getLayout } from '@websolutespa/bom-mixer-models';
3
- import { apiHandler } from '@websolutespa/bom-mixer-store';
4
3
  import { NextApiRequest, NextApiResponse } from 'next';
4
+ import { apiHandler } from '../api/api.handler';
5
5
 
6
6
  const DISALLOWED_KEYS = [
7
7
  '__NEXT_PRIVATE_STANDALONE_CONFIG',