diff --git a/clients/algoliasearch-client-javascript/base.tsup.config.ts b/clients/algoliasearch-client-javascript/base.tsup.config.ts index f47307929f4..3c7f3883e07 100644 --- a/clients/algoliasearch-client-javascript/base.tsup.config.ts +++ b/clients/algoliasearch-client-javascript/base.tsup.config.ts @@ -7,6 +7,14 @@ type PKG = { name: string; }; +const requesters = { + fetch: '@algolia/requester-fetch', + http: '@algolia/requester-node-http', + xhr: '@algolia/requester-browser-xhr', +}; + +type Requester = keyof typeof requesters; + export function getBaseConfig(cwd: string): Options { return { clean: true, @@ -16,35 +24,40 @@ export function getBaseConfig(cwd: string): Options { }; } -export function getDependencies(pkg: PKG, env: 'browser' | 'node'): string[] { +export function getDependencies(pkg: PKG, requester: Requester): string[] { const deps = Object.keys(pkg.dependencies || {}) || []; if (pkg.name !== 'algoliasearch') { return deps; } - if (env === 'node') { - return deps.filter((dep) => dep !== '@algolia/requester-browser-xhr'); + switch (requester) { + case 'http': + return deps.filter((dep) => dep !== requesters.fetch && dep !== requesters.xhr); + case 'xhr': + return deps.filter((dep) => dep !== requesters.fetch && dep !== requesters.http); + case 'fetch': + return deps.filter((dep) => dep !== requesters.xhr && dep !== requesters.http); + default: + throw new Error('unknown requester', requester); } - - return deps.filter((dep) => dep !== '@algolia/requester-node-http'); } -export function getBaseNodeOptions(pkg: PKG, cwd: string): Options { +export function getBaseNodeOptions(pkg: PKG, cwd: string, requester: Requester = 'http'): Options { return { ...getBaseConfig(cwd), platform: 'node', target: 'node14', - external: [...getDependencies(pkg, 'node'), 'node:crypto'], + external: [...getDependencies(pkg, requester), 'node:crypto'], }; } -export function getBaseBrowserOptions(pkg: PKG, cwd: string): Options { +export function getBaseBrowserOptions(pkg: PKG, cwd: string, requester: Requester = 'xhr'): Options { return { ...getBaseConfig(cwd), platform: 'browser', format: ['esm'], target: ['chrome109', 'safari15.6', 'firefox115', 'edge126'], - external: [...getDependencies(pkg, 'browser'), 'dom'], + external: [...getDependencies(pkg, requester), 'dom'], }; } diff --git a/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.browser.test.ts b/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.browser.test.ts index d7666a7d6b9..35bee1e1127 100644 --- a/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.browser.test.ts +++ b/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.browser.test.ts @@ -1,356 +1,14 @@ -import type { EchoResponse } from '@algolia/client-common'; -import { - DEFAULT_CONNECT_TIMEOUT_BROWSER, - DEFAULT_READ_TIMEOUT_BROWSER, - DEFAULT_WRITE_TIMEOUT_BROWSER, -} from '@algolia/client-common'; -import { echoRequester } from '@algolia/requester-browser-xhr'; - import { algoliasearch, apiClientVersion } from '../builds/browser'; -import { liteClient } from '../lite/builds/browser'; - -const client = algoliasearch('APP_ID', 'API_KEY', { - requester: echoRequester(), -}); - -describe('api', () => { - it('exposes the `appId` currently in use at the root of the API', () => { - expect(client.appId).toEqual('APP_ID'); - }); - - it('provides a `clearCache` method', () => { - expect(client.clearCache).not.toBeUndefined(); - expect(() => client.clearCache()).not.toThrow(); - }); - - it('provides a `setClientApiKey` method', () => { - const _client = algoliasearch('foo', 'bar', { - requester: echoRequester(), - }); - - expect(_client.transporter.baseQueryParameters['x-algolia-api-key']).toEqual('bar'); - expect(_client.setClientApiKey).not.toBeUndefined(); - _client.setClientApiKey({ apiKey: 'tabac' }); - expect(_client.transporter.baseQueryParameters['x-algolia-api-key']).toEqual('tabac'); - }); - - it('sets the user agent', async () => { - const req = (await client.customPost({ - path: '/test', - })) as unknown as EchoResponse; - - expect(req.algoliaAgent).toMatchInlineSnapshot( - `"Algolia%20for%20JavaScript%20(${apiClientVersion})%3B%20Search%20(${apiClientVersion})%3B%20Browser"`, - ); - }); - - it('throws with undefined API key', () => { - expect(() => algoliasearch('APP_ID', '')).toThrow('`apiKey` is missing'); - }); - - it('throws with undefined app ID', () => { - expect(() => algoliasearch('', 'API_KEY')).toThrow('`appId` is missing'); - }); - - it('provides the search client at the root of the API', () => { - expect(client.search).not.toBeUndefined(); - }); - - describe('_ua', () => { - it('provides a backward compatible `_ua` variable at the root of the client', () => { - expect(client._ua).toEqual( - expect.stringContaining(`Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion});`), - ); - }); - - it('keeps `_ua` updated with the transporter algolia agent', () => { - expect(client._ua).toEqual(expect.stringMatching(/.*; Browser$/g)); - - client.addAlgoliaAgent('Jest', '0.0.1'); - - expect(client._ua).toEqual(expect.stringMatching(/.*; Jest \(0\.0\.1\)$/g)); - }); - }); - - it('exposes the search client transporter for the algoliasearch client', () => { - expect(client.transporter).not.toBeUndefined(); - expect(client.transporter).toEqual({ - algoliaAgent: { - add: expect.any(Function), - value: expect.stringContaining(`Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion});`), - }, - baseHeaders: { - 'content-type': 'text/plain', - }, - baseQueryParameters: { - 'x-algolia-api-key': 'API_KEY', - 'x-algolia-application-id': 'APP_ID', - }, - hosts: expect.arrayContaining([ - { - accept: 'read', - protocol: 'https', - url: 'APP_ID-dsn.algolia.net', - }, - { - accept: 'write', - protocol: 'https', - url: 'APP_ID.algolia.net', - }, - { - accept: 'readWrite', - protocol: 'https', - url: 'APP_ID-3.algolianet.com', - }, - { - accept: 'readWrite', - protocol: 'https', - url: 'APP_ID-1.algolianet.com', - }, - { - accept: 'readWrite', - protocol: 'https', - url: 'APP_ID-2.algolianet.com', - }, - ]), - hostsCache: { - clear: expect.any(Function), - delete: expect.any(Function), - get: expect.any(Function), - set: expect.any(Function), - }, - request: expect.any(Function), - requester: { - send: expect.any(Function), - }, - requestsCache: { - clear: expect.any(Function), - delete: expect.any(Function), - get: expect.any(Function), - set: expect.any(Function), - }, - responsesCache: { - clear: expect.any(Function), - delete: expect.any(Function), - get: expect.any(Function), - set: expect.any(Function), - }, - timeouts: { - connect: DEFAULT_CONNECT_TIMEOUT_BROWSER, - read: DEFAULT_READ_TIMEOUT_BROWSER, - write: DEFAULT_WRITE_TIMEOUT_BROWSER, - }, - }); - }); - - describe('init clients', () => { - it('provides an init method for the analytics client', () => { - expect(client.initAnalytics).not.toBeUndefined(); - }); - - it('provides an init method for the abtesting client', () => { - expect(client.initAbtesting).not.toBeUndefined(); - }); - - it('provides an init method for the personalization client', () => { - expect(client.initPersonalization).not.toBeUndefined(); - }); - - it('default `init` clients to the root `algoliasearch` credentials', async () => { - const abtestingClient = client.initAbtesting({ options: { requester: echoRequester() } }); - const analyticsClient = client.initAnalytics({ options: { requester: echoRequester() } }); - const personalizationClient = client.initPersonalization({ - region: 'eu', - options: { requester: echoRequester() }, - }); - - const res1 = (await abtestingClient.customGet({ - path: 'abtestingClient', - })) as unknown as EchoResponse; - const res2 = (await analyticsClient.customGet({ - path: 'analyticsClient', - })) as unknown as EchoResponse; - const res3 = (await personalizationClient.customGet({ - path: 'personalizationClient', - })) as unknown as EchoResponse; - - expect(res1.searchParams).toEqual( - expect.objectContaining({ - 'x-algolia-application-id': 'APP_ID', - 'x-algolia-api-key': 'API_KEY', - }), - ); - expect(res2.searchParams).toEqual( - expect.objectContaining({ - 'x-algolia-application-id': 'APP_ID', - 'x-algolia-api-key': 'API_KEY', - }), - ); - expect(res3.searchParams).toEqual( - expect.objectContaining({ - 'x-algolia-application-id': 'APP_ID', - 'x-algolia-api-key': 'API_KEY', - }), - ); - }); - - it('`init` clients accept different credentials', async () => { - const abtestingClient = client.initAbtesting({ - appId: 'appId1', - apiKey: 'apiKey1', - options: { requester: echoRequester() }, - }); - const analyticsClient = client.initAnalytics({ - appId: 'appId2', - apiKey: 'apiKey2', - options: { requester: echoRequester() }, - }); - const personalizationClient = client.initPersonalization({ - appId: 'appId3', - apiKey: 'apiKey3', - region: 'eu', - options: { requester: echoRequester() }, - }); - - const res1 = (await abtestingClient.customGet({ - path: 'abtestingClient', - })) as unknown as EchoResponse; - const res2 = (await analyticsClient.customGet({ - path: 'analyticsClient', - })) as unknown as EchoResponse; - const res3 = (await personalizationClient.customGet({ - path: 'personalizationClient', - })) as unknown as EchoResponse; - - expect(res1.searchParams).toEqual( - expect.objectContaining({ - 'x-algolia-application-id': 'appId1', - 'x-algolia-api-key': 'apiKey1', - }), - ); - expect(res2.searchParams).toEqual( - expect.objectContaining({ - 'x-algolia-application-id': 'appId2', - 'x-algolia-api-key': 'apiKey2', - }), - ); - expect(res3.searchParams).toEqual( - expect.objectContaining({ - 'x-algolia-application-id': 'appId3', - 'x-algolia-api-key': 'apiKey3', - }), - ); - }); - }); -}); describe('bundle', () => { - it('expose both a full bundled package and a lite one', () => { - expect(liteClient).not.toBeUndefined(); - expect(algoliasearch).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({ - 'x-algolia-api-key': 'API_KEY', - 'x-algolia-application-id': 'APP_ID', - }); - }); - - 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({ - 'x-algolia-api-key': 'API_KEY', - 'x-algolia-application-id': 'APP_ID', - }); - }); - - 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({ - 'x-algolia-api-key': 'API_KEY', - 'x-algolia-application-id': 'APP_ID', - }); - }); -}); - -describe('init', () => { - test('sets authMode', async () => { - const qpClient = algoliasearch('foo', 'bar', { - authMode: 'WithinQueryParameters', - requester: echoRequester(), - }); - const headerClient = algoliasearch('foo', 'bar', { - authMode: 'WithinHeaders', - requester: echoRequester(), - }); - - const qpResult = (await qpClient.customGet({ - path: '1/foo', - })) as unknown as EchoResponse; - expect(qpResult.searchParams).toEqual({ - 'x-algolia-api-key': 'bar', - 'x-algolia-application-id': 'foo', - }); - - const headerResult = (await headerClient.customGet({ - path: '1/bar', - })) as unknown as EchoResponse; - expect(headerResult.headers).toEqual({ - accept: 'application/json', - 'content-type': 'text/plain', - 'x-algolia-api-key': 'bar', - 'x-algolia-application-id': 'foo', - }); - }); - - test('defaults to qp', async () => { - const res = (await client.customGet({ - path: '1/foo', - })) as unknown as EchoResponse; - expect(res.searchParams).toEqual({ - 'x-algolia-api-key': 'API_KEY', - 'x-algolia-application-id': 'APP_ID', + const client = algoliasearch('APP_ID', 'API_KEY'); + + it('sets the ua', () => { + expect(client.transporter.algoliaAgent).toEqual({ + add: expect.any(Function), + value: expect.stringContaining( + `Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion}); Browser`, + ), }); }); }); diff --git a/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.common.test.ts b/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.common.test.ts new file mode 100644 index 00000000000..114cf071d5a --- /dev/null +++ b/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.common.test.ts @@ -0,0 +1,365 @@ +import type { EchoResponse } from '@algolia/client-common'; +import { + DEFAULT_CONNECT_TIMEOUT_NODE, + DEFAULT_READ_TIMEOUT_NODE, + DEFAULT_WRITE_TIMEOUT_NODE, +} from '@algolia/client-common'; +import { echoRequester } from '@algolia/requester-node-http/src/echoRequester'; + +import { algoliasearch, apiClientVersion } from '../builds/node'; +import { liteClient } from '../lite/builds/node'; + +const client = algoliasearch('APP_ID', 'API_KEY', { + requester: echoRequester(), +}); + +describe('api', () => { + it('exposes the `appId` currently in use at the root of the API', () => { + expect(client.appId).toEqual('APP_ID'); + }); + + it('provides a `clearCache` method', () => { + expect(client.clearCache).not.toBeUndefined(); + expect(() => client.clearCache()).not.toThrow(); + }); + + it('provides a `setClientApiKey` method', () => { + const _client = algoliasearch('foo', 'bar'); + expect(_client.transporter.baseHeaders['x-algolia-api-key']).toEqual('bar'); + expect(_client.setClientApiKey).not.toBeUndefined(); + _client.setClientApiKey({ apiKey: 'tabac' }); + expect(_client.transporter.baseHeaders['x-algolia-api-key']).toEqual('tabac'); + }); + + it('throws with undefined API key', () => { + expect(() => algoliasearch('APP_ID', '')).toThrow('`apiKey` is missing'); + }); + + it('throws with undefined app ID', () => { + expect(() => algoliasearch('', 'API_KEY')).toThrow('`appId` is missing'); + }); + + it('provides the search client at the root of the API', () => { + expect(client.search).not.toBeUndefined(); + }); + + describe('_ua', () => { + it('provides a backward compatible `_ua` variable at the root of the client', () => { + expect(client._ua).toEqual( + expect.stringContaining(`Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion});`), + ); + }); + + it('keeps `_ua` updated with the transporter algolia agent', () => { + expect(client._ua).toEqual(expect.stringMatching(/.*; Node\.js \(.*\)$/g)); + + client.addAlgoliaAgent('Jest', '0.0.1'); + + expect(client._ua).toEqual(expect.stringMatching(/.*; Jest \(0\.0\.1\)$/g)); + }); + }); + + it('exposes the search client transporter for the algoliasearch client', () => { + expect(client.transporter).not.toBeUndefined(); + expect(client.transporter).toEqual({ + algoliaAgent: { + add: expect.any(Function), + value: expect.stringContaining( + `Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion}); Node.js`, + ), + }, + baseHeaders: { + 'content-type': 'text/plain', + 'x-algolia-api-key': 'API_KEY', + 'x-algolia-application-id': 'APP_ID', + }, + baseQueryParameters: {}, + hosts: expect.arrayContaining([ + { + accept: 'read', + protocol: 'https', + url: 'APP_ID-dsn.algolia.net', + }, + { + accept: 'write', + protocol: 'https', + url: 'APP_ID.algolia.net', + }, + { + accept: 'readWrite', + protocol: 'https', + url: 'APP_ID-3.algolianet.com', + }, + { + accept: 'readWrite', + protocol: 'https', + url: 'APP_ID-1.algolianet.com', + }, + { + accept: 'readWrite', + protocol: 'https', + url: 'APP_ID-2.algolianet.com', + }, + ]), + hostsCache: { + clear: expect.any(Function), + delete: expect.any(Function), + get: expect.any(Function), + set: expect.any(Function), + }, + request: expect.any(Function), + requester: { + send: expect.any(Function), + }, + requestsCache: { + clear: expect.any(Function), + delete: expect.any(Function), + get: expect.any(Function), + set: expect.any(Function), + }, + responsesCache: { + clear: expect.any(Function), + delete: expect.any(Function), + get: expect.any(Function), + set: expect.any(Function), + }, + timeouts: { + connect: DEFAULT_CONNECT_TIMEOUT_NODE, + read: DEFAULT_READ_TIMEOUT_NODE, + write: DEFAULT_WRITE_TIMEOUT_NODE, + }, + }); + }); + + describe('init clients', () => { + it('provides an init method for the analytics client', () => { + expect(client.initAnalytics).not.toBeUndefined(); + }); + + it('provides an init method for the abtesting client', () => { + expect(client.initAbtesting).not.toBeUndefined(); + }); + + it('provides an init method for the personalization client', () => { + expect(client.initPersonalization).not.toBeUndefined(); + }); + + it('provides an init method for the recommend client', () => { + expect(client.initRecommend).not.toBeUndefined(); + }); + + it('default `init` clients to the root `algoliasearch` credentials', async () => { + const abtestingClient = client.initAbtesting({ options: { requester: echoRequester() } }); + const analyticsClient = client.initAnalytics({ options: { requester: echoRequester() } }); + const recommendClient = client.initRecommend({ options: { requester: echoRequester() } }); + const personalizationClient = client.initPersonalization({ + region: 'eu', + options: { requester: echoRequester() }, + }); + + const res1 = (await abtestingClient.customGet({ + path: 'abtestingClient', + })) as unknown as EchoResponse; + const res2 = (await analyticsClient.customGet({ + path: 'analyticsClient', + })) as unknown as EchoResponse; + const res3 = (await personalizationClient.customGet({ + path: 'personalizationClient', + })) as unknown as EchoResponse; + const res4 = (await recommendClient.customGet({ + path: 'recommendClient', + })) as unknown as EchoResponse; + + expect(res1.headers).toEqual( + expect.objectContaining({ + 'x-algolia-application-id': 'APP_ID', + 'x-algolia-api-key': 'API_KEY', + }), + ); + expect(res2.headers).toEqual( + expect.objectContaining({ + 'x-algolia-application-id': 'APP_ID', + 'x-algolia-api-key': 'API_KEY', + }), + ); + expect(res3.headers).toEqual( + expect.objectContaining({ + 'x-algolia-application-id': 'APP_ID', + 'x-algolia-api-key': 'API_KEY', + }), + ); + expect(res4.headers).toEqual( + expect.objectContaining({ + 'x-algolia-application-id': 'APP_ID', + 'x-algolia-api-key': 'API_KEY', + }), + ); + }); + + it('`init` clients accept different credentials', async () => { + const abtestingClient = client.initAbtesting({ + appId: 'appId1', + apiKey: 'apiKey1', + options: { requester: echoRequester() }, + }); + const analyticsClient = client.initAnalytics({ + appId: 'appId2', + apiKey: 'apiKey2', + options: { requester: echoRequester() }, + }); + const personalizationClient = client.initPersonalization({ + appId: 'appId3', + apiKey: 'apiKey3', + region: 'eu', + options: { requester: echoRequester() }, + }); + const recommendClient = client.initRecommend({ + appId: 'appId4', + apiKey: 'apiKey4', + options: { requester: echoRequester() }, + }); + + const res1 = (await abtestingClient.customGet({ + path: 'abtestingClient', + })) as unknown as EchoResponse; + const res2 = (await analyticsClient.customGet({ + path: 'analyticsClient', + })) as unknown as EchoResponse; + const res3 = (await personalizationClient.customGet({ + path: 'personalizationClient', + })) as unknown as EchoResponse; + const res4 = (await recommendClient.customGet({ + path: 'recommendClient', + })) as unknown as EchoResponse; + + expect(res1.headers).toEqual( + expect.objectContaining({ + 'x-algolia-application-id': 'appId1', + 'x-algolia-api-key': 'apiKey1', + }), + ); + expect(res2.headers).toEqual( + expect.objectContaining({ + 'x-algolia-application-id': 'appId2', + 'x-algolia-api-key': 'apiKey2', + }), + ); + expect(res3.headers).toEqual( + expect.objectContaining({ + 'x-algolia-application-id': 'appId3', + 'x-algolia-api-key': 'apiKey3', + }), + ); + expect(res4.headers).toEqual( + expect.objectContaining({ + 'x-algolia-application-id': 'appId4', + 'x-algolia-api-key': 'apiKey4', + }), + ); + }); + }); +}); + +describe('bundle', () => { + it('expose both a full bundled package and a lite one', () => { + expect(liteClient).not.toBeUndefined(); + expect(algoliasearch).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); + }); +}); + +describe('init', () => { + test('sets authMode', async () => { + const qpClient = algoliasearch('foo', 'bar', { + authMode: 'WithinQueryParameters', + requester: echoRequester(), + }); + const headerClient = algoliasearch('foo', 'bar', { + authMode: 'WithinHeaders', + requester: echoRequester(), + }); + + const qpResult = (await qpClient.customGet({ + path: '1/foo', + })) as unknown as EchoResponse; + expect(qpResult.searchParams).toEqual({ + 'x-algolia-api-key': 'bar', + 'x-algolia-application-id': 'foo', + }); + + const headerResult = (await headerClient.customGet({ + path: '1/bar', + })) as unknown as EchoResponse; + expect(headerResult.headers).toEqual({ + accept: 'application/json', + 'content-type': 'text/plain', + 'x-algolia-api-key': 'bar', + 'x-algolia-application-id': 'foo', + }); + }); + + test('defaults to headers', async () => { + const res = (await client.customGet({ + path: '1/foo', + })) as unknown as EchoResponse; + expect(res.headers).toEqual({ + accept: 'application/json', + 'content-type': 'text/plain', + 'x-algolia-api-key': 'API_KEY', + 'x-algolia-application-id': 'APP_ID', + }); + }); +}); diff --git a/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.fetch.test.ts b/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.fetch.test.ts new file mode 100644 index 00000000000..57e2c37cd60 --- /dev/null +++ b/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.fetch.test.ts @@ -0,0 +1,14 @@ +import { algoliasearch, apiClientVersion } from '../builds/fetch'; + +describe('bundle', () => { + const client = algoliasearch('APP_ID', 'API_KEY'); + + it('sets the ua', () => { + expect(client.transporter.algoliaAgent).toEqual({ + add: expect.any(Function), + value: expect.stringContaining( + `Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion}); Fetch`, + ), + }); + }); +}); diff --git a/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.node.test.ts b/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.node.test.ts index 5fb2aee6da0..5621624168e 100644 --- a/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.node.test.ts +++ b/clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.node.test.ts @@ -1,348 +1,14 @@ -import type { EchoResponse } from '@algolia/client-common'; -import { - DEFAULT_CONNECT_TIMEOUT_NODE, - DEFAULT_READ_TIMEOUT_NODE, - DEFAULT_WRITE_TIMEOUT_NODE, -} from '@algolia/client-common'; -import { echoRequester } from '@algolia/requester-node-http'; - import { algoliasearch, apiClientVersion } from '../builds/node'; -import { liteClient } from '../lite/builds/node'; - -const client = algoliasearch('APP_ID', 'API_KEY', { - requester: echoRequester(), -}); - -describe('api', () => { - it('exposes the `appId` currently in use at the root of the API', () => { - expect(client.appId).toEqual('APP_ID'); - }); - - it('provides a `clearCache` method', () => { - expect(client.clearCache).not.toBeUndefined(); - expect(() => client.clearCache()).not.toThrow(); - }); - - it('provides a `setClientApiKey` method', () => { - const _client = algoliasearch('foo', 'bar', { - requester: echoRequester(), - }); - - expect(_client.transporter.baseHeaders['x-algolia-api-key']).toEqual('bar'); - expect(_client.setClientApiKey).not.toBeUndefined(); - _client.setClientApiKey({ apiKey: 'tabac' }); - expect(_client.transporter.baseHeaders['x-algolia-api-key']).toEqual('tabac'); - }); - - it('sets the user agent', async () => { - const req = (await client.customPost({ - path: '/test', - })) as unknown as EchoResponse; - - expect(req.algoliaAgent).toMatchInlineSnapshot( - `"Algolia%20for%20JavaScript%20(${apiClientVersion})%3B%20Search%20(${apiClientVersion})%3B%20Node.js%20(${process.versions.node})"`, - ); - }); - - it('throws with undefined API key', () => { - expect(() => algoliasearch('APP_ID', '')).toThrow('`apiKey` is missing'); - }); - - it('throws with undefined app ID', () => { - expect(() => algoliasearch('', 'API_KEY')).toThrow('`appId` is missing'); - }); - - it('provides the search client at the root of the API', () => { - expect(client.search).not.toBeUndefined(); - }); - - describe('_ua', () => { - it('provides a backward compatible `_ua` variable at the root of the client', () => { - expect(client._ua).toEqual( - expect.stringContaining(`Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion});`), - ); - }); - - it('keeps `_ua` updated with the transporter algolia agent', () => { - expect(client._ua).toEqual(expect.stringMatching(/.*; Node\.js \(.*\)$/g)); - - client.addAlgoliaAgent('Jest', '0.0.1'); - - expect(client._ua).toEqual(expect.stringMatching(/.*; Jest \(0\.0\.1\)$/g)); - }); - }); - - it('exposes the search client transporter for the algoliasearch client', () => { - expect(client.transporter).not.toBeUndefined(); - expect(client.transporter).toEqual({ - algoliaAgent: { - add: expect.any(Function), - value: expect.stringContaining(`Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion});`), - }, - baseHeaders: { - 'content-type': 'text/plain', - 'x-algolia-api-key': 'API_KEY', - 'x-algolia-application-id': 'APP_ID', - }, - baseQueryParameters: {}, - hosts: expect.arrayContaining([ - { - accept: 'read', - protocol: 'https', - url: 'APP_ID-dsn.algolia.net', - }, - { - accept: 'write', - protocol: 'https', - url: 'APP_ID.algolia.net', - }, - { - accept: 'readWrite', - protocol: 'https', - url: 'APP_ID-3.algolianet.com', - }, - { - accept: 'readWrite', - protocol: 'https', - url: 'APP_ID-1.algolianet.com', - }, - { - accept: 'readWrite', - protocol: 'https', - url: 'APP_ID-2.algolianet.com', - }, - ]), - hostsCache: { - clear: expect.any(Function), - delete: expect.any(Function), - get: expect.any(Function), - set: expect.any(Function), - }, - request: expect.any(Function), - requester: { - send: expect.any(Function), - }, - requestsCache: { - clear: expect.any(Function), - delete: expect.any(Function), - get: expect.any(Function), - set: expect.any(Function), - }, - responsesCache: { - clear: expect.any(Function), - delete: expect.any(Function), - get: expect.any(Function), - set: expect.any(Function), - }, - timeouts: { - connect: DEFAULT_CONNECT_TIMEOUT_NODE, - read: DEFAULT_READ_TIMEOUT_NODE, - write: DEFAULT_WRITE_TIMEOUT_NODE, - }, - }); - }); - - describe('init clients', () => { - it('provides an init method for the analytics client', () => { - expect(client.initAnalytics).not.toBeUndefined(); - }); - - it('provides an init method for the abtesting client', () => { - expect(client.initAbtesting).not.toBeUndefined(); - }); - - it('provides an init method for the personalization client', () => { - expect(client.initPersonalization).not.toBeUndefined(); - }); - - it('default `init` clients to the root `algoliasearch` credentials', async () => { - const abtestingClient = client.initAbtesting({ options: { requester: echoRequester() } }); - const analyticsClient = client.initAnalytics({ options: { requester: echoRequester() } }); - const personalizationClient = client.initPersonalization({ - region: 'eu', - options: { requester: echoRequester() }, - }); - - const res1 = (await abtestingClient.customGet({ - path: 'abtestingClient', - })) as unknown as EchoResponse; - const res2 = (await analyticsClient.customGet({ - path: 'analyticsClient', - })) as unknown as EchoResponse; - const res3 = (await personalizationClient.customGet({ - path: 'personalizationClient', - })) as unknown as EchoResponse; - - expect(res1.headers).toEqual( - expect.objectContaining({ - 'x-algolia-application-id': 'APP_ID', - 'x-algolia-api-key': 'API_KEY', - }), - ); - expect(res2.headers).toEqual( - expect.objectContaining({ - 'x-algolia-application-id': 'APP_ID', - 'x-algolia-api-key': 'API_KEY', - }), - ); - expect(res3.headers).toEqual( - expect.objectContaining({ - 'x-algolia-application-id': 'APP_ID', - 'x-algolia-api-key': 'API_KEY', - }), - ); - }); - - it('`init` clients accept different credentials', async () => { - const abtestingClient = client.initAbtesting({ - appId: 'appId1', - apiKey: 'apiKey1', - options: { requester: echoRequester() }, - }); - const analyticsClient = client.initAnalytics({ - appId: 'appId2', - apiKey: 'apiKey2', - options: { requester: echoRequester() }, - }); - const personalizationClient = client.initPersonalization({ - appId: 'appId3', - apiKey: 'apiKey3', - region: 'eu', - options: { requester: echoRequester() }, - }); - - const res1 = (await abtestingClient.customGet({ - path: 'abtestingClient', - })) as unknown as EchoResponse; - const res2 = (await analyticsClient.customGet({ - path: 'analyticsClient', - })) as unknown as EchoResponse; - const res3 = (await personalizationClient.customGet({ - path: 'personalizationClient', - })) as unknown as EchoResponse; - - expect(res1.headers).toEqual( - expect.objectContaining({ - 'x-algolia-application-id': 'appId1', - 'x-algolia-api-key': 'apiKey1', - }), - ); - expect(res2.headers).toEqual( - expect.objectContaining({ - 'x-algolia-application-id': 'appId2', - 'x-algolia-api-key': 'apiKey2', - }), - ); - expect(res3.headers).toEqual( - expect.objectContaining({ - 'x-algolia-application-id': 'appId3', - 'x-algolia-api-key': 'apiKey3', - }), - ); - }); - }); -}); describe('bundle', () => { - it('expose both a full bundled package and a lite one', () => { - expect(liteClient).not.toBeUndefined(); - expect(algoliasearch).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); - }); -}); - -describe('init', () => { - test('sets authMode', async () => { - const qpClient = algoliasearch('foo', 'bar', { - authMode: 'WithinQueryParameters', - requester: echoRequester(), - }); - const headerClient = algoliasearch('foo', 'bar', { - authMode: 'WithinHeaders', - requester: echoRequester(), - }); - - const qpResult = (await qpClient.customGet({ - path: '1/foo', - })) as unknown as EchoResponse; - expect(qpResult.searchParams).toEqual({ - 'x-algolia-api-key': 'bar', - 'x-algolia-application-id': 'foo', - }); - - const headerResult = (await headerClient.customGet({ - path: '1/bar', - })) as unknown as EchoResponse; - expect(headerResult.headers).toEqual({ - accept: 'application/json', - 'content-type': 'text/plain', - 'x-algolia-api-key': 'bar', - 'x-algolia-application-id': 'foo', - }); - }); - - test('defaults to headers', async () => { - const res = (await client.customGet({ - path: '1/foo', - })) as unknown as EchoResponse; - expect(res.headers).toEqual({ - accept: 'application/json', - 'content-type': 'text/plain', - 'x-algolia-api-key': 'API_KEY', - 'x-algolia-application-id': 'APP_ID', + const client = algoliasearch('APP_ID', 'API_KEY'); + + it('sets the ua', () => { + expect(client.transporter.algoliaAgent).toEqual({ + add: expect.any(Function), + value: expect.stringContaining( + `Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion}); Node.js`, + ), }); }); }); diff --git a/clients/algoliasearch-client-javascript/packages/algoliasearch/jest.config.cjs b/clients/algoliasearch-client-javascript/packages/algoliasearch/jest.config.cjs index cbd6c43fe6d..c970a925774 100644 --- a/clients/algoliasearch-client-javascript/packages/algoliasearch/jest.config.cjs +++ b/clients/algoliasearch-client-javascript/packages/algoliasearch/jest.config.cjs @@ -11,12 +11,17 @@ module.exports = { { ...baseConfig, testEnvironment: 'jsdom', - testPathIgnorePatterns: [ '__tests__/algoliasearch.node.test.ts' ], + testMatch: [ '**/algoliasearch.browser.*' ], }, { ...baseConfig, testEnvironment: 'node', - testPathIgnorePatterns: [ '__tests__/algoliasearch.browser.test.ts' ], + testMatch: [ '**/algoliasearch.(node|common).*' ], + }, + { + ...baseConfig, + testEnvironment: "miniflare", + testMatch: [ '**/algoliasearch.fetch.*' ], }, ], }; diff --git a/clients/algoliasearch-client-javascript/packages/client-common/package.json b/clients/algoliasearch-client-javascript/packages/client-common/package.json index 26d23b7f432..c6a00cc49b5 100644 --- a/clients/algoliasearch-client-javascript/packages/client-common/package.json +++ b/clients/algoliasearch-client-javascript/packages/client-common/package.json @@ -19,11 +19,13 @@ "types": { "import": "./dist/common.d.ts", "module": "./dist/common.d.ts", - "require": "./dist/common.d.cts" + "require": "./dist/common.d.cts", + "default": "./dist/common.d.cts" }, "import": "./dist/common.esm.js", "module": "./dist/common.esm.js", - "require": "./dist/common.cjs" + "require": "./dist/common.cjs", + "default": "./dist/common.cjs" }, "./src/*": "./src/*.ts" }, diff --git a/clients/algoliasearch-client-javascript/packages/client-common/src/createEchoRequester.ts b/clients/algoliasearch-client-javascript/packages/client-common/src/createEchoRequester.ts index 85bb4f188da..be9d38ffa61 100644 --- a/clients/algoliasearch-client-javascript/packages/client-common/src/createEchoRequester.ts +++ b/clients/algoliasearch-client-javascript/packages/client-common/src/createEchoRequester.ts @@ -1,7 +1,13 @@ import type { EchoResponse, EndRequest, Requester, Response } from './types'; +type BasicURL = { + host: string; + search: string; + pathname: string; +}; + export type EchoRequesterParams = { - getURL: (url: string) => URL; + getURL: (url: string) => BasicURL; status?: number; }; @@ -9,7 +15,7 @@ function getUrlParams({ host, search, pathname, -}: URL): Pick { +}: BasicURL): Pick { const urlSearchParams = search.split('?'); if (urlSearchParams.length === 1) { return { diff --git a/clients/algoliasearch-client-javascript/packages/requester-fetch/package.json b/clients/algoliasearch-client-javascript/packages/requester-fetch/package.json index b0caf00a22a..09886806fba 100644 --- a/clients/algoliasearch-client-javascript/packages/requester-fetch/package.json +++ b/clients/algoliasearch-client-javascript/packages/requester-fetch/package.json @@ -15,16 +15,23 @@ "types": { "import": "./dist/requester.fetch.node.d.ts", "module": "./dist/requester.fetch.node.d.ts", - "require": "./dist/requester.fetch.node.d.cts" + "require": "./dist/requester.fetch.node.d.cts", + "default": "./dist/requester.fetch.node.d.cts" }, "import": "./dist/requester.fetch.node.js", "module": "./dist/requester.fetch.node.js", - "require": "./dist/requester.fetch.node.cjs" + "require": "./dist/requester.fetch.node.cjs", + "default": "./dist/requester.fetch.node.cjs" + }, + "worker": { + "types": "./dist/requester.fetch.node.d.ts", + "default": "./dist/requester.fetch.node.js" }, "default": { "types": "./dist/requester.fetch.browser.d.ts", "module": "./dist/requester.fetch.browser.js", - "import": "./dist/requester.fetch.browser.js" + "import": "./dist/requester.fetch.browser.js", + "default": "./dist/requester.fetch.browser.js" } }, "./src/*": "./src/*.ts" diff --git a/clients/algoliasearch-client-javascript/packages/requester-node-http/index.ts b/clients/algoliasearch-client-javascript/packages/requester-node-http/index.ts index d43eff3c7f0..85352ebe21f 100644 --- a/clients/algoliasearch-client-javascript/packages/requester-node-http/index.ts +++ b/clients/algoliasearch-client-javascript/packages/requester-node-http/index.ts @@ -1,2 +1,2 @@ -export * from './src/echoRequester'; export * from './src/createHttpRequester'; +export * from './src/echoRequester'; diff --git a/clients/algoliasearch-client-javascript/packages/requester-node-http/package.json b/clients/algoliasearch-client-javascript/packages/requester-node-http/package.json index 8b2d7c234e4..29dec4858e4 100644 --- a/clients/algoliasearch-client-javascript/packages/requester-node-http/package.json +++ b/clients/algoliasearch-client-javascript/packages/requester-node-http/package.json @@ -19,11 +19,13 @@ "types": { "import": "./dist/requester.http.d.ts", "module": "./dist/requester.http.d.ts", - "require": "./dist/requester.http.d.cts" + "require": "./dist/requester.http.d.cts", + "default": "./dist/requester.http.d.cts" }, "import": "./dist/requester.http.js", "module": "./dist/requester.http.js", - "require": "./dist/requester.http.cjs" + "require": "./dist/requester.http.cjs", + "default": "./dist/requester.http.cjs" }, "./src/*": "./src/*.ts" }, diff --git a/clients/algoliasearch-client-javascript/yarn.lock b/clients/algoliasearch-client-javascript/yarn.lock index 0cc31dea58b..37f668dba11 100644 --- a/clients/algoliasearch-client-javascript/yarn.lock +++ b/clients/algoliasearch-client-javascript/yarn.lock @@ -11,6 +11,7 @@ __metadata: dependencies: "@algolia/client-common": "npm:5.3.2" "@algolia/requester-browser-xhr": "npm:5.3.2" + "@algolia/requester-fetch": "npm:5.3.2" "@algolia/requester-node-http": "npm:5.3.2" "@arethetypeswrong/cli": "npm:0.15.4" "@types/node": "npm:22.5.1" @@ -27,6 +28,7 @@ __metadata: dependencies: "@algolia/client-common": "npm:5.3.2" "@algolia/requester-browser-xhr": "npm:5.3.2" + "@algolia/requester-fetch": "npm:5.3.2" "@algolia/requester-node-http": "npm:5.3.2" "@arethetypeswrong/cli": "npm:0.15.4" "@types/node": "npm:22.5.1" @@ -61,6 +63,7 @@ __metadata: dependencies: "@algolia/client-common": "npm:5.3.2" "@algolia/requester-browser-xhr": "npm:5.3.2" + "@algolia/requester-fetch": "npm:5.3.2" "@algolia/requester-node-http": "npm:5.3.2" "@arethetypeswrong/cli": "npm:0.15.4" "@types/node": "npm:22.5.1" @@ -77,6 +80,7 @@ __metadata: dependencies: "@algolia/client-common": "npm:5.3.2" "@algolia/requester-browser-xhr": "npm:5.3.2" + "@algolia/requester-fetch": "npm:5.3.2" "@algolia/requester-node-http": "npm:5.3.2" "@arethetypeswrong/cli": "npm:0.15.4" "@types/node": "npm:22.5.1" @@ -93,6 +97,7 @@ __metadata: dependencies: "@algolia/client-common": "npm:5.3.2" "@algolia/requester-browser-xhr": "npm:5.3.2" + "@algolia/requester-fetch": "npm:5.3.2" "@algolia/requester-node-http": "npm:5.3.2" "@arethetypeswrong/cli": "npm:0.15.4" "@types/node": "npm:22.5.1" @@ -109,6 +114,7 @@ __metadata: dependencies: "@algolia/client-common": "npm:5.3.2" "@algolia/requester-browser-xhr": "npm:5.3.2" + "@algolia/requester-fetch": "npm:5.3.2" "@algolia/requester-node-http": "npm:5.3.2" "@arethetypeswrong/cli": "npm:0.15.4" "@types/node": "npm:22.5.1" @@ -125,6 +131,7 @@ __metadata: dependencies: "@algolia/client-common": "npm:5.3.2" "@algolia/requester-browser-xhr": "npm:5.3.2" + "@algolia/requester-fetch": "npm:5.3.2" "@algolia/requester-node-http": "npm:5.3.2" "@arethetypeswrong/cli": "npm:0.15.4" "@types/node": "npm:22.5.1" @@ -141,6 +148,7 @@ __metadata: dependencies: "@algolia/client-common": "npm:5.3.2" "@algolia/requester-browser-xhr": "npm:5.3.2" + "@algolia/requester-fetch": "npm:5.3.2" "@algolia/requester-node-http": "npm:5.3.2" "@arethetypeswrong/cli": "npm:0.15.4" "@types/node": "npm:22.5.1" @@ -157,6 +165,7 @@ __metadata: dependencies: "@algolia/client-common": "npm:5.3.2" "@algolia/requester-browser-xhr": "npm:5.3.2" + "@algolia/requester-fetch": "npm:5.3.2" "@algolia/requester-node-http": "npm:5.3.2" "@arethetypeswrong/cli": "npm:0.15.4" "@types/node": "npm:22.5.1" @@ -173,6 +182,7 @@ __metadata: dependencies: "@algolia/client-common": "npm:5.3.2" "@algolia/requester-browser-xhr": "npm:5.3.2" + "@algolia/requester-fetch": "npm:5.3.2" "@algolia/requester-node-http": "npm:5.3.2" "@arethetypeswrong/cli": "npm:0.15.4" "@types/node": "npm:22.5.1" @@ -203,7 +213,7 @@ __metadata: languageName: unknown linkType: soft -"@algolia/requester-fetch@workspace:packages/requester-fetch": +"@algolia/requester-fetch@npm:5.3.2, @algolia/requester-fetch@workspace:packages/requester-fetch": version: 0.0.0-use.local resolution: "@algolia/requester-fetch@workspace:packages/requester-fetch" dependencies: @@ -1713,6 +1723,13 @@ __metadata: languageName: node linkType: hard +"@cloudflare/workers-types@npm:^4.20221111.1": + version: 4.20240903.0 + resolution: "@cloudflare/workers-types@npm:4.20240903.0" + checksum: 10/d6f3ab8e3b36094c7392951793fc429a7853e0b3c8771800d61b7147df1db1ab43c9e6a73afe43546b4874f40620634313bcda19c1acadf7d73c4baef1942c53 + languageName: node + linkType: hard + "@colors/colors@npm:1.5.0": version: 1.5.0 resolution: "@colors/colors@npm:1.5.0" @@ -1916,6 +1933,13 @@ __metadata: languageName: node linkType: hard +"@fastify/busboy@npm:^2.0.0": + version: 2.1.1 + resolution: "@fastify/busboy@npm:2.1.1" + checksum: 10/2bb8a7eca8289ed14c9eb15239bc1019797454624e769b39a0b90ed204d032403adc0f8ed0d2aef8a18c772205fa7808cf5a1b91f21c7bfc7b6032150b1062c5 + languageName: node + linkType: hard + "@hutson/parse-repository-url@npm:^3.0.0": version: 3.0.2 resolution: "@hutson/parse-repository-url@npm:3.0.2" @@ -1923,6 +1947,13 @@ __metadata: languageName: node linkType: hard +"@iarna/toml@npm:^2.2.5": + version: 2.2.5 + resolution: "@iarna/toml@npm:2.2.5" + checksum: 10/b61426dc1a3297bbcb24cb8e9c638663866b4bb6f28f2c377b167e4b1f8956d8d208c484b73bb59f4232249903545cc073364c43576d2d5ad66afbd730ad24a9 + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -2019,7 +2050,7 @@ __metadata: languageName: node linkType: hard -"@jest/environment@npm:^29.7.0": +"@jest/environment@npm:>=27, @jest/environment@npm:^29.7.0": version: 29.7.0 resolution: "@jest/environment@npm:29.7.0" dependencies: @@ -2050,7 +2081,7 @@ __metadata: languageName: node linkType: hard -"@jest/fake-timers@npm:^29.7.0": +"@jest/fake-timers@npm:>=27, @jest/fake-timers@npm:^29.7.0": version: 29.7.0 resolution: "@jest/fake-timers@npm:29.7.0" dependencies: @@ -2180,7 +2211,7 @@ __metadata: languageName: node linkType: hard -"@jest/types@npm:^29.6.3": +"@jest/types@npm:>=27, @jest/types@npm:^29.6.3": version: 29.6.3 resolution: "@jest/types@npm:29.6.3" dependencies: @@ -2325,6 +2356,192 @@ __metadata: languageName: node linkType: hard +"@miniflare/cache@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/cache@npm:2.14.2" + dependencies: + "@miniflare/core": "npm:2.14.2" + "@miniflare/shared": "npm:2.14.2" + http-cache-semantics: "npm:^4.1.0" + undici: "npm:5.28.2" + checksum: 10/109bc3ebcca20bbeb0672442964b97218f0073d58b9983b0ead16af8b8de69a10a84ef1f8b26c61db90943e6b3b11b9e7d376812234de0dbe86dabc99c6a2006 + languageName: node + linkType: hard + +"@miniflare/core@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/core@npm:2.14.2" + dependencies: + "@iarna/toml": "npm:^2.2.5" + "@miniflare/queues": "npm:2.14.2" + "@miniflare/shared": "npm:2.14.2" + "@miniflare/watcher": "npm:2.14.2" + busboy: "npm:^1.6.0" + dotenv: "npm:^10.0.0" + kleur: "npm:^4.1.4" + set-cookie-parser: "npm:^2.4.8" + undici: "npm:5.28.2" + urlpattern-polyfill: "npm:^4.0.3" + checksum: 10/e1123b309183f402897ff4f6f7b36883be50f53247dc4069d6e5897a6b458e06aa00347f4da2cd967ed1736219f0ffcbd253f2ff91a07413db054bbae13d6a5e + languageName: node + linkType: hard + +"@miniflare/d1@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/d1@npm:2.14.2" + dependencies: + "@miniflare/core": "npm:2.14.2" + "@miniflare/shared": "npm:2.14.2" + checksum: 10/2aab7606e80d83ec560e571333893952f727ab53dd9881053cc95dfdb80ead6515cf925cefd11da1fcb9d79a939156bdf4d53a3ec128f07f18cef8137bd4cd96 + languageName: node + linkType: hard + +"@miniflare/durable-objects@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/durable-objects@npm:2.14.2" + dependencies: + "@miniflare/core": "npm:2.14.2" + "@miniflare/shared": "npm:2.14.2" + "@miniflare/storage-memory": "npm:2.14.2" + undici: "npm:5.28.2" + checksum: 10/2c8e15f2fe132f3df875171de274e8ce7fac41e3faa9887ca02ff1301b983f044a5b7ba9ca3d3cc1ee8c99bbec83c51ec1500a14e5acfd886ebeaed74b20a4bc + languageName: node + linkType: hard + +"@miniflare/html-rewriter@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/html-rewriter@npm:2.14.2" + dependencies: + "@miniflare/core": "npm:2.14.2" + "@miniflare/shared": "npm:2.14.2" + html-rewriter-wasm: "npm:^0.4.1" + undici: "npm:5.28.2" + checksum: 10/a4a438f5129a15b1222f5f9e980b472ef7acbf8b470fe7f59ff7936a4038bdc73a4d6815ce6ed9db97f939da9e3b90f1ced4ef230f87fbe6145533911ff80302 + languageName: node + linkType: hard + +"@miniflare/kv@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/kv@npm:2.14.2" + dependencies: + "@miniflare/shared": "npm:2.14.2" + checksum: 10/62c90e150e3d83fca3e69b37b4d8ab7814a5704dcb99ef9322f3323f16f3e9f6963ebc72b9e588acace304adf7cfea5ea5f2a6380b431077e554c29a86cb44ca + languageName: node + linkType: hard + +"@miniflare/queues@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/queues@npm:2.14.2" + dependencies: + "@miniflare/shared": "npm:2.14.2" + checksum: 10/78fc197464b652b4a42d131a62fb2b46189a637fb35ae00d1e717a2552f36910828cdf99c1e6ca3762195d6894f622fd6be143ff91309ab6aeb24d15f6848e4a + languageName: node + linkType: hard + +"@miniflare/r2@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/r2@npm:2.14.2" + dependencies: + "@miniflare/core": "npm:2.14.2" + "@miniflare/shared": "npm:2.14.2" + undici: "npm:5.28.2" + checksum: 10/e3b3d630d98bc6333909240d3a7905264860774e803aa105ae756fcbbe0d07e636e39a5e66ddcd5e6c8c4814c78869e8c2b3b89d8222f3342a46995ccece984f + languageName: node + linkType: hard + +"@miniflare/runner-vm@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/runner-vm@npm:2.14.2" + dependencies: + "@miniflare/shared": "npm:2.14.2" + checksum: 10/499e251a6c55674946a9615e4cfb419a61fd9d95d9c52c51fdf17cbb42b309f415f49740923c9454b7fae93022d8dadae231a2e5ebc499cc65ab505bd398f3ea + languageName: node + linkType: hard + +"@miniflare/shared-test-environment@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/shared-test-environment@npm:2.14.2" + dependencies: + "@cloudflare/workers-types": "npm:^4.20221111.1" + "@miniflare/cache": "npm:2.14.2" + "@miniflare/core": "npm:2.14.2" + "@miniflare/d1": "npm:2.14.2" + "@miniflare/durable-objects": "npm:2.14.2" + "@miniflare/html-rewriter": "npm:2.14.2" + "@miniflare/kv": "npm:2.14.2" + "@miniflare/queues": "npm:2.14.2" + "@miniflare/r2": "npm:2.14.2" + "@miniflare/shared": "npm:2.14.2" + "@miniflare/sites": "npm:2.14.2" + "@miniflare/storage-memory": "npm:2.14.2" + "@miniflare/web-sockets": "npm:2.14.2" + checksum: 10/e791141379eb047dd40d575750dfdc864420a9df9ff192bada2a156fe9b9572509536e7960515484d1a9d5f1d93e4187d8a1aab25ead92db1d2a29d31b786c99 + languageName: node + linkType: hard + +"@miniflare/shared@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/shared@npm:2.14.2" + dependencies: + "@types/better-sqlite3": "npm:^7.6.0" + kleur: "npm:^4.1.4" + npx-import: "npm:^1.1.4" + picomatch: "npm:^2.3.1" + checksum: 10/a89781803f6609e1b22a718834579d4a3dddb10ca6b9e9b5a4fe54e43a2dee07cf3c8864721a244d7b8b85073e81876dfb9c1fcb7a0d8a2bda6aa5cae79b9830 + languageName: node + linkType: hard + +"@miniflare/sites@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/sites@npm:2.14.2" + dependencies: + "@miniflare/kv": "npm:2.14.2" + "@miniflare/shared": "npm:2.14.2" + "@miniflare/storage-file": "npm:2.14.2" + checksum: 10/3c51443cce54d2dee19b5dea59a704cdb38b254ca4bfc7465da141f0d4705fdefd9f6d1ad3d975f40641372bd00d08db3c43f646380d87d15a3b66bb3e5ec359 + languageName: node + linkType: hard + +"@miniflare/storage-file@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/storage-file@npm:2.14.2" + dependencies: + "@miniflare/shared": "npm:2.14.2" + "@miniflare/storage-memory": "npm:2.14.2" + checksum: 10/2fcd42537b8b46232b4b9d5355e01e79b6a4868b45fe7752ef17a04ea68320011bb5e285c06a69306f2d06f98f3f1761d0efa9140c5638606ed584d39c373575 + languageName: node + linkType: hard + +"@miniflare/storage-memory@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/storage-memory@npm:2.14.2" + dependencies: + "@miniflare/shared": "npm:2.14.2" + checksum: 10/dfff7b04101d9164fdf29cda376b6165f864d79d366396c2ac7e6e78ae73e38f2ac190726c74fd595875c583b6765a7275ad711a8208f0bfa6107d12bed63fea + languageName: node + linkType: hard + +"@miniflare/watcher@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/watcher@npm:2.14.2" + dependencies: + "@miniflare/shared": "npm:2.14.2" + checksum: 10/118071395739a6d6091c9eac2cd4aa7e5530c77a00a50f5bd842225bcf94a2b60de13ce57cb553a58c7f445e7124e838c69976a24e25f7b7d1fb47a7d20869d4 + languageName: node + linkType: hard + +"@miniflare/web-sockets@npm:2.14.2": + version: 2.14.2 + resolution: "@miniflare/web-sockets@npm:2.14.2" + dependencies: + "@miniflare/core": "npm:2.14.2" + "@miniflare/shared": "npm:2.14.2" + undici: "npm:5.28.2" + ws: "npm:^8.2.2" + checksum: 10/eae602e2946294c0637dece688797699b7d0a35cb5dcd76d5030d9bec95a0c38b24002726c401e2c58cb04e691ad9cca40ce76e64c5652f4340cfeac2262d2ff + languageName: node + linkType: hard + "@napi-rs/wasm-runtime@npm:0.2.4": version: 0.2.4 resolution: "@napi-rs/wasm-runtime@npm:0.2.4" @@ -3191,6 +3408,15 @@ __metadata: languageName: node linkType: hard +"@types/better-sqlite3@npm:^7.6.0": + version: 7.6.11 + resolution: "@types/better-sqlite3@npm:7.6.11" + dependencies: + "@types/node": "npm:*" + checksum: 10/660f29485803e8f1a443b6009c48d172130e5d91f5b2728d8868ed9b39650cf5835b6747fb61141ea4f706dd321fcbf442dac245437ed7f3511901d3578380d3 + languageName: node + linkType: hard + "@types/estree@npm:0.0.39": version: 0.0.39 resolution: "@types/estree@npm:0.0.39" @@ -3517,6 +3743,7 @@ __metadata: "@algolia/client-search": "npm:5.3.2" "@algolia/recommend": "npm:5.3.2" "@algolia/requester-browser-xhr": "npm:5.3.2" + "@algolia/requester-fetch": "npm:5.3.2" "@algolia/requester-node-http": "npm:5.3.2" "@arethetypeswrong/cli": "npm:0.15.4" "@babel/preset-env": "npm:7.25.4" @@ -3524,6 +3751,7 @@ __metadata: "@types/jest": "npm:29.5.12" "@types/node": "npm:22.5.1" jest: "npm:29.7.0" + jest-environment-miniflare: "npm:2.14.3" publint: "npm:0.2.10" rollup: "npm:4.21.2" tsup: "npm:8.2.4" @@ -4004,6 +4232,15 @@ __metadata: languageName: node linkType: hard +"builtins@npm:^5.0.0": + version: 5.1.0 + resolution: "builtins@npm:5.1.0" + dependencies: + semver: "npm:^7.0.0" + checksum: 10/60aa9969f69656bf6eab82cd74b23ab805f112ae46a54b912bccc1533875760f2d2ce95e0a7d13144e35ada9f0386f17ed4961908bc9434b5a5e21375b1902b2 + languageName: node + linkType: hard + "bundle-require@npm:^5.0.0": version: 5.0.0 resolution: "bundle-require@npm:5.0.0" @@ -4037,6 +4274,15 @@ __metadata: languageName: node linkType: hard +"busboy@npm:^1.6.0": + version: 1.6.0 + resolution: "busboy@npm:1.6.0" + dependencies: + streamsearch: "npm:^1.1.0" + checksum: 10/bee10fa10ea58e7e3e7489ffe4bda6eacd540a17de9f9cd21cc37e297b2dd9fe52b2715a5841afaec82900750d810d01d7edb4b2d456427f449b92b417579763 + languageName: node + linkType: hard + "byte-size@npm:8.1.1": version: 8.1.1 resolution: "byte-size@npm:8.1.1" @@ -4982,6 +5228,13 @@ __metadata: languageName: node linkType: hard +"dotenv@npm:^10.0.0": + version: 10.0.0 + resolution: "dotenv@npm:10.0.0" + checksum: 10/55f701ae213e3afe3f4232fae5edfb6e0c49f061a363ff9f1c5a0c2bf3fb990a6e49aeada11b2a116efb5fdc3bc3f1ef55ab330be43033410b267f7c0809a9dc + languageName: node + linkType: hard + "dotenv@npm:^16.4.4, dotenv@npm:~16.4.5": version: 16.4.5 resolution: "dotenv@npm:16.4.5" @@ -5366,6 +5619,23 @@ __metadata: languageName: node linkType: hard +"execa@npm:^6.1.0": + version: 6.1.0 + resolution: "execa@npm:6.1.0" + dependencies: + cross-spawn: "npm:^7.0.3" + get-stream: "npm:^6.0.1" + human-signals: "npm:^3.0.1" + is-stream: "npm:^3.0.0" + merge-stream: "npm:^2.0.0" + npm-run-path: "npm:^5.1.0" + onetime: "npm:^6.0.0" + signal-exit: "npm:^3.0.7" + strip-final-newline: "npm:^3.0.0" + checksum: 10/669437011a7896b41b6b84786f9054c93202cb8336bd4fe15b6376bcddc37fd31f2e81f7f446fa1de519cbe831a0b93457ee185e5072caee1f230366f7d07aef + languageName: node + linkType: hard + "exit@npm:^0.1.2": version: 0.1.2 resolution: "exit@npm:0.1.2" @@ -5729,7 +5999,7 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^6.0.0": +"get-stream@npm:^6.0.0, get-stream@npm:^6.0.1": version: 6.0.1 resolution: "get-stream@npm:6.0.1" checksum: 10/781266d29725f35c59f1d214aedc92b0ae855800a980800e2923b3fbc4e56b3cb6e462c42e09a1cf1a00c64e056a78fa407cbe06c7c92b7e5cd49b4b85c2a497 @@ -6088,7 +6358,14 @@ __metadata: languageName: node linkType: hard -"http-cache-semantics@npm:^4.1.1": +"html-rewriter-wasm@npm:^0.4.1": + version: 0.4.1 + resolution: "html-rewriter-wasm@npm:0.4.1" + checksum: 10/f3414f3db4bcc03958f3a880b669ea8337eeede08993743169ea240cb86dd72c9e04eeec20a5e5e2321d602d3dda68df79df26e573e2ff4bc69fb95a482ed1f1 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.0, http-cache-semantics@npm:^4.1.1": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" checksum: 10/362d5ed66b12ceb9c0a328fb31200b590ab1b02f4a254a697dc796850cc4385603e75f53ec59f768b2dad3bfa1464bd229f7de278d2899a0e3beffc634b6683f @@ -6143,6 +6420,13 @@ __metadata: languageName: node linkType: hard +"human-signals@npm:^3.0.1": + version: 3.0.1 + resolution: "human-signals@npm:3.0.1" + checksum: 10/0b2741651e668ddebbc9ba5163c9c33cd4f837270133eda5831f50374d010e7eacc415fe5ed04b4b113d9779a81eef1d03467a7c7eb55ec094b2bd1dd8d3a837 + languageName: node + linkType: hard + "human-signals@npm:^8.0.0": version: 8.0.0 resolution: "human-signals@npm:8.0.0" @@ -6546,6 +6830,13 @@ __metadata: languageName: node linkType: hard +"is-stream@npm:^3.0.0": + version: 3.0.0 + resolution: "is-stream@npm:3.0.0" + checksum: 10/172093fe99119ffd07611ab6d1bcccfe8bc4aa80d864b15f43e63e54b7abc71e779acd69afdb854c4e2a67fdc16ae710e370eda40088d1cfc956a50ed82d8f16 + languageName: node + linkType: hard + "is-stream@npm:^4.0.1": version: 4.0.1 resolution: "is-stream@npm:4.0.1" @@ -6863,6 +7154,25 @@ __metadata: languageName: node linkType: hard +"jest-environment-miniflare@npm:2.14.3": + version: 2.14.3 + resolution: "jest-environment-miniflare@npm:2.14.3" + dependencies: + "@jest/environment": "npm:>=27" + "@jest/fake-timers": "npm:>=27" + "@jest/types": "npm:>=27" + "@miniflare/queues": "npm:2.14.2" + "@miniflare/runner-vm": "npm:2.14.2" + "@miniflare/shared": "npm:2.14.2" + "@miniflare/shared-test-environment": "npm:2.14.2" + jest-mock: "npm:>=27" + jest-util: "npm:>=27" + peerDependencies: + jest: ">=27" + checksum: 10/cd65bf7b2b86ee738175713f081adeceb86e44c206f330826f45fde17a8cd04ee9ad72aaadc9a09a2c0c2a53c25a02316e0e2b3b28c33dc94d45c007919b0500 + languageName: node + linkType: hard + "jest-environment-node@npm:^29.7.0": version: 29.7.0 resolution: "jest-environment-node@npm:29.7.0" @@ -6946,7 +7256,7 @@ __metadata: languageName: node linkType: hard -"jest-mock@npm:^29.7.0": +"jest-mock@npm:>=27, jest-mock@npm:^29.7.0": version: 29.7.0 resolution: "jest-mock@npm:29.7.0" dependencies: @@ -7090,7 +7400,7 @@ __metadata: languageName: node linkType: hard -"jest-util@npm:^29.0.0, jest-util@npm:^29.7.0": +"jest-util@npm:>=27, jest-util@npm:^29.0.0, jest-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-util@npm:29.7.0" dependencies: @@ -7365,6 +7675,13 @@ __metadata: languageName: node linkType: hard +"kleur@npm:^4.1.4": + version: 4.1.5 + resolution: "kleur@npm:4.1.5" + checksum: 10/44d84cc4eedd4311099402ef6d4acd9b2d16e08e499d6ef3bb92389bd4692d7ef09e35248c26e27f98acac532122acb12a1bfee645994ae3af4f0a37996da7df + languageName: node + linkType: hard + "lerna@npm:8.1.8": version: 8.1.8 resolution: "lerna@npm:8.1.8" @@ -7815,6 +8132,13 @@ __metadata: languageName: node linkType: hard +"mimic-fn@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-fn@npm:4.0.0" + checksum: 10/995dcece15ee29aa16e188de6633d43a3db4611bcf93620e7e62109ec41c79c0f34277165b8ce5e361205049766e371851264c21ac64ca35499acb5421c2ba56 + languageName: node + linkType: hard + "mimic-response@npm:^2.0.0": version: 2.1.0 resolution: "mimic-response@npm:2.1.0" @@ -8399,7 +8723,7 @@ __metadata: languageName: node linkType: hard -"npm-run-path@npm:^5.2.0": +"npm-run-path@npm:^5.1.0, npm-run-path@npm:^5.2.0": version: 5.3.0 resolution: "npm-run-path@npm:5.3.0" dependencies: @@ -8420,6 +8744,18 @@ __metadata: languageName: node linkType: hard +"npx-import@npm:^1.1.4": + version: 1.1.4 + resolution: "npx-import@npm:1.1.4" + dependencies: + execa: "npm:^6.1.0" + parse-package-name: "npm:^1.0.0" + semver: "npm:^7.3.7" + validate-npm-package-name: "npm:^4.0.0" + checksum: 10/384a60d1c9de3023dd13dac627277cdc3dff65c82b9b22c3378da66dade96116f3baf98d66bd351903d74b8cfb2c09ab835c1c8558b675a492eaa30d17652b9d + languageName: node + linkType: hard + "number-is-nan@npm:^1.0.0": version: 1.0.1 resolution: "number-is-nan@npm:1.0.1" @@ -8551,6 +8887,15 @@ __metadata: languageName: node linkType: hard +"onetime@npm:^6.0.0": + version: 6.0.0 + resolution: "onetime@npm:6.0.0" + dependencies: + mimic-fn: "npm:^4.0.0" + checksum: 10/0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788 + languageName: node + linkType: hard + "open@npm:^8.4.0": version: 8.4.2 resolution: "open@npm:8.4.2" @@ -8809,6 +9154,13 @@ __metadata: languageName: node linkType: hard +"parse-package-name@npm:^1.0.0": + version: 1.0.0 + resolution: "parse-package-name@npm:1.0.0" + checksum: 10/4352537f7a967323ba5841ddbd59dd12d4fd7292c8e7ec61973a00ea5b5ecef7594a1ec7d9a930cd3599d0f2908ddb00beedf0020de74fa789e48a056149bd96 + languageName: node + linkType: hard + "parse-path@npm:^7.0.0": version: 7.0.0 resolution: "parse-path@npm:7.0.0" @@ -9794,6 +10146,13 @@ __metadata: languageName: node linkType: hard +"set-cookie-parser@npm:^2.4.8": + version: 2.7.0 + resolution: "set-cookie-parser@npm:2.7.0" + checksum: 10/5c0a197c022d614b3168efbb27a1e81c6eb97a07f1502780648be7483a6bada38c4e516f3d168769e7e3e819d431efdf7b659dcb450196bb7e2594e6a11a2dd7 + languageName: node + linkType: hard + "set-function-length@npm:^1.2.1": version: 1.2.2 resolution: "set-function-length@npm:1.2.2" @@ -10078,6 +10437,13 @@ __metadata: languageName: node linkType: hard +"streamsearch@npm:^1.1.0": + version: 1.1.0 + resolution: "streamsearch@npm:1.1.0" + checksum: 10/612c2b2a7dbcc859f74597112f80a42cbe4d448d03da790d5b7b39673c1197dd3789e91cd67210353e58857395d32c1e955a9041c4e6d5bae723436b3ed9ed14 + languageName: node + linkType: hard + "string-length@npm:^4.0.1": version: 4.0.2 resolution: "string-length@npm:4.0.2" @@ -10187,6 +10553,13 @@ __metadata: languageName: node linkType: hard +"strip-final-newline@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-final-newline@npm:3.0.0" + checksum: 10/23ee263adfa2070cd0f23d1ac14e2ed2f000c9b44229aec9c799f1367ec001478469560abefd00c5c99ee6f0b31c137d53ec6029c53e9f32a93804e18c201050 + languageName: node + linkType: hard + "strip-final-newline@npm:^4.0.0": version: 4.0.0 resolution: "strip-final-newline@npm:4.0.0" @@ -10775,6 +11148,15 @@ __metadata: languageName: node linkType: hard +"undici@npm:5.28.2": + version: 5.28.2 + resolution: "undici@npm:5.28.2" + dependencies: + "@fastify/busboy": "npm:^2.0.0" + checksum: 10/07ab8b812c7322f5faba55268562e3626463171ace8a2e5861e5793e69f8901e809bcdeb4013126fe8d1602baac247ea3c0c996073dbf9709516295b0a4dd18f + languageName: node + linkType: hard + "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.0 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" @@ -10893,6 +11275,13 @@ __metadata: languageName: node linkType: hard +"urlpattern-polyfill@npm:^4.0.3": + version: 4.0.3 + resolution: "urlpattern-polyfill@npm:4.0.3" + checksum: 10/e456b5075afdf84a625b2cc17506b683cfa0639b74b0874cfb0b8dba3fc5c4c1fa7698ef253c32658ee3b5fe4cfdad1c58b595be4c3fe59949d15cdaf171dbbf + languageName: node + linkType: hard + "util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -10937,6 +11326,15 @@ __metadata: languageName: node linkType: hard +"validate-npm-package-name@npm:^4.0.0": + version: 4.0.0 + resolution: "validate-npm-package-name@npm:4.0.0" + dependencies: + builtins: "npm:^5.0.0" + checksum: 10/a32fd537bad17fcb59cfd58ae95a414d443866020d448ec3b22e8d40550cb585026582a57efbe1f132b882eea4da8ac38ee35f7be0dd72988a3cb55d305a20c1 + languageName: node + linkType: hard + "vlq@npm:^0.2.2": version: 0.2.3 resolution: "vlq@npm:0.2.3" @@ -11187,7 +11585,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.11.0": +"ws@npm:^8.11.0, ws@npm:^8.2.2": version: 8.18.0 resolution: "ws@npm:8.18.0" peerDependencies: diff --git a/generators/src/main/java/com/algolia/codegen/AlgoliaJavascriptGenerator.java b/generators/src/main/java/com/algolia/codegen/AlgoliaJavascriptGenerator.java index 7eed51e9335..4ed48566633 100644 --- a/generators/src/main/java/com/algolia/codegen/AlgoliaJavascriptGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/AlgoliaJavascriptGenerator.java @@ -76,6 +76,7 @@ public void processOpts() { // builds supportingFiles.add(new SupportingFile("client/builds/browser.mustache", "builds", "browser.ts")); supportingFiles.add(new SupportingFile("client/builds/node.mustache", "builds", "node.ts")); + supportingFiles.add(new SupportingFile("client/builds/fetch.mustache", "builds", "fetch.ts")); } // `algoliasearch` related files else { @@ -84,6 +85,7 @@ public void processOpts() { // `algoliasearch` builds supportingFiles.add(new SupportingFile("algoliasearch/builds/definition.mustache", "builds", "browser.ts")); supportingFiles.add(new SupportingFile("algoliasearch/builds/definition.mustache", "builds", "node.ts")); + supportingFiles.add(new SupportingFile("algoliasearch/builds/definition.mustache", "builds", "fetch.ts")); supportingFiles.add(new SupportingFile("algoliasearch/builds/models.mustache", "builds", "models.ts")); // `lite` builds diff --git a/templates/javascript/clients/algoliasearch/builds/definition.mustache b/templates/javascript/clients/algoliasearch/builds/definition.mustache index fb35555d0e6..b455f154338 100644 --- a/templates/javascript/clients/algoliasearch/builds/definition.mustache +++ b/templates/javascript/clients/algoliasearch/builds/definition.mustache @@ -21,9 +21,9 @@ import type { export * from './models'; export type Algoliasearch = SearchClient & { - initRecommend: (initOptions: InitClientOptions)=> RecommendClient; - initAnalytics: (initOptions: InitClientOptions & InitClientRegion)=> AnalyticsClient; - initAbtesting: (initOptions: InitClientOptions & InitClientRegion)=> AbtestingClient; + initRecommend: (initOptions?: InitClientOptions)=> RecommendClient; + initAnalytics: (initOptions?: InitClientOptions & InitClientRegion)=> AnalyticsClient; + initAbtesting: (initOptions?: InitClientOptions & InitClientRegion)=> AbtestingClient; initPersonalization: (initOptions: InitClientOptions & Required>)=> PersonalizationClient; }; diff --git a/templates/javascript/clients/client/builds/definition.mustache b/templates/javascript/clients/client/builds/definition.mustache index 9b307e06e69..db8bfb10a88 100644 --- a/templates/javascript/clients/client/builds/definition.mustache +++ b/templates/javascript/clients/client/builds/definition.mustache @@ -1,5 +1,6 @@ import { createXhrRequester } from '@algolia/requester-browser-xhr'; import { createHttpRequester } from '@algolia/requester-node-http'; +import { createFetchRequester } from '@algolia/requester-fetch'; import { createMemoryCache, createFallbackableCache, createBrowserLocalStorageCache, createNullCache, ClientOptions, serializeQueryParameters, DEFAULT_CONNECT_TIMEOUT_NODE, DEFAULT_READ_TIMEOUT_NODE, DEFAULT_WRITE_TIMEOUT_NODE, DEFAULT_CONNECT_TIMEOUT_BROWSER, DEFAULT_READ_TIMEOUT_BROWSER, DEFAULT_WRITE_TIMEOUT_BROWSER } from '@algolia/client-common'; import { create{{#lambda.titlecase}}{{apiName}}{{/lambda.titlecase}}, apiClientVersion } from '../src/{{apiName}}'; diff --git a/templates/javascript/clients/client/builds/fetch.mustache b/templates/javascript/clients/client/builds/fetch.mustache new file mode 100644 index 00000000000..3873d5d59b5 --- /dev/null +++ b/templates/javascript/clients/client/builds/fetch.mustache @@ -0,0 +1,26 @@ +// {{{generationBanner}}} + +export type {{#lambda.titlecase}}{{apiName}}{{/lambda.titlecase}} = ReturnType{{#nodeSearchHelpers}} & SearchClientNodeHelpers{{/nodeSearchHelpers}}; + +{{> client/builds/definition}} + return { + ...create{{#lambda.titlecase}}{{apiName}}{{/lambda.titlecase}}({ + appId, + apiKey,{{#hasRegionalHost}}region,{{/hasRegionalHost}} + timeouts: { + connect: DEFAULT_CONNECT_TIMEOUT_NODE, + read: DEFAULT_READ_TIMEOUT_NODE, + write: DEFAULT_WRITE_TIMEOUT_NODE, + }, + algoliaAgents: [{ segment: 'Fetch' }], + requester: createFetchRequester(), + responsesCache: createNullCache(), + requestsCache: createNullCache(), + hostsCache: createMemoryCache(), + ...options, + }), + {{#nodeSearchHelpers}} + {{> client/api/nodeHelpers}} + {{/nodeSearchHelpers}} + } +} \ No newline at end of file diff --git a/templates/javascript/clients/package.mustache b/templates/javascript/clients/package.mustache index def16bda2fd..33cf20a8d49 100644 --- a/templates/javascript/clients/package.mustache +++ b/templates/javascript/clients/package.mustache @@ -30,6 +30,10 @@ "module": "./dist/builds/node.js", "require": "./dist/builds/node.cjs" }, + "worker": { + "types": "./dist/fetch.d.ts", + "default": "./dist/builds/fetch.js" + }, "default": { "types": "./dist/browser.d.ts", "module": "./dist/builds/browser.js", @@ -50,7 +54,8 @@ "dependencies": { "@algolia/client-common": "{{utilsPackageVersion}}", "@algolia/requester-browser-xhr": "{{utilsPackageVersion}}", - "@algolia/requester-node-http": "{{utilsPackageVersion}}" + "@algolia/requester-node-http": "{{utilsPackageVersion}}", + "@algolia/requester-fetch": "{{utilsPackageVersion}}" }, {{/isAlgoliasearchClient}} {{#isAlgoliasearchClient}} @@ -68,6 +73,10 @@ "module": "./dist/node.js", "require": "./dist/node.cjs" }, + "worker": { + "types": "./dist/fetch.d.ts", + "default": "./dist/fetch.js" + }, "default": { "types": "./dist/browser.d.ts", "module": "./dist/browser.js", @@ -113,7 +122,8 @@ "@algolia/client-common": "{{utilsPackageVersion}}", "@algolia/recommend": "{{recommendVersion}}", "@algolia/requester-browser-xhr": "{{utilsPackageVersion}}", - "@algolia/requester-node-http": "{{utilsPackageVersion}}" + "@algolia/requester-node-http": "{{utilsPackageVersion}}", + "@algolia/requester-fetch": "{{utilsPackageVersion}}" }, {{/isAlgoliasearchClient}} "devDependencies": { @@ -122,6 +132,7 @@ "@babel/preset-typescript": "7.24.7", "@types/jest": "29.5.12", "jest": "29.7.0", + "jest-environment-miniflare": "2.14.3", {{/isAlgoliasearchClient}} "@arethetypeswrong/cli": "0.15.4", "@types/node": "22.5.1", diff --git a/templates/javascript/clients/tsup.config.mustache b/templates/javascript/clients/tsup.config.mustache index a59c71d7251..48031a8a502 100644 --- a/templates/javascript/clients/tsup.config.mustache +++ b/templates/javascript/clients/tsup.config.mustache @@ -9,7 +9,6 @@ const nodeOptions: Options = { ...getBaseNodeOptions(pkg, __dirname), dts: { entry: { 'node': '{{#isAlgoliasearchClient}}lite/{{/isAlgoliasearchClient}}builds/node.ts' } }, entry: ['{{#isAlgoliasearchClient}}lite/{{/isAlgoliasearchClient}}builds/node.ts', '{{#isAlgoliasearchClient}}lite/{{/isAlgoliasearchClient}}src/*.ts'], - {{#isAlgoliasearchClient}} outDir: 'dist/lite', {{/isAlgoliasearchClient}} @@ -19,18 +18,28 @@ const nodeConfigs: Options[] = [ { ...nodeOptions, format: 'cjs', - name: 'node{{#isAlgoliasearchClient}} lite{{/isAlgoliasearchClient}} cjs' + name: `node ${pkg.name} cjs` }, { ...nodeOptions, format: 'esm', - name: 'node{{#isAlgoliasearchClient}} lite{{/isAlgoliasearchClient}} esm' + name: `node ${pkg.name} esm` }, + {{^isAlgoliasearchClient}} + { + ...nodeOptions, + format: 'esm', + name: `fetch ${pkg.name} esm`, + dts: { entry: { 'fetch': 'builds/fetch.ts' } }, + external: getDependencies(pkg, 'fetch'), + entry: ['builds/fetch.ts', 'src/*.ts'], + }, + {{/isAlgoliasearchClient}} {{#isAlgoliasearchClient}} { ...nodeOptions, format: 'cjs', - name: 'node cjs', + name: 'node algoliasearch cjs', dts: { entry: { 'node': 'builds/node.ts' } }, entry: ['builds/node.ts'], outDir: 'dist', @@ -38,11 +47,20 @@ const nodeConfigs: Options[] = [ { ...nodeOptions, format: 'esm', - name: 'node esm', + name: 'node algoliasearch esm', dts: { entry: { 'node': 'builds/node.ts' } }, entry: ['builds/node.ts'], outDir: 'dist', }, + { + ...nodeOptions, + format: 'esm', + name: 'fetch algoliasearch esm', + dts: { entry: { 'fetch': 'builds/fetch.ts' } }, + entry: ['builds/fetch.ts'], + outDir: 'dist', + external: getDependencies(pkg, 'fetch'), + }, {{/isAlgoliasearchClient}} ]; @@ -51,7 +69,6 @@ const browserOptions: Options = { {{^isAlgoliasearchClient}} globalName: '{{apiName}}', {{/isAlgoliasearchClient}} - {{#isAlgoliasearchClient}} globalName: 'lite', outDir: 'dist/lite', @@ -62,7 +79,7 @@ const browserConfigs: Options[] = [ { ...browserOptions, minify: false, - name: 'browser esm', + name: `browser ${pkg.name} esm`, dts: { entry: { 'browser': '{{#isAlgoliasearchClient}}lite/{{/isAlgoliasearchClient}}builds/browser.ts' } }, entry: ['{{#isAlgoliasearchClient}}lite/{{/isAlgoliasearchClient}}builds/browser.ts', '{{#isAlgoliasearchClient}}lite/{{/isAlgoliasearchClient}}src/*.ts'], {{#isAlgoliasearchClient}} @@ -73,14 +90,14 @@ const browserConfigs: Options[] = [ ...browserOptions, dts: false, minify: true, - name: 'browser min esm', + name: `browser ${pkg.name} min esm`, entry: {'builds/browser.min': '{{#isAlgoliasearchClient}}lite/{{/isAlgoliasearchClient}}builds/browser.ts'}, external: [], {{#isAlgoliasearchClient}} noExternal: ['dom', '@algolia/client-common', '@algolia/requester-browser-xhr'], {{/isAlgoliasearchClient}} {{^isAlgoliasearchClient}} - noExternal: getDependencies(pkg, 'browser'), + noExternal: getDependencies(pkg, 'xhr'), {{/isAlgoliasearchClient}} }, {{#isAlgoliasearchClient}} @@ -102,7 +119,7 @@ const browserConfigs: Options[] = [ entry: {'browser.min': 'builds/browser.ts'}, outDir: 'dist', external: [], - noExternal: getDependencies(pkg, 'browser'), + noExternal: getDependencies(pkg, 'xhr'), } {{/isAlgoliasearchClient}} ];