@smess/networking 1.0.29 → 1.0.30

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.
Files changed (131) hide show
  1. package/dist/index.d.ts +6 -0
  2. package/dist/index.js +6 -0
  3. package/dist/services/storefront.cart.service.d.ts +73 -0
  4. package/dist/services/storefront.cart.service.js +167 -0
  5. package/dist/services/storefront.cart.service.test.d.ts +1 -0
  6. package/dist/services/storefront.cart.service.test.js +211 -0
  7. package/dist/services/storefront.checkout.service.d.ts +62 -0
  8. package/dist/services/storefront.checkout.service.js +75 -0
  9. package/dist/services/storefront.checkout.service.test.d.ts +1 -0
  10. package/dist/services/storefront.checkout.service.test.js +158 -0
  11. package/dist/services/storefront.customer.metadata.service.d.ts +91 -0
  12. package/dist/services/storefront.customer.metadata.service.js +225 -0
  13. package/dist/services/storefront.customer.metadata.service.test.d.ts +1 -0
  14. package/dist/services/storefront.customer.metadata.service.test.js +271 -0
  15. package/dist/services/storefront.order.service.d.ts +45 -0
  16. package/dist/services/storefront.order.service.js +99 -0
  17. package/dist/services/storefront.order.service.test.d.ts +1 -0
  18. package/dist/services/storefront.order.service.test.js +158 -0
  19. package/dist/services/storefront.product.service.d.ts +52 -0
  20. package/dist/services/storefront.product.service.js +75 -0
  21. package/dist/services/storefront.product.service.test.d.ts +1 -0
  22. package/dist/services/storefront.product.service.test.js +120 -0
  23. package/dist/services/storefront.store.service.d.ts +52 -0
  24. package/dist/services/storefront.store.service.js +140 -0
  25. package/dist/services/storefront.store.service.test.d.ts +1 -0
  26. package/dist/services/storefront.store.service.test.js +90 -0
  27. package/dist/src/core/axios.d.ts +51 -0
  28. package/dist/src/core/axios.js +65 -0
  29. package/dist/src/core/axios.observable.d.ts +11 -0
  30. package/dist/src/core/axios.observable.js +58 -0
  31. package/dist/src/core/base.provider.advanced.test.d.ts +1 -0
  32. package/dist/src/core/base.provider.advanced.test.js +29 -0
  33. package/dist/src/core/base.provider.d.ts +15 -0
  34. package/dist/src/core/base.provider.js +13 -0
  35. package/dist/src/core/base.provider.test.d.ts +1 -0
  36. package/dist/src/core/base.provider.test.js +36 -0
  37. package/dist/src/core/base.service.wrapper.advanced.test.d.ts +1 -0
  38. package/dist/src/core/base.service.wrapper.advanced.test.js +39 -0
  39. package/dist/src/core/base.service.wrapper.d.ts +7 -0
  40. package/dist/src/core/base.service.wrapper.js +11 -0
  41. package/dist/src/core/base.service.wrapper.test.d.ts +1 -0
  42. package/dist/src/core/base.service.wrapper.test.js +25 -0
  43. package/dist/src/core/rx.http.service.d.ts +51 -0
  44. package/dist/src/core/rx.http.service.js +65 -0
  45. package/dist/src/index.d.ts +25 -0
  46. package/dist/src/index.js +29 -0
  47. package/dist/src/services/auth.service.d.ts +65 -0
  48. package/dist/src/services/auth.service.js +197 -0
  49. package/dist/src/services/auth.service.test.d.ts +1 -0
  50. package/dist/src/services/auth.service.test.js +334 -0
  51. package/dist/src/services/cache.service.d.ts +31 -0
  52. package/dist/src/services/cache.service.js +77 -0
  53. package/dist/src/services/cache.service.test.d.ts +1 -0
  54. package/dist/src/services/cache.service.test.js +88 -0
  55. package/dist/src/services/customer.service.d.ts +199 -0
  56. package/dist/src/services/customer.service.js +114 -0
  57. package/dist/src/services/customer.service.test.d.ts +1 -0
  58. package/dist/src/services/customer.service.test.js +430 -0
  59. package/dist/src/services/employee.service.d.ts +73 -0
  60. package/dist/src/services/employee.service.js +74 -0
  61. package/dist/src/services/employee.service.test.d.ts +1 -0
  62. package/dist/src/services/employee.service.test.js +127 -0
  63. package/dist/src/services/logger.service.d.ts +31 -0
  64. package/dist/src/services/logger.service.js +93 -0
  65. package/dist/src/services/logger.service.test.d.ts +1 -0
  66. package/dist/src/services/logger.service.test.js +31 -0
  67. package/dist/src/services/order.service.d.ts +73 -0
  68. package/dist/src/services/order.service.js +97 -0
  69. package/dist/src/services/order.service.test.d.ts +1 -0
  70. package/dist/src/services/order.service.test.js +163 -0
  71. package/dist/src/services/product.service.d.ts +21 -0
  72. package/dist/src/services/product.service.js +42 -0
  73. package/dist/src/services/product.service.test.d.ts +1 -0
  74. package/dist/src/services/product.service.test.js +61 -0
  75. package/dist/src/services/smess.service.d.ts +36 -0
  76. package/dist/src/services/smess.service.js +128 -0
  77. package/dist/src/services/smess.service.test.d.ts +1 -0
  78. package/dist/src/services/smess.service.test.js +103 -0
  79. package/dist/src/services/store.cart.service.d.ts +158 -0
  80. package/dist/src/services/store.cart.service.js +177 -0
  81. package/dist/src/services/store.cart.service.test.d.ts +1 -0
  82. package/dist/src/services/store.cart.service.test.js +394 -0
  83. package/dist/src/services/store.product.service.d.ts +124 -0
  84. package/dist/src/services/store.product.service.js +102 -0
  85. package/dist/src/services/store.product.service.test.d.ts +1 -0
  86. package/dist/src/services/store.product.service.test.js +319 -0
  87. package/dist/src/services/store.service.d.ts +79 -0
  88. package/dist/src/services/store.service.js +235 -0
  89. package/dist/src/services/store.service.test.d.ts +1 -0
  90. package/dist/src/services/store.service.test.js +274 -0
  91. package/dist/src/services/storefront.cart.service.d.ts +73 -0
  92. package/dist/src/services/storefront.cart.service.js +167 -0
  93. package/dist/src/services/storefront.cart.service.test.d.ts +1 -0
  94. package/dist/src/services/storefront.cart.service.test.js +211 -0
  95. package/dist/src/services/storefront.checkout.service.d.ts +62 -0
  96. package/dist/src/services/storefront.checkout.service.js +75 -0
  97. package/dist/src/services/storefront.checkout.service.test.d.ts +1 -0
  98. package/dist/src/services/storefront.checkout.service.test.js +158 -0
  99. package/dist/src/services/storefront.customer.metadata.service.d.ts +91 -0
  100. package/dist/src/services/storefront.customer.metadata.service.js +225 -0
  101. package/dist/src/services/storefront.customer.metadata.service.test.d.ts +1 -0
  102. package/dist/src/services/storefront.customer.metadata.service.test.js +271 -0
  103. package/dist/src/services/storefront.order.service.d.ts +45 -0
  104. package/dist/src/services/storefront.order.service.js +99 -0
  105. package/dist/src/services/storefront.order.service.test.d.ts +1 -0
  106. package/dist/src/services/storefront.order.service.test.js +158 -0
  107. package/dist/src/services/storefront.product.service.d.ts +52 -0
  108. package/dist/src/services/storefront.product.service.js +75 -0
  109. package/dist/src/services/storefront.product.service.test.d.ts +1 -0
  110. package/dist/src/services/storefront.product.service.test.js +120 -0
  111. package/dist/src/services/storefront.store.service.d.ts +52 -0
  112. package/dist/src/services/storefront.store.service.js +140 -0
  113. package/dist/src/services/storefront.store.service.test.d.ts +1 -0
  114. package/dist/src/services/storefront.store.service.test.js +90 -0
  115. package/dist/src/services/user.service.d.ts +16 -0
  116. package/dist/src/services/user.service.js +37 -0
  117. package/dist/src/services/user.service.test.d.ts +1 -0
  118. package/dist/src/services/user.service.test.js +52 -0
  119. package/dist/src/services/utils/withAuthReset.d.ts +3 -0
  120. package/dist/src/services/utils/withAuthReset.js +8 -0
  121. package/dist/src/types/types.d.ts +93 -0
  122. package/dist/src/types/types.js +82 -0
  123. package/dist/src/types/types.test.d.ts +1 -0
  124. package/dist/src/types/types.test.js +25 -0
  125. package/dist/src/utils/cache-import.d.ts +3 -0
  126. package/dist/src/utils/cache-import.js +2 -0
  127. package/dist/src/utils/networking-import.d.ts +4 -0
  128. package/dist/src/utils/networking-import.js +3 -0
  129. package/dist/src/utils/rxjs-import.d.ts +5 -0
  130. package/dist/src/utils/rxjs-import.js +5 -0
  131. package/package.json +1 -1
@@ -0,0 +1,75 @@
1
+ import { Accept, SMESSHeader, SmessService } from "./smess.service";
2
+ export class StorefrontProductProvider {
3
+ constructor(config, target) {
4
+ this.config = config;
5
+ this.target = target;
6
+ }
7
+ get baseURL() {
8
+ return this.config.version
9
+ ? `${this.config.baseUrl}/${this.config.version}`
10
+ : this.config.baseUrl;
11
+ }
12
+ get path() {
13
+ switch (this.target) {
14
+ case "product-list":
15
+ return "/storefront/products";
16
+ case "product-collection":
17
+ return "/storefront/products/collection";
18
+ case "product-detail":
19
+ return "/storefront/products/${id}";
20
+ default:
21
+ return "/storefront/products";
22
+ }
23
+ }
24
+ get method() {
25
+ return "GET";
26
+ }
27
+ get headers() {
28
+ let headers = SmessService.getHeaders(Accept.V1, null);
29
+ if (this.config.clientId) {
30
+ headers[SMESSHeader.ClientId] = this.config.clientId;
31
+ }
32
+ if (this.config.apiKey) {
33
+ headers[SMESSHeader.ApiKey] = this.config.apiKey;
34
+ }
35
+ return SmessService.filterHeaders(headers);
36
+ }
37
+ getPath(...queryParams) {
38
+ let definedPath = this.path;
39
+ const params = definedPath.match(/\$\{(.+?)\}/g);
40
+ params?.forEach((value, index) => {
41
+ definedPath = definedPath.replace(value, String(queryParams[index]));
42
+ });
43
+ return definedPath;
44
+ }
45
+ }
46
+ export class StorefrontProductService {
47
+ constructor(config) {
48
+ this.config = config;
49
+ }
50
+ provider(target) {
51
+ const targetWrapper = new StorefrontProductProvider(this.config, target);
52
+ return new SmessService(targetWrapper);
53
+ }
54
+ /**
55
+ * List products with pagination and filtering
56
+ * GET /storefront/products
57
+ */
58
+ listProducts(params) {
59
+ return this.provider("product-list").request(params);
60
+ }
61
+ /**
62
+ * Get product collection with per_page pagination style
63
+ * GET /storefront/products/collection
64
+ */
65
+ getProductCollection(params) {
66
+ return this.provider("product-collection").request(params);
67
+ }
68
+ /**
69
+ * Get product details by ID
70
+ * GET /storefront/products/{id}
71
+ */
72
+ getProductDetail(id) {
73
+ return this.provider("product-detail").request(null, undefined, id);
74
+ }
75
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,120 @@
1
+ import { StorefrontProductService, StorefrontProductProvider, } from "./storefront.product.service";
2
+ import { NetworkingUIEventWrapped, AlertModel, } from "../types/types";
3
+ import { of } from "rxjs";
4
+ describe("StorefrontProductService", () => {
5
+ const config = {
6
+ baseUrl: "https://api.example.com",
7
+ version: "api/v1",
8
+ isProd: false,
9
+ clientId: "test-client-id",
10
+ apiKey: "test-api-key",
11
+ };
12
+ let service;
13
+ beforeEach(() => {
14
+ service = new StorefrontProductService(config);
15
+ });
16
+ describe("StorefrontProductProvider", () => {
17
+ it("should generate correct path for product-list", () => {
18
+ const provider = new StorefrontProductProvider(config, "product-list");
19
+ expect(provider.path).toBe("/storefront/products");
20
+ expect(provider.method).toBe("GET");
21
+ });
22
+ it("should generate correct path for product-collection", () => {
23
+ const provider = new StorefrontProductProvider(config, "product-collection");
24
+ expect(provider.path).toBe("/storefront/products/collection");
25
+ expect(provider.method).toBe("GET");
26
+ });
27
+ it("should generate correct path for product-detail", () => {
28
+ const provider = new StorefrontProductProvider(config, "product-detail");
29
+ expect(provider.path).toBe("/storefront/products/${id}");
30
+ expect(provider.method).toBe("GET");
31
+ expect(provider.getPath(123)).toBe("/storefront/products/123");
32
+ });
33
+ it("should include correct headers", () => {
34
+ const provider = new StorefrontProductProvider(config, "product-list");
35
+ const headers = provider.headers;
36
+ expect(headers["X-Client-Id"]).toBe("test-client-id");
37
+ expect(headers["X-Api-Key"]).toBe("test-api-key");
38
+ expect(headers["Accept"]).toBe("application/json");
39
+ });
40
+ it("should generate correct baseURL with version", () => {
41
+ const provider = new StorefrontProductProvider(config, "product-list");
42
+ expect(provider.baseURL).toBe("https://api.example.com/api/v1");
43
+ });
44
+ });
45
+ describe("listProducts", () => {
46
+ it("should list products successfully", async () => {
47
+ const params = {
48
+ page: 1,
49
+ limit: 20,
50
+ store_id: 1,
51
+ category: "Electronics",
52
+ };
53
+ const response = {
54
+ data: { products: [], total: 0 },
55
+ };
56
+ jest.spyOn(service, "provider").mockReturnValue({
57
+ request: () => of(NetworkingUIEventWrapped.succeeded(response)),
58
+ });
59
+ const result = await service.listProducts(params).toPromise();
60
+ expect(result?.hasSuccess).toBe(true);
61
+ expect(result?.response).toEqual(response);
62
+ });
63
+ it("should handle list products error", async () => {
64
+ jest.spyOn(service, "provider").mockReturnValue({
65
+ request: () => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
66
+ });
67
+ const result = await service.listProducts().toPromise();
68
+ expect(result?.hasFailed).toBe(true);
69
+ expect(result?.alertModel).toBeInstanceOf(AlertModel);
70
+ });
71
+ });
72
+ describe("getProductCollection", () => {
73
+ it("should get product collection successfully", async () => {
74
+ const params = {
75
+ page: 1,
76
+ per_page: 20,
77
+ only_promoted: true,
78
+ only_discounted: false,
79
+ };
80
+ const response = {
81
+ data: { products: [], total: 0 },
82
+ };
83
+ jest.spyOn(service, "provider").mockReturnValue({
84
+ request: () => of(NetworkingUIEventWrapped.succeeded(response)),
85
+ });
86
+ const result = await service.getProductCollection(params).toPromise();
87
+ expect(result?.hasSuccess).toBe(true);
88
+ expect(result?.response).toEqual(response);
89
+ });
90
+ it("should handle get product collection error", async () => {
91
+ jest.spyOn(service, "provider").mockReturnValue({
92
+ request: () => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
93
+ });
94
+ const result = await service.getProductCollection().toPromise();
95
+ expect(result?.hasFailed).toBe(true);
96
+ expect(result?.alertModel).toBeInstanceOf(AlertModel);
97
+ });
98
+ });
99
+ describe("getProductDetail", () => {
100
+ it("should get product detail successfully", async () => {
101
+ const response = {
102
+ data: { id: 123, name: "Test Product" },
103
+ };
104
+ jest.spyOn(service, "provider").mockReturnValue({
105
+ request: (_payload, _mockResponse, id) => of(NetworkingUIEventWrapped.succeeded(response)),
106
+ });
107
+ const result = await service.getProductDetail(123).toPromise();
108
+ expect(result?.hasSuccess).toBe(true);
109
+ expect(result?.response).toEqual(response);
110
+ });
111
+ it("should handle get product detail error", async () => {
112
+ jest.spyOn(service, "provider").mockReturnValue({
113
+ request: (_payload, _mockResponse, id) => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
114
+ });
115
+ const result = await service.getProductDetail(123).toPromise();
116
+ expect(result?.hasFailed).toBe(true);
117
+ expect(result?.alertModel).toBeInstanceOf(AlertModel);
118
+ });
119
+ });
120
+ });
@@ -0,0 +1,52 @@
1
+ import { ProviderType, NetworkingConfig, NetworkingUIEventWrapped, HttpResponse } from "../types/types";
2
+ import { SmessService } from "./smess.service";
3
+ import { Observable } from "rxjs";
4
+ export type StorefrontStoreTarget = "store-list" | "store-information";
5
+ export interface StorefrontStoreData {
6
+ id: number;
7
+ data: HttpResponse;
8
+ timestamp: number;
9
+ }
10
+ export interface StorefrontStoreListData {
11
+ data: HttpResponse;
12
+ timestamp: number;
13
+ }
14
+ export declare class StorefrontStoreProvider implements ProviderType {
15
+ private readonly config;
16
+ private readonly target;
17
+ constructor(config: NetworkingConfig, target: StorefrontStoreTarget);
18
+ get baseURL(): string;
19
+ get path(): string;
20
+ get method(): string;
21
+ get headers(): Record<string, string>;
22
+ getPath(...queryParams: unknown[]): string;
23
+ }
24
+ export declare class StorefrontStoreService {
25
+ private readonly config;
26
+ private readonly cacheService;
27
+ private readonly storeListCache;
28
+ constructor(config: NetworkingConfig);
29
+ provider(target: StorefrontStoreTarget): SmessService<StorefrontStoreProvider>;
30
+ /**
31
+ * List all accessible stores with shipping rules
32
+ * GET /storefront/stores/list
33
+ */
34
+ listStores(): Observable<NetworkingUIEventWrapped<HttpResponse>>;
35
+ /**
36
+ * Get detailed store information by ID including shipping rules
37
+ * GET /storefront/stores/{id}/information
38
+ */
39
+ getStoreInformation(id: number): Observable<NetworkingUIEventWrapped<HttpResponse>>;
40
+ /**
41
+ * Clear all cache
42
+ */
43
+ clearCache(): Promise<void>;
44
+ /**
45
+ * Clear cache for a specific store
46
+ */
47
+ clearStoreCache(id: number): Promise<void>;
48
+ /**
49
+ * Check if cache is still valid (24 hours)
50
+ */
51
+ private isCacheValid;
52
+ }
@@ -0,0 +1,140 @@
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
+ export class StorefrontStoreProvider {
7
+ constructor(config, target) {
8
+ this.config = config;
9
+ this.target = target;
10
+ }
11
+ get baseURL() {
12
+ return this.config.version
13
+ ? `${this.config.baseUrl}/${this.config.version}`
14
+ : this.config.baseUrl;
15
+ }
16
+ get path() {
17
+ switch (this.target) {
18
+ case "store-list":
19
+ return "/storefront/stores/list";
20
+ case "store-information":
21
+ return "/storefront/stores/${id}/information";
22
+ default:
23
+ return "/storefront/stores/list";
24
+ }
25
+ }
26
+ get method() {
27
+ return "GET";
28
+ }
29
+ get headers() {
30
+ let headers = SmessService.getHeaders(Accept.V1, null);
31
+ if (this.config.clientId) {
32
+ headers[SMESSHeader.ClientId] = this.config.clientId;
33
+ }
34
+ if (this.config.apiKey) {
35
+ headers[SMESSHeader.ApiKey] = this.config.apiKey;
36
+ }
37
+ return SmessService.filterHeaders(headers);
38
+ }
39
+ getPath(...queryParams) {
40
+ let definedPath = this.path;
41
+ const params = definedPath.match(/\$\{(.+?)\}/g);
42
+ params?.forEach((value, index) => {
43
+ definedPath = definedPath.replace(value, String(queryParams[index]));
44
+ });
45
+ return definedPath;
46
+ }
47
+ }
48
+ export class StorefrontStoreService {
49
+ constructor(config) {
50
+ this.config = config;
51
+ // Initialize cache services for different data types
52
+ this.cacheService = new GenericIndexedDBService("StorefrontStoreCache", "id, timestamp", (data) => data, (data) => data);
53
+ this.storeListCache = new GenericIndexedDBService("StorefrontStoreListCache", "timestamp", (data) => data, (data) => data);
54
+ }
55
+ provider(target) {
56
+ const targetWrapper = new StorefrontStoreProvider(this.config, target);
57
+ return new SmessService(targetWrapper);
58
+ }
59
+ /**
60
+ * List all accessible stores with shipping rules
61
+ * GET /storefront/stores/list
62
+ */
63
+ listStores() {
64
+ return from(this.storeListCache.getAll("storefront-store-list")).pipe(switchMap((cachedData) => {
65
+ if (cachedData &&
66
+ cachedData.length > 0 &&
67
+ this.isCacheValid(cachedData[0].timestamp)) {
68
+ return of(NetworkingUIEventWrapped.succeeded(cachedData[0].data));
69
+ }
70
+ return this.provider("store-list")
71
+ .request()
72
+ .pipe(map((response) => {
73
+ if (response.response) {
74
+ this.storeListCache.saveAll([
75
+ {
76
+ data: response.response,
77
+ timestamp: Date.now(),
78
+ },
79
+ ], "storefront-store-list");
80
+ }
81
+ return response;
82
+ }), catchError((error) => {
83
+ if (cachedData && cachedData.length > 0) {
84
+ return of(NetworkingUIEventWrapped.succeeded(cachedData[0].data));
85
+ }
86
+ throw error;
87
+ }));
88
+ }));
89
+ }
90
+ /**
91
+ * Get detailed store information by ID including shipping rules
92
+ * GET /storefront/stores/{id}/information
93
+ */
94
+ getStoreInformation(id) {
95
+ return from(this.cacheService.getOne(String(id))).pipe(switchMap((cachedData) => {
96
+ if (cachedData && this.isCacheValid(cachedData.timestamp)) {
97
+ return of(NetworkingUIEventWrapped.succeeded(cachedData.data));
98
+ }
99
+ return this.provider("store-information")
100
+ .request(null, undefined, id)
101
+ .pipe(map((response) => {
102
+ if (response.response) {
103
+ this.cacheService.saveOne({
104
+ id,
105
+ data: response.response,
106
+ timestamp: Date.now(),
107
+ });
108
+ }
109
+ return response;
110
+ }), catchError((error) => {
111
+ if (cachedData) {
112
+ return of(NetworkingUIEventWrapped.succeeded(cachedData.data));
113
+ }
114
+ throw error;
115
+ }));
116
+ }));
117
+ }
118
+ /**
119
+ * Clear all cache
120
+ */
121
+ clearCache() {
122
+ return Promise.all([
123
+ this.cacheService.clearAll(),
124
+ this.storeListCache.clearAll(),
125
+ ]).then(() => { });
126
+ }
127
+ /**
128
+ * Clear cache for a specific store
129
+ */
130
+ clearStoreCache(id) {
131
+ return this.cacheService.delete(String(id));
132
+ }
133
+ /**
134
+ * Check if cache is still valid (24 hours)
135
+ */
136
+ isCacheValid(timestamp) {
137
+ const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours
138
+ return Date.now() - timestamp < CACHE_DURATION;
139
+ }
140
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,90 @@
1
+ import { StorefrontStoreService, StorefrontStoreProvider, } from "./storefront.store.service";
2
+ import { NetworkingUIEventWrapped, AlertModel, } from "../types/types";
3
+ import { of } from "rxjs";
4
+ describe("StorefrontStoreService", () => {
5
+ const config = {
6
+ baseUrl: "https://api.example.com",
7
+ version: "api/v1",
8
+ isProd: false,
9
+ clientId: "test-client-id",
10
+ apiKey: "test-api-key",
11
+ };
12
+ let service;
13
+ beforeEach(() => {
14
+ service = new StorefrontStoreService(config);
15
+ });
16
+ describe("StorefrontStoreProvider", () => {
17
+ it("should generate correct path for store-list", () => {
18
+ const provider = new StorefrontStoreProvider(config, "store-list");
19
+ expect(provider.path).toBe("/storefront/stores/list");
20
+ expect(provider.method).toBe("GET");
21
+ });
22
+ it("should generate correct path for store-information", () => {
23
+ const provider = new StorefrontStoreProvider(config, "store-information");
24
+ expect(provider.path).toBe("/storefront/stores/${id}/information");
25
+ expect(provider.method).toBe("GET");
26
+ expect(provider.getPath(1)).toBe("/storefront/stores/1/information");
27
+ });
28
+ it("should include correct headers", () => {
29
+ const provider = new StorefrontStoreProvider(config, "store-list");
30
+ const headers = provider.headers;
31
+ expect(headers["X-Client-Id"]).toBe("test-client-id");
32
+ expect(headers["X-Api-Key"]).toBe("test-api-key");
33
+ expect(headers["Accept"]).toBe("application/json");
34
+ });
35
+ it("should generate correct baseURL with version", () => {
36
+ const provider = new StorefrontStoreProvider(config, "store-list");
37
+ expect(provider.baseURL).toBe("https://api.example.com/api/v1");
38
+ });
39
+ });
40
+ describe("listStores", () => {
41
+ it("should list stores successfully", async () => {
42
+ const response = {
43
+ data: { stores: [], total: 0 },
44
+ };
45
+ jest.spyOn(service, "provider").mockReturnValue({
46
+ request: () => of(NetworkingUIEventWrapped.succeeded(response)),
47
+ });
48
+ const result = await service.listStores().toPromise();
49
+ expect(result?.hasSuccess).toBe(true);
50
+ expect(result?.response).toEqual(response);
51
+ });
52
+ it("should handle list stores error", async () => {
53
+ jest.spyOn(service, "provider").mockReturnValue({
54
+ request: () => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
55
+ });
56
+ const result = await service.listStores().toPromise();
57
+ expect(result?.hasFailed).toBe(true);
58
+ expect(result?.alertModel).toBeInstanceOf(AlertModel);
59
+ });
60
+ });
61
+ describe("getStoreInformation", () => {
62
+ it("should get store information successfully", async () => {
63
+ const response = {
64
+ data: { id: 1, name: "Test Store" },
65
+ };
66
+ jest.spyOn(service, "provider").mockReturnValue({
67
+ request: (_payload, _mockResponse, id) => of(NetworkingUIEventWrapped.succeeded(response)),
68
+ });
69
+ const result = await service.getStoreInformation(1).toPromise();
70
+ expect(result?.hasSuccess).toBe(true);
71
+ expect(result?.response).toEqual(response);
72
+ });
73
+ it("should handle get store information error", async () => {
74
+ jest.spyOn(service, "provider").mockReturnValue({
75
+ request: (_payload, _mockResponse, id) => of(NetworkingUIEventWrapped.failed(AlertModel.default())),
76
+ });
77
+ const result = await service.getStoreInformation(1).toPromise();
78
+ expect(result?.hasFailed).toBe(true);
79
+ expect(result?.alertModel).toBeInstanceOf(AlertModel);
80
+ });
81
+ });
82
+ describe("cache management", () => {
83
+ it("should clear all cache", async () => {
84
+ await expect(service.clearCache()).resolves.toBeUndefined();
85
+ });
86
+ it("should clear specific store cache", async () => {
87
+ await expect(service.clearStoreCache(1)).resolves.toBeUndefined();
88
+ });
89
+ });
90
+ });
@@ -0,0 +1,51 @@
1
+ import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "../utils/networking-import";
2
+ import type { AxiosInterceptorManager } from "axios";
3
+ import { AxiosObservable } from "./axios.observable";
4
+ export interface Axiosable {
5
+ request<T = unknown>(config: AxiosRequestConfig): AxiosObservable<T>;
6
+ get<T = unknown>(url: string, config?: AxiosRequestConfig): AxiosObservable<T>;
7
+ head<T = unknown>(url: string, config?: AxiosRequestConfig): AxiosObservable<T>;
8
+ post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): AxiosObservable<T>;
9
+ put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): AxiosObservable<T>;
10
+ patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): AxiosObservable<T>;
11
+ delete<T = unknown>(url: string, config?: AxiosRequestConfig): AxiosObservable<T>;
12
+ }
13
+ declare class Axios implements Axiosable {
14
+ private axiosInstance;
15
+ static defaults: Omit<import("axios").AxiosDefaults<any>, "headers"> & {
16
+ headers: import("axios").HeadersDefaults & {
17
+ [key: string]: import("axios").AxiosHeaderValue;
18
+ };
19
+ };
20
+ static interceptors: {
21
+ request: AxiosInterceptorManager<import("axios").InternalAxiosRequestConfig>;
22
+ response: AxiosInterceptorManager<AxiosResponse>;
23
+ };
24
+ constructor(axiosInstance: AxiosInstance);
25
+ get defaults(): Omit<import("axios").AxiosDefaults<any>, "headers"> & {
26
+ headers: import("axios").HeadersDefaults & {
27
+ [key: string]: import("axios").AxiosHeaderValue;
28
+ };
29
+ };
30
+ get interceptors(): {
31
+ request: AxiosInterceptorManager<import("axios").InternalAxiosRequestConfig>;
32
+ response: AxiosInterceptorManager<AxiosResponse>;
33
+ };
34
+ static request<T = any>(config: AxiosRequestConfig): AxiosObservable<T>;
35
+ static get<T = any>(url: string, config?: AxiosRequestConfig): AxiosObservable<T>;
36
+ static post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosObservable<T>;
37
+ static put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosObservable<T>;
38
+ static patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosObservable<T>;
39
+ static delete<T = any>(url: string, config?: AxiosRequestConfig): AxiosObservable<T>;
40
+ static head<T = any>(url: string, config?: AxiosRequestConfig): AxiosObservable<T>;
41
+ static create(config: AxiosRequestConfig): Axios;
42
+ request<T = any>(config: AxiosRequestConfig): AxiosObservable<T>;
43
+ get<T = any>(url: string, config?: AxiosRequestConfig): AxiosObservable<T>;
44
+ head<T = any>(url: string, config?: AxiosRequestConfig): AxiosObservable<T>;
45
+ post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosObservable<T>;
46
+ put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosObservable<T>;
47
+ patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosObservable<T>;
48
+ delete<T = any>(url: string, config?: AxiosRequestConfig): AxiosObservable<T>;
49
+ }
50
+ export default Axios;
51
+ export { Axios };
@@ -0,0 +1,65 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any -- Required for axios compatibility */
2
+ import { axios, } from "../utils/networking-import";
3
+ import { createObservable } from "./axios.observable";
4
+ class Axios {
5
+ constructor(axiosInstance) {
6
+ this.axiosInstance = axiosInstance;
7
+ }
8
+ get defaults() {
9
+ return this.axiosInstance.defaults;
10
+ }
11
+ get interceptors() {
12
+ return this.axiosInstance.interceptors;
13
+ }
14
+ // ----- Static Methods -----
15
+ static request(config) {
16
+ return createObservable(axios.request, [config]);
17
+ }
18
+ static get(url, config) {
19
+ return createObservable(axios.get, [url, config]);
20
+ }
21
+ static post(url, data, config) {
22
+ return createObservable(axios.post, [url, data, config]);
23
+ }
24
+ static put(url, data, config) {
25
+ return createObservable(axios.put, [url, data, config]);
26
+ }
27
+ static patch(url, data, config) {
28
+ return createObservable(axios.patch, [url, data, config]);
29
+ }
30
+ static delete(url, config) {
31
+ return createObservable(axios.delete, [url, config]);
32
+ }
33
+ static head(url, config) {
34
+ return createObservable(axios.head, [url, config]);
35
+ }
36
+ static create(config) {
37
+ return new Axios(axios.create(config));
38
+ }
39
+ // ----- Instance Methods -----
40
+ request(config) {
41
+ return createObservable(this.axiosInstance.request, [config]);
42
+ }
43
+ get(url, config) {
44
+ return createObservable(this.axiosInstance.get, [url, config]);
45
+ }
46
+ head(url, config) {
47
+ return createObservable(this.axiosInstance.head, [url, config]);
48
+ }
49
+ post(url, data, config) {
50
+ return createObservable(this.axiosInstance.post, [url, data, config]);
51
+ }
52
+ put(url, data, config) {
53
+ return createObservable(this.axiosInstance.put, [url, data, config]);
54
+ }
55
+ patch(url, data, config) {
56
+ return createObservable(this.axiosInstance.patch, [url, data, config]);
57
+ }
58
+ delete(url, config) {
59
+ return createObservable(this.axiosInstance.delete, [url, config]);
60
+ }
61
+ }
62
+ Axios.defaults = axios.defaults;
63
+ Axios.interceptors = axios.interceptors;
64
+ export default Axios;
65
+ export { Axios };
@@ -0,0 +1,11 @@
1
+ import { AxiosResponse } from "../utils/networking-import";
2
+ import type { AxiosPromise } from "axios";
3
+ import { Observable } from "../utils/rxjs-import";
4
+ export type AxiosObservable<T> = Observable<AxiosResponse<T>>;
5
+ interface ObservableOptions {
6
+ retry?: number;
7
+ timeoutMs?: number;
8
+ cache?: boolean;
9
+ }
10
+ export declare function createObservable<T>(promiseFactory: (...args: any[]) => AxiosPromise<T>, args: any[], options?: ObservableOptions): AxiosObservable<T>;
11
+ export {};
@@ -0,0 +1,58 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any -- Required for axios compatibility */
2
+ import { axios, } from "../utils/networking-import";
3
+ import { Observable, timeout as rxTimeout, retry as rxRetry, shareReplay, catchError, throwError, } from "../utils/rxjs-import";
4
+ import { $logger } from "../services/logger.service";
5
+ export function createObservable(promiseFactory, args, options = {}) {
6
+ let config = args[args.length - 1];
7
+ if (config && typeof config === "object" && !Array.isArray(config)) {
8
+ config = { ...config };
9
+ }
10
+ else {
11
+ config = {};
12
+ args.push(config);
13
+ }
14
+ let cancelSource = null;
15
+ const hasCancelToken = !!config.cancelToken;
16
+ if (!hasCancelToken) {
17
+ $logger.warn("[Networking] You can omit cancelToken — unsubscribing cancels the request automatically.", undefined, "axios.observable");
18
+ }
19
+ let source$ = new Observable((subscriber) => {
20
+ if (!hasCancelToken) {
21
+ cancelSource = axios.CancelToken.source();
22
+ config.cancelToken = cancelSource.token;
23
+ }
24
+ promiseFactory(...args)
25
+ .then((response) => {
26
+ subscriber.next(response);
27
+ subscriber.complete();
28
+ })
29
+ .catch((error) => {
30
+ if (!subscriber.closed) {
31
+ subscriber.error(error);
32
+ }
33
+ });
34
+ return () => {
35
+ if (cancelSource) {
36
+ cancelSource.cancel("Request canceled via unsubscribe.");
37
+ }
38
+ };
39
+ });
40
+ // Add timeout if specified
41
+ if (options.timeoutMs) {
42
+ source$ = source$.pipe(rxTimeout(options.timeoutMs));
43
+ }
44
+ // Add retry logic
45
+ if (options.retry) {
46
+ source$ = source$.pipe(rxRetry(options.retry));
47
+ }
48
+ // Cache the response if needed
49
+ if (options.cache) {
50
+ source$ = source$.pipe(shareReplay({ bufferSize: 1, refCount: false }));
51
+ }
52
+ // Optional: Log or catch errors globally
53
+ source$ = source$.pipe(catchError((err) => {
54
+ $logger.error("[createObservable error]:", err, "axios.observable");
55
+ return throwError(() => err);
56
+ }));
57
+ return source$;
58
+ }
@@ -0,0 +1 @@
1
+ export {};