@smess/networking 1.0.9 → 1.0.12
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/README.md +26 -20
- package/dist/core/axios.d.ts +3 -3
- package/dist/core/axios.js +2 -2
- package/dist/core/axios.observable.d.ts +3 -3
- package/dist/core/axios.observable.js +7 -7
- package/dist/core/base.provider.advanced.test.js +15 -15
- package/dist/core/base.provider.d.ts +1 -1
- package/dist/core/base.provider.js +2 -2
- package/dist/core/base.provider.test.js +22 -18
- package/dist/core/base.service.wrapper.advanced.test.js +16 -13
- package/dist/core/base.service.wrapper.d.ts +2 -2
- package/dist/core/base.service.wrapper.js +1 -1
- package/dist/core/base.service.wrapper.test.js +14 -14
- package/dist/core/rx.http.service.d.ts +3 -3
- package/dist/core/rx.http.service.js +2 -2
- package/dist/index.d.ts +13 -13
- package/dist/index.js +15 -15
- package/dist/services/auth.service.d.ts +6 -5
- package/dist/services/auth.service.js +50 -28
- package/dist/services/auth.service.test.js +67 -51
- package/dist/services/cache.service.d.ts +1 -1
- package/dist/services/cache.service.js +7 -7
- package/dist/services/cache.service.test.d.ts +1 -1
- package/dist/services/cache.service.test.js +37 -37
- package/dist/services/customer.service.d.ts +4 -4
- package/dist/services/customer.service.js +19 -17
- package/dist/services/customer.service.test.js +38 -34
- package/dist/services/logger.service.js +11 -11
- package/dist/services/logger.service.test.js +12 -12
- package/dist/services/order.service.d.ts +5 -4
- package/dist/services/order.service.js +32 -30
- package/dist/services/order.service.test.js +47 -47
- package/dist/services/product.service.d.ts +4 -4
- package/dist/services/product.service.js +8 -8
- package/dist/services/product.service.test.js +27 -19
- package/dist/services/smess.service.d.ts +2 -2
- package/dist/services/smess.service.js +19 -19
- package/dist/services/smess.service.test.js +36 -32
- package/dist/services/store.service.d.ts +4 -4
- package/dist/services/store.service.js +70 -50
- package/dist/services/store.service.test.d.ts +1 -1
- package/dist/services/store.service.test.js +161 -85
- package/dist/services/user.service.d.ts +3 -3
- package/dist/services/user.service.js +11 -8
- package/dist/services/user.service.test.js +23 -17
- package/dist/types/types.js +3 -3
- package/dist/types/types.test.js +8 -8
- package/dist/utils/cache-import.d.ts +1 -1
- package/dist/utils/cache-import.js +1 -1
- package/dist/utils/networking-import.d.ts +3 -3
- package/dist/utils/networking-import.js +2 -2
- package/dist/utils/rxjs-import.d.ts +2 -2
- package/dist/utils/rxjs-import.js +2 -2
- package/package.json +1 -1
|
@@ -1,51 +1,59 @@
|
|
|
1
|
-
import { ProductService } from
|
|
2
|
-
import { NetworkingUIEventWrapped } from
|
|
3
|
-
import { of, throwError } from
|
|
4
|
-
import { BaseServiceWrapper } from
|
|
5
|
-
describe(
|
|
1
|
+
import { ProductService } from "./product.service";
|
|
2
|
+
import { NetworkingUIEventWrapped } from "../types/types";
|
|
3
|
+
import { of, throwError } from "rxjs";
|
|
4
|
+
import { BaseServiceWrapper } from "../core/base.service.wrapper";
|
|
5
|
+
describe("ProductService", () => {
|
|
6
6
|
const config = {
|
|
7
|
-
baseUrl:
|
|
7
|
+
baseUrl: "https://jsonplaceholder.typicode.com",
|
|
8
8
|
isProd: false,
|
|
9
|
-
clientId:
|
|
10
|
-
apiKey:
|
|
9
|
+
clientId: "test-client",
|
|
10
|
+
apiKey: "test-key",
|
|
11
11
|
};
|
|
12
|
-
const product = { id: 1, name:
|
|
12
|
+
const product = { id: 1, name: "Product", price: 10 };
|
|
13
13
|
let requestSpy;
|
|
14
14
|
beforeEach(() => {
|
|
15
|
-
requestSpy = jest
|
|
15
|
+
requestSpy = jest
|
|
16
|
+
.spyOn(BaseServiceWrapper.prototype, "request")
|
|
17
|
+
.mockImplementation(() => of(NetworkingUIEventWrapped.succeeded(product)));
|
|
16
18
|
});
|
|
17
19
|
afterEach(() => {
|
|
18
20
|
requestSpy.mockRestore();
|
|
19
21
|
});
|
|
20
|
-
it(
|
|
22
|
+
it("should fetch product by id", (done) => {
|
|
21
23
|
const service = new ProductService(config, 1);
|
|
22
|
-
service
|
|
24
|
+
service
|
|
25
|
+
.fetchProductById(1)
|
|
26
|
+
.subscribe((result) => {
|
|
23
27
|
expect(result.response).toEqual(product);
|
|
24
28
|
done();
|
|
25
29
|
});
|
|
26
30
|
});
|
|
27
|
-
it(
|
|
31
|
+
it("should fetch all products", (done) => {
|
|
28
32
|
const service = new ProductService(config);
|
|
29
|
-
service
|
|
33
|
+
service
|
|
34
|
+
.fetchAllProducts()
|
|
35
|
+
.subscribe((result) => {
|
|
30
36
|
expect(result.response).toEqual(product);
|
|
31
37
|
done();
|
|
32
38
|
});
|
|
33
39
|
});
|
|
34
|
-
it(
|
|
40
|
+
it("should create a product", (done) => {
|
|
35
41
|
const service = new ProductService(config);
|
|
36
|
-
service
|
|
42
|
+
service
|
|
43
|
+
.createProduct({ name: "New Product", price: 99.99 })
|
|
44
|
+
.subscribe((result) => {
|
|
37
45
|
expect(result.response).toEqual(product);
|
|
38
46
|
done();
|
|
39
47
|
});
|
|
40
48
|
});
|
|
41
|
-
it(
|
|
42
|
-
requestSpy.mockImplementationOnce(() => throwError(() => new Error(
|
|
49
|
+
it("request should handle error", (done) => {
|
|
50
|
+
requestSpy.mockImplementationOnce(() => throwError(() => new Error("Test error")));
|
|
43
51
|
const service = new ProductService(config);
|
|
44
52
|
// Simulate error by calling a method that uses request
|
|
45
53
|
service.fetchProductById(1).subscribe({
|
|
46
54
|
error: (err) => {
|
|
47
55
|
expect(err).toBeInstanceOf(Error);
|
|
48
|
-
expect(err.message).toBe(
|
|
56
|
+
expect(err.message).toBe("Test error");
|
|
49
57
|
done();
|
|
50
58
|
},
|
|
51
59
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { HeaderType, NetworkingUIEventWrapped, ProviderType } from
|
|
2
|
-
import { Observable } from
|
|
1
|
+
import { HeaderType, NetworkingUIEventWrapped, ProviderType } from "../types/types";
|
|
2
|
+
import { Observable } from "../utils/rxjs-import";
|
|
3
3
|
export declare enum SMESSHeader {
|
|
4
4
|
ContentType = "Content-Type",
|
|
5
5
|
Authorization = "Authorization",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { AlertButtonModel, AlertModel, NetworkingUIEventWrapped, } from
|
|
2
|
-
import { catchError, mergeMap, of, startWith, } from
|
|
3
|
-
import HttpService from
|
|
4
|
-
import { $logger } from
|
|
1
|
+
import { AlertButtonModel, AlertModel, NetworkingUIEventWrapped, } from "../types/types";
|
|
2
|
+
import { catchError, mergeMap, of, startWith, } from "../utils/rxjs-import";
|
|
3
|
+
import HttpService from "../core/rx.http.service";
|
|
4
|
+
import { $logger } from "../services/logger.service";
|
|
5
5
|
export var SMESSHeader;
|
|
6
6
|
(function (SMESSHeader) {
|
|
7
7
|
SMESSHeader["ContentType"] = "Content-Type";
|
|
@@ -32,12 +32,12 @@ export class SmessService {
|
|
|
32
32
|
constructor(target) {
|
|
33
33
|
this.target = target;
|
|
34
34
|
// Set default headers
|
|
35
|
-
$logger.info(
|
|
35
|
+
$logger.info("SmessService initialized", {
|
|
36
36
|
target: this.target,
|
|
37
37
|
baseURL: this.target.baseURL,
|
|
38
38
|
method: this.target.method,
|
|
39
39
|
headers: this.target.headers,
|
|
40
|
-
},
|
|
40
|
+
}, "SmessService");
|
|
41
41
|
this.httpService = HttpService.create({
|
|
42
42
|
baseURL: this.target.baseURL,
|
|
43
43
|
headers: this.target.headers,
|
|
@@ -47,7 +47,7 @@ export class SmessService {
|
|
|
47
47
|
const originalRequest = error.config;
|
|
48
48
|
if (error.response?.status === 401 && !originalRequest._retry) {
|
|
49
49
|
originalRequest._retry = true;
|
|
50
|
-
$logger.info(
|
|
50
|
+
$logger.info("SmessService constructor - 401 retry", originalRequest, "SmessService");
|
|
51
51
|
// Implement token refresh logic here
|
|
52
52
|
// Then retry the original request
|
|
53
53
|
// return httpService.request(originalRequest);
|
|
@@ -58,21 +58,21 @@ export class SmessService {
|
|
|
58
58
|
static getHeaders(version, authorization = null, options) {
|
|
59
59
|
const headers = this.commonHeaders(version, options);
|
|
60
60
|
if (authorization) {
|
|
61
|
-
headers[
|
|
61
|
+
headers["Authorization"] = authorization;
|
|
62
62
|
}
|
|
63
63
|
return headers;
|
|
64
64
|
}
|
|
65
65
|
static filterHeaders(headers) {
|
|
66
|
-
const filteredHeaders = Object.fromEntries(Object.entries(headers).filter(([_, value]) => value !== undefined && value !== null && value !==
|
|
66
|
+
const filteredHeaders = Object.fromEntries(Object.entries(headers).filter(([_, value]) => value !== undefined && value !== null && value !== ""));
|
|
67
67
|
return filteredHeaders;
|
|
68
68
|
}
|
|
69
69
|
static commonHeaders(version, options) {
|
|
70
|
-
const { shouldAddClientIdHeader = true
|
|
70
|
+
const { shouldAddClientIdHeader = true } = options ?? {};
|
|
71
71
|
const headers = {
|
|
72
72
|
Accept: version,
|
|
73
|
-
Authorization:
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
Authorization: "",
|
|
74
|
+
"Content-Type": ContentType.Json,
|
|
75
|
+
"X-Api-Key": "",
|
|
76
76
|
};
|
|
77
77
|
return headers;
|
|
78
78
|
}
|
|
@@ -83,20 +83,20 @@ export class SmessService {
|
|
|
83
83
|
: this.target.path;
|
|
84
84
|
const config = { url };
|
|
85
85
|
let observable;
|
|
86
|
-
if (this.target.method ===
|
|
86
|
+
if (this.target.method === "GET") {
|
|
87
87
|
if (request) {
|
|
88
88
|
config.data = request;
|
|
89
89
|
config.params = request;
|
|
90
90
|
}
|
|
91
91
|
observable = this.httpService.get(url, config);
|
|
92
92
|
}
|
|
93
|
-
else if (this.target.method ===
|
|
93
|
+
else if (this.target.method === "POST") {
|
|
94
94
|
observable = this.httpService.post(url, request, config);
|
|
95
95
|
}
|
|
96
|
-
else if (this.target.method ===
|
|
96
|
+
else if (this.target.method === "PATCH") {
|
|
97
97
|
observable = this.httpService.patch(url, request, config);
|
|
98
98
|
}
|
|
99
|
-
else if (this.target.method ===
|
|
99
|
+
else if (this.target.method === "PUT") {
|
|
100
100
|
observable = this.httpService.put(url, request, config);
|
|
101
101
|
}
|
|
102
102
|
else {
|
|
@@ -106,7 +106,7 @@ export class SmessService {
|
|
|
106
106
|
}
|
|
107
107
|
// MARK: - Private
|
|
108
108
|
transformAxiosError(error, mockResponse) {
|
|
109
|
-
$logger.error(
|
|
109
|
+
$logger.error("transformAxiosError", error, "SmessService");
|
|
110
110
|
const message = error instanceof Error ? error.message : String(error);
|
|
111
111
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Required for axios compatibility
|
|
112
112
|
const response = error.response;
|
|
@@ -119,7 +119,7 @@ export class SmessService {
|
|
|
119
119
|
return of(NetworkingUIEventWrapped.failed(alertModel));
|
|
120
120
|
}
|
|
121
121
|
transformAxiosResponse(response) {
|
|
122
|
-
$logger.info(
|
|
122
|
+
$logger.info("transformAxiosResponse", response, "SmessService");
|
|
123
123
|
if (response instanceof NetworkingUIEventWrapped) {
|
|
124
124
|
return of(response);
|
|
125
125
|
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any -- Required for test mocks */
|
|
2
|
-
import { SmessService } from
|
|
3
|
-
import { NetworkingUIEventWrapped } from
|
|
4
|
-
import { of, throwError } from
|
|
5
|
-
describe(
|
|
2
|
+
import { SmessService } from "./smess.service";
|
|
3
|
+
import { NetworkingUIEventWrapped, } from "../types/types";
|
|
4
|
+
import { of, throwError } from "rxjs";
|
|
5
|
+
describe("SmessService", () => {
|
|
6
6
|
const config = {
|
|
7
|
-
baseUrl:
|
|
7
|
+
baseUrl: "https://api.example.com",
|
|
8
8
|
isProd: false,
|
|
9
|
-
clientId:
|
|
10
|
-
apiKey:
|
|
9
|
+
clientId: "test-client",
|
|
10
|
+
apiKey: "test-key",
|
|
11
11
|
};
|
|
12
12
|
const provider = {
|
|
13
13
|
baseURL: config.baseUrl,
|
|
14
|
-
path:
|
|
15
|
-
method:
|
|
14
|
+
path: "/resource",
|
|
15
|
+
method: "GET",
|
|
16
16
|
headers: {},
|
|
17
|
-
getPath: () =>
|
|
17
|
+
getPath: () => "/resource",
|
|
18
18
|
};
|
|
19
|
-
it(
|
|
19
|
+
it("should return succeeded for GET", (done) => {
|
|
20
20
|
const service = new SmessService(provider);
|
|
21
|
-
service[
|
|
22
|
-
get: jest.fn(() => of({ data: { foo:
|
|
21
|
+
service["httpService"] = {
|
|
22
|
+
get: jest.fn(() => of({ data: { foo: "bar" } })),
|
|
23
23
|
post: jest.fn(),
|
|
24
24
|
patch: jest.fn(),
|
|
25
25
|
put: jest.fn(),
|
|
@@ -28,33 +28,35 @@ describe('SmessService', () => {
|
|
|
28
28
|
};
|
|
29
29
|
service.request().subscribe((result) => {
|
|
30
30
|
if (result.hasSuccess) {
|
|
31
|
-
expect(result.response).toEqual({ foo:
|
|
31
|
+
expect(result.response).toEqual({ foo: "bar" });
|
|
32
32
|
done();
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
35
|
});
|
|
36
|
-
it(
|
|
37
|
-
const postProvider = { ...provider, method:
|
|
36
|
+
it("should return succeeded for POST", (done) => {
|
|
37
|
+
const postProvider = { ...provider, method: "POST" };
|
|
38
38
|
const service = new SmessService(postProvider);
|
|
39
|
-
service[
|
|
39
|
+
service["httpService"] = {
|
|
40
40
|
get: jest.fn(),
|
|
41
|
-
post: jest.fn(() => of({ data: { foo:
|
|
41
|
+
post: jest.fn(() => of({ data: { foo: "baz" } })),
|
|
42
42
|
patch: jest.fn(),
|
|
43
43
|
put: jest.fn(),
|
|
44
44
|
request: jest.fn(),
|
|
45
45
|
interceptors: { response: { use: jest.fn() } },
|
|
46
46
|
};
|
|
47
|
-
service
|
|
47
|
+
service
|
|
48
|
+
.request({ some: "data" })
|
|
49
|
+
.subscribe((result) => {
|
|
48
50
|
if (result.hasSuccess) {
|
|
49
|
-
expect(result.response).toEqual({ foo:
|
|
51
|
+
expect(result.response).toEqual({ foo: "baz" });
|
|
50
52
|
done();
|
|
51
53
|
}
|
|
52
54
|
});
|
|
53
55
|
});
|
|
54
|
-
it(
|
|
56
|
+
it("should handle error", (done) => {
|
|
55
57
|
const service = new SmessService(provider);
|
|
56
|
-
service[
|
|
57
|
-
get: jest.fn(() => throwError(() => new Error(
|
|
58
|
+
service["httpService"] = {
|
|
59
|
+
get: jest.fn(() => throwError(() => new Error("Test error"))),
|
|
58
60
|
post: jest.fn(),
|
|
59
61
|
patch: jest.fn(),
|
|
60
62
|
put: jest.fn(),
|
|
@@ -66,32 +68,34 @@ describe('SmessService', () => {
|
|
|
66
68
|
expect(result).toBeInstanceOf(NetworkingUIEventWrapped);
|
|
67
69
|
expect(result.hasFailed).toBe(true);
|
|
68
70
|
expect(result.alertModel).toBeTruthy();
|
|
69
|
-
expect(result.alertModel?.message).toBe(
|
|
71
|
+
expect(result.alertModel?.message).toBe("Test error");
|
|
70
72
|
done();
|
|
71
73
|
}
|
|
72
74
|
});
|
|
73
75
|
});
|
|
74
|
-
it(
|
|
76
|
+
it("should return mock response if provided", (done) => {
|
|
75
77
|
const service = new SmessService(provider);
|
|
76
|
-
service[
|
|
77
|
-
get: jest.fn(() => throwError(() => new Error(
|
|
78
|
+
service["httpService"] = {
|
|
79
|
+
get: jest.fn(() => throwError(() => new Error("Test error"))),
|
|
78
80
|
post: jest.fn(),
|
|
79
81
|
patch: jest.fn(),
|
|
80
82
|
put: jest.fn(),
|
|
81
83
|
request: jest.fn((payload, mockResponse) => {
|
|
82
|
-
if (payload ===
|
|
83
|
-
return throwError(() => new Error(
|
|
84
|
+
if (payload === "error") {
|
|
85
|
+
return throwError(() => new Error("Test error"));
|
|
84
86
|
}
|
|
85
87
|
if (mockResponse !== undefined) {
|
|
86
88
|
return of(NetworkingUIEventWrapped.succeeded(mockResponse));
|
|
87
89
|
}
|
|
88
|
-
return of({ data: { foo:
|
|
90
|
+
return of({ data: { foo: "mock" } });
|
|
89
91
|
}),
|
|
90
92
|
interceptors: { response: { use: jest.fn() } },
|
|
91
93
|
};
|
|
92
|
-
service
|
|
94
|
+
service
|
|
95
|
+
.request(undefined, { foo: "mock" })
|
|
96
|
+
.subscribe((result) => {
|
|
93
97
|
if (result.hasSuccess) {
|
|
94
|
-
expect(result.response).toEqual({ foo:
|
|
98
|
+
expect(result.response).toEqual({ foo: "mock" });
|
|
95
99
|
done();
|
|
96
100
|
}
|
|
97
101
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ProviderType, NetworkingConfig, NetworkingUIEventWrapped, HttpResponse } from
|
|
2
|
-
import { SmessService } from
|
|
3
|
-
import { BehaviorSubject, Observable } from
|
|
4
|
-
export type StoreTarget =
|
|
1
|
+
import { ProviderType, NetworkingConfig, NetworkingUIEventWrapped, HttpResponse } from "../types/types";
|
|
2
|
+
import { SmessService } from "./smess.service";
|
|
3
|
+
import { BehaviorSubject, Observable } from "rxjs";
|
|
4
|
+
export type StoreTarget = "store-get" | "store-list" | "store-product-category-list" | "store-product-collection" | "store-featured-product-list";
|
|
5
5
|
export interface ProductCollectionRequest {
|
|
6
6
|
page?: number;
|
|
7
7
|
per_page?: number;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { NetworkingUIEventWrapped } from
|
|
2
|
-
import { Accept, SMESSHeader, SmessService } from
|
|
3
|
-
import { from, of } from
|
|
4
|
-
import { map, switchMap, catchError } from
|
|
5
|
-
import { GenericIndexedDBService } from
|
|
1
|
+
import { NetworkingUIEventWrapped, } from "../types/types";
|
|
2
|
+
import { Accept, SMESSHeader, SmessService } from "./smess.service";
|
|
3
|
+
import { from, of } from "rxjs";
|
|
4
|
+
import { map, switchMap, catchError } from "rxjs/operators";
|
|
5
|
+
import { GenericIndexedDBService } from "./cache.service";
|
|
6
6
|
export class StoreProvider {
|
|
7
7
|
constructor(config, target, $authToken) {
|
|
8
8
|
this.config = config;
|
|
@@ -10,26 +10,28 @@ export class StoreProvider {
|
|
|
10
10
|
this.$authToken = $authToken;
|
|
11
11
|
}
|
|
12
12
|
get baseURL() {
|
|
13
|
-
return this.config.version
|
|
13
|
+
return this.config.version
|
|
14
|
+
? `${this.config.baseUrl}/${this.config.version}`
|
|
15
|
+
: this.config.baseUrl;
|
|
14
16
|
}
|
|
15
17
|
get path() {
|
|
16
18
|
switch (this.target) {
|
|
17
|
-
case
|
|
18
|
-
return
|
|
19
|
-
case
|
|
20
|
-
return
|
|
21
|
-
case
|
|
22
|
-
return
|
|
23
|
-
case
|
|
24
|
-
return
|
|
25
|
-
case
|
|
26
|
-
return
|
|
19
|
+
case "store-get":
|
|
20
|
+
return "/store/${id}/information";
|
|
21
|
+
case "store-list":
|
|
22
|
+
return "/store/list";
|
|
23
|
+
case "store-product-category-list":
|
|
24
|
+
return "/store/product-category-list";
|
|
25
|
+
case "store-product-collection":
|
|
26
|
+
return "/store/${id}/product-collection";
|
|
27
|
+
case "store-featured-product-list":
|
|
28
|
+
return "/store/${id}/featured-product-list";
|
|
27
29
|
default:
|
|
28
|
-
return
|
|
30
|
+
return "/store/${id}";
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
get method() {
|
|
32
|
-
return
|
|
34
|
+
return "GET";
|
|
33
35
|
}
|
|
34
36
|
get headers() {
|
|
35
37
|
let headers = SmessService.getHeaders(Accept.V1, this.$authToken.value);
|
|
@@ -55,34 +57,36 @@ export class StoreService {
|
|
|
55
57
|
this.config = config;
|
|
56
58
|
this.$authToken = $authToken;
|
|
57
59
|
// Initialize cache services for different data types
|
|
58
|
-
this.cacheService = new GenericIndexedDBService(
|
|
59
|
-
this.storeListCache = new GenericIndexedDBService(
|
|
60
|
-
this.productCollectionCache = new GenericIndexedDBService(
|
|
61
|
-
this.productCategoryCache = new GenericIndexedDBService(
|
|
62
|
-
this.featuredProductCache = new GenericIndexedDBService(
|
|
60
|
+
this.cacheService = new GenericIndexedDBService("StoreCache", "id, timestamp", (data) => data, (data) => data);
|
|
61
|
+
this.storeListCache = new GenericIndexedDBService("StoreListCache", "timestamp", (data) => data, (data) => data);
|
|
62
|
+
this.productCollectionCache = new GenericIndexedDBService("ProductCollectionCache", "storeId, timestamp", (data) => data, (data) => data);
|
|
63
|
+
this.productCategoryCache = new GenericIndexedDBService("ProductCategoryCache", "timestamp", (data) => data, (data) => data);
|
|
64
|
+
this.featuredProductCache = new GenericIndexedDBService("FeaturedProductCache", "storeId, timestamp", (data) => data, (data) => data);
|
|
63
65
|
}
|
|
64
66
|
provider(target) {
|
|
65
67
|
const targetWrapper = new StoreProvider(this.config, target, this.$authToken);
|
|
66
68
|
return new SmessService(targetWrapper);
|
|
67
69
|
}
|
|
68
70
|
get(id) {
|
|
69
|
-
return from(this.cacheService.getOne(id)).pipe(switchMap(cachedData => {
|
|
71
|
+
return from(this.cacheService.getOne(id)).pipe(switchMap((cachedData) => {
|
|
70
72
|
if (cachedData && this.isCacheValid(cachedData.timestamp)) {
|
|
71
73
|
// Return cached data if valid
|
|
72
74
|
return of(NetworkingUIEventWrapped.succeeded(cachedData.data));
|
|
73
75
|
}
|
|
74
76
|
// Fetch from network if no cache or expired
|
|
75
|
-
return this.provider(
|
|
77
|
+
return this.provider("store-get")
|
|
78
|
+
.request(null, undefined, id)
|
|
79
|
+
.pipe(map((response) => {
|
|
76
80
|
// Cache the successful response
|
|
77
81
|
if (response.response) {
|
|
78
82
|
this.cacheService.saveOne({
|
|
79
83
|
id,
|
|
80
84
|
data: response.response,
|
|
81
|
-
timestamp: Date.now()
|
|
85
|
+
timestamp: Date.now(),
|
|
82
86
|
});
|
|
83
87
|
}
|
|
84
88
|
return response;
|
|
85
|
-
}), catchError(error => {
|
|
89
|
+
}), catchError((error) => {
|
|
86
90
|
// If network fails and we have stale cache, return it
|
|
87
91
|
if (cachedData) {
|
|
88
92
|
return of(NetworkingUIEventWrapped.succeeded(cachedData.data));
|
|
@@ -92,19 +96,25 @@ export class StoreService {
|
|
|
92
96
|
}));
|
|
93
97
|
}
|
|
94
98
|
list() {
|
|
95
|
-
return from(this.storeListCache.getAll(
|
|
96
|
-
if (cachedData &&
|
|
99
|
+
return from(this.storeListCache.getAll("store-list")).pipe(switchMap((cachedData) => {
|
|
100
|
+
if (cachedData &&
|
|
101
|
+
cachedData.length > 0 &&
|
|
102
|
+
this.isCacheValid(cachedData[0].timestamp)) {
|
|
97
103
|
return of(NetworkingUIEventWrapped.succeeded(cachedData[0].data));
|
|
98
104
|
}
|
|
99
|
-
return this.provider(
|
|
105
|
+
return this.provider("store-list")
|
|
106
|
+
.request()
|
|
107
|
+
.pipe(map((response) => {
|
|
100
108
|
if (response.response) {
|
|
101
|
-
this.storeListCache.saveAll([
|
|
109
|
+
this.storeListCache.saveAll([
|
|
110
|
+
{
|
|
102
111
|
data: response.response,
|
|
103
|
-
timestamp: Date.now()
|
|
104
|
-
}
|
|
112
|
+
timestamp: Date.now(),
|
|
113
|
+
},
|
|
114
|
+
], "store-list");
|
|
105
115
|
}
|
|
106
116
|
return response;
|
|
107
|
-
}), catchError(error => {
|
|
117
|
+
}), catchError((error) => {
|
|
108
118
|
if (cachedData && cachedData.length > 0) {
|
|
109
119
|
return of(NetworkingUIEventWrapped.succeeded(cachedData[0].data));
|
|
110
120
|
}
|
|
@@ -113,19 +123,25 @@ export class StoreService {
|
|
|
113
123
|
}));
|
|
114
124
|
}
|
|
115
125
|
productCategoryList() {
|
|
116
|
-
return from(this.productCategoryCache.getAll(
|
|
117
|
-
if (cachedData &&
|
|
126
|
+
return from(this.productCategoryCache.getAll("product-category-list")).pipe(switchMap((cachedData) => {
|
|
127
|
+
if (cachedData &&
|
|
128
|
+
cachedData.length > 0 &&
|
|
129
|
+
this.isCacheValid(cachedData[0].timestamp)) {
|
|
118
130
|
return of(NetworkingUIEventWrapped.succeeded(cachedData[0].data));
|
|
119
131
|
}
|
|
120
|
-
return this.provider(
|
|
132
|
+
return this.provider("store-product-category-list")
|
|
133
|
+
.request()
|
|
134
|
+
.pipe(map((response) => {
|
|
121
135
|
if (response.response) {
|
|
122
|
-
this.productCategoryCache.saveAll([
|
|
136
|
+
this.productCategoryCache.saveAll([
|
|
137
|
+
{
|
|
123
138
|
data: response.response,
|
|
124
|
-
timestamp: Date.now()
|
|
125
|
-
}
|
|
139
|
+
timestamp: Date.now(),
|
|
140
|
+
},
|
|
141
|
+
], "product-category-list");
|
|
126
142
|
}
|
|
127
143
|
return response;
|
|
128
|
-
}), catchError(error => {
|
|
144
|
+
}), catchError((error) => {
|
|
129
145
|
if (cachedData && cachedData.length > 0) {
|
|
130
146
|
return of(NetworkingUIEventWrapped.succeeded(cachedData[0].data));
|
|
131
147
|
}
|
|
@@ -135,21 +151,23 @@ export class StoreService {
|
|
|
135
151
|
}
|
|
136
152
|
productCollection(id, payload) {
|
|
137
153
|
const cacheKey = `${id}-${JSON.stringify(payload)}`;
|
|
138
|
-
return from(this.productCollectionCache.getOne(cacheKey)).pipe(switchMap(cachedData => {
|
|
154
|
+
return from(this.productCollectionCache.getOne(cacheKey)).pipe(switchMap((cachedData) => {
|
|
139
155
|
if (cachedData && this.isCacheValid(cachedData.timestamp)) {
|
|
140
156
|
return of(NetworkingUIEventWrapped.succeeded(cachedData.data));
|
|
141
157
|
}
|
|
142
|
-
return this.provider(
|
|
158
|
+
return this.provider("store-product-collection")
|
|
159
|
+
.request(payload, undefined, id)
|
|
160
|
+
.pipe(map((response) => {
|
|
143
161
|
if (response.response) {
|
|
144
162
|
this.productCollectionCache.saveOne({
|
|
145
163
|
storeId: cacheKey,
|
|
146
164
|
request: payload,
|
|
147
165
|
data: response.response,
|
|
148
|
-
timestamp: Date.now()
|
|
166
|
+
timestamp: Date.now(),
|
|
149
167
|
});
|
|
150
168
|
}
|
|
151
169
|
return response;
|
|
152
|
-
}), catchError(error => {
|
|
170
|
+
}), catchError((error) => {
|
|
153
171
|
if (cachedData) {
|
|
154
172
|
return of(NetworkingUIEventWrapped.succeeded(cachedData.data));
|
|
155
173
|
}
|
|
@@ -158,20 +176,22 @@ export class StoreService {
|
|
|
158
176
|
}));
|
|
159
177
|
}
|
|
160
178
|
featuredProductList(id) {
|
|
161
|
-
return from(this.featuredProductCache.getOne(id)).pipe(switchMap(cachedData => {
|
|
179
|
+
return from(this.featuredProductCache.getOne(id)).pipe(switchMap((cachedData) => {
|
|
162
180
|
if (cachedData && this.isCacheValid(cachedData.timestamp)) {
|
|
163
181
|
return of(NetworkingUIEventWrapped.succeeded(cachedData.data));
|
|
164
182
|
}
|
|
165
|
-
return this.provider(
|
|
183
|
+
return this.provider("store-featured-product-list")
|
|
184
|
+
.request(null, undefined, id)
|
|
185
|
+
.pipe(map((response) => {
|
|
166
186
|
if (response.response) {
|
|
167
187
|
this.featuredProductCache.saveOne({
|
|
168
188
|
storeId: id,
|
|
169
189
|
data: response.response,
|
|
170
|
-
timestamp: Date.now()
|
|
190
|
+
timestamp: Date.now(),
|
|
171
191
|
});
|
|
172
192
|
}
|
|
173
193
|
return response;
|
|
174
|
-
}), catchError(error => {
|
|
194
|
+
}), catchError((error) => {
|
|
175
195
|
if (cachedData) {
|
|
176
196
|
return of(NetworkingUIEventWrapped.succeeded(cachedData.data));
|
|
177
197
|
}
|
|
@@ -186,7 +206,7 @@ export class StoreService {
|
|
|
186
206
|
this.storeListCache.clearAll(),
|
|
187
207
|
this.productCollectionCache.clearAll(),
|
|
188
208
|
this.productCategoryCache.clearAll(),
|
|
189
|
-
this.featuredProductCache.clearAll()
|
|
209
|
+
this.featuredProductCache.clearAll(),
|
|
190
210
|
]).then(() => { });
|
|
191
211
|
}
|
|
192
212
|
clearStoreCache(id) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "fake-indexeddb/auto";
|