@miso.ai/client-sdk-core 1.12.3-beta.5 → 1.12.3

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.
@@ -31,6 +31,12 @@ class ApiBase extends _commons.Component {
31
31
  payload,
32
32
  options
33
33
  });
34
+ const headers = this._headers({
35
+ apiGroup,
36
+ apiName,
37
+ payload,
38
+ options
39
+ });
34
40
  payload = this._preprocess({
35
41
  apiGroup,
36
42
  apiName,
@@ -42,6 +48,7 @@ class ApiBase extends _commons.Component {
42
48
  apiName,
43
49
  payload,
44
50
  url,
51
+ headers,
45
52
  options
46
53
  };
47
54
  this._events.emit('request', Object.assign({}, requestData, bulkInfo));
@@ -52,15 +59,31 @@ class ApiBase extends _commons.Component {
52
59
  this._events.emit('response', Object.assign({}, responseData, bulkInfo));
53
60
  return this._postprocess(responseData);
54
61
  }
62
+ _headers({
63
+ apiGroup,
64
+ apiName,
65
+ payload,
66
+ options
67
+ }) {
68
+ return this.helpers.applyHeaderPasses(this, {
69
+ apiGroup,
70
+ apiName,
71
+ payload,
72
+ headers: {},
73
+ options
74
+ });
75
+ }
55
76
  _preprocess({
56
77
  apiGroup,
57
78
  apiName,
58
- payload
79
+ payload,
80
+ options
59
81
  }) {
60
82
  return this.helpers.applyPayloadPasses(this, {
61
83
  apiGroup,
62
84
  apiName,
63
- payload
85
+ payload,
86
+ options
64
87
  });
65
88
  }
66
89
  _url({
@@ -81,13 +104,16 @@ class ApiBase extends _commons.Component {
81
104
  apiGroup,
82
105
  apiName,
83
106
  url,
107
+ headers,
84
108
  payload,
85
109
  options: {
86
110
  bulk
87
111
  } = {}
88
112
  } = _ref,
89
113
  options = _objectWithoutPropertiesLoose(_ref.options, _excluded);
90
- return bulk ? this.helpers.fetchForBulk(apiGroup, apiName, payload) : this.helpers.fetch(url, payload, options);
114
+ return bulk ? this.helpers.fetchForBulk(apiGroup, apiName, payload) : this.helpers.fetch(url, payload, Object.assign({}, options, {
115
+ headers
116
+ }));
91
117
  }
92
118
  _postprocess({
93
119
  response
@@ -15,20 +15,14 @@ class ApiHelpers {
15
15
  async fetch(url, payload, {
16
16
  method = 'POST',
17
17
  headers,
18
- timeout,
19
- sendApiKeyByHeader
18
+ timeout
20
19
  } = {}) {
21
20
  const {
22
21
  apiKey,
23
22
  request = {}
24
23
  } = this._client.options;
25
24
  timeout = timeout || request.timeout;
26
- sendApiKeyByHeader = sendApiKeyByHeader || request.sendApiKeyByHeader;
27
- if (sendApiKeyByHeader) {
28
- headers = Object.assign({}, headers, {
29
- 'X-API-KEY': apiKey
30
- });
31
- }
25
+
32
26
  // TODO: external abort signal
33
27
  // TODO: organize arguments
34
28
  const body = method !== 'GET' && payload != undefined ? JSON.stringify(payload) : undefined;
@@ -113,15 +107,13 @@ class ApiHelpers {
113
107
  throw new Error(`Send beacon unsuccessful: ${url}`);
114
108
  }
115
109
  }
116
- url(paths, options = {}) {
110
+ url(paths) {
117
111
  const {
118
- apiKey,
119
- request = {}
112
+ apiKey
120
113
  } = this._client.options;
121
- const sendApiKeyByHeader = options.sendApiKeyByHeader || request.sendApiKeyByHeader;
122
114
  const apiName = paths.filter(s => s).join('/');
123
115
  const url = `${this.getApiEndpoint(apiName)}/${apiName}`;
124
- return sendApiKeyByHeader ? url : `${url}?api_key=${window.encodeURIComponent(apiKey)}`;
116
+ return `${url}?api_key=${window.encodeURIComponent(apiKey)}`;
125
117
  }
126
118
  getApiEndpoint(apiName) {
127
119
  const {
@@ -170,5 +162,29 @@ class ApiHelpers {
170
162
  }
171
163
  return payload;
172
164
  }
165
+ applyHeaderPasses(component, {
166
+ apiGroup,
167
+ apiName,
168
+ payload,
169
+ headers,
170
+ options
171
+ }) {
172
+ const client = this._client;
173
+ for (const pass of this._root._headersPasses) {
174
+ try {
175
+ headers = pass({
176
+ client,
177
+ apiGroup,
178
+ apiName,
179
+ payload,
180
+ headers,
181
+ options
182
+ }) || headers;
183
+ } catch (e) {
184
+ (component._error || console.error)(e);
185
+ }
186
+ }
187
+ return headers;
188
+ }
173
189
  }
174
190
  exports.default = ApiHelpers;
@@ -54,6 +54,9 @@ class MisoClient extends _commons.Component {
54
54
  if (!options.apiKey) {
55
55
  throw new Error('Require API key to initialize miso client.');
56
56
  }
57
+ if (options.request && options.request.sendApiKeyByHeader) {
58
+ console.warn('`sendApiKeyByHeader` option is deprecated. Please call `MisoClient.plugins.use("std:header-api-key");` instead.');
59
+ }
57
60
  options.dataEndpoint = options.dataEndpoint || options.apiHost;
58
61
  options.eventEndpoint = options.eventEndpoint || options.apiHost;
59
62
  delete options.apiHost;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _commons = require("@miso.ai/commons");
8
+ const _excluded = ["payload"],
9
+ _excluded2 = ["_meta", "metadata"],
10
+ _excluded3 = ["user_type"];
11
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
12
+ const PLUGIN_ID = 'std:api-patch';
13
+ class ApiPatchPlugin extends _commons.Component {
14
+ static get id() {
15
+ return PLUGIN_ID;
16
+ }
17
+ constructor() {
18
+ super('api-patch');
19
+ }
20
+ install(MisoClient, context) {
21
+ context.addSubtree(this);
22
+ context.addPayloadPass(this._patchApiPayload.bind(this));
23
+ }
24
+ _patchApiPayload(args) {
25
+ let {
26
+ payload
27
+ } = args,
28
+ rest = _objectWithoutPropertiesLoose(args, _excluded);
29
+ if (!payload) {
30
+ return payload; // the GET request
31
+ }
32
+ payload = this._copyMetadataToMeta(payload, rest);
33
+ payload = this._suppressMetadata(payload, rest);
34
+ payload = this._suppressUserType(payload, rest);
35
+ return payload;
36
+ }
37
+ _copyMetadataToMeta(payload, {
38
+ apiGroup
39
+ }) {
40
+ switch (apiGroup) {
41
+ case _commons.API.GROUP.ASK:
42
+ if (payload.metadata) {
43
+ return Object.assign({}, payload, {
44
+ _meta: payload.metadata
45
+ });
46
+ }
47
+ return payload;
48
+ default:
49
+ return payload;
50
+ }
51
+ }
52
+ _suppressMetadata(payload, {
53
+ apiGroup
54
+ }) {
55
+ switch (apiGroup) {
56
+ case _commons.API.GROUP.SEARCH:
57
+ case _commons.API.GROUP.RECOMMENDATION:
58
+ const rest = _objectWithoutPropertiesLoose(payload, _excluded2);
59
+ return rest;
60
+ default:
61
+ return payload;
62
+ }
63
+ }
64
+ _suppressUserType(payload, {
65
+ apiGroup
66
+ }) {
67
+ switch (apiGroup) {
68
+ case _commons.API.GROUP.SEARCH:
69
+ case _commons.API.GROUP.RECOMMENDATION:
70
+ const rest = _objectWithoutPropertiesLoose(payload, _excluded3);
71
+ return rest;
72
+ default:
73
+ return payload;
74
+ }
75
+ }
76
+ }
77
+ exports.default = ApiPatchPlugin;
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _commons = require("@miso.ai/commons");
8
+ const {
9
+ GROUP,
10
+ NAME
11
+ } = _commons.API;
12
+ const PLUGIN_ID = 'std:context';
13
+ class ContextPlugin extends _commons.Component {
14
+ static get id() {
15
+ return PLUGIN_ID;
16
+ }
17
+ constructor() {
18
+ super('context');
19
+ }
20
+ install(MisoClient, context) {
21
+ context.addSubtree(this);
22
+ MisoClient.on('create', this._injectClient.bind(this));
23
+ context.addHeadersPass(this._modifyHeaders.bind(this));
24
+ context.addPayloadPass(this._modifyPayload.bind(this));
25
+ }
26
+ _injectClient(client) {
27
+ const context = new ClientContext(this);
28
+ (0, _commons.delegateProperties)(client.context, context, ['anonymous_id', 'user_id', 'user_hash', 'user_type', 'site', 'auth']);
29
+ }
30
+ _modifyHeaders({
31
+ client,
32
+ headers
33
+ }) {
34
+ const {
35
+ auth
36
+ } = client.context;
37
+ if (auth) {
38
+ headers = Object.assign({}, headers, {
39
+ Authorization: auth
40
+ });
41
+ }
42
+ return headers;
43
+ }
44
+ _modifyPayload({
45
+ client,
46
+ apiGroup,
47
+ apiName,
48
+ payload
49
+ }) {
50
+ if (!payload) {
51
+ return payload; // the GET request
52
+ }
53
+ switch (apiGroup) {
54
+ case GROUP.INTERACTIONS:
55
+ if (apiName === NAME.UPLOAD) {
56
+ return this._modifyPayloadForInteractions(client, payload);
57
+ }
58
+ return payload;
59
+ default:
60
+ return this._modifyPayloadForQueries(client, payload);
61
+ }
62
+ }
63
+ _modifyPayloadForQueries(client, payload) {
64
+ const {
65
+ user_id,
66
+ user_hash,
67
+ user_type,
68
+ anonymous_id,
69
+ site
70
+ } = client.context;
71
+ const userInfo = user_id ? {
72
+ user_id,
73
+ user_type,
74
+ user_hash
75
+ } : {
76
+ anonymous_id
77
+ };
78
+ const metadata = site ? {
79
+ site
80
+ } : undefined;
81
+ return (0, _commons.mergeApiPayloads)(payload, Object.assign({}, userInfo, {
82
+ metadata
83
+ }));
84
+ }
85
+ _modifyPayloadForInteractions(client, {
86
+ data
87
+ }) {
88
+ const {
89
+ anonymous_id,
90
+ user_id,
91
+ site
92
+ } = client.context;
93
+ const userInfo = {
94
+ anonymous_id,
95
+ user_id
96
+ };
97
+ const custom_context = site ? {
98
+ site
99
+ } : undefined;
100
+ const context = custom_context ? {
101
+ custom_context
102
+ } : undefined;
103
+ data = data.map(obj => (0, _commons.mergeInteractions)(obj, Object.assign({}, userInfo, {
104
+ context
105
+ })));
106
+ return {
107
+ data
108
+ };
109
+ }
110
+ }
111
+ exports.default = ContextPlugin;
112
+ let _pageBasedAutoAnonymousId;
113
+ function getAutoAnonymousId() {
114
+ // 1. Cache the value for the page
115
+ // 2. Get and set the value from cookies/localStorage is possible
116
+ // 3. In case cookies/localStorage are disabled, generate a new value for each page
117
+ return _pageBasedAutoAnonymousId || (_pageBasedAutoAnonymousId = (0, _commons.getOrComputeFromStorage)('miso_anonymous_id', _commons.uuidv4));
118
+ }
119
+ class ClientContext {
120
+ constructor(plugin) {
121
+ this._plugin = plugin;
122
+ this._props = {};
123
+ }
124
+ get anonymous_id() {
125
+ return this._props.anonymous_id || getAutoAnonymousId();
126
+ }
127
+ set anonymous_id(value) {
128
+ this._requireString('anonymous_id', value);
129
+ this._set('anonymous_id', value);
130
+ }
131
+ get user_id() {
132
+ return this._props.user_id;
133
+ }
134
+ set user_id(value) {
135
+ this._requireString('user_id', value);
136
+ this._set('user_id', value);
137
+ }
138
+ get user_hash() {
139
+ return this._props.user_hash;
140
+ }
141
+ set user_hash(value) {
142
+ this._requireString('user_hash', value);
143
+ this._set('user_hash', value);
144
+ }
145
+ get user_type() {
146
+ return this._props.user_type;
147
+ }
148
+ set user_type(value) {
149
+ this._requireString('user_type', value);
150
+ this._set('user_type', value);
151
+ }
152
+ get site() {
153
+ return this._props.site;
154
+ }
155
+ set site(value) {
156
+ this._requireString('site', value);
157
+ this._set('site', value);
158
+ }
159
+ get auth() {
160
+ return this._props.auth;
161
+ }
162
+ set auth(value) {
163
+ this._requireString('auth', value);
164
+ this._set('auth', value);
165
+ }
166
+
167
+ // helpers //
168
+ _set(key, value) {
169
+ this._props[key] = value;
170
+ this._plugin._events.emit('set', `${key} = '${value}'`);
171
+ }
172
+ _requireString(key, value) {
173
+ if (typeof value !== 'string' && typeof value !== 'undefined') {
174
+ throw new Error(`${key} must be a string`);
175
+ }
176
+ return value;
177
+ }
178
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ const PLUGIN_ID = 'std:header-api-key';
8
+ class HeaderApiKeyPlugin {
9
+ static get id() {
10
+ return PLUGIN_ID;
11
+ }
12
+ install(MisoClient, context) {
13
+ context.addUrlPass(this._modifyUrl.bind(this));
14
+ context.addHeadersPass(this._modifyHeaders.bind(this));
15
+ MisoClient.debug(`<plugin:${PLUGIN_ID}>`, '[info]', `Send API key in header`);
16
+ }
17
+ _modifyUrl({
18
+ url
19
+ }) {
20
+ // remove api_key from url
21
+ return url.replace(/[?&]api_key=[^&]*/g, '');
22
+ }
23
+ _modifyHeaders({
24
+ client,
25
+ headers
26
+ }) {
27
+ const {
28
+ apiKey
29
+ } = client.options;
30
+ return apiKey ? Object.assign({}, headers, {
31
+ 'X-API-KEY': apiKey
32
+ }) : headers;
33
+ }
34
+ }
35
+ exports.default = HeaderApiKeyPlugin;
@@ -3,10 +3,10 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- Object.defineProperty(exports, "ApiPlugin", {
6
+ Object.defineProperty(exports, "ApiPatchPlugin", {
7
7
  enumerable: true,
8
8
  get: function () {
9
- return _api.default;
9
+ return _apiPatch.default;
10
10
  }
11
11
  });
12
12
  Object.defineProperty(exports, "AutoEventsPlugin", {
@@ -15,6 +15,18 @@ Object.defineProperty(exports, "AutoEventsPlugin", {
15
15
  return _autoEvents.default;
16
16
  }
17
17
  });
18
+ Object.defineProperty(exports, "ContextPlugin", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _context.default;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "HeaderApiKeyPlugin", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _headerApiKey.default;
28
+ }
29
+ });
18
30
  Object.defineProperty(exports, "InteractionsPlugin", {
19
31
  enumerable: true,
20
32
  get: function () {
@@ -33,16 +45,11 @@ Object.defineProperty(exports, "PageInfoPlugin", {
33
45
  return _pageInfo.default;
34
46
  }
35
47
  });
36
- Object.defineProperty(exports, "UserPlugin", {
37
- enumerable: true,
38
- get: function () {
39
- return _user.default;
40
- }
41
- });
42
- var _user = _interopRequireDefault(require("./user.js"));
48
+ var _context = _interopRequireDefault(require("./context.js"));
43
49
  var _pageInfo = _interopRequireDefault(require("./page-info.js"));
44
50
  var _autoEvents = _interopRequireDefault(require("./auto-events.js"));
45
51
  var _interactions = _interopRequireDefault(require("./interactions.js"));
46
52
  var _nativeFetch = _interopRequireDefault(require("./native-fetch.js"));
47
- var _api = _interopRequireDefault(require("./api.js"));
53
+ var _apiPatch = _interopRequireDefault(require("./api-patch.js"));
54
+ var _headerApiKey = _interopRequireDefault(require("./header-api-key.js"));
48
55
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -92,6 +92,12 @@ class PluginRoot extends _commons.Registry {
92
92
  }
93
93
  this._root._payloadPasses.push(pass);
94
94
  }
95
+ addHeadersPass(pass) {
96
+ if (typeof pass !== 'function') {
97
+ throw new Error(`Expect parameter to be a function: ${pass}`);
98
+ }
99
+ this._root._headersPasses.push(pass);
100
+ }
95
101
  addUrlPass(pass) {
96
102
  if (typeof pass !== 'function') {
97
103
  throw new Error(`Expect parameter to be a function: ${pass}`);
@@ -233,7 +239,7 @@ class PluginRoot extends _commons.Registry {
233
239
  exports.default = PluginRoot;
234
240
  class PluginContext {
235
241
  constructor(root, classes) {
236
- (0, _commons.delegateGetters)(this, root, ['getPluginClass', 'addSubtree', 'addPayloadPass', 'addUrlPass', 'setCustomFetch', 'setCustomSendBeacon', 'onHubUpdate', 'onHubEmit', 'whenInstalled', 'whenRegistered']);
242
+ (0, _commons.delegateGetters)(this, root, ['getPluginClass', 'addSubtree', 'addPayloadPass', 'addHeadersPass', 'addUrlPass', 'setCustomFetch', 'setCustomSendBeacon', 'onHubUpdate', 'onHubEmit', 'whenInstalled', 'whenRegistered']);
237
243
  (0, _commons.defineValues)(this, {
238
244
  classes
239
245
  });
package/dist/cjs/root.js CHANGED
@@ -21,6 +21,7 @@ class Root extends _commons.Component {
21
21
  this._pluginRoot = new _pluginRoot.default(this);
22
22
  this._clients = [];
23
23
  this._payloadPasses = [];
24
+ this._headersPasses = [];
24
25
  this._urlPasses = [];
25
26
  this._customFetch = undefined;
26
27
  this._customSendBeacon = undefined;
@@ -4,4 +4,4 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _default = exports.default = '1.12.3-beta.5';
7
+ var _default = exports.default = '1.12.3';
package/package.json CHANGED
@@ -29,7 +29,7 @@
29
29
  "url": "https://github.com/MisoAI/miso-client-js-sdk/issues"
30
30
  },
31
31
  "dependencies": {
32
- "@miso.ai/commons": "1.12.3-beta.5"
32
+ "@miso.ai/commons": "1.12.3"
33
33
  },
34
- "version": "1.12.3-beta.5"
34
+ "version": "1.12.3"
35
35
  }
package/src/api/base.js CHANGED
@@ -17,8 +17,9 @@ export default class ApiBase extends Component {
17
17
  const bulkInfo = bulk ? { bulk: this.helpers.bulkInfo } : undefined;
18
18
  const apiGroup = this._apiPath;
19
19
  const url = this._url({ apiGroup, apiName, payload, options });
20
+ const headers = this._headers({ apiGroup, apiName, payload, options });
20
21
  payload = this._preprocess({ apiGroup, apiName, payload, options });
21
- const requestData = { apiGroup, apiName, payload, url, options };
22
+ const requestData = { apiGroup, apiName, payload, url, headers, options };
22
23
  this._events.emit('request', { ...requestData, ...bulkInfo });
23
24
  const response = await this._send(requestData);
24
25
  const responseData = { ...requestData, response };
@@ -26,8 +27,12 @@ export default class ApiBase extends Component {
26
27
  return this._postprocess(responseData);
27
28
  }
28
29
 
29
- _preprocess({ apiGroup, apiName, payload }) {
30
- return this.helpers.applyPayloadPasses(this, { apiGroup, apiName, payload });
30
+ _headers({ apiGroup, apiName, payload, options }) {
31
+ return this.helpers.applyHeaderPasses(this, { apiGroup, apiName, payload, headers: {}, options });
32
+ }
33
+
34
+ _preprocess({ apiGroup, apiName, payload, options }) {
35
+ return this.helpers.applyPayloadPasses(this, { apiGroup, apiName, payload, options });
31
36
  }
32
37
 
33
38
  _url({ apiGroup, apiName, options }) {
@@ -35,8 +40,8 @@ export default class ApiBase extends Component {
35
40
  return this.helpers.applyUrlPasses(this, { apiGroup, apiName, url, options });
36
41
  }
37
42
 
38
- async _send({ apiGroup, apiName, url, payload, options: { bulk, ...options } = {} }) {
39
- return bulk ? this.helpers.fetchForBulk(apiGroup, apiName, payload) : this.helpers.fetch(url, payload, options);
43
+ async _send({ apiGroup, apiName, url, headers, payload, options: { bulk, ...options } = {} }) {
44
+ return bulk ? this.helpers.fetchForBulk(apiGroup, apiName, payload) : this.helpers.fetch(url, payload, { ...options, headers });
40
45
  }
41
46
 
42
47
  _postprocess({ response }) {
@@ -13,15 +13,10 @@ export default class ApiHelpers {
13
13
  method = 'POST',
14
14
  headers,
15
15
  timeout,
16
- sendApiKeyByHeader,
17
16
  } = {}) {
18
17
  const { apiKey, request = {} } = this._client.options;
19
18
  timeout = timeout || request.timeout;
20
- sendApiKeyByHeader = sendApiKeyByHeader || request.sendApiKeyByHeader;
21
19
 
22
- if (sendApiKeyByHeader) {
23
- headers = { ...headers, 'X-API-KEY': apiKey };
24
- }
25
20
  // TODO: external abort signal
26
21
  // TODO: organize arguments
27
22
  const body = method !== 'GET' && payload != undefined ? JSON.stringify(payload) : undefined;
@@ -91,12 +86,11 @@ export default class ApiHelpers {
91
86
  }
92
87
  }
93
88
 
94
- url(paths, options = {}) {
95
- const { apiKey, request = {} } = this._client.options;
96
- const sendApiKeyByHeader = options.sendApiKeyByHeader || request.sendApiKeyByHeader;
89
+ url(paths) {
90
+ const { apiKey } = this._client.options;
97
91
  const apiName = paths.filter(s => s).join('/');
98
92
  const url = `${this.getApiEndpoint(apiName)}/${apiName}`;
99
- return sendApiKeyByHeader ? url : `${url}?api_key=${window.encodeURIComponent(apiKey)}`;
93
+ return `${url}?api_key=${window.encodeURIComponent(apiKey)}`;
100
94
  }
101
95
 
102
96
  getApiEndpoint(apiName) {
@@ -131,4 +125,16 @@ export default class ApiHelpers {
131
125
  return payload;
132
126
  }
133
127
 
128
+ applyHeaderPasses(component, { apiGroup, apiName, payload, headers, options }) {
129
+ const client = this._client;
130
+ for (const pass of this._root._headersPasses) {
131
+ try {
132
+ headers = pass({ client, apiGroup, apiName, payload, headers, options }) || headers;
133
+ } catch(e) {
134
+ (component._error || console.error)(e);
135
+ }
136
+ }
137
+ return headers;
138
+ }
139
+
134
140
  }
package/src/client.js CHANGED
@@ -54,6 +54,9 @@ class MisoClient extends Component {
54
54
  if (!options.apiKey) {
55
55
  throw new Error('Require API key to initialize miso client.');
56
56
  }
57
+ if (options.request && options.request.sendApiKeyByHeader) {
58
+ console.warn('`sendApiKeyByHeader` option is deprecated. Please call `MisoClient.plugins.use("std:header-api-key");` instead.');
59
+ }
57
60
 
58
61
  options.dataEndpoint = options.dataEndpoint || options.apiHost;
59
62
  options.eventEndpoint = options.eventEndpoint || options.apiHost;
@@ -0,0 +1,68 @@
1
+ import { Component, API } from '@miso.ai/commons';
2
+
3
+ const PLUGIN_ID = 'std:api-patch';
4
+
5
+ export default class ApiPatchPlugin extends Component {
6
+
7
+ static get id() {
8
+ return PLUGIN_ID;
9
+ }
10
+
11
+ constructor() {
12
+ super('api-patch');
13
+ }
14
+
15
+ install(MisoClient, context) {
16
+ context.addSubtree(this);
17
+ context.addPayloadPass(this._patchApiPayload.bind(this));
18
+ }
19
+
20
+ _patchApiPayload(args) {
21
+ let { payload, ...rest } = args;
22
+ if (!payload) {
23
+ return payload; // the GET request
24
+ }
25
+ payload = this._copyMetadataToMeta(payload, rest);
26
+ payload = this._suppressMetadata(payload, rest);
27
+ payload = this._suppressUserType(payload, rest);
28
+ return payload;
29
+ }
30
+
31
+ _copyMetadataToMeta(payload, { apiGroup }) {
32
+ switch (apiGroup) {
33
+ case API.GROUP.ASK:
34
+ if (payload.metadata) {
35
+ return {
36
+ ...payload,
37
+ _meta: payload.metadata,
38
+ };
39
+ }
40
+ return payload;
41
+ default:
42
+ return payload;
43
+ }
44
+ }
45
+
46
+ _suppressMetadata(payload, { apiGroup }) {
47
+ switch (apiGroup) {
48
+ case API.GROUP.SEARCH:
49
+ case API.GROUP.RECOMMENDATION:
50
+ const { _meta, metadata, ...rest } = payload;
51
+ return rest;
52
+ default:
53
+ return payload;
54
+ }
55
+ }
56
+
57
+ _suppressUserType(payload, { apiGroup }) {
58
+ switch (apiGroup) {
59
+ case API.GROUP.SEARCH:
60
+ case API.GROUP.RECOMMENDATION:
61
+ const { user_type, ...rest } = payload;
62
+ return rest;
63
+ default:
64
+ return payload;
65
+ }
66
+ }
67
+
68
+ }
@@ -0,0 +1,153 @@
1
+ import { API, uuidv4, Component, delegateProperties, getOrComputeFromStorage, mergeInteractions, mergeApiPayloads } from '@miso.ai/commons';
2
+
3
+ const { GROUP, NAME } = API;
4
+
5
+ const PLUGIN_ID = 'std:context';
6
+
7
+ export default class ContextPlugin extends Component {
8
+
9
+ static get id() {
10
+ return PLUGIN_ID;
11
+ }
12
+
13
+ constructor() {
14
+ super('context');
15
+ }
16
+
17
+ install(MisoClient, context) {
18
+ context.addSubtree(this);
19
+ MisoClient.on('create', this._injectClient.bind(this));
20
+ context.addHeadersPass(this._modifyHeaders.bind(this));
21
+ context.addPayloadPass(this._modifyPayload.bind(this));
22
+ }
23
+
24
+ _injectClient(client) {
25
+ const context = new ClientContext(this);
26
+ delegateProperties(client.context, context, ['anonymous_id', 'user_id', 'user_hash', 'user_type', 'site', 'auth']);
27
+ }
28
+
29
+ _modifyHeaders({ client, headers }) {
30
+ const { auth } = client.context;
31
+ if (auth) {
32
+ headers = { ...headers, Authorization: auth };
33
+ }
34
+ return headers;
35
+ }
36
+
37
+ _modifyPayload({ client, apiGroup, apiName, payload }) {
38
+ if (!payload) {
39
+ return payload; // the GET request
40
+ }
41
+ switch (apiGroup) {
42
+ case GROUP.INTERACTIONS:
43
+ if (apiName === NAME.UPLOAD) {
44
+ return this._modifyPayloadForInteractions(client, payload);
45
+ }
46
+ return payload;
47
+ default:
48
+ return this._modifyPayloadForQueries(client, payload);
49
+ }
50
+ }
51
+
52
+ _modifyPayloadForQueries(client, payload) {
53
+ const { user_id, user_hash, user_type, anonymous_id, site } = client.context;
54
+ const userInfo = user_id ? { user_id, user_type, user_hash } : { anonymous_id };
55
+ const metadata = site ? { site } : undefined;
56
+ return mergeApiPayloads(payload, { ...userInfo, metadata });
57
+ }
58
+
59
+ _modifyPayloadForInteractions(client, { data }) {
60
+ const { anonymous_id, user_id, site } = client.context;
61
+ const userInfo = { anonymous_id, user_id };
62
+ const custom_context = site ? { site } : undefined;
63
+ const context = custom_context ? { custom_context } : undefined;
64
+ data = data.map(obj => mergeInteractions(obj, { ...userInfo, context }));
65
+ return { data };
66
+ }
67
+
68
+ }
69
+
70
+ let _pageBasedAutoAnonymousId;
71
+
72
+ function getAutoAnonymousId() {
73
+ // 1. Cache the value for the page
74
+ // 2. Get and set the value from cookies/localStorage is possible
75
+ // 3. In case cookies/localStorage are disabled, generate a new value for each page
76
+ return _pageBasedAutoAnonymousId || (_pageBasedAutoAnonymousId = getOrComputeFromStorage('miso_anonymous_id', uuidv4));
77
+ }
78
+
79
+ class ClientContext {
80
+
81
+ constructor(plugin) {
82
+ this._plugin = plugin;
83
+ this._props = {};
84
+ }
85
+
86
+ get anonymous_id() {
87
+ return this._props.anonymous_id || getAutoAnonymousId();
88
+ }
89
+
90
+ set anonymous_id(value) {
91
+ this._requireString('anonymous_id', value);
92
+ this._set('anonymous_id', value);
93
+ }
94
+
95
+ get user_id() {
96
+ return this._props.user_id;
97
+ }
98
+
99
+ set user_id(value) {
100
+ this._requireString('user_id', value);
101
+ this._set('user_id', value);
102
+ }
103
+
104
+ get user_hash() {
105
+ return this._props.user_hash;
106
+ }
107
+
108
+ set user_hash(value) {
109
+ this._requireString('user_hash', value);
110
+ this._set('user_hash', value);
111
+ }
112
+
113
+ get user_type() {
114
+ return this._props.user_type;
115
+ }
116
+
117
+ set user_type(value) {
118
+ this._requireString('user_type', value);
119
+ this._set('user_type', value);
120
+ }
121
+
122
+ get site() {
123
+ return this._props.site;
124
+ }
125
+
126
+ set site(value) {
127
+ this._requireString('site', value);
128
+ this._set('site', value);
129
+ }
130
+
131
+ get auth() {
132
+ return this._props.auth;
133
+ }
134
+
135
+ set auth(value) {
136
+ this._requireString('auth', value);
137
+ this._set('auth', value);
138
+ }
139
+
140
+ // helpers //
141
+ _set(key, value) {
142
+ this._props[key] = value;
143
+ this._plugin._events.emit('set', `${key} = '${value}'`);
144
+ }
145
+
146
+ _requireString(key, value) {
147
+ if (typeof value !== 'string' && typeof value !== 'undefined') {
148
+ throw new Error(`${key} must be a string`);
149
+ }
150
+ return value;
151
+ }
152
+
153
+ }
@@ -0,0 +1,25 @@
1
+ const PLUGIN_ID = 'std:header-api-key';
2
+
3
+ export default class HeaderApiKeyPlugin {
4
+
5
+ static get id() {
6
+ return PLUGIN_ID;
7
+ }
8
+
9
+ install(MisoClient, context) {
10
+ context.addUrlPass(this._modifyUrl.bind(this));
11
+ context.addHeadersPass(this._modifyHeaders.bind(this));
12
+ MisoClient.debug(`<plugin:${PLUGIN_ID}>`, '[info]', `Send API key in header`);
13
+ }
14
+
15
+ _modifyUrl({ url }) {
16
+ // remove api_key from url
17
+ return url.replace(/[?&]api_key=[^&]*/g, '');
18
+ }
19
+
20
+ _modifyHeaders({ client, headers }) {
21
+ const { apiKey } = client.options;
22
+ return apiKey ? { ...headers, 'X-API-KEY': apiKey } : headers;
23
+ }
24
+
25
+ }
@@ -1,6 +1,7 @@
1
- export { default as UserPlugin } from './user.js';
1
+ export { default as ContextPlugin } from './context.js';
2
2
  export { default as PageInfoPlugin } from './page-info.js';
3
3
  export { default as AutoEventsPlugin } from './auto-events.js';
4
4
  export { default as InteractionsPlugin } from './interactions.js';
5
5
  export { default as NativeFetchPlugin } from './native-fetch.js';
6
- export { default as ApiPlugin } from './api.js';
6
+ export { default as ApiPatchPlugin } from './api-patch.js';
7
+ export { default as HeaderApiKeyPlugin } from './header-api-key.js';
@@ -94,6 +94,13 @@ export default class PluginRoot extends Registry {
94
94
  this._root._payloadPasses.push(pass);
95
95
  }
96
96
 
97
+ addHeadersPass(pass) {
98
+ if (typeof pass !== 'function') {
99
+ throw new Error(`Expect parameter to be a function: ${pass}`);
100
+ }
101
+ this._root._headersPasses.push(pass);
102
+ }
103
+
97
104
  addUrlPass(pass) {
98
105
  if (typeof pass !== 'function') {
99
106
  throw new Error(`Expect parameter to be a function: ${pass}`);
@@ -243,7 +250,7 @@ export default class PluginRoot extends Registry {
243
250
  class PluginContext {
244
251
 
245
252
  constructor(root, classes) {
246
- delegateGetters(this, root, ['getPluginClass', 'addSubtree', 'addPayloadPass', 'addUrlPass', 'setCustomFetch', 'setCustomSendBeacon', 'onHubUpdate', 'onHubEmit', 'whenInstalled', 'whenRegistered']);
253
+ delegateGetters(this, root, ['getPluginClass', 'addSubtree', 'addPayloadPass', 'addHeadersPass', 'addUrlPass', 'setCustomFetch', 'setCustomSendBeacon', 'onHubUpdate', 'onHubEmit', 'whenInstalled', 'whenRegistered']);
247
254
  defineValues(this, { classes });
248
255
  }
249
256
 
package/src/root.js CHANGED
@@ -13,6 +13,7 @@ class Root extends Component {
13
13
  this._pluginRoot = new PluginRoot(this);
14
14
  this._clients = [];
15
15
  this._payloadPasses = [];
16
+ this._headersPasses = [];
16
17
  this._urlPasses = [];
17
18
  this._customFetch = undefined;
18
19
  this._customSendBeacon = undefined;
package/src/version.js CHANGED
@@ -1 +1 @@
1
- export default '1.12.3-beta.5';
1
+ export default '1.12.3';
@@ -1,42 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _commons = require("@miso.ai/commons");
8
- const _excluded = ["_meta"];
9
- function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
10
- const PLUGIN_ID = 'std:api';
11
- class ApiPlugin extends _commons.Component {
12
- static get id() {
13
- return PLUGIN_ID;
14
- }
15
- constructor() {
16
- super('api');
17
- }
18
- install(MisoClient, context) {
19
- context.addSubtree(this);
20
- context.addPayloadPass(this._suppressMetaObject.bind(this));
21
- }
22
- _suppressMetaObject(args) {
23
- if (!this._shallSuppressMetaObject(args)) {
24
- return args.payload;
25
- }
26
- const {} = args,
27
- payload = _objectWithoutPropertiesLoose(args.payload, _excluded);
28
- return payload;
29
- }
30
- _shallSuppressMetaObject({
31
- apiGroup,
32
- apiName
33
- }) {
34
- switch (apiGroup) {
35
- case _commons.API.GROUP.SEARCH:
36
- case _commons.API.GROUP.RECOMMENDATION:
37
- return true;
38
- }
39
- return false;
40
- }
41
- }
42
- exports.default = ApiPlugin;
@@ -1,139 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _commons = require("@miso.ai/commons");
8
- const {
9
- GROUP,
10
- NAME
11
- } = _commons.API;
12
- const PLUGIN_ID = 'std:user';
13
- class UserPlugin extends _commons.Component {
14
- static get id() {
15
- return PLUGIN_ID;
16
- }
17
- constructor() {
18
- super('user');
19
- this._contexts = new WeakMap();
20
- }
21
- install(MisoClient, context) {
22
- context.addSubtree(this);
23
- MisoClient.on('create', this._injectClient.bind(this));
24
- context.addPayloadPass(this._modifyPayload.bind(this));
25
- }
26
- _injectClient(client) {
27
- const context = new UserContext(this);
28
- this._contexts.set(client, context);
29
- (0, _commons.delegateProperties)(client.context, context, ['anonymous_id', 'user_id', 'user_hash', 'user_type']);
30
- }
31
- _modifyPayload({
32
- client,
33
- apiGroup,
34
- apiName,
35
- payload
36
- }) {
37
- if (apiGroup === GROUP.INTERACTIONS && apiName === NAME.UPLOAD) {
38
- return this._modifyPayloadForInteractions(client, payload);
39
- }
40
- if (apiGroup === GROUP.ASK && apiName === NAME.QUESTIONS) {
41
- return this._modifyPayloadForAsk(client, payload);
42
- }
43
- return this._modifyPayloadForOthers(client, payload);
44
- }
45
- _modifyPayloadForOthers(client, payload) {
46
- const {
47
- user_id,
48
- user_hash,
49
- anonymous_id
50
- } = client.context;
51
- const userInfo = user_id ? {
52
- user_id,
53
- user_hash
54
- } : {
55
- anonymous_id
56
- };
57
- return Object.assign({}, userInfo, payload);
58
- }
59
- _modifyPayloadForAsk(client, payload) {
60
- const {
61
- user_id,
62
- user_hash,
63
- user_type,
64
- anonymous_id
65
- } = client.context;
66
- const userInfo = user_id ? {
67
- user_id,
68
- user_hash
69
- } : {
70
- anonymous_id
71
- };
72
- if (user_id && user_type) {
73
- userInfo.user_type = user_type;
74
- }
75
- return Object.assign({}, userInfo, payload);
76
- }
77
- _modifyPayloadForInteractions(client, {
78
- data
79
- }) {
80
- const {
81
- anonymous_id,
82
- user_id
83
- } = client.context;
84
- const userInfo = (0, _commons.trimObj)({
85
- anonymous_id,
86
- user_id
87
- });
88
- data = data.map(obj => Object.assign({}, userInfo, obj));
89
- return {
90
- data
91
- };
92
- }
93
- }
94
- exports.default = UserPlugin;
95
- let _pageBasedAutoAnonymousId;
96
- function getAutoAnonymousId() {
97
- // 1. Cache the value for the page
98
- // 2. Get and set the value from cookies/localStorage is possible
99
- // 3. In case cookies/localStorage are disabled, generate a new value for each page
100
- return _pageBasedAutoAnonymousId || (_pageBasedAutoAnonymousId = (0, _commons.getOrComputeFromStorage)('miso_anonymous_id', _commons.uuidv4));
101
- }
102
- class UserContext {
103
- constructor(plugin) {
104
- this._plugin = plugin;
105
- }
106
- get anonymous_id() {
107
- return this._anonymousId || getAutoAnonymousId();
108
- }
109
- set anonymous_id(value) {
110
- value = (0, _commons.asString)(value);
111
- this._anonymousId = value;
112
- this._plugin._events.emit('set', `anonymous_id = '${value}'`);
113
- }
114
- get user_id() {
115
- return this._userId;
116
- }
117
- set user_id(value) {
118
- value = (0, _commons.asString)(value);
119
- this._userId = value;
120
- this._plugin._events.emit('set', `user_id = '${value}'`);
121
- }
122
- get user_hash() {
123
- return this._userHash;
124
- }
125
- set user_hash(value) {
126
- if (typeof value !== 'string' && typeof value !== 'undefined') {
127
- throw new Error(`User hash must be a string`);
128
- }
129
- this._userHash = value;
130
- this._plugin._events.emit('set', `user_hash = '${value}'`);
131
- }
132
- get user_type() {
133
- return this._userType;
134
- }
135
- set user_type(value) {
136
- this._userType = value;
137
- this._plugin._events.emit('set', `user_type = '${value}'`);
138
- }
139
- }
package/src/plugin/api.js DELETED
@@ -1,37 +0,0 @@
1
- import { Component, API } from '@miso.ai/commons';
2
-
3
- const PLUGIN_ID = 'std:api';
4
-
5
- export default class ApiPlugin extends Component {
6
-
7
- static get id() {
8
- return PLUGIN_ID;
9
- }
10
-
11
- constructor() {
12
- super('api');
13
- }
14
-
15
- install(MisoClient, context) {
16
- context.addSubtree(this);
17
- context.addPayloadPass(this._suppressMetaObject.bind(this));
18
- }
19
-
20
- _suppressMetaObject(args) {
21
- if (!this._shallSuppressMetaObject(args)) {
22
- return args.payload;
23
- }
24
- const { payload: { _meta, ...payload } = {} } = args;
25
- return payload;
26
- }
27
-
28
- _shallSuppressMetaObject({ apiGroup, apiName }) {
29
- switch (apiGroup) {
30
- case API.GROUP.SEARCH:
31
- case API.GROUP.RECOMMENDATION:
32
- return true;
33
- }
34
- return false;
35
- }
36
-
37
- }
@@ -1,120 +0,0 @@
1
- import { API, uuidv4, asString, trimObj, Component, delegateProperties, getOrComputeFromStorage } from '@miso.ai/commons';
2
-
3
- const { GROUP, NAME } = API;
4
-
5
- const PLUGIN_ID = 'std:user';
6
-
7
- export default class UserPlugin extends Component {
8
-
9
- static get id() {
10
- return PLUGIN_ID;
11
- }
12
-
13
- constructor() {
14
- super('user');
15
- this._contexts = new WeakMap();
16
- }
17
-
18
- install(MisoClient, context) {
19
- context.addSubtree(this);
20
- MisoClient.on('create', this._injectClient.bind(this));
21
- context.addPayloadPass(this._modifyPayload.bind(this));
22
- }
23
-
24
- _injectClient(client) {
25
- const context = new UserContext(this);
26
- this._contexts.set(client, context);
27
- delegateProperties(client.context, context, ['anonymous_id', 'user_id', 'user_hash', 'user_type']);
28
- }
29
-
30
- _modifyPayload({ client, apiGroup, apiName, payload }) {
31
- if (apiGroup === GROUP.INTERACTIONS && apiName === NAME.UPLOAD) {
32
- return this._modifyPayloadForInteractions(client, payload);
33
- }
34
- if (apiGroup === GROUP.ASK && apiName === NAME.QUESTIONS) {
35
- return this._modifyPayloadForAsk(client, payload);
36
- }
37
- return this._modifyPayloadForOthers(client, payload);
38
- }
39
-
40
- _modifyPayloadForOthers(client, payload) {
41
- const { user_id, user_hash, anonymous_id } = client.context;
42
- const userInfo = user_id ? { user_id, user_hash } : { anonymous_id };
43
- return { ...userInfo, ...payload };
44
- }
45
-
46
- _modifyPayloadForAsk(client, payload) {
47
- const { user_id, user_hash, user_type, anonymous_id } = client.context;
48
- const userInfo = user_id ? { user_id, user_hash } : { anonymous_id };
49
- if (user_id && user_type) {
50
- userInfo.user_type = user_type;
51
- }
52
- return { ...userInfo, ...payload };
53
- }
54
-
55
- _modifyPayloadForInteractions(client, { data }) {
56
- const { anonymous_id, user_id } = client.context;
57
- const userInfo = trimObj({ anonymous_id, user_id });
58
- data = data.map(obj => ({ ...userInfo, ...obj }));
59
- return { data };
60
- }
61
-
62
- }
63
-
64
- let _pageBasedAutoAnonymousId;
65
-
66
- function getAutoAnonymousId() {
67
- // 1. Cache the value for the page
68
- // 2. Get and set the value from cookies/localStorage is possible
69
- // 3. In case cookies/localStorage are disabled, generate a new value for each page
70
- return _pageBasedAutoAnonymousId || (_pageBasedAutoAnonymousId = getOrComputeFromStorage('miso_anonymous_id', uuidv4));
71
- }
72
-
73
- class UserContext {
74
-
75
- constructor(plugin) {
76
- this._plugin = plugin;
77
- }
78
-
79
- get anonymous_id() {
80
- return this._anonymousId || getAutoAnonymousId();
81
- }
82
-
83
- set anonymous_id(value) {
84
- value = asString(value);
85
- this._anonymousId = value;
86
- this._plugin._events.emit('set', `anonymous_id = '${value}'`);
87
- }
88
-
89
- get user_id() {
90
- return this._userId;
91
- }
92
-
93
- set user_id(value) {
94
- value = asString(value);
95
- this._userId = value;
96
- this._plugin._events.emit('set', `user_id = '${value}'`);
97
- }
98
-
99
- get user_hash() {
100
- return this._userHash;
101
- }
102
-
103
- set user_hash(value) {
104
- if (typeof value !== 'string' && typeof value !== 'undefined') {
105
- throw new Error(`User hash must be a string`);
106
- }
107
- this._userHash = value;
108
- this._plugin._events.emit('set', `user_hash = '${value}'`);
109
- }
110
-
111
- get user_type() {
112
- return this._userType;
113
- }
114
-
115
- set user_type(value) {
116
- this._userType = value;
117
- this._plugin._events.emit('set', `user_type = '${value}'`);
118
- }
119
-
120
- }