@searchspring/snap-preact 0.28.0 → 0.30.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/cjs/Instantiators/RecommendationInstantiator.d.ts +6 -5
- package/dist/cjs/Instantiators/RecommendationInstantiator.d.ts.map +1 -1
- package/dist/cjs/Instantiators/RecommendationInstantiator.js +19 -5
- package/dist/cjs/Snap.d.ts +67 -13
- package/dist/cjs/Snap.d.ts.map +1 -1
- package/dist/cjs/Snap.js +220 -79
- package/dist/cjs/create/createAutocompleteController.d.ts +1 -1
- package/dist/cjs/create/createAutocompleteController.d.ts.map +1 -1
- package/dist/cjs/create/createAutocompleteController.js +6 -1
- package/dist/cjs/create/createFinderController.d.ts +1 -1
- package/dist/cjs/create/createFinderController.d.ts.map +1 -1
- package/dist/cjs/create/createFinderController.js +6 -1
- package/dist/cjs/create/createRecommendationController.d.ts +1 -1
- package/dist/cjs/create/createRecommendationController.d.ts.map +1 -1
- package/dist/cjs/create/createRecommendationController.js +6 -1
- package/dist/cjs/create/createSearchController.d.ts +1 -1
- package/dist/cjs/create/createSearchController.d.ts.map +1 -1
- package/dist/cjs/create/createSearchController.js +6 -1
- package/dist/cjs/getBundleDetails/getBundleDetails.d.ts.map +1 -1
- package/dist/cjs/getBundleDetails/getBundleDetails.js +3 -2
- package/dist/cjs/types.d.ts +11 -5
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/esm/Instantiators/RecommendationInstantiator.d.ts +6 -5
- package/dist/esm/Instantiators/RecommendationInstantiator.d.ts.map +1 -1
- package/dist/esm/Instantiators/RecommendationInstantiator.js +21 -6
- package/dist/esm/Snap.d.ts +67 -13
- package/dist/esm/Snap.d.ts.map +1 -1
- package/dist/esm/Snap.js +184 -61
- package/dist/esm/create/createAutocompleteController.d.ts +1 -1
- package/dist/esm/create/createAutocompleteController.d.ts.map +1 -1
- package/dist/esm/create/createAutocompleteController.js +6 -1
- package/dist/esm/create/createFinderController.d.ts +1 -1
- package/dist/esm/create/createFinderController.d.ts.map +1 -1
- package/dist/esm/create/createFinderController.js +6 -1
- package/dist/esm/create/createRecommendationController.d.ts +1 -1
- package/dist/esm/create/createRecommendationController.d.ts.map +1 -1
- package/dist/esm/create/createRecommendationController.js +6 -1
- package/dist/esm/create/createSearchController.d.ts +1 -1
- package/dist/esm/create/createSearchController.d.ts.map +1 -1
- package/dist/esm/create/createSearchController.js +6 -1
- package/dist/esm/getBundleDetails/getBundleDetails.d.ts.map +1 -1
- package/dist/esm/getBundleDetails/getBundleDetails.js +3 -2
- package/dist/esm/types.d.ts +11 -5
- package/dist/esm/types.d.ts.map +1 -1
- package/package.json +13 -13
package/dist/esm/Snap.js
CHANGED
|
@@ -3,14 +3,14 @@ import deepmerge from 'deepmerge';
|
|
|
3
3
|
import { isPlainObject } from 'is-plain-object';
|
|
4
4
|
import { render } from 'preact';
|
|
5
5
|
import { Client } from '@searchspring/snap-client';
|
|
6
|
-
import { Logger
|
|
6
|
+
import { Logger } from '@searchspring/snap-logger';
|
|
7
7
|
import { Tracker } from '@searchspring/snap-tracker';
|
|
8
|
-
import { version, DomTargeter, url, cookies, featureFlags } from '@searchspring/snap-toolbox';
|
|
9
|
-
import { getContext } from '@searchspring/snap-toolbox';
|
|
8
|
+
import { AppMode, version, getContext, DomTargeter, url, cookies, featureFlags } from '@searchspring/snap-toolbox';
|
|
10
9
|
import { ControllerTypes } from '@searchspring/snap-controller';
|
|
11
10
|
import { default as createSearchController } from './create/createSearchController';
|
|
12
11
|
export const BRANCH_COOKIE = 'ssBranch';
|
|
13
|
-
export const
|
|
12
|
+
export const DEV_COOKIE = 'ssDev';
|
|
13
|
+
const SESSION_ATTRIBUTION = 'ssAttribution';
|
|
14
14
|
const COMPONENT_ERROR = `Uncaught Error - Invalid value passed as the component.
|
|
15
15
|
This usually happens when you pass a JSX Element, and not a function that returns the component, in the snap config.
|
|
16
16
|
|
|
@@ -47,6 +47,10 @@ This usually happens when you pass a JSX Element, and not a function that return
|
|
|
47
47
|
The error above happened in the following targeter in the Snap Config`;
|
|
48
48
|
export class Snap {
|
|
49
49
|
constructor(config, services) {
|
|
50
|
+
this.mode = AppMode.production;
|
|
51
|
+
this._instantiatorPromises = {};
|
|
52
|
+
this._controllerPromises = {};
|
|
53
|
+
this.controllers = {};
|
|
50
54
|
this.getInstantiator = (id) => {
|
|
51
55
|
return this._instantiatorPromises[id] || Promise.reject(`getInstantiator could not find instantiator with id: ${id}`);
|
|
52
56
|
};
|
|
@@ -58,12 +62,22 @@ export class Snap {
|
|
|
58
62
|
controllerIds.forEach((id) => getControllerPromises.push(this.getController(id)));
|
|
59
63
|
return Promise.all(getControllerPromises);
|
|
60
64
|
};
|
|
65
|
+
// exposed method used for creating controllers dynamically - calls _createController()
|
|
61
66
|
this.createController = async (type, config, services, urlConfig, context, callback) => {
|
|
67
|
+
if (typeof this._controllerPromises[config.id] != 'undefined') {
|
|
68
|
+
throw new Error(`Controller with id '${config.id}' is already defined`);
|
|
69
|
+
}
|
|
70
|
+
this._controllerPromises[config.id] = new Promise((resolve) => this._createController(type, config, services, urlConfig, context, async (cntrlr) => {
|
|
71
|
+
if (typeof callback == 'function')
|
|
72
|
+
await callback(cntrlr);
|
|
73
|
+
resolve(cntrlr);
|
|
74
|
+
}));
|
|
75
|
+
return this._controllerPromises[config.id];
|
|
76
|
+
};
|
|
77
|
+
// internal use method that creates controllers without verifying if id is in use first
|
|
78
|
+
this._createController = async (type, config, services, urlConfig, context, callback) => {
|
|
62
79
|
let importPromise;
|
|
63
80
|
switch (type) {
|
|
64
|
-
case ControllerTypes.search:
|
|
65
|
-
importPromise = import('./create/createSearchController');
|
|
66
|
-
break;
|
|
67
81
|
case ControllerTypes.autocomplete:
|
|
68
82
|
importPromise = import('./create/createAutocompleteController');
|
|
69
83
|
break;
|
|
@@ -73,10 +87,17 @@ export class Snap {
|
|
|
73
87
|
case ControllerTypes.recommendation:
|
|
74
88
|
importPromise = import('./create/createRecommendationController');
|
|
75
89
|
break;
|
|
90
|
+
case ControllerTypes.search:
|
|
91
|
+
default:
|
|
92
|
+
importPromise = import('./create/createSearchController');
|
|
93
|
+
break;
|
|
76
94
|
}
|
|
95
|
+
// @ts-ignore - we know the config is correct, but complicated typing
|
|
77
96
|
const creationFunc = (await importPromise).default;
|
|
78
97
|
if (!this.controllers[config.id]) {
|
|
79
|
-
|
|
98
|
+
window.searchspring.controller = window.searchspring.controller || {};
|
|
99
|
+
window.searchspring.controller[config.id] = this.controllers[config.id] = creationFunc({
|
|
100
|
+
mode: this.mode,
|
|
80
101
|
url: deepmerge(this.config.url || {}, urlConfig || {}),
|
|
81
102
|
controller: config,
|
|
82
103
|
context: deepmerge(this.context || {}, context || {}),
|
|
@@ -95,15 +116,42 @@ export class Snap {
|
|
|
95
116
|
}
|
|
96
117
|
return this.controllers[config.id];
|
|
97
118
|
};
|
|
119
|
+
this.handlers = {
|
|
120
|
+
error: (event) => {
|
|
121
|
+
try {
|
|
122
|
+
const { filename } = event;
|
|
123
|
+
if (filename.includes('snapui.searchspring.io') && this.tracker.track.error) {
|
|
124
|
+
const { colno, lineno, error: { stack }, message, timeStamp, } = event;
|
|
125
|
+
const userAgent = navigator.userAgent;
|
|
126
|
+
const href = window.location.href;
|
|
127
|
+
const beaconPayload = {
|
|
128
|
+
userAgent,
|
|
129
|
+
href,
|
|
130
|
+
filename,
|
|
131
|
+
stack,
|
|
132
|
+
message,
|
|
133
|
+
colno,
|
|
134
|
+
lineno,
|
|
135
|
+
timeStamp,
|
|
136
|
+
};
|
|
137
|
+
this.tracker.track.error(beaconPayload);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
// prevent error metrics from breaking the app
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
window.removeEventListener('error', this.handlers.error);
|
|
146
|
+
window.addEventListener('error', this.handlers.error);
|
|
98
147
|
this.config = config;
|
|
99
|
-
this.logger = services?.logger || new Logger('Snap Preact ');
|
|
100
148
|
let globalContext = {};
|
|
101
149
|
try {
|
|
102
150
|
// get global context
|
|
103
151
|
globalContext = getContext(['shopper', 'config', 'merchandising']);
|
|
104
152
|
}
|
|
105
153
|
catch (err) {
|
|
106
|
-
|
|
154
|
+
console.error('Snap failed to find global context');
|
|
107
155
|
}
|
|
108
156
|
// merge configs - but only merge plain objects
|
|
109
157
|
this.config = deepmerge(this.config || {}, globalContext.config || {}, {
|
|
@@ -115,8 +163,9 @@ export class Snap {
|
|
|
115
163
|
if ((!services?.client || !services?.tracker) && !this.config?.client?.globals?.siteId) {
|
|
116
164
|
throw new Error(`Snap: config provided must contain a valid config.client.globals.siteId value`);
|
|
117
165
|
}
|
|
118
|
-
|
|
119
|
-
|
|
166
|
+
// segmented merchandising context -> client globals
|
|
167
|
+
if (this.config.client?.globals && this.context.merchandising?.segments) {
|
|
168
|
+
if (this.config.client.globals?.merchandising) {
|
|
120
169
|
this.config.client.globals.merchandising.segments = deepmerge(this.config.client.globals.merchandising.segments, this.context.merchandising.segments);
|
|
121
170
|
}
|
|
122
171
|
else {
|
|
@@ -125,33 +174,73 @@ export class Snap {
|
|
|
125
174
|
};
|
|
126
175
|
}
|
|
127
176
|
}
|
|
128
|
-
this.client = services?.client || new Client(this.config.client.globals, this.config.client.config);
|
|
129
|
-
this.tracker = services?.tracker || new Tracker(this.config.client.globals);
|
|
130
|
-
this._controllerPromises = {};
|
|
131
|
-
this._instantiatorPromises = {};
|
|
132
|
-
this.controllers = {};
|
|
133
|
-
// TODO environment switch using URL?
|
|
134
|
-
this.logger.setMode(process.env.NODE_ENV);
|
|
135
|
-
// log version
|
|
136
|
-
this.logger.imageText({
|
|
137
|
-
url: 'https://snapui.searchspring.io/favicon.svg',
|
|
138
|
-
text: `[${version}]`,
|
|
139
|
-
style: `color: ${this.logger.colors.indigo}; font-weight: bold;`,
|
|
140
|
-
});
|
|
141
177
|
try {
|
|
142
178
|
const urlParams = url(window.location.href);
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
179
|
+
const branchOverride = urlParams?.params?.query?.branch || cookies.get(BRANCH_COOKIE);
|
|
180
|
+
/* app mode priority:
|
|
181
|
+
1. node env
|
|
182
|
+
2. config
|
|
183
|
+
3. override via query param / cookie
|
|
184
|
+
*/
|
|
185
|
+
// node env
|
|
186
|
+
if (process.env.NODE_ENV && Object.values(AppMode).includes(process.env.NODE_ENV)) {
|
|
187
|
+
this.mode = process.env.NODE_ENV;
|
|
188
|
+
}
|
|
189
|
+
// config
|
|
190
|
+
if (this.config.mode && Object.values(AppMode).includes(this.config.mode)) {
|
|
191
|
+
this.mode = this.config.mode;
|
|
192
|
+
}
|
|
193
|
+
// query param / cookiev override
|
|
194
|
+
if ((urlParams?.params?.query && 'dev' in urlParams.params.query) || !!cookies.get(DEV_COOKIE)) {
|
|
195
|
+
if (urlParams?.params.query?.dev == 'false' || urlParams?.params.query?.dev == '0') {
|
|
196
|
+
cookies.unset(DEV_COOKIE);
|
|
197
|
+
this.mode = AppMode.production;
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
cookies.set(DEV_COOKIE, '1', 'Lax', 0);
|
|
201
|
+
this.mode = AppMode.development;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// client mode uses client config over snap config
|
|
205
|
+
if (this.config.client) {
|
|
206
|
+
this.config.client.config = this.config.client.config || {};
|
|
207
|
+
this.config.client.config.mode = this.config.client.config.mode || this.mode;
|
|
208
|
+
}
|
|
209
|
+
this.client = services?.client || new Client(this.config.client.globals, this.config.client.config);
|
|
210
|
+
this.tracker = services?.tracker || new Tracker(this.config.client.globals, { framework: 'preact' });
|
|
211
|
+
this.logger = services?.logger || new Logger({ prefix: 'Snap Preact ', mode: this.mode });
|
|
212
|
+
// check for tracking attribution in URL ?ss_attribution=type:id
|
|
213
|
+
const sessionAttribution = window.sessionStorage?.getItem(SESSION_ATTRIBUTION);
|
|
214
|
+
if (urlParams?.params?.query?.ss_attribution) {
|
|
215
|
+
const attribution = urlParams.params.query.ss_attribution.split(':');
|
|
216
|
+
const [type, id] = attribution;
|
|
217
|
+
if (type && id) {
|
|
218
|
+
this.tracker.updateContext('attribution', { type, id });
|
|
219
|
+
}
|
|
220
|
+
// save to session storage
|
|
221
|
+
window.sessionStorage?.setItem(SESSION_ATTRIBUTION, urlParams.params.query.ss_attribution);
|
|
222
|
+
}
|
|
223
|
+
else if (sessionAttribution) {
|
|
224
|
+
const [type, id] = sessionAttribution.split(':');
|
|
225
|
+
if (type && id) {
|
|
226
|
+
this.tracker.updateContext('attribution', { type, id });
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// log version
|
|
230
|
+
this.logger.imageText({
|
|
231
|
+
url: 'https://snapui.searchspring.io/favicon.svg',
|
|
232
|
+
text: `[${version}]`,
|
|
233
|
+
style: `color: ${this.logger.colors.indigo}; font-weight: bold;`,
|
|
234
|
+
});
|
|
235
|
+
if (branchOverride && !document.querySelector(`script[${BRANCH_COOKIE}]`)) {
|
|
236
|
+
this.logger.warn(`...loading build... '${branchOverride}'`);
|
|
237
|
+
// set a cookie with branch
|
|
146
238
|
if (featureFlags.cookies) {
|
|
147
|
-
cookies.set(BRANCH_COOKIE,
|
|
148
|
-
cookies.set(SS_DEV_COOKIE, '1', 'Lax', 0);
|
|
239
|
+
cookies.set(BRANCH_COOKIE, branchOverride, 'Lax', 3600000); // 1 hour
|
|
149
240
|
}
|
|
150
241
|
else {
|
|
151
242
|
this.logger.warn('Cookies are not supported/enabled by this browser, branch overrides will not persist!');
|
|
152
243
|
}
|
|
153
|
-
this.logger.setMode(LogMode.DEVELOPMENT);
|
|
154
|
-
this.logger.warn(`...loading build... '${branchParam}'`);
|
|
155
244
|
// get the path and siteId from the current bundle script in case its not the same as the client config
|
|
156
245
|
let path = `https://snapui.searchspring.io/${this.config.client.globals.siteId}/`;
|
|
157
246
|
const script = document.querySelector('script[src*="//snapui.searchspring.io"]');
|
|
@@ -163,9 +252,9 @@ export class Snap {
|
|
|
163
252
|
}
|
|
164
253
|
// append script with new branch in path
|
|
165
254
|
const branchScript = document.createElement('script');
|
|
166
|
-
const src = `${path}${
|
|
255
|
+
const src = `${path}${branchOverride}/bundle.js`;
|
|
167
256
|
branchScript.src = src;
|
|
168
|
-
branchScript.setAttribute(BRANCH_COOKIE,
|
|
257
|
+
branchScript.setAttribute(BRANCH_COOKIE, branchOverride);
|
|
169
258
|
new DomTargeter([
|
|
170
259
|
{
|
|
171
260
|
selector: 'body',
|
|
@@ -179,34 +268,43 @@ export class Snap {
|
|
|
179
268
|
},
|
|
180
269
|
},
|
|
181
270
|
], async (target, elem) => {
|
|
182
|
-
|
|
271
|
+
const props = {};
|
|
183
272
|
try {
|
|
184
273
|
const getBundleDetails = (await import('./getBundleDetails/getBundleDetails')).getBundleDetails;
|
|
185
|
-
|
|
274
|
+
props.details = await getBundleDetails(src);
|
|
186
275
|
}
|
|
187
276
|
catch (err) {
|
|
188
|
-
error = err;
|
|
277
|
+
props.error = err;
|
|
189
278
|
}
|
|
190
279
|
const BranchOverride = (await import('./components/BranchOverride')).BranchOverride;
|
|
191
|
-
render(_jsx(BranchOverride, {
|
|
280
|
+
render(_jsx(BranchOverride, { ...props, name: branchOverride, onRemoveClick: () => {
|
|
192
281
|
cookies.unset(BRANCH_COOKIE);
|
|
193
282
|
const urlState = url(window.location.href);
|
|
194
|
-
delete urlState
|
|
195
|
-
|
|
283
|
+
delete urlState?.params.query['branch'];
|
|
284
|
+
const newUrl = urlState?.url();
|
|
285
|
+
if (newUrl && newUrl != window.location.href) {
|
|
286
|
+
window.location.href = newUrl;
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
window.location.reload();
|
|
290
|
+
}
|
|
196
291
|
} }), elem);
|
|
197
|
-
|
|
292
|
+
// reset the global searchspring object
|
|
293
|
+
delete window.searchspring;
|
|
198
294
|
document.head.appendChild(branchScript);
|
|
199
295
|
});
|
|
200
296
|
// prevent further instantiation of config
|
|
201
297
|
return;
|
|
202
298
|
}
|
|
203
299
|
}
|
|
204
|
-
catch (e) {
|
|
205
|
-
|
|
206
|
-
window.searchspring.context = this.context;
|
|
207
|
-
if (this.client)
|
|
208
|
-
window.searchspring.client = this.client;
|
|
300
|
+
catch (e) {
|
|
301
|
+
this.logger.error(e);
|
|
209
302
|
}
|
|
303
|
+
// bind to window global
|
|
304
|
+
window.searchspring = window.searchspring || {};
|
|
305
|
+
window.searchspring.context = this.context;
|
|
306
|
+
if (this.client)
|
|
307
|
+
window.searchspring.client = this.client;
|
|
210
308
|
// autotrack shopper id from the context
|
|
211
309
|
if (this.context?.shopper?.id) {
|
|
212
310
|
this.tracker.track.shopper.login({
|
|
@@ -217,7 +315,7 @@ export class Snap {
|
|
|
217
315
|
if (this.context?.shopper?.cart) {
|
|
218
316
|
const cart = this.context.shopper.cart;
|
|
219
317
|
if (Array.isArray(cart)) {
|
|
220
|
-
const cartItems = cart.filter((item) => item?.sku || item?.childSku).map((item) => (item?.sku || item?.childSku).trim());
|
|
318
|
+
const cartItems = cart.filter((item) => item?.sku || item?.childSku).map((item) => (item?.sku || item?.childSku || '').trim());
|
|
221
319
|
this.tracker.cookies.cart.set(cartItems);
|
|
222
320
|
}
|
|
223
321
|
}
|
|
@@ -226,7 +324,12 @@ export class Snap {
|
|
|
226
324
|
case 'search': {
|
|
227
325
|
this.config.controllers[type].forEach((controller, index) => {
|
|
228
326
|
try {
|
|
327
|
+
if (typeof this._controllerPromises[controller.config.id] != 'undefined') {
|
|
328
|
+
this.logger.error(`Controller with id '${controller.config.id}' is already defined`);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
229
331
|
const cntrlr = createSearchController({
|
|
332
|
+
mode: this.mode,
|
|
230
333
|
url: deepmerge(this.config.url || {}, controller.url || {}),
|
|
231
334
|
controller: controller.config,
|
|
232
335
|
context: deepmerge(this.context || {}, controller.context || {}),
|
|
@@ -239,7 +342,8 @@ export class Snap {
|
|
|
239
342
|
logger: controller.services?.logger,
|
|
240
343
|
tracker: controller.services?.tracker || this.tracker,
|
|
241
344
|
});
|
|
242
|
-
|
|
345
|
+
window.searchspring.controller = window.searchspring.controller || {};
|
|
346
|
+
window.searchspring.controller[cntrlr.config.id] = this.controllers[cntrlr.config.id] = cntrlr;
|
|
243
347
|
this._controllerPromises[cntrlr.config.id] = new Promise((resolve) => resolve(cntrlr));
|
|
244
348
|
let searched = false;
|
|
245
349
|
const runSearch = () => {
|
|
@@ -273,7 +377,7 @@ export class Snap {
|
|
|
273
377
|
runSearch();
|
|
274
378
|
}
|
|
275
379
|
cntrlr.createTargeter({ controller: cntrlr, ...target }, async (target, elem, originalElem) => {
|
|
276
|
-
if (target.skeleton) {
|
|
380
|
+
if (target && target.skeleton && elem) {
|
|
277
381
|
const Skeleton = await target.skeleton();
|
|
278
382
|
setTimeout(() => {
|
|
279
383
|
render(_jsx(Skeleton, {}), elem);
|
|
@@ -291,6 +395,10 @@ export class Snap {
|
|
|
291
395
|
}
|
|
292
396
|
case 'autocomplete': {
|
|
293
397
|
this.config.controllers[type].forEach((controller, index) => {
|
|
398
|
+
if (typeof this._controllerPromises[controller.config.id] != 'undefined') {
|
|
399
|
+
this.logger.error(`Controller with id '${controller.config.id}' is already defined`);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
294
402
|
this._controllerPromises[controller.config.id] = new Promise((resolve) => {
|
|
295
403
|
try {
|
|
296
404
|
let bound = false;
|
|
@@ -316,8 +424,9 @@ export class Snap {
|
|
|
316
424
|
}
|
|
317
425
|
};
|
|
318
426
|
if (!controller?.targeters || controller?.targeters.length === 0) {
|
|
319
|
-
this.
|
|
320
|
-
|
|
427
|
+
this._createController(ControllerTypes.autocomplete, controller.config, controller.services, controller.url, controller.context, (cntrlr) => {
|
|
428
|
+
if (cntrlr)
|
|
429
|
+
resolve(cntrlr);
|
|
321
430
|
});
|
|
322
431
|
}
|
|
323
432
|
controller?.targeters?.forEach((target, target_index) => {
|
|
@@ -343,8 +452,9 @@ export class Snap {
|
|
|
343
452
|
...target,
|
|
344
453
|
},
|
|
345
454
|
], async (target, elem, originalElem) => {
|
|
346
|
-
const cntrlr = await this.
|
|
347
|
-
|
|
455
|
+
const cntrlr = await this._createController(ControllerTypes.autocomplete, controller.config, controller.services, controller.url, controller.context, (cntrlr) => {
|
|
456
|
+
if (cntrlr)
|
|
457
|
+
resolve(cntrlr);
|
|
348
458
|
});
|
|
349
459
|
runBind();
|
|
350
460
|
targetFunction({ controller: cntrlr, ...target }, elem, originalElem);
|
|
@@ -361,6 +471,10 @@ export class Snap {
|
|
|
361
471
|
}
|
|
362
472
|
case 'finder': {
|
|
363
473
|
this.config.controllers[type].forEach((controller, index) => {
|
|
474
|
+
if (typeof this._controllerPromises[controller.config.id] != 'undefined') {
|
|
475
|
+
this.logger.error(`Controller with id '${controller.config.id}' is already defined`);
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
364
478
|
this._controllerPromises[controller.config.id] = new Promise((resolve) => {
|
|
365
479
|
try {
|
|
366
480
|
let searched = false;
|
|
@@ -384,8 +498,9 @@ export class Snap {
|
|
|
384
498
|
}
|
|
385
499
|
};
|
|
386
500
|
if (!controller?.targeters || controller?.targeters.length === 0) {
|
|
387
|
-
this.
|
|
388
|
-
|
|
501
|
+
this._createController(ControllerTypes.finder, controller.config, controller.services, controller.url, controller.context, (cntrlr) => {
|
|
502
|
+
if (cntrlr)
|
|
503
|
+
resolve(cntrlr);
|
|
389
504
|
});
|
|
390
505
|
}
|
|
391
506
|
controller?.targeters?.forEach((target, target_index) => {
|
|
@@ -396,8 +511,9 @@ export class Snap {
|
|
|
396
511
|
throw new Error(`Targets at index ${target_index} missing component value (Component).`);
|
|
397
512
|
}
|
|
398
513
|
const targeter = new DomTargeter([{ ...target }], async (target, elem, originalElem) => {
|
|
399
|
-
const cntrlr = await this.
|
|
400
|
-
|
|
514
|
+
const cntrlr = await this._createController(ControllerTypes.finder, controller.config, controller.services, controller.url, controller.context, (cntrlr) => {
|
|
515
|
+
if (cntrlr)
|
|
516
|
+
resolve(cntrlr);
|
|
401
517
|
});
|
|
402
518
|
runSearch();
|
|
403
519
|
targetFunction({ controller: cntrlr, ...target }, elem, originalElem);
|
|
@@ -414,6 +530,10 @@ export class Snap {
|
|
|
414
530
|
}
|
|
415
531
|
case 'recommendation': {
|
|
416
532
|
this.config.controllers[type].forEach((controller, index) => {
|
|
533
|
+
if (typeof this._controllerPromises[controller.config.id] != 'undefined') {
|
|
534
|
+
this.logger.error(`Controller with id '${controller.config.id}' is already defined`);
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
417
537
|
this._controllerPromises[controller.config.id] = new Promise((resolve) => {
|
|
418
538
|
try {
|
|
419
539
|
let searched = false;
|
|
@@ -437,8 +557,9 @@ export class Snap {
|
|
|
437
557
|
}
|
|
438
558
|
};
|
|
439
559
|
if (!controller?.targeters || controller?.targeters.length === 0) {
|
|
440
|
-
this.
|
|
441
|
-
|
|
560
|
+
this._createController(ControllerTypes.recommendation, controller.config, controller.services, controller.url, controller.context, (cntrlr) => {
|
|
561
|
+
if (cntrlr)
|
|
562
|
+
resolve(cntrlr);
|
|
442
563
|
});
|
|
443
564
|
}
|
|
444
565
|
controller?.targeters?.forEach((target, target_index) => {
|
|
@@ -449,8 +570,9 @@ export class Snap {
|
|
|
449
570
|
throw new Error(`Targets at index ${target_index} missing component value (Component).`);
|
|
450
571
|
}
|
|
451
572
|
const targeter = new DomTargeter([{ ...target }], async (target, elem, originalElem) => {
|
|
452
|
-
const cntrlr = await this.
|
|
453
|
-
|
|
573
|
+
const cntrlr = await this._createController(ControllerTypes.recommendation, controller.config, controller.services, controller.url, controller.context, (cntrlr) => {
|
|
574
|
+
if (cntrlr)
|
|
575
|
+
resolve(cntrlr);
|
|
454
576
|
});
|
|
455
577
|
runSearch();
|
|
456
578
|
targetFunction({ controller: cntrlr, ...target }, elem, originalElem);
|
|
@@ -470,6 +592,7 @@ export class Snap {
|
|
|
470
592
|
if (this.config?.instantiators?.recommendation) {
|
|
471
593
|
try {
|
|
472
594
|
this._instantiatorPromises.recommendation = import('./Instantiators/RecommendationInstantiator').then(({ RecommendationInstantiator }) => {
|
|
595
|
+
this.config.instantiators.recommendation.mode = this.config.instantiators.recommendation.mode || this.mode;
|
|
473
596
|
return new RecommendationInstantiator(this.config.instantiators.recommendation, {
|
|
474
597
|
client: this.client,
|
|
475
598
|
tracker: this.tracker,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AutocompleteController } from '@searchspring/snap-controller';
|
|
2
2
|
import type { SnapControllerServices, SnapAutocompleteControllerConfig } from '../types';
|
|
3
|
-
declare const _default: (config: SnapAutocompleteControllerConfig, services?: SnapControllerServices) => AutocompleteController;
|
|
3
|
+
declare const _default: (config: SnapAutocompleteControllerConfig, services?: SnapControllerServices | undefined) => AutocompleteController;
|
|
4
4
|
export default _default;
|
|
5
5
|
//# sourceMappingURL=createAutocompleteController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createAutocompleteController.d.ts","sourceRoot":"","sources":["../../../src/create/createAutocompleteController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AASvE,OAAO,KAAK,EAAE,sBAAsB,EAAE,gCAAgC,EAAE,MAAM,UAAU,CAAC;iCAIjE,gCAAgC,
|
|
1
|
+
{"version":3,"file":"createAutocompleteController.d.ts","sourceRoot":"","sources":["../../../src/create/createAutocompleteController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AASvE,OAAO,KAAK,EAAE,sBAAsB,EAAE,gCAAgC,EAAE,MAAM,UAAU,CAAC;iCAIjE,gCAAgC,oDAAsC,sBAAsB;AAApH,wBAwBE"}
|
|
@@ -10,13 +10,18 @@ import { Tracker } from '@searchspring/snap-tracker';
|
|
|
10
10
|
configureMobx({ useProxies: 'never' });
|
|
11
11
|
export default (config, services) => {
|
|
12
12
|
const urlManager = (services?.urlManager || new UrlManager(new UrlTranslator(config.url), reactLinker)).detach();
|
|
13
|
+
// set client mode
|
|
14
|
+
if (config.mode && config.client) {
|
|
15
|
+
config.client.config = config.client.config || {};
|
|
16
|
+
config.client.config.mode = config.mode;
|
|
17
|
+
}
|
|
13
18
|
const cntrlr = new AutocompleteController(config.controller, {
|
|
14
19
|
client: services?.client || new Client(config.client.globals, config.client.config),
|
|
15
20
|
store: services?.store || new AutocompleteStore(config.controller, { urlManager }),
|
|
16
21
|
urlManager,
|
|
17
22
|
eventManager: services?.eventManager || new EventManager(),
|
|
18
23
|
profiler: services?.profiler || new Profiler(),
|
|
19
|
-
logger: services?.logger || new Logger(),
|
|
24
|
+
logger: services?.logger || new Logger({ mode: config.mode }),
|
|
20
25
|
tracker: services?.tracker || new Tracker(config.client.globals),
|
|
21
26
|
}, config.context);
|
|
22
27
|
return cntrlr;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FinderController } from '@searchspring/snap-controller';
|
|
2
2
|
import type { SnapControllerServices, SnapFinderControllerConfig } from '../types';
|
|
3
|
-
declare const _default: (config: SnapFinderControllerConfig, services?: SnapControllerServices) => FinderController;
|
|
3
|
+
declare const _default: (config: SnapFinderControllerConfig, services?: SnapControllerServices | undefined) => FinderController;
|
|
4
4
|
export default _default;
|
|
5
5
|
//# sourceMappingURL=createFinderController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createFinderController.d.ts","sourceRoot":"","sources":["../../../src/create/createFinderController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AASjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;iCAI3D,0BAA0B,
|
|
1
|
+
{"version":3,"file":"createFinderController.d.ts","sourceRoot":"","sources":["../../../src/create/createFinderController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AASjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;iCAI3D,0BAA0B,oDAAsC,gBAAgB;AAAxG,wBAwBE"}
|
|
@@ -10,13 +10,18 @@ import { Tracker } from '@searchspring/snap-tracker';
|
|
|
10
10
|
configureMobx({ useProxies: 'never' });
|
|
11
11
|
export default (config, services) => {
|
|
12
12
|
const urlManager = (services?.urlManager || new UrlManager(new UrlTranslator(config.url), reactLinker)).detach(true);
|
|
13
|
+
// set client mode
|
|
14
|
+
if (config.mode && config.client) {
|
|
15
|
+
config.client.config = config.client.config || {};
|
|
16
|
+
config.client.config.mode = config.mode;
|
|
17
|
+
}
|
|
13
18
|
const cntrlr = new FinderController(config.controller, {
|
|
14
19
|
client: services?.client || new Client(config.client.globals, config.client.config),
|
|
15
20
|
store: services?.store || new FinderStore(config.controller, { urlManager }),
|
|
16
21
|
urlManager,
|
|
17
22
|
eventManager: services?.eventManager || new EventManager(),
|
|
18
23
|
profiler: services?.profiler || new Profiler(),
|
|
19
|
-
logger: services?.logger || new Logger(),
|
|
24
|
+
logger: services?.logger || new Logger({ mode: config.mode }),
|
|
20
25
|
tracker: services?.tracker || new Tracker(config.client.globals),
|
|
21
26
|
}, config.context);
|
|
22
27
|
return cntrlr;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RecommendationController } from '@searchspring/snap-controller';
|
|
2
2
|
import type { SnapControllerServices, SnapRecommendationControllerConfig } from '../types';
|
|
3
|
-
declare const _default: (config: SnapRecommendationControllerConfig, services?: SnapControllerServices) => RecommendationController;
|
|
3
|
+
declare const _default: (config: SnapRecommendationControllerConfig, services?: SnapControllerServices | undefined) => RecommendationController;
|
|
4
4
|
export default _default;
|
|
5
5
|
//# sourceMappingURL=createRecommendationController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createRecommendationController.d.ts","sourceRoot":"","sources":["../../../src/create/createRecommendationController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AASzE,OAAO,KAAK,EAAE,sBAAsB,EAAE,kCAAkC,EAAE,MAAM,UAAU,CAAC;iCAInE,kCAAkC,
|
|
1
|
+
{"version":3,"file":"createRecommendationController.d.ts","sourceRoot":"","sources":["../../../src/create/createRecommendationController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AASzE,OAAO,KAAK,EAAE,sBAAsB,EAAE,kCAAkC,EAAE,MAAM,UAAU,CAAC;iCAInE,kCAAkC,oDAAsC,wBAAwB;AAAxH,wBAwBE"}
|
|
@@ -10,13 +10,18 @@ import { Tracker } from '@searchspring/snap-tracker';
|
|
|
10
10
|
configureMobx({ useProxies: 'never' });
|
|
11
11
|
export default (config, services) => {
|
|
12
12
|
const urlManager = (services?.urlManager || new UrlManager(new UrlTranslator(config.url), reactLinker)).detach(true);
|
|
13
|
+
// set client mode
|
|
14
|
+
if (config.mode && config.client) {
|
|
15
|
+
config.client.config = config.client.config || {};
|
|
16
|
+
config.client.config.mode = config.mode;
|
|
17
|
+
}
|
|
13
18
|
const cntrlr = new RecommendationController(config.controller, {
|
|
14
19
|
client: services?.client || new Client(config.client.globals, config.client.config),
|
|
15
20
|
store: services?.store || new RecommendationStore(config.controller, { urlManager }),
|
|
16
21
|
urlManager,
|
|
17
22
|
eventManager: services?.eventManager || new EventManager(),
|
|
18
23
|
profiler: services?.profiler || new Profiler(),
|
|
19
|
-
logger: services?.logger || new Logger(),
|
|
24
|
+
logger: services?.logger || new Logger({ mode: config.mode }),
|
|
20
25
|
tracker: services?.tracker || new Tracker(config.client.globals),
|
|
21
26
|
}, config.context);
|
|
22
27
|
return cntrlr;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SearchController } from '@searchspring/snap-controller';
|
|
2
2
|
import type { SnapControllerServices, SnapSearchControllerConfig } from '../types';
|
|
3
|
-
declare const _default: (config: SnapSearchControllerConfig, services?: SnapControllerServices) => SearchController;
|
|
3
|
+
declare const _default: (config: SnapSearchControllerConfig, services?: SnapControllerServices | undefined) => SearchController;
|
|
4
4
|
export default _default;
|
|
5
5
|
//# sourceMappingURL=createSearchController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSearchController.d.ts","sourceRoot":"","sources":["../../../src/create/createSearchController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAQjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;iCAI3D,0BAA0B,
|
|
1
|
+
{"version":3,"file":"createSearchController.d.ts","sourceRoot":"","sources":["../../../src/create/createSearchController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAQjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;iCAI3D,0BAA0B,oDAAsC,gBAAgB;AAAxG,wBAwBE"}
|
|
@@ -10,13 +10,18 @@ import { Tracker } from '@searchspring/snap-tracker';
|
|
|
10
10
|
configureMobx({ useProxies: 'never' });
|
|
11
11
|
export default (config, services) => {
|
|
12
12
|
const urlManager = services?.urlManager || new UrlManager(new UrlTranslator(config.url), reactLinker);
|
|
13
|
+
// set client mode
|
|
14
|
+
if (config.mode && config.client) {
|
|
15
|
+
config.client.config = config.client.config || {};
|
|
16
|
+
config.client.config.mode = config.mode;
|
|
17
|
+
}
|
|
13
18
|
const cntrlr = new SearchController(config.controller, {
|
|
14
19
|
client: services?.client || new Client(config.client.globals, config.client.config),
|
|
15
20
|
store: services?.store || new SearchStore(config.controller, { urlManager }),
|
|
16
21
|
urlManager,
|
|
17
22
|
eventManager: services?.eventManager || new EventManager(),
|
|
18
23
|
profiler: services?.profiler || new Profiler(),
|
|
19
|
-
logger: services?.logger || new Logger(),
|
|
24
|
+
logger: services?.logger || new Logger({ mode: config.mode }),
|
|
20
25
|
tracker: services?.tracker || new Tracker(config.client.globals),
|
|
21
26
|
}, config.context);
|
|
22
27
|
return cntrlr;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getBundleDetails.d.ts","sourceRoot":"","sources":["../../../src/getBundleDetails/getBundleDetails.ts"],"names":[],"mappings":"AAAA,aAAK,aAAa,GAAG;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAe,MAAM,KAAG,QAAQ,aAAa,
|
|
1
|
+
{"version":3,"file":"getBundleDetails.d.ts","sourceRoot":"","sources":["../../../src/getBundleDetails/getBundleDetails.ts"],"names":[],"mappings":"AAAA,aAAK,aAAa,GAAG;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAe,MAAM,KAAG,QAAQ,aAAa,CAyBzE,CAAC"}
|
|
@@ -5,10 +5,11 @@ export const getBundleDetails = async (url) => {
|
|
|
5
5
|
request.onreadystatechange = () => {
|
|
6
6
|
if (request.readyState === request.DONE) {
|
|
7
7
|
const status = request.status;
|
|
8
|
-
|
|
8
|
+
const lastModified = request.getResponseHeader('Last-Modified');
|
|
9
|
+
if ((lastModified && status === 0) || (status >= 200 && status < 400)) {
|
|
9
10
|
resolve({
|
|
10
11
|
url,
|
|
11
|
-
lastModified:
|
|
12
|
+
lastModified: lastModified.split(',')[1].trim(),
|
|
12
13
|
});
|
|
13
14
|
}
|
|
14
15
|
else {
|