Skip to content

Commit

Permalink
feat(javascript): support generic for hits (#854)
Browse files Browse the repository at this point in the history
Co-authored-by: Cl茅ment Vannicatte <vannicattec@gmail.com>
  • Loading branch information
millotp and shortcuts committed Jul 25, 2022
1 parent 80af64c commit d18cbc4
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.servers.Server;
import java.util.List;
import java.util.Map;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.SupportingFile;
import org.openapitools.codegen.languages.TypeScriptNodeClientCodegen;
import org.openapitools.codegen.model.ModelMap;
import org.openapitools.codegen.model.ModelsMap;
import org.openapitools.codegen.model.OperationsMap;

public class AlgoliaJavaScriptGenerator extends TypeScriptNodeClientCodegen {
Expand Down Expand Up @@ -132,6 +134,13 @@ private void setDefaultGeneratorOptions() {
}
}

@Override
public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) {
Map<String, ModelsMap> models = super.postProcessAllModels(objs);
GenericPropagator.propagateGenericsToModels(models);
return models;
}

/** Provides an opportunity to inspect and modify operation data before the code is generated. */
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
Expand Down Expand Up @@ -176,6 +185,8 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
ope.vendorExtensions.put("x-create-wrapping-object", true);
}

GenericPropagator.propagateGenericsToOperations(results, allModels);

return results;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,27 @@ private static boolean propagateGenericRecursive(Map<String, CodegenModel> model
return false;
}

private static void setGenericToComposedSchema(Map<String, CodegenModel> models, List<CodegenProperty> composedSchemas) {
if (composedSchemas == null) {
return;
}
for (CodegenProperty prop : composedSchemas) {
if (hasGeneric(propertyToModel(models, prop))) {
setHasChildGeneric(prop);
}
}
}

private static void propagateToComposedSchema(Map<String, CodegenModel> models, CodegenModel model) {
CodegenComposedSchemas composedSchemas = model.getComposedSchemas();
if (composedSchemas == null || !hasGeneric(model)) {
return;
}
setGenericToComposedSchema(models, composedSchemas.getOneOf());
setGenericToComposedSchema(models, composedSchemas.getAllOf());
setGenericToComposedSchema(models, composedSchemas.getAnyOf());
}

private static Map<String, CodegenModel> convertToMap(Map<String, ModelsMap> models) {
Map<String, CodegenModel> modelsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (ModelsMap modelMap : models.values()) {
Expand Down Expand Up @@ -138,6 +159,10 @@ public static void propagateGenericsToModels(Map<String, ModelsMap> modelsMap) {
for (CodegenModel model : models.values()) {
propagateGenericRecursive(models, model);
}

for (CodegenModel model : models.values()) {
propagateToComposedSchema(models, model);
}
}

/** Mark operations with a generic return type with x-is-generic */
Expand Down
4 changes: 4 additions & 0 deletions generators/src/main/java/com/algolia/codegen/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,8 @@ public static void setGenerationBanner(Map<String, Object> additionalProperties)
"This file is generated, manual changes will be lost - read more on" + " https://github.com/algolia/api-clients-automation."
);
}

public static void prettyPrint(Object o) {
Json.prettyPrint(o);
}
}
11 changes: 4 additions & 7 deletions playground/javascript/node/search.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { searchClient } from '@algolia/client-search';
import { ApiError, EchoResponse } from '@algolia/client-common';
import { ApiError } from '@algolia/client-common';
import dotenv from 'dotenv';
import { echoRequester } from '@algolia/requester-node-http';

dotenv.config({ path: '../../.env' });

Expand All @@ -12,17 +11,15 @@ const searchIndex = process.env.SEARCH_INDEX || 'test_index';
const searchQuery = process.env.SEARCH_QUERY || 'test_query';

// Init client with appId and apiKey
const client = searchClient(appId, apiKey, { requester: echoRequester() });
const client = searchClient(appId, apiKey);

client.addAlgoliaAgent('Node playground', '0.0.1');

async function testSearch() {
try {
const res = (await client.post({
path: '/test/minimal',
})) as unknown as EchoResponse;
const res = await client.search<{ name: string }>({ requests: [{ indexName: searchIndex, query: searchQuery }] });

console.log(`[OK]`, res);
console.log(`[OK]`, res.results[0].hits![0].name);
} catch (e: any) {
// Instance of
if (e instanceof ApiError) {
Expand Down
2 changes: 1 addition & 1 deletion templates/javascript/clients/api-single.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function create{{capitalizedApiName}}({
{{/isSearchClient}}
{{#operation}}
{{> client/api/operation/jsdoc}}
{{nickname}}( {{> client/api/operation/parameters}} ) : Promise<{{{returnType}}}> {
{{nickname}}{{#vendorExtensions.x-is-generic}}<T>{{/vendorExtensions.x-is-generic}}( {{> client/api/operation/parameters}} ) : Promise<{{{returnType}}}{{#vendorExtensions.x-is-generic}}<T>{{/vendorExtensions.x-is-generic}}> {
{{#vendorExtensions.x-legacy-signature}}
{{> client/api/operation/legacySearchCompatible/implementation}}
{{/vendorExtensions.x-legacy-signature}}
Expand Down
16 changes: 12 additions & 4 deletions templates/javascript/clients/model.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,27 @@ import { {{classname}} } from '{{filename}}';
/**
* {{{description}}}
*/{{/description}}
export type {{classname}} = {{#oneOf}}{{{.}}} {{^-last}}|{{/-last}} {{/oneOf}}{{#allOf}}{{{.}}} {{^-last}}&{{/-last}} {{/allOf}};
export type {{classname}}{{#vendorExtensions.x-has-child-generic}}<T>{{/vendorExtensions.x-has-child-generic}} = {{#composedSchemas.oneOf}}{{{dataType}}}{{#vendorExtensions.x-has-child-generic}}<T>{{/vendorExtensions.x-has-child-generic}} {{^-last}}|{{/-last}} {{/composedSchemas.oneOf}}
{{#composedSchemas.allOf}}{{{dataType}}}{{#vendorExtensions.x-has-child-generic}}<T>{{/vendorExtensions.x-has-child-generic}} {{^-last}}&{{/-last}} {{/composedSchemas.allOf}};
{{/interfaces.size}}{{^interfaces.size}}
{{#description}}
/**
* {{{description}}}
*/{{/description}}{{^isEnum}}
export type {{classname}} = {{#parent}} {{{.}}} & {{/parent}} {
export type {{classname}}{{#vendorExtensions.x-is-generic}}<T>{{/vendorExtensions.x-is-generic}}{{#vendorExtensions.x-has-child-generic}}<T>{{/vendorExtensions.x-has-child-generic}} = {{^vendorExtensions.x-is-generic}}{{#parent}}{{{.}}} & {{/parent}}{{/vendorExtensions.x-is-generic}}{{#vendorExtensions.x-is-generic}}T & {{/vendorExtensions.x-is-generic}} {
{{#vendorExtensions}}
{{#vars}}{{#description}}
/**
* {{{description}}}
*/{{/description}}
{{name}}{{^required}}?{{/required}}: {{#isEnum}}{{classname}}{{{nameInCamelCase}}}{{#isArray}}[]{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{#isNullable}} | null{{/isNullable}}{{/isEnum}};{{/vars}}
} {{#vendorExtensions.x-is-SearchForHitsOptions}} & { facet?: never; maxFacetHits?: never; facetQuery?: never }; {{/vendorExtensions.x-is-SearchForHitsOptions}}
{{name}}{{^required}}?{{/required}}: {{#isEnum}}{{classname}}{{{nameInCamelCase}}}{{#isArray}}[]{{/isArray}}{{/isEnum}}
{{^isEnum}}{{#x-propagated-generic}}{{{complexType}}}<T>{{#isArray}}[]{{/isArray}}{{/x-propagated-generic}}
{{^x-propagated-generic}}
{{#x-has-child-generic}}{{{complexType}}}<T>{{#isArray}}[]{{/isArray}}{{/x-has-child-generic}}
{{^x-has-child-generic}}{{{dataType}}}{{/x-has-child-generic}}
{{/x-propagated-generic}}{{#isNullable}} | null{{/isNullable}}{{/isEnum}};{{/vars}}
} {{#x-is-SearchForHitsOptions}} & { facet?: never; maxFacetHits?: never; facetQuery?: never }; {{/x-is-SearchForHitsOptions}}
{{/vendorExtensions}}
{{/isEnum}}
{{#hasEnums}}{{#vars}}{{#isEnum}}export type {{classname}}{{nameInCamelCase}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}|{{/-last}}{{/enumVars}}{{/allowableValues}}{{/isEnum}}{{/vars}}{{/hasEnums}}
{{#isEnum}}export type {{classname}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}|{{/-last}}{{/enumVars}}{{/allowableValues}}{{/isEnum}}
Expand Down

0 comments on commit d18cbc4

Please sign in to comment.