Skip to content

Commit ef80b78

Browse files
committed
Merge branch 'main' into chore/prepare-release-2022-06-24
2 parents f429687 + 6047578 commit ef80b78

File tree

11 files changed

+290
-55
lines changed

11 files changed

+290
-55
lines changed

clients/algoliasearch-client-javascript/packages/client-search/model/clientMethodProps.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { CreateRetryablePromiseOptions } from '@experimental-api-clients-automation/client-common';
2+
13
import type { ApiKey } from './apiKey';
24
import type { AssignUserIdParams } from './assignUserIdParams';
35
import type { AttributeOrBuiltInOperation } from './attributeOrBuiltInOperation';
@@ -6,7 +8,9 @@ import type { BatchDictionaryEntriesParams } from './batchDictionaryEntriesParam
68
import type { BatchWriteParams } from './batchWriteParams';
79
import type { BrowseRequest } from './browseRequest';
810
import type { DictionaryType } from './dictionaryType';
11+
import type { GetTaskResponse } from './getTaskResponse';
912
import type { IndexSettings } from './indexSettings';
13+
import type { Key } from './key';
1014
import type { LogType } from './logType';
1115
import type { OperationIndexParams } from './operationIndexParams';
1216
import type { Rule } from './rule';
@@ -719,3 +723,44 @@ export type UpdateApiKeyProps = {
719723
key: string;
720724
apiKey: ApiKey;
721725
};
726+
727+
type WaitForOptions<T> = Omit<
728+
CreateRetryablePromiseOptions<T>,
729+
'func' | 'validate'
730+
>;
731+
732+
export type WaitForTaskOptions = WaitForOptions<GetTaskResponse> & {
733+
/**
734+
* The `indexName` where the operation was performed.
735+
*/
736+
indexName: string;
737+
/**
738+
* The `taskID` returned by the method response.
739+
*/
740+
taskID: number;
741+
};
742+
743+
export type WaitForApiKeyOptions = WaitForOptions<Key> & {
744+
/**
745+
* The API Key.
746+
*/
747+
key: string;
748+
} & (
749+
| {
750+
/**
751+
* The operation that has been performed, used to compute the stop condition.
752+
*/
753+
operation: 'add' | 'delete';
754+
apiKey?: never;
755+
}
756+
| {
757+
/**
758+
* The operation that has been performed, used to compute the stop condition.
759+
*/
760+
operation: 'update';
761+
/**
762+
* The updated fields, used to compute the stop condition.
763+
*/
764+
apiKey: Partial<ApiKey>;
765+
}
766+
);

clients/algoliasearch-client-javascript/packages/client-search/src/searchClient.ts

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import type {
1212
Request,
1313
RequestOptions,
1414
QueryParameters,
15-
CreateRetryablePromiseOptions,
15+
ApiError,
1616
} from '@experimental-api-clients-automation/client-common';
1717

1818
import type { AddApiKeyResponse } from '../model/addApiKeyResponse';
@@ -21,6 +21,8 @@ import type { BatchParams } from '../model/batchParams';
2121
import type { BatchResponse } from '../model/batchResponse';
2222
import type { BrowseResponse } from '../model/browseResponse';
2323
import type {
24+
WaitForTaskOptions,
25+
WaitForApiKeyOptions,
2426
AddOrUpdateObjectProps,
2527
AssignUserIdProps,
2628
BatchProps,
@@ -183,34 +185,71 @@ export function createSearchClient({
183185
return {
184186
addAlgoliaAgent,
185187
/**
186-
* Wait for a task to complete with `indexName` and `taskID`.
188+
* Helper: Wait for a task to complete with `indexName` and `taskID`.
187189
*
188190
* @summary Wait for a task to complete.
189-
* @param waitForTaskProps - The waitForTaskProps object.
190-
* @param waitForTaskProps.indexName - The index in which to perform the request.
191-
* @param waitForTaskProps.taskID - The unique identifier of the task to wait for.
191+
* @param waitForTaskOptions - The waitForTaskOptions object.
192+
* @param waitForTaskOptions.indexName - The `indexName` where the operation was performed.
193+
* @param waitForTaskOptions.taskID - The `taskID` returned in the method response.
192194
*/
193195
waitForTask({
194196
indexName,
195197
taskID,
196198
...createRetryablePromiseOptions
197-
}: Omit<
198-
CreateRetryablePromiseOptions<GetTaskResponse>,
199-
'func' | 'validate'
200-
> & {
201-
indexName: string;
202-
taskID: number;
203-
}): Promise<void> {
204-
return new Promise<void>((resolve, reject) => {
205-
createRetryablePromise<GetTaskResponse>({
199+
}: WaitForTaskOptions): Promise<GetTaskResponse> {
200+
return createRetryablePromise({
201+
...createRetryablePromiseOptions,
202+
func: () => this.getTask({ indexName, taskID }),
203+
validate: (response) => response.status === 'published',
204+
});
205+
},
206+
207+
/**
208+
* Helper: Wait for an API key to be valid, updated or deleted based on a given `operation`.
209+
*
210+
* @summary Wait for an API key task to be processed.
211+
* @param waitForApiKeyOptions - The waitForApiKeyOptions object.
212+
* @param waitForApiKeyOptions.operation - The `operation` that was done on a `key`.
213+
* @param waitForApiKeyOptions.key - The `key` that has been added, deleted or updated.
214+
* @param waitForApiKeyOptions.apiKey - Necessary to know if an `update` operation has been processed, compare fields of the response with it.
215+
*/
216+
waitForApiKey({
217+
operation,
218+
key,
219+
apiKey,
220+
...createRetryablePromiseOptions
221+
}: WaitForApiKeyOptions): Promise<ApiError | Key> {
222+
if (operation === 'update') {
223+
return createRetryablePromise({
206224
...createRetryablePromiseOptions,
207-
func: () => this.getTask({ indexName, taskID }),
208-
validate: (response) => response.status === 'published',
209-
})
210-
.then(() => resolve())
211-
.catch(reject);
225+
func: () => this.getApiKey({ key }),
226+
validate: (response) => {
227+
for (const [entry, values] of Object.entries(apiKey)) {
228+
if (Array.isArray(values)) {
229+
if (
230+
values.length !== response[entry].length ||
231+
values.some((val, index) => val !== response[entry][index])
232+
) {
233+
return false;
234+
}
235+
} else if (values !== response[entry]) {
236+
return false;
237+
}
238+
}
239+
240+
return true;
241+
},
242+
});
243+
}
244+
245+
return createRetryablePromise({
246+
...createRetryablePromiseOptions,
247+
func: () => this.getApiKey({ key }).catch((error) => error),
248+
validate: (error: ApiError) =>
249+
operation === 'add' ? error.status !== 404 : error.status === 404,
212250
});
213251
},
252+
214253
/**
215254
* Add a new API Key with specific permissions/restrictions.
216255
*

scripts/cli/utils.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,17 @@ type Prompt = {
2525
interactive: boolean;
2626
};
2727

28-
export function getClientChoices(job: Job, language?: LangArg): string[] {
29-
const withoutAlgoliaSearch = PROMPT_CLIENTS.filter(
28+
export function getClientChoices(
29+
job: Job,
30+
language?: LangArg,
31+
clientList = PROMPT_CLIENTS
32+
): string[] {
33+
const withoutAlgoliaSearch = clientList.filter(
3034
(client) => client !== 'algoliasearch'
3135
);
3236

3337
if (!language) {
34-
return job === 'specs' ? withoutAlgoliaSearch : PROMPT_CLIENTS;
38+
return job === 'specs' ? withoutAlgoliaSearch : clientList;
3539
}
3640

3741
const isJavaScript = language === ALL || language === 'javascript';
@@ -41,7 +45,7 @@ export function getClientChoices(job: Job, language?: LangArg): string[] {
4145
case 'build':
4246
// Only `JavaScript` provide a lite client, others can build anything but it.
4347
if (isJavaScript) {
44-
return PROMPT_CLIENTS.filter((client) => client !== 'lite');
48+
return clientList.filter((client) => client !== 'lite');
4549
}
4650

4751
return withoutAlgoliaSearch.filter((client) => client !== 'lite');
@@ -56,7 +60,7 @@ export function getClientChoices(job: Job, language?: LangArg): string[] {
5660

5761
return withoutAlgoliaSearch.filter((client) => client !== 'lite');
5862
default:
59-
return PROMPT_CLIENTS;
63+
return clientList;
6064
}
6165
}
6266

@@ -107,7 +111,7 @@ export async function prompt({
107111
decision.language = langArg;
108112
}
109113

110-
decision.clientList = getClientChoices(job, decision.language);
114+
decision.clientList = getClientChoices(job, decision.language, CLIENTS);
111115

112116
if (!clientArg || !clientArg.length) {
113117
if (interactive) {
@@ -117,15 +121,15 @@ export async function prompt({
117121
name: 'client',
118122
message: 'Select a client',
119123
default: ALL,
120-
choices: decision.clientList,
124+
choices: getClientChoices(job, decision.language),
121125
},
122126
]);
123127

124128
decision.client = [client];
125129
}
126130
} else {
127131
clientArg.forEach((client) => {
128-
if (!decision.clientList.includes(client)) {
132+
if (!PROMPT_CLIENTS.includes(client)) {
129133
throw new Error(
130134
`The '${clientArg}' client can't run with the given job: '${job}'.\n\nAllowed choices are: ${decision.clientList.join(
131135
', '

templates/javascript/api-single.mustache

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export function create{{capitalizedApiName}}({
1818
hosts: getDefaultHosts({{^hasRegionalHost}}appIdOption{{/hasRegionalHost}}{{#hasRegionalHost}}regionOption{{/hasRegionalHost}}),
1919
...options,
2020
algoliaAgent: getAlgoliaAgent({
21-
algoliaAgents: algoliaAgents,
21+
algoliaAgents,
2222
client: '{{{algoliaAgent}}}',
2323
version: apiClientVersion,
2424
}),
@@ -40,30 +40,7 @@ export function create{{capitalizedApiName}}({
4040
return {
4141
addAlgoliaAgent,
4242
{{#isSearchClient}}
43-
/**
44-
* Wait for a task to complete with `indexName` and `taskID`.
45-
*
46-
* @summary Wait for a task to complete.
47-
* @param waitForTaskProps - The waitForTaskProps object.
48-
* @param waitForTaskProps.indexName - The index in which to perform the request.
49-
* @param waitForTaskProps.taskID - The unique identifier of the task to wait for.
50-
*/
51-
waitForTask({
52-
indexName,
53-
taskID,
54-
...createRetryablePromiseOptions,
55-
}: {
56-
indexName: string;
57-
taskID: number;
58-
} & Omit<CreateRetryablePromiseOptions<GetTaskResponse>, 'func' | 'validate'>): Promise<void> {
59-
return new Promise<void>((resolve, reject) => {
60-
createRetryablePromise<GetTaskResponse>({
61-
...createRetryablePromiseOptions,
62-
func: () => this.getTask({ indexName, taskID }),
63-
validate: (response) => response.status === 'published',
64-
}).then(() => resolve()).catch(reject);
65-
});
66-
},
43+
{{> api/helpers}}
6744
{{/isSearchClient}}
6845
{{#operation}}
6946
{{> api/operation/jsdoc}}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Helper: Wait for a task to complete with `indexName` and `taskID`.
3+
*
4+
* @summary Wait for a task to complete.
5+
* @param waitForTaskOptions - The waitForTaskOptions object.
6+
* @param waitForTaskOptions.indexName - The `indexName` where the operation was performed.
7+
* @param waitForTaskOptions.taskID - The `taskID` returned in the method response.
8+
*/
9+
waitForTask({
10+
indexName,
11+
taskID,
12+
...createRetryablePromiseOptions
13+
}: WaitForTaskOptions): Promise<GetTaskResponse> {
14+
return createRetryablePromise({
15+
...createRetryablePromiseOptions,
16+
func: () => this.getTask({ indexName, taskID }),
17+
validate: (response) => response.status === 'published',
18+
});
19+
},
20+
21+
/**
22+
* Helper: Wait for an API key to be valid, updated or deleted based on a given `operation`.
23+
*
24+
* @summary Wait for an API key task to be processed.
25+
* @param waitForApiKeyOptions - The waitForApiKeyOptions object.
26+
* @param waitForApiKeyOptions.operation - The `operation` that was done on a `key`.
27+
* @param waitForApiKeyOptions.key - The `key` that has been added, deleted or updated.
28+
* @param waitForApiKeyOptions.apiKey - Necessary to know if an `update` operation has been processed, compare fields of the response with it.
29+
*/
30+
waitForApiKey({
31+
operation,
32+
key,
33+
apiKey,
34+
...createRetryablePromiseOptions
35+
}: WaitForApiKeyOptions): Promise<ApiError | Key> {
36+
if (operation === 'update') {
37+
return createRetryablePromise({
38+
...createRetryablePromiseOptions,
39+
func: () => this.getApiKey({ key }),
40+
validate: (response) => {
41+
for (const [entry, values] of Object.entries(apiKey)) {
42+
if (Array.isArray(values)) {
43+
if (
44+
values.length !== response[entry].length ||
45+
values.some((val, index) => val !== response[entry][index])
46+
) {
47+
return false;
48+
}
49+
} else if (values !== response[entry]) {
50+
return false;
51+
}
52+
}
53+
54+
return true;
55+
},
56+
});
57+
}
58+
59+
return createRetryablePromise({
60+
...createRetryablePromiseOptions,
61+
func: () => this.getApiKey({ key }).catch((error) => error),
62+
validate: (error: ApiError) =>
63+
operation === 'add' ? error.status !== 404 : error.status === 404,
64+
});
65+
},

templates/javascript/api/imports.mustache

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import type {
1515
RequestOptions,
1616
QueryParameters,
1717
{{#isSearchClient}}
18-
CreateRetryablePromiseOptions,
18+
ApiError,
1919
{{/isSearchClient}}
2020
} from '{{{npmNamespace}}}/client-common';
2121

@@ -25,6 +25,10 @@ import { {{classname}} } from '{{filename}}';
2525

2626
{{#operations}}
2727
import type {
28+
{{#isSearchClient}}
29+
WaitForTaskOptions,
30+
WaitForApiKeyOptions,
31+
{{/isSearchClient}}
2832
{{#operation}}
2933
{{#vendorExtensions}}
3034
{{#x-create-wrapping-object}}

0 commit comments

Comments
 (0)