From c06f890d85625ff4b2997d0f7a3600dc8b38372d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Vannicatte?= <20689156+shortcuts@users.noreply.github.com> Date: Wed, 23 Feb 2022 17:15:58 +0100 Subject: [PATCH] feat(javascript): provide `algoliasearch` package (#158) --- .github/actions/cache/action.yml | 7 ++ .github/workflows/check.yml | 1 + .../bundlesize.config.json | 6 +- .../packages/algoliasearch/builds/browser.ts | 84 ++++++++++++++++++ .../packages/algoliasearch/builds/node.ts | 83 ++++++++++++++++++ .../packages/algoliasearch/index.d.ts | 2 + .../packages/algoliasearch/index.js | 2 + .../packages/algoliasearch/package.json | 35 ++++++++ .../packages/algoliasearch/tsconfig.json | 8 ++ .../client-common/src/types/CreateClient.ts | 3 +- .../rollup.config.js | 28 ++++-- playground/javascript/node/algoliasearch.ts | 87 +++++++++++++++++++ playground/javascript/node/package.json | 5 +- yarn.lock | 16 ++++ 14 files changed, 357 insertions(+), 10 deletions(-) create mode 100644 clients/algoliasearch-client-javascript/packages/algoliasearch/builds/browser.ts create mode 100644 clients/algoliasearch-client-javascript/packages/algoliasearch/builds/node.ts create mode 100644 clients/algoliasearch-client-javascript/packages/algoliasearch/index.d.ts create mode 100644 clients/algoliasearch-client-javascript/packages/algoliasearch/index.js create mode 100644 clients/algoliasearch-client-javascript/packages/algoliasearch/package.json create mode 100644 clients/algoliasearch-client-javascript/packages/algoliasearch/tsconfig.json create mode 100644 playground/javascript/node/algoliasearch.ts diff --git a/.github/actions/cache/action.yml b/.github/actions/cache/action.yml index cbd1c8eab5..66a1345811 100644 --- a/.github/actions/cache/action.yml +++ b/.github/actions/cache/action.yml @@ -36,6 +36,13 @@ runs: path: /home/runner/work/api-clients-automation/api-clients-automation/clients/algoliasearch-client-javascript/packages/requester-browser-xhr/dist key: ${{ runner.os }}-${{ env.CACHE_VERSION }}-js-requester-browser-xhr-${{ hashFiles('clients/algoliasearch-client-javascript/packages/requester-browser-xhr/**') }} + - name: Restore built JavaScript algoliasearch client + if: ${{ inputs.job == 'cts' }} + uses: actions/cache@v2 + with: + path: /home/runner/work/api-clients-automation/api-clients-automation/clients/algoliasearch-client-javascript/packages/algoliasearch/dist + key: ${{ runner.os }}-${{ env.CACHE_VERSION }}-js-algoliasearch-${{ hashFiles('clients/algoliasearch-client-javascript/packages/algoliasearch/**') }} + - name: Restore built JavaScript search client if: ${{ inputs.job == 'cts' }} uses: actions/cache@v2 diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 8bfdfc0479..d852f93364 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -76,6 +76,7 @@ jobs: - client-common - requester-browser-xhr - requester-node-http + - algoliasearch steps: - uses: actions/checkout@v2 diff --git a/clients/algoliasearch-client-javascript/bundlesize.config.json b/clients/algoliasearch-client-javascript/bundlesize.config.json index 1d3a665cc2..27e80d2f40 100644 --- a/clients/algoliasearch-client-javascript/bundlesize.config.json +++ b/clients/algoliasearch-client-javascript/bundlesize.config.json @@ -1,5 +1,9 @@ { "files": [ + { + "path": "packages/algoliasearch/dist/algoliasearch.umd.browser.js", + "maxSize": "6.25KB" + }, { "path": "packages/client-abtesting/dist/client-abtesting.umd.browser.js", "maxSize": "3.25KB" @@ -14,7 +18,7 @@ }, { "path": "packages/client-personalization/dist/client-personalization.umd.browser.js", - "maxSize": "3.00KB" + "maxSize": "3.25KB" }, { "path": "packages/client-query-suggestions/dist/client-query-suggestions.umd.browser.js", diff --git a/clients/algoliasearch-client-javascript/packages/algoliasearch/builds/browser.ts b/clients/algoliasearch-client-javascript/packages/algoliasearch/builds/browser.ts new file mode 100644 index 0000000000..4da5a3355e --- /dev/null +++ b/clients/algoliasearch-client-javascript/packages/algoliasearch/builds/browser.ts @@ -0,0 +1,84 @@ +import type { + AnalyticsApi, + Region as AnalyticsRegion, +} from '@algolia/client-analytics/src/analyticsApi'; +import { createAnalyticsApi } from '@algolia/client-analytics/src/analyticsApi'; +import type { + CreateClientOptions, + Host, + Requester, +} from '@algolia/client-common'; +import type { + PersonalizationApi, + Region as PersonalizationRegion, +} from '@algolia/client-personalization/src/personalizationApi'; +import { createPersonalizationApi } from '@algolia/client-personalization/src/personalizationApi'; +import { createSearchApi } from '@algolia/client-search/src/searchApi'; +import { createXhrRequester } from '@algolia/requester-browser-xhr'; + +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export function algoliasearch( + appId: string, + apiKey: string, + options?: { requester?: Requester; hosts?: Host[] } +) { + if (!appId) { + throw new Error('`appId` is missing.'); + } + + if (!apiKey) { + throw new Error('`apiKey` is missing.'); + } + + const commonOptions: Omit = { + timeouts: { + connect: 1, + read: 2, + write: 30, + }, + requester: options?.requester ?? createXhrRequester(), + userAgents: [{ segment: 'Browser' }], + authMode: 'WithinQueryParameters', + ...options, + }; + + function initAnalytics( + analyticsAppId: string, + analyticsApiKey: string, + region?: AnalyticsRegion, + analyticsOptions?: { requester?: Requester; hosts?: Host[] } + ): AnalyticsApi { + return createAnalyticsApi({ + appId: analyticsAppId, + apiKey: analyticsApiKey, + region, + ...analyticsOptions, + ...commonOptions, + }); + } + + function initPersonalization( + personalizationAppId: string, + personalizationApiKey: string, + region: PersonalizationRegion, + personalizationOptions?: { requester?: Requester; hosts?: Host[] } + ): PersonalizationApi { + if (!region) { + throw new Error('`region` is missing.'); + } + + return createPersonalizationApi({ + appId: personalizationAppId, + apiKey: personalizationApiKey, + region, + ...personalizationOptions, + ...commonOptions, + }); + } + + return { + ...createSearchApi({ appId, apiKey, ...commonOptions }), + initAnalytics, + initPersonalization, + }; +} diff --git a/clients/algoliasearch-client-javascript/packages/algoliasearch/builds/node.ts b/clients/algoliasearch-client-javascript/packages/algoliasearch/builds/node.ts new file mode 100644 index 0000000000..e17d171f54 --- /dev/null +++ b/clients/algoliasearch-client-javascript/packages/algoliasearch/builds/node.ts @@ -0,0 +1,83 @@ +import type { + AnalyticsApi, + Region as AnalyticsRegion, +} from '@algolia/client-analytics/src/analyticsApi'; +import { createAnalyticsApi } from '@algolia/client-analytics/src/analyticsApi'; +import type { + CreateClientOptions, + Host, + Requester, +} from '@algolia/client-common'; +import type { + PersonalizationApi, + Region as PersonalizationRegion, +} from '@algolia/client-personalization/src/personalizationApi'; +import { createPersonalizationApi } from '@algolia/client-personalization/src/personalizationApi'; +import { createSearchApi } from '@algolia/client-search/src/searchApi'; +import { createHttpRequester } from '@algolia/requester-node-http'; + +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export function algoliasearch( + appId: string, + apiKey: string, + options?: { requester?: Requester; hosts?: Host[] } +) { + if (!appId) { + throw new Error('`appId` is missing.'); + } + + if (!apiKey) { + throw new Error('`apiKey` is missing.'); + } + + const commonOptions: Omit = { + timeouts: { + connect: 2, + read: 5, + write: 30, + }, + requester: options?.requester ?? createHttpRequester(), + userAgents: [{ segment: 'Node.js', version: process.versions.node }], + ...options, + }; + + function initAnalytics( + analyticsAppId: string, + analyticsApiKey: string, + region?: AnalyticsRegion, + analyticsOptions?: { requester?: Requester; hosts?: Host[] } + ): AnalyticsApi { + return createAnalyticsApi({ + appId: analyticsAppId, + apiKey: analyticsApiKey, + region, + ...analyticsOptions, + ...commonOptions, + }); + } + + function initPersonalization( + personalizationAppId: string, + personalizationApiKey: string, + region: PersonalizationRegion, + personalizationOptions?: { requester?: Requester; hosts?: Host[] } + ): PersonalizationApi { + if (!region) { + throw new Error('`region` is missing.'); + } + + return createPersonalizationApi({ + appId: personalizationAppId, + apiKey: personalizationApiKey, + region, + ...personalizationOptions, + ...commonOptions, + }); + } + + return { + ...createSearchApi({ appId, apiKey, ...commonOptions }), + initAnalytics, + initPersonalization, + }; +} diff --git a/clients/algoliasearch-client-javascript/packages/algoliasearch/index.d.ts b/clients/algoliasearch-client-javascript/packages/algoliasearch/index.d.ts new file mode 100644 index 0000000000..7b4d638346 --- /dev/null +++ b/clients/algoliasearch-client-javascript/packages/algoliasearch/index.d.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/no-unresolved +export * from './dist/algoliasearch/builds/node'; diff --git a/clients/algoliasearch-client-javascript/packages/algoliasearch/index.js b/clients/algoliasearch-client-javascript/packages/algoliasearch/index.js new file mode 100644 index 0000000000..1bfaf73d0e --- /dev/null +++ b/clients/algoliasearch-client-javascript/packages/algoliasearch/index.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/no-commonjs,import/extensions +module.exports = require('./dist/algoliasearch.cjs.node.js'); diff --git a/clients/algoliasearch-client-javascript/packages/algoliasearch/package.json b/clients/algoliasearch-client-javascript/packages/algoliasearch/package.json new file mode 100644 index 0000000000..3808b693f0 --- /dev/null +++ b/clients/algoliasearch-client-javascript/packages/algoliasearch/package.json @@ -0,0 +1,35 @@ +{ + "name": "algoliasearch", + "version": "5.0.0", + "description": "A fully-featured and blazing-fast JavaScript API client to interact with Algolia API.", + "repository": "algolia/algoliasearch-client-javascript", + "author": "Algolia", + "license": "MIT", + "main": "index.js", + "module": "dist/algoliasearch.esm.node.js", + "types": "index.d.ts", + "jsdelivr": "dist/algoliasearch.umd.browser.js", + "unpkg": "dist/algoliasearch.umd.browser.js", + "browser": { + "./index.js": "./dist/algoliasearch.cjs.browser.js", + "./lite.js": "./dist/algoliasearch-lite.cjs.browser.js" + }, + "scripts": { + "clean": "rm -rf ./dist" + }, + "engines": { + "node": "^14.0.0" + }, + "dependencies": { + "@algolia/client-analytics": "5.0.0", + "@algolia/client-common": "5.0.0", + "@algolia/client-personalization": "5.0.0", + "@algolia/client-search": "5.0.0", + "@algolia/requester-browser-xhr": "5.0.0", + "@algolia/requester-node-http": "5.0.0" + }, + "devDependencies": { + "@types/node": "16.11.11", + "typescript": "4.5.4" + } +} diff --git a/clients/algoliasearch-client-javascript/packages/algoliasearch/tsconfig.json b/clients/algoliasearch-client-javascript/packages/algoliasearch/tsconfig.json new file mode 100644 index 0000000000..e5af720cb3 --- /dev/null +++ b/clients/algoliasearch-client-javascript/packages/algoliasearch/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": ["builds/node.ts", "builds/browser.ts"], + "exclude": ["dist", "node_modules"] +} diff --git a/clients/algoliasearch-client-javascript/packages/client-common/src/types/CreateClient.ts b/clients/algoliasearch-client-javascript/packages/client-common/src/types/CreateClient.ts index 21993b9a61..1ee437db11 100644 --- a/clients/algoliasearch-client-javascript/packages/client-common/src/types/CreateClient.ts +++ b/clients/algoliasearch-client-javascript/packages/client-common/src/types/CreateClient.ts @@ -1,4 +1,5 @@ import type { Host } from './Host'; +import type { Requester } from './Requester'; import type { Timeouts, UserAgentOptions } from './Transporter'; export type AuthMode = 'WithinHeaders' | 'WithinQueryParameters'; @@ -6,7 +7,7 @@ export type AuthMode = 'WithinHeaders' | 'WithinQueryParameters'; export type CreateClientOptions = { appId: string; apiKey: string; - requester: any; + requester: Requester; timeouts: Timeouts; userAgents: UserAgentOptions[]; hosts?: Host[]; diff --git a/clients/algoliasearch-client-javascript/rollup.config.js b/clients/algoliasearch-client-javascript/rollup.config.js index 28be4d6329..c76ceccb03 100644 --- a/clients/algoliasearch-client-javascript/rollup.config.js +++ b/clients/algoliasearch-client-javascript/rollup.config.js @@ -45,7 +45,9 @@ function createBundlers({ output, clientPath }) { } function getAvailableClients() { - const availableClients = []; + // We default `algoliasearch` as it's not a generated client, but an aggregation of + // multiple clients. + const availableClients = ['algoliasearch']; const generators = Object.entries( generatorConfig['generator-cli'].generators ); @@ -112,15 +114,19 @@ function initPackagesConfig() { } return availableClients.flatMap((packageName) => { + const isAlgoliasearchClient = packageName.startsWith('algoliasearch'); const commonConfig = { package: packageName, - name: `@algolia/${packageName}`, + name: isAlgoliasearchClient ? packageName : `@algolia/${packageName}`, output: packageName, - dependencies: [ - '@algolia/client-common', - '@algolia/requester-browser-xhr', - '@algolia/requester-node-http', - ], + dependencies: isAlgoliasearchClient + ? [ + '@algolia/client-analytics', + '@algolia/client-common', + '@algolia/client-personalization', + '@algolia/client-search', + ] + : ['@algolia/client-common'], external: [], }; const browserFormats = ['umd-browser', 'esm-browser', 'cjs-browser']; @@ -132,6 +138,10 @@ function initPackagesConfig() { input: 'builds/browser.ts', formats: browserFormats, external: ['dom'], + dependencies: [ + ...commonConfig.dependencies, + '@algolia/requester-browser-xhr', + ], globals: { [packageName]: packageName, }, @@ -139,6 +149,10 @@ function initPackagesConfig() { { ...commonConfig, input: 'builds/node.ts', + dependencies: [ + ...commonConfig.dependencies, + '@algolia/requester-node-http', + ], formats: nodeFormats, }, ]; diff --git a/playground/javascript/node/algoliasearch.ts b/playground/javascript/node/algoliasearch.ts new file mode 100644 index 0000000000..09c05d2bc9 --- /dev/null +++ b/playground/javascript/node/algoliasearch.ts @@ -0,0 +1,87 @@ +import { algoliasearch } from 'algoliasearch'; +import { ApiError } from '@algolia/client-common'; +import dotenv from 'dotenv'; + +dotenv.config({ path: '../../.env' }); + +const appId = process.env.ALGOLIA_APPLICATION_ID || '**** APP_ID *****'; +const apiKey = process.env.ALGOLIA_SEARCH_KEY || '**** SEARCH_API_KEY *****'; + +const searchIndex = process.env.SEARCH_INDEX || 'test_index'; +const searchQuery = process.env.SEARCH_QUERY || 'test_query'; + +const analyticsAppId = + process.env.ALGOLIA_APPLICATION_ID || '**** APP_ID *****'; +const analyticsApiKey = + process.env.ALGOLIA_ANALYTICS_KEY || '**** ANALYTICS_API_KEY *****'; + +const analyticsIndex = process.env.ANALYTICS_INDEX || 'test_index'; + +const personalizationAppId = + process.env.ALGOLIA_APPLICATION_ID || '**** APP_ID *****'; +const personalizationApiKey = + process.env.ALGOLIA_RECOMMENDATION_KEY || '**** RECOMMENDATION_API_KEY *****'; + +// Init client with appId and apiKey +const client = algoliasearch(appId, apiKey); + +client.addUserAgent('algoliasearch node playground', '0.0.1'); + +async function testAlgoliasearch() { + try { + const res = await client.search({ + indexName: searchIndex, + searchParams: { query: searchQuery }, + }); + + console.log(`[OK search]`, res); + } catch (e) { + if (e instanceof ApiError) { + return console.log(`[${e.status}] ${e.message}`, e.stackTrace); + } + + console.log('[ERROR search]', e); + } + + try { + const analyticsClient = client.initAnalytics( + analyticsAppId, + analyticsApiKey + ); + + const res = await analyticsClient.getTopFilterForAttribute({ + attribute: 'myAttribute1,myAttribute2', + index: analyticsIndex, + }); + + console.log(`[OK analytics ]`, res); + } catch (e) { + if (e instanceof ApiError) { + return console.log(`[${e.status}] ${e.message}`, e.stackTrace); + } + + console.log('[ERROR analytics]', e); + } + + try { + const personalizationCilent = client.initPersonalization( + personalizationAppId, + personalizationApiKey, + 'eu' + ); + + const res = await personalizationCilent.getUserTokenProfile({ + userToken: 'wouhou', + }); + + console.log(`[OK personalization]`, res); + } catch (e) { + if (e instanceof ApiError) { + return console.log(`[${e.status}] ${e.message}`, e.stackTrace); + } + + console.log('[ERROR personalization]', e); + } +} + +testAlgoliasearch(); diff --git a/playground/javascript/node/package.json b/playground/javascript/node/package.json index 798df687f5..30d5b6e185 100644 --- a/playground/javascript/node/package.json +++ b/playground/javascript/node/package.json @@ -4,6 +4,7 @@ "private": true, "scripts": { "build": "tsc", + "start:algoliasearch": "yarn build && yarn test:algoliasearch", "start:abtesting": "yarn build && yarn test:abtesting", "start:analytics": "yarn build && yarn test:analytics", "start:personalization": "yarn build && yarn test:personalization", @@ -12,6 +13,7 @@ "start:search": "yarn build && yarn test:search", "start:sources": "yarn build && yarn test:sources", "start:predict": "yarn build && yarn test:predict", + "test:algoliasearch": "node dist/algoliasearch.js", "test:abtesting": "node dist/analytics.js", "test:analytics": "node dist/analytics.js", "test:personalization": "node dist/personalization.js", @@ -31,7 +33,8 @@ "@algolia/client-search": "5.0.0", "@algolia/client-sources": "0.0.1", "@algolia/recommend": "5.0.0", - "@algolia/requester-node-http": "5.0.0" + "@algolia/requester-node-http": "5.0.0", + "algoliasearch": "5.0.0" }, "devDependencies": { "dotenv": "10.0.0", diff --git a/yarn.lock b/yarn.lock index ed993e3f75..4dfa561300 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3514,6 +3514,21 @@ __metadata: languageName: unknown linkType: soft +"algoliasearch@5.0.0, algoliasearch@workspace:clients/algoliasearch-client-javascript/packages/algoliasearch": + version: 0.0.0-use.local + resolution: "algoliasearch@workspace:clients/algoliasearch-client-javascript/packages/algoliasearch" + dependencies: + "@algolia/client-analytics": 5.0.0 + "@algolia/client-common": 5.0.0 + "@algolia/client-personalization": 5.0.0 + "@algolia/client-search": 5.0.0 + "@algolia/requester-browser-xhr": 5.0.0 + "@algolia/requester-node-http": 5.0.0 + "@types/node": 16.11.11 + typescript: 4.5.4 + languageName: unknown + linkType: soft + "ansi-align@npm:^3.0.0": version: 3.0.1 resolution: "ansi-align@npm:3.0.1" @@ -6970,6 +6985,7 @@ __metadata: "@algolia/client-sources": 0.0.1 "@algolia/recommend": 5.0.0 "@algolia/requester-node-http": 5.0.0 + algoliasearch: 5.0.0 dotenv: 10.0.0 typescript: 4.5.4 languageName: unknown