@searchspring/snap-controller 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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +167 -0
  3. package/dist/cjs/Abstract/AbstractController.d.ts +40 -0
  4. package/dist/cjs/Abstract/AbstractController.d.ts.map +1 -0
  5. package/dist/cjs/Abstract/AbstractController.js +281 -0
  6. package/dist/cjs/Autocomplete/AutocompleteController.d.ts +40 -0
  7. package/dist/cjs/Autocomplete/AutocompleteController.d.ts.map +1 -0
  8. package/dist/cjs/Autocomplete/AutocompleteController.js +687 -0
  9. package/dist/cjs/Finder/FinderController.d.ts +14 -0
  10. package/dist/cjs/Finder/FinderController.d.ts.map +1 -0
  11. package/dist/cjs/Finder/FinderController.js +286 -0
  12. package/dist/cjs/Recommendation/RecommendationController.d.ts +31 -0
  13. package/dist/cjs/Recommendation/RecommendationController.d.ts.map +1 -0
  14. package/dist/cjs/Recommendation/RecommendationController.js +452 -0
  15. package/dist/cjs/Search/SearchController.d.ts +23 -0
  16. package/dist/cjs/Search/SearchController.d.ts.map +1 -0
  17. package/dist/cjs/Search/SearchController.js +429 -0
  18. package/dist/cjs/index.d.ts +7 -0
  19. package/dist/cjs/index.d.ts.map +1 -0
  20. package/dist/cjs/index.js +24 -0
  21. package/dist/cjs/types.d.ts +52 -0
  22. package/dist/cjs/types.d.ts.map +1 -0
  23. package/dist/cjs/types.js +2 -0
  24. package/dist/cjs/utils/getParams.d.ts +2 -0
  25. package/dist/cjs/utils/getParams.d.ts.map +1 -0
  26. package/dist/cjs/utils/getParams.js +72 -0
  27. package/dist/esm/Abstract/AbstractController.d.ts +40 -0
  28. package/dist/esm/Abstract/AbstractController.d.ts.map +1 -0
  29. package/dist/esm/Abstract/AbstractController.js +181 -0
  30. package/dist/esm/Autocomplete/AutocompleteController.d.ts +40 -0
  31. package/dist/esm/Autocomplete/AutocompleteController.d.ts.map +1 -0
  32. package/dist/esm/Autocomplete/AutocompleteController.js +472 -0
  33. package/dist/esm/Finder/FinderController.d.ts +14 -0
  34. package/dist/esm/Finder/FinderController.d.ts.map +1 -0
  35. package/dist/esm/Finder/FinderController.js +164 -0
  36. package/dist/esm/Recommendation/RecommendationController.d.ts +31 -0
  37. package/dist/esm/Recommendation/RecommendationController.d.ts.map +1 -0
  38. package/dist/esm/Recommendation/RecommendationController.js +330 -0
  39. package/dist/esm/Search/SearchController.d.ts +23 -0
  40. package/dist/esm/Search/SearchController.d.ts.map +1 -0
  41. package/dist/esm/Search/SearchController.js +282 -0
  42. package/dist/esm/index.d.ts +7 -0
  43. package/dist/esm/index.d.ts.map +1 -0
  44. package/dist/esm/index.js +6 -0
  45. package/dist/esm/types.d.ts +52 -0
  46. package/dist/esm/types.d.ts.map +1 -0
  47. package/dist/esm/types.js +1 -0
  48. package/dist/esm/utils/getParams.d.ts +2 -0
  49. package/dist/esm/utils/getParams.d.ts.map +1 -0
  50. package/dist/esm/utils/getParams.js +68 -0
  51. package/package.json +40 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Searchspring
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # Snap Controller
2
+
3
+ <a href="https://www.npmjs.com/package/@searchspring/snap-controller"><img alt="NPM Status" src="https://img.shields.io/npm/v/@searchspring/snap-controller.svg?style=flat"></a>
4
+
5
+ The heart of controlling Search, Autocomplete, & Finder functionality. The Controller is responsible for tying various Snap services together.
6
+
7
+
8
+ ## Dependencies
9
+
10
+ Snap Controller is a top-level package that requires the following dependencies as services:
11
+
12
+ <a href="https://www.npmjs.com/package/@searchspring/snap-client"><img alt="NPM Status" src="https://img.shields.io/npm/v/@searchspring/snap-client.svg?style=flat"></a> [@searchspring/snap-client](https://github.com/searchspring/snap/tree/main/packages/snap-client)
13
+
14
+ <a href="https://www.npmjs.com/package/@searchspring/snap-store-mobx"><img alt="NPM Status" src="https://img.shields.io/npm/v/@searchspring/snap-store-mobx.svg?style=flat"></a> [@searchspring/snap-store-mobx](https://github.com/searchspring/snap/tree/main/packages/snap-store-mobx)
15
+
16
+ <a href="https://www.npmjs.com/package/@searchspring/snap-url-manager"><img alt="NPM Status" src="https://img.shields.io/npm/v/@searchspring/snap-url-manager.svg?style=flat"></a> [@searchspring/snap-url-manager](https://github.com/searchspring/snap/tree/main/packages/snap-url-manager)
17
+
18
+ <a href="https://www.npmjs.com/package/@searchspring/snap-event-manager"><img alt="NPM Status" src="https://img.shields.io/npm/v/@searchspring/snap-event-manager.svg?style=flat"></a> [@searchspring/snap-event-manager](https://github.com/searchspring/snap/tree/main/packages/snap-event-manager)
19
+
20
+ <a href="https://www.npmjs.com/package/@searchspring/snap-profiler"><img alt="NPM Status" src="https://img.shields.io/npm/v/@searchspring/snap-profiler.svg?style=flat"></a> [@searchspring/snap-profiler](https://github.com/searchspring/snap/tree/main/packages/snap-profiler)
21
+
22
+ <a href="https://www.npmjs.com/package/@searchspring/snap-logger"><img alt="NPM Status" src="https://img.shields.io/npm/v/@searchspring/snap-logger.svg?style=flat"></a> [@searchspring/snap-logger](https://github.com/searchspring/snap/tree/main/packages/snap-logger)
23
+
24
+ ## Installation
25
+
26
+ To install the `snap-controller` package and it's services:
27
+
28
+ ```bash
29
+ npm install --save @searchspring/snap-controller @searchspring/snap-client @searchspring/snap-store-mobx @searchspring/snap-url-manager @searchspring/snap-event-manager @searchspring/snap-profiler @searchspring/snap-logger
30
+ ```
31
+
32
+
33
+ ## Instantiation
34
+ Each `Controller` must be passed a configuration object as the first parameter to the constructor, and a services object (dependencies) as the second. The contents of these objects will depend on which type of `Controller` is being instantiated. For example, a `SearchController` would usually be paired with a `SearchStore` service, and would take a `SearchControllerConfig` configuration object.
35
+
36
+ The complete example below shows how a `SearchController` could be instatiated, initialized and searched:
37
+
38
+ ```typescript
39
+ import { Client } from '@searchspring/snap-client';
40
+ import { SearchStore } from '@searchspring/snap-store-mobx';
41
+ import { UrlManager, UrlTranslator } from '@searchspring/snap-url-manager';
42
+ import { EventManager } from '@searchspring/snap-event-manager';
43
+ import { Profiler } from '@searchspring/snap-profiler';
44
+ import { Logger } from '@searchspring/snap-logger';
45
+ import { Tracker } from '@searchspring/snap-tracker';
46
+ import { SearchController } from '@searchspring/snap-controller';
47
+
48
+ const configuration = {
49
+ id: 'search'
50
+ };
51
+
52
+ const urlManager = new UrlManager(new UrlTranslator());
53
+ const services = {
54
+ client: new Client({ siteId: 'abc123' }),
55
+ store: new SearchStore(configuration, { urlManager }),
56
+ urlManager,
57
+ eventManager: new EventManager(),
58
+ profiler: new Profiler(),
59
+ logger: new Logger(),
60
+ tracker: new Tracker(),
61
+ }
62
+
63
+ const controller = new SearchController(configuration, services);
64
+ controller.init();
65
+ controller.search();
66
+ ```
67
+
68
+ ## Configuration
69
+ The configuration object provided during instantiation provides a way of configuring the controller for different behavior. Each controller type (`SearchController`, `AutocompleteController`, `FinderController`, etc...) has default configurations that can be modified with the instantiation configuration object. At minimum an `id` attribute is required for identifying controllers. The `id` should be unique to each *instance* of a controller.
70
+ ## Services
71
+ Along with a configuration, each controller is passed a collection of services during instantiation. These services are then used by the controller and made available via controller methods. Sometimes controllers might share a reference to a service (the `client` service for example), but in most cases a controller will have it's own instance of a service. Some services (like the `SearchStore`) share services with the controller (in the example above, the `UrlManager` is shared).
72
+
73
+ ```typescript
74
+ { client, store, urlManager, eventManager, profiler, logger }
75
+ ```
76
+ ### client
77
+ The `client` service makes the requests to the API when the controller `search` method is called. The response is passed onto the `store` service. This service is exposed as `controller.client`.
78
+
79
+ ### store
80
+ This service mutates the API responses and adds convenience functions for common functionality. The `store` data is then used by the UI components for display. This service is exposed as `controller.store`.
81
+ ### urlManager
82
+ `urlManager` is responsible for updating the page URL when interacting with UI components. The type of translator passed into the `UrlManager` constructor will determine the types of URLs generated. This service is exposed as `controller.urlManager`.
83
+ ### eventManager
84
+ Middleware provide an opportunity to hook into these events they occur. Middleware are attached to events, and these events are managed by the `eventManager`. This service is exposed as `controller.eventManager`.
85
+
86
+ ### profiler
87
+ Controllers may need to know how long a certain event took, the `profiler` service provides the means to track this information. This service is exposed as `controller.profiler`.
88
+
89
+ ### logger
90
+ The `logger` service provides logging functionality to a controller. Each controller logs when errors in middleware and when controller events occur. The logger is responsible for sending this information to the developer console. In addition the logger may provide additional emoji or colors to use. This service is exposed as `controller.log`.
91
+
92
+ ## Initialization
93
+ Invoking the `init` method is required to subscribe to changes that occur in the UrlManager. It also fires the `init` event which executes attached middleware. This can be fired manually as needed; if it was not manually fired it will happen automatically on the first call to the controller `search` method.
94
+
95
+ ```typescript
96
+ controller.init();
97
+ ```
98
+
99
+ ## Searching
100
+ The `search` method of a controller will run the search that is expected by leveraging the `client` service to make the request; the subsequent response will be passed to the `store` service.
101
+
102
+ Most controllers will provide a means of manipulating the request and response using `beforeSearch` and `afterSearch` events respectively. Read on for details about events.
103
+
104
+ ```typescript
105
+ controller.search();
106
+ ```
107
+
108
+ ## Stores
109
+ Different controller types will utilize different Snap Stores (typically of the same name). Each `store` will provide different properties and methods for its unique purposes. See the documentation for more details.
110
+
111
+ ## Events
112
+ Each controller will fire various events. Some of the event names are shared between controllers for consistency (ex: `beforeSearch`, `afterSearch`, `afterStore`); however the attaching of middleware and execution of it must remain separate. This is why a new `EventManager` instance is created for each controller. Middleware are attached to events via the `on` method and the functions should almost always end with `await next()` unless purposefully preventing the next attached middleware from executing.
113
+
114
+ ```typescript
115
+ controller.on('init', async (eventData, next) => {
116
+ const { controller } = eventData;
117
+
118
+ controller.log.debug('init event has occurred');
119
+
120
+ await next();
121
+ });
122
+ ```
123
+
124
+ Note: Groups of middleware (plugins) can be attached using the `plugin` method.
125
+
126
+ The data available within a middleware (first parameter) is determined by what gets passed into the `fire` method. For existing events on the controller, the `fire` method is already being called when appropriate to the event, and the `eventData` will typically be an object containing a reference to the controller and any other details that may be of importance to the particular event. Custom events can be created as needed; but keep in mind that any middleware tied to the event should be bound (using `on` or `plugin`) prior to the execution of the `fire` method.
127
+
128
+ ```typescript
129
+ controller.eventManager.fire('customEventName', { thing1: 'one', thing2: 2 });
130
+ ```
131
+
132
+ See the EventManager documentation for more details.
133
+
134
+ ## Environment
135
+ A controller's environment is initialized at build time, and is used to control certain runtime behavior. For example, a `production` build will supress most logs while a `development` build will show them all.
136
+ ## Logging
137
+ The logger provides a clear way of outputting details like profile data or errors to the developer console. A `production` build will supress most logs while a `development` build will show them all. The environment is automatically determined, but can be toggled during runtime by setting it to either `development` or `production`.
138
+
139
+ ```typescript
140
+ controller.environment = 'development';
141
+ ```
142
+
143
+ The use of `console.log()` is discouraged. Logging should be done via controller instance to help debug and navigate the sea of console logs. Each controller will output the `id` for easily deciphering which controller made the log.
144
+
145
+ ```typescript
146
+ controller.log.warn('THIS IS A WARNING!');
147
+ ```
148
+
149
+ Many logs are supressed depending on a development `environment` of the controller instance. The Logger documentation provides more details about the various methods, colors and emoji available.
150
+
151
+ ## Controller Types
152
+ Each `Controller` has a unique configuration and set of default events; it may also provide additional methods for specific functionality.
153
+
154
+ ### Abstract
155
+ The base class for all controllers.
156
+
157
+ ### Autocomplete
158
+ Used for autocomplete searches.
159
+
160
+ ### Finder
161
+ A specialized controller used for building custom product finders.
162
+
163
+ ### Recommendation
164
+ The standard controller used for recommendation profiles.
165
+
166
+ ### Search
167
+ The standard controller used on search pages and PLPs.
@@ -0,0 +1,40 @@
1
+ import { LogMode } from '@searchspring/snap-logger';
2
+ import { DomTargeter } from '@searchspring/snap-toolbox';
3
+ import type { AbstractStore } from '@searchspring/snap-store-mobx';
4
+ import type { UrlManager } from '@searchspring/snap-url-manager';
5
+ import type { EventManager, Middleware } from '@searchspring/snap-event-manager';
6
+ import type { Profiler } from '@searchspring/snap-profiler';
7
+ import type { Logger } from '@searchspring/snap-logger';
8
+ import type { Tracker } from '@searchspring/snap-tracker';
9
+ import type { Target, OnTarget } from '@searchspring/snap-toolbox';
10
+ import type { ControllerServices, ControllerConfig, Attachments } from '../types';
11
+ export declare abstract class AbstractController {
12
+ id: string;
13
+ type: string;
14
+ config: ControllerConfig;
15
+ client: any;
16
+ store: AbstractStore;
17
+ urlManager: UrlManager;
18
+ eventManager: EventManager;
19
+ profiler: Profiler;
20
+ log: Logger;
21
+ tracker: Tracker;
22
+ targeters: {
23
+ [key: string]: DomTargeter;
24
+ };
25
+ private _initialized;
26
+ private _environment;
27
+ get initialized(): boolean;
28
+ constructor(config: ControllerConfig, { client, store, urlManager, eventManager, profiler, logger, tracker }: ControllerServices);
29
+ createTargeter(target: Target, onTarget: OnTarget, document?: Document): DomTargeter;
30
+ addTargeter(target: DomTargeter): DomTargeter;
31
+ set environment(env: LogMode);
32
+ get environment(): LogMode;
33
+ init(): Promise<void>;
34
+ retarget(): void;
35
+ abstract search(): Promise<void>;
36
+ plugin(func: (cntrlr: AbstractController, ...args: any[]) => Promise<void>, ...args: unknown[]): Promise<void>;
37
+ on<T>(event: string, ...func: Middleware<T>[]): void;
38
+ use(attachments: Attachments): void;
39
+ }
40
+ //# sourceMappingURL=AbstractController.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AbstractController.d.ts","sourceRoot":"","sources":["../../../src/Abstract/AbstractController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAE,WAAW,EAAgB,MAAM,4BAA4B,CAAC;AAGvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGlF,8BAAsB,kBAAkB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,SAAc;IAClB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,MAAC;IACP,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE;QACjB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;KAC3B,CAAM;IAEP,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAsB;IAE1C,IAAI,WAAW,IAAI,OAAO,CAEzB;gBAEW,MAAM,EAAE,gBAAgB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB;IAyEzH,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,WAAW;IAIpF,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW;IASpD,IAAW,WAAW,CAAC,GAAG,EAAE,OAAO,EAKlC;IAED,IAAW,WAAW,IAAI,OAAO,CAEhC;IAEY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA+C3B,QAAQ,IAAI,IAAI;aAMP,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAE1B,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,IAAI,OAAA,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7G,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI;IAIpD,GAAG,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;CAoC1C"}
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (_) try {
18
+ 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;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
39
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
40
+ if (ar || !(i in from)) {
41
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
42
+ ar[i] = from[i];
43
+ }
44
+ }
45
+ return to.concat(ar || Array.prototype.slice.call(from));
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.AbstractController = void 0;
49
+ var snap_logger_1 = require("@searchspring/snap-logger");
50
+ var snap_toolbox_1 = require("@searchspring/snap-toolbox");
51
+ var SS_DEV_COOKIE = 'ssDev';
52
+ var AbstractController = /** @class */ (function () {
53
+ function AbstractController(config, _a) {
54
+ var client = _a.client, store = _a.store, urlManager = _a.urlManager, eventManager = _a.eventManager, profiler = _a.profiler, logger = _a.logger, tracker = _a.tracker;
55
+ var _b, _c, _d;
56
+ this.type = 'abstract';
57
+ this.targeters = {};
58
+ this._initialized = false;
59
+ this._environment = snap_logger_1.LogMode.PRODUCTION;
60
+ if (typeof config != 'object' || typeof config.id != 'string' || !config.id.match(/^[a-zA-Z0-9_-]*$/)) {
61
+ throw new Error("Invalid config passed to controller. The \"id\" attribute must be an alphanumeric string.");
62
+ }
63
+ if (typeof client != 'object' || typeof client.search != 'function') {
64
+ throw new Error("Invalid service 'client' passed to controller. Missing \"search\" function.");
65
+ }
66
+ if (typeof store != 'object' || typeof store.update != 'function') {
67
+ throw new Error("Invalid service 'store' passed to controller. Missing \"update\" function.");
68
+ }
69
+ if (typeof urlManager != 'object' || typeof urlManager.subscribe != 'function') {
70
+ throw new Error("Invalid service 'urlManager' passed to controller. Missing \"subscribe\" function.");
71
+ }
72
+ if (typeof eventManager != 'object' || typeof eventManager.on != 'function') {
73
+ throw new Error("Invalid service 'eventManager' passed to controller. Missing \"on\" function.");
74
+ }
75
+ if (typeof eventManager != 'object' || typeof eventManager.fire != 'function') {
76
+ throw new Error("Invalid service 'eventManager' passed to controller. Missing \"fire\" function.");
77
+ }
78
+ if (typeof profiler != 'object' || typeof profiler.setNamespace != 'function') {
79
+ throw new Error("Invalid service 'profiler' passed to controller. Missing \"setNamespace\" function.");
80
+ }
81
+ if (typeof profiler != 'object' || typeof profiler.create != 'function') {
82
+ throw new Error("Invalid service 'profiler' passed to controller. Missing \"create\" function.");
83
+ }
84
+ if (typeof logger != 'object' || typeof logger.dev != 'function') {
85
+ throw new Error("Invalid service 'logger' passed to controller. Missing \"dev\" function.");
86
+ }
87
+ if (typeof tracker != 'object' || typeof tracker.track != 'object') {
88
+ throw new Error("Invalid service 'tracker' passed to controller. Missing \"track\" object.");
89
+ }
90
+ window.searchspring = window.searchspring || {};
91
+ window.searchspring.controller = window.searchspring.controller || {};
92
+ if (window.searchspring.controller[config.id]) {
93
+ throw new Error("Controller with id '".concat(config.id, "' is already defined"));
94
+ }
95
+ window.searchspring.controller[config.id] = this;
96
+ this.id = config.id;
97
+ this.config = config;
98
+ this.client = client;
99
+ this.store = store;
100
+ this.urlManager = urlManager;
101
+ this.eventManager = eventManager;
102
+ this.profiler = profiler;
103
+ this.log = logger;
104
+ this.tracker = tracker;
105
+ // configure the logger
106
+ this.log.setNamespace(this.config.id);
107
+ // set namespaces
108
+ this.profiler.setNamespace(this.config.id);
109
+ // set environment
110
+ if ((_d = (_c = (_b = (0, snap_toolbox_1.url)(window.location.href)) === null || _b === void 0 ? void 0 : _b.params) === null || _c === void 0 ? void 0 : _c.query) === null || _d === void 0 ? void 0 : _d.dev) {
111
+ snap_toolbox_1.cookies.set(SS_DEV_COOKIE, '1', 'Lax', 0);
112
+ }
113
+ var dev = snap_toolbox_1.cookies.get(SS_DEV_COOKIE);
114
+ this.environment = (dev === '1' ? 'development' : process.env.NODE_ENV);
115
+ }
116
+ Object.defineProperty(AbstractController.prototype, "initialized", {
117
+ get: function () {
118
+ return this._initialized;
119
+ },
120
+ enumerable: false,
121
+ configurable: true
122
+ });
123
+ AbstractController.prototype.createTargeter = function (target, onTarget, document) {
124
+ return this.addTargeter(new snap_toolbox_1.DomTargeter([target], onTarget, document));
125
+ };
126
+ AbstractController.prototype.addTargeter = function (target) {
127
+ var _a;
128
+ var firstTarget = target.getTargets()[0];
129
+ var targetName = (_a = firstTarget === null || firstTarget === void 0 ? void 0 : firstTarget.name) !== null && _a !== void 0 ? _a : firstTarget === null || firstTarget === void 0 ? void 0 : firstTarget.selector;
130
+ if (targetName && !this.targeters[targetName]) {
131
+ this.targeters[targetName] = target;
132
+ return target;
133
+ }
134
+ };
135
+ Object.defineProperty(AbstractController.prototype, "environment", {
136
+ get: function () {
137
+ return this._environment;
138
+ },
139
+ set: function (env) {
140
+ if (Object.values(snap_logger_1.LogMode).includes(env)) {
141
+ this._environment = env;
142
+ this.log.setMode(env);
143
+ }
144
+ },
145
+ enumerable: false,
146
+ configurable: true
147
+ });
148
+ AbstractController.prototype.init = function () {
149
+ return __awaiter(this, void 0, void 0, function () {
150
+ var initProfile, err_1, err_2;
151
+ var _this = this;
152
+ return __generator(this, function (_a) {
153
+ switch (_a.label) {
154
+ case 0:
155
+ if (this._initialized) {
156
+ this.log.warn("'init' middleware recalled");
157
+ }
158
+ initProfile = this.profiler.create({ type: 'event', name: 'init', context: this.config }).start();
159
+ _a.label = 1;
160
+ case 1:
161
+ _a.trys.push([1, 6, , 7]);
162
+ _a.label = 2;
163
+ case 2:
164
+ _a.trys.push([2, 4, , 5]);
165
+ return [4 /*yield*/, this.eventManager.fire('init', {
166
+ controller: this,
167
+ })];
168
+ case 3:
169
+ _a.sent();
170
+ return [3 /*break*/, 5];
171
+ case 4:
172
+ err_1 = _a.sent();
173
+ if ((err_1 === null || err_1 === void 0 ? void 0 : err_1.message) == 'cancelled') {
174
+ this.log.warn("'init' middleware cancelled");
175
+ }
176
+ else {
177
+ this.log.error("error in 'init' middleware");
178
+ throw err_1;
179
+ }
180
+ return [3 /*break*/, 5];
181
+ case 5: return [3 /*break*/, 7];
182
+ case 6:
183
+ err_2 = _a.sent();
184
+ if (err_2) {
185
+ console.error(err_2);
186
+ }
187
+ return [3 /*break*/, 7];
188
+ case 7:
189
+ if (!this._initialized) {
190
+ // subscribe to urlManager changes
191
+ this.urlManager.subscribe(function (prev, next) {
192
+ try {
193
+ var prevString = JSON.stringify(prev);
194
+ var nextString = JSON.stringify(next);
195
+ if (prevString !== nextString) {
196
+ _this.search();
197
+ }
198
+ }
199
+ catch (err) {
200
+ _this.log.error('URL state is invalid', err);
201
+ }
202
+ });
203
+ this._initialized = true;
204
+ }
205
+ initProfile.stop();
206
+ this.log.profile(initProfile);
207
+ return [2 /*return*/];
208
+ }
209
+ });
210
+ });
211
+ };
212
+ AbstractController.prototype.retarget = function () {
213
+ var _this = this;
214
+ Object.keys(this.targeters).forEach(function (target) {
215
+ _this.targeters[target].retarget();
216
+ });
217
+ };
218
+ AbstractController.prototype.plugin = function (func) {
219
+ var args = [];
220
+ for (var _i = 1; _i < arguments.length; _i++) {
221
+ args[_i - 1] = arguments[_i];
222
+ }
223
+ return __awaiter(this, void 0, void 0, function () {
224
+ return __generator(this, function (_a) {
225
+ switch (_a.label) {
226
+ case 0: return [4 /*yield*/, func.apply(void 0, __spreadArray([this], args, false))];
227
+ case 1:
228
+ _a.sent();
229
+ return [2 /*return*/];
230
+ }
231
+ });
232
+ });
233
+ };
234
+ AbstractController.prototype.on = function (event) {
235
+ var _a;
236
+ var func = [];
237
+ for (var _i = 1; _i < arguments.length; _i++) {
238
+ func[_i - 1] = arguments[_i];
239
+ }
240
+ (_a = this.eventManager).on.apply(_a, __spreadArray([event], func, false));
241
+ };
242
+ AbstractController.prototype.use = function (attachments) {
243
+ var _this = this;
244
+ // attach plugins
245
+ if (attachments === null || attachments === void 0 ? void 0 : attachments.plugins) {
246
+ try {
247
+ if (!Array.isArray(attachments === null || attachments === void 0 ? void 0 : attachments.plugins)) {
248
+ throw 'invalid format';
249
+ }
250
+ attachments === null || attachments === void 0 ? void 0 : attachments.plugins.forEach(function (plugin) {
251
+ if (!Array.isArray(plugin)) {
252
+ throw 'invalid format';
253
+ }
254
+ var func = plugin[0], args = plugin.slice(1);
255
+ _this.plugin.apply(_this, __spreadArray([func], args, false));
256
+ });
257
+ }
258
+ catch (err) {
259
+ this.log.warn('plugins not attached - use format [func, ...args?][]');
260
+ }
261
+ }
262
+ // attach event middleware
263
+ if (attachments === null || attachments === void 0 ? void 0 : attachments.middleware) {
264
+ Object.keys(attachments.middleware).forEach(function (eventName) {
265
+ var eventMiddleware = attachments.middleware[eventName];
266
+ var middlewareArray;
267
+ if (Array.isArray(eventMiddleware)) {
268
+ middlewareArray = eventMiddleware;
269
+ }
270
+ else {
271
+ middlewareArray = [eventMiddleware];
272
+ }
273
+ middlewareArray.forEach(function (middleware) {
274
+ _this.on(eventName, middleware);
275
+ });
276
+ });
277
+ }
278
+ };
279
+ return AbstractController;
280
+ }());
281
+ exports.AbstractController = AbstractController;
@@ -0,0 +1,40 @@
1
+ import { StorageStore } from '@searchspring/snap-store-mobx';
2
+ import { AbstractController } from '../Abstract/AbstractController';
3
+ import type { AutocompleteStore } from '@searchspring/snap-store-mobx';
4
+ import type { AutocompleteControllerConfig, ControllerServices } from '../types';
5
+ import type { AutocompleteRequestModel } from '@searchspring/snapi-types';
6
+ declare type AutocompleteTrackMethods = {
7
+ product: {
8
+ click: (e: any, result: any) => void;
9
+ };
10
+ };
11
+ export declare class AutocompleteController extends AbstractController {
12
+ type: string;
13
+ store: AutocompleteStore;
14
+ config: AutocompleteControllerConfig;
15
+ storage: StorageStore;
16
+ constructor(config: AutocompleteControllerConfig, { client, store, urlManager, eventManager, profiler, logger, tracker }: ControllerServices);
17
+ track: AutocompleteTrackMethods;
18
+ get params(): AutocompleteRequestModel;
19
+ setFocused(inputElement?: HTMLInputElement): Promise<void>;
20
+ reset(): void;
21
+ handlers: {
22
+ input: {
23
+ enterKey: (e: KeyboardEvent) => Promise<void>;
24
+ escKey: (e: KeyboardEvent) => void;
25
+ focus: (e: FocusEvent) => void;
26
+ formSubmit: (e: any) => Promise<void>;
27
+ keyUp: (e: KeyboardEvent) => void;
28
+ timeoutDelay: any;
29
+ };
30
+ document: {
31
+ click: (e: MouseEvent) => void;
32
+ };
33
+ };
34
+ unbind(): void;
35
+ bind(): Promise<void>;
36
+ searchTrending: () => Promise<void>;
37
+ search: () => Promise<void>;
38
+ }
39
+ export {};
40
+ //# sourceMappingURL=AutocompleteController.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutocompleteController.d.ts","sourceRoot":"","sources":["../../../src/Autocomplete/AutocompleteController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAA0B,MAAM,+BAA+B,CAAC;AAErF,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,4BAA4B,EAAkD,kBAAkB,EAAa,MAAM,UAAU,CAAC;AAC5I,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAuB1E,aAAK,wBAAwB,GAAG;IAC/B,OAAO,EAAE;QACR,KAAK,EAAE,CAAC,CAAC,KAAA,EAAE,MAAM,KAAA,KAAK,IAAI,CAAC;KAC3B,CAAC;CACF,CAAC;AAEF,qBAAa,sBAAuB,SAAQ,kBAAkB;IACtD,IAAI,SAAkB;IACtB,KAAK,EAAE,iBAAiB,CAAC;IACzB,MAAM,EAAE,4BAA4B,CAAC;IACrC,OAAO,EAAE,YAAY,CAAC;gBAEjB,MAAM,EAAE,4BAA4B,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB;IAkD5I,KAAK,EAAE,wBAAwB,CAO7B;IAEF,IAAI,MAAM,IAAI,wBAAwB,CA+BrC;IAEK,UAAU,CAAC,YAAY,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BhE,KAAK,IAAI,IAAI;IASb,QAAQ;;0BAEc,aAAa,KAAG,QAAQ,IAAI,CAAC;wBA6CrC,aAAa,KAAG,IAAI;uBAMrB,UAAU,KAAG,IAAI;oCAQL,QAAQ,IAAI,CAAC;uBAwCzB,aAAa,KAAG,IAAI;;;;uBA0CpB,UAAU,KAAG,IAAI;;MAS5B;IAEF,MAAM,IAAI,IAAI;IAYR,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAgE3B,cAAc,QAAa,QAAQ,IAAI,CAAC,CAsBtC;IAEF,MAAM,QAAa,QAAQ,IAAI,CAAC,CA6G9B;CACF"}