@athoscommerce/snap-client 1.0.0
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/LICENSE +21 -0
- package/README.md +261 -0
- package/dist/cjs/Client/Client.d.ts +29 -0
- package/dist/cjs/Client/Client.d.ts.map +1 -0
- package/dist/cjs/Client/Client.js +278 -0
- package/dist/cjs/Client/NetworkCache/NetworkCache.d.ts +12 -0
- package/dist/cjs/Client/NetworkCache/NetworkCache.d.ts.map +1 -0
- package/dist/cjs/Client/NetworkCache/NetworkCache.js +198 -0
- package/dist/cjs/Client/apis/Abstract.d.ts +60 -0
- package/dist/cjs/Client/apis/Abstract.d.ts.map +1 -0
- package/dist/cjs/Client/apis/Abstract.js +297 -0
- package/dist/cjs/Client/apis/Meta.d.ts +8 -0
- package/dist/cjs/Client/apis/Meta.d.ts.map +1 -0
- package/dist/cjs/Client/apis/Meta.js +102 -0
- package/dist/cjs/Client/apis/Recommend.d.ts +15 -0
- package/dist/cjs/Client/apis/Recommend.d.ts.map +1 -0
- package/dist/cjs/Client/apis/Recommend.js +276 -0
- package/dist/cjs/Client/apis/Search.d.ts +12 -0
- package/dist/cjs/Client/apis/Search.d.ts.map +1 -0
- package/dist/cjs/Client/apis/Search.js +137 -0
- package/dist/cjs/Client/apis/Suggest.d.ts +9 -0
- package/dist/cjs/Client/apis/Suggest.d.ts.map +1 -0
- package/dist/cjs/Client/apis/Suggest.js +145 -0
- package/dist/cjs/Client/apis/index.d.ts +6 -0
- package/dist/cjs/Client/apis/index.d.ts.map +1 -0
- package/dist/cjs/Client/apis/index.js +21 -0
- package/dist/cjs/Client/transforms/index.d.ts +5 -0
- package/dist/cjs/Client/transforms/index.d.ts.map +1 -0
- package/dist/cjs/Client/transforms/index.js +20 -0
- package/dist/cjs/Client/transforms/recommendationFiltersPost.d.ts +3 -0
- package/dist/cjs/Client/transforms/recommendationFiltersPost.d.ts.map +1 -0
- package/dist/cjs/Client/transforms/recommendationFiltersPost.js +63 -0
- package/dist/cjs/Client/transforms/searchRequest.d.ts +49 -0
- package/dist/cjs/Client/transforms/searchRequest.d.ts.map +1 -0
- package/dist/cjs/Client/transforms/searchRequest.js +169 -0
- package/dist/cjs/Client/transforms/searchResponse.d.ts +146 -0
- package/dist/cjs/Client/transforms/searchResponse.d.ts.map +1 -0
- package/dist/cjs/Client/transforms/searchResponse.js +296 -0
- package/dist/cjs/Client/transforms/suggestResponse.d.ts +18 -0
- package/dist/cjs/Client/transforms/suggestResponse.d.ts.map +1 -0
- package/dist/cjs/Client/transforms/suggestResponse.js +30 -0
- package/dist/cjs/Client/utils/fibonacci.d.ts +2 -0
- package/dist/cjs/Client/utils/fibonacci.d.ts.map +1 -0
- package/dist/cjs/Client/utils/fibonacci.js +14 -0
- package/dist/cjs/Client/utils/index.d.ts +2 -0
- package/dist/cjs/Client/utils/index.d.ts.map +1 -0
- package/dist/cjs/Client/utils/index.js +17 -0
- package/dist/cjs/Client/utils/mergeParams.d.ts +2 -0
- package/dist/cjs/Client/utils/mergeParams.d.ts.map +1 -0
- package/dist/cjs/Client/utils/mergeParams.js +27 -0
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +17 -0
- package/dist/cjs/types.d.ts +212 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +2 -0
- package/dist/esm/Client/Client.d.ts +29 -0
- package/dist/esm/Client/Client.d.ts.map +1 -0
- package/dist/esm/Client/Client.js +157 -0
- package/dist/esm/Client/NetworkCache/NetworkCache.d.ts +12 -0
- package/dist/esm/Client/NetworkCache/NetworkCache.d.ts.map +1 -0
- package/dist/esm/Client/NetworkCache/NetworkCache.js +168 -0
- package/dist/esm/Client/apis/Abstract.d.ts +60 -0
- package/dist/esm/Client/apis/Abstract.d.ts.map +1 -0
- package/dist/esm/Client/apis/Abstract.js +165 -0
- package/dist/esm/Client/apis/Meta.d.ts +8 -0
- package/dist/esm/Client/apis/Meta.d.ts.map +1 -0
- package/dist/esm/Client/apis/Meta.js +23 -0
- package/dist/esm/Client/apis/Recommend.d.ts +15 -0
- package/dist/esm/Client/apis/Recommend.d.ts.map +1 -0
- package/dist/esm/Client/apis/Recommend.js +172 -0
- package/dist/esm/Client/apis/Search.d.ts +12 -0
- package/dist/esm/Client/apis/Search.d.ts.map +1 -0
- package/dist/esm/Client/apis/Search.js +41 -0
- package/dist/esm/Client/apis/Suggest.d.ts +9 -0
- package/dist/esm/Client/apis/Suggest.d.ts.map +1 -0
- package/dist/esm/Client/apis/Suggest.js +45 -0
- package/dist/esm/Client/apis/index.d.ts +6 -0
- package/dist/esm/Client/apis/index.d.ts.map +1 -0
- package/dist/esm/Client/apis/index.js +5 -0
- package/dist/esm/Client/transforms/index.d.ts +5 -0
- package/dist/esm/Client/transforms/index.d.ts.map +1 -0
- package/dist/esm/Client/transforms/index.js +4 -0
- package/dist/esm/Client/transforms/recommendationFiltersPost.d.ts +3 -0
- package/dist/esm/Client/transforms/recommendationFiltersPost.d.ts.map +1 -0
- package/dist/esm/Client/transforms/recommendationFiltersPost.js +59 -0
- package/dist/esm/Client/transforms/searchRequest.d.ts +49 -0
- package/dist/esm/Client/transforms/searchRequest.d.ts.map +1 -0
- package/dist/esm/Client/transforms/searchRequest.js +152 -0
- package/dist/esm/Client/transforms/searchResponse.d.ts +146 -0
- package/dist/esm/Client/transforms/searchResponse.d.ts.map +1 -0
- package/dist/esm/Client/transforms/searchResponse.js +284 -0
- package/dist/esm/Client/transforms/suggestResponse.d.ts +18 -0
- package/dist/esm/Client/transforms/suggestResponse.d.ts.map +1 -0
- package/dist/esm/Client/transforms/suggestResponse.js +26 -0
- package/dist/esm/Client/utils/fibonacci.d.ts +2 -0
- package/dist/esm/Client/utils/fibonacci.d.ts.map +1 -0
- package/dist/esm/Client/utils/fibonacci.js +10 -0
- package/dist/esm/Client/utils/index.d.ts +2 -0
- package/dist/esm/Client/utils/index.d.ts.map +1 -0
- package/dist/esm/Client/utils/index.js +1 -0
- package/dist/esm/Client/utils/mergeParams.d.ts +2 -0
- package/dist/esm/Client/utils/mergeParams.d.ts.map +1 -0
- package/dist/esm/Client/utils/mergeParams.js +20 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/types.d.ts +212 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +1 -0
- package/package.json +31 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
14
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
15
|
+
if (ar || !(i in from)) {
|
|
16
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
17
|
+
ar[i] = from[i];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
21
|
+
};
|
|
22
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
23
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.NetworkCache = void 0;
|
|
27
|
+
var deepmerge_1 = __importDefault(require("deepmerge"));
|
|
28
|
+
var CACHE_STORAGE_KEY = 'athos-networkcache';
|
|
29
|
+
var defaultConfig = {
|
|
30
|
+
enabled: true,
|
|
31
|
+
ttl: 300000, // ms
|
|
32
|
+
maxSize: 1000, // KB
|
|
33
|
+
purgeable: true,
|
|
34
|
+
};
|
|
35
|
+
var NetworkCache = /** @class */ (function () {
|
|
36
|
+
function NetworkCache(config) {
|
|
37
|
+
var _this = this;
|
|
38
|
+
var _a;
|
|
39
|
+
this.memoryCache = {};
|
|
40
|
+
this.config = (0, deepmerge_1.default)(defaultConfig, config || {});
|
|
41
|
+
this.load();
|
|
42
|
+
// this allows you to pre-populate the cache from the config - primarily used for email recs
|
|
43
|
+
((_a = this.config) === null || _a === void 0 ? void 0 : _a.entries) &&
|
|
44
|
+
Object.keys(this.config.entries).map(function (key) {
|
|
45
|
+
if (_this.config.entries && _this.config.entries[key]) {
|
|
46
|
+
_this.set(key, _this.config.entries[key]);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
NetworkCache.prototype.load = function () {
|
|
51
|
+
// initialize cache from session storage
|
|
52
|
+
if (typeof window !== 'undefined' && (window === null || window === void 0 ? void 0 : window.sessionStorage)) {
|
|
53
|
+
var stored = window.sessionStorage.getItem(CACHE_STORAGE_KEY);
|
|
54
|
+
var newStored = __assign({}, (stored && JSON.parse(stored)));
|
|
55
|
+
this.memoryCache = newStored || {};
|
|
56
|
+
}
|
|
57
|
+
this.purgeExpired();
|
|
58
|
+
};
|
|
59
|
+
NetworkCache.prototype.get = function (key) {
|
|
60
|
+
var _a, _b, _c;
|
|
61
|
+
if (this.config.enabled) {
|
|
62
|
+
this.load();
|
|
63
|
+
try {
|
|
64
|
+
var ignoreKeys_1 = [];
|
|
65
|
+
if (typeof window !== 'undefined') {
|
|
66
|
+
var navigationType = (_c = (_b = (_a = window.performance) === null || _a === void 0 ? void 0 : _a.getEntriesByType('navigation')) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.type;
|
|
67
|
+
if (navigationType === 'back_forward') {
|
|
68
|
+
ignoreKeys_1 = ['lastViewed', 'cart'];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (Object.keys(this.memoryCache).length && key) {
|
|
72
|
+
var storageKey = key;
|
|
73
|
+
// this only applies to search calls
|
|
74
|
+
if (ignoreKeys_1.length && key.startsWith('/v1/search')) {
|
|
75
|
+
try {
|
|
76
|
+
var url_1 = key.split('{')[0];
|
|
77
|
+
var payload = '{' + key.split('{')[1];
|
|
78
|
+
var searchParams_1 = JSON.parse(payload);
|
|
79
|
+
var foundKey = Object.keys(this.memoryCache).find(function (cachedResponse) {
|
|
80
|
+
try {
|
|
81
|
+
var storedUrl = cachedResponse.split('{')[0];
|
|
82
|
+
if (storedUrl == url_1) {
|
|
83
|
+
var storedPayload = '{' + cachedResponse.split('{')[1];
|
|
84
|
+
var parsedPayload = JSON.parse(storedPayload);
|
|
85
|
+
var allKeys = Array.from(new Set(__spreadArray(__spreadArray([], Object.keys(searchParams_1), true), Object.keys(parsedPayload), true)));
|
|
86
|
+
for (var _i = 0, allKeys_1 = allKeys; _i < allKeys_1.length; _i++) {
|
|
87
|
+
var k = allKeys_1[_i];
|
|
88
|
+
if (ignoreKeys_1.includes(k))
|
|
89
|
+
continue;
|
|
90
|
+
if (JSON.stringify(searchParams_1[k]) !== JSON.stringify(parsedPayload[k])) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
else
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
catch (_a) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
if (foundKey) {
|
|
104
|
+
storageKey = foundKey;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
// key is not json
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (this.memoryCache[storageKey]) {
|
|
112
|
+
// compare the expiry time of the item with the current time
|
|
113
|
+
if (Date.now() >= this.memoryCache[storageKey].expires) {
|
|
114
|
+
// remove item
|
|
115
|
+
var newStored = __assign({}, this.memoryCache);
|
|
116
|
+
delete newStored[storageKey];
|
|
117
|
+
// update storage
|
|
118
|
+
window.sessionStorage.setItem(CACHE_STORAGE_KEY, JSON.stringify(newStored));
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
return this.memoryCache[storageKey].value;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
console.warn('something went wrong getting from cache', err);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
NetworkCache.prototype.purgeExpired = function () {
|
|
132
|
+
var _this = this;
|
|
133
|
+
Object.keys(this.memoryCache).forEach(function (cacheKey) {
|
|
134
|
+
//clean up expired cache keys in memory
|
|
135
|
+
if (Date.now() > _this.memoryCache[cacheKey].expires) {
|
|
136
|
+
delete _this.memoryCache[cacheKey];
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
// update storage
|
|
140
|
+
try {
|
|
141
|
+
if (typeof window !== 'undefined' && (window === null || window === void 0 ? void 0 : window.sessionStorage)) {
|
|
142
|
+
var stringifiedCache = JSON.stringify(this.memoryCache);
|
|
143
|
+
window.sessionStorage.setItem(CACHE_STORAGE_KEY, stringifiedCache);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch (_a) {
|
|
147
|
+
console.warn('failed to store network cache');
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
NetworkCache.prototype.set = function (key, value) {
|
|
151
|
+
var _this = this;
|
|
152
|
+
if (this.config.enabled) {
|
|
153
|
+
this.load();
|
|
154
|
+
try {
|
|
155
|
+
var cacheObject = {
|
|
156
|
+
value: value,
|
|
157
|
+
expires: Date.now() + this.config.ttl,
|
|
158
|
+
purgeable: this.config.purgeable,
|
|
159
|
+
};
|
|
160
|
+
// purge old items if we are over max size
|
|
161
|
+
var size = new Blob([JSON.stringify(this.memoryCache)], { endings: 'native' }).size / 1024;
|
|
162
|
+
while (size > this.config.maxSize) {
|
|
163
|
+
var oldestKey = Object.keys(this.memoryCache)
|
|
164
|
+
.filter(function (key) { return _this.memoryCache[key].purgeable; })
|
|
165
|
+
.sort(function (a, b) {
|
|
166
|
+
return _this.memoryCache[a].expires - _this.memoryCache[b].expires;
|
|
167
|
+
})[0];
|
|
168
|
+
if (!oldestKey)
|
|
169
|
+
break;
|
|
170
|
+
delete this.memoryCache[oldestKey];
|
|
171
|
+
// recalculate size after removing oldest
|
|
172
|
+
size = new Blob([JSON.stringify(this.memoryCache)], { endings: 'native' }).size / 1024;
|
|
173
|
+
}
|
|
174
|
+
// store cache in memory
|
|
175
|
+
this.memoryCache[key] = cacheObject;
|
|
176
|
+
if (typeof window !== 'undefined' && (window === null || window === void 0 ? void 0 : window.sessionStorage)) {
|
|
177
|
+
window.sessionStorage.setItem(CACHE_STORAGE_KEY, JSON.stringify(this.memoryCache));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch (_a) {
|
|
181
|
+
console.warn('something went wrong setting to cache');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
NetworkCache.prototype.clear = function () {
|
|
186
|
+
try {
|
|
187
|
+
this.memoryCache = {};
|
|
188
|
+
if (typeof window !== 'undefined' && (window === null || window === void 0 ? void 0 : window.sessionStorage)) {
|
|
189
|
+
window.sessionStorage.setItem(CACHE_STORAGE_KEY, '');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch (_a) {
|
|
193
|
+
console.warn('something went wrong clearing cache');
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
return NetworkCache;
|
|
197
|
+
}());
|
|
198
|
+
exports.NetworkCache = NetworkCache;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { AppMode } from '@athoscommerce/snap-toolbox';
|
|
2
|
+
import { NetworkCache } from '../NetworkCache/NetworkCache';
|
|
3
|
+
import { CacheConfig, HTTPHeaders, GenericGlobals } from '../../types';
|
|
4
|
+
export type Json = any;
|
|
5
|
+
export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
|
6
|
+
export type HTTPQuery = {
|
|
7
|
+
[key: string]: string | number | null | boolean | Array<string | number | null | boolean> | HTTPQuery;
|
|
8
|
+
};
|
|
9
|
+
export type HTTPBody = Json | FormData | URLSearchParams;
|
|
10
|
+
export interface RequestOpts {
|
|
11
|
+
path: string;
|
|
12
|
+
method: HTTPMethod;
|
|
13
|
+
headers: HTTPHeaders;
|
|
14
|
+
query?: HTTPQuery;
|
|
15
|
+
body?: HTTPBody;
|
|
16
|
+
origin?: string;
|
|
17
|
+
subDomain?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class API<PathConfigurationType> {
|
|
20
|
+
configuration: ApiConfiguration<PathConfigurationType>;
|
|
21
|
+
private retryDelay;
|
|
22
|
+
private retryCount;
|
|
23
|
+
cache: NetworkCache;
|
|
24
|
+
constructor(configuration: ApiConfiguration<PathConfigurationType>);
|
|
25
|
+
protected get mode(): AppMode;
|
|
26
|
+
protected request<T>(context: RequestOpts, cacheKey?: string): Promise<T>;
|
|
27
|
+
private createFetchParams;
|
|
28
|
+
private fetchApi;
|
|
29
|
+
}
|
|
30
|
+
export type FetchAPI = WindowOrWorkerGlobalScope['fetch'];
|
|
31
|
+
export interface ApiConfigurationParameters<PathConfigurationType = Record<string, string>> {
|
|
32
|
+
mode?: keyof typeof AppMode | AppMode;
|
|
33
|
+
initiator?: string;
|
|
34
|
+
origin?: string;
|
|
35
|
+
fetchApi?: FetchAPI;
|
|
36
|
+
queryParamsStringify?: (params: HTTPQuery) => string;
|
|
37
|
+
headers?: HTTPHeaders;
|
|
38
|
+
maxRetry?: number;
|
|
39
|
+
cache?: CacheConfig;
|
|
40
|
+
globals?: GenericGlobals;
|
|
41
|
+
paths?: PathConfigurationType;
|
|
42
|
+
}
|
|
43
|
+
export declare class ApiConfiguration<PathConfigurationType> {
|
|
44
|
+
private config;
|
|
45
|
+
constructor(config?: ApiConfigurationParameters<PathConfigurationType>);
|
|
46
|
+
get cache(): CacheConfig;
|
|
47
|
+
get maxRetry(): number;
|
|
48
|
+
get origin(): string;
|
|
49
|
+
get initiator(): string;
|
|
50
|
+
get fetchApi(): FetchAPI;
|
|
51
|
+
get queryParamsStringify(): (params: HTTPQuery) => string;
|
|
52
|
+
get headers(): HTTPHeaders;
|
|
53
|
+
set headers(newHeaders: HTTPHeaders);
|
|
54
|
+
get globals(): GenericGlobals;
|
|
55
|
+
set globals(newGlobals: GenericGlobals);
|
|
56
|
+
get mode(): AppMode;
|
|
57
|
+
get paths(): PathConfigurationType;
|
|
58
|
+
}
|
|
59
|
+
export declare function querystring(params: HTTPQuery, prefix?: string): string;
|
|
60
|
+
//# sourceMappingURL=Abstract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Abstract.d.ts","sourceRoot":"","sources":["../../../../src/Client/apis/Abstract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
24
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
50
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
51
|
+
};
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
exports.ApiConfiguration = exports.API = void 0;
|
|
54
|
+
exports.querystring = querystring;
|
|
55
|
+
var deepmerge_1 = __importDefault(require("deepmerge"));
|
|
56
|
+
var snap_toolbox_1 = require("@athoscommerce/snap-toolbox");
|
|
57
|
+
var fibonacci_1 = require("../utils/fibonacci");
|
|
58
|
+
var NetworkCache_1 = require("../NetworkCache/NetworkCache");
|
|
59
|
+
var isBlob = function (value) { return typeof Blob !== 'undefined' && value instanceof Blob; };
|
|
60
|
+
var API = /** @class */ (function () {
|
|
61
|
+
function API(configuration) {
|
|
62
|
+
this.configuration = configuration;
|
|
63
|
+
this.retryDelay = 1000;
|
|
64
|
+
this.retryCount = 0;
|
|
65
|
+
this.cache = new NetworkCache_1.NetworkCache(this.configuration.cache);
|
|
66
|
+
}
|
|
67
|
+
Object.defineProperty(API.prototype, "mode", {
|
|
68
|
+
get: function () {
|
|
69
|
+
return this.configuration.mode;
|
|
70
|
+
},
|
|
71
|
+
enumerable: false,
|
|
72
|
+
configurable: true
|
|
73
|
+
});
|
|
74
|
+
API.prototype.request = function (context, cacheKey) {
|
|
75
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
76
|
+
var _a, url, init, cachedResponse, response, responseJSON, err_1;
|
|
77
|
+
var _this = this;
|
|
78
|
+
var _b;
|
|
79
|
+
return __generator(this, function (_c) {
|
|
80
|
+
switch (_c.label) {
|
|
81
|
+
case 0:
|
|
82
|
+
_a = this.createFetchParams(context), url = _a.url, init = _a.init;
|
|
83
|
+
if (cacheKey) {
|
|
84
|
+
cachedResponse = this.cache.get("".concat(context.path, "/").concat(cacheKey)) || this.cache.get("".concat(context.path, "/*"));
|
|
85
|
+
if (cachedResponse) {
|
|
86
|
+
this.retryCount = 0; // reset count and delay incase rate limit occurs again before a page refresh
|
|
87
|
+
this.retryDelay = 1000;
|
|
88
|
+
return [2 /*return*/, cachedResponse];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
_c.label = 1;
|
|
92
|
+
case 1:
|
|
93
|
+
_c.trys.push([1, 10, , 13]);
|
|
94
|
+
return [4 /*yield*/, this.fetchApi(url, init)];
|
|
95
|
+
case 2:
|
|
96
|
+
response = _c.sent();
|
|
97
|
+
return [4 /*yield*/, (response === null || response === void 0 ? void 0 : response.json())];
|
|
98
|
+
case 3:
|
|
99
|
+
responseJSON = _c.sent();
|
|
100
|
+
if (!(response.status >= 200 && response.status < 300)) return [3 /*break*/, 4];
|
|
101
|
+
this.retryCount = 0; // reset count and delay incase rate limit occurs again before a page refresh
|
|
102
|
+
this.retryDelay = 1000;
|
|
103
|
+
if (cacheKey) {
|
|
104
|
+
// save in the cache before returning
|
|
105
|
+
this.cache.set("".concat(context.path, "/").concat(cacheKey), responseJSON);
|
|
106
|
+
}
|
|
107
|
+
return [2 /*return*/, responseJSON];
|
|
108
|
+
case 4:
|
|
109
|
+
if (!(response.status == 429)) return [3 /*break*/, 8];
|
|
110
|
+
if (!(this.retryCount < this.configuration.maxRetry)) return [3 /*break*/, 6];
|
|
111
|
+
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, _this.retryDelay); })];
|
|
112
|
+
case 5:
|
|
113
|
+
_c.sent(); // delay retry
|
|
114
|
+
this.retryDelay = (0, fibonacci_1.fibonacci)(this.retryCount) * 1000;
|
|
115
|
+
this.retryCount++;
|
|
116
|
+
throw new Error('Rate limited.');
|
|
117
|
+
case 6: throw new Error('Retry rate limit exceeded.');
|
|
118
|
+
case 7: return [3 /*break*/, 9];
|
|
119
|
+
case 8:
|
|
120
|
+
if (response.status == 404 && (responseJSON === null || responseJSON === void 0 ? void 0 : responseJSON.message) == 'Profile is currently paused') {
|
|
121
|
+
//dont throw if profile is paused.
|
|
122
|
+
throw new Error("".concat(responseJSON.message, ": ").concat((_b = context.query) === null || _b === void 0 ? void 0 : _b.tag));
|
|
123
|
+
}
|
|
124
|
+
_c.label = 9;
|
|
125
|
+
case 9: throw new Error('Unexpected Response Status.');
|
|
126
|
+
case 10:
|
|
127
|
+
err_1 = _c.sent();
|
|
128
|
+
if (!(err_1.message == 'Rate limited.')) return [3 /*break*/, 12];
|
|
129
|
+
return [4 /*yield*/, this.request(context, cacheKey)];
|
|
130
|
+
case 11: return [2 /*return*/, _c.sent()];
|
|
131
|
+
case 12:
|
|
132
|
+
// throw an object with fetch details
|
|
133
|
+
throw { err: err_1, fetchDetails: __assign({ status: response === null || response === void 0 ? void 0 : response.status, message: (response === null || response === void 0 ? void 0 : response.statusText) || 'FAILED', url: url }, init) };
|
|
134
|
+
case 13: return [2 /*return*/];
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
API.prototype.createFetchParams = function (context) {
|
|
140
|
+
var _a, _b;
|
|
141
|
+
// grab siteID out of context to generate apiHost fo URL
|
|
142
|
+
var siteId = ((_a = context === null || context === void 0 ? void 0 : context.body) === null || _a === void 0 ? void 0 : _a.siteId) || ((_b = context === null || context === void 0 ? void 0 : context.query) === null || _b === void 0 ? void 0 : _b.siteId);
|
|
143
|
+
if (!siteId) {
|
|
144
|
+
throw new Error("Request failed. Missing \"siteId\" parameter.");
|
|
145
|
+
}
|
|
146
|
+
var siteIdHost = "https://".concat(siteId, ".a").concat(context.subDomain ? ".".concat(context.subDomain) : '', ".athoscommerce.net");
|
|
147
|
+
var origin = (context.origin || this.configuration.origin || siteIdHost).replace(/\/$/, '');
|
|
148
|
+
var url = "".concat(origin, "/").concat(context.path.replace(/^\//, ''));
|
|
149
|
+
// merging globals to request query
|
|
150
|
+
var combinedQuery = (0, deepmerge_1.default)(context.query || {}, this.configuration.globals);
|
|
151
|
+
if (Object.keys(combinedQuery).length !== 0) {
|
|
152
|
+
// only add the querystring to the URL if there are query parameters.
|
|
153
|
+
url += '?' + this.configuration.queryParamsStringify(combinedQuery);
|
|
154
|
+
}
|
|
155
|
+
// merging globals to request body
|
|
156
|
+
var body = (typeof FormData !== 'undefined' && context.body instanceof FormData) || context.body instanceof URLSearchParams || isBlob(context.body)
|
|
157
|
+
? context.body
|
|
158
|
+
: JSON.stringify(context.body ? (0, deepmerge_1.default)(context.body, this.configuration.globals) : context.body);
|
|
159
|
+
var headers = __assign(__assign({}, this.configuration.headers), context.headers);
|
|
160
|
+
var init = {
|
|
161
|
+
method: context.method,
|
|
162
|
+
headers: headers,
|
|
163
|
+
body: body,
|
|
164
|
+
};
|
|
165
|
+
return { url: url, init: init };
|
|
166
|
+
};
|
|
167
|
+
API.prototype.fetchApi = function (url, init) {
|
|
168
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
169
|
+
var response;
|
|
170
|
+
return __generator(this, function (_a) {
|
|
171
|
+
switch (_a.label) {
|
|
172
|
+
case 0: return [4 /*yield*/, this.configuration.fetchApi(url, init)];
|
|
173
|
+
case 1:
|
|
174
|
+
response = _a.sent();
|
|
175
|
+
return [2 /*return*/, response];
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
return API;
|
|
181
|
+
}());
|
|
182
|
+
exports.API = API;
|
|
183
|
+
var ApiConfiguration = /** @class */ (function () {
|
|
184
|
+
function ApiConfiguration(config) {
|
|
185
|
+
if (config === void 0) { config = {}; }
|
|
186
|
+
this.config = config;
|
|
187
|
+
if (!config.maxRetry) {
|
|
188
|
+
this.config.maxRetry = 8;
|
|
189
|
+
}
|
|
190
|
+
this.config.cache = this.config.cache || {};
|
|
191
|
+
this.config.mode = this.config.mode || snap_toolbox_1.AppMode.production;
|
|
192
|
+
if (this.config.mode == snap_toolbox_1.AppMode.development) {
|
|
193
|
+
this.config.cache.enabled = false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
Object.defineProperty(ApiConfiguration.prototype, "cache", {
|
|
197
|
+
get: function () {
|
|
198
|
+
var _a;
|
|
199
|
+
return ((_a = this.config) === null || _a === void 0 ? void 0 : _a.cache) || {};
|
|
200
|
+
},
|
|
201
|
+
enumerable: false,
|
|
202
|
+
configurable: true
|
|
203
|
+
});
|
|
204
|
+
Object.defineProperty(ApiConfiguration.prototype, "maxRetry", {
|
|
205
|
+
get: function () {
|
|
206
|
+
return this.config.maxRetry || 8;
|
|
207
|
+
},
|
|
208
|
+
enumerable: false,
|
|
209
|
+
configurable: true
|
|
210
|
+
});
|
|
211
|
+
Object.defineProperty(ApiConfiguration.prototype, "origin", {
|
|
212
|
+
get: function () {
|
|
213
|
+
return this.config.origin || '';
|
|
214
|
+
},
|
|
215
|
+
enumerable: false,
|
|
216
|
+
configurable: true
|
|
217
|
+
});
|
|
218
|
+
Object.defineProperty(ApiConfiguration.prototype, "initiator", {
|
|
219
|
+
get: function () {
|
|
220
|
+
return this.config.initiator || "snap/client/".concat(snap_toolbox_1.version);
|
|
221
|
+
},
|
|
222
|
+
enumerable: false,
|
|
223
|
+
configurable: true
|
|
224
|
+
});
|
|
225
|
+
Object.defineProperty(ApiConfiguration.prototype, "fetchApi", {
|
|
226
|
+
get: function () {
|
|
227
|
+
var _a;
|
|
228
|
+
return this.config.fetchApi || (typeof window !== 'undefined' ? (_a = window.fetch) === null || _a === void 0 ? void 0 : _a.bind(window) : fetch);
|
|
229
|
+
},
|
|
230
|
+
enumerable: false,
|
|
231
|
+
configurable: true
|
|
232
|
+
});
|
|
233
|
+
Object.defineProperty(ApiConfiguration.prototype, "queryParamsStringify", {
|
|
234
|
+
get: function () {
|
|
235
|
+
return this.config.queryParamsStringify || querystring;
|
|
236
|
+
},
|
|
237
|
+
enumerable: false,
|
|
238
|
+
configurable: true
|
|
239
|
+
});
|
|
240
|
+
Object.defineProperty(ApiConfiguration.prototype, "headers", {
|
|
241
|
+
get: function () {
|
|
242
|
+
return this.config.headers || {};
|
|
243
|
+
},
|
|
244
|
+
set: function (newHeaders) {
|
|
245
|
+
this.config.headers = newHeaders;
|
|
246
|
+
},
|
|
247
|
+
enumerable: false,
|
|
248
|
+
configurable: true
|
|
249
|
+
});
|
|
250
|
+
Object.defineProperty(ApiConfiguration.prototype, "globals", {
|
|
251
|
+
get: function () {
|
|
252
|
+
return this.config.globals || {};
|
|
253
|
+
},
|
|
254
|
+
set: function (newGlobals) {
|
|
255
|
+
this.config.globals = newGlobals;
|
|
256
|
+
},
|
|
257
|
+
enumerable: false,
|
|
258
|
+
configurable: true
|
|
259
|
+
});
|
|
260
|
+
Object.defineProperty(ApiConfiguration.prototype, "mode", {
|
|
261
|
+
get: function () {
|
|
262
|
+
return this.config.mode;
|
|
263
|
+
},
|
|
264
|
+
enumerable: false,
|
|
265
|
+
configurable: true
|
|
266
|
+
});
|
|
267
|
+
Object.defineProperty(ApiConfiguration.prototype, "paths", {
|
|
268
|
+
get: function () {
|
|
269
|
+
return this.config.paths || {};
|
|
270
|
+
},
|
|
271
|
+
enumerable: false,
|
|
272
|
+
configurable: true
|
|
273
|
+
});
|
|
274
|
+
return ApiConfiguration;
|
|
275
|
+
}());
|
|
276
|
+
exports.ApiConfiguration = ApiConfiguration;
|
|
277
|
+
function querystring(params, prefix) {
|
|
278
|
+
if (prefix === void 0) { prefix = ''; }
|
|
279
|
+
return Object.keys(params)
|
|
280
|
+
.map(function (key) {
|
|
281
|
+
var fullKey = prefix + (prefix.length ? "[".concat(key, "]") : key);
|
|
282
|
+
var value = params[key];
|
|
283
|
+
if (value instanceof Array) {
|
|
284
|
+
var multiValue = value.map(function (singleValue) { return encodeURIComponent(String(singleValue)); }).join("&".concat(encodeURIComponent(fullKey), "="));
|
|
285
|
+
return "".concat(encodeURIComponent(fullKey), "=").concat(multiValue);
|
|
286
|
+
}
|
|
287
|
+
if (value instanceof Date) {
|
|
288
|
+
return "".concat(encodeURIComponent(fullKey), "=").concat(encodeURIComponent(value.toISOString()));
|
|
289
|
+
}
|
|
290
|
+
if (value instanceof Object) {
|
|
291
|
+
return querystring(value, fullKey);
|
|
292
|
+
}
|
|
293
|
+
return "".concat(encodeURIComponent(fullKey), "=").concat(encodeURIComponent(String(value)));
|
|
294
|
+
})
|
|
295
|
+
.filter(function (part) { return part.length > 0; })
|
|
296
|
+
.join('&');
|
|
297
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MetaRequestModel, MetaResponseModel } from '@athoscommerce/snapi-types';
|
|
2
|
+
import { API } from '.';
|
|
3
|
+
import { MetaRequesterPaths } from '../../types';
|
|
4
|
+
export declare class MetaAPI extends API<MetaRequesterPaths> {
|
|
5
|
+
postMeta(requestParameters: MetaRequestModel): Promise<MetaResponseModel>;
|
|
6
|
+
getMeta(queryParameters: MetaRequestModel): Promise<MetaResponseModel>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=Meta.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Meta.d.ts","sourceRoot":"","sources":["../../../../src/Client/apis/Meta.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAEjF,OAAO,EAAE,GAAG,EAAa,MAAM,GAAG,CAAC;AACnC,OAAO,EAAe,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE9D,qBAAa,OAAQ,SAAQ,GAAG,CAAC,kBAAkB,CAAC;IACtC,QAAQ,CAAC,iBAAiB,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAkBzE,OAAO,CAAC,eAAe,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAanF"}
|