Skip to content

Commit

Permalink
feat(javascript): allow legacy signature for search method (#665)
Browse files Browse the repository at this point in the history
  • Loading branch information
shortcuts committed Jun 14, 2022
1 parent 867d3e2 commit 98b40e8
Show file tree
Hide file tree
Showing 16 changed files with 240 additions and 132 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,10 @@ jobs:
if: ${{ steps.cache.outputs.cache-hit != 'true' && matrix.client.language == 'javascript' }}
run: yarn cli build clients javascript algoliasearch

- name: Run JavaScript 'algoliasearch' client tests
if: ${{ steps.cache.outputs.cache-hit != 'true' && matrix.client.language == 'javascript' }}
run: yarn workspace @experimental-api-clients-automation/algoliasearch test

- name: Clean CTS output before generate
run: rm -rf ${{ matrix.client.testsToDelete }} || true

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import type { EchoResponse } from '@experimental-api-clients-automation/client-common';
import { echoRequester } from '@experimental-api-clients-automation/requester-node-http';

import { algoliasearch, apiClientVersion } from '../builds/node';

const client = algoliasearch('APP_ID', 'API_KEY', {
requester: echoRequester(),
});

describe('api', () => {
it('sets the user agent', async () => {
const req = (await client.post({
path: '/test',
})) as unknown as EchoResponse;

expect(req.algoliaAgent).toMatchInlineSnapshot(
`"Algolia%20for%20JavaScript%20(${apiClientVersion});%20Search%20(${apiClientVersion});%20Node.js%20(${process.versions.node})"`
);
});

it('throws with undefined API key', () => {
try {
algoliasearch('APP_ID', '');
} catch (e) {
expect((e as Error).message).toMatch('`apiKey` is missing.');
}
});

it('throws with undefined app ID', () => {
try {
algoliasearch('', 'API_KEY');
} catch (e) {
expect((e as Error).message).toMatch('`appId` is missing.');
}
});

it('provides the search client at the root of the API', () => {
expect(client.search).not.toBeUndefined();
});

it('provides an init method for the analytics client', () => {
expect(client.initAnalytics).not.toBeUndefined();
});

it('provides an init method for the personalization client', () => {
expect(client.initPersonalization).not.toBeUndefined();
});
});

/**
* We only test the legacy signature, as `algoliasearch` inherits methods from the `client-search`.
* The new signatures are already tested in the CTS.
*/
describe('search with legacy signature', () => {
it('allows searching for query', async () => {
const req = (await client.search([
{
indexName: 'theIndexName',
},
])) as unknown as EchoResponse;

expect(req.path).toEqual('/1/indexes/*/queries');
expect(req.method).toEqual('POST');
expect(req.data).toEqual({ requests: [{ indexName: 'theIndexName' }] });
expect(req.searchParams).toStrictEqual(undefined);
});

it('allows searching for facet', async () => {
const req = (await client.search([
{
indexName: 'theIndexName',
type: 'facet',
facet: 'theFacet',
},
])) as unknown as EchoResponse;

expect(req.path).toEqual('/1/indexes/*/queries');
expect(req.method).toEqual('POST');
expect(req.data).toEqual({
requests: [
{ indexName: 'theIndexName', type: 'facet', facet: 'theFacet' },
],
});
expect(req.searchParams).toStrictEqual(undefined);
});

it('accepts a `params` parameter for `searchParams`', async () => {
const req = (await client.search([
{
indexName: 'theIndexName',
params: {
hitsPerPage: 42,
},
},
])) as unknown as EchoResponse;

expect(req.path).toEqual('/1/indexes/*/queries');
expect(req.method).toEqual('POST');
expect(req.data).toEqual({
requests: [{ indexName: 'theIndexName', hitsPerPage: 42 }],
});
expect(req.searchParams).toStrictEqual(undefined);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { Config } from '@jest/types';

const config: Config.InitialOptions = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['__tests__'],
};

export default config;
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"browser": "dist/algoliasearch.cjs.browser.js",
"types": "index.d.ts",
"scripts": {
"clean": "rm -rf ./dist"
"clean": "rm -rf ./dist",
"test": "jest"
},
"dependencies": {
"@experimental-api-clients-automation/client-analytics": "0.4.0",
Expand All @@ -23,7 +24,9 @@
"@experimental-api-clients-automation/requester-node-http": "0.4.0"
},
"devDependencies": {
"@types/jest": "28.1.1",
"@types/node": "16.11.39",
"jest": "28.1.1",
"typescript": "4.7.3"
},
"engines": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"types": ["node", "jest"],
"outDir": "dist"
},
"include": ["builds/node.ts", "builds/browser.ts"],
"exclude": ["dist", "node_modules"]
"exclude": ["dist", "node_modules", "__tests__"]
}
12 changes: 12 additions & 0 deletions playground/javascript/node/algoliasearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ async function testAlgoliasearch() {
});

console.log(`[OK search]`, res);

const resWithLegacySignature: SearchResponses = await client.search([
{
indexName: searchIndex,
params: {
query: searchQuery,
hitsPerPage: 50,
},
},
]);

console.log(`[OK legacy search]`, resWithLegacySignature);
} catch (e) {
if (e instanceof ApiError) {
return console.log(`[${e.status}] ${e.message}`, e.stackTrace);
Expand Down
24 changes: 12 additions & 12 deletions playground/javascript/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@
"start:predict": "ts-node predict.ts"
},
"dependencies": {
"@experimental-api-clients-automation/algoliasearch": "0.3.0",
"@experimental-api-clients-automation/client-abtesting": "0.3.0",
"@experimental-api-clients-automation/client-analytics": "0.3.0",
"@experimental-api-clients-automation/client-common": "0.3.0",
"@experimental-api-clients-automation/client-insights": "0.3.0",
"@experimental-api-clients-automation/client-personalization": "0.3.0",
"@experimental-api-clients-automation/client-predict": "0.3.0",
"@experimental-api-clients-automation/client-query-suggestions": "0.3.0",
"@experimental-api-clients-automation/client-search": "0.3.0",
"@experimental-api-clients-automation/client-sources": "0.3.0",
"@experimental-api-clients-automation/recommend": "0.3.0",
"@experimental-api-clients-automation/requester-node-http": "0.3.0"
"@experimental-api-clients-automation/algoliasearch": "0.4.0",
"@experimental-api-clients-automation/client-abtesting": "0.4.0",
"@experimental-api-clients-automation/client-analytics": "0.4.0",
"@experimental-api-clients-automation/client-common": "0.4.0",
"@experimental-api-clients-automation/client-insights": "0.4.0",
"@experimental-api-clients-automation/client-personalization": "0.4.0",
"@experimental-api-clients-automation/client-predict": "0.4.0",
"@experimental-api-clients-automation/client-query-suggestions": "0.4.0",
"@experimental-api-clients-automation/client-search": "0.4.0",
"@experimental-api-clients-automation/client-sources": "0.4.0",
"@experimental-api-clients-automation/recommend": "0.4.0",
"@experimental-api-clients-automation/requester-node-http": "0.4.0"
},
"devDependencies": {
"dotenv": "16.0.1",
Expand Down
1 change: 1 addition & 0 deletions specs/search/paths/search/search.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ post:
operationId: search
x-use-read-transporter: true
x-cacheable: true
x-legacy-signature: true
summary: Search multiple indices.
description: Perform a search operation targeting one or many indices.
requestBody:
Expand Down
4 changes: 4 additions & 0 deletions templates/javascript/api-single.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ export function create{{capitalizedApiName}}({
{{#operation}}
{{> api/operation/jsdoc}}
{{nickname}}( {{> api/operation/parameters}} ) : Promise<{{{returnType}}}> {
{{#vendorExtensions.x-legacy-signature}}
{{> api/operation/legacySearchCompatible/implementation}}
{{/vendorExtensions.x-legacy-signature}}

{{#allParams}}
{{#required}}
if ({{#isBoolean}}{{paramName}} === null || {{paramName}} === undefined{{/isBoolean}}{{^isBoolean}}!{{paramName}}{{/isBoolean}}) {
Expand Down
3 changes: 3 additions & 0 deletions templates/javascript/api/imports.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ import type {
{{#x-create-wrapping-object}}
{{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Props,
{{/x-create-wrapping-object}}
{{#x-legacy-signature}}
LegacySearchMethodProps,
{{/x-legacy-signature}}
{{/vendorExtensions}}
{{/operation}}
} from '../model/clientMethodProps';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
if (searchMethodParams && Array.isArray(searchMethodParams)) {
const newSignatureRequest: SearchMethodParams = {
requests: searchMethodParams.map(({ params, ...legacyRequest }) => {
if (legacyRequest.type === 'facet') {
return {
...legacyRequest,
...params,
type: 'facet',
};
}

return {
...legacyRequest,
...params,
facet: undefined,
maxFacetHits: undefined,
facetQuery: undefined,
};
}),
};

// eslint-disable-next-line no-param-reassign
searchMethodParams = newSignatureRequest;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { SearchForFacetsOptions } from './searchForFacetsOptions';
import type { SearchForHitsOptions } from './searchForHitsOptions';
import { SearchParamsObject } from './searchParamsObject';
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* In v4, the search parameters are wrapped in a `params` parameter.
*
* @deprecated The `search` method now accepts flat `searchParams` at the root of the method.
*/
type LegacySearchParams = {
params?: SearchParamsObject;
};

/**
* In v4, the search parameters are wrapped in a `params` parameter.
*
* @deprecated The `search` method now accepts flat `searchParams` at the root of the method.
*/
type LegacySearchForFacets = LegacySearchParams & SearchForFacetsOptions;

/**
* In v4, the search parameters are wrapped in a `params` parameter.
*
* @deprecated The `search` method now accepts flat `searchParams` at the root of the method.
*/
type LegacySearchForHits = LegacySearchParams & SearchForHitsOptions;

type LegacySearchQuery = LegacySearchForFacets | LegacySearchForHits;

/**
* Search method signature compatible with the `algoliasearch` v4 package. When using this signature, extra computation will be required to make it match the new signature.
*
* @deprecated This signature will be removed from the next major version, we recommend using the `SearchMethodParams` type for performances and future proof reasons.
*/
export type LegacySearchMethodProps = LegacySearchQuery[];
2 changes: 1 addition & 1 deletion templates/javascript/api/operation/parameters.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{{/x-create-wrapping-object}}
{{#x-is-single-body-param}}
{{#bodyParams}}
{{paramName}}: {{{dataType}}},
{{paramName}}: {{{dataType}}} {{#x-legacy-signature}} | LegacySearchMethodProps{{/x-legacy-signature}},
{{/bodyParams}}
{{/x-is-single-body-param}}
{{/vendorExtensions}}
Expand Down
13 changes: 11 additions & 2 deletions templates/javascript/clientMethodProps.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@
import { {{classname}} } from '{{filename}}';
{{/imports}}

{{! Imports for the legacy search method signature }}
{{#operations}}{{#operation}}{{#vendorExtensions.x-legacy-signature}}{{> api/operation/legacySearchCompatible/imports}}{{/vendorExtensions.x-legacy-signature}}{{/operation}}{{/operations}}

{{#operations}}
{{#operation}}
{{#vendorExtensions.x-create-wrapping-object}}

{{#vendorExtensions}}
{{#x-create-wrapping-object}}
/**
* Properties for the `{{nickname}}` method.
*/
Expand All @@ -20,7 +25,11 @@ export type {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Props = {
{{paramName}}{{^required}}?{{/required}}: {{{dataType}}};
{{/allParams}}
}
{{/vendorExtensions.x-create-wrapping-object}}
{{/x-create-wrapping-object}}

{{#x-legacy-signature}}{{> api/operation/legacySearchCompatible/model}}{{/x-legacy-signature}}

{{/vendorExtensions}}

{{/operation}}
{{/operations}}
Expand Down
Loading

0 comments on commit 98b40e8

Please sign in to comment.