Skip to content

Commit ddb77b5

Browse files
committed
feat(javascript): add bridge to transformation on algoliasearch
1 parent 35e96d0 commit ddb77b5

File tree

4 files changed

+234
-114
lines changed

4 files changed

+234
-114
lines changed

clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.common.test.ts

Lines changed: 78 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -143,131 +143,112 @@ describe('api', () => {
143143
});
144144
});
145145

146-
describe('init clients', () => {
147-
test('provides an init method for the analytics client', () => {
148-
expect(client.initAnalytics).not.toBeUndefined();
146+
describe('bridge methods', () => {
147+
test('throws when missing transformation.region', () => {
148+
//@ts-expect-error
149+
expect(() => algoliasearch('APP_ID', 'API_KEY', { transformation: { taskID: 'foo' } })).toThrow(
150+
'`region` must be provided when leveraging the transformation pipeline',
151+
);
149152
});
150153

151-
test('provides an init method for the abtesting client', () => {
152-
expect(client.initAbtesting).not.toBeUndefined();
154+
test('throws when missing transformation.taskID', () => {
155+
//@ts-expect-error
156+
expect(() => algoliasearch('APP_ID', 'API_KEY', { transformation: { region: 'us' } })).toThrow(
157+
'`taskID` must be provided when leveraging the transformation pipeline',
158+
);
153159
});
154160

155-
test('provides an init method for the personalization client', () => {
156-
expect(client.initPersonalization).not.toBeUndefined();
157-
});
161+
test('throws when calling the transformation methods without init parameters', async () => {
162+
await expect(client.saveObjectsWithTransformation({
163+
indexName: 'foo',
164+
objects: [{ objectID: 'bar', baz: 42 }],
165+
waitForTasks: true,
166+
})).rejects.toThrow(
167+
'`transformation.taskID` and `transformation.region` must be provided at client instantiation before calling this method.',
168+
);
158169

159-
test('provides an init method for the recommend client', () => {
160-
expect(client.initRecommend).not.toBeUndefined();
170+
await expect(client.partialUpdateObjectsWithTransformation({
171+
indexName: 'foo',
172+
objects: [{ objectID: 'bar', baz: 42 }],
173+
waitForTasks: true,
174+
}),
175+
).rejects.toThrow(
176+
'`transformation.taskID` and `transformation.region` must be provided at client instantiation before calling this method.',
177+
);
161178
});
162179

163-
test('default `init` clients to the root `algoliasearch` credentials', async () => {
164-
const abtestingClient = client.initAbtesting({ options: { requester: browserEchoRequester() } });
165-
const analyticsClient = client.initAnalytics({ options: { requester: browserEchoRequester() } });
166-
const recommendClient = client.initRecommend({ options: { requester: browserEchoRequester() } });
167-
const personalizationClient = client.initPersonalization({
168-
region: 'eu',
169-
options: { requester: browserEchoRequester() },
180+
test('exposes the transformation methods at the root of the client', async () => {
181+
const ingestionClient = algoliasearch('APP_ID', 'API_KEY', {
182+
requester: browserEchoRequester(),
183+
transformation: { taskID: "foo", region: "us" }
170184
});
171185

172-
const res1 = (await abtestingClient.customGet({
173-
path: 'abtestingClient',
174-
})) as unknown as EchoResponse;
175-
const res2 = (await analyticsClient.customGet({
176-
path: 'analyticsClient',
177-
})) as unknown as EchoResponse;
178-
const res3 = (await personalizationClient.customGet({
179-
path: 'personalizationClient',
180-
})) as unknown as EchoResponse;
181-
const res4 = (await recommendClient.customGet({
182-
path: 'recommendClient',
186+
expect(ingestionClient.saveObjectsWithTransformation).not.toBeUndefined();
187+
188+
let res = (await ingestionClient.saveObjectsWithTransformation({
189+
indexName: 'foo',
190+
objects: [{ objectID: 'bar', baz: 42 }],
191+
waitForTasks: true,
183192
})) as unknown as EchoResponse;
184193

185-
expect(res1.headers).toEqual(
186-
expect.objectContaining({
187-
'x-algolia-application-id': 'APP_ID',
188-
'x-algolia-api-key': 'API_KEY',
189-
}),
190-
);
191-
expect(res2.headers).toEqual(
194+
expect(res.headers).toEqual(
192195
expect.objectContaining({
193196
'x-algolia-application-id': 'APP_ID',
194197
'x-algolia-api-key': 'API_KEY',
195198
}),
196199
);
197-
expect(res3.headers).toEqual(
198-
expect.objectContaining({
199-
'x-algolia-application-id': 'APP_ID',
200-
'x-algolia-api-key': 'API_KEY',
201-
}),
202-
);
203-
expect(res4.headers).toEqual(
200+
expect(res.url.startsWith("https://data.us.algolia.com/2/tasks/foo/push?watch=true")).toBeTruthy();
201+
expect(res.data).toEqual({
202+
action: "addObject",
203+
records: [{
204+
baz: 42,
205+
objectID: "bar"
206+
}]
207+
});
208+
expect(ingestionClient.partialUpdateObjectsWithTransformation).not.toBeUndefined();
209+
210+
res = (await ingestionClient.partialUpdateObjectsWithTransformation({
211+
indexName: 'foo',
212+
objects: [{ objectID: 'bar', baz: 42 }],
213+
waitForTasks: true,
214+
createIfNotExists: true,
215+
})) as unknown as EchoResponse;
216+
217+
expect(res.headers).toEqual(
204218
expect.objectContaining({
205219
'x-algolia-application-id': 'APP_ID',
206220
'x-algolia-api-key': 'API_KEY',
207221
}),
208222
);
209-
});
210-
211-
test('`init` clients accept different credentials', async () => {
212-
const abtestingClient = client.initAbtesting({
213-
appId: 'appId1',
214-
apiKey: 'apiKey1',
215-
options: { requester: browserEchoRequester() },
216-
});
217-
const analyticsClient = client.initAnalytics({
218-
appId: 'appId2',
219-
apiKey: 'apiKey2',
220-
options: { requester: browserEchoRequester() },
221-
});
222-
const personalizationClient = client.initPersonalization({
223-
appId: 'appId3',
224-
apiKey: 'apiKey3',
225-
region: 'eu',
226-
options: { requester: browserEchoRequester() },
227-
});
228-
const recommendClient = client.initRecommend({
229-
appId: 'appId4',
230-
apiKey: 'apiKey4',
231-
options: { requester: browserEchoRequester() },
223+
expect(res.url.startsWith("https://data.us.algolia.com/2/tasks/foo/push?watch=true")).toBeTruthy();
224+
expect(res.data).toEqual({
225+
action: "partialUpdateObject",
226+
records: [{
227+
baz: 42,
228+
objectID: "bar"
229+
}]
232230
});
233231

234-
const res1 = (await abtestingClient.customGet({
235-
path: 'abtestingClient',
236-
})) as unknown as EchoResponse;
237-
const res2 = (await analyticsClient.customGet({
238-
path: 'analyticsClient',
239-
})) as unknown as EchoResponse;
240-
const res3 = (await personalizationClient.customGet({
241-
path: 'personalizationClient',
242-
})) as unknown as EchoResponse;
243-
const res4 = (await recommendClient.customGet({
244-
path: 'recommendClient',
232+
res = (await ingestionClient.partialUpdateObjectsWithTransformation({
233+
indexName: 'foo',
234+
objects: [{ objectID: 'bar', baz: 42 }],
235+
waitForTasks: true,
245236
})) as unknown as EchoResponse;
246237

247-
expect(res1.headers).toEqual(
248-
expect.objectContaining({
249-
'x-algolia-application-id': 'appId1',
250-
'x-algolia-api-key': 'apiKey1',
251-
}),
252-
);
253-
expect(res2.headers).toEqual(
254-
expect.objectContaining({
255-
'x-algolia-application-id': 'appId2',
256-
'x-algolia-api-key': 'apiKey2',
257-
}),
258-
);
259-
expect(res3.headers).toEqual(
238+
expect(res.headers).toEqual(
260239
expect.objectContaining({
261-
'x-algolia-application-id': 'appId3',
262-
'x-algolia-api-key': 'apiKey3',
263-
}),
264-
);
265-
expect(res4.headers).toEqual(
266-
expect.objectContaining({
267-
'x-algolia-application-id': 'appId4',
268-
'x-algolia-api-key': 'apiKey4',
240+
'x-algolia-application-id': 'APP_ID',
241+
'x-algolia-api-key': 'API_KEY',
269242
}),
270243
);
244+
expect(res.url.startsWith("https://data.us.algolia.com/2/tasks/foo/push?watch=true")).toBeTruthy();
245+
expect(res.data).toEqual({
246+
action: "partialUpdateObjectNoCreate",
247+
records: [{
248+
baz: 42,
249+
objectID: "bar"
250+
}]
251+
});
271252
});
272253
});
273254
});

playground/javascript/node/algoliasearch.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,19 @@ import type { SearchResponses } from 'algoliasearch';
66

77
const appId = process.env.ALGOLIA_APPLICATION_ID || '**** APP_ID *****';
88
const apiKey = process.env.ALGOLIA_SEARCH_KEY || '**** SEARCH_API_KEY *****';
9+
const adminApiKey = process.env.ALGOLIA_ADMIN_KEY || '**** ADMIN_API_KEY *****';
910

1011
const searchIndex = process.env.SEARCH_INDEX || 'test_index';
1112
const searchQuery = process.env.SEARCH_QUERY || 'test_query';
1213
const analyticsIndex = process.env.ANALYTICS_INDEX || 'test_index';
1314

14-
// Init client with appId and apiKey
15-
const client = algoliasearch(appId, apiKey);
16-
const clientLite = liteClient(appId, apiKey);
17-
18-
client.addAlgoliaAgent('algoliasearch node playground', '0.0.1');
19-
2015
async function testAlgoliasearch() {
16+
// Init client with appId and apiKey
17+
const client = algoliasearch(appId, apiKey);
18+
const clientLite = liteClient(appId, apiKey);
19+
20+
client.addAlgoliaAgent('algoliasearch node playground', '0.0.1');
21+
2122
try {
2223
const res: SearchResponses = await client.search({
2324
requests: [
@@ -131,4 +132,14 @@ async function testAlgoliasearch() {
131132
}
132133
}
133134

134-
testAlgoliasearch();
135+
async function testAlgoliasearchBridgeIngestion() {
136+
// Init client with appId and apiKey
137+
const client = algoliasearch(appId, adminApiKey, { transformation: {taskID: '942f7183-8596-4e51-a887-977c5b362f3d', region: 'eu'}});
138+
139+
await client.saveObjectsWithTransformation({indexName: "foo", objects: [{objectID: "foo", data: {baz: "baz", win: 42}}], waitForTasks: true })
140+
141+
await client.partialUpdateObjectsWithTransformation({indexName: "foo", objects: [{objectID: "foo", data: {baz: "baz", win: 42}}], waitForTasks: true, createIfNotExists: false })
142+
}
143+
144+
// testAlgoliasearch();
145+
testAlgoliasearchBridgeIngestion()

0 commit comments

Comments
 (0)