Skip to content

feat(recommend): introduce Recommend API client #1280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,12 @@ module.exports = {
['@algolia/client-account', './packages/client-account/src'],
['@algolia/client-analytics', './packages/client-analytics/src'],
['@algolia/client-common', './packages/client-common/src'],
['@algolia/client-search', './packages/client-search/src'],
['@algolia/client-personalization', './packages/client-personalization/src'],
['@algolia/client-recommendation', './packages/client-recommendation/src'],
['@algolia/client-search', './packages/client-search/src'],
['@algolia/logger-common', './packages/logger-common/src'],
['@algolia/logger-console', './packages/logger-console/src'],
['@algolia/recommend', './packages/recommend/src'],
['@algolia/requester-browser-xhr', './packages/requester-browser-xhr/src'],
['@algolia/requester-common', './packages/requester-common/src'],
['@algolia/requester-node-http', './packages/requester-node-http/src'],
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<a href="https://npmjs.org/package/algoliasearch"><img src="https://img.shields.io/npm/v/algoliasearch.svg?style=flat-square" alt="NPM version"></img></a>
<a href="http://npm-stat.com/charts.html?package=algoliasearch"><img src="https://img.shields.io/npm/dm/algoliasearch.svg?style=flat-square" alt="NPM downloads"></a>
<a href="https://www.jsdelivr.com/package/npm/algoliasearch"><img src="https://data.jsdelivr.com/v1/package/npm/algoliasearch/badge" alt="jsDelivr Downloads"></img></a>
<a href="LICENSE.txt"><img src="https://img.shields.io/badge/license-MIT-green.svg?style=flat-square" alt="License"></a>
<a href="LICENSE.md"><img src="https://img.shields.io/badge/license-MIT-green.svg?style=flat-square" alt="License"></a>
</p>
</p>

Expand Down Expand Up @@ -88,4 +88,4 @@ Encountering an issue? Before reaching out to support, we recommend heading to o

## 📄 License

Algolia JavaScript API Client is an open-sourced software licensed under the [MIT license](LICENSE.txt).
Algolia JavaScript API Client is an open-sourced software licensed under the [MIT license](LICENSE.md).
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"version": "4.9.3",
"private": true,
"license": "MIT",
"version": "4.9.3",
"workspaces": [
"packages/*"
],
Expand Down Expand Up @@ -98,11 +98,15 @@
"bundlesize": [
{
"path": "packages/algoliasearch/dist/algoliasearch.umd.js",
"maxSize": "7.85KB"
"maxSize": "7.95KB"
},
{
"path": "packages/algoliasearch/dist/algoliasearch-lite.umd.js",
"maxSize": "4.35KB"
},
{
"path": "packages/recommend/dist/recommend.umd.js",
"maxSize": "4.1KB"
}
]
}
4 changes: 2 additions & 2 deletions packages/algoliasearch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<a href="https://npmjs.org/package/algoliasearch"><img src="https://img.shields.io/npm/v/algoliasearch.svg?style=flat-square" alt="NPM version"></img></a>
<a href="http://npm-stat.com/charts.html?package=algoliasearch"><img src="https://img.shields.io/npm/dm/algoliasearch.svg?style=flat-square" alt="NPM downloads"></a>
<a href="https://www.jsdelivr.com/package/npm/algoliasearch"><img src="https://data.jsdelivr.com/v1/package/npm/algoliasearch/badge" alt="jsDelivr Downloads"></img></a>
<a href="LICENSE.txt"><img src="https://img.shields.io/badge/license-MIT-green.svg?style=flat-square" alt="License"></a>
<a href="LICENSE.md"><img src="https://img.shields.io/badge/license-MIT-green.svg?style=flat-square" alt="License"></a>
</p>
</p>

Expand Down Expand Up @@ -79,4 +79,4 @@ For full documentation, visit the **[online documentation](https://www.algolia.c

## 📄 License

Algolia JavaScript API Client is an open-sourced software licensed under the [MIT license](LICENSE.txt).
Algolia JavaScript API Client is an open-sourced software licensed under the [MIT license](LICENSE.md).
2 changes: 1 addition & 1 deletion packages/algoliasearch/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@algolia/client-account": "4.9.3",
"@algolia/client-analytics": "4.9.3",
"@algolia/client-common": "4.9.3",
"@algolia/client-recommendation": "4.9.3",
"@algolia/client-personalization": "4.9.3",
"@algolia/client-search": "4.9.3",
"@algolia/logger-common": "4.9.3",
"@algolia/logger-console": "4.9.3",
Expand Down
30 changes: 15 additions & 15 deletions packages/algoliasearch/src/__tests__/default.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ describe('default preset', () => {

expect(client.transporter.requestsCache).not.toBe(cache);
expect(customClient.transporter.requestsCache).toBe(cache);
expect(customClient.initRecommendation().transporter.requestsCache).not.toBe(cache);
expect(customClient.initPersonalization().transporter.requestsCache).not.toBe(cache);
expect(customClient.initAnalytics({ requestsCache: cache }).transporter.requestsCache).toBe(
cache
);
Expand All @@ -92,7 +92,7 @@ describe('default preset', () => {
read: 46,
write: 47,
});
expect(customClient.initRecommendation().transporter.timeouts).toEqual({
expect(customClient.initPersonalization().transporter.timeouts).toEqual({
connect: testing.isBrowser() ? 1 : 2,
read: testing.isBrowser() ? 2 : 5,
write: 30,
Expand All @@ -110,7 +110,7 @@ describe('default preset', () => {
expect(customClient.transporter.hosts).toEqual([createStatelessHost({ url: 'foo.com' })]);

expect(customClient.initAnalytics().transporter.queryParameters).toEqual({});
expect(customClient.initRecommendation().transporter.headers).toEqual({
expect(customClient.initPersonalization().transporter.headers).toEqual({
'content-type': 'application/json',
'x-algolia-application-id': 'appId',
'x-algolia-api-key': 'apiKey',
Expand All @@ -119,31 +119,31 @@ describe('default preset', () => {
createStatelessHost({ url: 'foo.com' }),
]);

expect(customClient.initRecommendation().transporter.queryParameters).not.toEqual({
expect(customClient.initPersonalization().transporter.queryParameters).not.toEqual({
queryParameter: 'bar',
});

expect(customClient.initRecommendation().transporter.headers).toEqual({
expect(customClient.initPersonalization().transporter.headers).toEqual({
'content-type': 'application/json',
'x-algolia-application-id': 'appId',
'x-algolia-api-key': 'apiKey',
});
expect(customClient.initRecommendation().transporter.hosts).not.toEqual([
expect(customClient.initPersonalization().transporter.hosts).not.toEqual([
createStatelessHost({ url: 'foo.com' }),
]);
});

test('shared implementations between clients', () => {
const analytics = client.initAnalytics();
const recommendation = client.initRecommendation();
const personalization = client.initPersonalization();

expect(analytics.transporter).not.toBe(client.transporter);
expect(analytics.transporter.hostsCache).toBe(client.transporter.hostsCache);
expect(analytics.transporter.userAgent).toBe(client.transporter.userAgent);

expect(recommendation.transporter).not.toBe(client.transporter);
expect(recommendation.transporter.hostsCache).toBe(client.transporter.hostsCache);
expect(recommendation.transporter.userAgent).toBe(client.transporter.userAgent);
expect(personalization.transporter).not.toBe(client.transporter);
expect(personalization.transporter.hostsCache).toBe(client.transporter.hostsCache);
expect(personalization.transporter.userAgent).toBe(client.transporter.userAgent);
});

test('allows clients to override credentials', () => {
Expand All @@ -154,12 +154,12 @@ describe('default preset', () => {
const analytics = clientWithOptions.initAnalytics({
apiKey: 'analytics',
});
const recommendation = clientWithOptions.initRecommendation({
apiKey: 'recommendation',
const personalization = clientWithOptions.initPersonalization({
apiKey: 'personalization',
});

expect(analytics.transporter.headers['x-algolia-api-key']).toBe('analytics');
expect(recommendation.transporter.headers['x-algolia-api-key']).toBe('recommendation');
expect(personalization.transporter.headers['x-algolia-api-key']).toBe('personalization');
});

test('allows clients to keep default credentials', () => {
Expand All @@ -168,10 +168,10 @@ describe('default preset', () => {
expect(clientWithOptions.transporter.headers['x-algolia-api-key']).toBe('apiKey');

const analytics = clientWithOptions.initAnalytics();
const recommendation = clientWithOptions.initRecommendation();
const personalization = clientWithOptions.initPersonalization();

expect(analytics.transporter.headers['x-algolia-api-key']).toBe('apiKey');
expect(recommendation.transporter.headers['x-algolia-api-key']).toBe('apiKey');
expect(personalization.transporter.headers['x-algolia-api-key']).toBe('apiKey');
});

it('can be destroyed', () => {
Expand Down
55 changes: 37 additions & 18 deletions packages/algoliasearch/src/builds/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ import {
} from '@algolia/client-analytics';
import { version, WaitablePromise } from '@algolia/client-common';
import {
createRecommendationClient,
createPersonalizationClient,
getPersonalizationStrategy,
GetPersonalizationStrategyResponse,
PersonalizationClient as BasePersonalizationClient,
PersonalizationStrategy,
RecommendationClient as BaseRecommendationClient,
setPersonalizationStrategy,
SetPersonalizationStrategyResponse,
} from '@algolia/client-recommendation';
} from '@algolia/client-personalization';
import {
addApiKey,
AddApiKeyOptions,
Expand Down Expand Up @@ -192,7 +192,7 @@ import { createConsoleLogger } from '@algolia/logger-console';
import { createBrowserXhrRequester } from '@algolia/requester-browser-xhr';
import { createUserAgent, RequestOptions } from '@algolia/transporter';

import { AlgoliaSearchOptions, InitAnalyticsOptions, InitRecommendationOptions } from '../types';
import { AlgoliaSearchOptions, InitAnalyticsOptions, InitPersonalizationOptions } from '../types';

export default function algoliasearch(
appId: string,
Expand All @@ -219,10 +219,22 @@ export default function algoliasearch(
}),
userAgent: createUserAgent(version).add({ segment: 'Browser' }),
};
const searchClientOptions = { ...commonOptions, ...options };
const initPersonalization = () => (
clientOptions?: InitPersonalizationOptions
): PersonalizationClient => {
return createPersonalizationClient({
...commonOptions,
...clientOptions,
methods: {
getPersonalizationStrategy,
setPersonalizationStrategy,
},
});
};

return createSearchClient({
...commonOptions,
...options,
...searchClientOptions,
methods: {
search: multipleQueries,
searchForFacetValues: multipleSearchForFacetValues,
Expand Down Expand Up @@ -319,17 +331,15 @@ export default function algoliasearch(
},
});
},
initPersonalization,
initRecommendation: () => (
clientOptions?: InitRecommendationOptions
): RecommendationClient => {
return createRecommendationClient({
...commonOptions,
...clientOptions,
methods: {
getPersonalizationStrategy,
setPersonalizationStrategy,
},
});
clientOptions?: InitPersonalizationOptions
): PersonalizationClient => {
searchClientOptions.logger.info(
'The `initRecommendation` method is deprecated. Use `initPersonalization` instead.'
);

return initPersonalization()(clientOptions);
},
},
});
Expand All @@ -338,7 +348,7 @@ export default function algoliasearch(
// eslint-disable-next-line functional/immutable-data
algoliasearch.version = version;

export type RecommendationClient = BaseRecommendationClient & {
export type PersonalizationClient = BasePersonalizationClient & {
readonly getPersonalizationStrategy: (
requestOptions?: RequestOptions
) => Readonly<Promise<GetPersonalizationStrategyResponse>>;
Expand All @@ -348,6 +358,11 @@ export type RecommendationClient = BaseRecommendationClient & {
) => Readonly<Promise<SetPersonalizationStrategyResponse>>;
};

/**
* @deprecated Use `PersonalizationClient` instead.
*/
export type RecommendationClient = PersonalizationClient;

export type AnalyticsClient = BaseAnalyticsClient & {
readonly addABTest: (
abTest: ABTest,
Expand Down Expand Up @@ -663,7 +678,11 @@ export type SearchClient = BaseSearchClient & {
requestOptions?: RequestOptions
) => Readonly<Promise<TaskStatusResponse>>;
readonly initAnalytics: (options?: InitAnalyticsOptions) => AnalyticsClient;
readonly initRecommendation: (options?: InitRecommendationOptions) => RecommendationClient;
readonly initPersonalization: (options?: InitPersonalizationOptions) => PersonalizationClient;
/**
* @deprecated Use `initPersonalization` instead.
*/
readonly initRecommendation: (options?: InitPersonalizationOptions) => PersonalizationClient;
};

export * from '../types';
55 changes: 37 additions & 18 deletions packages/algoliasearch/src/builds/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ import {
} from '@algolia/client-analytics';
import { destroy, version, WaitablePromise } from '@algolia/client-common';
import {
createRecommendationClient,
createPersonalizationClient,
getPersonalizationStrategy,
GetPersonalizationStrategyResponse,
PersonalizationClient as BasePersonalizationClient,
PersonalizationStrategy,
RecommendationClient as BaseRecommendationClient,
setPersonalizationStrategy,
SetPersonalizationStrategyResponse,
} from '@algolia/client-recommendation';
} from '@algolia/client-personalization';
import {
addApiKey,
AddApiKeyOptions,
Expand Down Expand Up @@ -194,7 +194,7 @@ import { Destroyable } from '@algolia/requester-common';
import { createNodeHttpRequester } from '@algolia/requester-node-http';
import { createUserAgent, RequestOptions } from '@algolia/transporter';

import { AlgoliaSearchOptions, InitAnalyticsOptions, InitRecommendationOptions } from '../types';
import { AlgoliaSearchOptions, InitAnalyticsOptions, InitPersonalizationOptions } from '../types';

export default function algoliasearch(
appId: string,
Expand All @@ -219,10 +219,22 @@ export default function algoliasearch(
version: process.versions.node,
}),
};
const searchClientOptions = { ...commonOptions, ...options };
const initPersonalization = () => (
clientOptions?: InitPersonalizationOptions
): PersonalizationClient => {
return createPersonalizationClient({
...commonOptions,
...clientOptions,
methods: {
getPersonalizationStrategy,
setPersonalizationStrategy,
},
});
};

return createSearchClient({
...commonOptions,
...options,
...searchClientOptions,
methods: {
search: multipleQueries,
searchForFacetValues: multipleSearchForFacetValues,
Expand Down Expand Up @@ -322,17 +334,15 @@ export default function algoliasearch(
},
});
},
initPersonalization,
initRecommendation: () => (
clientOptions?: InitRecommendationOptions
): RecommendationClient => {
return createRecommendationClient({
...commonOptions,
...clientOptions,
methods: {
getPersonalizationStrategy,
setPersonalizationStrategy,
},
});
clientOptions?: InitPersonalizationOptions
): PersonalizationClient => {
searchClientOptions.logger.info(
'The `initRecommendation` method is deprecated. Use `initPersonalization` instead.'
);

return initPersonalization()(clientOptions);
},
},
});
Expand All @@ -341,7 +351,7 @@ export default function algoliasearch(
// eslint-disable-next-line functional/immutable-data
algoliasearch.version = version;

export type RecommendationClient = BaseRecommendationClient & {
export type PersonalizationClient = BasePersonalizationClient & {
readonly getPersonalizationStrategy: (
requestOptions?: RequestOptions
) => Readonly<Promise<GetPersonalizationStrategyResponse>>;
Expand All @@ -351,6 +361,11 @@ export type RecommendationClient = BaseRecommendationClient & {
) => Readonly<Promise<SetPersonalizationStrategyResponse>>;
};

/**
* @deprecated Use `PersonalizationClient` instead.
*/
export type RecommendationClient = PersonalizationClient;

export type AnalyticsClient = BaseAnalyticsClient & {
readonly addABTest: (
abTest: ABTest,
Expand Down Expand Up @@ -671,7 +686,11 @@ export type SearchClient = BaseSearchClient & {
requestOptions?: RequestOptions
) => Readonly<Promise<TaskStatusResponse>>;
readonly initAnalytics: (options?: InitAnalyticsOptions) => AnalyticsClient;
readonly initRecommendation: (options?: InitRecommendationOptions) => RecommendationClient;
readonly initPersonalization: (options?: InitPersonalizationOptions) => PersonalizationClient;
/**
* @deprecated Use `initPersonalization` instead.
*/
readonly initRecommendation: (options?: InitPersonalizationOptions) => PersonalizationClient;
} & Destroyable;

export * from '../types';
Loading