@websolutespa/bom-mixer-store 0.3.0 → 0.3.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.js +37 -29
- package/dist/index.mjs +37 -29
- package/package.json +5 -3
- package/src/__tests/example.test.ts +8 -0
- package/src/api/api.handler.ts +43 -0
- package/src/api/api.service.ts +52 -0
- package/src/fs/fs.service.ts +127 -0
- package/src/index.ts +15 -0
- package/src/middleware/middleware.service.ts +79 -0
- package/src/mock/mock-menu.service.ts +286 -0
- package/src/mock/mock-page.service.ts +79 -0
- package/src/mock/mock.handler.ts +6 -0
- package/src/mock/mock.service.ts +73 -0
- package/src/mock/mock.store.ts +80 -0
- package/src/revalidate/revalidate.handler.ts +0 -0
- package/src/session/session.handler.ts +82 -0
- package/src/static/static.service.ts +102 -0
- package/src/static/static.ts +223 -0
- package/src/store/store.handler.ts +176 -0
- package/src/store/store.service.ts +34 -0
- package/src/store/store.ts +15 -0
- package/src/storeApi/storeApi.service.ts +191 -0
- package/src/storeApi/storeApi.store.ts +66 -0
package/CHANGELOG.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -573,6 +573,26 @@ var MockMenuService = class extends MockService {
|
|
|
573
573
|
}
|
|
574
574
|
}
|
|
575
575
|
};
|
|
576
|
+
async function collectPages(store, items) {
|
|
577
|
+
if (!items) {
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
for (const item of items) {
|
|
581
|
+
if (item.type === "page" && typeof item.page.value === "number" && store[item.page.relationTo] !== void 0) {
|
|
582
|
+
const value = await store[item.page.relationTo].findOne(item.page.value);
|
|
583
|
+
if (value) {
|
|
584
|
+
item.page.value = value;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
switch (item.type) {
|
|
588
|
+
case "group":
|
|
589
|
+
case "link":
|
|
590
|
+
case "page":
|
|
591
|
+
await collectPages(store, item.items);
|
|
592
|
+
break;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
576
596
|
async function decorateMenu(store, item, market = "ww", locale = "en") {
|
|
577
597
|
const items = item.items || [];
|
|
578
598
|
const decoratedItem = {
|
|
@@ -590,27 +610,7 @@ async function decorateMenu(store, item, market = "ww", locale = "en") {
|
|
|
590
610
|
}
|
|
591
611
|
}
|
|
592
612
|
});
|
|
593
|
-
|
|
594
|
-
if (!items2) {
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
for (const item2 of items2) {
|
|
598
|
-
if (item2.type === "page" && typeof item2.page.value === "number" && store[item2.page.relationTo] !== void 0) {
|
|
599
|
-
const value = await store[item2.page.relationTo].findOne(item2.page.value);
|
|
600
|
-
if (value) {
|
|
601
|
-
item2.page.value = value;
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
switch (item2.type) {
|
|
605
|
-
case "group":
|
|
606
|
-
case "link":
|
|
607
|
-
case "page":
|
|
608
|
-
await collectPages(item2.items);
|
|
609
|
-
break;
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
await collectPages(items);
|
|
613
|
+
await collectPages(store, items);
|
|
614
614
|
decoratedItem.items = items.filter((x) => hasMarket(x, market)).map((x) => decorateMenuItem(x, categories, routes, market));
|
|
615
615
|
return decoratedItem;
|
|
616
616
|
}
|
|
@@ -619,12 +619,14 @@ async function decorateMenus(store, items, market = "ww", locale = "en") {
|
|
|
619
619
|
}
|
|
620
620
|
function decorateMenuCategory(item, categories, routes, market, depth = 0) {
|
|
621
621
|
const decoratedItem = {
|
|
622
|
-
|
|
623
|
-
type: item.type,
|
|
624
|
-
title: "",
|
|
622
|
+
abstract: item.abstract,
|
|
625
623
|
category: "",
|
|
624
|
+
customClass: item.customClass,
|
|
626
625
|
href: "",
|
|
627
|
-
|
|
626
|
+
id: item.id || "",
|
|
627
|
+
items: [],
|
|
628
|
+
title: "",
|
|
629
|
+
type: item.type
|
|
628
630
|
};
|
|
629
631
|
const category = typeof item.category === "string" ? categories.find((x) => x.id === item.category) : item.category;
|
|
630
632
|
if (category) {
|
|
@@ -680,9 +682,11 @@ function decorateMenuRoute(item) {
|
|
|
680
682
|
function decorateMenuGroup(item, categories, routes, market) {
|
|
681
683
|
const items = item.items || [];
|
|
682
684
|
const decoratedItem = {
|
|
685
|
+
abstract: item.abstract,
|
|
686
|
+
customClass: item.customClass,
|
|
683
687
|
id: item.id || "",
|
|
684
|
-
type: item.type,
|
|
685
688
|
title: item.title,
|
|
689
|
+
type: item.type,
|
|
686
690
|
items: items.filter((x) => hasMarket(x, market)).map((x) => decorateMenuItem(x, categories, routes, market))
|
|
687
691
|
};
|
|
688
692
|
return decoratedItem;
|
|
@@ -690,11 +694,13 @@ function decorateMenuGroup(item, categories, routes, market) {
|
|
|
690
694
|
function decorateMenuLink(item, categories, routes, market) {
|
|
691
695
|
const items = item.items || [];
|
|
692
696
|
const decoratedItem = {
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
title: item.title,
|
|
697
|
+
abstract: item.abstract,
|
|
698
|
+
customClass: item.customClass,
|
|
696
699
|
href: item.href,
|
|
700
|
+
id: item.id || "",
|
|
697
701
|
target: item.target || "",
|
|
702
|
+
title: item.title,
|
|
703
|
+
type: item.type,
|
|
698
704
|
items: items.filter((x) => hasMarket(x, market)).map((x) => decorateMenuItem(x, categories, routes, market))
|
|
699
705
|
};
|
|
700
706
|
return decoratedItem;
|
|
@@ -706,6 +712,8 @@ function decorateMenuPage(item, categories, routes, market) {
|
|
|
706
712
|
id: item.id || "",
|
|
707
713
|
type: item.type,
|
|
708
714
|
title: item.title || item.page.value.title || "",
|
|
715
|
+
abstract: item.abstract || item.page.value.abstract || "",
|
|
716
|
+
customClass: item.customClass,
|
|
709
717
|
href: route?.id || "",
|
|
710
718
|
media: item.page.value.media,
|
|
711
719
|
page: route?.page || "",
|
package/dist/index.mjs
CHANGED
|
@@ -523,6 +523,26 @@ var MockMenuService = class extends MockService {
|
|
|
523
523
|
}
|
|
524
524
|
}
|
|
525
525
|
};
|
|
526
|
+
async function collectPages(store, items) {
|
|
527
|
+
if (!items) {
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
for (const item of items) {
|
|
531
|
+
if (item.type === "page" && typeof item.page.value === "number" && store[item.page.relationTo] !== void 0) {
|
|
532
|
+
const value = await store[item.page.relationTo].findOne(item.page.value);
|
|
533
|
+
if (value) {
|
|
534
|
+
item.page.value = value;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
switch (item.type) {
|
|
538
|
+
case "group":
|
|
539
|
+
case "link":
|
|
540
|
+
case "page":
|
|
541
|
+
await collectPages(store, item.items);
|
|
542
|
+
break;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
526
546
|
async function decorateMenu(store, item, market = "ww", locale = "en") {
|
|
527
547
|
const items = item.items || [];
|
|
528
548
|
const decoratedItem = {
|
|
@@ -540,27 +560,7 @@ async function decorateMenu(store, item, market = "ww", locale = "en") {
|
|
|
540
560
|
}
|
|
541
561
|
}
|
|
542
562
|
});
|
|
543
|
-
|
|
544
|
-
if (!items2) {
|
|
545
|
-
return;
|
|
546
|
-
}
|
|
547
|
-
for (const item2 of items2) {
|
|
548
|
-
if (item2.type === "page" && typeof item2.page.value === "number" && store[item2.page.relationTo] !== void 0) {
|
|
549
|
-
const value = await store[item2.page.relationTo].findOne(item2.page.value);
|
|
550
|
-
if (value) {
|
|
551
|
-
item2.page.value = value;
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
switch (item2.type) {
|
|
555
|
-
case "group":
|
|
556
|
-
case "link":
|
|
557
|
-
case "page":
|
|
558
|
-
await collectPages(item2.items);
|
|
559
|
-
break;
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
await collectPages(items);
|
|
563
|
+
await collectPages(store, items);
|
|
564
564
|
decoratedItem.items = items.filter((x) => hasMarket(x, market)).map((x) => decorateMenuItem(x, categories, routes, market));
|
|
565
565
|
return decoratedItem;
|
|
566
566
|
}
|
|
@@ -569,12 +569,14 @@ async function decorateMenus(store, items, market = "ww", locale = "en") {
|
|
|
569
569
|
}
|
|
570
570
|
function decorateMenuCategory(item, categories, routes, market, depth = 0) {
|
|
571
571
|
const decoratedItem = {
|
|
572
|
-
|
|
573
|
-
type: item.type,
|
|
574
|
-
title: "",
|
|
572
|
+
abstract: item.abstract,
|
|
575
573
|
category: "",
|
|
574
|
+
customClass: item.customClass,
|
|
576
575
|
href: "",
|
|
577
|
-
|
|
576
|
+
id: item.id || "",
|
|
577
|
+
items: [],
|
|
578
|
+
title: "",
|
|
579
|
+
type: item.type
|
|
578
580
|
};
|
|
579
581
|
const category = typeof item.category === "string" ? categories.find((x) => x.id === item.category) : item.category;
|
|
580
582
|
if (category) {
|
|
@@ -630,9 +632,11 @@ function decorateMenuRoute(item) {
|
|
|
630
632
|
function decorateMenuGroup(item, categories, routes, market) {
|
|
631
633
|
const items = item.items || [];
|
|
632
634
|
const decoratedItem = {
|
|
635
|
+
abstract: item.abstract,
|
|
636
|
+
customClass: item.customClass,
|
|
633
637
|
id: item.id || "",
|
|
634
|
-
type: item.type,
|
|
635
638
|
title: item.title,
|
|
639
|
+
type: item.type,
|
|
636
640
|
items: items.filter((x) => hasMarket(x, market)).map((x) => decorateMenuItem(x, categories, routes, market))
|
|
637
641
|
};
|
|
638
642
|
return decoratedItem;
|
|
@@ -640,11 +644,13 @@ function decorateMenuGroup(item, categories, routes, market) {
|
|
|
640
644
|
function decorateMenuLink(item, categories, routes, market) {
|
|
641
645
|
const items = item.items || [];
|
|
642
646
|
const decoratedItem = {
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
title: item.title,
|
|
647
|
+
abstract: item.abstract,
|
|
648
|
+
customClass: item.customClass,
|
|
646
649
|
href: item.href,
|
|
650
|
+
id: item.id || "",
|
|
647
651
|
target: item.target || "",
|
|
652
|
+
title: item.title,
|
|
653
|
+
type: item.type,
|
|
648
654
|
items: items.filter((x) => hasMarket(x, market)).map((x) => decorateMenuItem(x, categories, routes, market))
|
|
649
655
|
};
|
|
650
656
|
return decoratedItem;
|
|
@@ -656,6 +662,8 @@ function decorateMenuPage(item, categories, routes, market) {
|
|
|
656
662
|
id: item.id || "",
|
|
657
663
|
type: item.type,
|
|
658
664
|
title: item.title || item.page.value.title || "",
|
|
665
|
+
abstract: item.abstract || item.page.value.abstract || "",
|
|
666
|
+
customClass: item.customClass,
|
|
659
667
|
href: route?.id || "",
|
|
660
668
|
media: item.page.value.media,
|
|
661
669
|
page: route?.page || "",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@websolutespa/bom-mixer-store",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Mixer Store module of the BOM Repository",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bom",
|
|
@@ -45,12 +45,14 @@
|
|
|
45
45
|
"sideEffects": false,
|
|
46
46
|
"prepack": {
|
|
47
47
|
"types": "./dist/index.d.ts",
|
|
48
|
-
"main": "./dist/index.js"
|
|
48
|
+
"main": "./dist/index.js",
|
|
49
|
+
"source": "./src/index.ts"
|
|
49
50
|
},
|
|
50
51
|
"postpack": {
|
|
51
52
|
"types": "./src/index.ts",
|
|
52
53
|
"main": "./src/index.ts"
|
|
53
54
|
},
|
|
54
55
|
"types": "./dist/index.d.ts",
|
|
55
|
-
"main": "./dist/index.js"
|
|
56
|
+
"main": "./dist/index.js",
|
|
57
|
+
"source": "./src/index.ts"
|
|
56
58
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { NextApiRequest, NextApiResponse } from 'next';
|
|
2
|
+
|
|
3
|
+
export type ICrudMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | string;
|
|
4
|
+
|
|
5
|
+
export type IHandler = (request: NextApiRequest, response: NextApiResponse) => Promise<any>;
|
|
6
|
+
|
|
7
|
+
export type IApiHandler = Record<ICrudMethod, IHandler>;
|
|
8
|
+
|
|
9
|
+
export function apiHandler(handler: IApiHandler): any {
|
|
10
|
+
return async (request: NextApiRequest, response: NextApiResponse): Promise<any> => {
|
|
11
|
+
const method: ICrudMethod = (request.method || 'GET').toLowerCase() as ICrudMethod;
|
|
12
|
+
// check handler supports HTTP method
|
|
13
|
+
if (!handler[method]) {
|
|
14
|
+
return response.status(405).end(`Method ${method} Not Allowed`);
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
// global middleware
|
|
18
|
+
// await jwtMiddleware(request, response);
|
|
19
|
+
// route handler
|
|
20
|
+
await handler[method](request, response);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
// console.log('error', error);
|
|
23
|
+
// global error handler
|
|
24
|
+
return errorHandler(error, response);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function errorHandler(error: any, response: NextApiResponse): Promise<any> | void {
|
|
30
|
+
if (typeof (error) === 'string') {
|
|
31
|
+
// custom application error
|
|
32
|
+
const is404 = error.toLowerCase().endsWith('not found');
|
|
33
|
+
const statusCode = is404 ? 404 : 400;
|
|
34
|
+
return response.status(statusCode).json({ message: error });
|
|
35
|
+
}
|
|
36
|
+
if (error.name === 'UnauthorizedError') {
|
|
37
|
+
// jwt authentication error
|
|
38
|
+
return response.status(401).json({ message: 'Invalid Token' });
|
|
39
|
+
}
|
|
40
|
+
// default to 500 server error
|
|
41
|
+
console.error(error);
|
|
42
|
+
return response.status(500).json({ message: error.message });
|
|
43
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { FetchRequestOptions, httpFetch, merge } from '@websolutespa/bom-core';
|
|
2
|
+
|
|
3
|
+
const defaultApiOptions: FetchRequestOptions = {
|
|
4
|
+
// mode: 'cors',
|
|
5
|
+
headers: {
|
|
6
|
+
// Authorization: `Bearer ${BEARER}`,
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// typeof eval === 'function' ? defaultApiOptions.mode = 'cors' : null;
|
|
11
|
+
// const BEARER = process.env.STORE_BEARER || '7584f15d12972fb1e7695e998dd5e4c754f46c74d06a08e8d76f556adcd045e48cd52bed6faac098784471ac273ee40243194b9cff7eba3c4a768f8f41d2d51959a7f767b943c7f0170f6e5f632db523803c357083bf7a7bf03ee8e0df2d8ce5cd52e0211283b34d7781313da775018a9e950433d2b6faf711c20e5a63b25243';
|
|
12
|
+
|
|
13
|
+
export function getApiUrl(pathname: string): string {
|
|
14
|
+
const localUrl = process.env.NEXT_PUBLIC_URL === 'https://' ?
|
|
15
|
+
process.env.NEXT_PUBLIC_MOCK_FALLBACK_URL :
|
|
16
|
+
process.env.NEXT_PUBLIC_URL;
|
|
17
|
+
const apiBase = process.env.NEXT_PUBLIC_API || '/api';
|
|
18
|
+
const url = `${localUrl}${apiBase}${pathname}`;
|
|
19
|
+
return url;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function apiFetch<T = any>(pathname: string, options: FetchRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {
|
|
23
|
+
const url = new URL(getApiUrl(pathname));
|
|
24
|
+
if (serviceOptions) {
|
|
25
|
+
url.searchParams.append('locale', serviceOptions.locale);
|
|
26
|
+
url.searchParams.append('market', serviceOptions.market);
|
|
27
|
+
}
|
|
28
|
+
const apiOptions = merge({ ...defaultApiOptions }, options);
|
|
29
|
+
// console.log('apiFetch', url.href, apiOptions);
|
|
30
|
+
const apiResponse = await httpFetch(url.href, apiOptions);
|
|
31
|
+
return apiResponse;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function apiGet<T = any>(url: string, options: FetchRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {
|
|
35
|
+
return await apiFetch<T>(url, { ...options, method: 'GET' }, serviceOptions);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function apiPost<T = any>(url: string, payload?: unknown, options: FetchRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {
|
|
39
|
+
return await apiFetch<T>(url, { ...options, method: 'POST', body: payload ? JSON.stringify(payload) : undefined }, serviceOptions);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function apiPut<T = any>(url: string, payload?: unknown, options: FetchRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {
|
|
43
|
+
return await apiFetch<T>(url, { ...options, method: 'PUT', body: payload ? JSON.stringify(payload) : undefined }, serviceOptions);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function apiPatch<T = any>(url: string, payload?: unknown, options: FetchRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {
|
|
47
|
+
return await apiFetch<T>(url, { ...options, method: 'PATCH', body: payload ? JSON.stringify(payload) : undefined }, serviceOptions);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function apiDelete<T = any>(url: string, options: FetchRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {
|
|
51
|
+
return await apiFetch<T>(url, { ...options, method: 'DELETE' }, serviceOptions);
|
|
52
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
export async function fsExists(pathname: string): Promise<boolean> {
|
|
6
|
+
try {
|
|
7
|
+
await fs.promises.access(pathname);
|
|
8
|
+
return true;
|
|
9
|
+
} catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function fsRead(pathname: string, encoding = 'utf8'): Promise<any> {
|
|
15
|
+
try {
|
|
16
|
+
const data = await fs.promises.readFile(pathname, encoding);
|
|
17
|
+
return data || null;
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.log('fsRead', error, pathname);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function fsReadJson(pathname: string): Promise<any> {
|
|
25
|
+
try {
|
|
26
|
+
const data = await fsRead(pathname);
|
|
27
|
+
if (data) {
|
|
28
|
+
return JSON.parse(data);
|
|
29
|
+
} else {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.log('fsReadJson', error, pathname);
|
|
34
|
+
// throw (error);
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function fsWrite(pathname: string, data: string, encoding = 'utf8'): Promise<void> {
|
|
40
|
+
try {
|
|
41
|
+
await fs.promises.mkdir(path.dirname(pathname), { recursive: true });
|
|
42
|
+
await fs.promises.writeFile(pathname, data, encoding);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.log('fsWrite', error, pathname);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function fsWriteJson(pathname: string, data: any): Promise<void> {
|
|
49
|
+
try {
|
|
50
|
+
await fsWrite(pathname, JSON.stringify(data, null, 2));
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.log('fsWriteJson', error, pathname);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function fsExistOrCreateFolder(pathname: string): Promise<void> {
|
|
57
|
+
try {
|
|
58
|
+
const exists = fs.existsSync(pathname);
|
|
59
|
+
if (!exists) {
|
|
60
|
+
await fs.promises.mkdir(pathname);
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.log('fsExistOrCreateFolder', error, pathname);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export async function fsReadDirectory(pathname: string, extension?: string): Promise<{ name: string, data: string }[]> {
|
|
68
|
+
const files = await fs.promises.readdir(pathname);
|
|
69
|
+
const items = files.flatMap(async (file: string) => {
|
|
70
|
+
const filePath = path.join(pathname, file);
|
|
71
|
+
const stat = await fs.promises.stat(filePath);
|
|
72
|
+
if (stat.isDirectory()) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (extension && path.parse(file).ext !== extension) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const data = await fs.promises.readFile(filePath);
|
|
79
|
+
if (!data) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
name: path.parse(file).name,
|
|
84
|
+
data: data.toString(),
|
|
85
|
+
};
|
|
86
|
+
}) as Promise<{ name: string, data: string }>[];
|
|
87
|
+
const items2 = (await Promise.all(items)).filter(Boolean);
|
|
88
|
+
return items2;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export async function fsReadJsonDirectory(pathname: string): Promise<{ name: string, data: any }[]> {
|
|
92
|
+
try {
|
|
93
|
+
const datas = await fsReadDirectory(pathname, '.json');
|
|
94
|
+
return datas.filter(Boolean).map(x => {
|
|
95
|
+
x.data = JSON.parse(x.data);
|
|
96
|
+
return x;
|
|
97
|
+
});
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.log('fsReadJsonDirectory', error, pathname);
|
|
100
|
+
// throw (error);
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function fsWatch(pathname: string, callback: (eventType: any, fileName: string) => void, options?: { interval: 2000 }): void {
|
|
106
|
+
const debounced = debounce(callback);
|
|
107
|
+
return fs.watch(pathname, options, debounced);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function fsWatchFile(pathname: string, callback: (eventType: any, fileName: string) => void, options?: { interval: 2000 }): void {
|
|
111
|
+
const debounced = debounce(callback);
|
|
112
|
+
return fs.watchFile(pathname, options, debounced);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function pathJoin(...paths: string[]): string {
|
|
116
|
+
return path.join(process.cwd(), ...paths);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function debounce(callback: (...args: any[]) => void, timeout: number = 300) {
|
|
120
|
+
let timer: NodeJS.Timeout;
|
|
121
|
+
return (...args: any[]) => {
|
|
122
|
+
clearTimeout(timer);
|
|
123
|
+
timer = setTimeout(() => {
|
|
124
|
+
callback(...args);
|
|
125
|
+
}, timeout);
|
|
126
|
+
};
|
|
127
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from './api/api.handler';
|
|
2
|
+
export * from './api/api.service';
|
|
3
|
+
export * from './middleware/middleware.service';
|
|
4
|
+
export * from './mock/mock.handler';
|
|
5
|
+
export * from './mock/mock.service';
|
|
6
|
+
export * from './mock/mock.store';
|
|
7
|
+
// export * from './session/session.handler';
|
|
8
|
+
export * from './static/static';
|
|
9
|
+
export * from './static/static.service';
|
|
10
|
+
export * from './store/store';
|
|
11
|
+
export * from './store/store.handler';
|
|
12
|
+
export * from './store/store.service';
|
|
13
|
+
export * from './storeApi/storeApi.service';
|
|
14
|
+
export * from './storeApi/storeApi.store';
|
|
15
|
+
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { NextRequest } from 'next/server';
|
|
2
|
+
|
|
3
|
+
const API_BASE = process.env.NEXT_PUBLIC_API || '/api';
|
|
4
|
+
|
|
5
|
+
export function isStaticRequest(request: NextRequest) {
|
|
6
|
+
const url = request.nextUrl;
|
|
7
|
+
const isStatic = url.pathname.indexOf('.') !== -1;
|
|
8
|
+
return isStatic;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function isNextRequest(request: NextRequest) {
|
|
12
|
+
const url = request.nextUrl;
|
|
13
|
+
const isNext = url.pathname.indexOf('/_next/') === 0;
|
|
14
|
+
return isNext;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isApiRequest(request: NextRequest) {
|
|
18
|
+
const url = request.nextUrl;
|
|
19
|
+
const isApi = url.pathname.indexOf(API_BASE) === 0;
|
|
20
|
+
return isApi;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
import { NextApiRequest, NextApiResponse } from 'next';
|
|
25
|
+
|
|
26
|
+
export type RouteMiddleware = (request: NextRequest, event: NextFetchEvent) => Promise<Response | undefined> | Response | undefined;
|
|
27
|
+
|
|
28
|
+
export type ApiMiddleware = (request: NextApiRequest, response: NextApiResponse) => unknown;
|
|
29
|
+
|
|
30
|
+
// Helper method to wait for a middleware to execute before continuing
|
|
31
|
+
// And to throw an error when an error happens in a middleware
|
|
32
|
+
export default function useApiMiddleware(middleware) {
|
|
33
|
+
return (request, response) => new Promise((resolve, reject) => {
|
|
34
|
+
middleware(request, response, (result) => {
|
|
35
|
+
if (result instanceof Error) {
|
|
36
|
+
return reject(result);
|
|
37
|
+
}
|
|
38
|
+
return resolve(result);
|
|
39
|
+
});
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
* @name withMiddleware
|
|
44
|
+
* @description combine multiple middleware before handling your API endpoint
|
|
45
|
+
* @param middlewares
|
|
46
|
+
export function withApiMiddleware(...middlewares: ApiMiddleware[]) {
|
|
47
|
+
|
|
48
|
+
return async function withMiddlewareHandler(request: NextApiRequest, response: NextApiResponse) {
|
|
49
|
+
|
|
50
|
+
async function evaluateHandler(middleware: ApiMiddleware, innerMiddleware?: ApiMiddleware | undefined) {
|
|
51
|
+
// return early when the request has
|
|
52
|
+
// been ended by a previous middleware
|
|
53
|
+
if (response.headersSent) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (typeof middleware === 'function') {
|
|
57
|
+
const handler = await middleware(request, response);
|
|
58
|
+
if (typeof handler === 'function') {
|
|
59
|
+
if (innerMiddleware) {
|
|
60
|
+
await handler(innerMiddleware);
|
|
61
|
+
const index = middlewares.indexOf(innerMiddleware);
|
|
62
|
+
// remove inner middleware
|
|
63
|
+
if (index >= 0) {
|
|
64
|
+
middlewares.splice(index, 1);
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
await handler();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
for (let index = 0; index < middlewares.length; index++) {
|
|
73
|
+
const middleware = middlewares[index];
|
|
74
|
+
const nextMiddleware = middlewares[index + 1];
|
|
75
|
+
await evaluateHandler(middleware, nextMiddleware);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
*/
|