Skip to content

Commit a3c1861

Browse files
authored
feat(generators): generate algoliasearch JS client (#760)
1 parent e191243 commit a3c1861

Some content is hidden

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

56 files changed

+508
-2355
lines changed

.github/workflows/check.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,6 @@ jobs:
225225
if: ${{ steps.cache.outputs.cache-hit != 'true' && matrix.client.language != 'php' }}
226226
run: yarn cli build clients ${{ matrix.client.language }} ${{ matrix.client.toBuild }}
227227

228-
- name: Build JavaScript 'algoliasearch' client
229-
if: ${{ steps.cache.outputs.cache-hit != 'true' && matrix.client.language == 'javascript' }}
230-
run: yarn cli build clients javascript algoliasearch
231-
232228
- name: Run JavaScript 'algoliasearch' client tests
233229
if: ${{ steps.cache.outputs.cache-hit != 'true' && matrix.client.language == 'javascript' }}
234230
run: cd ${{ matrix.client.path }} && yarn workspace @experimental-api-clients-automation/algoliasearch test

config/generation.config.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@ module.exports = {
2121
'!clients/algoliasearch-client-javascript/.github/**',
2222
'!clients/algoliasearch-client-javascript/.yarn/**',
2323
'!clients/algoliasearch-client-javascript/scripts/**',
24-
'!clients/algoliasearch-client-javascript/packages/algoliasearch/**',
2524
'!clients/algoliasearch-client-javascript/packages/requester-*/**',
2625
'!clients/algoliasearch-client-javascript/packages/client-common/**',
27-
'clients/algoliasearch-client-javascript/packages/algoliasearch/lite/**',
2826

2927
// PHP
3028
'!clients/algoliasearch-client-php/*',

config/openapitools.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
"generator-cli": {
33
"version": "6.0.0",
44
"generators": {
5-
"javascript-search": {
6-
"output": "#{cwd}/clients/algoliasearch-client-javascript/packages/client-search",
5+
"javascript-algoliasearch": {
6+
"output": "#{cwd}/clients/algoliasearch-client-javascript/packages/algoliasearch",
77
"reservedWordsMappings": "queryParameters=queryParameters,requestOptions=requestOptions,delete=delete",
88
"additionalProperties": {
99
"packageVersion": "0.6.1"
1010
}
1111
},
12-
"javascript-lite": {
13-
"output": "#{cwd}/clients/algoliasearch-client-javascript/packages/algoliasearch/lite",
12+
"javascript-search": {
13+
"output": "#{cwd}/clients/algoliasearch-client-javascript/packages/client-search",
1414
"reservedWordsMappings": "queryParameters=queryParameters,requestOptions=requestOptions,delete=delete",
1515
"additionalProperties": {
1616
"packageVersion": "0.6.1"

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

Lines changed: 76 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
public class AlgoliaJavaScriptGenerator extends TypeScriptNodeClientCodegen {
1414

1515
private String CLIENT;
16+
private boolean isAlgoliasearchClient;
1617

1718
@Override
1819
public String getName() {
@@ -24,6 +25,7 @@ public void processOpts() {
2425
super.processOpts();
2526

2627
CLIENT = Utils.camelize((String) additionalProperties.get("client"));
28+
isAlgoliasearchClient = CLIENT.equals("algoliasearch");
2729

2830
// generator specific options
2931
setSupportsES6(true);
@@ -35,23 +37,67 @@ public void processOpts() {
3537
// clear all supported files to avoid unwanted ones
3638
supportingFiles.clear();
3739

38-
supportingFiles.add(new SupportingFile("clientMethodProps.mustache", "model", "clientMethodProps.ts"));
39-
supportingFiles.add(new SupportingFile("modelBarrel.mustache", "model", "index.ts"));
40-
supportingFiles.add(new SupportingFile("browser.mustache", "builds", "browser.ts"));
41-
supportingFiles.add(new SupportingFile("node.mustache", "builds", "node.ts"));
40+
// Files common to both generations
41+
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
42+
supportingFiles.add(new SupportingFile("tsconfig.mustache", "", "tsconfig.json"));
4243

43-
// root
44+
// root export files
4445
supportingFiles.add(new SupportingFile("index.mustache", "", "index.js"));
4546
supportingFiles.add(new SupportingFile("index.d.mustache", "", "index.d.ts"));
4647

47-
// the `lite` package is a subfolder of `algoliasearch`, which does not require
48-
// those package-related files, as they are present at an higher level.
49-
if (!CLIENT.equals("lite")) {
50-
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
51-
supportingFiles.add(new SupportingFile("tsconfig.mustache", "", "tsconfig.json"));
48+
// `client` related files, `algoliasearch` have it's own logic below
49+
if (!isAlgoliasearchClient) {
50+
// models
51+
supportingFiles.add(new SupportingFile("client/model/clientMethodProps.mustache", "model", "clientMethodProps.ts"));
52+
supportingFiles.add(new SupportingFile("client/model/modelBarrel.mustache", "model", "index.ts"));
53+
54+
// builds
55+
supportingFiles.add(new SupportingFile("client/builds/browser.mustache", "builds", "browser.ts"));
56+
supportingFiles.add(new SupportingFile("client/builds/node.mustache", "builds", "node.ts"));
57+
}
58+
// `algoliasearch` related files
59+
else {
60+
// `algoliasearch` builds
61+
supportingFiles.add(new SupportingFile("algoliasearch/builds/browser.mustache", "builds", "browser.ts"));
62+
supportingFiles.add(new SupportingFile("algoliasearch/builds/node.mustache", "builds", "node.ts"));
63+
supportingFiles.add(new SupportingFile("algoliasearch/builds/models.mustache", "builds", "models.ts"));
64+
65+
// `lite` builds
66+
supportingFiles.add(new SupportingFile("client/builds/browser.mustache", "lite/builds", "browser.ts"));
67+
supportingFiles.add(new SupportingFile("client/builds/node.mustache", "lite/builds", "node.ts"));
68+
69+
// `lite` models
70+
supportingFiles.add(new SupportingFile("client/model/clientMethodProps.mustache", "lite/model", "clientMethodProps.ts"));
71+
supportingFiles.add(new SupportingFile("client/model/modelBarrel.mustache", "lite/model", "index.ts"));
72+
73+
// `lite root export files
74+
supportingFiles.add(new SupportingFile("algoliasearch/lite.mustache", "", "lite.js"));
75+
supportingFiles.add(new SupportingFile("algoliasearch/lite.d.mustache", "", "lite.d.ts"));
5276
}
5377
}
5478

79+
@Override
80+
public String apiFileFolder() {
81+
String fileFolder = super.apiFileFolder();
82+
83+
if (!isAlgoliasearchClient) {
84+
return fileFolder;
85+
}
86+
87+
return fileFolder.replace("src", "lite/src");
88+
}
89+
90+
@Override
91+
public String modelFileFolder() {
92+
String fileFolder = super.modelFileFolder();
93+
94+
if (!isAlgoliasearchClient) {
95+
return fileFolder;
96+
}
97+
98+
return fileFolder.replace("model", "lite/model");
99+
}
100+
55101
@Override
56102
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<Server> servers) {
57103
return Utils.specifyCustomRequest(super.fromOperation(path, httpMethod, operation, servers));
@@ -66,7 +112,20 @@ private void setDefaultGeneratorOptions() {
66112
additionalProperties.put("algoliaAgent", Utils.capitalize(CLIENT));
67113
additionalProperties.put("gitRepoId", "algoliasearch-client-javascript");
68114
additionalProperties.put("isSearchClient", CLIENT.equals("search"));
69-
additionalProperties.put("isLiteClient", CLIENT.equals("lite"));
115+
additionalProperties.put("isAlgoliasearchClient", isAlgoliasearchClient);
116+
117+
if (isAlgoliasearchClient) {
118+
// Files used to create the package.json of the algoliasearch package
119+
additionalProperties.put("analyticsVersion", Utils.getOpenApiToolsField("javascript", "analytics", "packageVersion"));
120+
additionalProperties.put("personalizationVersion", Utils.getOpenApiToolsField("javascript", "personalization", "packageVersion"));
121+
additionalProperties.put("searchVersion", Utils.getOpenApiToolsField("javascript", "search", "packageVersion"));
122+
123+
// Files used to generate the `lite` client
124+
apiName = "lite" + Utils.API_SUFFIX;
125+
additionalProperties.put("apiName", apiName);
126+
additionalProperties.put("capitalizedApiName", Utils.capitalize(apiName));
127+
additionalProperties.put("algoliaAgent", "Lite");
128+
}
70129
}
71130

72131
/** Provides an opportunity to inspect and modify operation data before the code is generated. */
@@ -128,7 +187,9 @@ public String toApiName(String name) {
128187
return "Default" + Utils.API_SUFFIX;
129188
}
130189

131-
return Utils.capitalize(CLIENT + Utils.API_SUFFIX);
190+
String endClient = isAlgoliasearchClient ? "lite" : CLIENT;
191+
192+
return Utils.capitalize(endClient + Utils.API_SUFFIX);
132193
}
133194

134195
/** The `apiFileName` is in camelCase. */
@@ -138,7 +199,9 @@ public String toApiFilename(String name) {
138199
return "default" + Utils.API_SUFFIX;
139200
}
140201

141-
return CLIENT + Utils.API_SUFFIX;
202+
String endClient = isAlgoliasearchClient ? "lite" : CLIENT;
203+
204+
return endClient + Utils.API_SUFFIX;
142205
}
143206

144207
/** The `apiFileName` is in camelCase. */

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public class Utils {
2020
public static final Set<String> CUSTOM_METHOD = Sets.newHashSet("del", "get", "post", "put");
2121

2222
private static JsonNode cacheConfig;
23+
private static JsonNode cacheOpenApiToolsConfig;
2324

2425
private Utils() {}
2526

@@ -140,6 +141,28 @@ public static String getClientConfigField(String language, String... fields) thr
140141
return value.asText();
141142
}
142143

144+
/** Get the `field` value in the `config/openapitools.json` file for the given language */
145+
public static String getOpenApiToolsField(String language, String client, String... fields) throws ConfigException {
146+
if (fields.length == 0) {
147+
throw new ConfigException("getOpenApiToolsField requires at least one field");
148+
}
149+
if (cacheOpenApiToolsConfig == null) {
150+
cacheOpenApiToolsConfig = readJsonFile("config/openapitools.json");
151+
}
152+
JsonNode value = cacheOpenApiToolsConfig
153+
.get("generator-cli")
154+
.get("generators")
155+
.get(language + "-" + client)
156+
.get("additionalProperties");
157+
for (String field : fields) {
158+
value = value.get(field);
159+
}
160+
if (!value.isTextual()) {
161+
throw new ConfigException(fields[fields.length - 1] + " is not a string");
162+
}
163+
return value.asText();
164+
}
165+
143166
public static JsonNode readJsonFile(String filePath) throws ConfigException {
144167
try {
145168
return Json.mapper().readTree(new File(filePath));

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,16 @@ public Map<String, Object> postProcessSupportingFileData(Map<String, Object> obj
9292
Map<String, Object> bundle = objs;
9393
bundle.clear();
9494

95+
// This only exists for the `javascript-algoliasearch` combo, because the `lite` client is
96+
// nested inside `algoliasearch`.
97+
String importClientName = client;
98+
if (language.equals("javascript") && client.equals("algoliasearch")) {
99+
importClientName = "lite";
100+
}
101+
95102
// We can put whatever we want in the bundle, and it will be accessible in the template
96-
bundle.put("client", Utils.createClientName(client, language) + "Client");
97-
bundle.put("clientPrefix", Utils.createClientName(client, language));
103+
bundle.put("client", Utils.createClientName(importClientName, language) + "Client");
104+
bundle.put("clientPrefix", Utils.createClientName(importClientName, language));
98105
bundle.put("hasRegionalHost", hasRegionalHost);
99106
bundle.put("defaultRegion", client.equals("predict") ? "ew" : "us");
100107
bundle.put("lambda", lambda);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public void addDataToBundle(Map<String, Object> bundle) throws GeneratorExceptio
2727
String clientName = output.substring(output.lastIndexOf('/') + 1);
2828
String npmNamespace = Utils.getClientConfigField("javascript", "npmNamespace");
2929

30-
if (clientName.equals("lite")) {
30+
if (clientName.equals("algoliasearch")) {
3131
bundle.put("import", npmNamespace + "/" + "algoliasearch/lite");
3232
} else {
3333
bundle.put("import", npmNamespace + "/" + clientName);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public TestsClient(String language, String client) {
2020
@Override
2121
public boolean available() {
2222
// no `lite` client test for now
23-
if (language.equals("javascript") && client.equals("lite")) {
23+
if (language.equals("javascript") && client.equals("algoliasearch")) {
2424
return false;
2525
}
2626

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ protected Map<String, Request[]> loadRequestCTS() throws Exception {
1818
String clientName = client;
1919
// This special case allow us to read the `search` CTS to generated the tests for the
2020
// `lite` client, which is only available in JavaScript
21-
if (language.equals("javascript") && client.equals("lite")) {
21+
if (language.equals("javascript") && client.equals("algoliasearch")) {
2222
clientName = "search";
2323
}
2424
return super.loadCTS("methods/requests", clientName, Request[].class);

scripts/buildClients.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ export async function buildClients(
6666
): Promise<void> {
6767
const langs = [...new Set(generators.map((gen) => gen.language))];
6868

69+
if (langs.includes('javascript')) {
70+
await run('yarn install', {
71+
verbose,
72+
cwd: getLanguageFolder('javascript'),
73+
});
74+
}
75+
6976
if (!CI && !skipUtils && langs.includes('javascript')) {
7077
const spinner = createSpinner(
7178
"building 'JavaScript' utils",

scripts/buildSpecs.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,9 @@ async function buildSpec(
194194
verbose: boolean,
195195
useCache: boolean
196196
): Promise<void> {
197-
const isLite = spec === 'lite';
197+
const isAlgoliasearch = spec === 'algoliasearch';
198198
// In case of lite we use a the `search` spec as a base because only its bundled form exists.
199-
const specBase = isLite ? 'search' : spec;
199+
const specBase = isAlgoliasearch ? 'search' : spec;
200200
const cacheFile = toAbsolutePath(`specs/dist/${spec}.cache`);
201201
let hash = '';
202202

@@ -233,7 +233,7 @@ async function buildSpec(
233233
);
234234

235235
// Add the correct tags to be able to generate the proper client
236-
if (!isLite) {
236+
if (!isAlgoliasearch) {
237237
await transformBundle({
238238
bundledPath: toAbsolutePath(bundledPath),
239239
clientName: spec,

scripts/ci/githubActions/createMatrix.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,6 @@ async function getClientMatrix(baseBranch: string): Promise<void> {
3131
);
3232

3333
for (const { language, client, output } of Object.values(GENERATORS)) {
34-
// `algoliasearch` is an aggregation of generated clients.
35-
// `lite` is a subfolder of `algoliasearch`
36-
if (client === 'algoliasearch') {
37-
continue;
38-
}
39-
4034
const languageDependencies = Object.entries(DEPENDENCIES).reduce(
4135
(finalDeps, [key, deps]) => {
4236
if (key.startsWith(`${language.toUpperCase()}_`)) {
@@ -51,7 +45,7 @@ async function getClientMatrix(baseBranch: string): Promise<void> {
5145
{} as Record<string, string[]>
5246
);
5347

54-
const bundledSpec = client === 'lite' ? 'search' : client;
48+
const bundledSpec = client === 'algoliasearch' ? 'search' : client;
5549
const specChanges = await getNbGitDiff({
5650
branch: baseBranch,
5751
path: `specs/${bundledSpec}`,
@@ -90,12 +84,8 @@ async function getClientMatrix(baseBranch: string): Promise<void> {
9084
)}`;
9185
const testsToDelete = `${testsOutputBase}/client ${testsOutputBase}/methods`;
9286
let testsToStore = testsToDelete;
93-
let toBuild = matrix[language].toRun;
9487

9588
switch (language) {
96-
case 'javascript':
97-
toBuild = toBuild.filter((client) => client !== 'lite');
98-
break;
9989
case 'java':
10090
testsToStore = `${testsToDelete} ${testsRootFolder}/build.gradle`;
10191
break;
@@ -107,7 +97,6 @@ async function getClientMatrix(baseBranch: string): Promise<void> {
10797
language,
10898
path: matrix[language].path,
10999
toRun: matrix[language].toRun.join(' '),
110-
toBuild: toBuild.join(' '),
111100
cacheKey: await computeCacheKey(`clients-${language}`, [
112101
...matrix[language].cacheToCompute,
113102
'specs/common',
@@ -145,7 +134,7 @@ async function getSpecMatrix(): Promise<void> {
145134
}
146135

147136
// The `lite` spec is created by the `search` spec
148-
const bundledSpecName = client === 'lite' ? 'search' : client;
137+
const bundledSpecName = client === 'algoliasearch' ? 'search' : client;
149138

150139
matrix.toRun.push(client);
151140
matrix.cacheToCompute.push(`specs/${bundledSpecName}`);

scripts/ci/githubActions/types.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ type BaseMatrix = {
2222
* The list of clients to run in the CI.
2323
*/
2424
toRun: string;
25-
/**
26-
* The list of clients to build in the CI, defaults to `toRun`.
27-
*/
28-
toBuild: string;
2925
};
3026

3127
export type ClientMatrix = BaseMatrix & {

0 commit comments

Comments
 (0)