Skip to content

Commit a38ceec

Browse files
e-krebsshortcutsmillotp
authored
feat(specs): add composition API (#4056)
Co-authored-by: shortcuts <[email protected]> Co-authored-by: Pierre Millot <[email protected]>
1 parent e4df668 commit a38ceec

File tree

59 files changed

+2649
-42
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+2649
-42
lines changed

clients/algoliasearch-client-javascript/bundlesize.config.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
"path": "packages/client-analytics/dist/builds/browser.umd.js",
1717
"maxSize": "4.85KB"
1818
},
19+
{
20+
"path": "packages/client-composition/dist/builds/browser.umd.js",
21+
"maxSize": "4.05KB"
22+
},
1923
{
2024
"path": "packages/client-insights/dist/builds/browser.umd.js",
2125
"maxSize": "3.90KB"

clients/algoliasearch-client-javascript/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"packages/*"
77
],
88
"scripts": {
9-
"build": "lerna run build --scope '@algolia/requester-testing' --scope '@algolia/logger-console' --scope 'algoliasearch' --include-dependencies",
9+
"build": "lerna run build --scope '@algolia/requester-testing' --scope '@algolia/logger-console' --scope 'algoliasearch' --scope '@algolia/client-composition' --include-dependencies",
1010
"clean": "lerna run clean",
1111
"release:bump": "lerna version ${0:-patch} --no-changelog --no-git-tag-version --no-push --exact --force-publish --yes",
1212
"release:publish": "tsc --project scripts/tsconfig.json && node scripts/dist/scripts/publish.js",
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{
2+
"version": "0.0.1-alpha.0",
3+
"repository": {
4+
"type": "git",
5+
"url": "git+https://github.com/algolia/algoliasearch-client-javascript.git"
6+
},
7+
"type": "module",
8+
"license": "MIT",
9+
"author": "Algolia",
10+
"scripts": {
11+
"build": "yarn clean && yarn tsup && yarn rollup -c rollup.config.js",
12+
"clean": "rm -rf ./dist || true",
13+
"test:bundle": "publint . && attw --pack ."
14+
},
15+
"name": "@algolia/client-composition",
16+
"description": "JavaScript client for client-composition",
17+
"exports": {
18+
".": {
19+
"node": {
20+
"types": {
21+
"import": "./dist/node.d.ts",
22+
"module": "./dist/node.d.ts",
23+
"require": "./dist/node.d.cts"
24+
},
25+
"import": "./dist/builds/node.js",
26+
"module": "./dist/builds/node.js",
27+
"require": "./dist/builds/node.cjs"
28+
},
29+
"worker": {
30+
"types": "./dist/fetch.d.ts",
31+
"default": "./dist/builds/fetch.js"
32+
},
33+
"default": {
34+
"types": "./dist/browser.d.ts",
35+
"module": "./dist/builds/browser.js",
36+
"import": "./dist/builds/browser.js",
37+
"default": "./dist/builds/browser.umd.js"
38+
}
39+
},
40+
"./src/*": "./src/*.ts"
41+
},
42+
"jsdelivr": "./dist/builds/browser.umd.js",
43+
"unpkg": "./dist/builds/browser.umd.js",
44+
"react-native": "./dist/builds/browser.js",
45+
"files": [
46+
"dist",
47+
"index.js",
48+
"index.d.ts"
49+
],
50+
"dependencies": {
51+
"@algolia/client-common": "5.12.0",
52+
"@algolia/requester-browser-xhr": "5.12.0",
53+
"@algolia/requester-node-http": "5.12.0",
54+
"@algolia/requester-fetch": "5.12.0"
55+
},
56+
"devDependencies": {
57+
"@arethetypeswrong/cli": "0.16.4",
58+
"@types/node": "22.8.1",
59+
"publint": "0.2.12",
60+
"rollup": "4.24.2",
61+
"tsup": "8.3.5",
62+
"typescript": "5.6.3"
63+
},
64+
"engines": {
65+
"node": ">= 14.0.0"
66+
}
67+
}

clients/algoliasearch-client-javascript/yarn.lock

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ __metadata:
5454
languageName: unknown
5555
linkType: soft
5656

57+
"@algolia/client-composition@workspace:packages/client-composition":
58+
version: 0.0.0-use.local
59+
resolution: "@algolia/client-composition@workspace:packages/client-composition"
60+
dependencies:
61+
"@algolia/client-common": "npm:5.12.0"
62+
"@algolia/requester-browser-xhr": "npm:5.12.0"
63+
"@algolia/requester-fetch": "npm:5.12.0"
64+
"@algolia/requester-node-http": "npm:5.12.0"
65+
"@arethetypeswrong/cli": "npm:0.16.4"
66+
"@types/node": "npm:22.8.1"
67+
publint: "npm:0.2.12"
68+
rollup: "npm:4.24.2"
69+
tsup: "npm:8.3.5"
70+
typescript: "npm:5.6.3"
71+
languageName: unknown
72+
linkType: soft
73+
5774
"@algolia/client-insights@npm:5.12.0, @algolia/client-insights@workspace:packages/client-insights":
5875
version: 0.0.0-use.local
5976
resolution: "@algolia/client-insights@workspace:packages/client-insights"

config/clients.config.json

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,7 @@
113113
"extension": ".java",
114114
"outputFolder": "src/test/java/com/algolia"
115115
},
116-
"supportedVersions": [
117-
"8",
118-
"11",
119-
"21",
120-
"17"
121-
]
116+
"supportedVersions": ["8", "11", "21", "17"]
122117
},
123118
"javascript": {
124119
"clients": [
@@ -161,6 +156,10 @@
161156
{
162157
"name": "search",
163158
"output": "clients/algoliasearch-client-javascript/packages/client-search"
159+
},
160+
{
161+
"name": "composition",
162+
"output": "clients/algoliasearch-client-javascript/packages/client-composition"
164163
}
165164
],
166165
"folder": "clients/algoliasearch-client-javascript",
@@ -257,13 +256,7 @@
257256
"extension": ".py",
258257
"outputFolder": ""
259258
},
260-
"supportedVersions": [
261-
"3.8",
262-
"3.9",
263-
"3.10",
264-
"3.11",
265-
"3.12"
266-
]
259+
"supportedVersions": ["3.8", "3.9", "3.10", "3.11", "3.12"]
267260
},
268261
"ruby": {
269262
"clients": [

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class AlgoliaJavascriptGenerator extends TypeScriptNodeClientCodegen {
1818

1919
private String CLIENT;
2020
private boolean isAlgoliasearchClient;
21+
private boolean isAlgoliaCompositionClient;
2122

2223
@Override
2324
public String getName() {
@@ -30,6 +31,7 @@ public void processOpts() {
3031

3132
CLIENT = Helpers.camelize((String) additionalProperties.get("client"));
3233
isAlgoliasearchClient = CLIENT.equals("algoliasearch");
34+
isAlgoliaCompositionClient = CLIENT.equals("composition");
3335

3436
// generator specific options
3537
setSupportsES6(true);
@@ -155,6 +157,7 @@ private void setDefaultGeneratorOptions() {
155157
additionalProperties.put("isSearchClient", CLIENT.equals("search") || isAlgoliasearchClient);
156158
additionalProperties.put("isIngestionClient", CLIENT.equals("ingestion"));
157159
additionalProperties.put("isAlgoliasearchClient", isAlgoliasearchClient);
160+
additionalProperties.put("isAlgoliaCompositionClient", isAlgoliaCompositionClient);
158161
additionalProperties.put("packageVersion", Helpers.getPackageJsonVersion(packageName));
159162
additionalProperties.put("packageName", packageName);
160163
additionalProperties.put("npmPackageName", isAlgoliasearchClient ? packageName : "@algolia/" + packageName);
@@ -169,10 +172,16 @@ private void setDefaultGeneratorOptions() {
169172
continue;
170173
}
171174

175+
String version = Helpers.getPackageJsonVersion(name);
176+
177+
if (version.contains("alpha") || version.contains("beta")) {
178+
continue;
179+
}
180+
172181
var dependency = new HashMap<String, Object>();
173182
dependency.put("dependencyName", Helpers.createClientName((String) pkg.get("name"), "javascript"));
174183
dependency.put("dependencyPackage", "@algolia/" + name);
175-
dependency.put("dependencyVersion", Helpers.getPackageJsonVersion(name));
184+
dependency.put("dependencyVersion", version);
176185
dependency.put("withInitMethod", !name.contains("search"));
177186
dependency.put(
178187
"dependencyHasRegionalHosts",

generators/src/main/java/com/algolia/codegen/cts/AlgoliaCTSGenerator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ public Map<String, Object> postProcessSupportingFileData(Map<String, Object> obj
148148
// We can put whatever we want in the bundle, and it will be accessible in the template
149149
bundle.put("mode", mode);
150150
bundle.put("is" + Helpers.capitalize(client) + "Client", true);
151+
bundle.put("isStandaloneClient", client.contains("search") || client.equals("composition"));
151152
bundle.put("isSearchClient", client.contains("search")); // just so algoliasearch is treated as a search client too
152153
bundle.put("client", Helpers.createClientName(importClientName, language) + "Client");
153154
bundle.put("clientPrefix", Helpers.createClientName(importClientName, language));

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ public void addDataToBundle(Map<String, Object> bundle) throws GeneratorExceptio
4646
bundle.put("utilsPackageVersion", Helpers.getPackageJsonVersion("client-common"));
4747
bundle.put("algoliasearchVersion", Helpers.getPackageJsonVersion("algoliasearch"));
4848
bundle.put("initMethod", "init" + Helpers.capitalize(Helpers.camelize(client)));
49-
bundle.put("clientName", client.equals("algoliasearch") ? "liteClient" : "algoliasearch");
50-
bundle.put("importPackage", client.equals("algoliasearch") ? "algoliasearch/lite" : "algoliasearch");
49+
bundle.put(
50+
"clientName",
51+
client.equals("algoliasearch") ? "liteClient" : client.equals("composition") ? "compositionClient" : "algoliasearch"
52+
);
53+
bundle.put(
54+
"importPackage",
55+
client.equals("algoliasearch") ? "algoliasearch/lite" : client.equals("composition") ? "@algolia/client-composition" : "algoliasearch"
56+
);
5157
}
5258
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { ApiError } from '@algolia/client-common';
2+
import { compositionClient } from '@algolia/client-composition';
3+
4+
const appId = process.env.ALGOLIA_APPLICATION_ID || '**** APP_ID *****';
5+
const apiKey = process.env.ALGOLIA_ADMIN_KEY || '**** ADMIN_KEY *****';
6+
7+
// Init client with appId and apiKey
8+
const client = compositionClient(appId, apiKey);
9+
10+
async function testComposition() {
11+
try {
12+
const res = await client.listCompositions();
13+
14+
console.log(`[OK]`, res);
15+
} catch (e) {
16+
if (e instanceof ApiError) {
17+
return console.log(`[${e.status}] ${e.message}`, e.stackTrace, e);
18+
}
19+
20+
console.log('[ERROR]', e);
21+
}
22+
}
23+
24+
testComposition();

playground/javascript/node/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"@algolia/client-abtesting": "link:../../../clients/algoliasearch-client-javascript/packages/client-abtesting",
1111
"@algolia/client-analytics": "link:../../../clients/algoliasearch-client-javascript/packages/client-analytics",
1212
"@algolia/client-common": "link:../../../clients/algoliasearch-client-javascript/packages/client-common",
13+
"@algolia/client-composition": "link:../../../clients/algoliasearch-client-javascript/packages/client-composition",
1314
"@algolia/client-insights": "link:../../../clients/algoliasearch-client-javascript/packages/client-insights",
1415
"@algolia/client-personalization": "link:../../../clients/algoliasearch-client-javascript/packages/client-personalization",
1516
"@algolia/client-query-suggestions": "link:../../../clients/algoliasearch-client-javascript/packages/client-query-suggestions",

scripts/common.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,10 @@ export async function callGenerator(gen: Generator): Promise<void> {
276276
);
277277
}
278278

279+
export function isWSL(): boolean {
280+
return process.env.WSL_DISTRO_NAME !== undefined;
281+
}
282+
279283
export async function setupAndGen(
280284
generators: Generator[],
281285
mode: GeneratorMode,

scripts/cts/testServer/timeout.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export function assertValidTimeouts(expectedCount: number): void {
1717
for (const [lang, state] of Object.entries(timeoutState)) {
1818
let numberOfTestSuites = 1;
1919

20+
// python has sync and async tests
2021
if (lang === 'python') {
2122
numberOfTestSuites = 2;
2223
}
@@ -26,23 +27,23 @@ export function assertValidTimeouts(expectedCount: number): void {
2627
expect(state.duration.length).to.equal(3 * numberOfTestSuites);
2728

2829
for (let i = 0; i < numberOfTestSuites; i++) {
29-
expect(state.timestamp[3 * i + 1] - state.timestamp[3 * i]).to.be.closeTo(state.duration[3 * i], 100);
30-
expect(state.timestamp[3 * i + 2] - state.timestamp[3 * i + 1]).to.be.closeTo(state.duration[3 * i + 1], 100);
30+
expect(state.timestamp[3 * i + 1] - state.timestamp[3 * i]).to.be.closeTo(state.duration[3 * i], 400);
31+
expect(state.timestamp[3 * i + 2] - state.timestamp[3 * i + 1]).to.be.closeTo(state.duration[3 * i + 1], 400);
3132

3233
// languages are not consistent yet for the delay between requests
3334
switch (lang) {
3435
case 'javascript':
3536
expect(state.duration[3 * i] * 4).to.be.closeTo(state.duration[3 * i + 1], 300);
3637
break;
3738
case 'php':
38-
expect(state.duration[3 * i] * 2).to.be.closeTo(state.duration[3 * i + 1], 200);
39+
expect(state.duration[3 * i] * 2).to.be.closeTo(state.duration[3 * i + 1], 300);
3940
break;
4041
case 'swift':
4142
expect(state.duration[3 * i]).to.be.closeTo(state.duration[3 * i + 1], 800);
4243
break;
4344
default:
4445
// the delay should be the same, because the `retryCount` is per host instead of global
45-
expect(state.duration[3 * i]).to.be.closeTo(state.duration[3 * i + 1], 150);
46+
expect(state.duration[3 * i]).to.be.closeTo(state.duration[3 * i + 1], 300);
4647
break;
4748
}
4849
}

scripts/generate.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { callGenerator, setupAndGen } from './common.js';
1+
import { callGenerator, isWSL, run, setupAndGen } from './common.js';
22
import { getLanguageFolder } from './config.js';
33
import { formatter } from './formatter.js';
44
import { removeExistingCodegen } from './pre-gen/index.js';
@@ -15,6 +15,9 @@ export async function generate(generators: Generator[]): Promise<void> {
1515
});
1616

1717
for (const lang of [...new Set(generators.map((gen) => gen.language))]) {
18+
if (isWSL()) {
19+
await run(`sudo chmod 777 -R ${getLanguageFolder(lang)}`);
20+
}
1821
await formatter(lang, getLanguageFolder(lang));
1922
}
2023
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
description: Composition not found.
2+
content:
3+
application/json:
4+
schema:
5+
$ref: '../schemas/ErrorBase.yml'
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
compositionID:
2+
in: path
3+
name: compositionID
4+
description: Unique Composition ObjectID.
5+
required: true
6+
schema:
7+
$ref: '#/compositionObjectID'
8+
9+
compositionObjectID:
10+
type: string
11+
description: Unique Composition ObjectID.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
action:
2+
type: string
3+
enum:
4+
- upsert
5+
- delete
6+
description: Type of Composition Batch operation.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
title: getTaskResponse
2+
type: object
3+
additionalProperties: false
4+
properties:
5+
status:
6+
$ref: '../../../common/responses/common.yml#/taskStatus'
7+
required:
8+
- status
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
hit:
2+
type: object
3+
description: |
4+
Search result.
5+
6+
A hit is a record from your index, augmented with special attributes for highlighting, snippeting, and ranking.
7+
x-is-generic: true
8+
additionalProperties: true
9+
required:
10+
- objectID
11+
properties:
12+
objectID:
13+
$ref: '../../../common/parameters.yml#/objectID'
14+
_highlightResult:
15+
$ref: '../../../common/schemas/HighlightResult.yml#/highlightResultMap'
16+
_snippetResult:
17+
$ref: '../../../common/schemas/SnippetResult.yml#/snippetResultMap'
18+
_rankingInfo:
19+
$ref: '#/rankingInfo'
20+
_distinctSeqID:
21+
$ref: '../../../common/schemas/Hit.yml#/distinctSeqID'
22+
23+
rankingInfo:
24+
allOf:
25+
- $ref: '../../../common/schemas/Hit.yml#/rankingInfo'
26+
- $ref: '#/compositionRankingInfo'
27+
28+
compositionRankingInfo:
29+
type: object
30+
additionalProperties: false
31+
properties:
32+
composed:
33+
title: composedRankingInfo
34+
type: object
35+
additionalProperties: false
36+
properties:
37+
index:
38+
type: string
39+
inset:
40+
type: string
41+
required:
42+
- index
43+
- inset

0 commit comments

Comments
 (0)