@miso.ai/client-sdk-core 1.5.1 → 1.6.0-beta.2

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 (50) hide show
  1. package/dist/cjs/api/base.js +1 -15
  2. package/dist/cjs/api/helpers.js +2 -31
  3. package/dist/cjs/api/index.js +0 -9
  4. package/dist/cjs/api/interactions.js +7 -24
  5. package/dist/cjs/api/recommendation.js +0 -11
  6. package/dist/cjs/api/search.js +0 -8
  7. package/dist/cjs/classes.js +0 -9
  8. package/dist/cjs/client.js +0 -21
  9. package/dist/cjs/cmd.js +4 -8
  10. package/dist/cjs/context.js +0 -4
  11. package/dist/cjs/index.js +4 -8
  12. package/dist/cjs/plugin/anonymous.js +0 -4
  13. package/dist/cjs/plugin/auto-events.js +0 -28
  14. package/dist/cjs/plugin/index.js +0 -12
  15. package/dist/cjs/plugin/page-info.js +0 -12
  16. package/dist/cjs/plugin/plugin-root.js +7 -55
  17. package/dist/cjs/plugin/user.js +0 -26
  18. package/dist/cjs/root.js +4 -13
  19. package/dist/cjs/utils.js +7 -37
  20. package/dist/cjs/version.js +1 -1
  21. package/dist/es/api/base.js +1 -12
  22. package/dist/es/api/helpers.js +2 -27
  23. package/dist/es/api/index.js +0 -1
  24. package/dist/es/api/interactions.js +7 -20
  25. package/dist/es/api/recommendation.js +0 -7
  26. package/dist/es/api/search.js +0 -4
  27. package/dist/es/client.js +0 -13
  28. package/dist/es/cmd.js +4 -7
  29. package/dist/es/context.js +0 -1
  30. package/dist/es/index.js +4 -4
  31. package/dist/es/plugin/anonymous.js +0 -1
  32. package/dist/es/plugin/auto-events.js +0 -24
  33. package/dist/es/plugin/index.js +1 -2
  34. package/dist/es/plugin/page-info.js +0 -8
  35. package/dist/es/plugin/plugin-root.js +7 -48
  36. package/dist/es/plugin/user.js +0 -22
  37. package/dist/es/root.js +5 -7
  38. package/dist/es/utils.js +1 -34
  39. package/dist/es/version.js +1 -1
  40. package/package.json +2 -2
  41. package/dist/cjs/plugin/units/constants.js +0 -10
  42. package/dist/cjs/plugin/units/index.js +0 -41
  43. package/dist/cjs/plugin/units/tracker.js +0 -365
  44. package/dist/cjs/plugin/units/unit.js +0 -63
  45. package/dist/cjs/plugin/units/units.js +0 -70
  46. package/dist/es/plugin/units/constants.js +0 -2
  47. package/dist/es/plugin/units/index.js +0 -27
  48. package/dist/es/plugin/units/tracker.js +0 -353
  49. package/dist/es/plugin/units/unit.js +0 -50
  50. package/dist/es/plugin/units/units.js +0 -56
@@ -1,365 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
-
8
- var _commons = require("@miso.ai/commons");
9
-
10
- var _constants = require("./constants");
11
-
12
- var _utils = require("../../utils");
13
-
14
- const _excluded = ["impression", "viewable", "click"];
15
-
16
- function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
17
-
18
- function mergeOptions(def, opt) {
19
- // if opt is falsy then return false, merge otherwise
20
- return !!opt && Object.assign({}, def, opt);
21
- }
22
-
23
- const DEFAULT_TRACKING_OPTIONS = {
24
- watchElements: false,
25
- viewable: {
26
- area: 0.5,
27
- duration: 1000
28
- },
29
- click: {
30
- lenient: false
31
- }
32
- };
33
- const STATE = {
34
- INITIAL: 0,
35
- TRACKING: 1,
36
- TRIGGERED: 2
37
- };
38
-
39
- class Tracker {
40
- constructor(unit) {
41
- this._unit = unit;
42
- this._eventStates = new Map();
43
- this._sentEvents = {
44
- impression: new Set(),
45
- viewable: new Set(),
46
- click: new Set()
47
- };
48
- this._handleClick = this._handleClick.bind(this);
49
- }
50
-
51
- start(options) {
52
- const root = this._unit.element;
53
-
54
- if (!root) {
55
- throw new Error(`The unit has no bound element. Call unit.bind(element) to associated the unit to an element.`);
56
- }
57
-
58
- if (this._options) {
59
- // throw, for the options could be different and this won't be idempotent
60
- throw new Error(`Already tracking events.`);
61
- } // settle tracking options
62
-
63
-
64
- this._options = this._normalizeOptions(options);
65
-
66
- this._watchElements();
67
-
68
- this._trackClicks();
69
-
70
- this.sync();
71
- }
72
-
73
- sync() {
74
- const {
75
- impression,
76
- viewable
77
- } = this._options;
78
-
79
- if (!impression && !viewable) {
80
- return;
81
- } // scan all descendants for product item elements
82
-
83
-
84
- const elements = this._unit.element.querySelectorAll(`[${_constants.ATTR_PRODUCT_ID}]`);
85
-
86
- this._trackImpressions(elements);
87
-
88
- this._trackViewables(elements);
89
- }
90
-
91
- interceptEventPayload(callback) {
92
- this._eventPayloadPass = callback;
93
- }
94
-
95
- impression(productIds) {
96
- this._sendEvent('impression', productIds, true);
97
- }
98
-
99
- viewable(productIds) {
100
- this._sendEvent('viewable', productIds, true);
101
- }
102
-
103
- click(productIds) {
104
- this._sendEvent('click', productIds, true);
105
- }
106
-
107
- _normalizeOptions() {
108
- let _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
109
-
110
- let {
111
- impression = {},
112
- viewable = {},
113
- click = {}
114
- } = _ref,
115
- options = _objectWithoutPropertiesLoose(_ref, _excluded);
116
-
117
- return (0, _commons.trimObj)(Object.assign({}, DEFAULT_TRACKING_OPTIONS, options, {
118
- impression: mergeOptions(DEFAULT_TRACKING_OPTIONS.impression, impression),
119
- viewable: mergeOptions(DEFAULT_TRACKING_OPTIONS.viewable, viewable),
120
- click: mergeOptions(DEFAULT_TRACKING_OPTIONS.click, click)
121
- }));
122
- }
123
-
124
- _watchElements() {
125
- const {
126
- watchElements,
127
- impression,
128
- viewable
129
- } = this._options;
130
-
131
- if (!watchElements || !impression && !viewable) {
132
- return;
133
- }
134
-
135
- const observer = this._mutationObserver = new MutationObserver(mutations => {
136
- let hasAddedElements = false;
137
- let removedElements = [];
138
-
139
- for (const {
140
- addedNodes,
141
- removedNodes
142
- } of mutations) {
143
- hasAddedElements = hasAddedElements || addedNodes.length > 0;
144
- addedElements = [...addedElements, ...addedNodes];
145
- removedElements = [...removedElements, ...removedNodes];
146
- }
147
-
148
- if (hasAddedElements) {
149
- this.sync();
150
- }
151
-
152
- this._untrackViewables(removedElements);
153
- });
154
- observer.observe(this._element, {
155
- childList: true,
156
- subtree: true
157
- });
158
- }
159
-
160
- _unwatchElements() {
161
- this._mutationObserver && this._mutationObserver.disconnect();
162
- }
163
-
164
- _trackImpressions(elements) {
165
- const options = this._options.impression;
166
-
167
- if (!options) {
168
- return;
169
- }
170
-
171
- const productIds = [];
172
-
173
- for (const element of elements) {
174
- const productId = element.getAttribute(_constants.ATTR_PRODUCT_ID);
175
-
176
- if (!productId) {
177
- continue;
178
- }
179
-
180
- const state = this._getEventState(productId);
181
-
182
- if (state.impression !== STATE.TRIGGERED) {
183
- state.impression = STATE.TRIGGERED;
184
- productIds.push(productId);
185
- }
186
- }
187
-
188
- this._sendEvent('impression', productIds);
189
- }
190
-
191
- _trackViewables(elements) {
192
- const options = this._options.viewable;
193
-
194
- if (!options) {
195
- return;
196
- }
197
-
198
- for (const element of elements) {
199
- this._trackViewableOnElement(element);
200
- }
201
- }
202
-
203
- async _trackViewableOnElement(element) {
204
- if (!(0, _commons.isElement)(element)) {
205
- return;
206
- }
207
-
208
- const productId = element.getAttribute(_constants.ATTR_PRODUCT_ID);
209
-
210
- if (!productId) {
211
- return;
212
- } // TODO: when element is replaced without proper unload...
213
-
214
-
215
- const state = this._getEventState(productId);
216
-
217
- if (state.viewable !== STATE.INITIAL) {
218
- return;
219
- }
220
-
221
- state.viewable = STATE.TRACKING;
222
- const {
223
- area,
224
- duration
225
- } = this._options.viewable;
226
- await (0, _utils.viewable)(element, {
227
- area,
228
- duration
229
- });
230
- state.viewable = STATE.TRIGGERED;
231
-
232
- this._sendEvent('viewable', [productId]);
233
- }
234
-
235
- _untrackAllViewables() {// TODO
236
- }
237
-
238
- _untrackViewables(elements) {// we need to scan through all descendants to scavenge detached product items
239
- // TODO
240
- }
241
-
242
- _trackClicks() {
243
- this._unit.element.addEventListener('click', this._handleClick);
244
- }
245
-
246
- _untrackClicks() {
247
- this._unit.element.removeEventListener('click', this._handleClick);
248
- }
249
-
250
- _destroy() {
251
- this._unwatchElements();
252
-
253
- this._untrackClicks();
254
- }
255
-
256
- _getEventState(productId) {
257
- let state = this._eventStates.get(productId);
258
-
259
- if (!state) {
260
- this._eventStates.set(productId, state = {
261
- impression: STATE.INITIAL,
262
- viewable: STATE.INITIAL,
263
- click: STATE.INITIAL
264
- });
265
- }
266
-
267
- return state;
268
- }
269
-
270
- _handleClick(event) {
271
- const options = this._options && this._options.click;
272
-
273
- if (!options) {
274
- return;
275
- }
276
-
277
- let productId;
278
-
279
- for (let element = event.target; !productId && element && element !== document; element = element.parentElement) {
280
- productId = element.getAttribute(_constants.ATTR_PRODUCT_ID);
281
- }
282
-
283
- if (!productId) {
284
- return;
285
- }
286
-
287
- const state = this._getEventState(productId);
288
-
289
- if (state.click === STATE.TRIGGERED) {
290
- return;
291
- }
292
-
293
- if (!options.lenient) {// only left click counts
294
- // event isPreventDefault
295
- // go through a real link
296
- // TODO
297
- }
298
-
299
- state.click = STATE.TRIGGERED;
300
-
301
- this._sendEvent('click', [productId]);
302
- }
303
-
304
- _sendEvent(type, productIds, manual) {
305
- if (type !== 'impression' && type !== 'viewable' && type !== 'click') {
306
- throw new Error(`Unrecognized event type: ${type}`);
307
- }
308
-
309
- productIds = (0, _commons.asArray)(productIds); // dedupe
310
-
311
- const sentEvents = this._sentEvents[type];
312
- productIds = productIds.filter(id => {
313
- const sent = sentEvents.has(id);
314
-
315
- if (!sent) {
316
- sentEvents.add(id);
317
- }
318
-
319
- return !sent;
320
- });
321
-
322
- if (productIds.length === 0) {
323
- return;
324
- } // TODO: emit
325
- // we want to queue the event for a while so we can merge them and save requests
326
- // TODO
327
-
328
-
329
- const client = this._unit._context._client;
330
-
331
- const payloads = this._buildPayloads(type, productIds, manual);
332
-
333
- if (payloads.length > 0) {
334
- client.api.interactions.upload(payloads);
335
- }
336
- }
337
-
338
- _buildPayloads(type, productIds, manual) {
339
- const {
340
- id,
341
- uuid
342
- } = this._unit;
343
- let payload = {
344
- type: type === 'viewable' ? 'viewable_impression' : type,
345
- product_ids: productIds,
346
- context: {
347
- custom_context: {
348
- unit_id: id,
349
- unit_instance_uuid: uuid,
350
- trigger: manual ? 'manual' : 'auto'
351
- }
352
- }
353
- };
354
-
355
- if (this._eventPayloadPass) {
356
- // TODO: handle error
357
- payload = this._eventPayloadPass(payload);
358
- }
359
-
360
- return (0, _commons.asArray)(payload);
361
- }
362
-
363
- }
364
-
365
- exports.default = Tracker;
@@ -1,63 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
-
8
- var _commons = require("@miso.ai/commons");
9
-
10
- var _tracker = _interopRequireDefault(require("./tracker"));
11
-
12
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
-
14
- class Unit {
15
- constructor(context, id) {
16
- this._context = context;
17
- Object.defineProperties(this, {
18
- uuid: {
19
- value: (0, _commons.uuidv4)()
20
- },
21
- id: {
22
- value: id
23
- }
24
- });
25
-
26
- context._units.set(id, this);
27
- }
28
-
29
- get element() {
30
- return this._element;
31
- }
32
-
33
- get tracker() {
34
- return this._tracker || (this._tracker = new _tracker.default(this));
35
- }
36
-
37
- bind(element) {
38
- if (this._element === element) {
39
- return;
40
- } else if (this._element) {
41
- throw new Error(`Element has already been set.`);
42
- }
43
-
44
- this._element = element;
45
-
46
- this._context._e2u.set(element, this);
47
-
48
- return this;
49
- }
50
-
51
- destroy() {
52
- this._tracker && this._tracker._destroy();
53
-
54
- this._context._e2u.delete(this._element);
55
-
56
- this._context._units.delete(this.id);
57
-
58
- this._element = undefined;
59
- }
60
-
61
- }
62
-
63
- exports.default = Unit;
@@ -1,70 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
-
8
- var _commons = require("@miso.ai/commons");
9
-
10
- var _constants = require("./constants");
11
-
12
- var _unit = _interopRequireDefault(require("./unit"));
13
-
14
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
-
16
- class UnitsContext {
17
- constructor(plugin, client) {
18
- this._plugin = plugin;
19
- this._client = client;
20
- this._units = new Map();
21
- this._e2u = new WeakMap();
22
- this.interface = new Units(this);
23
- }
24
-
25
- list() {
26
- return [...this._units.values()];
27
- }
28
-
29
- create() {
30
- let id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'default';
31
-
32
- if (this._units.has(id)) {
33
- throw new Error(`Unit already exists: ${id}`);
34
- }
35
-
36
- return new _unit.default(this, id);
37
- }
38
-
39
- has() {
40
- let ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'default';
41
- return typeof ref === 'string' ? this._units.has(ref) : (0, _commons.isElement)(ref) && this._e2u.has(ref);
42
- }
43
-
44
- get() {
45
- let ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'default';
46
-
47
- if (typeof ref === 'string') {
48
- return this._units.get(ref) || new _unit.default(this, ref);
49
- } else if ((0, _commons.isElement)(ref)) {
50
- if (this._e2u.has(ref)) {
51
- return this._e2u.get(ref);
52
- } else {
53
- const id = ref.getAttribute(_constants.ATTR_UNIT_ID) || 'default';
54
- return new _unit.default(this, id).bind(ref);
55
- }
56
- } else {
57
- throw new Error(`Required input to be either a string unit ID or an element: ${ref}`);
58
- }
59
- }
60
-
61
- }
62
-
63
- exports.default = UnitsContext;
64
-
65
- class Units {
66
- constructor(context) {
67
- (0, _commons.delegateGetters)(this, context, ['list', 'has', 'create', 'get']);
68
- }
69
-
70
- }
@@ -1,2 +0,0 @@
1
- export const ATTR_UNIT_ID = 'data-miso-unit-id';
2
- export const ATTR_PRODUCT_ID = 'data-miso-product-id';
@@ -1,27 +0,0 @@
1
- import { Component } from '@miso.ai/commons';
2
- import UnitsContext from './units';
3
- const PLUGIN_ID = 'std:units';
4
- export default class UnitsPlugin extends Component {
5
- static get id() {
6
- return PLUGIN_ID;
7
- }
8
-
9
- constructor() {
10
- super('units');
11
- this._contexts = new WeakMap();
12
- }
13
-
14
- install(MisoClient, context) {
15
- context.addSubtree(this);
16
- MisoClient.on('create', this._injectClient.bind(this));
17
- }
18
-
19
- _injectClient(client) {
20
- const context = new UnitsContext(this, client);
21
-
22
- this._contexts.set(client, context);
23
-
24
- client.units = context.interface;
25
- }
26
-
27
- }