Skip to content

Commit

Permalink
feat(javascript): add abtesting client, better init usage (#784)
Browse files Browse the repository at this point in the history
  • Loading branch information
shortcuts committed Jul 5, 2022
1 parent 5d4926f commit 6b50ef0
Show file tree
Hide file tree
Showing 14 changed files with 238 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"files": [
{
"path": "packages/algoliasearch/dist/algoliasearch.umd.js",
"maxSize": "7.85KB"
"maxSize": "8.40KB"
},
{
"path": "packages/algoliasearch/dist/lite/lite.umd.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,100 @@ describe('api', () => {
expect(client.search).not.toBeUndefined();
});

it('provides an init method for the analytics client', () => {
expect(client.initAnalytics).not.toBeUndefined();
});
describe('init clients', () => {
it('provides an init method for the analytics client', () => {
expect(client.initAnalytics).not.toBeUndefined();
});

it('provides an init method for the personalization client', () => {
expect(client.initPersonalization).not.toBeUndefined();
it('provides an init method for the abtesting client', () => {
expect(client.initAbtesting).not.toBeUndefined();
});

it('provides an init method for the personalization client', () => {
expect(client.initPersonalization).not.toBeUndefined();
});

it('default `init` clients to the root `algoliasearch` credentials', async () => {
const abtestingClient = client.initAbtesting();
const analyticsClient = client.initAnalytics();
const personalizationClient = client.initPersonalization({
region: 'eu',
});

const res1 = (await abtestingClient.get({
path: 'abtestingClient',
})) as unknown as EchoResponse;
const res2 = (await analyticsClient.get({
path: 'analyticsClient',
})) as unknown as EchoResponse;
const res3 = (await personalizationClient.get({
path: 'personalizationClient',
})) as unknown as EchoResponse;

expect(res1.headers).toEqual(
expect.objectContaining({
'x-algolia-application-id': 'APP_ID',
'x-algolia-api-key': 'API_KEY',
})
);
expect(res2.headers).toEqual(
expect.objectContaining({
'x-algolia-application-id': 'APP_ID',
'x-algolia-api-key': 'API_KEY',
})
);
expect(res3.headers).toEqual(
expect.objectContaining({
'x-algolia-application-id': 'APP_ID',
'x-algolia-api-key': 'API_KEY',
})
);
});

it('`init` clients accept different credentials', async () => {
const abtestingClient = client.initAbtesting({
appId: 'appId1',
apiKey: 'apiKey1',
});
const analyticsClient = client.initAnalytics({
appId: 'appId2',
apiKey: 'apiKey2',
});
const personalizationClient = client.initPersonalization({
appId: 'appId3',
apiKey: 'apiKey3',
region: 'eu',
});

const res1 = (await abtestingClient.get({
path: 'abtestingClient',
})) as unknown as EchoResponse;
const res2 = (await analyticsClient.get({
path: 'analyticsClient',
})) as unknown as EchoResponse;
const res3 = (await personalizationClient.get({
path: 'personalizationClient',
})) as unknown as EchoResponse;

expect(res1.headers).toEqual(
expect.objectContaining({
'x-algolia-application-id': 'appId1',
'x-algolia-api-key': 'apiKey1',
})
);
expect(res2.headers).toEqual(
expect.objectContaining({
'x-algolia-application-id': 'appId2',
'x-algolia-api-key': 'apiKey2',
})
);
expect(res3.headers).toEqual(
expect.objectContaining({
'x-algolia-application-id': 'appId3',
'x-algolia-api-key': 'apiKey3',
})
);
});
});
});

Expand Down
2 changes: 1 addition & 1 deletion clients/algoliasearch-client-javascript/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1330,7 +1330,7 @@ __metadata:
languageName: unknown
linkType: soft

"@experimental-api-clients-automation/client-abtesting@workspace:packages/client-abtesting":
"@experimental-api-clients-automation/client-abtesting@0.7.2, @experimental-api-clients-automation/client-abtesting@workspace:packages/client-abtesting":
version: 0.0.0-use.local
resolution: "@experimental-api-clients-automation/client-abtesting@workspace:packages/client-abtesting"
dependencies:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ private void setDefaultGeneratorOptions() {
if (isAlgoliasearchClient) {
// Files used to create the package.json of the algoliasearch package
additionalProperties.put("analyticsVersion", Utils.getOpenApiToolsField("javascript", "analytics", "packageVersion"));
additionalProperties.put("abtestingVersion", Utils.getOpenApiToolsField("javascript", "abtesting", "packageVersion"));
additionalProperties.put("personalizationVersion", Utils.getOpenApiToolsField("javascript", "personalization", "packageVersion"));
additionalProperties.put("searchVersion", Utils.getOpenApiToolsField("javascript", "search", "packageVersion"));

Expand Down
44 changes: 22 additions & 22 deletions playground/javascript/node/algoliasearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,8 @@ const apiKey = process.env.ALGOLIA_SEARCH_KEY || '**** SEARCH_API_KEY *****';

const searchIndex = process.env.SEARCH_INDEX || 'test_index';
const searchQuery = process.env.SEARCH_QUERY || 'test_query';

const analyticsAppId =
process.env.ALGOLIA_APPLICATION_ID || '**** APP_ID *****';
const analyticsApiKey =
process.env.ALGOLIA_ANALYTICS_KEY || '**** ANALYTICS_API_KEY *****';

const analyticsIndex = process.env.ANALYTICS_INDEX || 'test_index';

const personalizationAppId =
process.env.ALGOLIA_APPLICATION_ID || '**** APP_ID *****';
const personalizationApiKey =
process.env.ALGOLIA_RECOMMENDATION_KEY || '**** RECOMMENDATION_API_KEY *****';

// Init client with appId and apiKey
const client = algoliasearch(appId, apiKey);
const clientLite = liteClient(appId, apiKey);
Expand Down Expand Up @@ -89,17 +78,14 @@ async function testAlgoliasearch() {
}

try {
const analyticsClient = client.initAnalytics(
analyticsAppId,
analyticsApiKey
);
const analyticsClient = client.initAnalytics();

const res = await analyticsClient.getTopFilterForAttribute({
attribute: 'myAttribute1,myAttribute2',
index: analyticsIndex,
});

console.log(`[OK analytics ]`, res);
console.log(`[OK analytics]`, res);
} catch (e) {
if (e instanceof ApiError) {
return console.log(`[${e.status}] ${e.message}`, e.stackTrace);
Expand All @@ -109,13 +95,27 @@ async function testAlgoliasearch() {
}

try {
const personalizationCilent = client.initPersonalization(
personalizationAppId,
personalizationApiKey,
'eu'
);
const abtestingClient = client.initAbtesting();

const res = await abtestingClient.getABTest({
id: 42,
});

console.log(`[OK abtesting]`, res);
} catch (e) {
if (e instanceof ApiError) {
return console.log(`[${e.status}] ${e.message}`, e.stackTrace);
}

console.log('[ERROR abtesting]', e);
}

try {
const personalizationClient = client.initPersonalization({
region: 'eu',
});

const res = await personalizationCilent.getUserTokenProfile({
const res = await personalizationClient.getUserTokenProfile({
userToken: 'wouhou',
});

Expand Down
1 change: 1 addition & 0 deletions playground/javascript/node/search.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { searchClient } from '@experimental-api-clients-automation/client-search';
import { ApiError } from '@experimental-api-clients-automation/client-common';
import dotenv from 'dotenv';
import { echoRequester } from '@experimental-api-clients-automation/requester-node-http';

dotenv.config({ path: '../../.env' });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { createXhrRequester } from '{{{npmNamespace}}}/requester-browser-xhr';
export function algoliasearch(
appId: string,
apiKey: string,
options?: { requester?: Requester; hosts?: Host[] }
options?: CommonClientOptions
) {
{{> algoliasearch/builds/checkParameters}}

Expand Down
32 changes: 13 additions & 19 deletions templates/javascript/clients/algoliasearch/builds/imports.mustache
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
import type {
AnalyticsClient,
Region as AnalyticsRegion,
} from '{{{npmNamespace}}}/client-analytics/src/analyticsClient';
import { createAnalyticsClient } from '{{{npmNamespace}}}/client-analytics/src/analyticsClient';
import type {
PersonalizationClient,
Region as PersonalizationRegion,
} from '{{{npmNamespace}}}/client-personalization/src/personalizationClient';
import { createPersonalizationClient } from '{{{npmNamespace}}}/client-personalization/src/personalizationClient';
import {
createSearchClient,
apiClientVersion as searchClientVersion,
} from '{{{npmNamespace}}}/client-search/src/searchClient';
import type {
CreateClientOptions,
Host,
Requester,
} from '{{{npmNamespace}}}/client-common';
import type { Region as AnalyticsRegion, AnalyticsClient } from '{{{npmNamespace}}}/client-analytics/src/analyticsClient';
import { createAnalyticsClient, REGIONS as analyticsRegions } from '{{{npmNamespace}}}/client-analytics/src/analyticsClient';

import type { Region as AbtestingRegion, AbtestingClient } from '{{{npmNamespace}}}/client-abtesting/src/abtestingClient';
import { createAbtestingClient, REGIONS as abtestingRegions } from '{{{npmNamespace}}}/client-abtesting/src/abtestingClient';

import type { Region as PersonalizationRegion, PersonalizationClient } from '{{{npmNamespace}}}/client-personalization/src/personalizationClient';
import { createPersonalizationClient, REGIONS as personalizationRegions } from '{{{npmNamespace}}}/client-personalization/src/personalizationClient';

import { createSearchClient, apiClientVersion as searchClientVersion } from '{{{npmNamespace}}}/client-search/src/searchClient';

import type { CreateClientOptions } from '{{{npmNamespace}}}/client-common';
import { CommonInitOptions, InitRegion, CommonClientOptions } from "./models"

export * from './models';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,70 @@
function initAnalytics(
analyticsAppId: string,
analyticsApiKey: string,
region?: AnalyticsRegion,
analyticsOptions?: { requester?: Requester; hosts?: Host[] }
): AnalyticsClient {
function initAnalytics(initOptions: CommonInitOptions & InitRegion<AnalyticsRegion> = {}): AnalyticsClient {
if (
initOptions.region &&
(typeof initOptions.region !== 'string' ||
!analyticsRegions.includes(initOptions.region))
) {
throw new Error(
`\`region\` must be one of the following: ${analyticsRegions.join(', ')}`
);
}

return createAnalyticsClient({
appId: analyticsAppId,
apiKey: analyticsApiKey,
region,
...analyticsOptions,
...initOptions.options,
...commonOptions,
appId: initOptions.appId ?? appId,
apiKey: initOptions.apiKey ?? apiKey,
region: initOptions.region,
});
}

function initAbtesting(initOptions: CommonInitOptions & InitRegion<AbtestingRegion> = {}): AbtestingClient {
if (
initOptions.region &&
(typeof initOptions.region !== 'string' ||
!abtestingRegions.includes(initOptions.region))
) {
throw new Error(
`\`region\` must be one of the following: ${abtestingRegions.join(', ')}`
);
}

return createAbtestingClient({
...initOptions.options,
...commonOptions,
appId: initOptions.appId ?? appId,
apiKey: initOptions.apiKey ?? apiKey,
region: initOptions.region,
});
}

function initPersonalization(
personalizationAppId: string,
personalizationApiKey: string,
region: PersonalizationRegion,
personalizationOptions?: { requester?: Requester; hosts?: Host[] }
): PersonalizationClient {
if (!region) {
function initPersonalization(initOptions: CommonInitOptions & Required<InitRegion<PersonalizationRegion>>): PersonalizationClient {
if (!initOptions.region) {
throw new Error('`region` is missing.');
}

if (
initOptions.region &&
(typeof initOptions.region !== 'string' ||
!personalizationRegions.includes(initOptions.region))
) {
throw new Error(
`\`region\` must be one of the following: ${personalizationRegions.join(', ')}`
);
}

return createPersonalizationClient({
appId: personalizationAppId,
apiKey: personalizationApiKey,
region,
...personalizationOptions,
...initOptions.options,
...commonOptions,
appId: initOptions.appId ?? appId,
apiKey: initOptions.apiKey ?? apiKey,
region: initOptions.region,
});
}

return {
...createSearchClient({ appId, apiKey, ...commonOptions }),
initAnalytics,
initPersonalization,
initAbtesting,
};
26 changes: 26 additions & 0 deletions templates/javascript/clients/algoliasearch/builds/models.mustache
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import type {
Host,
Requester,
} from '{{{npmNamespace}}}/client-common';
import {
ErrorBase,
PutProps,
Expand All @@ -9,5 +13,27 @@ import {
export * from '{{{npmNamespace}}}/client-search/model';
export * from '{{{npmNamespace}}}/client-personalization/model';
export * from '{{{npmNamespace}}}/client-analytics/model';
export * from '{{{npmNamespace}}}/client-abtesting/model';

export { ErrorBase, PutProps, PostProps, DelProps, GetProps };

export type CommonClientOptions = { requester?: Requester; hosts?: Host[] };

export type CommonInitOptions = Partial<{
/**
* App to target with the initialized client, defaults to the `algoliasearch` appId.
*/
appId: string;
/**
* API key of the targeted app ID, defaults to the `algoliasearch` apiKey.
*/
apiKey: string;
options: CommonClientOptions;
}>;

export type InitRegion<TRegion> = Partial<{
/**
* Available regions of the initialized client.
*/
region: TRegion;
}>;
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { createHttpRequester } from '{{{npmNamespace}}}/requester-node-http';
export function algoliasearch(
appId: string,
apiKey: string,
options?: { requester?: Requester; hosts?: Host[] }
options?: CommonClientOptions
) {
{{> algoliasearch/builds/checkParameters}}

Expand Down

0 comments on commit 6b50ef0

Please sign in to comment.