@miso.ai/client-sdk-core 1.5.1 → 1.6.0-beta.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.
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,6 +1,7 @@
1
1
  import { Component } from '@miso.ai/commons';
2
2
  export default class ApiBase extends Component {
3
3
  // TODO: use private fields (may encounter issues with rollup)
4
+
4
5
  constructor(api, apiPath) {
5
6
  super(apiPath, api);
6
7
  this._apiPath = apiPath;
@@ -8,7 +9,6 @@ export default class ApiBase extends Component {
8
9
  this.clientOptions = api._client.options;
9
10
  this.context = api._client.context;
10
11
  }
11
-
12
12
  async _run(apiName, payload) {
13
13
  let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
14
14
  this.helpers.assertReady();
@@ -19,14 +19,12 @@ export default class ApiBase extends Component {
19
19
  bulk: this.helpers.bulkInfo
20
20
  } : undefined;
21
21
  const apiGroup = this._apiPath;
22
-
23
22
  const url = this._url({
24
23
  apiGroup,
25
24
  apiName,
26
25
  payload,
27
26
  options
28
27
  });
29
-
30
28
  payload = this._preprocess({
31
29
  apiGroup,
32
30
  apiName,
@@ -40,19 +38,14 @@ export default class ApiBase extends Component {
40
38
  url,
41
39
  options
42
40
  };
43
-
44
41
  this._events.emit('request', Object.assign({}, requestData, bulkInfo));
45
-
46
42
  const response = await this._send(requestData);
47
43
  const responseData = Object.assign({}, requestData, {
48
44
  response
49
45
  });
50
-
51
46
  this._events.emit('response', Object.assign({}, responseData, bulkInfo));
52
-
53
47
  return this._postprocess(responseData);
54
48
  }
55
-
56
49
  _preprocess(_ref) {
57
50
  let {
58
51
  apiGroup,
@@ -65,7 +58,6 @@ export default class ApiBase extends Component {
65
58
  payload
66
59
  });
67
60
  }
68
-
69
61
  _url(_ref2) {
70
62
  let {
71
63
  apiGroup,
@@ -78,7 +70,6 @@ export default class ApiBase extends Component {
78
70
  url
79
71
  });
80
72
  }
81
-
82
73
  async _send(_ref3) {
83
74
  let {
84
75
  apiGroup,
@@ -94,7 +85,6 @@ export default class ApiBase extends Component {
94
85
  timeout
95
86
  });
96
87
  }
97
-
98
88
  _postprocess(_ref4) {
99
89
  let {
100
90
  response
@@ -102,5 +92,4 @@ export default class ApiBase extends Component {
102
92
  // TODO: we can introduce response passes
103
93
  return response.data;
104
94
  }
105
-
106
95
  }
@@ -6,9 +6,7 @@ export default class ApiHelpers {
6
6
  this._root = root;
7
7
  this._bulk = new Bulk(this._runBulkFetch.bind(this), client._error.bind(client));
8
8
  }
9
-
10
9
  assertReady() {}
11
-
12
10
  async fetch(url, payload) {
13
11
  let {
14
12
  method = 'POST',
@@ -28,37 +26,30 @@ export default class ApiHelpers {
28
26
  });
29
27
  timeoutId && clearTimeout(timeoutId);
30
28
  const resBody = await res.json();
31
-
32
29
  if (res.status >= 400 || resBody.errors) {
33
30
  var err = new Error(resBody.message);
34
31
  err.data = resBody;
35
32
  err.status = res.status;
36
33
  throw err;
37
34
  }
38
-
39
35
  return resBody;
40
36
  }
41
-
42
37
  get bulkInfo() {
43
38
  return this._bulk.info;
44
39
  }
45
-
46
40
  async fetchForBulk(apiGroup, apiName, payload) {
47
41
  let {
48
42
  method
49
43
  } = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
50
-
51
44
  if (method && method !== 'POST') {
52
45
  throw new Error(`Non-POST API is not supported in bulk mode: ${url}`);
53
46
  }
54
-
55
47
  return this._bulk.run({
56
48
  apiGroup,
57
49
  apiName,
58
50
  payload
59
51
  });
60
52
  }
61
-
62
53
  async _runBulkFetch(requests) {
63
54
  const url = this.url('bulk');
64
55
  const payload = {
@@ -79,7 +70,6 @@ export default class ApiHelpers {
79
70
  const {
80
71
  data: responses
81
72
  } = await this.fetch(url, payload);
82
-
83
73
  for (let i = 0, len = requests.length; i < len; i++) {
84
74
  const {
85
75
  resolution
@@ -89,7 +79,6 @@ export default class ApiHelpers {
89
79
  status_code,
90
80
  body
91
81
  } = responses[i];
92
-
93
82
  if (status_code >= 400 || error) {
94
83
  resolution.reject({
95
84
  status_code,
@@ -100,35 +89,28 @@ export default class ApiHelpers {
100
89
  }
101
90
  }
102
91
  }
103
-
104
92
  sendBeacon(url, payload) {
105
93
  let {
106
94
  method
107
95
  } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
108
-
109
96
  if (method && method !== 'POST') {
110
97
  throw new Error(`Non-POST API is not supported in useBeacon mode: ${url}`);
111
98
  }
112
-
113
99
  if (!window.navigator.sendBeacon(url, JSON.stringify(payload))) {
114
100
  throw new Error(`Send beacon unsuccessful: ${url}`);
115
101
  }
116
102
  }
117
-
118
103
  url() {
119
104
  const {
120
105
  apiKey
121
106
  } = this._client.options;
122
-
123
107
  for (var _len = arguments.length, paths = new Array(_len), _key = 0; _key < _len; _key++) {
124
108
  paths[_key] = arguments[_key];
125
109
  }
126
-
127
- const apiName = paths.filter(s => s).join('/'); // TODO: neutralize use of DOM API
128
-
110
+ const apiName = paths.filter(s => s).join('/');
111
+ // TODO: neutralize use of DOM API
129
112
  return `${this.getApiEndpoint(apiName)}/${apiName}?api_key=${window.encodeURIComponent(apiKey)}`;
130
113
  }
131
-
132
114
  getApiEndpoint(apiName) {
133
115
  const {
134
116
  dataEndpoint = API.DATA_ENDPOINT,
@@ -136,7 +118,6 @@ export default class ApiHelpers {
136
118
  } = this._client.options;
137
119
  return apiName === 'interactions' ? eventEndpoint : dataEndpoint;
138
120
  }
139
-
140
121
  applyUrlPasses(component, _ref2) {
141
122
  let {
142
123
  apiGroup,
@@ -144,7 +125,6 @@ export default class ApiHelpers {
144
125
  url
145
126
  } = _ref2;
146
127
  const client = this._client;
147
-
148
128
  for (const pass of this._root._urlPasses) {
149
129
  try {
150
130
  url = pass({
@@ -157,10 +137,8 @@ export default class ApiHelpers {
157
137
  component.error(e);
158
138
  }
159
139
  }
160
-
161
140
  return url;
162
141
  }
163
-
164
142
  applyPayloadPasses(component, _ref3) {
165
143
  let {
166
144
  apiGroup,
@@ -168,7 +146,6 @@ export default class ApiHelpers {
168
146
  payload
169
147
  } = _ref3;
170
148
  const client = this._client;
171
-
172
149
  for (const pass of this._root._payloadPasses) {
173
150
  try {
174
151
  payload = pass({
@@ -181,8 +158,6 @@ export default class ApiHelpers {
181
158
  component.error(e);
182
159
  }
183
160
  }
184
-
185
161
  return payload;
186
162
  }
187
-
188
163
  }
@@ -12,5 +12,4 @@ export default class Api extends Component {
12
12
  this.search = new Search(this);
13
13
  this.recommendation = new Recommendation(this);
14
14
  }
15
-
16
15
  }
@@ -1,14 +1,11 @@
1
1
  const _excluded = ["useBeacon"],
2
- _excluded2 = ["options"];
3
-
2
+ _excluded2 = ["options"];
4
3
  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; }
5
-
6
4
  import ApiBase from './base';
7
5
  export default class Interactions extends ApiBase {
8
6
  constructor(api) {
9
7
  super(api, 'interactions');
10
8
  }
11
-
12
9
  async upload(payload, options) {
13
10
  try {
14
11
  return await this._run('upload', payload, options);
@@ -20,7 +17,6 @@ export default class Interactions extends ApiBase {
20
17
  }
21
18
  }
22
19
  }
23
-
24
20
  _url(_ref) {
25
21
  let {
26
22
  apiGroup,
@@ -33,49 +29,41 @@ export default class Interactions extends ApiBase {
33
29
  url
34
30
  });
35
31
  }
36
-
37
32
  _preprocess(_ref2) {
38
33
  let {
39
34
  apiGroup,
40
35
  apiName,
41
36
  payload
42
37
  } = _ref2;
43
-
44
38
  if (apiName === 'upload') {
45
39
  payload = this._normalizeUploadPayload(payload);
46
40
  }
47
-
48
41
  return super._preprocess({
49
42
  apiGroup,
50
43
  apiName,
51
44
  payload
52
45
  });
53
46
  }
54
-
55
47
  _normalizeUploadPayload(payload) {
56
48
  // TODO: accept string as a shortcut of { type: payload } as well
57
49
  if (typeof payload !== 'object') {
58
50
  throw new Error(`Interactions payload has to be either an object or an array of objects: ${payload}`);
59
51
  }
60
-
61
52
  if (!Array.isArray(payload)) {
62
53
  payload = [payload];
63
54
  }
64
-
65
55
  return {
66
56
  data: payload
67
57
  };
68
58
  }
69
-
70
59
  async _send(_ref3) {
71
60
  let {
72
- options: {
73
- useBeacon = true
74
- } = {}
75
- } = _ref3,
76
- options = _objectWithoutPropertiesLoose(_ref3.options, _excluded),
77
- args = _objectWithoutPropertiesLoose(_ref3, _excluded2);
78
-
61
+ options: {
62
+ useBeacon = true
63
+ } = {}
64
+ } = _ref3,
65
+ options = _objectWithoutPropertiesLoose(_ref3.options, _excluded),
66
+ args = _objectWithoutPropertiesLoose(_ref3, _excluded2);
79
67
  if (useBeacon) {
80
68
  const {
81
69
  url,
@@ -89,5 +77,4 @@ export default class Interactions extends ApiBase {
89
77
  }));
90
78
  }
91
79
  }
92
-
93
80
  }
@@ -3,29 +3,22 @@ export default class Recommendation extends ApiBase {
3
3
  constructor(api) {
4
4
  super(api, 'recommendation');
5
5
  }
6
-
7
6
  async userToProducts(payload, options) {
8
7
  return this._run('user_to_products', payload, options);
9
8
  }
10
-
11
9
  async userToCategories(payload, options) {
12
10
  return this._run('user_to_categories', payload, options);
13
11
  }
14
-
15
12
  async userToAttributes(payload, options) {
16
13
  return this._run('user_to_attributes', payload, options);
17
14
  }
18
-
19
15
  async userToTrending(payload, options) {
20
16
  return this._run('user_to_trending', payload, options);
21
17
  }
22
-
23
18
  async userToHistory(payload, options) {
24
19
  return this._run('user_to_history', payload, options);
25
20
  }
26
-
27
21
  async productToProducts(payload, options) {
28
22
  return this._run('product_to_products', payload, options);
29
23
  }
30
-
31
24
  }
@@ -3,17 +3,13 @@ export default class Search extends ApiBase {
3
3
  constructor(api) {
4
4
  super(api, 'search');
5
5
  }
6
-
7
6
  async search(payload, options) {
8
7
  return this._run('search', payload, options);
9
8
  }
10
-
11
9
  async autocomplete(payload, options) {
12
10
  return this._run('autocomplete', payload, options);
13
11
  }
14
-
15
12
  async multipleGet(payload, options) {
16
13
  return this._run('mget', payload, options);
17
14
  }
18
-
19
15
  }
package/dist/es/client.js CHANGED
@@ -3,58 +3,45 @@ import { root, register } from './root';
3
3
  import Api from './api';
4
4
  import Context from './context';
5
5
  import * as helpers from './utils';
6
-
7
6
  class MisoClient extends Component {
8
7
  constructor(options) {
9
8
  super('client', root);
10
-
11
9
  this._config(options);
12
-
13
10
  this.context = new Context(this);
14
11
  this.api = new Api(this, root);
15
12
  register(this);
16
13
  }
17
-
18
14
  get version() {
19
15
  return MisoClient.version;
20
16
  }
21
-
22
17
  _config(options) {
23
18
  this.options = Object.freeze(this._normalizeOptions(options));
24
19
  }
25
-
26
20
  _normalizeOptions(options) {
27
21
  if (typeof options === 'string') {
28
22
  options = {
29
23
  apiKey: options
30
24
  };
31
25
  }
32
-
33
26
  if (options.readConfigFromScriptUrl) {
34
27
  options = Object.assign({}, this._readConfigFromScriptUrl(), options);
35
28
  }
36
-
37
29
  if (!options.apiKey) {
38
30
  throw new Error('Require API key to initialize miso client.');
39
31
  }
40
-
41
32
  options.dataEndpoint = options.dataEndpoint || options.apiHost;
42
33
  options.eventEndpoint = options.eventEndpoint || options.apiHost;
43
34
  delete options.apiHost;
44
35
  return trimObj(options);
45
36
  }
46
-
47
37
  _readConfigFromScriptUrl() {
48
38
  const me = document.currentScript;
49
39
  const url = me.src || me.href; // might be <link> as well
50
-
51
40
  const params = new URL(new Request(url).url).searchParams;
52
41
  return trimObj({
53
42
  apiKey: params.get('api_key') || undefined
54
43
  });
55
44
  }
56
-
57
45
  }
58
-
59
46
  MisoClient.helpers = helpers;
60
47
  export default MisoClient;
package/dist/es/cmd.js CHANGED
@@ -5,24 +5,21 @@ function execute(onError, fn) {
5
5
  onError(e);
6
6
  }
7
7
  }
8
-
9
8
  export default function (key) {
10
9
  let onError = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : e => console.error(e);
11
10
  const cmds = window[key] || (window[key] = []);
12
-
13
11
  if (cmds._processed) {
14
12
  return;
15
13
  }
16
-
17
14
  cmds._processed = true;
15
+ const exec = fn => execute(onError, fn);
18
16
 
19
- const exec = fn => execute(onError, fn); // overrides push function so future commands are executed immediately
20
-
21
-
17
+ // overrides push function so future commands are executed immediately
22
18
  Object.defineProperty(cmds, 'push', {
23
19
  value: exec
24
- }); // process existing miso commands
20
+ });
25
21
 
22
+ // process existing miso commands
26
23
  for (const fn of cmds) {
27
24
  exec(fn);
28
25
  }
@@ -4,5 +4,4 @@ export default class Context extends Component {
4
4
  super('context', client);
5
5
  this._client = client;
6
6
  }
7
-
8
7
  }
package/dist/es/index.js CHANGED
@@ -1,17 +1,17 @@
1
1
  import MisoClient from './client';
2
2
  import { init } from './root';
3
3
  import cmd from './cmd';
4
-
5
4
  if (!window.MisoClient) {
6
5
  // gaurantee to execute init() only once globally (across different script sources)
7
- window.MisoClient = init(MisoClient); // kick off misodev execution
6
+ window.MisoClient = init(MisoClient);
8
7
 
9
- cmd('misodev'); // do misocmd with setTimeout, so they will be executed after plugins are installed.
8
+ // kick off misodev execution
9
+ cmd('misodev');
10
10
 
11
+ // do misocmd with setTimeout, so they will be executed after plugins are installed.
11
12
  setTimeout(() => cmd('misocmd'));
12
13
  } else {
13
14
  // TODO: check version as well
14
15
  console.warn(`Use already defined window.MisoClient (${window.MisoClient.version}).`);
15
16
  }
16
-
17
17
  export default window.MisoClient;
@@ -5,5 +5,4 @@ export default class AnonymousPlugin {
5
5
  install
6
6
  });
7
7
  }
8
-
9
8
  }
@@ -4,26 +4,20 @@ export default class AutoEventsPlugin extends Component {
4
4
  static get id() {
5
5
  return PLUGIN_ID;
6
6
  }
7
-
8
7
  constructor() {
9
8
  super('auto-events');
10
9
  this._contexts = new WeakMap();
11
10
  }
12
-
13
11
  install(MisoClient, context) {
14
12
  context.addSubtree(this);
15
13
  MisoClient.on('create', this._injectClient.bind(this));
16
14
  context.addPayloadPass(this._captureApiRequest.bind(this));
17
15
  }
18
-
19
16
  _injectClient(client) {
20
17
  const context = new AutoEventsContext(this);
21
-
22
18
  this._contexts.set(client, context);
23
-
24
19
  client.autoEvents = context.interface;
25
20
  }
26
-
27
21
  _captureApiRequest(_ref) {
28
22
  let {
29
23
  client,
@@ -31,36 +25,28 @@ export default class AutoEventsPlugin extends Component {
31
25
  apiName,
32
26
  payload
33
27
  } = _ref;
34
-
35
28
  switch (apiGroup) {
36
29
  case 'search':
37
30
  switch (apiName) {
38
31
  case 'search':
39
32
  this._captureSearchApiRequest(client, payload);
40
-
41
33
  break;
42
34
  }
43
-
44
35
  break;
45
36
  }
46
37
  }
47
-
48
38
  _captureSearchApiRequest(client, _ref2) {
49
39
  let {
50
40
  q: keywords
51
41
  } = _ref2;
52
-
53
42
  if (!keywords || keywords === '*') {
54
43
  // might be a facet search without real keywords
55
44
  return;
56
45
  }
57
-
58
46
  const context = this._contexts.get(client);
59
-
60
47
  if (!context || !context._config.search) {
61
48
  return;
62
49
  }
63
-
64
50
  client.api.interactions.upload({
65
51
  type: 'search',
66
52
  search: {
@@ -73,9 +59,7 @@ export default class AutoEventsPlugin extends Component {
73
59
  }
74
60
  });
75
61
  }
76
-
77
62
  }
78
-
79
63
  class AutoEventsContext {
80
64
  constructor(plugin) {
81
65
  this._plugin = plugin;
@@ -86,30 +70,22 @@ class AutoEventsContext {
86
70
  config: this.config.bind(this)
87
71
  });
88
72
  }
89
-
90
73
  config() {
91
74
  let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
92
-
93
75
  if (typeof options !== 'object') {
94
76
  throw new Error(`Config options must be an object or undefined: ${options}`);
95
77
  }
96
-
97
78
  for (const key of options) {
98
79
  if (!this._config.hasOwnProperty(key)) {
99
80
  continue;
100
81
  }
101
-
102
82
  const oldValue = this._config[key];
103
83
  const newValue = options[key];
104
-
105
84
  if (newValue !== oldValue) {
106
85
  this._config[key] = oldValue;
107
-
108
86
  this._plugin._events.emit('config', `${key}: ${oldValue} -> ${newValue}`);
109
87
  }
110
88
  }
111
-
112
89
  return Object.freeze(Object.assign({}, this._config));
113
90
  }
114
-
115
91
  }
@@ -1,4 +1,3 @@
1
1
  export { default as UserPlugin } from './user';
2
2
  export { default as PageInfoPlugin } from './page-info';
3
- export { default as AutoEventsPlugin } from './auto-events';
4
- export { default as UnitsPlugin } from './units';
3
+ export { default as AutoEventsPlugin } from './auto-events';
@@ -4,16 +4,13 @@ export default class PageInfoPlugin {
4
4
  static get id() {
5
5
  return ID;
6
6
  }
7
-
8
7
  constructor() {}
9
-
10
8
  install(_, _ref) {
11
9
  let {
12
10
  addPayloadPass
13
11
  } = _ref;
14
12
  addPayloadPass(this._modifyPayload.bind(this));
15
13
  }
16
-
17
14
  _modifyPayload(_ref2) {
18
15
  let {
19
16
  apiGroup,
@@ -22,7 +19,6 @@ export default class PageInfoPlugin {
22
19
  } = _ref2;
23
20
  return apiGroup === 'interactions' && apiName === 'upload' ? this._modifyPayloadForInteractions(payload) : payload;
24
21
  }
25
-
26
22
  _modifyPayloadForInteractions(_ref3) {
27
23
  let {
28
24
  data
@@ -34,16 +30,13 @@ export default class PageInfoPlugin {
34
30
  data
35
31
  };
36
32
  }
37
-
38
33
  }
39
-
40
34
  function getPayloadContext() {
41
35
  return trimObj({
42
36
  page: readPageInfo(),
43
37
  campaign: readUtm()
44
38
  });
45
39
  }
46
-
47
40
  function readPageInfo() {
48
41
  return trimObj({
49
42
  url: window.location.href,
@@ -51,7 +44,6 @@ function readPageInfo() {
51
44
  title: document.title
52
45
  });
53
46
  }
54
-
55
47
  function readUtm() {
56
48
  const params = new URLSearchParams(window.location.search);
57
49
  let utm = trimObj({