Warp/node_modules/@algolia/client-search/dist/client-search.cjs.js
2024-01-05 19:14:38 +07:00

1380 lines
49 KiB
JavaScript

'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var clientCommon = require('@algolia/client-common');
var transporter = require('@algolia/transporter');
var requesterCommon = require('@algolia/requester-common');
var crypto = require('crypto');
function createBrowsablePromise(options) {
const browse = (data) => {
return options.request(data).then(response => {
/**
* First we send to the developer the
* batch retrieved from the API.
*/
if (options.batch !== undefined) {
options.batch(response.hits);
}
/**
* Then, we ask to the browse concrete implementation
* if we should stop browsing. As example, the `browseObjects`
* method will stop if the cursor is not present on the response.
*/
if (options.shouldStop(response)) {
return undefined;
}
/**
* Finally, if the response contains a cursor, we browse to the next
* batch using that same cursor. Otherwise, we just use the traditional
* browsing using the page element.
*/
if (response.cursor) {
return browse({
cursor: response.cursor,
});
}
return browse({
page: (data.page || 0) + 1,
});
});
};
return browse({});
}
const createSearchClient = options => {
const appId = options.appId;
const auth = clientCommon.createAuth(options.authMode !== undefined ? options.authMode : clientCommon.AuthMode.WithinHeaders, appId, options.apiKey);
const transporter$1 = transporter.createTransporter({
hosts: [
{ url: `${appId}-dsn.algolia.net`, accept: transporter.CallEnum.Read },
{ url: `${appId}.algolia.net`, accept: transporter.CallEnum.Write },
].concat(clientCommon.shuffle([
{ url: `${appId}-1.algolianet.com` },
{ url: `${appId}-2.algolianet.com` },
{ url: `${appId}-3.algolianet.com` },
])),
...options,
headers: {
...auth.headers(),
...{ 'content-type': 'application/x-www-form-urlencoded' },
...options.headers,
},
queryParameters: {
...auth.queryParameters(),
...options.queryParameters,
},
});
const base = {
transporter: transporter$1,
appId,
addAlgoliaAgent(segment, version) {
transporter$1.userAgent.add({ segment, version });
},
clearCache() {
return Promise.all([
transporter$1.requestsCache.clear(),
transporter$1.responsesCache.clear(),
]).then(() => undefined);
},
};
return clientCommon.addMethods(base, options.methods);
};
function createMissingObjectIDError() {
return {
name: 'MissingObjectIDError',
message: 'All objects must have an unique objectID ' +
'(like a primary key) to be valid. ' +
'Algolia is also able to generate objectIDs ' +
"automatically but *it's not recommended*. " +
"To do it, use the `{'autoGenerateObjectIDIfNotExist': true}` option.",
};
}
function createObjectNotFoundError() {
return {
name: 'ObjectNotFoundError',
message: 'Object not found.',
};
}
function createValidUntilNotFoundError() {
return {
name: 'ValidUntilNotFoundError',
message: 'ValidUntil not found in given secured api key.',
};
}
const addApiKey = (base) => {
return (acl, requestOptions) => {
const { queryParameters, ...options } = requestOptions || {};
const data = {
acl,
...(queryParameters !== undefined ? { queryParameters } : {}),
};
const wait = (response, waitRequestOptions) => {
return clientCommon.createRetryablePromise(retry => {
return getApiKey(base)(response.key, waitRequestOptions).catch((apiError) => {
if (apiError.status !== 404) {
throw apiError;
}
return retry();
});
});
};
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: '1/keys',
data,
}, options), wait);
};
};
const assignUserID = (base) => {
return (userID, clusterName, requestOptions) => {
const mappedRequestOptions = transporter.createMappedRequestOptions(requestOptions);
// eslint-disable-next-line functional/immutable-data
mappedRequestOptions.queryParameters['X-Algolia-User-ID'] = userID;
return base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: '1/clusters/mapping',
data: { cluster: clusterName },
}, mappedRequestOptions);
};
};
const assignUserIDs = (base) => {
return (userIDs, clusterName, requestOptions) => {
return base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: '1/clusters/mapping/batch',
data: {
users: userIDs,
cluster: clusterName,
},
}, requestOptions);
};
};
const clearDictionaryEntries = (base) => {
return (dictionary, requestOptions) => {
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('/1/dictionaries/%s/batch', dictionary),
data: {
clearExistingDictionaryEntries: true,
requests: { action: 'addEntry', body: [] },
},
}, requestOptions), (response, waitRequestOptions) => waitAppTask(base)(response.taskID, waitRequestOptions));
};
};
const copyIndex = (base) => {
return (from, to, requestOptions) => {
const wait = (response, waitRequestOptions) => {
return initIndex(base)(from, {
methods: { waitTask },
}).waitTask(response.taskID, waitRequestOptions);
};
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/operation', from),
data: {
operation: 'copy',
destination: to,
},
}, requestOptions), wait);
};
};
const copyRules = (base) => {
return (from, to, requestOptions) => {
return copyIndex(base)(from, to, {
...requestOptions,
scope: [ScopeEnum.Rules],
});
};
};
const copySettings = (base) => {
return (from, to, requestOptions) => {
return copyIndex(base)(from, to, {
...requestOptions,
scope: [ScopeEnum.Settings],
});
};
};
const copySynonyms = (base) => {
return (from, to, requestOptions) => {
return copyIndex(base)(from, to, {
...requestOptions,
scope: [ScopeEnum.Synonyms],
});
};
};
const customRequest = (base) => {
return (request, requestOptions) => {
if (request.method === requesterCommon.MethodEnum.Get) {
return base.transporter.read(request, requestOptions);
}
return base.transporter.write(request, requestOptions);
};
};
const deleteApiKey = (base) => {
return (apiKey, requestOptions) => {
const wait = (_, waitRequestOptions) => {
return clientCommon.createRetryablePromise(retry => {
return getApiKey(base)(apiKey, waitRequestOptions)
.then(retry)
.catch((apiError) => {
if (apiError.status !== 404) {
throw apiError;
}
});
});
};
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Delete,
path: clientCommon.encode('1/keys/%s', apiKey),
}, requestOptions), wait);
};
};
const deleteDictionaryEntries = (base) => {
return (dictionary, objectIDs, requestOptions) => {
const requests = objectIDs.map(objectID => ({
action: 'deleteEntry',
body: { objectID },
}));
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('/1/dictionaries/%s/batch', dictionary),
data: { clearExistingDictionaryEntries: false, requests },
}, requestOptions), (response, waitRequestOptions) => waitAppTask(base)(response.taskID, waitRequestOptions));
};
};
const generateSecuredApiKey = () => {
return (parentApiKey, restrictions) => {
const queryParameters = transporter.serializeQueryParameters(restrictions);
const securedKey = crypto.createHmac('sha256', parentApiKey)
.update(queryParameters)
.digest('hex');
return Buffer.from(securedKey + queryParameters).toString('base64');
};
};
const getApiKey = (base) => {
return (apiKey, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: clientCommon.encode('1/keys/%s', apiKey),
}, requestOptions);
};
};
const getAppTask = (base) => {
return (taskID, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: clientCommon.encode('1/task/%s', taskID.toString()),
}, requestOptions);
};
};
const getDictionarySettings = (base) => {
return (requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: '/1/dictionaries/*/settings',
}, requestOptions);
};
};
const getLogs = (base) => {
return (requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: '1/logs',
}, requestOptions);
};
};
const getSecuredApiKeyRemainingValidity = () => {
return (securedApiKey) => {
const decodedString = Buffer.from(securedApiKey, 'base64').toString('ascii');
const regex = /validUntil=(\d+)/;
const match = decodedString.match(regex);
if (match === null) {
throw createValidUntilNotFoundError();
}
return parseInt(match[1], 10) - Math.round(new Date().getTime() / 1000);
};
};
const getTopUserIDs = (base) => {
return (requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: '1/clusters/mapping/top',
}, requestOptions);
};
};
const getUserID = (base) => {
return (userID, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: clientCommon.encode('1/clusters/mapping/%s', userID),
}, requestOptions);
};
};
const hasPendingMappings = (base) => {
return (requestOptions) => {
const { retrieveMappings, ...options } = requestOptions || {};
if (retrieveMappings === true) {
// eslint-disable-next-line functional/immutable-data
options.getClusters = true;
}
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: '1/clusters/mapping/pending',
}, options);
};
};
const initIndex = (base) => {
return (indexName, options = {}) => {
const searchIndex = {
transporter: base.transporter,
appId: base.appId,
indexName,
};
return clientCommon.addMethods(searchIndex, options.methods);
};
};
const listApiKeys = (base) => {
return (requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: '1/keys',
}, requestOptions);
};
};
const listClusters = (base) => {
return (requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: '1/clusters',
}, requestOptions);
};
};
const listIndices = (base) => {
return (requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: '1/indexes',
}, requestOptions);
};
};
const listUserIDs = (base) => {
return (requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: '1/clusters/mapping',
}, requestOptions);
};
};
const moveIndex = (base) => {
return (from, to, requestOptions) => {
const wait = (response, waitRequestOptions) => {
return initIndex(base)(from, {
methods: { waitTask },
}).waitTask(response.taskID, waitRequestOptions);
};
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/operation', from),
data: {
operation: 'move',
destination: to,
},
}, requestOptions), wait);
};
};
const multipleBatch = (base) => {
return (requests, requestOptions) => {
const wait = (response, waitRequestOptions) => {
return Promise.all(Object.keys(response.taskID).map(indexName => {
return initIndex(base)(indexName, {
methods: { waitTask },
}).waitTask(response.taskID[indexName], waitRequestOptions);
}));
};
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: '1/indexes/*/batch',
data: {
requests,
},
}, requestOptions), wait);
};
};
const multipleGetObjects = (base) => {
return (requests, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Post,
path: '1/indexes/*/objects',
data: {
requests,
},
}, requestOptions);
};
};
const multipleQueries = (base) => {
return (queries, requestOptions) => {
const requests = queries.map(query => {
return {
...query,
params: transporter.serializeQueryParameters(query.params || {}),
};
});
return base.transporter.read({
method: requesterCommon.MethodEnum.Post,
path: '1/indexes/*/queries',
data: {
requests,
},
cacheable: true,
}, requestOptions);
};
};
const multipleSearchForFacetValues = (base) => {
return (queries, requestOptions) => {
return Promise.all(queries.map(query => {
const { facetName, facetQuery, ...params } = query.params;
return initIndex(base)(query.indexName, {
methods: { searchForFacetValues },
}).searchForFacetValues(facetName, facetQuery, {
...requestOptions,
...params,
});
}));
};
};
const removeUserID = (base) => {
return (userID, requestOptions) => {
const mappedRequestOptions = transporter.createMappedRequestOptions(requestOptions);
// eslint-disable-next-line functional/immutable-data
mappedRequestOptions.queryParameters['X-Algolia-User-ID'] = userID;
return base.transporter.write({
method: requesterCommon.MethodEnum.Delete,
path: '1/clusters/mapping',
}, mappedRequestOptions);
};
};
const replaceDictionaryEntries = (base) => {
return (dictionary, entries, requestOptions) => {
const requests = entries.map(entry => ({
action: 'addEntry',
body: entry,
}));
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('/1/dictionaries/%s/batch', dictionary),
data: { clearExistingDictionaryEntries: true, requests },
}, requestOptions), (response, waitRequestOptions) => waitAppTask(base)(response.taskID, waitRequestOptions));
};
};
const restoreApiKey = (base) => {
return (apiKey, requestOptions) => {
const wait = (_, waitRequestOptions) => {
return clientCommon.createRetryablePromise(retry => {
return getApiKey(base)(apiKey, waitRequestOptions).catch((apiError) => {
if (apiError.status !== 404) {
throw apiError;
}
return retry();
});
});
};
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/keys/%s/restore', apiKey),
}, requestOptions), wait);
};
};
const saveDictionaryEntries = (base) => {
return (dictionary, entries, requestOptions) => {
const requests = entries.map(entry => ({
action: 'addEntry',
body: entry,
}));
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('/1/dictionaries/%s/batch', dictionary),
data: { clearExistingDictionaryEntries: false, requests },
}, requestOptions), (response, waitRequestOptions) => waitAppTask(base)(response.taskID, waitRequestOptions));
};
};
const searchDictionaryEntries = (base) => {
return (dictionary, query, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('/1/dictionaries/%s/search', dictionary),
data: {
query,
},
cacheable: true,
}, requestOptions);
};
};
const searchUserIDs = (base) => {
return (query, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Post,
path: '1/clusters/mapping/search',
data: {
query,
},
}, requestOptions);
};
};
const setDictionarySettings = (base) => {
return (settings, requestOptions) => {
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Put,
path: '/1/dictionaries/*/settings',
data: settings,
}, requestOptions), (response, waitRequestOptions) => waitAppTask(base)(response.taskID, waitRequestOptions));
};
};
const updateApiKey = (base) => {
return (apiKey, requestOptions) => {
const updatedFields = Object.assign({}, requestOptions);
const { queryParameters, ...options } = requestOptions || {};
const data = queryParameters ? { queryParameters } : {};
const apiKeyFields = [
'acl',
'indexes',
'referers',
'restrictSources',
'queryParameters',
'description',
'maxQueriesPerIPPerHour',
'maxHitsPerQuery',
];
// Check that all the fields retrieved through getApiKey are the same as the ones we wanted to update
const hasChanged = (getApiKeyResponse) => {
return Object.keys(updatedFields)
.filter((updatedField) => apiKeyFields.indexOf(updatedField) !== -1)
.every(updatedField => {
// If the field is an array, we need to check that they are the same length and that all the values are the same
if (Array.isArray(getApiKeyResponse[updatedField]) &&
Array.isArray(updatedFields[updatedField])) {
const getApiKeyResponseArray = getApiKeyResponse[updatedField];
return (getApiKeyResponseArray.length === updatedFields[updatedField].length &&
getApiKeyResponseArray.every((value, index) => value === updatedFields[updatedField][index]));
}
else {
return getApiKeyResponse[updatedField] === updatedFields[updatedField];
}
});
};
const wait = (_, waitRequestOptions) => clientCommon.createRetryablePromise(retry => {
return getApiKey(base)(apiKey, waitRequestOptions).then(getApiKeyResponse => {
return hasChanged(getApiKeyResponse) ? Promise.resolve() : retry();
});
});
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Put,
path: clientCommon.encode('1/keys/%s', apiKey),
data,
}, options), wait);
};
};
const waitAppTask = (base) => {
return (taskID, requestOptions) => {
return clientCommon.createRetryablePromise(retry => {
return getAppTask(base)(taskID, requestOptions).then(response => {
return response.status !== 'published' ? retry() : undefined;
});
});
};
};
const batch = (base) => {
return (requests, requestOptions) => {
const wait = (response, waitRequestOptions) => {
return waitTask(base)(response.taskID, waitRequestOptions);
};
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/batch', base.indexName),
data: {
requests,
},
}, requestOptions), wait);
};
};
const browseObjects = (base) => {
return (requestOptions) => {
return createBrowsablePromise({
shouldStop: response => response.cursor === undefined,
...requestOptions,
request: (data) => base.transporter.read({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/browse', base.indexName),
data,
}, requestOptions),
});
};
};
const browseRules = (base) => {
return (requestOptions) => {
const options = {
hitsPerPage: 1000,
...requestOptions,
};
return createBrowsablePromise({
shouldStop: response => response.hits.length < options.hitsPerPage,
...options,
request(data) {
return searchRules(base)('', { ...options, ...data }).then((response) => {
return {
...response,
hits: response.hits.map(rule => {
// eslint-disable-next-line functional/immutable-data,no-param-reassign
delete rule._highlightResult;
return rule;
}),
};
});
},
});
};
};
const browseSynonyms = (base) => {
return (requestOptions) => {
const options = {
hitsPerPage: 1000,
...requestOptions,
};
return createBrowsablePromise({
shouldStop: response => response.hits.length < options.hitsPerPage,
...options,
request(data) {
return searchSynonyms(base)('', { ...options, ...data }).then((response) => {
return {
...response,
hits: response.hits.map(synonym => {
// eslint-disable-next-line functional/immutable-data,no-param-reassign
delete synonym._highlightResult;
return synonym;
}),
};
});
},
});
};
};
const chunkedBatch = (base) => {
return (bodies, action, requestOptions) => {
const { batchSize, ...options } = requestOptions || {};
const response = {
taskIDs: [],
objectIDs: [],
};
const forEachBatch = (lastIndex = 0) => {
// eslint-disable-next-line functional/prefer-readonly-type
const bodiesChunk = [];
// eslint-disable-next-line functional/no-let
let index;
/* eslint-disable-next-line functional/no-loop-statement */
for (index = lastIndex; index < bodies.length; index++) {
// eslint-disable-next-line functional/immutable-data
bodiesChunk.push(bodies[index]);
if (bodiesChunk.length === (batchSize || 1000)) {
break;
}
}
if (bodiesChunk.length === 0) {
return Promise.resolve(response);
}
return batch(base)(bodiesChunk.map(body => {
return {
action,
body,
};
}), options).then(res => {
response.objectIDs = response.objectIDs.concat(res.objectIDs); // eslint-disable-line functional/immutable-data
response.taskIDs.push(res.taskID); // eslint-disable-line functional/immutable-data
index++;
return forEachBatch(index);
});
};
return clientCommon.createWaitablePromise(forEachBatch(), (chunkedBatchResponse, waitRequestOptions) => {
return Promise.all(chunkedBatchResponse.taskIDs.map(taskID => {
return waitTask(base)(taskID, waitRequestOptions);
}));
});
};
};
const clearObjects = (base) => {
return (requestOptions) => {
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/clear', base.indexName),
}, requestOptions), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const clearRules = (base) => {
return (requestOptions) => {
const { forwardToReplicas, ...options } = requestOptions || {};
const mappedRequestOptions = transporter.createMappedRequestOptions(options);
if (forwardToReplicas) {
mappedRequestOptions.queryParameters.forwardToReplicas = 1; // eslint-disable-line functional/immutable-data
}
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/rules/clear', base.indexName),
}, mappedRequestOptions), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const clearSynonyms = (base) => {
return (requestOptions) => {
const { forwardToReplicas, ...options } = requestOptions || {};
const mappedRequestOptions = transporter.createMappedRequestOptions(options);
if (forwardToReplicas) {
mappedRequestOptions.queryParameters.forwardToReplicas = 1; // eslint-disable-line functional/immutable-data
}
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/synonyms/clear', base.indexName),
}, mappedRequestOptions), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const deleteBy = (base) => {
return (filters, requestOptions) => {
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/deleteByQuery', base.indexName),
data: filters,
}, requestOptions), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const deleteIndex = (base) => {
return (requestOptions) => {
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Delete,
path: clientCommon.encode('1/indexes/%s', base.indexName),
}, requestOptions), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const deleteObject = (base) => {
return (objectID, requestOptions) => {
return clientCommon.createWaitablePromise(deleteObjects(base)([objectID], requestOptions).then(response => {
return { taskID: response.taskIDs[0] };
}), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const deleteObjects = (base) => {
return (objectIDs, requestOptions) => {
const objects = objectIDs.map(objectID => {
return { objectID };
});
return chunkedBatch(base)(objects, BatchActionEnum.DeleteObject, requestOptions);
};
};
const deleteRule = (base) => {
return (objectID, requestOptions) => {
const { forwardToReplicas, ...options } = requestOptions || {};
const mappedRequestOptions = transporter.createMappedRequestOptions(options);
if (forwardToReplicas) {
mappedRequestOptions.queryParameters.forwardToReplicas = 1; // eslint-disable-line functional/immutable-data
}
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Delete,
path: clientCommon.encode('1/indexes/%s/rules/%s', base.indexName, objectID),
}, mappedRequestOptions), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const deleteSynonym = (base) => {
return (objectID, requestOptions) => {
const { forwardToReplicas, ...options } = requestOptions || {};
const mappedRequestOptions = transporter.createMappedRequestOptions(options);
if (forwardToReplicas) {
mappedRequestOptions.queryParameters.forwardToReplicas = 1; // eslint-disable-line functional/immutable-data
}
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Delete,
path: clientCommon.encode('1/indexes/%s/synonyms/%s', base.indexName, objectID),
}, mappedRequestOptions), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const exists = (base) => {
return (requestOptions) => {
return getSettings(base)(requestOptions)
.then(() => true)
.catch(error => {
if (error.status !== 404) {
throw error;
}
return false;
});
};
};
const findAnswers = (base) => {
return (query, queryLanguages, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/answers/%s/prediction', base.indexName),
data: {
query,
queryLanguages,
},
cacheable: true,
}, requestOptions);
};
};
const findObject = (base) => {
return (callback, requestOptions) => {
const { query, paginate, ...options } = requestOptions || {};
// eslint-disable-next-line functional/no-let
let page = 0;
const forEachPage = () => {
return search(base)(query || '', { ...options, page }).then(result => {
// eslint-disable-next-line functional/no-loop-statement
for (const [position, hit] of Object.entries(result.hits)) {
// eslint-disable-next-line promise/no-callback-in-promise
if (callback(hit)) {
return {
object: hit,
position: parseInt(position, 10),
page,
};
}
}
page++;
// paginate if option was set and has next page
if (paginate === false || page >= result.nbPages) {
throw createObjectNotFoundError();
}
return forEachPage();
});
};
return forEachPage();
};
};
const getObject = (base) => {
return (objectID, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: clientCommon.encode('1/indexes/%s/%s', base.indexName, objectID),
}, requestOptions);
};
};
const getObjectPosition = () => {
return (searchResponse, objectID) => {
// eslint-disable-next-line functional/no-loop-statement
for (const [position, hit] of Object.entries(searchResponse.hits)) {
if (hit.objectID === objectID) {
return parseInt(position, 10);
}
}
return -1;
};
};
const getObjects = (base) => {
return (objectIDs, requestOptions) => {
const { attributesToRetrieve, ...options } = requestOptions || {};
const requests = objectIDs.map(objectID => {
return {
indexName: base.indexName,
objectID,
...(attributesToRetrieve ? { attributesToRetrieve } : {}),
};
});
return base.transporter.read({
method: requesterCommon.MethodEnum.Post,
path: '1/indexes/*/objects',
data: {
requests,
},
}, options);
};
};
const getRule = (base) => {
return (objectID, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: clientCommon.encode('1/indexes/%s/rules/%s', base.indexName, objectID),
}, requestOptions);
};
};
const getSettings = (base) => {
return (requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: clientCommon.encode('1/indexes/%s/settings', base.indexName),
data: {
getVersion: 2,
},
}, requestOptions);
};
};
const getSynonym = (base) => {
return (objectID, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: clientCommon.encode(`1/indexes/%s/synonyms/%s`, base.indexName, objectID),
}, requestOptions);
};
};
const getTask = (base) => {
return (taskID, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Get,
path: clientCommon.encode('1/indexes/%s/task/%s', base.indexName, taskID.toString()),
}, requestOptions);
};
};
const partialUpdateObject = (base) => {
return (object, requestOptions) => {
return clientCommon.createWaitablePromise(partialUpdateObjects(base)([object], requestOptions).then(response => {
return {
objectID: response.objectIDs[0],
taskID: response.taskIDs[0],
};
}), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const partialUpdateObjects = (base) => {
return (objects, requestOptions) => {
const { createIfNotExists, ...options } = requestOptions || {};
const action = createIfNotExists
? BatchActionEnum.PartialUpdateObject
: BatchActionEnum.PartialUpdateObjectNoCreate;
return chunkedBatch(base)(objects, action, options);
};
};
const replaceAllObjects = (base) => {
return (objects, requestOptions) => {
const { safe, autoGenerateObjectIDIfNotExist, batchSize, ...options } = requestOptions || {};
const operation = (from, to, type, operationRequestOptions) => {
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/operation', from),
data: {
operation: type,
destination: to,
},
}, operationRequestOptions), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
const randomSuffix = Math.random()
.toString(36)
.substring(7);
const temporaryIndexName = `${base.indexName}_tmp_${randomSuffix}`;
const saveObjectsInTemporary = saveObjects({
appId: base.appId,
transporter: base.transporter,
indexName: temporaryIndexName,
});
// @ts-ignore
// eslint-disable-next-line prefer-const, functional/no-let, functional/prefer-readonly-type
let responses = [];
const copyWaitablePromise = operation(base.indexName, temporaryIndexName, 'copy', {
...options,
scope: ['settings', 'synonyms', 'rules'],
});
// eslint-disable-next-line functional/immutable-data
responses.push(copyWaitablePromise);
const result = (safe
? copyWaitablePromise.wait(options)
: copyWaitablePromise)
.then(() => {
const saveObjectsWaitablePromise = saveObjectsInTemporary(objects, {
...options,
autoGenerateObjectIDIfNotExist,
batchSize,
});
// eslint-disable-next-line functional/immutable-data
responses.push(saveObjectsWaitablePromise);
return safe ? saveObjectsWaitablePromise.wait(options) : saveObjectsWaitablePromise;
})
.then(() => {
const moveWaitablePromise = operation(temporaryIndexName, base.indexName, 'move', options);
// eslint-disable-next-line functional/immutable-data
responses.push(moveWaitablePromise);
return safe ? moveWaitablePromise.wait(options) : moveWaitablePromise;
})
.then(() => Promise.all(responses))
.then(([copyResponse, saveObjectsResponse, moveResponse]) => {
return {
objectIDs: saveObjectsResponse.objectIDs,
taskIDs: [copyResponse.taskID, ...saveObjectsResponse.taskIDs, moveResponse.taskID],
};
});
return clientCommon.createWaitablePromise(result, (_, waitRequestOptions) => {
return Promise.all(responses.map(response => response.wait(waitRequestOptions)));
});
};
};
const replaceAllRules = (base) => {
return (rules, requestOptions) => {
return saveRules(base)(rules, {
...requestOptions,
clearExistingRules: true,
});
};
};
const replaceAllSynonyms = (base) => {
return (synonyms, requestOptions) => {
return saveSynonyms(base)(synonyms, {
...requestOptions,
clearExistingSynonyms: true,
});
};
};
const saveObject = (base) => {
return (object, requestOptions) => {
return clientCommon.createWaitablePromise(saveObjects(base)([object], requestOptions).then(response => {
return {
objectID: response.objectIDs[0],
taskID: response.taskIDs[0],
};
}), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const saveObjects = (base) => {
return (objects, requestOptions) => {
const { autoGenerateObjectIDIfNotExist, ...options } = requestOptions || {};
const action = autoGenerateObjectIDIfNotExist
? BatchActionEnum.AddObject
: BatchActionEnum.UpdateObject;
if (action === BatchActionEnum.UpdateObject) {
// eslint-disable-next-line functional/no-loop-statement
for (const object of objects) {
if (object.objectID === undefined) {
return clientCommon.createWaitablePromise(Promise.reject(createMissingObjectIDError()));
}
}
}
return chunkedBatch(base)(objects, action, options);
};
};
const saveRule = (base) => {
return (rule, requestOptions) => {
return saveRules(base)([rule], requestOptions);
};
};
const saveRules = (base) => {
return (rules, requestOptions) => {
const { forwardToReplicas, clearExistingRules, ...options } = requestOptions || {};
const mappedRequestOptions = transporter.createMappedRequestOptions(options);
if (forwardToReplicas) {
mappedRequestOptions.queryParameters.forwardToReplicas = 1; // eslint-disable-line functional/immutable-data
}
if (clearExistingRules) {
mappedRequestOptions.queryParameters.clearExistingRules = 1; // eslint-disable-line functional/immutable-data
}
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/rules/batch', base.indexName),
data: rules,
}, mappedRequestOptions), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const saveSynonym = (base) => {
return (synonym, requestOptions) => {
return saveSynonyms(base)([synonym], requestOptions);
};
};
const saveSynonyms = (base) => {
return (synonyms, requestOptions) => {
const { forwardToReplicas, clearExistingSynonyms, replaceExistingSynonyms, ...options } = requestOptions || {};
const mappedRequestOptions = transporter.createMappedRequestOptions(options);
if (forwardToReplicas) {
mappedRequestOptions.queryParameters.forwardToReplicas = 1; // eslint-disable-line functional/immutable-data
}
if (replaceExistingSynonyms || clearExistingSynonyms) {
mappedRequestOptions.queryParameters.replaceExistingSynonyms = 1; // eslint-disable-line functional/immutable-data
}
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/synonyms/batch', base.indexName),
data: synonyms,
}, mappedRequestOptions), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const search = (base) => {
return (query, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/query', base.indexName),
data: {
query,
},
cacheable: true,
}, requestOptions);
};
};
const searchForFacetValues = (base) => {
return (facetName, facetQuery, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/facets/%s/query', base.indexName, facetName),
data: {
facetQuery,
},
cacheable: true,
}, requestOptions);
};
};
const searchRules = (base) => {
return (query, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/rules/search', base.indexName),
data: {
query,
},
}, requestOptions);
};
};
const searchSynonyms = (base) => {
return (query, requestOptions) => {
return base.transporter.read({
method: requesterCommon.MethodEnum.Post,
path: clientCommon.encode('1/indexes/%s/synonyms/search', base.indexName),
data: {
query,
},
}, requestOptions);
};
};
const setSettings = (base) => {
return (settings, requestOptions) => {
const { forwardToReplicas, ...options } = requestOptions || {};
const mappedRequestOptions = transporter.createMappedRequestOptions(options);
if (forwardToReplicas) {
mappedRequestOptions.queryParameters.forwardToReplicas = 1; // eslint-disable-line functional/immutable-data
}
return clientCommon.createWaitablePromise(base.transporter.write({
method: requesterCommon.MethodEnum.Put,
path: clientCommon.encode('1/indexes/%s/settings', base.indexName),
data: settings,
}, mappedRequestOptions), (response, waitRequestOptions) => waitTask(base)(response.taskID, waitRequestOptions));
};
};
const waitTask = (base) => {
return (taskID, requestOptions) => {
return clientCommon.createRetryablePromise(retry => {
return getTask(base)(taskID, requestOptions).then(response => {
return response.status !== 'published' ? retry() : undefined;
});
});
};
};
const ApiKeyACLEnum = {
AddObject: 'addObject',
Analytics: 'analytics',
Browser: 'browse',
DeleteIndex: 'deleteIndex',
DeleteObject: 'deleteObject',
EditSettings: 'editSettings',
Inference: 'inference',
ListIndexes: 'listIndexes',
Logs: 'logs',
Personalization: 'personalization',
Recommendation: 'recommendation',
Search: 'search',
SeeUnretrievableAttributes: 'seeUnretrievableAttributes',
Settings: 'settings',
Usage: 'usage',
};
const BatchActionEnum = {
AddObject: 'addObject',
UpdateObject: 'updateObject',
PartialUpdateObject: 'partialUpdateObject',
PartialUpdateObjectNoCreate: 'partialUpdateObjectNoCreate',
DeleteObject: 'deleteObject',
DeleteIndex: 'delete',
ClearIndex: 'clear',
};
const ScopeEnum = {
Settings: 'settings',
Synonyms: 'synonyms',
Rules: 'rules',
};
const StrategyEnum = {
None: 'none',
StopIfEnoughMatches: 'stopIfEnoughMatches',
};
const SynonymEnum = {
Synonym: 'synonym',
OneWaySynonym: 'oneWaySynonym',
AltCorrection1: 'altCorrection1',
AltCorrection2: 'altCorrection2',
Placeholder: 'placeholder',
};
exports.ApiKeyACLEnum = ApiKeyACLEnum;
exports.BatchActionEnum = BatchActionEnum;
exports.ScopeEnum = ScopeEnum;
exports.StrategyEnum = StrategyEnum;
exports.SynonymEnum = SynonymEnum;
exports.addApiKey = addApiKey;
exports.assignUserID = assignUserID;
exports.assignUserIDs = assignUserIDs;
exports.batch = batch;
exports.browseObjects = browseObjects;
exports.browseRules = browseRules;
exports.browseSynonyms = browseSynonyms;
exports.chunkedBatch = chunkedBatch;
exports.clearDictionaryEntries = clearDictionaryEntries;
exports.clearObjects = clearObjects;
exports.clearRules = clearRules;
exports.clearSynonyms = clearSynonyms;
exports.copyIndex = copyIndex;
exports.copyRules = copyRules;
exports.copySettings = copySettings;
exports.copySynonyms = copySynonyms;
exports.createBrowsablePromise = createBrowsablePromise;
exports.createMissingObjectIDError = createMissingObjectIDError;
exports.createObjectNotFoundError = createObjectNotFoundError;
exports.createSearchClient = createSearchClient;
exports.createValidUntilNotFoundError = createValidUntilNotFoundError;
exports.customRequest = customRequest;
exports.deleteApiKey = deleteApiKey;
exports.deleteBy = deleteBy;
exports.deleteDictionaryEntries = deleteDictionaryEntries;
exports.deleteIndex = deleteIndex;
exports.deleteObject = deleteObject;
exports.deleteObjects = deleteObjects;
exports.deleteRule = deleteRule;
exports.deleteSynonym = deleteSynonym;
exports.exists = exists;
exports.findAnswers = findAnswers;
exports.findObject = findObject;
exports.generateSecuredApiKey = generateSecuredApiKey;
exports.getApiKey = getApiKey;
exports.getAppTask = getAppTask;
exports.getDictionarySettings = getDictionarySettings;
exports.getLogs = getLogs;
exports.getObject = getObject;
exports.getObjectPosition = getObjectPosition;
exports.getObjects = getObjects;
exports.getRule = getRule;
exports.getSecuredApiKeyRemainingValidity = getSecuredApiKeyRemainingValidity;
exports.getSettings = getSettings;
exports.getSynonym = getSynonym;
exports.getTask = getTask;
exports.getTopUserIDs = getTopUserIDs;
exports.getUserID = getUserID;
exports.hasPendingMappings = hasPendingMappings;
exports.initIndex = initIndex;
exports.listApiKeys = listApiKeys;
exports.listClusters = listClusters;
exports.listIndices = listIndices;
exports.listUserIDs = listUserIDs;
exports.moveIndex = moveIndex;
exports.multipleBatch = multipleBatch;
exports.multipleGetObjects = multipleGetObjects;
exports.multipleQueries = multipleQueries;
exports.multipleSearchForFacetValues = multipleSearchForFacetValues;
exports.partialUpdateObject = partialUpdateObject;
exports.partialUpdateObjects = partialUpdateObjects;
exports.removeUserID = removeUserID;
exports.replaceAllObjects = replaceAllObjects;
exports.replaceAllRules = replaceAllRules;
exports.replaceAllSynonyms = replaceAllSynonyms;
exports.replaceDictionaryEntries = replaceDictionaryEntries;
exports.restoreApiKey = restoreApiKey;
exports.saveDictionaryEntries = saveDictionaryEntries;
exports.saveObject = saveObject;
exports.saveObjects = saveObjects;
exports.saveRule = saveRule;
exports.saveRules = saveRules;
exports.saveSynonym = saveSynonym;
exports.saveSynonyms = saveSynonyms;
exports.search = search;
exports.searchDictionaryEntries = searchDictionaryEntries;
exports.searchForFacetValues = searchForFacetValues;
exports.searchRules = searchRules;
exports.searchSynonyms = searchSynonyms;
exports.searchUserIDs = searchUserIDs;
exports.setDictionarySettings = setDictionarySettings;
exports.setSettings = setSettings;
exports.updateApiKey = updateApiKey;
exports.waitAppTask = waitAppTask;
exports.waitTask = waitTask;