Skip to content

Commit 611be74

Browse files
feat(javascript): add accountCopyIndex helper (generated)
algolia/api-clients-automation#4798 Co-authored-by: algolia-bot <[email protected]> Co-authored-by: Clément Vannicatte <[email protected]>
1 parent b455a9f commit 611be74

File tree

4 files changed

+269
-5
lines changed

4 files changed

+269
-5
lines changed

packages/client-common/src/transporter/errors.ts

+18
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,24 @@ export class AlgoliaError extends Error {
1212
}
1313
}
1414

15+
export class IndexNotFoundError extends AlgoliaError {
16+
constructor(indexName: string) {
17+
super(`${indexName} does not exist`, 'IndexNotFoundError');
18+
}
19+
}
20+
21+
export class IndicesInSameAppError extends AlgoliaError {
22+
constructor() {
23+
super('Indices are in the same application. Use operationIndex instead.', 'IndicesInSameAppError');
24+
}
25+
}
26+
27+
export class IndexAlreadyExistsError extends AlgoliaError {
28+
constructor(indexName: string) {
29+
super(`${indexName} index already exists.`, 'IndexAlreadyExistsError');
30+
}
31+
}
32+
1533
export class ErrorWithStackTrace extends AlgoliaError {
1634
stackTrace: StackFrame[];
1735

packages/client-search/builds/fetch.ts

+114-2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,19 @@ export type SearchClient = ReturnType<typeof createSearchClient> & SearchClientN
44

55
import { createHmac } from 'node:crypto';
66

7-
import { createMemoryCache, createNullCache, createNullLogger, serializeQueryParameters } from '@algolia/client-common';
7+
import {
8+
IndexAlreadyExistsError,
9+
IndexNotFoundError,
10+
IndicesInSameAppError,
11+
createMemoryCache,
12+
createNullCache,
13+
createNullLogger,
14+
serializeQueryParameters,
15+
} from '@algolia/client-common';
816
import { createFetchRequester } from '@algolia/requester-fetch';
17+
import { createHttpRequester } from '@algolia/requester-node-http';
918

10-
import type { ClientOptions } from '@algolia/client-common';
19+
import type { ClientOptions, RequestOptions } from '@algolia/client-common';
1120

1221
import { createSearchClient } from '../src/searchClient';
1322

@@ -16,9 +25,14 @@ export { apiClientVersion } from '../src/searchClient';
1625
export * from '../model';
1726

1827
import type {
28+
AccountCopyIndexOptions,
29+
BrowseResponse,
1930
GenerateSecuredApiKeyOptions,
2031
GetSecuredApiKeyRemainingValidityOptions,
2132
SearchClientNodeHelpers,
33+
SearchRulesResponse,
34+
SearchSynonymsResponse,
35+
UpdatedAtResponse,
2236
} from '../model';
2337

2438
export function searchClient(appId: string, apiKey: string, options?: ClientOptions): SearchClient {
@@ -82,6 +96,104 @@ export function searchClient(appId: string, apiKey: string, options?: ClientOpti
8296
createHmac('sha256', parentApiKey).update(queryParameters).digest('hex') + queryParameters,
8397
).toString('base64');
8498
},
99+
100+
/**
101+
* Helper: Copies the given `sourceIndexName` records, rules and synonyms to an other Algolia application for the given `destinationIndexName`.
102+
* See https://api-clients-automation.netlify.app/docs/add-new-api-client#5-helpers for implementation details.
103+
*
104+
* @summary Helper: Copies the given `sourceIndexName` records, rules and synonyms to an other Algolia application for the given `destinationIndexName`.
105+
* @param accountCopyIndex - The `accountCopyIndex` object.
106+
* @param accountCopyIndex.sourceIndexName - The name of the index to copy.
107+
* @param accountCopyIndex.destinationAppID - The application ID to write the index to.
108+
* @param accountCopyIndex.destinationApiKey - The API Key of the `destinationAppID` to write the index to, must have write ACLs.
109+
* @param accountCopyIndex.destinationIndexName - The name of the index to write the copied index to.
110+
* @param requestOptions - The requestOptions to send along with the query, they will be forwarded to the `setSettings`, `saveRules`, `saveSynonyms` and `saveObjects` method and merged with the transporter requestOptions.
111+
*/
112+
async accountCopyIndex(
113+
{ sourceIndexName, destinationAppID, destinationApiKey, destinationIndexName }: AccountCopyIndexOptions,
114+
requestOptions?: RequestOptions,
115+
): Promise<void> {
116+
const responses: Array<{ taskID: UpdatedAtResponse['taskID'] }> = [];
117+
118+
if (this.appId === destinationAppID) {
119+
throw new IndicesInSameAppError();
120+
}
121+
122+
if (!(await this.indexExists({ indexName: sourceIndexName }))) {
123+
throw new IndexNotFoundError(sourceIndexName);
124+
}
125+
126+
const destinationClient = createSearchClient({
127+
appId: destinationAppID,
128+
apiKey: destinationApiKey,
129+
timeouts: {
130+
connect: 2000,
131+
read: 5000,
132+
write: 30000,
133+
},
134+
logger: createNullLogger(),
135+
requester: createHttpRequester(),
136+
algoliaAgents: [{ segment: 'accountCopyIndex', version: process.versions.node }],
137+
responsesCache: createNullCache(),
138+
requestsCache: createNullCache(),
139+
hostsCache: createMemoryCache(),
140+
...options,
141+
});
142+
143+
if (await destinationClient.indexExists({ indexName: destinationIndexName })) {
144+
throw new IndexAlreadyExistsError(destinationIndexName);
145+
}
146+
147+
responses.push(
148+
await destinationClient.setSettings(
149+
{
150+
indexName: destinationIndexName,
151+
indexSettings: await this.getSettings({ indexName: sourceIndexName }),
152+
},
153+
requestOptions,
154+
),
155+
);
156+
157+
await this.browseRules({
158+
indexName: sourceIndexName,
159+
async aggregator(response: SearchRulesResponse) {
160+
responses.push(
161+
await destinationClient.saveRules(
162+
{ indexName: destinationIndexName, rules: response.hits },
163+
requestOptions,
164+
),
165+
);
166+
},
167+
});
168+
169+
await this.browseSynonyms({
170+
indexName: sourceIndexName,
171+
async aggregator(response: SearchSynonymsResponse) {
172+
responses.push(
173+
await destinationClient.saveSynonyms(
174+
{ indexName: destinationIndexName, synonymHit: response.hits },
175+
requestOptions,
176+
),
177+
);
178+
},
179+
});
180+
181+
await this.browseObjects({
182+
indexName: sourceIndexName,
183+
async aggregator(response: BrowseResponse) {
184+
responses.push(
185+
...(await destinationClient.saveObjects(
186+
{ indexName: destinationIndexName, objects: response.hits },
187+
requestOptions,
188+
)),
189+
);
190+
},
191+
});
192+
193+
for (const response of responses) {
194+
await destinationClient.waitForTask({ indexName: destinationIndexName, taskID: response.taskID });
195+
}
196+
},
85197
/**
86198
* Helper: Retrieves the remaining validity of the previous generated `securedApiKey`, the `ValidUntil` parameter must have been provided.
87199
*

packages/client-search/builds/node.ts

+114-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,17 @@ import { createHmac } from 'node:crypto';
66

77
import { createHttpRequester } from '@algolia/requester-node-http';
88

9-
import { createMemoryCache, createNullCache, createNullLogger, serializeQueryParameters } from '@algolia/client-common';
10-
11-
import type { ClientOptions } from '@algolia/client-common';
9+
import {
10+
IndexAlreadyExistsError,
11+
IndexNotFoundError,
12+
IndicesInSameAppError,
13+
createMemoryCache,
14+
createNullCache,
15+
createNullLogger,
16+
serializeQueryParameters,
17+
} from '@algolia/client-common';
18+
19+
import type { ClientOptions, RequestOptions } from '@algolia/client-common';
1220

1321
import { createSearchClient } from '../src/searchClient';
1422

@@ -17,9 +25,14 @@ export { apiClientVersion } from '../src/searchClient';
1725
export * from '../model';
1826

1927
import type {
28+
AccountCopyIndexOptions,
29+
BrowseResponse,
2030
GenerateSecuredApiKeyOptions,
2131
GetSecuredApiKeyRemainingValidityOptions,
2232
SearchClientNodeHelpers,
33+
SearchRulesResponse,
34+
SearchSynonymsResponse,
35+
UpdatedAtResponse,
2336
} from '../model';
2437

2538
export function searchClient(appId: string, apiKey: string, options?: ClientOptions): SearchClient {
@@ -83,6 +96,104 @@ export function searchClient(appId: string, apiKey: string, options?: ClientOpti
8396
createHmac('sha256', parentApiKey).update(queryParameters).digest('hex') + queryParameters,
8497
).toString('base64');
8598
},
99+
100+
/**
101+
* Helper: Copies the given `sourceIndexName` records, rules and synonyms to an other Algolia application for the given `destinationIndexName`.
102+
* See https://api-clients-automation.netlify.app/docs/add-new-api-client#5-helpers for implementation details.
103+
*
104+
* @summary Helper: Copies the given `sourceIndexName` records, rules and synonyms to an other Algolia application for the given `destinationIndexName`.
105+
* @param accountCopyIndex - The `accountCopyIndex` object.
106+
* @param accountCopyIndex.sourceIndexName - The name of the index to copy.
107+
* @param accountCopyIndex.destinationAppID - The application ID to write the index to.
108+
* @param accountCopyIndex.destinationApiKey - The API Key of the `destinationAppID` to write the index to, must have write ACLs.
109+
* @param accountCopyIndex.destinationIndexName - The name of the index to write the copied index to.
110+
* @param requestOptions - The requestOptions to send along with the query, they will be forwarded to the `setSettings`, `saveRules`, `saveSynonyms` and `saveObjects` method and merged with the transporter requestOptions.
111+
*/
112+
async accountCopyIndex(
113+
{ sourceIndexName, destinationAppID, destinationApiKey, destinationIndexName }: AccountCopyIndexOptions,
114+
requestOptions?: RequestOptions,
115+
): Promise<void> {
116+
const responses: Array<{ taskID: UpdatedAtResponse['taskID'] }> = [];
117+
118+
if (this.appId === destinationAppID) {
119+
throw new IndicesInSameAppError();
120+
}
121+
122+
if (!(await this.indexExists({ indexName: sourceIndexName }))) {
123+
throw new IndexNotFoundError(sourceIndexName);
124+
}
125+
126+
const destinationClient = createSearchClient({
127+
appId: destinationAppID,
128+
apiKey: destinationApiKey,
129+
timeouts: {
130+
connect: 2000,
131+
read: 5000,
132+
write: 30000,
133+
},
134+
logger: createNullLogger(),
135+
requester: createHttpRequester(),
136+
algoliaAgents: [{ segment: 'accountCopyIndex', version: process.versions.node }],
137+
responsesCache: createNullCache(),
138+
requestsCache: createNullCache(),
139+
hostsCache: createMemoryCache(),
140+
...options,
141+
});
142+
143+
if (await destinationClient.indexExists({ indexName: destinationIndexName })) {
144+
throw new IndexAlreadyExistsError(destinationIndexName);
145+
}
146+
147+
responses.push(
148+
await destinationClient.setSettings(
149+
{
150+
indexName: destinationIndexName,
151+
indexSettings: await this.getSettings({ indexName: sourceIndexName }),
152+
},
153+
requestOptions,
154+
),
155+
);
156+
157+
await this.browseRules({
158+
indexName: sourceIndexName,
159+
async aggregator(response: SearchRulesResponse) {
160+
responses.push(
161+
await destinationClient.saveRules(
162+
{ indexName: destinationIndexName, rules: response.hits },
163+
requestOptions,
164+
),
165+
);
166+
},
167+
});
168+
169+
await this.browseSynonyms({
170+
indexName: sourceIndexName,
171+
async aggregator(response: SearchSynonymsResponse) {
172+
responses.push(
173+
await destinationClient.saveSynonyms(
174+
{ indexName: destinationIndexName, synonymHit: response.hits },
175+
requestOptions,
176+
),
177+
);
178+
},
179+
});
180+
181+
await this.browseObjects({
182+
indexName: sourceIndexName,
183+
async aggregator(response: BrowseResponse) {
184+
responses.push(
185+
...(await destinationClient.saveObjects(
186+
{ indexName: destinationIndexName, objects: response.hits },
187+
requestOptions,
188+
)),
189+
);
190+
},
191+
});
192+
193+
for (const response of responses) {
194+
await destinationClient.waitForTask({ indexName: destinationIndexName, taskID: response.taskID });
195+
}
196+
},
86197
/**
87198
* Helper: Retrieves the remaining validity of the previous generated `securedApiKey`, the `ValidUntil` parameter must have been provided.
88199
*

packages/client-search/model/clientMethodProps.ts

+23
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,7 @@ export type GetSecuredApiKeyRemainingValidityOptions = {
821821
};
822822

823823
export type SearchClientNodeHelpers = {
824+
accountCopyIndex: (opts: AccountCopyIndexOptions) => Promise<void>;
824825
generateSecuredApiKey: (opts: GenerateSecuredApiKeyOptions) => string;
825826
getSecuredApiKeyRemainingValidity: (opts: GetSecuredApiKeyRemainingValidityOptions) => number;
826827
};
@@ -877,3 +878,25 @@ export type ReplaceAllObjectsOptions = {
877878
*/
878879
scopes?: Array<ScopeType>;
879880
};
881+
882+
export type AccountCopyIndexOptions = {
883+
/**
884+
* The name of the index to copy to the `destinationClient`.
885+
*/
886+
sourceIndexName: string;
887+
888+
/**
889+
* The application ID to write the index to.
890+
*/
891+
destinationAppID: string;
892+
893+
/**
894+
* The API Key of the `destinationAppID` to write the index to, must have write ACLs.
895+
*/
896+
destinationApiKey: string;
897+
898+
/**
899+
* The name of the index to write the copy in.
900+
*/
901+
destinationIndexName: string;
902+
};

0 commit comments

Comments
 (0)