diff --git a/generators/src/main/java/com/algolia/codegen/cts/tests/ParametersWithDataType.java b/generators/src/main/java/com/algolia/codegen/cts/tests/ParametersWithDataType.java index 0cd8c7ddaa4..9e9b84587cc 100644 --- a/generators/src/main/java/com/algolia/codegen/cts/tests/ParametersWithDataType.java +++ b/generators/src/main/java/com/algolia/codegen/cts/tests/ParametersWithDataType.java @@ -654,6 +654,10 @@ private void transferPrimitiveData(IJsonSchemaValidationProperties spec, Map allModels) { Map models = convertToMap(language, client, allModels); for (CodegenOperation ope : operations.getOperations().getOperation()) { + for (CodegenParameter param : ope.requiredParams) { + if (param.vendorExtensions.containsKey("x-is-generic")) { + setHasGenericParameter(ope); + break; + } + } + if (ope.returnType == null) { continue; } + CodegenModel returnType = models.get(ope.returnType); if (returnType != null && hasGeneric(returnType)) { ope.vendorExtensions.put("x-is-generic", true); diff --git a/playground/javascript/browser/eslint.config.js b/playground/javascript/browser/eslint.config.js index 092408a9f09..33c02ac29ac 100644 --- a/playground/javascript/browser/eslint.config.js +++ b/playground/javascript/browser/eslint.config.js @@ -1,8 +1,8 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' +import js from '@eslint/js'; +import reactHooks from 'eslint-plugin-react-hooks'; +import reactRefresh from 'eslint-plugin-react-refresh'; +import globals from 'globals'; +import tseslint from 'typescript-eslint'; export default tseslint.config( { ignores: ['dist'] }, @@ -19,10 +19,7 @@ export default tseslint.config( }, rules: { ...reactHooks.configs.recommended.rules, - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], + 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], }, }, -) +); diff --git a/playground/javascript/browser/src/App.css b/playground/javascript/browser/src/App.css index 29988233a4b..40dd53e678b 100644 --- a/playground/javascript/browser/src/App.css +++ b/playground/javascript/browser/src/App.css @@ -5,8 +5,9 @@ h1 { } body { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, - Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; + font-family: + -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, + sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; } em { diff --git a/playground/javascript/browser/src/App.tsx b/playground/javascript/browser/src/App.tsx index 1971fa6b919..0d3555223bf 100644 --- a/playground/javascript/browser/src/App.tsx +++ b/playground/javascript/browser/src/App.tsx @@ -1,5 +1,5 @@ import { liteClient as algoliasearch } from 'algoliasearch/lite'; -import { Hit } from 'instantsearch.js'; +import type { Hit } from 'instantsearch.js'; import { Carousel, Configure, diff --git a/playground/javascript/browser/src/Panel.tsx b/playground/javascript/browser/src/Panel.tsx index bbff1e71fa6..bff33b4f699 100644 --- a/playground/javascript/browser/src/Panel.tsx +++ b/playground/javascript/browser/src/Panel.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import type React from 'react'; type PanelProps = React.PropsWithChildren<{ header: string; diff --git a/playground/javascript/browser/src/main.tsx b/playground/javascript/browser/src/main.tsx index b356a577c7e..8214535010a 100644 --- a/playground/javascript/browser/src/main.tsx +++ b/playground/javascript/browser/src/main.tsx @@ -1,10 +1,10 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import './index.css' -import {App} from './App.tsx' +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import { App } from './App.tsx'; +import './index.css'; createRoot(document.getElementById('root')!).render( , -) +); diff --git a/playground/javascript/browser/vite.config.ts b/playground/javascript/browser/vite.config.ts index 2328e170b0c..26f4e71e6e1 100644 --- a/playground/javascript/browser/vite.config.ts +++ b/playground/javascript/browser/vite.config.ts @@ -1,7 +1,7 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react-swc' +import react from '@vitejs/plugin-react-swc'; +import { defineConfig } from 'vite'; // https://vite.dev/config/ export default defineConfig({ plugins: [react()], -}) +}); diff --git a/playground/javascript/node/algoliasearch.ts b/playground/javascript/node/algoliasearch.ts index 9b69b523119..f61193fcb9d 100644 --- a/playground/javascript/node/algoliasearch.ts +++ b/playground/javascript/node/algoliasearch.ts @@ -16,7 +16,7 @@ async function testAlgoliasearch() { // Init client with appId and apiKey const client = algoliasearch(appId, apiKey); const clientLite = liteClient(appId, apiKey); - + client.addAlgoliaAgent('algoliasearch node playground', '0.0.1'); try { @@ -134,12 +134,21 @@ async function testAlgoliasearch() { async function testAlgoliasearchBridgeIngestion() { // Init client with appId and apiKey - const client = algoliasearch(appId, adminApiKey, { transformation: { region: 'eu'}}); - - await client.saveObjectsWithTransformation({indexName: "foo", objects: [{objectID: "foo", data: {baz: "baz", win: 42}}], waitForTasks: true }) - - await client.partialUpdateObjectsWithTransformation({indexName: "foo", objects: [{objectID: "foo", data: {baz: "baz", win: 42}}], waitForTasks: true, createIfNotExists: false }) + const client = algoliasearch(appId, adminApiKey, { transformation: { region: 'eu' } }); + + await client.saveObjectsWithTransformation({ + indexName: 'foo', + objects: [{ objectID: 'foo', data: { baz: 'baz', win: 42 } }], + waitForTasks: true, + }); + + await client.partialUpdateObjectsWithTransformation({ + indexName: 'foo', + objects: [{ objectID: 'foo', data: { baz: 'baz', win: 42 } }], + waitForTasks: true, + createIfNotExists: false, + }); } // testAlgoliasearch(); -testAlgoliasearchBridgeIngestion() +testAlgoliasearchBridgeIngestion(); diff --git a/playground/javascript/node/analytics.ts b/playground/javascript/node/analytics.ts index 5a18da03aa2..af2c95d7607 100644 --- a/playground/javascript/node/analytics.ts +++ b/playground/javascript/node/analytics.ts @@ -11,10 +11,13 @@ const client = analyticsClient(appId, apiKey, 'de'); async function testAnalytics() { try { - const res = await client.getTopFilterForAttribute({ - attribute: 'myAttribute1,myAttribute2', - index: analyticsIndex, - }, {timeouts: {read:20000, write: 30000}}); + const res = await client.getTopFilterForAttribute( + { + attribute: 'myAttribute1,myAttribute2', + index: analyticsIndex, + }, + { timeouts: { read: 20000, write: 30000 } }, + ); console.log(`[OK]`, res); } catch (e) { diff --git a/playground/javascript/node/composition.ts b/playground/javascript/node/composition.ts index 71320fff8b4..30ca7851397 100644 --- a/playground/javascript/node/composition.ts +++ b/playground/javascript/node/composition.ts @@ -9,7 +9,7 @@ const client = compositionClient(appId, apiKey); async function testComposition() { try { - console.log(appId, apiKey) + console.log(appId, apiKey); // create a new composition // const res = await client.multipleBatch({ // requests: [ @@ -36,8 +36,7 @@ async function testComposition() { // }); // console.log(`[OK]`, res); - console.log(await client.search({ compositionID: 'id1', requestBody: {} })) - + console.log(await client.search({ compositionID: 'id1', requestBody: {} })); } catch (e) { if (e instanceof ApiError) { return console.log(`[${e.status}] ${e.message}`, e.stackTrace, e); diff --git a/playground/javascript/node/compositionFull.ts b/playground/javascript/node/compositionFull.ts index 8aba1975b13..decd199da7c 100644 --- a/playground/javascript/node/compositionFull.ts +++ b/playground/javascript/node/compositionFull.ts @@ -9,7 +9,7 @@ const client = compositionClient(appId, apiKey); async function testComposition() { try { - console.log(appId, apiKey) + console.log(appId, apiKey); // create a new composition // const res = await client.multipleBatch({ // requests: [ @@ -36,8 +36,7 @@ async function testComposition() { // }); // console.log(`[OK]`, res); - console.log(await client.listCompositions()) - + console.log(await client.listCompositions()); } catch (e) { if (e instanceof ApiError) { return console.log(`[${e.status}] ${e.message}`, e.stackTrace, e); diff --git a/playground/javascript/node/search.ts b/playground/javascript/node/search.ts index fd0bc7d1b37..c150553cd3c 100644 --- a/playground/javascript/node/search.ts +++ b/playground/javascript/node/search.ts @@ -1,5 +1,6 @@ import { ApiError } from '@algolia/client-common'; -import { apiClientVersion, searchClient, SearchQuery } from '@algolia/client-search'; +import type { SearchQuery } from '@algolia/client-search'; +import { apiClientVersion, searchClient } from '@algolia/client-search'; const appId = process.env.ALGOLIA_APPLICATION_ID || '**** APP_ID *****'; const apiKey = process.env.ALGOLIA_ADMIN_KEY || '**** SEARCH_API_KEY *****'; @@ -15,15 +16,31 @@ client.addAlgoliaAgent('Node playground', '0.0.1'); const requests: SearchQuery[] = [{ indexName: searchIndex, query: searchQuery }]; console.log('version', apiClientVersion, 'requests', requests); +interface Animal { + name: string; + age: number; + objectID: string; +} + async function testSearch() { try { const req = await client.setSettings({ indexName: 'theIndexName', indexSettings: { distinct: true }, - }) - + }); console.log(`[OK]`, req); + + const a: Animal = { + name: 'Dog', + age: 5, + objectID: 'dog-123', + }; + + const ssss = await client.saveObject({ + indexName: 'theIndexName', + body: a, + }); } catch (e: any) { // Instance of if (e instanceof ApiError) { diff --git a/specs/search/paths/objects/object.yml b/specs/search/paths/objects/object.yml index 193a622bc4e..602e778faea 100644 --- a/specs/search/paths/objects/object.yml +++ b/specs/search/paths/objects/object.yml @@ -64,10 +64,15 @@ put: requestBody: required: true description: The record. A schemaless object with attributes that are useful in the context of search and discovery. + x-is-generic: true content: application/json: schema: type: object + example: + objectID: blackTShirt + name: Black T-shirt + color: '#000000' responses: '200': $ref: '../../../common/responses/UpdatedAtWithObjectId.yml' diff --git a/specs/search/paths/objects/objects.yml b/specs/search/paths/objects/objects.yml index 23dd01a01e5..9d7eda2385f 100644 --- a/specs/search/paths/objects/objects.yml +++ b/specs/search/paths/objects/objects.yml @@ -23,10 +23,15 @@ post: requestBody: required: true description: The record. A schemaless object with attributes that are useful in the context of search and discovery. + x-is-generic: true content: application/json: schema: type: object + example: + objectID: blackTShirt + name: Black T-shirt + color: '#000000' responses: '201': description: Created diff --git a/templates/javascript/clients/api-single.mustache b/templates/javascript/clients/api-single.mustache index ae8a3babe75..5062c57cd56 100644 --- a/templates/javascript/clients/api-single.mustache +++ b/templates/javascript/clients/api-single.mustache @@ -101,7 +101,7 @@ export function create{{#lambda.titlecase}}{{clientName}}{{/lambda.titlecase}}({ {{/isCompositionFullClient}} {{#operation}} {{> client/api/operation/jsdoc}} - {{nickname}}{{#vendorExtensions.x-is-generic}}{{/vendorExtensions.x-is-generic}}( {{> client/api/operation/parameters}} ) : Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}{{#vendorExtensions.x-is-generic}}{{/vendorExtensions.x-is-generic}}> { + {{nickname}}{{#vendorExtensions.x-is-generic}}{{/vendorExtensions.x-is-generic}}{{#vendorExtensions.x-has-generic-parameter}}{{/vendorExtensions.x-has-generic-parameter}}( {{> client/api/operation/parameters}} ) : Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}{{#vendorExtensions.x-is-generic}}{{/vendorExtensions.x-is-generic}}> { {{#vendorExtensions.x-legacy-signature}} {{> client/api/operation/legacySearchCompatible/implementation}} {{/vendorExtensions.x-legacy-signature}} diff --git a/templates/javascript/clients/client/api/operation/parameters.mustache b/templates/javascript/clients/client/api/operation/parameters.mustache index 68a1190a6c8..523892e5cd5 100644 --- a/templates/javascript/clients/client/api/operation/parameters.mustache +++ b/templates/javascript/clients/client/api/operation/parameters.mustache @@ -1,6 +1,6 @@ {{#vendorExtensions}} {{#x-create-wrapping-object}} - { {{#allParams}}{{paramName}}, {{/allParams}} }: {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Props{{^hasRequiredParams}} = {}{{/hasRequiredParams}}, + { {{#allParams}}{{paramName}}, {{/allParams}} }: {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Props{{#x-has-generic-parameter}}{{/x-has-generic-parameter}}{{^hasRequiredParams}} = {}{{/hasRequiredParams}}, {{/x-create-wrapping-object}} {{#x-is-single-body-param}} {{#bodyParams}} diff --git a/templates/javascript/clients/client/model/clientMethodProps.mustache b/templates/javascript/clients/client/model/clientMethodProps.mustache index 0f836419967..904c463d167 100644 --- a/templates/javascript/clients/client/model/clientMethodProps.mustache +++ b/templates/javascript/clients/client/model/clientMethodProps.mustache @@ -26,14 +26,14 @@ import type { CreateIterablePromise } from '@algolia/client-common'; /** * Properties for the `{{nickname}}` method. */ -export type {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Props = { +export type {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Props{{#x-has-generic-parameter}}{{/x-has-generic-parameter}} = { {{#allParams}} {{#description}} /** * {{{description}}} */ {{/description}} - {{paramName}}{{^required}}?{{/required}}: {{{dataType}}}; + {{paramName}}{{^required}}?{{/required}}: {{#vendorExtensions.x-is-generic}}T{{/vendorExtensions.x-is-generic}}{{^vendorExtensions.x-is-generic}}{{{dataType}}}{{/vendorExtensions.x-is-generic}}; {{/allParams}} } {{/x-create-wrapping-object}}