Skip to content

Commit

Permalink
feat(clients): add recommend to algoliasearch
Browse files Browse the repository at this point in the history
  • Loading branch information
shortcuts committed Jun 20, 2024
1 parent 24ea158 commit 5064d64
Show file tree
Hide file tree
Showing 25 changed files with 385 additions and 96 deletions.
64 changes: 57 additions & 7 deletions clients/algoliasearch-client-javascript/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2928,11 +2928,11 @@ __metadata:
linkType: hard

"@types/node@npm:*":
version: 20.14.5
resolution: "@types/node@npm:20.14.5"
version: 20.11.25
resolution: "@types/node@npm:20.11.25"
dependencies:
undici-types: "npm:~5.26.4"
checksum: 10/74c7974a8c75280f9397f22ce34d10d5575668e3c357a165f385c9365c39b3ccda3aa2e7237e7e907fc72e515afb93cc0be1f3e2074cc1889c1ffeb01d2843cc
checksum: 10/861265f1bbb151404bd8842b595f027a4ff067c61ecff9a37b9f7f53922c18dd532c8e795e8e7675dd8dba056645623fd2b9848d5ef72863ec3609096cd2923e
languageName: node
linkType: hard

Expand Down Expand Up @@ -3088,7 +3088,16 @@ __metadata:
languageName: node
linkType: hard

"acorn@npm:^8.1.0, acorn@npm:^8.11.0, acorn@npm:^8.8.1, acorn@npm:^8.8.2":
"acorn@npm:^8.1.0, acorn@npm:^8.8.1, acorn@npm:^8.8.2":
version: 8.11.3
resolution: "acorn@npm:8.11.3"
bin:
acorn: bin/acorn
checksum: 10/b688e7e3c64d9bfb17b596e1b35e4da9d50553713b3b3630cf5690f2b023a84eac90c56851e6912b483fe60e8b4ea28b254c07e92f17ef83d72d78745a8352dd
languageName: node
linkType: hard

"acorn@npm:^8.11.0":
version: 8.12.0
resolution: "acorn@npm:8.12.0"
bin:
Expand Down Expand Up @@ -6847,7 +6856,14 @@ __metadata:
languageName: node
linkType: hard

"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0":
"lru-cache@npm:^10.0.1":
version: 10.2.0
resolution: "lru-cache@npm:10.2.0"
checksum: 10/502ec42c3309c0eae1ce41afca471f831c278566d45a5273a0c51102dee31e0e250a62fa9029c3370988df33a14188a38e682c16143b794de78668de3643e302
languageName: node
linkType: hard

"lru-cache@npm:^10.2.0":
version: 10.2.2
resolution: "lru-cache@npm:10.2.2"
checksum: 10/ff1a496d30b5eaec2c9079080965bb0cede203cf878371f7033a007f1e54cd4aa13cc8abf7ccec4c994a83a22ed5476e83a55bb57cc07e6c1547a42937e42c37
Expand Down Expand Up @@ -7370,7 +7386,7 @@ __metadata:
languageName: node
linkType: hard

"node-gyp@npm:^10.0.0, node-gyp@npm:latest":
"node-gyp@npm:^10.0.0":
version: 10.1.0
resolution: "node-gyp@npm:10.1.0"
dependencies:
Expand All @@ -7390,6 +7406,26 @@ __metadata:
languageName: node
linkType: hard

"node-gyp@npm:latest":
version: 10.0.1
resolution: "node-gyp@npm:10.0.1"
dependencies:
env-paths: "npm:^2.2.0"
exponential-backoff: "npm:^3.1.1"
glob: "npm:^10.3.10"
graceful-fs: "npm:^4.2.6"
make-fetch-happen: "npm:^13.0.0"
nopt: "npm:^7.0.0"
proc-log: "npm:^3.0.0"
semver: "npm:^7.3.5"
tar: "npm:^6.1.2"
which: "npm:^4.0.0"
bin:
node-gyp: bin/node-gyp.js
checksum: 10/578cf0c821f258ce4b6ebce4461eca4c991a4df2dee163c0624f2fe09c7d6d37240be4942285a0048d307230248ee0b18382d6623b9a0136ce9533486deddfa8
languageName: node
linkType: hard

"node-int64@npm:^0.4.0":
version: 0.4.0
resolution: "node-int64@npm:0.4.0"
Expand Down Expand Up @@ -9343,7 +9379,7 @@ __metadata:
languageName: node
linkType: hard

"tar@npm:6.2.1, tar@npm:^6.1.11, tar@npm:^6.1.2":
"tar@npm:6.2.1":
version: 6.2.1
resolution: "tar@npm:6.2.1"
dependencies:
Expand All @@ -9357,6 +9393,20 @@ __metadata:
languageName: node
linkType: hard

"tar@npm:^6.1.11, tar@npm:^6.1.2":
version: 6.2.0
resolution: "tar@npm:6.2.0"
dependencies:
chownr: "npm:^2.0.0"
fs-minipass: "npm:^2.0.0"
minipass: "npm:^5.0.0"
minizlib: "npm:^2.1.1"
mkdirp: "npm:^1.0.3"
yallist: "npm:^4.0.0"
checksum: 10/2042bbb14830b5cd0d584007db0eb0a7e933e66d1397e72a4293768d2332449bc3e312c266a0887ec20156dea388d8965e53b4fc5097f42d78593549016da089
languageName: node
linkType: hard

"temp-dir@npm:1.0.0":
version: 1.0.0
resolution: "temp-dir@npm:1.0.0"
Expand Down
1 change: 0 additions & 1 deletion config/clients.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@
}
],
"folder": "clients/algoliasearch-client-javascript",
"npmNamespace": "@algolia",
"gitRepoId": "algoliasearch-client-javascript",
"packageVersion": "5.0.0-beta.4",
"modelFolder": "model",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ private void setDefaultGeneratorOptions() {
additionalProperties.put("abtestingVersion", Helpers.getPackageJsonVersion("client-abtesting"));
additionalProperties.put("personalizationVersion", Helpers.getPackageJsonVersion("client-personalization"));
additionalProperties.put("searchVersion", Helpers.getPackageJsonVersion("client-search"));
additionalProperties.put("recommendVersion", Helpers.getPackageJsonVersion("recommend"));

// Files used to generate the `lite` client
apiName = "lite" + Helpers.API_SUFFIX;
Expand Down Expand Up @@ -185,7 +186,6 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
setDefaultGeneratorOptions();
try {
additionalProperties.put("utilsPackageVersion", Helpers.getPackageJsonVersion("client-common"));
additionalProperties.put("npmNamespace", Helpers.getClientConfigField("javascript", "npmNamespace"));
} catch (GeneratorException e) {
e.printStackTrace();
System.exit(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ public void addTestsSupportingFiles(List<SupportingFile> supportingFiles) {

@Override
public void addDataToBundle(Map<String, Object> bundle) throws GeneratorException {
String npmNamespace = Helpers.getClientConfigField("javascript", "npmNamespace");

bundle.put("utilsPackageVersion", Helpers.getPackageJsonVersion("client-common"));
bundle.put("npmNamespace", npmNamespace);

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

clients.add(Map.of("packageName", packageName, "packagePath", "link:../../../" + output.replace("#{cwd}/", "")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.algolia.codegen.utils.*;
import java.io.File;
import java.util.*;
import org.apache.commons.lang3.ArrayUtils;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenResponse;
Expand All @@ -24,10 +25,32 @@ protected Map<String, Request[]> loadRequestCTS() throws Exception {
String clientName = client;
// This special case allow us to read the `search` CTS to generated the tests for the
// `lite` client, which is only available in Javascript
if ((language.equals("javascript") || language.equals("dart")) && client.equals("algoliasearch")) {
if (client.equals("algoliasearch")) {
clientName = "search";
}
return super.loadCTS("requests", clientName, Request[].class);

Map<String, Request[]> baseCTS = super.loadCTS("requests", clientName, Request[].class);

// The algoliasearch client bundles many client and therefore should provide tests for all the
// subsequent specs
if (client.equals("algoliasearch")) {
Map<String, Request[]> recommendCTS = super.loadCTS("requests", "recommend", Request[].class);
for (Map.Entry<String, Request[]> entry : recommendCTS.entrySet()) {
String operation = entry.getKey();
// custom methods are common to every clients, we don't want duplicate tests
if (operation.startsWith("custom")) {
continue;
}

if (baseCTS.containsKey(operation)) {
baseCTS.put(operation, ArrayUtils.addAll(baseCTS.get(operation), entry.getValue()));
} else {
baseCTS.put(operation, entry.getValue());
}
}
}

return baseCTS;
}

@Override
Expand Down Expand Up @@ -75,7 +98,9 @@ public void run(Map<String, CodegenModel> models, Map<String, CodegenOperation>
throw new CTSException(
"operationId '" +
operationId +
"' does not exist in the tests suite, please create the file:" +
"' does not exist in the " +
client +
" tests suite, please create the file:" +
" 'tests/CTS/requests/" +
client +
"/" +
Expand Down
5 changes: 2 additions & 3 deletions scripts/buildClients.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import * as fsp from 'fs/promises';

import { run, toAbsolutePath } from './common.js';
import { getClientsConfigField, getLanguageFolder } from './config.js';
import { getLanguageFolder } from './config.js';
import { createSpinner } from './spinners.js';
import type { Generator, Language } from './types.js';

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

await run('YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install', { cwd });
Expand Down
10 changes: 2 additions & 8 deletions scripts/ci/githubActions/createMatrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@
import * as core from '@actions/core';

import { CLIENTS, createClientName, GENERATORS, LANGUAGES } from '../../common.js';
import {
getClientsConfigField,
getLanguageFolder,
getTestExtension,
getTestOutputFolder,
} from '../../config.js';
import { getLanguageFolder, getTestExtension, getTestOutputFolder } from '../../config.js';

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

// `algoliasearch` is not preceded by `@algolia`
return client === 'algoliasearch' ? packageName : `${npmNamespace}/${packageName}`;
return client === 'algoliasearch' ? packageName : `@algolia/${packageName}`;
});

buildCommand = `cd ${matrix[language].path} && yarn build:many '{${packageNames.join(
Expand Down
2 changes: 1 addition & 1 deletion scripts/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export async function formatter(language: string, cwd: string): Promise<void> {
await run('goimports -w . && golangci-lint run --fix', { cwd, language });
break;
case 'javascript':
await run(`yarn eslint --ext=ts,json ${cwd} --fix --no-error-on-unmatched-pattern`);
await run(`yarn eslint --fix --no-error-on-unmatched-pattern --ext=ts,json ${cwd}`);
break;
case 'java':
await run(
Expand Down
56 changes: 35 additions & 21 deletions scripts/specs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { Spec } from '../types.js';
import { lintCommon, transformBundle } from './format.js';
import type { BaseBuildSpecsOptions } from './types.js';

const ALGOLIASEARCH_LITE_OPERATIONS = ['search', 'customPost'];
const ALGOLIASEARCH_LITE_OPERATIONS = ['search', 'customPost', 'getRecommendations'];

/**
* Creates a lite search spec with the `ALGOLIASEARCH_LITE_OPERATIONS` methods
Expand All @@ -19,32 +19,36 @@ const ALGOLIASEARCH_LITE_OPERATIONS = ['search', 'customPost'];
async function buildLiteSpec({
spec,
bundledPath,
docs,
useCache,
}: {
spec: string;
bundledPath: string;
docs: boolean;
useCache: boolean;
}): Promise<void> {
const parsed = yaml.load(await fsp.readFile(toAbsolutePath(bundledPath), 'utf8')) as Spec;

// Filter methods.
parsed.paths = Object.entries(parsed.paths).reduce(
(acc, [path, operations]) => {
for (const [, operation] of Object.entries(operations)) {
if (ALGOLIASEARCH_LITE_OPERATIONS.includes(operation.operationId)) {
return { ...acc, [path]: { post: operation } };
}
}
await buildSpec({ spec: 'recommend', outputFormat: 'yml', docs, useCache });

return acc;
},
{} as Spec['paths'],
);
const base = yaml.load(await fsp.readFile(toAbsolutePath(bundledPath), 'utf8')) as Spec;
const recommend = yaml.load(
await fsp.readFile(toAbsolutePath(bundledPath.replace('algoliasearch', 'recommend')), 'utf8'),
) as Spec;
base.paths = { ...base.paths, ...recommend.paths };
base.components.schemas = { ...base.components.schemas, ...recommend.components.schemas };

await fsp.writeFile(bundledPath, yaml.dump(parsed));
const lite = { ...base, paths: {} };

// remove unused components for the outputted light spec
await run(
`yarn openapi bundle ${bundledPath} -o ${bundledPath} --ext yml --remove-unused-components`,
);
for (const [path, operations] of Object.entries(base.paths)) {
for (const [, operation] of Object.entries(operations)) {
if (ALGOLIASEARCH_LITE_OPERATIONS.includes(operation.operationId)) {
lite.paths[path] = { post: operation };

break;
}
}
}

await fsp.writeFile(bundledPath, yaml.dump(lite));

await transformBundle({
bundledPath,
Expand All @@ -71,11 +75,12 @@ async function buildSpec({

// In case of lite we use a the `search` spec as a base because only its bundled form exists.
const specBase = isAlgoliasearch ? 'search' : spec;
const deps = isAlgoliasearch ? ['search', 'recommend'] : [spec];
const logSuffix = docs ? 'doc spec' : 'spec';
const cache = new Cache({
folder: toAbsolutePath('specs/'),
generatedFiles: [docs ? `bundled/${spec}.doc.yml` : `bundled/${spec}.yml`],
filesToCache: [specBase, 'common'],
filesToCache: [...deps, 'common'],
cacheFile: toAbsolutePath(`specs/dist/${spec}.${docs ? 'doc.' : ''}cache`),
});

Expand Down Expand Up @@ -113,6 +118,8 @@ async function buildSpec({
await buildLiteSpec({
spec,
bundledPath: toAbsolutePath(bundledPath),
docs,
useCache,
});
}

Expand Down Expand Up @@ -140,6 +147,13 @@ export async function buildSpecs({

await lintCommon(useCache);

// the `lite` spec will build the `recommend` spec, so we remove it from the list
// to prevent concurrent builds
if (clients.includes('algoliasearch')) {
// eslint-disable-next-line no-param-reassign

Check failure on line 153 in scripts/specs/index.ts

View workflow job for this annotation

GitHub Actions / scripts

'no-param-reassign' rule is disabled but never reported
clients = clients.filter((client) => client !== 'recommend');
}

await Promise.all(
clients.map((client) => buildSpec({ spec: client, outputFormat, docs, useCache })),
);
Expand Down
5 changes: 4 additions & 1 deletion scripts/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ export type Language = keyof typeof config;
export type Spec = {
servers: Server[];
tags: Tag[];
paths: Path[];
paths: Path;
components: {
schemas: Record<string, any>;
};
};

/**
Expand Down
Loading

0 comments on commit 5064d64

Please sign in to comment.