@searchspring/snap-client 0.20.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.
Files changed (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +174 -0
  3. package/dist/cjs/Client/Client.d.ts +15 -0
  4. package/dist/cjs/Client/Client.d.ts.map +1 -0
  5. package/dist/cjs/Client/Client.js +198 -0
  6. package/dist/cjs/Client/NetworkCache/NetworkCache.d.ts +10 -0
  7. package/dist/cjs/Client/NetworkCache/NetworkCache.d.ts.map +1 -0
  8. package/dist/cjs/Client/NetworkCache/NetworkCache.js +104 -0
  9. package/dist/cjs/Client/apis/Abstract.d.ts +49 -0
  10. package/dist/cjs/Client/apis/Abstract.d.ts.map +1 -0
  11. package/dist/cjs/Client/apis/Abstract.js +209 -0
  12. package/dist/cjs/Client/apis/Hybrid.d.ts +10 -0
  13. package/dist/cjs/Client/apis/Hybrid.d.ts.map +1 -0
  14. package/dist/cjs/Client/apis/Hybrid.js +137 -0
  15. package/dist/cjs/Client/apis/Legacy.d.ts +11 -0
  16. package/dist/cjs/Client/apis/Legacy.d.ts.map +1 -0
  17. package/dist/cjs/Client/apis/Legacy.js +147 -0
  18. package/dist/cjs/Client/apis/Recommend.d.ts +81 -0
  19. package/dist/cjs/Client/apis/Recommend.d.ts.map +1 -0
  20. package/dist/cjs/Client/apis/Recommend.js +222 -0
  21. package/dist/cjs/Client/apis/Snap.d.ts +8 -0
  22. package/dist/cjs/Client/apis/Snap.d.ts.map +1 -0
  23. package/dist/cjs/Client/apis/Snap.js +126 -0
  24. package/dist/cjs/Client/apis/Suggest.d.ts +45 -0
  25. package/dist/cjs/Client/apis/Suggest.d.ts.map +1 -0
  26. package/dist/cjs/Client/apis/Suggest.js +145 -0
  27. package/dist/cjs/Client/apis/index.d.ts +7 -0
  28. package/dist/cjs/Client/apis/index.d.ts.map +1 -0
  29. package/dist/cjs/Client/apis/index.js +18 -0
  30. package/dist/cjs/Client/transforms/index.d.ts +4 -0
  31. package/dist/cjs/Client/transforms/index.d.ts.map +1 -0
  32. package/dist/cjs/Client/transforms/index.js +15 -0
  33. package/dist/cjs/Client/transforms/searchRequest.d.ts +47 -0
  34. package/dist/cjs/Client/transforms/searchRequest.d.ts.map +1 -0
  35. package/dist/cjs/Client/transforms/searchRequest.js +151 -0
  36. package/dist/cjs/Client/transforms/searchResponse.d.ts +31 -0
  37. package/dist/cjs/Client/transforms/searchResponse.d.ts.map +1 -0
  38. package/dist/cjs/Client/transforms/searchResponse.js +246 -0
  39. package/dist/cjs/Client/transforms/suggestResponse.d.ts +29 -0
  40. package/dist/cjs/Client/transforms/suggestResponse.d.ts.map +1 -0
  41. package/dist/cjs/Client/transforms/suggestResponse.js +53 -0
  42. package/dist/cjs/Client/utils/charsParams.d.ts +3 -0
  43. package/dist/cjs/Client/utils/charsParams.d.ts.map +1 -0
  44. package/dist/cjs/Client/utils/charsParams.js +23 -0
  45. package/dist/cjs/Client/utils/fibonacci.d.ts +2 -0
  46. package/dist/cjs/Client/utils/fibonacci.d.ts.map +1 -0
  47. package/dist/cjs/Client/utils/fibonacci.js +14 -0
  48. package/dist/cjs/Client/utils/hashParams.d.ts +3 -0
  49. package/dist/cjs/Client/utils/hashParams.d.ts.map +1 -0
  50. package/dist/cjs/Client/utils/hashParams.js +10 -0
  51. package/dist/cjs/Client/utils/htmlUnescape.d.ts +2 -0
  52. package/dist/cjs/Client/utils/htmlUnescape.d.ts.map +1 -0
  53. package/dist/cjs/Client/utils/htmlUnescape.js +12 -0
  54. package/dist/cjs/Client/utils/index.d.ts +2 -0
  55. package/dist/cjs/Client/utils/index.d.ts.map +1 -0
  56. package/dist/cjs/Client/utils/index.js +13 -0
  57. package/dist/cjs/Client/utils/mergeParams.d.ts +2 -0
  58. package/dist/cjs/Client/utils/mergeParams.d.ts.map +1 -0
  59. package/dist/cjs/Client/utils/mergeParams.js +18 -0
  60. package/dist/cjs/index.d.ts +3 -0
  61. package/dist/cjs/index.d.ts.map +1 -0
  62. package/dist/cjs/index.js +13 -0
  63. package/dist/cjs/types.d.ts +45 -0
  64. package/dist/cjs/types.d.ts.map +1 -0
  65. package/dist/cjs/types.js +2 -0
  66. package/dist/esm/Client/Client.d.ts +15 -0
  67. package/dist/esm/Client/Client.d.ts.map +1 -0
  68. package/dist/esm/Client/Client.js +108 -0
  69. package/dist/esm/Client/NetworkCache/NetworkCache.d.ts +10 -0
  70. package/dist/esm/Client/NetworkCache/NetworkCache.d.ts.map +1 -0
  71. package/dist/esm/Client/NetworkCache/NetworkCache.js +89 -0
  72. package/dist/esm/Client/apis/Abstract.d.ts +49 -0
  73. package/dist/esm/Client/apis/Abstract.d.ts.map +1 -0
  74. package/dist/esm/Client/apis/Abstract.js +119 -0
  75. package/dist/esm/Client/apis/Hybrid.d.ts +10 -0
  76. package/dist/esm/Client/apis/Hybrid.d.ts.map +1 -0
  77. package/dist/esm/Client/apis/Hybrid.js +49 -0
  78. package/dist/esm/Client/apis/Legacy.d.ts +11 -0
  79. package/dist/esm/Client/apis/Legacy.d.ts.map +1 -0
  80. package/dist/esm/Client/apis/Legacy.js +44 -0
  81. package/dist/esm/Client/apis/Recommend.d.ts +81 -0
  82. package/dist/esm/Client/apis/Recommend.d.ts.map +1 -0
  83. package/dist/esm/Client/apis/Recommend.js +91 -0
  84. package/dist/esm/Client/apis/Snap.d.ts +8 -0
  85. package/dist/esm/Client/apis/Snap.d.ts.map +1 -0
  86. package/dist/esm/Client/apis/Snap.js +36 -0
  87. package/dist/esm/Client/apis/Suggest.d.ts +45 -0
  88. package/dist/esm/Client/apis/Suggest.d.ts.map +1 -0
  89. package/dist/esm/Client/apis/Suggest.js +45 -0
  90. package/dist/esm/Client/apis/index.d.ts +7 -0
  91. package/dist/esm/Client/apis/index.d.ts.map +1 -0
  92. package/dist/esm/Client/apis/index.js +6 -0
  93. package/dist/esm/Client/transforms/index.d.ts +4 -0
  94. package/dist/esm/Client/transforms/index.d.ts.map +1 -0
  95. package/dist/esm/Client/transforms/index.js +3 -0
  96. package/dist/esm/Client/transforms/searchRequest.d.ts +47 -0
  97. package/dist/esm/Client/transforms/searchRequest.d.ts.map +1 -0
  98. package/dist/esm/Client/transforms/searchRequest.js +133 -0
  99. package/dist/esm/Client/transforms/searchResponse.d.ts +31 -0
  100. package/dist/esm/Client/transforms/searchResponse.d.ts.map +1 -0
  101. package/dist/esm/Client/transforms/searchResponse.js +249 -0
  102. package/dist/esm/Client/transforms/suggestResponse.d.ts +29 -0
  103. package/dist/esm/Client/transforms/suggestResponse.d.ts.map +1 -0
  104. package/dist/esm/Client/transforms/suggestResponse.js +42 -0
  105. package/dist/esm/Client/utils/charsParams.d.ts +3 -0
  106. package/dist/esm/Client/utils/charsParams.d.ts.map +1 -0
  107. package/dist/esm/Client/utils/charsParams.js +19 -0
  108. package/dist/esm/Client/utils/fibonacci.d.ts +2 -0
  109. package/dist/esm/Client/utils/fibonacci.d.ts.map +1 -0
  110. package/dist/esm/Client/utils/fibonacci.js +10 -0
  111. package/dist/esm/Client/utils/hashParams.d.ts +3 -0
  112. package/dist/esm/Client/utils/hashParams.d.ts.map +1 -0
  113. package/dist/esm/Client/utils/hashParams.js +6 -0
  114. package/dist/esm/Client/utils/htmlUnescape.d.ts +2 -0
  115. package/dist/esm/Client/utils/htmlUnescape.d.ts.map +1 -0
  116. package/dist/esm/Client/utils/htmlUnescape.js +8 -0
  117. package/dist/esm/Client/utils/index.d.ts +2 -0
  118. package/dist/esm/Client/utils/index.d.ts.map +1 -0
  119. package/dist/esm/Client/utils/index.js +1 -0
  120. package/dist/esm/Client/utils/mergeParams.d.ts +2 -0
  121. package/dist/esm/Client/utils/mergeParams.d.ts.map +1 -0
  122. package/dist/esm/Client/utils/mergeParams.js +10 -0
  123. package/dist/esm/index.d.ts +3 -0
  124. package/dist/esm/index.d.ts.map +1 -0
  125. package/dist/esm/index.js +1 -0
  126. package/dist/esm/types.d.ts +45 -0
  127. package/dist/esm/types.d.ts.map +1 -0
  128. package/dist/esm/types.js +1 -0
  129. package/package.json +27 -0
@@ -0,0 +1,3 @@
1
+ export * from './Client/Client';
2
+ export { ClientGlobals, ClientConfig } from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ __exportStar(require("./Client/Client"), exports);
@@ -0,0 +1,45 @@
1
+ export declare type ClientConfig = {
2
+ meta?: {
3
+ api?: SnapApiConfig;
4
+ cache?: CacheConfig;
5
+ };
6
+ search?: {
7
+ api?: SnapApiConfig;
8
+ cache?: CacheConfig;
9
+ };
10
+ autocomplete?: {
11
+ api?: SnapApiConfig;
12
+ cache?: CacheConfig;
13
+ };
14
+ recommend?: {
15
+ api?: SnapApiConfig;
16
+ cache?: CacheConfig;
17
+ };
18
+ suggest?: {
19
+ api?: SnapApiConfig;
20
+ cache?: CacheConfig;
21
+ };
22
+ };
23
+ export declare type CacheConfig = {
24
+ enabled?: boolean;
25
+ ttl?: number;
26
+ maxSize?: number;
27
+ purgeable?: boolean;
28
+ };
29
+ export declare type CacheEntry = {
30
+ value: Response;
31
+ expires?: number;
32
+ purgeable?: boolean;
33
+ };
34
+ export declare type Cache = {
35
+ [key: string]: CacheEntry;
36
+ };
37
+ export declare type SnapApiConfig = {
38
+ origin?: string;
39
+ };
40
+ export declare type ClientGlobals = {
41
+ siteId: string;
42
+ [configurationPath: string]: any;
43
+ };
44
+ export declare type ParameterObject = Record<string, boolean | string | string[] | number | number[]>;
45
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,oBAAY,YAAY,GAAG;IAC1B,IAAI,CAAC,EAAE;QACN,GAAG,CAAC,EAAE,aAAa,CAAC;QACpB,KAAK,CAAC,EAAE,WAAW,CAAC;KACpB,CAAC;IACF,MAAM,CAAC,EAAE;QACR,GAAG,CAAC,EAAE,aAAa,CAAC;QACpB,KAAK,CAAC,EAAE,WAAW,CAAC;KACpB,CAAC;IACF,YAAY,CAAC,EAAE;QACd,GAAG,CAAC,EAAE,aAAa,CAAC;QACpB,KAAK,CAAC,EAAE,WAAW,CAAC;KACpB,CAAC;IACF,SAAS,CAAC,EAAE;QACX,GAAG,CAAC,EAAE,aAAa,CAAC;QACpB,KAAK,CAAC,EAAE,WAAW,CAAC;KACpB,CAAC;IACF,OAAO,CAAC,EAAE;QACT,GAAG,CAAC,EAAE,aAAa,CAAC;QACpB,KAAK,CAAC,EAAE,WAAW,CAAC;KACpB,CAAC;CACF,CAAC;AAEF,oBAAY,WAAW,GAAG;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,oBAAY,UAAU,GAAG;IACxB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,oBAAY,KAAK,GAAG;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAC;CAC1B,CAAC;AAEF,oBAAY,aAAa,GAAG;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,oBAAY,aAAa,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,iBAAiB,EAAE,MAAM,GAAG,GAAG,CAAC;CACjC,CAAC;AAEF,oBAAY,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,15 @@
1
+ import { TrendingRequestModel, TrendingResponseModel, RecommendCombinedRequestModel, RecommendCombinedResponseModel } from './apis';
2
+ import type { ClientGlobals, ClientConfig } from '../types';
3
+ import type { MetaRequestModel, MetaResponseModel, SearchRequestModel, SearchResponseModel, AutocompleteRequestModel, AutocompleteResponseModel } from '@searchspring/snapi-types';
4
+ export declare class Client {
5
+ private globals;
6
+ private config;
7
+ private requesters;
8
+ constructor(globals: ClientGlobals, config?: ClientConfig);
9
+ meta(params?: MetaRequestModel): Promise<MetaResponseModel>;
10
+ autocomplete(params?: AutocompleteRequestModel): Promise<[MetaResponseModel, AutocompleteResponseModel]>;
11
+ search(params?: SearchRequestModel): Promise<[MetaResponseModel, SearchResponseModel]>;
12
+ trending(params: Partial<TrendingRequestModel>): Promise<TrendingResponseModel>;
13
+ recommend(params: RecommendCombinedRequestModel): Promise<RecommendCombinedResponseModel>;
14
+ }
15
+ //# sourceMappingURL=Client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Client.d.ts","sourceRoot":"","sources":["../../../src/Client/Client.ts"],"names":[],"mappings":"AAAA,OAAO,EAKN,oBAAoB,EACpB,qBAAqB,EAErB,6BAA6B,EAC7B,8BAA8B,EAG9B,MAAM,QAAQ,CAAC;AAEhB,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE5D,OAAO,KAAK,EACX,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,MAAM,2BAA2B,CAAC;AAgCnC,qBAAa,MAAM;IAClB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,UAAU,CAMhB;gBAEU,OAAO,EAAE,aAAa,EAAE,MAAM,GAAE,YAAiB;IA0CvD,IAAI,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAO3D,YAAY,CAAC,MAAM,GAAE,wBAA6B,GAAG,OAAO,CAAC,CAAC,iBAAiB,EAAE,yBAAyB,CAAC,CAAC;IAU5G,MAAM,CAAC,MAAM,GAAE,kBAAuB,GAAG,OAAO,CAAC,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;IAM1F,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAM/E,SAAS,CAAC,MAAM,EAAE,6BAA6B,GAAG,OAAO,CAAC,8BAA8B,CAAC;CAkC/F"}
@@ -0,0 +1,108 @@
1
+ import { HybridAPI, SuggestAPI, RecommendAPI, ApiConfiguration, } from './apis';
2
+ import deepmerge from 'deepmerge';
3
+ const defaultConfig = {
4
+ meta: {
5
+ cache: {
6
+ purgeable: false,
7
+ },
8
+ },
9
+ search: {
10
+ api: {
11
+ // origin: 'https://snapi.kube.searchspring.io',
12
+ },
13
+ },
14
+ autocomplete: {
15
+ api: {
16
+ // origin: 'https://snapi.kube.searchspring.io',
17
+ },
18
+ },
19
+ recommend: {
20
+ api: {
21
+ // origin: 'https://snapi.kube.searchspring.io',
22
+ },
23
+ },
24
+ suggest: {
25
+ api: {
26
+ // origin: 'https://snapi.kube.searchspring.io',
27
+ },
28
+ },
29
+ };
30
+ export class Client {
31
+ constructor(globals, config = {}) {
32
+ if (!globals?.siteId) {
33
+ throw 'no siteId specified!';
34
+ }
35
+ this.globals = globals;
36
+ this.config = deepmerge(defaultConfig, config);
37
+ this.requesters = {
38
+ autocomplete: new HybridAPI(new ApiConfiguration({
39
+ origin: this.config.autocomplete?.api?.origin,
40
+ cacheSettings: this.config.autocomplete.cache,
41
+ })),
42
+ meta: new HybridAPI(new ApiConfiguration({
43
+ origin: this.config.meta?.api?.origin,
44
+ cacheSettings: this.config.meta.cache,
45
+ })),
46
+ recommend: new RecommendAPI(new ApiConfiguration({
47
+ origin: this.config.recommend?.api?.origin,
48
+ cacheSettings: this.config.recommend.cache,
49
+ })),
50
+ search: new HybridAPI(new ApiConfiguration({
51
+ origin: this.config.search?.api?.origin,
52
+ cacheSettings: this.config.search.cache,
53
+ })),
54
+ suggest: new SuggestAPI(new ApiConfiguration({
55
+ origin: this.config.suggest?.api?.origin,
56
+ cacheSettings: this.config.suggest.cache,
57
+ })),
58
+ };
59
+ }
60
+ async meta(params) {
61
+ const defaultParams = { siteId: this.globals.siteId };
62
+ params = deepmerge(defaultParams, params || {});
63
+ return this.requesters.meta.getMeta(params);
64
+ }
65
+ async autocomplete(params = {}) {
66
+ if (!params.search?.query?.string) {
67
+ throw 'query string parameter is required';
68
+ }
69
+ params = deepmerge(this.globals, params);
70
+ return Promise.all([this.meta({ siteId: params.siteId }), this.requesters.autocomplete.getAutocomplete(params)]);
71
+ }
72
+ async search(params = {}) {
73
+ params = deepmerge(this.globals, params);
74
+ return Promise.all([this.meta({ siteId: params.siteId }), this.requesters.search.getSearch(params)]);
75
+ }
76
+ async trending(params) {
77
+ params = deepmerge({ siteId: this.globals.siteId }, params || {});
78
+ return this.requesters.suggest.getTrending(params);
79
+ }
80
+ async recommend(params) {
81
+ // TODO - batching
82
+ const { tag, ...otherParams } = params;
83
+ if (!tag) {
84
+ throw 'tag parameter is required';
85
+ }
86
+ const profileParams = {
87
+ tag,
88
+ siteId: params.siteId || this.globals.siteId,
89
+ };
90
+ if (otherParams.branch) {
91
+ profileParams.branch = otherParams.branch;
92
+ delete otherParams.branch;
93
+ }
94
+ const recommendParams = {
95
+ tags: [tag],
96
+ siteId: params.siteId || this.globals.siteId,
97
+ ...otherParams,
98
+ };
99
+ const [profile, recommendations] = await Promise.all([
100
+ this.requesters.recommend.getProfile(profileParams),
101
+ this.requesters.recommend.batchRecommendations(recommendParams),
102
+ ]);
103
+ return {
104
+ ...profile,
105
+ results: recommendations[0].results,
106
+ };
107
+ }
108
+ }
@@ -0,0 +1,10 @@
1
+ import { CacheConfig } from '../../types';
2
+ export declare class NetworkCache {
3
+ private memoryCache;
4
+ config: CacheConfig;
5
+ constructor(config?: CacheConfig);
6
+ get(key: string): Response;
7
+ set(key: string, value: Response): void;
8
+ clear(): void;
9
+ }
10
+ //# sourceMappingURL=NetworkCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NetworkCache.d.ts","sourceRoot":"","sources":["../../../../src/Client/NetworkCache/NetworkCache.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAS,MAAM,aAAa,CAAC;AAWjD,qBAAa,YAAY;IACxB,OAAO,CAAC,WAAW,CAAa;IAChC,MAAM,EAAE,WAAW,CAAC;gBAER,MAAM,CAAC,EAAE,WAAW;IAIzB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ;IAgC1B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI;IAyCvC,KAAK;CAQZ"}
@@ -0,0 +1,89 @@
1
+ import deepmerge from 'deepmerge';
2
+ const CACHE_STORAGE_KEY = 'ss-networkcache';
3
+ const defaultConfig = {
4
+ enabled: true,
5
+ ttl: 300000,
6
+ maxSize: 200,
7
+ purgeable: true,
8
+ };
9
+ export class NetworkCache {
10
+ constructor(config) {
11
+ this.memoryCache = {};
12
+ this.config = deepmerge(defaultConfig, config || {});
13
+ }
14
+ get(key) {
15
+ try {
16
+ if (this.memoryCache[key]) {
17
+ if (Date.now() < this.memoryCache[key].expires) {
18
+ return this.memoryCache[key].value;
19
+ }
20
+ }
21
+ const stored = sessionStorage.getItem(CACHE_STORAGE_KEY);
22
+ const localData = stored && JSON.parse(stored);
23
+ if (localData && key && localData[key]) {
24
+ // compare the expiry time of the item with the current time
25
+ if (Date.now() > localData[key].expires) {
26
+ // remove item
27
+ const newStored = {
28
+ ...localData,
29
+ };
30
+ delete newStored[key];
31
+ //update storage
32
+ sessionStorage.setItem(CACHE_STORAGE_KEY, JSON.stringify(newStored));
33
+ return undefined;
34
+ }
35
+ else {
36
+ return localData[key].value;
37
+ }
38
+ }
39
+ }
40
+ catch (err) {
41
+ console.warn('something went wrong, browser might not have cookies enabled');
42
+ }
43
+ }
44
+ set(key, value) {
45
+ if (this.config.enabled) {
46
+ try {
47
+ const cacheObject = {
48
+ value,
49
+ expires: Date.now() + this.config.ttl,
50
+ purgeable: this.config.purgeable,
51
+ };
52
+ this.memoryCache[key] = cacheObject;
53
+ const stored = sessionStorage.getItem(CACHE_STORAGE_KEY);
54
+ const newStored = {
55
+ ...(stored && JSON.parse(stored)),
56
+ };
57
+ newStored[key] = cacheObject;
58
+ let size = new Blob([JSON.stringify(newStored)], { endings: 'native' }).size / 1024;
59
+ while (size > this.config.maxSize) {
60
+ const oldestKey = Object.keys(newStored)
61
+ .filter((key) => newStored[key].purgeable)
62
+ .sort((a, b) => {
63
+ return newStored[a].expires - newStored[b].expires;
64
+ })[0];
65
+ if (!oldestKey)
66
+ break;
67
+ delete newStored[oldestKey];
68
+ // recalculate size after removing oldest
69
+ size = new Blob([JSON.stringify(newStored)], { endings: 'native' }).size / 1024;
70
+ }
71
+ if (size < this.config.maxSize) {
72
+ sessionStorage.setItem(CACHE_STORAGE_KEY, JSON.stringify(newStored));
73
+ }
74
+ }
75
+ catch (err) {
76
+ console.warn('something went wrong, browser might not have cookies enabled');
77
+ }
78
+ }
79
+ }
80
+ clear() {
81
+ try {
82
+ this.memoryCache = {};
83
+ sessionStorage.setItem(CACHE_STORAGE_KEY, '');
84
+ }
85
+ catch (err) {
86
+ console.warn('something went wrong, browser might not have cookies enabled');
87
+ }
88
+ }
89
+ }
@@ -0,0 +1,49 @@
1
+ import { NetworkCache } from '../NetworkCache/NetworkCache';
2
+ import { CacheConfig } from '../../types';
3
+ export declare type Json = any;
4
+ export declare type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
5
+ export declare type HTTPHeaders = {
6
+ [key: string]: string;
7
+ };
8
+ export declare type HTTPQuery = {
9
+ [key: string]: string | number | null | boolean | Array<string | number | null | boolean> | HTTPQuery;
10
+ };
11
+ export declare type HTTPBody = Json | FormData | URLSearchParams;
12
+ export interface RequestOpts {
13
+ path: string;
14
+ method: HTTPMethod;
15
+ headers: HTTPHeaders;
16
+ query?: HTTPQuery;
17
+ body?: HTTPBody;
18
+ }
19
+ export declare class API {
20
+ protected configuration: ApiConfiguration;
21
+ private retryDelay;
22
+ private retryCount;
23
+ cache: NetworkCache;
24
+ constructor(configuration: ApiConfiguration);
25
+ protected request(context: RequestOpts, cacheKey?: any): Promise<Response>;
26
+ private createFetchParams;
27
+ private fetchApi;
28
+ }
29
+ export declare type FetchAPI = WindowOrWorkerGlobalScope['fetch'];
30
+ export interface ApiConfigurationParameters {
31
+ origin?: string;
32
+ fetchApi?: FetchAPI;
33
+ queryParamsStringify?: (params: HTTPQuery) => string;
34
+ headers?: HTTPHeaders;
35
+ maxRetry?: number;
36
+ cacheSettings?: CacheConfig;
37
+ }
38
+ export declare class ApiConfiguration {
39
+ private configuration;
40
+ constructor(configuration: ApiConfigurationParameters);
41
+ get cacheSettings(): CacheConfig;
42
+ get maxRetry(): number;
43
+ get origin(): string;
44
+ get fetchApi(): FetchAPI;
45
+ get queryParamsStringify(): (params: HTTPQuery) => string;
46
+ get headers(): HTTPHeaders | undefined;
47
+ }
48
+ export declare function querystring(params: HTTPQuery, prefix?: string): string;
49
+ //# sourceMappingURL=Abstract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Abstract.d.ts","sourceRoot":"","sources":["../../../../src/Client/apis/Abstract.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1C,oBAAY,IAAI,GAAG,GAAG,CAAC;AACvB,oBAAY,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAC1F,oBAAY,WAAW,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC;AACpD,oBAAY,SAAS,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,GAAG,SAAS,CAAA;CAAE,CAAC;AAClI,oBAAY,QAAQ,GAAG,IAAI,GAAG,QAAQ,GAAG,eAAe,CAAC;AAEzD,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,IAAI,CAAC,EAAE,QAAQ,CAAC;CAChB;AAED,qBAAa,GAAG;IAMH,SAAS,CAAC,aAAa,EAAE,gBAAgB;IALrD,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAK;IAEhB,KAAK,EAAE,YAAY,CAAC;gBAEL,aAAa,EAAE,gBAAgB;cAIrC,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;IAmChF,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,QAAQ,CAId;CACF;AAED,oBAAY,QAAQ,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;AAE1D,MAAM,WAAW,0BAA0B;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,MAAM,CAAC;IACrD,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,WAAW,CAAC;CAC5B;AAED,qBAAa,gBAAgB;IAChB,OAAO,CAAC,aAAa;gBAAb,aAAa,EAAE,0BAA0B;IAM7D,IAAI,aAAa,IAAI,WAAW,CAE/B;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,QAAQ,IAAI,QAAQ,CAEvB;IAED,IAAI,oBAAoB,IAAI,CAAC,MAAM,EAAE,SAAS,KAAK,MAAM,CAExD;IAED,IAAI,OAAO,IAAI,WAAW,GAAG,SAAS,CAErC;CACD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,SAAK,GAAG,MAAM,CAmBlE"}
@@ -0,0 +1,119 @@
1
+ import { fibonacci } from '../utils/fibonacci';
2
+ import { NetworkCache } from '../NetworkCache/NetworkCache';
3
+ const isBlob = (value) => typeof Blob !== 'undefined' && value instanceof Blob;
4
+ export class API {
5
+ constructor(configuration) {
6
+ this.configuration = configuration;
7
+ this.retryDelay = 1000;
8
+ this.retryCount = 1;
9
+ this.fetchApi = async (url, init) => {
10
+ const response = await this.configuration.fetchApi(url, init);
11
+ return response;
12
+ };
13
+ this.cache = new NetworkCache(configuration.cacheSettings);
14
+ }
15
+ async request(context, cacheKey) {
16
+ const { url, init } = this.createFetchParams(context);
17
+ if (cacheKey) {
18
+ const cachedResponse = this.cache.get(cacheKey);
19
+ if (cachedResponse) {
20
+ this.retryCount = 0; // reset count and delay incase rate limit occurs again before a page refresh
21
+ this.retryDelay = 1000;
22
+ return cachedResponse;
23
+ }
24
+ }
25
+ const response = await this.fetchApi(url, init);
26
+ const responseJSON = await response.json();
27
+ if (response.status >= 200 && response.status < 300) {
28
+ this.retryCount = 0; // reset count and delay incase rate limit occurs again before a page refresh
29
+ this.retryDelay = 1000;
30
+ if (cacheKey) {
31
+ // save in the cache before returning
32
+ this.cache.set(cacheKey, responseJSON);
33
+ }
34
+ return responseJSON;
35
+ }
36
+ else if (response.status == 429) {
37
+ if (this.retryCount < this.configuration.maxRetry) {
38
+ await new Promise((resolve) => setTimeout(resolve, this.retryDelay)); // delay retry
39
+ this.retryDelay = fibonacci(this.retryCount) * 1000;
40
+ this.retryCount++;
41
+ return await this.request(context, cacheKey);
42
+ }
43
+ else {
44
+ throw response.status;
45
+ }
46
+ }
47
+ throw response.status;
48
+ }
49
+ createFetchParams(context) {
50
+ // grab siteID out of context to generate apiHost fo URL
51
+ const siteId = context?.body?.siteId || context?.query?.siteId;
52
+ if (!siteId) {
53
+ throw new Error(`Request failed. Missing "siteId" parameter.`);
54
+ }
55
+ const siteIdHost = `https://${siteId}.a.searchspring.io`;
56
+ const origin = (this.configuration.origin || siteIdHost).replace(/\/$/, '');
57
+ let url = `${origin}/${context.path.replace(/^\//, '')}`;
58
+ if (context.query !== undefined && Object.keys(context.query).length !== 0) {
59
+ // only add the querystring to the URL if there are query parameters.
60
+ url += '?' + this.configuration.queryParamsStringify(context.query);
61
+ }
62
+ const body = (typeof FormData !== 'undefined' && context.body instanceof FormData) || context.body instanceof URLSearchParams || isBlob(context.body)
63
+ ? context.body
64
+ : JSON.stringify(context.body);
65
+ const headers = Object.assign({}, this.configuration.headers, context.headers);
66
+ const init = {
67
+ method: context.method,
68
+ headers: headers,
69
+ body,
70
+ };
71
+ return { url, init };
72
+ }
73
+ }
74
+ export class ApiConfiguration {
75
+ constructor(configuration) {
76
+ this.configuration = configuration;
77
+ if (!configuration.maxRetry) {
78
+ this.configuration.maxRetry = 8;
79
+ }
80
+ }
81
+ get cacheSettings() {
82
+ return this.configuration.cacheSettings;
83
+ }
84
+ get maxRetry() {
85
+ return this.configuration.maxRetry;
86
+ }
87
+ get origin() {
88
+ return this.configuration.origin;
89
+ }
90
+ get fetchApi() {
91
+ return this.configuration.fetchApi || window.fetch.bind(window);
92
+ }
93
+ get queryParamsStringify() {
94
+ return this.configuration.queryParamsStringify || querystring;
95
+ }
96
+ get headers() {
97
+ return this.configuration.headers;
98
+ }
99
+ }
100
+ export function querystring(params, prefix = '') {
101
+ return Object.keys(params)
102
+ .map((key) => {
103
+ const fullKey = prefix + (prefix.length ? `[${key}]` : key);
104
+ const value = params[key];
105
+ if (value instanceof Array) {
106
+ const multiValue = value.map((singleValue) => encodeURIComponent(String(singleValue))).join(`&${encodeURIComponent(fullKey)}=`);
107
+ return `${encodeURIComponent(fullKey)}=${multiValue}`;
108
+ }
109
+ if (value instanceof Date) {
110
+ return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`;
111
+ }
112
+ if (value instanceof Object) {
113
+ return querystring(value, fullKey);
114
+ }
115
+ return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`;
116
+ })
117
+ .filter((part) => part.length > 0)
118
+ .join('&');
119
+ }
@@ -0,0 +1,10 @@
1
+ import { AutocompleteRequestModel, AutocompleteResponseModel, MetaRequestModel, MetaResponseModel, SearchRequestModel, SearchResponseModel } from '@searchspring/snapi-types';
2
+ import { API, ApiConfiguration } from '.';
3
+ export declare class HybridAPI extends API {
4
+ private requesters;
5
+ constructor(configuration: ApiConfiguration);
6
+ getMeta(requestParameters: MetaRequestModel): Promise<MetaResponseModel>;
7
+ getSearch(requestParameters: SearchRequestModel): Promise<SearchResponseModel>;
8
+ getAutocomplete(requestParameters: AutocompleteRequestModel): Promise<AutocompleteResponseModel>;
9
+ }
10
+ //# sourceMappingURL=Hybrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Hybrid.d.ts","sourceRoot":"","sources":["../../../../src/Client/apis/Hybrid.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,GAAG,EAAsC,gBAAgB,EAA6C,MAAM,GAAG,CAAC;AAGzH,qBAAa,SAAU,SAAQ,GAAG;IACjC,OAAO,CAAC,UAAU,CAGhB;gBAEU,aAAa,EAAE,gBAAgB;IASrC,OAAO,CAAC,iBAAiB,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAKxE,SAAS,CAAC,iBAAiB,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAQ9E,eAAe,CAAC,iBAAiB,EAAE,wBAAwB,GAAG,OAAO,CAAC,yBAAyB,CAAC;CAoCtG"}
@@ -0,0 +1,49 @@
1
+ import { API, LegacyAPI, SuggestAPI, ApiConfiguration } from '.';
2
+ import { transformSearchRequest, transformSearchResponse, transformSuggestResponse } from '../transforms';
3
+ export class HybridAPI extends API {
4
+ constructor(configuration) {
5
+ super(configuration);
6
+ this.requesters = {
7
+ legacy: new LegacyAPI(new ApiConfiguration({ origin: configuration.origin, cacheSettings: this.configuration.cacheSettings })),
8
+ suggest: new SuggestAPI(new ApiConfiguration({ origin: configuration.origin, cacheSettings: this.configuration.cacheSettings })),
9
+ };
10
+ }
11
+ async getMeta(requestParameters) {
12
+ const legacyRequestParameters = requestParameters;
13
+ return this.requesters.legacy.getMeta(legacyRequestParameters);
14
+ }
15
+ async getSearch(requestParameters) {
16
+ const legacyRequestParameters = transformSearchRequest(requestParameters);
17
+ const legacyData = await this.requesters.legacy.getSearch(legacyRequestParameters);
18
+ return transformSearchResponse(legacyData, requestParameters);
19
+ }
20
+ async getAutocomplete(requestParameters) {
21
+ const legacyRequestParameters = transformSearchRequest(requestParameters);
22
+ const suggestParams = {
23
+ siteId: legacyRequestParameters.siteId,
24
+ language: 'en',
25
+ query: legacyRequestParameters.q,
26
+ suggestionCount: (requestParameters.suggestions || {}).count || 5,
27
+ };
28
+ if (!((requestParameters.search || {}).query || {}).spellCorrection) {
29
+ suggestParams.disableSpellCorrect = true;
30
+ }
31
+ const suggestResults = await this.requesters.suggest.getSuggest(suggestParams);
32
+ const transformedSuggestResults = transformSuggestResponse(suggestResults);
33
+ const q = (suggestResults.suggested || {}).text || transformedSuggestResults.correctedQuery || suggestResults.query;
34
+ const queryParameters = {
35
+ ...legacyRequestParameters,
36
+ redirectResponse: 'full',
37
+ q,
38
+ };
39
+ const legacyResults = await this.requesters.legacy.getAutocomplete(queryParameters);
40
+ const searchResults = transformSearchResponse(legacyResults, requestParameters);
41
+ return {
42
+ ...searchResults,
43
+ search: {
44
+ query: q,
45
+ },
46
+ autocomplete: transformedSuggestResults,
47
+ };
48
+ }
49
+ }
@@ -0,0 +1,11 @@
1
+ import { MetaRequestModel, MetaResponseModel } from '@searchspring/snapi-types';
2
+ import { API } from '.';
3
+ export declare class LegacyAPI extends API {
4
+ private getEndpoint;
5
+ postMeta(requestParameters: MetaRequestModel): Promise<MetaResponseModel>;
6
+ getMeta(queryParameters: MetaRequestModel): Promise<MetaResponseModel>;
7
+ getSearch(queryParameters: any): Promise<any>;
8
+ getAutocomplete(queryParameters: any): Promise<any>;
9
+ getFinder(queryParameters: any): Promise<any>;
10
+ }
11
+ //# sourceMappingURL=Legacy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Legacy.d.ts","sourceRoot":"","sources":["../../../../src/Client/apis/Legacy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEhF,OAAO,EAAE,GAAG,EAA0B,MAAM,GAAG,CAAC;AAEhD,qBAAa,SAAU,SAAQ,GAAG;YACnB,WAAW;IAiBnB,QAAQ,CAAC,iBAAiB,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAkBzE,OAAO,CAAC,eAAe,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAgBtE,SAAS,CAAC,eAAe,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAI7C,eAAe,CAAC,eAAe,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAInD,SAAS,CAAC,eAAe,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;CAGnD"}
@@ -0,0 +1,44 @@
1
+ import { API } from '.';
2
+ export class LegacyAPI extends API {
3
+ async getEndpoint(queryParameters, path = '/api/search/search.json') {
4
+ queryParameters.resultsFormat = 'native';
5
+ const headerParameters = {};
6
+ const legacyResponse = await this.request({
7
+ path,
8
+ method: 'GET',
9
+ headers: headerParameters,
10
+ query: queryParameters,
11
+ }, path + JSON.stringify(queryParameters));
12
+ return legacyResponse;
13
+ }
14
+ async postMeta(requestParameters) {
15
+ const headerParameters = {};
16
+ headerParameters['Content-Type'] = 'application/json';
17
+ const response = await this.request({
18
+ path: '/api/meta/meta.json',
19
+ method: 'POST',
20
+ headers: headerParameters,
21
+ body: requestParameters,
22
+ }, '/api/meta/meta.json' + JSON.stringify(requestParameters));
23
+ return response;
24
+ }
25
+ async getMeta(queryParameters) {
26
+ const headerParameters = {};
27
+ const response = await this.request({
28
+ path: '/api/meta/meta.json',
29
+ method: 'GET',
30
+ headers: headerParameters,
31
+ query: queryParameters,
32
+ }, '/api/meta/meta.json' + JSON.stringify(queryParameters));
33
+ return response;
34
+ }
35
+ async getSearch(queryParameters) {
36
+ return this.getEndpoint(queryParameters, '/api/search/search.json');
37
+ }
38
+ async getAutocomplete(queryParameters) {
39
+ return this.getEndpoint(queryParameters, '/api/search/autocomplete.json');
40
+ }
41
+ async getFinder(queryParameters) {
42
+ return this.getEndpoint(queryParameters, '/api/search/finder.json');
43
+ }
44
+ }