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 Mar 12, 2024
1 parent c27282b commit d9ac12f
Show file tree
Hide file tree
Showing 25 changed files with 321 additions and 125 deletions.
3 changes: 2 additions & 1 deletion clients/algoliasearch-client-javascript/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ __metadata:
languageName: unknown
linkType: soft

"@algolia/recommend@workspace:packages/recommend":
"@algolia/recommend@npm:5.0.0-alpha.106, @algolia/recommend@workspace:packages/recommend":
version: 0.0.0-use.local
resolution: "@algolia/recommend@workspace:packages/recommend"
dependencies:
Expand Down Expand Up @@ -3119,6 +3119,7 @@ __metadata:
"@algolia/client-common": "npm:5.0.0-alpha.107"
"@algolia/client-personalization": "npm:5.0.0-alpha.106"
"@algolia/client-search": "npm:5.0.0-alpha.106"
"@algolia/recommend": "npm:5.0.0-alpha.106"
"@algolia/requester-browser-xhr": "npm:5.0.0-alpha.107"
"@algolia/requester-node-http": "npm:5.0.0-alpha.107"
"@babel/preset-env": "npm:7.24.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 @@ -158,7 +158,6 @@
}
],
"folder": "clients/algoliasearch-client-javascript",
"npmNamespace": "@algolia",
"gitRepoId": "algoliasearch-client-javascript",
"packageVersion": "5.0.0-alpha.108",
"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 @@ -4,6 +4,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 @@ -19,10 +20,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 @@ -70,7 +93,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
59 changes: 39 additions & 20 deletions scripts/buildSpecs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { GENERATORS, capitalize, createClientName, exists, run, toAbsolutePath }
import { createSpinner } from './spinners.js';
import type { CodeSamples, Language, SnippetSamples, Spec } from './types.js';

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

function mapLanguageToCodeSampleSupporter(language: Language): CodeSamples['lang'] {
switch (language) {
Expand Down Expand Up @@ -192,27 +192,36 @@ async function lintCommon(useCache: boolean): Promise<void> {
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: {} };

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 @@ -239,25 +248,26 @@ 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`),
});

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

if (useCache) {
spinner.text = `checking cache for '${specBase}'`;
spinner.text = `checking cache for '${spec}'`;

if (await cache.isValid()) {
spinner.succeed(`job skipped, cache found for '${specBase}'`);
spinner.succeed(`job skipped, cache found for '${spec}'`);
return;
}

spinner.text = `cache not found for '${specBase}'`;
spinner.text = `cache not found for '${spec}'`;
}

// First linting the base
Expand All @@ -281,6 +291,8 @@ async function buildSpec({
await buildLiteSpec({
spec,
bundledPath: toAbsolutePath(bundledPath),
docs,
useCache,
});
}

Expand Down Expand Up @@ -314,6 +326,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
clients = clients.filter((client) => client !== 'recommend');
}

await Promise.all(
clients.map((client) => buildSpec({ spec: client, outputFormat, docs, useCache })),
);
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
11 changes: 9 additions & 2 deletions scripts/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,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 Expand Up @@ -105,5 +108,9 @@ export type SnippetSamples = Record<Language, Record<string, string>>;
*/
type Path = Record<
Method,
Record<string, any> & { operationId: string; 'x-codeSamples': CodeSamples[]; summary: string }
Record<string, any> & {
operationId: string;
'x-codeSamples': CodeSamples[];
summary: string;
}
>;
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// {{{generationBanner}}}

import type { InitClientOptions, InitClientRegion } from "./models"

{{> algoliasearch/builds/definition}}
const commonOptions: CreateClientOptions = {
apiKey,
Expand Down Expand Up @@ -33,8 +35,9 @@
get _ua(): string {
return this.transporter.algoliaAgent.value;
},
initAbtesting,
initAnalytics,
initPersonalization,
initAbtesting,
initRecommend,
};
}
Loading

0 comments on commit d9ac12f

Please sign in to comment.