diff --git a/algolia/__tests__/client.test.ts b/algolia/__tests__/client.test.ts index c4e88f0..d500993 100644 --- a/algolia/__tests__/client.test.ts +++ b/algolia/__tests__/client.test.ts @@ -17,11 +17,8 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; const algoliasearchSpy = vi.fn(() => ({ __mockClient: true })); -// algoliasearch v4 uses a default export; v5 uses a named export. The -// production module imports the default with a `type SearchClient` -// type-only named import, so mocking the default is sufficient. vi.mock("algoliasearch", () => ({ - default: (...args: unknown[]) => + algoliasearch: (...args: unknown[]) => algoliasearchSpy(...(args as Parameters)), })); @@ -59,7 +56,7 @@ describe("getAlgoliaClient", () => { it("constructs the SDK with applicationId + adminApiKey", () => { mod.configureAlgolia({ applicationId: "APP_X", searchApiKey: "S", adminApiKey: "ADMIN" }); const client = mod.getAlgoliaClient(); - expect(algoliasearchSpy).toHaveBeenCalledExactlyOnceWith("APP_X", "ADMIN", expect.objectContaining({ requester: expect.anything() })); + expect(algoliasearchSpy).toHaveBeenCalledExactlyOnceWith("APP_X", "ADMIN"); expect(client).toEqual({ __mockClient: true }); }); @@ -77,7 +74,7 @@ describe("getAlgoliaClient", () => { mod.configureAlgolia({ applicationId: "APP_X", searchApiKey: "S", adminApiKey: "ADMIN2" }); mod.getAlgoliaClient(); expect(algoliasearchSpy).toHaveBeenCalledTimes(2); - expect(algoliasearchSpy).toHaveBeenNthCalledWith(2, "APP_X", "ADMIN2", expect.anything()); + expect(algoliasearchSpy).toHaveBeenNthCalledWith(2, "APP_X", "ADMIN2"); }); it("throws when applicationId is missing", () => { @@ -88,11 +85,7 @@ describe("getAlgoliaClient", () => { it("falls back to searchApiKey when adminApiKey is empty", () => { mod.configureAlgolia({ applicationId: "APP", searchApiKey: "SEARCH_ONLY", adminApiKey: "" }); mod.getAlgoliaClient(); - expect(algoliasearchSpy).toHaveBeenCalledExactlyOnceWith( - "APP", - "SEARCH_ONLY", - expect.objectContaining({ requester: expect.anything() }), - ); + expect(algoliasearchSpy).toHaveBeenCalledExactlyOnceWith("APP", "SEARCH_ONLY"); }); it("throws when both keys are empty", () => { @@ -103,11 +96,7 @@ describe("getAlgoliaClient", () => { it("prefers adminApiKey over searchApiKey when both present", () => { mod.configureAlgolia({ applicationId: "APP", searchApiKey: "S", adminApiKey: "ADMIN" }); mod.getAlgoliaClient(); - expect(algoliasearchSpy).toHaveBeenCalledExactlyOnceWith( - "APP", - "ADMIN", - expect.objectContaining({ requester: expect.anything() }), - ); + expect(algoliasearchSpy).toHaveBeenCalledExactlyOnceWith("APP", "ADMIN"); }); }); diff --git a/algolia/client.ts b/algolia/client.ts index 4a318cf..0986553 100644 --- a/algolia/client.ts +++ b/algolia/client.ts @@ -16,8 +16,7 @@ * Magento, and Algolia has consistent muscle memory. */ -import algoliasearch, { type SearchClient } from "algoliasearch"; -import { createFetchRequester } from "@algolia/requester-fetch"; +import { algoliasearch, type SearchClient } from "algoliasearch"; import type { AlgoliaConfig } from "./types"; @@ -73,14 +72,10 @@ export function getAlgoliaClient(): SearchClient { "as a worker env var, or populate searchApiKey on the block.", ); } - // algoliasearch v4's default Node http requester relies on - // `node:http` which isn't available in Cloudflare Workers, so the - // first request hangs / crashes. `@algolia/requester-fetch` uses - // the global `fetch`, which is what every Deco target runtime - // provides — Workers, Bun, modern Node. - cachedClient = algoliasearch(c.applicationId, key, { - requester: createFetchRequester(), - }); + // algoliasearch v5 uses the global `fetch` and `crypto` APIs by + // default — works on Cloudflare Workers, Bun, Deno, modern Node. + // v4 (with crypto / node:http imports) does not run on Workers. + cachedClient = algoliasearch(c.applicationId, key); return cachedClient; } diff --git a/bun.lock b/bun.lock index 665d94c..e50d452 100644 --- a/bun.lock +++ b/bun.lock @@ -5,14 +5,13 @@ "": { "name": "@decocms/apps", "devDependencies": { - "@algolia/requester-fetch": "^4.27.0", "@biomejs/biome": "^2.4.7", "@decocms/start": "5.3.0", "@semantic-release/exec": "^7.1.0", "@tanstack/react-query": "^5.90.21", "@types/react": "^19.0.0", "@vitest/coverage-v8": "^4.1.0", - "algoliasearch": "^4.27.0", + "algoliasearch": "^5.53.0", "happy-dom": "^20.9.0", "knip": "^5.86.0", "react": "^19.0.0", @@ -22,15 +21,13 @@ "vitest": "^4.1.0", }, "peerDependencies": { - "@algolia/requester-fetch": "^4", "@decocms/start": ">=5.3.0", "@tanstack/react-query": ">=5", - "algoliasearch": "^4 || ^5", + "algoliasearch": "^5", "react": ">=18", "react-dom": ">=18", }, "optionalPeers": [ - "@algolia/requester-fetch", "algoliasearch", ], }, @@ -44,37 +41,33 @@ "@actions/io": ["@actions/io@3.0.2", "", {}, "sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw=="], - "@algolia/cache-browser-local-storage": ["@algolia/cache-browser-local-storage@4.27.0", "", { "dependencies": { "@algolia/cache-common": "4.27.0" } }, "sha512-YGog2s57sO20lvpa+hv5XLAAmiTI1kHsCMRtPVfiaOdIQnvRla21lfH08onqEbZihOPVI8GULwt79zQB2ymKzg=="], + "@algolia/abtesting": ["@algolia/abtesting@1.19.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-Lhnez3hhXHk25lfxLAMxvkP4fmN3+1RgADhD2ssMDBYuAsDVReeyP+3SGRx+ntq8ijMrLqUyfvO72TB6jsTteQ=="], - "@algolia/cache-common": ["@algolia/cache-common@4.27.0", "", {}, "sha512-Sr8zjNXj82p6lO4W9CdzfF0m0/9h/H6VAdSHOTtimm/cTzXIYXRI2IZq7+Nt2ljJ7Ukx+7dIFcxQjE57eQSPsw=="], + "@algolia/client-abtesting": ["@algolia/client-abtesting@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-0ZjA5Hcmaoz5Lj6OG0zhfIyeqzJZnLW2CRJA1W17UwMFGRtZAJ9yJKRvPEDA6gkpsIoQxORTSW6sWFiuYncPNQ=="], - "@algolia/cache-in-memory": ["@algolia/cache-in-memory@4.27.0", "", { "dependencies": { "@algolia/cache-common": "4.27.0" } }, "sha512-abgMRTcVD0IllNvMM9JFhxtyLn1v6Ey7mQ7+BGS3JCzvkCX7KZqlS0BIuVUDgx9sPIfOeNsG/awGzMmP50TwZw=="], + "@algolia/client-analytics": ["@algolia/client-analytics@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-kWNodP75iiEaOtemC9F/hlxNBG5E2QUjN1BusnE6m2b4l7Qh/BUO3fGCVsmKJI65VO4VKGGmT43ICvHtTcJ2JQ=="], - "@algolia/client-account": ["@algolia/client-account@4.27.0", "", { "dependencies": { "@algolia/client-common": "4.27.0", "@algolia/client-search": "4.27.0", "@algolia/transporter": "4.27.0" } }, "sha512-sSHxwrKTKJrwfoR/LcQJZfmiWJcM5d9Rp7afMChxOcdGdkSdIwrNBC8SCcHRenA3GsZ6mg+j6px7KWYxJ34btA=="], + "@algolia/client-common": ["@algolia/client-common@5.53.0", "", {}, "sha512-YPN45TXD9Wrse185t/Ta7nktZsqpv97oOjCzp2sblHnCL6rBc9TDeJAg1IGl2UpdwnSD05Zu/5wLB4watOUMyg=="], - "@algolia/client-analytics": ["@algolia/client-analytics@4.27.0", "", { "dependencies": { "@algolia/client-common": "4.27.0", "@algolia/client-search": "4.27.0", "@algolia/requester-common": "4.27.0", "@algolia/transporter": "4.27.0" } }, "sha512-MqIDyxODljn9ZC4oqjQD0kez2a4zjIJ9ywA/b7cIiUiK/tDjZNTVjYd9WXMKQlXnWUwfrfXJZClVVqN1iCXS+Q=="], + "@algolia/client-insights": ["@algolia/client-insights@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-qAcYTDJE6m924FDDUQvdD6vh7DYaqOeSpFS74IP37/JRV0v4cGBauyxTF2WzDnokUylQDbqreoFIJZfg0Fitmw=="], - "@algolia/client-common": ["@algolia/client-common@4.27.0", "", { "dependencies": { "@algolia/requester-common": "4.27.0", "@algolia/transporter": "4.27.0" } }, "sha512-ZrT6l/YPQgyIUuBCxcYPeXol2VBLUMuNb1rKXrm6z1f/iTiwqtnEEb16/6CC11+Re0ZGXrdcMVrgDRrzveQ1aQ=="], + "@algolia/client-personalization": ["@algolia/client-personalization@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-fQaY+DkSJOpuUVUe8MQTwrdiKAqkJGhpDarB08duBn/sUv7Bkib6MDRQauCcWTWTe4HIW+EbwQP9R4kci1V/Yw=="], - "@algolia/client-personalization": ["@algolia/client-personalization@4.27.0", "", { "dependencies": { "@algolia/client-common": "4.27.0", "@algolia/requester-common": "4.27.0", "@algolia/transporter": "4.27.0" } }, "sha512-OZqaFFVm+10hAlmxpiTWi/o2n+YKBESbSqSy2yXAumPH/kaK4moJHFblbh8IkV3KZR0lLm4hzPtn8Q2nWNiDUA=="], + "@algolia/client-query-suggestions": ["@algolia/client-query-suggestions@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-o72tsiEZGfeS/dxL9IADfzcZWGEwKDEe5CvtrBuT//3JR+SHuTtHRI2ZTf7D7bcKagcbojvO8hnkHdfoakSlYg=="], - "@algolia/client-search": ["@algolia/client-search@4.27.0", "", { "dependencies": { "@algolia/client-common": "4.27.0", "@algolia/requester-common": "4.27.0", "@algolia/transporter": "4.27.0" } }, "sha512-qmX/f67ay0eZ4V5Io8fWWOcUVo/gqre2yei1PnmEhQU2Gul6ushg25QnNrfu4BODiRrw1rwYveZaLCiHvcUxrQ=="], + "@algolia/client-search": ["@algolia/client-search@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-Ds16IyPm/dNJPCU8OzApo2gwGrgWT5BYHhE3NFwZbpCveqyvPDB9sZDDkJ5DsdOGT2aC+R3i0/M1OVXF2qdgPg=="], - "@algolia/logger-common": ["@algolia/logger-common@4.27.0", "", {}, "sha512-pIrmQRXtDV+zTMVXKtKCosC2rWhn0F0TdUeb9etA6RiAz6jY6bY6f0+JX7YekDK09SnmZMLIyUa7Jci+Ied9bw=="], + "@algolia/ingestion": ["@algolia/ingestion@1.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-oNbT6z4NwD8Pou9VPINGlN/tlG1afESh2EbxqnP6rwl95xKVD/Zlciis1PpNeO/9U/rrajc1+7DcfKi03tX1KQ=="], - "@algolia/logger-console": ["@algolia/logger-console@4.27.0", "", { "dependencies": { "@algolia/logger-common": "4.27.0" } }, "sha512-UWvta8BxsR/u5z9eI088mOSLQaGtmoCtXeN3DYJurlxAdJwPuKtEb5+433kxA6/E9f2/JgoW89KZ1vNP9pcHBQ=="], + "@algolia/monitoring": ["@algolia/monitoring@1.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-G+KZb/yd+qAOFn/cEvTGeLxQm8aP3a0od50l3z/ylccY+/o4YG3TNcjU1tFQHW4mXC137GPyR7W70R0kRQDLnA=="], - "@algolia/recommend": ["@algolia/recommend@4.27.0", "", { "dependencies": { "@algolia/cache-browser-local-storage": "4.27.0", "@algolia/cache-common": "4.27.0", "@algolia/cache-in-memory": "4.27.0", "@algolia/client-common": "4.27.0", "@algolia/client-search": "4.27.0", "@algolia/logger-common": "4.27.0", "@algolia/logger-console": "4.27.0", "@algolia/requester-browser-xhr": "4.27.0", "@algolia/requester-common": "4.27.0", "@algolia/requester-node-http": "4.27.0", "@algolia/transporter": "4.27.0" } }, "sha512-CFy54xDjrsazPi3KN04yPmLRDT72AKokc3RLOdWQvG0/uEUjj7dhWqe9qenxpL4ydsjO7S1eY5YqmX+uMGonlg=="], + "@algolia/recommend": ["@algolia/recommend@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-6aVfYd55Un6IUgPLbo84WfgFZlS3L0vA1ttzXL5vahHewUJ8jYgd89TzlWRTeej7w70mb9RWsVlFYGmJ/diQww=="], - "@algolia/requester-browser-xhr": ["@algolia/requester-browser-xhr@4.27.0", "", { "dependencies": { "@algolia/requester-common": "4.27.0" } }, "sha512-dTenMBIIpyp5o3C2ZnfbsuSlD/lL9jPkk6T+2+qm38fyw2nf49ANbcHFE79NgiGrnmw7QrYveCs9NIP3Wk4v6g=="], + "@algolia/requester-browser-xhr": ["@algolia/requester-browser-xhr@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0" } }, "sha512-ke27DqgzCOlt+RbeEdCxtXxMQOnAOi8ujr2wid0DmDKzR95Kw/f9sBsuhBxtjevCqJRJszfRTLY0B1pbO6IhkA=="], - "@algolia/requester-common": ["@algolia/requester-common@4.27.0", "", {}, "sha512-VC3prAQVgWTubMStb3mJz6i61Hqbtagi2LeIbgNtoFJFff3XZDcAaO1D5r0GYl2+DrB2VzUHnQXbkiuI+HHYyg=="], + "@algolia/requester-fetch": ["@algolia/requester-fetch@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0" } }, "sha512-GngiOqt2Gq4oLno6yXQVj9om+qSO9SWAoduoTOEg79dKZ62brB8OOIvSJG/vDNoanYi6a7Al9uDZwXvi+bcVTg=="], - "@algolia/requester-fetch": ["@algolia/requester-fetch@4.27.0", "", { "dependencies": { "@algolia/requester-common": "4.27.0" } }, "sha512-kMpcyZENA9sHu2218S0CXi5G/8aqX7dfPfF+10h3IqnCDvwQMb6QPkEDqqKTd3SaR45wmBe5lXDOFVpHxnjm3w=="], - - "@algolia/requester-node-http": ["@algolia/requester-node-http@4.27.0", "", { "dependencies": { "@algolia/requester-common": "4.27.0" } }, "sha512-y8nUqaUQeSOQ5oaNo0b2QPznyBFW9LoIwljyUphJ+gUZpU6O/j2/C8ovoqDpIe6J0etqHg5RCcBizrCFZuLpyw=="], - - "@algolia/transporter": ["@algolia/transporter@4.27.0", "", { "dependencies": { "@algolia/cache-common": "4.27.0", "@algolia/logger-common": "4.27.0", "@algolia/requester-common": "4.27.0" } }, "sha512-PvSbELU4VjN3xSX79ki+zIdOGhTxyJXWvRDzkUjfTx2iNfPWDdTjzKbP1o+268coJztxrkuBwJz90Urek7o1Kw=="], + "@algolia/requester-node-http": ["@algolia/requester-node-http@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0" } }, "sha512-6mF9LZMUk0QqWvrnxkxBqhswwz6Xfiwy6/gmTzL5HrlhdVG3ITAqGV2k3XmVThP1h0Ulc3VQwiNCD7/Nr4JNlQ=="], "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], @@ -428,7 +421,7 @@ "aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="], - "algoliasearch": ["algoliasearch@4.27.0", "", { "dependencies": { "@algolia/cache-browser-local-storage": "4.27.0", "@algolia/cache-common": "4.27.0", "@algolia/cache-in-memory": "4.27.0", "@algolia/client-account": "4.27.0", "@algolia/client-analytics": "4.27.0", "@algolia/client-common": "4.27.0", "@algolia/client-personalization": "4.27.0", "@algolia/client-search": "4.27.0", "@algolia/logger-common": "4.27.0", "@algolia/logger-console": "4.27.0", "@algolia/recommend": "4.27.0", "@algolia/requester-browser-xhr": "4.27.0", "@algolia/requester-common": "4.27.0", "@algolia/requester-node-http": "4.27.0", "@algolia/transporter": "4.27.0" } }, "sha512-C88C5grLa5VOCp9eYZJt+q99ik7yNdm92l7Q9+4XK0Md8kL05Lg8l2v9ZVX0uMW3mH9pAFxMMXlLOvqNumA4lw=="], + "algoliasearch": ["algoliasearch@5.53.0", "", { "dependencies": { "@algolia/abtesting": "1.19.0", "@algolia/client-abtesting": "5.53.0", "@algolia/client-analytics": "5.53.0", "@algolia/client-common": "5.53.0", "@algolia/client-insights": "5.53.0", "@algolia/client-personalization": "5.53.0", "@algolia/client-query-suggestions": "5.53.0", "@algolia/client-search": "5.53.0", "@algolia/ingestion": "1.53.0", "@algolia/monitoring": "1.53.0", "@algolia/recommend": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-OGW1q6b91CRSSeiOnM8LxuR5NYJ2esvw66jUZ4IIvdv+ItNkx3pwLuyR+jaCdbGee4ov5WgUnyPryyh11xvByQ=="], "ansi-escapes": ["ansi-escapes@7.3.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg=="], diff --git a/package.json b/package.json index 7e3d5e6..bd847e4 100644 --- a/package.json +++ b/package.json @@ -123,17 +123,13 @@ "access": "public" }, "peerDependencies": { - "@algolia/requester-fetch": "^4", "@decocms/start": ">=5.3.0", "@tanstack/react-query": ">=5", - "algoliasearch": "^4 || ^5", + "algoliasearch": "^5", "react": ">=18", "react-dom": ">=18" }, "peerDependenciesMeta": { - "@algolia/requester-fetch": { - "optional": true - }, "algoliasearch": { "optional": true } @@ -144,9 +140,8 @@ "@semantic-release/exec": "^7.1.0", "@tanstack/react-query": "^5.90.21", "@types/react": "^19.0.0", - "@algolia/requester-fetch": "^4.27.0", "@vitest/coverage-v8": "^4.1.0", - "algoliasearch": "^4.27.0", + "algoliasearch": "^5.53.0", "happy-dom": "^20.9.0", "knip": "^5.86.0", "react": "^19.0.0",