Skip to content

Commit d9ac12f

Browse files
committed
feat(clients): add recommend to algoliasearch
1 parent c27282b commit d9ac12f

File tree

25 files changed

+321
-125
lines changed

25 files changed

+321
-125
lines changed

clients/algoliasearch-client-javascript/yarn.lock

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ __metadata:
124124
languageName: unknown
125125
linkType: soft
126126

127-
"@algolia/recommend@workspace:packages/recommend":
127+
"@algolia/recommend@npm:5.0.0-alpha.106, @algolia/recommend@workspace:packages/recommend":
128128
version: 0.0.0-use.local
129129
resolution: "@algolia/recommend@workspace:packages/recommend"
130130
dependencies:
@@ -3119,6 +3119,7 @@ __metadata:
31193119
"@algolia/client-common": "npm:5.0.0-alpha.107"
31203120
"@algolia/client-personalization": "npm:5.0.0-alpha.106"
31213121
"@algolia/client-search": "npm:5.0.0-alpha.106"
3122+
"@algolia/recommend": "npm:5.0.0-alpha.106"
31223123
"@algolia/requester-browser-xhr": "npm:5.0.0-alpha.107"
31233124
"@algolia/requester-node-http": "npm:5.0.0-alpha.107"
31243125
"@babel/preset-env": "npm:7.24.0"

config/clients.config.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@
158158
}
159159
],
160160
"folder": "clients/algoliasearch-client-javascript",
161-
"npmNamespace": "@algolia",
162161
"gitRepoId": "algoliasearch-client-javascript",
163162
"packageVersion": "5.0.0-alpha.108",
164163
"modelFolder": "model",

generators/src/main/java/com/algolia/codegen/AlgoliaJavascriptGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ private void setDefaultGeneratorOptions() {
155155
additionalProperties.put("abtestingVersion", Helpers.getPackageJsonVersion("client-abtesting"));
156156
additionalProperties.put("personalizationVersion", Helpers.getPackageJsonVersion("client-personalization"));
157157
additionalProperties.put("searchVersion", Helpers.getPackageJsonVersion("client-search"));
158+
additionalProperties.put("recommendVersion", Helpers.getPackageJsonVersion("recommend"));
158159

159160
// Files used to generate the `lite` client
160161
apiName = "lite" + Helpers.API_SUFFIX;
@@ -185,7 +186,6 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
185186
setDefaultGeneratorOptions();
186187
try {
187188
additionalProperties.put("utilsPackageVersion", Helpers.getPackageJsonVersion("client-common"));
188-
additionalProperties.put("npmNamespace", Helpers.getClientConfigField("javascript", "npmNamespace"));
189189
} catch (GeneratorException e) {
190190
e.printStackTrace();
191191
System.exit(1);

generators/src/main/java/com/algolia/codegen/cts/manager/JavascriptCTSManager.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ public void addTestsSupportingFiles(List<SupportingFile> supportingFiles) {
2121

2222
@Override
2323
public void addDataToBundle(Map<String, Object> bundle) throws GeneratorException {
24-
String npmNamespace = Helpers.getClientConfigField("javascript", "npmNamespace");
25-
2624
bundle.put("utilsPackageVersion", Helpers.getPackageJsonVersion("client-common"));
27-
bundle.put("npmNamespace", npmNamespace);
2825

2926
List<Map<String, String>> clients = new ArrayList<>();
3027
String importName = "";
@@ -35,7 +32,7 @@ public void addDataToBundle(Map<String, Object> bundle) throws GeneratorExceptio
3532
String output = c.get("output").asText();
3633
String packageName = output.substring(output.lastIndexOf("/") + 1);
3734
if (!packageName.equals("algoliasearch")) {
38-
packageName = npmNamespace + "/" + packageName;
35+
packageName = "@algolia/" + packageName;
3936
}
4037

4138
clients.add(Map.of("packageName", packageName, "packagePath", "link:../../../" + output.replace("#{cwd}/", "")));

generators/src/main/java/com/algolia/codegen/cts/tests/TestsRequest.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.algolia.codegen.utils.*;
55
import java.io.File;
66
import java.util.*;
7+
import org.apache.commons.lang3.ArrayUtils;
78
import org.openapitools.codegen.CodegenModel;
89
import org.openapitools.codegen.CodegenOperation;
910
import org.openapitools.codegen.CodegenResponse;
@@ -19,10 +20,32 @@ protected Map<String, Request[]> loadRequestCTS() throws Exception {
1920
String clientName = client;
2021
// This special case allow us to read the `search` CTS to generated the tests for the
2122
// `lite` client, which is only available in Javascript
22-
if ((language.equals("javascript") || language.equals("dart")) && client.equals("algoliasearch")) {
23+
if (client.equals("algoliasearch")) {
2324
clientName = "search";
2425
}
25-
return super.loadCTS("requests", clientName, Request[].class);
26+
27+
Map<String, Request[]> baseCTS = super.loadCTS("requests", clientName, Request[].class);
28+
29+
// The algoliasearch client bundles many client and therefore should provide tests for all the
30+
// subsequent specs
31+
if (client.equals("algoliasearch")) {
32+
Map<String, Request[]> recommendCTS = super.loadCTS("requests", "recommend", Request[].class);
33+
for (Map.Entry<String, Request[]> entry : recommendCTS.entrySet()) {
34+
String operation = entry.getKey();
35+
// custom methods are common to every clients, we don't want duplicate tests
36+
if (operation.startsWith("custom")) {
37+
continue;
38+
}
39+
40+
if (baseCTS.containsKey(operation)) {
41+
baseCTS.put(operation, ArrayUtils.addAll(baseCTS.get(operation), entry.getValue()));
42+
} else {
43+
baseCTS.put(operation, entry.getValue());
44+
}
45+
}
46+
}
47+
48+
return baseCTS;
2649
}
2750

2851
@Override
@@ -70,7 +93,9 @@ public void run(Map<String, CodegenModel> models, Map<String, CodegenOperation>
7093
throw new CTSException(
7194
"operationId '" +
7295
operationId +
73-
"' does not exist in the tests suite, please create the file:" +
96+
"' does not exist in the " +
97+
client +
98+
" tests suite, please create the file:" +
7499
" 'tests/CTS/requests/" +
75100
client +
76101
"/" +

scripts/buildClients.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import * as fsp from 'fs/promises';
33

44
import { run, toAbsolutePath } from './common.js';
5-
import { getClientsConfigField, getLanguageFolder } from './config.js';
5+
import { getLanguageFolder } from './config.js';
66
import { createSpinner } from './spinners.js';
77
import type { Generator, Language } from './types.js';
88

@@ -17,9 +17,8 @@ async function buildClient(language: Language, gens: Generator[]): Promise<void>
1717
await run('dotnet build --configuration Release', { cwd, language });
1818
break;
1919
case 'javascript':
20-
const npmNamespace = getClientsConfigField('javascript', 'npmNamespace');
2120
const packageNames = gens.map(({ additionalProperties: { packageName } }) =>
22-
packageName === 'algoliasearch' ? packageName : `${npmNamespace}/${packageName}`,
21+
packageName === 'algoliasearch' ? packageName : `@algolia/${packageName}`,
2322
);
2423

2524
await run('YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install', { cwd });

scripts/buildSpecs.ts

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { GENERATORS, capitalize, createClientName, exists, run, toAbsolutePath }
77
import { createSpinner } from './spinners.js';
88
import type { CodeSamples, Language, SnippetSamples, Spec } from './types.js';
99

10-
const ALGOLIASEARCH_LITE_OPERATIONS = ['search', 'customPost'];
10+
const ALGOLIASEARCH_LITE_OPERATIONS = ['search', 'customPost', 'getRecommendations'];
1111

1212
function mapLanguageToCodeSampleSupporter(language: Language): CodeSamples['lang'] {
1313
switch (language) {
@@ -192,27 +192,36 @@ async function lintCommon(useCache: boolean): Promise<void> {
192192
async function buildLiteSpec({
193193
spec,
194194
bundledPath,
195+
docs,
196+
useCache,
195197
}: {
196198
spec: string;
197199
bundledPath: string;
200+
docs: boolean;
201+
useCache: boolean;
198202
}): Promise<void> {
199-
const parsed = yaml.load(await fsp.readFile(toAbsolutePath(bundledPath), 'utf8')) as Spec;
200-
201-
// Filter methods.
202-
parsed.paths = Object.entries(parsed.paths).reduce(
203-
(acc, [path, operations]) => {
204-
for (const [, operation] of Object.entries(operations)) {
205-
if (ALGOLIASEARCH_LITE_OPERATIONS.includes(operation.operationId)) {
206-
return { ...acc, [path]: { post: operation } };
207-
}
208-
}
203+
await buildSpec({ spec: 'recommend', outputFormat: 'yml', docs, useCache });
209204

210-
return acc;
211-
},
212-
{} as Spec['paths'],
213-
);
205+
const base = yaml.load(await fsp.readFile(toAbsolutePath(bundledPath), 'utf8')) as Spec;
206+
const recommend = yaml.load(
207+
await fsp.readFile(toAbsolutePath(bundledPath.replace('algoliasearch', 'recommend')), 'utf8'),
208+
) as Spec;
209+
base.paths = { ...base.paths, ...recommend.paths };
210+
base.components.schemas = { ...base.components.schemas, ...recommend.components.schemas };
214211

215-
await fsp.writeFile(bundledPath, yaml.dump(parsed));
212+
const lite = { ...base, paths: {} };
213+
214+
for (const [path, operations] of Object.entries(base.paths)) {
215+
for (const [, operation] of Object.entries(operations)) {
216+
if (ALGOLIASEARCH_LITE_OPERATIONS.includes(operation.operationId)) {
217+
lite.paths[path] = { post: operation };
218+
219+
break;
220+
}
221+
}
222+
}
223+
224+
await fsp.writeFile(bundledPath, yaml.dump(lite));
216225

217226
await transformBundle({
218227
bundledPath,
@@ -239,25 +248,26 @@ async function buildSpec({
239248

240249
// In case of lite we use a the `search` spec as a base because only its bundled form exists.
241250
const specBase = isAlgoliasearch ? 'search' : spec;
251+
const deps = isAlgoliasearch ? ['search', 'recommend'] : [spec];
242252
const logSuffix = docs ? 'doc spec' : 'spec';
243253
const cache = new Cache({
244254
folder: toAbsolutePath('specs/'),
245255
generatedFiles: [docs ? `bundled/${spec}.doc.yml` : `bundled/${spec}.yml`],
246-
filesToCache: [specBase, 'common'],
256+
filesToCache: [...deps, 'common'],
247257
cacheFile: toAbsolutePath(`specs/dist/${spec}.${docs ? 'doc.' : ''}cache`),
248258
});
249259

250260
const spinner = createSpinner(`starting '${spec}' ${logSuffix}`);
251261

252262
if (useCache) {
253-
spinner.text = `checking cache for '${specBase}'`;
263+
spinner.text = `checking cache for '${spec}'`;
254264

255265
if (await cache.isValid()) {
256-
spinner.succeed(`job skipped, cache found for '${specBase}'`);
266+
spinner.succeed(`job skipped, cache found for '${spec}'`);
257267
return;
258268
}
259269

260-
spinner.text = `cache not found for '${specBase}'`;
270+
spinner.text = `cache not found for '${spec}'`;
261271
}
262272

263273
// First linting the base
@@ -281,6 +291,8 @@ async function buildSpec({
281291
await buildLiteSpec({
282292
spec,
283293
bundledPath: toAbsolutePath(bundledPath),
294+
docs,
295+
useCache,
284296
});
285297
}
286298

@@ -314,6 +326,13 @@ export async function buildSpecs({
314326

315327
await lintCommon(useCache);
316328

329+
// the `lite` spec will build the `recommend` spec, so we remove it from the list
330+
// to prevent concurrent builds
331+
if (clients.includes('algoliasearch')) {
332+
// eslint-disable-next-line no-param-reassign
333+
clients = clients.filter((client) => client !== 'recommend');
334+
}
335+
317336
await Promise.all(
318337
clients.map((client) => buildSpec({ spec: client, outputFormat, docs, useCache })),
319338
);

scripts/ci/githubActions/createMatrix.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@
22
import * as core from '@actions/core';
33

44
import { CLIENTS, createClientName, GENERATORS, LANGUAGES } from '../../common.js';
5-
import {
6-
getClientsConfigField,
7-
getLanguageFolder,
8-
getTestExtension,
9-
getTestOutputFolder,
10-
} from '../../config.js';
5+
import { getLanguageFolder, getTestExtension, getTestOutputFolder } from '../../config.js';
116

127
import { COMMON_DEPENDENCIES, DEPENDENCIES } from './setRunVariables.js';
138
import type { ClientMatrix, CreateMatrix, ToRunMatrix } from './types.js';
@@ -102,12 +97,11 @@ async function createClientMatrix(baseBranch: string): Promise<void> {
10297
testsToStore = `${testsToStore} ${testsRootFolder}/build.gradle`;
10398
break;
10499
case 'javascript':
105-
const npmNamespace = getClientsConfigField('javascript', 'npmNamespace');
106100
const packageNames = matrix[language].toRun.map((client) => {
107101
const packageName = GENERATORS[`${language}-${client}`].additionalProperties.packageName;
108102

109103
// `algoliasearch` is not preceded by `@algolia`
110-
return client === 'algoliasearch' ? packageName : `${npmNamespace}/${packageName}`;
104+
return client === 'algoliasearch' ? packageName : `@algolia/${packageName}`;
111105
});
112106

113107
buildCommand = `cd ${matrix[language].path} && yarn build:many '{${packageNames.join(

scripts/formatter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export async function formatter(language: string, cwd: string): Promise<void> {
2828
await run('goimports -w . && golangci-lint run --fix', { cwd, language });
2929
break;
3030
case 'javascript':
31-
await run(`yarn eslint --ext=ts,json ${cwd} --fix --no-error-on-unmatched-pattern`);
31+
await run(`yarn eslint --fix --no-error-on-unmatched-pattern --ext=ts,json ${cwd}`);
3232
break;
3333
case 'java':
3434
await run(

scripts/types.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ export type Language = keyof typeof config;
4141
export type Spec = {
4242
servers: Server[];
4343
tags: Tag[];
44-
paths: Path[];
44+
paths: Path;
45+
components: {
46+
schemas: Record<string, any>;
47+
};
4548
};
4649

4750
/**
@@ -105,5 +108,9 @@ export type SnippetSamples = Record<Language, Record<string, string>>;
105108
*/
106109
type Path = Record<
107110
Method,
108-
Record<string, any> & { operationId: string; 'x-codeSamples': CodeSamples[]; summary: string }
111+
Record<string, any> & {
112+
operationId: string;
113+
'x-codeSamples': CodeSamples[];
114+
summary: string;
115+
}
109116
>;

templates/javascript/clients/algoliasearch/builds/browser.mustache

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// {{{generationBanner}}}
22

3+
import type { InitClientOptions, InitClientRegion } from "./models"
4+
35
{{> algoliasearch/builds/definition}}
46
const commonOptions: CreateClientOptions = {
57
apiKey,
@@ -33,8 +35,9 @@
3335
get _ua(): string {
3436
return this.transporter.algoliaAgent.value;
3537
},
38+
initAbtesting,
3639
initAnalytics,
3740
initPersonalization,
38-
initAbtesting,
41+
initRecommend,
3942
};
4043
}

0 commit comments

Comments
 (0)