@constructor-io/constructorio-client-javascript 2.47.0 → 2.48.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.
- package/lib/constructorio.js +6 -0
- package/lib/modules/assistant.js +205 -0
- package/lib/types/assistant.d.ts +22 -0
- package/lib/types/constructorio.d.ts +4 -1
- package/lib/types/index.d.ts +2 -0
- package/lib/version.js +1 -1
- package/package.json +5 -4
package/lib/constructorio.js
CHANGED
|
@@ -17,6 +17,7 @@ var EventDispatcher = require('./utils/event-dispatcher');
|
|
|
17
17
|
var helpers = require('./utils/helpers');
|
|
18
18
|
var packageVersion = require('./version');
|
|
19
19
|
var Quizzes = require('./modules/quizzes');
|
|
20
|
+
var Assistant = require('./modules/assistant');
|
|
20
21
|
|
|
21
22
|
// Compute package version string
|
|
22
23
|
var computePackageVersion = function computePackageVersion() {
|
|
@@ -40,6 +41,7 @@ var ConstructorIO = /*#__PURE__*/function () {
|
|
|
40
41
|
* @param {string} parameters.apiKey - Constructor.io API key
|
|
41
42
|
* @param {string} [parameters.serviceUrl='https://ac.cnstrc.com'] - API URL endpoint
|
|
42
43
|
* @param {string} [parameters.quizzesServiceUrl='https://quizzes.cnstrc.com'] - Quizzes API URL endpoint
|
|
44
|
+
* @param {string} [parameters.assistantServiceUrl='https://assistant.cnstrc.com'] - AI Assistant API URL endpoint
|
|
43
45
|
* @param {array} [parameters.segments] - User segments
|
|
44
46
|
* @param {object} [parameters.testCells] - User test cells
|
|
45
47
|
* @param {string} [parameters.clientId] - Client ID, defaults to value supplied by 'constructorio-id' module
|
|
@@ -61,6 +63,7 @@ var ConstructorIO = /*#__PURE__*/function () {
|
|
|
61
63
|
* @property {object} recommendations - Interface to {@link module:recommendations}
|
|
62
64
|
* @property {object} tracker - Interface to {@link module:tracker}
|
|
63
65
|
* @property {object} quizzes - Interface to {@link module:quizzes}
|
|
66
|
+
* @property {object} assistant - Interface to {@link module:assistant}
|
|
64
67
|
* @returns {class}
|
|
65
68
|
*/
|
|
66
69
|
function ConstructorIO() {
|
|
@@ -70,6 +73,7 @@ var ConstructorIO = /*#__PURE__*/function () {
|
|
|
70
73
|
versionFromOptions = options.version,
|
|
71
74
|
serviceUrl = options.serviceUrl,
|
|
72
75
|
quizzesServiceUrl = options.quizzesServiceUrl,
|
|
76
|
+
assistantServiceUrl = options.assistantServiceUrl,
|
|
73
77
|
segments = options.segments,
|
|
74
78
|
testCells = options.testCells,
|
|
75
79
|
clientId = options.clientId,
|
|
@@ -112,6 +116,7 @@ var ConstructorIO = /*#__PURE__*/function () {
|
|
|
112
116
|
version: versionFromOptions || versionFromGlobal || computePackageVersion(),
|
|
113
117
|
serviceUrl: helpers.addHTTPSToString(normalizedServiceUrl) || 'https://ac.cnstrc.com',
|
|
114
118
|
quizzesServiceUrl: quizzesServiceUrl && quizzesServiceUrl.replace(/\/$/, '') || 'https://quizzes.cnstrc.com',
|
|
119
|
+
assistantServiceUrl: assistantServiceUrl && assistantServiceUrl.replace(/\/$/, '') || 'https://assistant.cnstrc.com',
|
|
115
120
|
sessionId: sessionId || session_id,
|
|
116
121
|
clientId: clientId || client_id,
|
|
117
122
|
userId: userId,
|
|
@@ -136,6 +141,7 @@ var ConstructorIO = /*#__PURE__*/function () {
|
|
|
136
141
|
this.recommendations = new Recommendations(this.options);
|
|
137
142
|
this.tracker = new Tracker(this.options);
|
|
138
143
|
this.quizzes = new Quizzes(this.options);
|
|
144
|
+
this.assistant = new Assistant(this.options);
|
|
139
145
|
|
|
140
146
|
// Dispatch initialization event
|
|
141
147
|
new EventDispatcher(options.eventDispatcher).queue('instantiated', this.options);
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
5
|
+
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
6
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
7
|
+
var _require = require('../utils/helpers'),
|
|
8
|
+
cleanParams = _require.cleanParams,
|
|
9
|
+
trimNonBreakingSpaces = _require.trimNonBreakingSpaces,
|
|
10
|
+
encodeURIComponentRFC3986 = _require.encodeURIComponentRFC3986,
|
|
11
|
+
stringify = _require.stringify;
|
|
12
|
+
|
|
13
|
+
// Create URL from supplied intent (term) and parameters
|
|
14
|
+
function createAssistantUrl(intent, parameters, options) {
|
|
15
|
+
var apiKey = options.apiKey,
|
|
16
|
+
version = options.version,
|
|
17
|
+
sessionId = options.sessionId,
|
|
18
|
+
clientId = options.clientId,
|
|
19
|
+
userId = options.userId,
|
|
20
|
+
segments = options.segments,
|
|
21
|
+
testCells = options.testCells,
|
|
22
|
+
assistantServiceUrl = options.assistantServiceUrl;
|
|
23
|
+
var queryParams = {
|
|
24
|
+
c: version
|
|
25
|
+
};
|
|
26
|
+
queryParams.key = apiKey;
|
|
27
|
+
queryParams.i = clientId;
|
|
28
|
+
queryParams.s = sessionId;
|
|
29
|
+
|
|
30
|
+
// Validate intent is provided
|
|
31
|
+
if (!intent || typeof intent !== 'string') {
|
|
32
|
+
throw new Error('intent is a required parameter of type string');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Validate domain is provided
|
|
36
|
+
if (!parameters.domain || typeof parameters.domain !== 'string') {
|
|
37
|
+
throw new Error('parameters.domain is a required parameter of type string');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Pull test cells from options
|
|
41
|
+
if (testCells) {
|
|
42
|
+
Object.keys(testCells).forEach(function (testCellKey) {
|
|
43
|
+
queryParams["ef-".concat(testCellKey)] = testCells[testCellKey];
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Pull user segments from options
|
|
48
|
+
if (segments && segments.length) {
|
|
49
|
+
queryParams.us = segments;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Pull user id from options and ensure string
|
|
53
|
+
if (userId) {
|
|
54
|
+
queryParams.ui = String(userId);
|
|
55
|
+
}
|
|
56
|
+
if (parameters) {
|
|
57
|
+
var domain = parameters.domain,
|
|
58
|
+
numResultsPerPage = parameters.numResultsPerPage;
|
|
59
|
+
|
|
60
|
+
// Pull domain from parameters
|
|
61
|
+
if (domain) {
|
|
62
|
+
queryParams.domain = domain;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Pull results number from parameters
|
|
66
|
+
if (numResultsPerPage) {
|
|
67
|
+
queryParams.num_results_per_page = numResultsPerPage;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
72
|
+
queryParams._dt = Date.now();
|
|
73
|
+
queryParams = cleanParams(queryParams);
|
|
74
|
+
var queryString = stringify(queryParams);
|
|
75
|
+
var cleanedQuery = intent.replace(/^\//, '|'); // For compatibility with backend API
|
|
76
|
+
|
|
77
|
+
return "".concat(assistantServiceUrl, "/v1/intent/").concat(encodeURIComponentRFC3986(trimNonBreakingSpaces(cleanedQuery)), "?").concat(queryString);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Add event listeners to custom SSE that pushes data to the stream
|
|
81
|
+
function setupEventListeners(eventSource, controller, eventTypes) {
|
|
82
|
+
var addListener = function addListener(type) {
|
|
83
|
+
eventSource.addEventListener(type, function (event) {
|
|
84
|
+
var data = JSON.parse(event.data);
|
|
85
|
+
controller.enqueue({
|
|
86
|
+
type: type,
|
|
87
|
+
data: data
|
|
88
|
+
}); // Enqueue data into the stream
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Set up listeners for all event types except END
|
|
93
|
+
Object.values(eventTypes).forEach(function (type) {
|
|
94
|
+
if (type !== eventTypes.END) {
|
|
95
|
+
addListener(type);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Handle the END event separately to close the stream
|
|
100
|
+
eventSource.addEventListener(eventTypes.END, function () {
|
|
101
|
+
controller.close(); // Close the stream
|
|
102
|
+
eventSource.close(); // Close the EventSource connection
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Handle errors from the EventSource
|
|
106
|
+
// eslint-disable-next-line no-param-reassign
|
|
107
|
+
eventSource.onerror = function (error) {
|
|
108
|
+
controller.error(error); // Pass the error to the stream
|
|
109
|
+
eventSource.close(); // Close the EventSource connection
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Interface to assistant SSE.
|
|
115
|
+
*
|
|
116
|
+
* @module assistant
|
|
117
|
+
* @inner
|
|
118
|
+
* @returns {object}
|
|
119
|
+
*/
|
|
120
|
+
var Assistant = /*#__PURE__*/function () {
|
|
121
|
+
function Assistant(options) {
|
|
122
|
+
(0, _classCallCheck2["default"])(this, Assistant);
|
|
123
|
+
this.options = options || {};
|
|
124
|
+
}
|
|
125
|
+
(0, _createClass2["default"])(Assistant, [{
|
|
126
|
+
key: "getAssistantResultsStream",
|
|
127
|
+
value:
|
|
128
|
+
/**
|
|
129
|
+
* Retrieve assistant results from EventStream
|
|
130
|
+
*
|
|
131
|
+
* @function getAssistantResultsStream
|
|
132
|
+
* @description Retrieve a stream of assistant results from Constructor.io API
|
|
133
|
+
* @param {string} intent - Intent to use to perform an intent based recommendations
|
|
134
|
+
* @param {object} [parameters] - Additional parameters to refine result set
|
|
135
|
+
* @param {string} [parameters.domain] - domain name e.g. swimming sports gear, groceries
|
|
136
|
+
* @param {number} [parameters.numResultsPerPage] - The total number of results to return
|
|
137
|
+
* @returns {ReadableStream} Returns a ReadableStream.
|
|
138
|
+
* @example
|
|
139
|
+
* const readableStream = constructorio.assistant.getAssistantResultsStream('I want to get shoes', {
|
|
140
|
+
* domain: "nike_sportswear",
|
|
141
|
+
* });
|
|
142
|
+
* const reader = readableStream.getReader();
|
|
143
|
+
* const { value, done } = await reader.read();
|
|
144
|
+
*/
|
|
145
|
+
function getAssistantResultsStream(query, parameters) {
|
|
146
|
+
var eventSource;
|
|
147
|
+
var readableStream;
|
|
148
|
+
try {
|
|
149
|
+
var requestUrl = createAssistantUrl(query, parameters, this.options);
|
|
150
|
+
|
|
151
|
+
// Create an EventSource that connects to the Server Sent Events API
|
|
152
|
+
eventSource = new EventSource(requestUrl);
|
|
153
|
+
|
|
154
|
+
// Create a readable stream that data will be pushed into
|
|
155
|
+
readableStream = new ReadableStream({
|
|
156
|
+
// To be called on stream start
|
|
157
|
+
start: function start(controller) {
|
|
158
|
+
// Listen to events emitted from ASA Server Sent Events and push data to the ReadableStream
|
|
159
|
+
setupEventListeners(eventSource, controller, Assistant.EventTypes);
|
|
160
|
+
},
|
|
161
|
+
// To be called on stream cancelling
|
|
162
|
+
cancel: function cancel() {
|
|
163
|
+
// Close the EventSource connection when the stream is prematurely canceled
|
|
164
|
+
eventSource.close();
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
} catch (e) {
|
|
168
|
+
if (readableStream) {
|
|
169
|
+
var _readableStream;
|
|
170
|
+
(_readableStream = readableStream) === null || _readableStream === void 0 ? void 0 : _readableStream.cancel();
|
|
171
|
+
} else {
|
|
172
|
+
var _eventSource;
|
|
173
|
+
// If the stream was not successfully created, close the EventSource directly
|
|
174
|
+
(_eventSource = eventSource) === null || _eventSource === void 0 ? void 0 : _eventSource.close();
|
|
175
|
+
}
|
|
176
|
+
throw new Error(e.message);
|
|
177
|
+
}
|
|
178
|
+
return readableStream;
|
|
179
|
+
}
|
|
180
|
+
}]);
|
|
181
|
+
return Assistant;
|
|
182
|
+
}();
|
|
183
|
+
(0, _defineProperty2["default"])(Assistant, "EventTypes", {
|
|
184
|
+
START: 'start',
|
|
185
|
+
// Denotes the start of the stream
|
|
186
|
+
GROUP: 'group',
|
|
187
|
+
// Represents a semantic grouping of search results, optionally having textual explanation
|
|
188
|
+
SEARCH_RESULT: 'search_result',
|
|
189
|
+
// Represents a set of results with metadata (used to show results with search refinements)
|
|
190
|
+
ARTICLE_REFERENCE: 'article_reference',
|
|
191
|
+
// Represents a set of content with metadata
|
|
192
|
+
RECIPE_INFO: 'recipe_info',
|
|
193
|
+
// Represents recipes' auxiliary information like cooking times & serving sizes
|
|
194
|
+
RECIPE_INSTRUCTIONS: 'recipe_instructions',
|
|
195
|
+
// Represents recipe instructions
|
|
196
|
+
SERVER_ERROR: 'server_error',
|
|
197
|
+
// Server Error event
|
|
198
|
+
IMAGE_META: 'image_meta',
|
|
199
|
+
// This event type is used for enhancing recommendations with media content such as images
|
|
200
|
+
END: 'end' // Represents the end of data stream
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
module.exports = Assistant;
|
|
204
|
+
module.exports.createAssistantUrl = createAssistantUrl;
|
|
205
|
+
module.exports.setupEventListeners = setupEventListeners;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConstructorClientOptions,
|
|
3
|
+
} from '.';
|
|
4
|
+
|
|
5
|
+
export default Assistant;
|
|
6
|
+
|
|
7
|
+
export interface IAssistantParameters {
|
|
8
|
+
domain: string;
|
|
9
|
+
numResultsPerPage?: number;
|
|
10
|
+
filters?: Record<string, any>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
declare class Assistant {
|
|
14
|
+
constructor(options: ConstructorClientOptions);
|
|
15
|
+
|
|
16
|
+
options: ConstructorClientOptions;
|
|
17
|
+
|
|
18
|
+
getAssistantResultsStream(
|
|
19
|
+
intent: string,
|
|
20
|
+
parameters?: IAssistantParameters,
|
|
21
|
+
): ReadableStream;
|
|
22
|
+
}
|
|
@@ -3,6 +3,7 @@ import Browse from './browse';
|
|
|
3
3
|
import Autocomplete from './autocomplete';
|
|
4
4
|
import Recommendations from './recommendations';
|
|
5
5
|
import Quizzes from './quizzes';
|
|
6
|
+
import Assistant from './assistant';
|
|
6
7
|
import Tracker from './tracker';
|
|
7
8
|
import { ConstructorClientOptions } from '.';
|
|
8
9
|
|
|
@@ -23,11 +24,13 @@ declare class ConstructorIO {
|
|
|
23
24
|
|
|
24
25
|
quizzes: Quizzes;
|
|
25
26
|
|
|
27
|
+
assistant: Assistant;
|
|
28
|
+
|
|
26
29
|
tracker: Tracker;
|
|
27
30
|
|
|
28
31
|
setClientOptions(options: ConstructorClientOptions): void;
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
declare namespace ConstructorIO {
|
|
32
|
-
export { Search, Browse, Autocomplete, Recommendations, Quizzes, Tracker };
|
|
35
|
+
export { Search, Browse, Autocomplete, Recommendations, Quizzes, Tracker, Assistant };
|
|
33
36
|
}
|
package/lib/types/index.d.ts
CHANGED
package/lib/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constructor-io/constructorio-client-javascript",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.48.0",
|
|
4
4
|
"description": "Constructor.io JavaScript client",
|
|
5
5
|
"main": "lib/constructorio.js",
|
|
6
6
|
"types": "lib/types/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"clean": "sudo rm -rf node_modules package-lock.json",
|
|
9
|
-
"
|
|
10
|
-
"version": "npm run verify-node-version && npm run docs && git add ./docs/* && npm run bundle && git add -A ./dist && git add ./src/version.js",
|
|
9
|
+
"version": "node ./src/generateVersion.js && npm run verify-node-version && npm run docs && git add ./docs/* && npm run bundle && git add -A ./dist && git add ./src/version.js",
|
|
11
10
|
"check-license": "license-checker --production --onlyAllow 'Apache-2.0;BSD-3-Clause;MIT;0BSD;BSD-2-Clause'",
|
|
12
11
|
"verify-node-version": "chmod +x ./scripts/verify-node-version.sh && ./scripts/verify-node-version.sh",
|
|
13
12
|
"lint": "eslint 'src/**/*.js' 'spec/**/*.js' 'src/**/*.d.ts'",
|
|
@@ -59,6 +58,7 @@
|
|
|
59
58
|
"eslint": "^8.17.0",
|
|
60
59
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
61
60
|
"eslint-plugin-import": "^2.25.2",
|
|
61
|
+
"eventsource": "^2.0.2",
|
|
62
62
|
"husky": "^7.0.4",
|
|
63
63
|
"jsdoc": "^4.0.2",
|
|
64
64
|
"jsdom": "^16.7.0",
|
|
@@ -69,7 +69,8 @@
|
|
|
69
69
|
"qs": "^6.11.0",
|
|
70
70
|
"sinon": "^7.5.0",
|
|
71
71
|
"sinon-chai": "^3.7.0",
|
|
72
|
-
"tsd": "^0.24.1"
|
|
72
|
+
"tsd": "^0.24.1",
|
|
73
|
+
"web-streams-polyfill": "^4.0.0"
|
|
73
74
|
},
|
|
74
75
|
"dependencies": {
|
|
75
76
|
"@constructor-io/constructorio-id": "^2.4.17",
|