diff --git a/README.md b/README.md index 231b1615..34b9da5a 100644 --- a/README.md +++ b/README.md @@ -64,19 +64,19 @@ To start using this SDK, you will need the following: #### Option 1: Using NPM -Install the Ably JavaScript SDK and the Spaces SDK: +Install the Ably Pub/Sub SDK and the Spaces SDK: ```sh -npm install ably @ably/spaces +npm install @ably/pubsub-device @ably/spaces ``` To instantiate the Spaces SDK, create an [Ably client](https://ably.com/docs/getting-started/setup) and pass it into the Spaces constructor: ```ts import Spaces from '@ably/spaces'; -import { Realtime } from 'ably'; +import { createClient } from '@ably/pubsub-device'; -const client = new Realtime({ key: "", clientId: "" }); +const client = createClient({ key: "", clientId: "" }); const spaces = new Spaces(client); ``` You can use [basic authentication](https://ably.com/docs/auth/basic) i.e. the API Key directly for testing purposes, however it is strongly recommended that you use [token authentication](https://ably.com/docs/auth/token) in production environments. diff --git a/__mocks__/ably/index.ts b/__mocks__/@ably/pubsub-core/index.ts similarity index 94% rename from __mocks__/ably/index.ts rename to __mocks__/@ably/pubsub-core/index.ts index a3c455ba..3622fd34 100644 --- a/__mocks__/ably/index.ts +++ b/__mocks__/@ably/pubsub-core/index.ts @@ -1,4 +1,4 @@ -import { PresenceMessage, Rest, ErrorInfo } from 'ably'; +import { PresenceMessage, Http, ErrorInfo } from '@ably/pubsub-core'; const MOCK_CLIENT_ID = 'MOCK_CLIENT_ID'; @@ -95,6 +95,6 @@ class MockErrorInfo extends ErrorInfo {} // maintain the PresenceMessage class so tests can initialise it directly using // PresenceMessage.fromValues. -MockRealtime.PresenceMessage = Rest.PresenceMessage; +MockRealtime.PresenceMessage = Http.PresenceMessage; export { MockRealtime as Realtime, MockErrorInfo as ErrorInfo }; diff --git a/demo/api/ably-token-request/index.ts b/demo/api/ably-token-request/index.ts index 9e077434..e64d2fb0 100644 --- a/demo/api/ably-token-request/index.ts +++ b/demo/api/ably-token-request/index.ts @@ -1,5 +1,5 @@ import * as dotenv from 'dotenv'; -import * as Ably from 'ably'; +import * as Ably from '@ably/pubsub-core'; import { HandlerEvent } from '@netlify/functions'; dotenv.config(); @@ -21,7 +21,7 @@ Please see README.md for more details on configuring your Ably API Key.`); } const clientId = event.queryStringParameters?.['clientId'] || process.env.DEFAULT_CLIENT_ID || 'NO_CLIENT_ID'; - const client = new Ably.Rest(process.env.ABLY_API_KEY); + const client = new Ably.Http(process.env.ABLY_API_KEY); const tokenRequestData = await client.auth.createTokenRequest({ clientId: clientId }); return { diff --git a/demo/api/ably-token-request/package-lock.json b/demo/api/ably-token-request/package-lock.json index 51bd49ce..0c8f09da 100644 --- a/demo/api/ably-token-request/package-lock.json +++ b/demo/api/ably-token-request/package-lock.json @@ -9,9 +9,9 @@ "version": "1.0.0", "license": "MIT", "dependencies": { + "@ably/pubsub-core": "3.0.0-canary.20260917T1031.521a3374", "@netlify/functions": "^1.4.0", "@types/node": "^18.3.0", - "ably": "^2.3.0", "dotenv": "^16.0.3", "typescript": "^4.9.5" } @@ -24,6 +24,35 @@ "bops": "^1.0.1" } }, + "node_modules/@ably/pubsub-core": { + "version": "3.0.0-canary.20260917T1031.521a3374", + "resolved": "https://registry.npmjs.org/@ably/pubsub-core/-/pubsub-core-3.0.0-canary.20260917T1031.521a3374.tgz", + "integrity": "sha512-9ZaMCA3ID1Xw7AtkiB/TeytffbXeTVetpPQtWkH7IvyU62w8d+T3MQHAVb1bIgo6HrvFBooKrzQx0e89ZE5R7w==", + "license": "Apache-2.0", + "dependencies": { + "@ably/msgpack-js": "^0.4.0", + "dequal": "^2.0.3", + "fastestsmallesttextencoderdecoder": "^1.0.22", + "got": "^11.8.5", + "ulid": "^2.3.0", + "ws": "^8.17.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/@netlify/functions": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-1.4.0.tgz", @@ -101,33 +130,6 @@ "@types/node": "*" } }, - "node_modules/ably": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ably/-/ably-2.3.0.tgz", - "integrity": "sha512-4QyN2SEUG1Svpg5LIr/K14U+X9e5Wv/dsldPcPZGwaE1iFVZxl7Ccb6/lcBMn+8Uq0+2q9rzTKFnGERQIRIHVg==", - "dependencies": { - "@ably/msgpack-js": "^0.4.0", - "fastestsmallesttextencoderdecoder": "^1.0.22", - "got": "^11.8.5", - "ulid": "^2.3.0", - "ws": "^8.17.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, "node_modules/base64-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.0.2.tgz", @@ -226,6 +228,15 @@ "node": ">=10" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/dotenv": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", @@ -462,6 +473,19 @@ "bops": "^1.0.1" } }, + "@ably/pubsub-core": { + "version": "3.0.0-canary.20260917T1031.521a3374", + "resolved": "https://registry.npmjs.org/@ably/pubsub-core/-/pubsub-core-3.0.0-canary.20260917T1031.521a3374.tgz", + "integrity": "sha512-9ZaMCA3ID1Xw7AtkiB/TeytffbXeTVetpPQtWkH7IvyU62w8d+T3MQHAVb1bIgo6HrvFBooKrzQx0e89ZE5R7w==", + "requires": { + "@ably/msgpack-js": "^0.4.0", + "dequal": "^2.0.3", + "fastestsmallesttextencoderdecoder": "^1.0.22", + "got": "^11.8.5", + "ulid": "^2.3.0", + "ws": "^8.17.1" + } + }, "@netlify/functions": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-1.4.0.tgz", @@ -525,18 +549,6 @@ "@types/node": "*" } }, - "ably": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ably/-/ably-2.3.0.tgz", - "integrity": "sha512-4QyN2SEUG1Svpg5LIr/K14U+X9e5Wv/dsldPcPZGwaE1iFVZxl7Ccb6/lcBMn+8Uq0+2q9rzTKFnGERQIRIHVg==", - "requires": { - "@ably/msgpack-js": "^0.4.0", - "fastestsmallesttextencoderdecoder": "^1.0.22", - "got": "^11.8.5", - "ulid": "^2.3.0", - "ws": "^8.17.1" - } - }, "base64-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.0.2.tgz", @@ -607,6 +619,11 @@ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, "dotenv": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", diff --git a/demo/api/ably-token-request/package.json b/demo/api/ably-token-request/package.json index 64508514..02939680 100644 --- a/demo/api/ably-token-request/package.json +++ b/demo/api/ably-token-request/package.json @@ -14,9 +14,9 @@ "author": "Netlify", "license": "MIT", "dependencies": { + "@ably/pubsub-core": "3.0.0-canary.20260917T1031.521a3374", "@netlify/functions": "^1.4.0", "@types/node": "^18.3.0", - "ably": "^2.3.0", "dotenv": "^16.0.3", "typescript": "^4.9.5" } diff --git a/demo/package-lock.json b/demo/package-lock.json index 097c86b0..2527224f 100644 --- a/demo/package-lock.json +++ b/demo/package-lock.json @@ -8,8 +8,8 @@ "name": "demo", "version": "1.0.0", "dependencies": { + "@ably/pubsub-device": "3.0.0-canary.20260917T1031.521a3374", "@ably/spaces": "file:..", - "ably": "^2.3.0", "classnames": "^2.3.2", "dayjs": "^1.11.9", "nanoid": "^3.3.11", @@ -41,15 +41,16 @@ }, "..": { "name": "@ably/spaces", - "version": "0.4.0", + "version": "0.5.2", "license": "ISC", "dependencies": { "nanoid": "^3.3.11" }, "devDependencies": { + "@ably/pubsub-device": "3.0.0-canary.20260917T1031.521a3374", "@playwright/test": "^1.53.0", "@rollup/plugin-node-resolve": "^15.3.1", - "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-terser": "^1.0.0", "@testing-library/react": "^14.3.1", "@types/express": "^4.17.23", "@types/react": "^18.3.23", @@ -73,7 +74,7 @@ "vitest": "^3.2.3" }, "peerDependencies": { - "ably": "^2.3.0", + "@ably/pubsub-core": "3.0.0-canary.20260917T1031.521a3374", "react": ">=16.8.0", "react-dom": ">=16.8.0" }, @@ -103,6 +104,59 @@ "bops": "^1.0.1" } }, + "node_modules/@ably/pubsub-core": { + "version": "3.0.0-canary.20260917T1031.521a3374", + "resolved": "https://registry.npmjs.org/@ably/pubsub-core/-/pubsub-core-3.0.0-canary.20260917T1031.521a3374.tgz", + "integrity": "sha512-9ZaMCA3ID1Xw7AtkiB/TeytffbXeTVetpPQtWkH7IvyU62w8d+T3MQHAVb1bIgo6HrvFBooKrzQx0e89ZE5R7w==", + "license": "Apache-2.0", + "dependencies": { + "@ably/msgpack-js": "^0.4.0", + "dequal": "^2.0.3", + "fastestsmallesttextencoderdecoder": "^1.0.22", + "got": "^11.8.5", + "ulid": "^2.3.0", + "ws": "^8.17.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@ably/pubsub-device": { + "version": "3.0.0-canary.20260917T1031.521a3374", + "resolved": "https://registry.npmjs.org/@ably/pubsub-device/-/pubsub-device-3.0.0-canary.20260917T1031.521a3374.tgz", + "integrity": "sha512-lGmu5B9ncJRb2YH5SyVOeMDBui+ouiyiZe/67bqsgqsVAM2N0Ra+CoMhp5PfVspsZpy/c95zg1Q2XhNtAt5PmA==", + "license": "Apache-2.0", + "dependencies": { + "@ably/pubsub-core": "3.0.0-canary.20260917T1031.521a3374" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/@ably/spaces": { "resolved": "..", "link": true @@ -1635,33 +1689,6 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" } }, - "node_modules/ably": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ably/-/ably-2.3.0.tgz", - "integrity": "sha512-4QyN2SEUG1Svpg5LIr/K14U+X9e5Wv/dsldPcPZGwaE1iFVZxl7Ccb6/lcBMn+8Uq0+2q9rzTKFnGERQIRIHVg==", - "dependencies": { - "@ably/msgpack-js": "^0.4.0", - "fastestsmallesttextencoderdecoder": "^1.0.22", - "got": "^11.8.5", - "ulid": "^2.3.0", - "ws": "^8.17.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -2107,6 +2134,15 @@ "node": ">=10" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -2972,17 +3008,6 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "node_modules/jiti": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", - "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -19170,12 +19195,34 @@ "bops": "^1.0.1" } }, + "@ably/pubsub-core": { + "version": "3.0.0-canary.20260917T1031.521a3374", + "resolved": "https://registry.npmjs.org/@ably/pubsub-core/-/pubsub-core-3.0.0-canary.20260917T1031.521a3374.tgz", + "integrity": "sha512-9ZaMCA3ID1Xw7AtkiB/TeytffbXeTVetpPQtWkH7IvyU62w8d+T3MQHAVb1bIgo6HrvFBooKrzQx0e89ZE5R7w==", + "requires": { + "@ably/msgpack-js": "^0.4.0", + "dequal": "^2.0.3", + "fastestsmallesttextencoderdecoder": "^1.0.22", + "got": "^11.8.5", + "ulid": "^2.3.0", + "ws": "^8.17.1" + } + }, + "@ably/pubsub-device": { + "version": "3.0.0-canary.20260917T1031.521a3374", + "resolved": "https://registry.npmjs.org/@ably/pubsub-device/-/pubsub-device-3.0.0-canary.20260917T1031.521a3374.tgz", + "integrity": "sha512-lGmu5B9ncJRb2YH5SyVOeMDBui+ouiyiZe/67bqsgqsVAM2N0Ra+CoMhp5PfVspsZpy/c95zg1Q2XhNtAt5PmA==", + "requires": { + "@ably/pubsub-core": "3.0.0-canary.20260917T1031.521a3374" + } + }, "@ably/spaces": { "version": "file:..", "requires": { + "@ably/pubsub-device": "3.0.0-canary.20260917T1031.521a3374", "@playwright/test": "^1.53.0", "@rollup/plugin-node-resolve": "^15.3.1", - "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-terser": "^1.0.0", "@testing-library/react": "^14.3.1", "@types/express": "^4.17.23", "@types/react": "^18.3.23", @@ -20148,18 +20195,6 @@ "react-refresh": "^0.17.0" } }, - "ably": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ably/-/ably-2.3.0.tgz", - "integrity": "sha512-4QyN2SEUG1Svpg5LIr/K14U+X9e5Wv/dsldPcPZGwaE1iFVZxl7Ccb6/lcBMn+8Uq0+2q9rzTKFnGERQIRIHVg==", - "requires": { - "@ably/msgpack-js": "^0.4.0", - "fastestsmallesttextencoderdecoder": "^1.0.22", - "got": "^11.8.5", - "ulid": "^2.3.0", - "ws": "^8.17.1" - } - }, "acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -20459,6 +20494,11 @@ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, "didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -21095,14 +21135,6 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "jiti": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", - "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", - "dev": true, - "optional": true, - "peer": true - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/demo/package.json b/demo/package.json index 63b26b18..83b9758a 100644 --- a/demo/package.json +++ b/demo/package.json @@ -12,8 +12,8 @@ "deploy:production": "npm run build && netlify deploy --prod" }, "dependencies": { + "@ably/pubsub-device": "3.0.0-canary.20260917T1031.521a3374", "@ably/spaces": "file:..", - "ably": "^2.3.0", "classnames": "^2.3.2", "dayjs": "^1.11.9", "nanoid": "^3.3.11", diff --git a/demo/src/components/Paragraph.tsx b/demo/src/components/Paragraph.tsx index fd8888dd..98876237 100644 --- a/demo/src/components/Paragraph.tsx +++ b/demo/src/components/Paragraph.tsx @@ -1,6 +1,6 @@ import React, { useRef } from 'react'; import cn from 'classnames'; -import { ChannelProvider } from 'ably/react'; +import { ChannelProvider } from '@ably/pubsub-device/react'; import { generateSpaceName, getMemberFirstName, getOutlineClasses, getParamValueFromUrl } from '../utils'; import { StickyLabel } from './StickyLabel'; diff --git a/demo/src/components/Title.tsx b/demo/src/components/Title.tsx index 47dfa38e..692f09c6 100644 --- a/demo/src/components/Title.tsx +++ b/demo/src/components/Title.tsx @@ -1,6 +1,6 @@ import React, { useRef } from 'react'; import cn from 'classnames'; -import { ChannelProvider } from 'ably/react'; +import { ChannelProvider } from '@ably/pubsub-device/react'; import { generateSpaceName, getMemberFirstName, getOutlineClasses, getParamValueFromUrl } from '../utils'; import { LockFilledSvg } from './svg/LockedFilled.tsx'; diff --git a/demo/src/hooks/useTextComponentLock.ts b/demo/src/hooks/useTextComponentLock.ts index b75761a2..26516c8d 100644 --- a/demo/src/hooks/useTextComponentLock.ts +++ b/demo/src/hooks/useTextComponentLock.ts @@ -1,5 +1,5 @@ import { MutableRefObject, useCallback } from 'react'; -import { useChannel } from 'ably/react'; +import { useChannel } from '@ably/pubsub-device/react'; import { useMembers, useLock } from '@ably/spaces/react'; import sanitize from 'sanitize-html'; import { findActiveMember } from '../utils'; diff --git a/demo/src/main.tsx b/demo/src/main.tsx index 30c02d54..991f99f9 100644 --- a/demo/src/main.tsx +++ b/demo/src/main.tsx @@ -6,16 +6,16 @@ import './index.css'; import { SlidesStateContextProvider } from './components/SlidesStateContext.tsx'; import Spaces from '@ably/spaces'; import { SpacesProvider, SpaceProvider } from '@ably/spaces/react'; -import { Realtime } from 'ably'; +import { createClient } from '@ably/pubsub-device'; import { nanoid } from 'nanoid'; import { generateSpaceName, getParamValueFromUrl } from './utils'; -import { AblyProvider } from 'ably/react'; +import { AblyProvider } from '@ably/pubsub-device/react'; const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); const clientId = nanoid(); -const client = new Realtime({ +const client = createClient({ authUrl: `/api/ably-token-request?clientId=${clientId}`, clientId, }); diff --git a/docs/connection-and-channel-management.md b/docs/connection-and-channel-management.md index 1c64aec2..f324d612 100644 --- a/docs/connection-and-channel-management.md +++ b/docs/connection-and-channel-management.md @@ -9,7 +9,7 @@ This document describes how to access a connection and channels on Spaces, and w When initializing the Spaces SDK, an Ably client is passed as a required argument: ```ts -const client = new Realtime({ key: "", clientId: "" }); +const client = createClient({ key: "", clientId: "" }); const spaces = new Spaces(client); ``` diff --git a/docs/react.md b/docs/react.md index 87b55ac0..57177036 100644 --- a/docs/react.md +++ b/docs/react.md @@ -39,11 +39,11 @@ Start by connecting your app to Ably using the `SpacesProvider` component. The `SpacesProvider` should wrap every component that needs to access Spaces. ```jsx -import { Realtime } from "ably"; +import { createClient } from "@ably/pubsub-device"; import Spaces from "@ably/spaces"; import { SpacesProvider, SpaceProvider } from "@ably/spaces/react"; -const ably = new Realtime({ key: "your-ably-api-key", clientId: 'me' }); +const ably = createClient({ key: "your-ably-api-key", clientId: 'me' }); const spaces = new Spaces(ably); root.render( diff --git a/docs/usage.md b/docs/usage.md index c48c4059..18edffbe 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -22,10 +22,10 @@ Spaces is built on top of the [Ably JavaScript SDK](https://github.com/ably/ably ### NPM -You'll need to install both the ably client and the spaces client: +You'll need to install both the Ably Pub/Sub client and the spaces client: ```sh -npm install ably @ably/spaces +npm install @ably/pubsub-device @ably/spaces ``` ### CDN @@ -39,7 +39,7 @@ You can also use Spaces with a CDN like [unpkg](https://www.unpkg.com/): > **Note** > -> If you do this, then replace the call to `new Realtime` in the next section with `new Ably.Realtime`. +> If you do this, then replace the call to `createClient` in the next section with `new Ably.Realtime`. ## Authentication and instantiation @@ -48,10 +48,10 @@ You can pass an Ably client directly to the spaces constructor. The Ably client instantiation accepts client options. You will need at minimum an [Ably API key](#ably-api-key) and a [clientId](https://ably.com/docs/auth/identified-clients?lang=javascripts). A clientId represents an identity of an connection. In most cases this will something like the id of a user: ```ts -import { Realtime } from 'ably'; +import { createClient } from '@ably/pubsub-device'; import Spaces from '@ably/spaces'; -const client = new Realtime({ key: "", clientId: "" }); +const client = createClient({ key: "", clientId: "" }); const spaces = new Spaces(client); ``` diff --git a/examples/avatar-stack.ts b/examples/avatar-stack.ts index 60c1a615..55ef2ce0 100644 --- a/examples/avatar-stack.ts +++ b/examples/avatar-stack.ts @@ -1,10 +1,10 @@ import Spaces from '@ably/spaces'; -import { Realtime } from 'ably'; +import { createClient } from '@ably/pubsub-device'; import { renderAvatars, renderNotification } from './my-application'; // Create Ably client -const client = new Realtime({ authUrl: '', clientId: '' }); +const client = createClient({ authUrl: '', clientId: '' }); // Initialize the Spaces SDK with an Ably client const spaces = new Spaces(client); diff --git a/examples/live-cursors.ts b/examples/live-cursors.ts index 3866866c..614822a9 100644 --- a/examples/live-cursors.ts +++ b/examples/live-cursors.ts @@ -1,10 +1,10 @@ import Spaces from '@ably/spaces'; -import { Realtime } from 'ably'; +import { createClient } from '@ably/pubsub-device'; import renderCursor from './my-application'; // Create Ably client -const client = new Realtime({ authUrl: '', clientId: '' }); +const client = createClient({ authUrl: '', clientId: '' }); // Initialize the Spaces SDK with an Ably client const spaces = new Spaces(client); diff --git a/examples/location.ts b/examples/location.ts index 197caed6..ce1f4ed3 100644 --- a/examples/location.ts +++ b/examples/location.ts @@ -1,10 +1,10 @@ import Spaces from '@ably-labs/spaces'; -import { Realtime } from 'ably'; +import { createClient } from '@ably/pubsub-device'; import updateLocationsForMember from './my-application'; // Create Ably client -const client = new Realtime({ authUrl: '', clientId: '' }); +const client = createClient({ authUrl: '', clientId: '' }); // Initialize the Spaces SDK with an Ably client const spaces = new Spaces(client); diff --git a/examples/locking.ts b/examples/locking.ts index 41fb8148..770e856f 100644 --- a/examples/locking.ts +++ b/examples/locking.ts @@ -1,10 +1,10 @@ import Spaces, { LockStatus } from '@ably/spaces'; -import { Realtime } from 'ably'; +import { createClient } from '@ably/pubsub-device'; import { enableLocationEditing, lockId } from './my-application'; // Create Ably client -const client = new Realtime({ authUrl: '', clientId: '' }); +const client = createClient({ authUrl: '', clientId: '' }); // Initialize the Spaces SDK with an Ably client const spaces = new Spaces(client); diff --git a/examples/locks.ts b/examples/locks.ts index 686f8a5b..651e254d 100644 --- a/examples/locks.ts +++ b/examples/locks.ts @@ -1,6 +1,6 @@ // An example of members locating at and locking elements in a slides // application. -import Ably from 'ably'; +import { createClient } from '@ably/pubsub-device'; import Spaces from '../dist/cjs/Spaces.js'; import { Lock, LockAttributes } from '../dist/cjs/index.js'; @@ -32,7 +32,7 @@ class SlideElement { // define a main async function since we can't use await at the top-level. const main = async () => { info('initialising Ably client'); - const client = new Ably.Realtime({ + const client = createClient({ key: process.env.ABLY_API_KEY, clientId: 'Alice', }); diff --git a/package-lock.json b/package-lock.json index 0416a14c..c1e1b551 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "nanoid": "^3.3.11" }, "devDependencies": { + "@ably/pubsub-device": "3.0.0-canary.20260917T1031.521a3374", "@playwright/test": "^1.53.0", "@rollup/plugin-node-resolve": "^15.3.1", "@rollup/plugin-terser": "^1.0.0", @@ -38,7 +39,7 @@ "vitest": "^3.2.3" }, "peerDependencies": { - "ably": "^2.3.0", + "@ably/pubsub-core": "3.0.0-canary.20260917T1031.521a3374", "react": ">=16.8.0", "react-dom": ">=16.8.0" }, @@ -55,11 +56,64 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/@ably/msgpack-js/-/msgpack-js-0.4.0.tgz", "integrity": "sha512-IPt/BoiQwCWubqoNik1aw/6M/DleMdrxJOUpSja6xmMRbT2p1TA8oqKWgfZabqzrq8emRNeSl/+4XABPNnW5pQ==", - "peer": true, "dependencies": { "bops": "^1.0.1" } }, + "node_modules/@ably/pubsub-core": { + "version": "3.0.0-canary.20260917T1031.521a3374", + "resolved": "https://registry.npmjs.org/@ably/pubsub-core/-/pubsub-core-3.0.0-canary.20260917T1031.521a3374.tgz", + "integrity": "sha512-9ZaMCA3ID1Xw7AtkiB/TeytffbXeTVetpPQtWkH7IvyU62w8d+T3MQHAVb1bIgo6HrvFBooKrzQx0e89ZE5R7w==", + "license": "Apache-2.0", + "dependencies": { + "@ably/msgpack-js": "^0.4.0", + "dequal": "^2.0.3", + "fastestsmallesttextencoderdecoder": "^1.0.22", + "got": "^11.8.5", + "ulid": "^2.3.0", + "ws": "^8.17.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@ably/pubsub-device": { + "version": "3.0.0-canary.20260917T1031.521a3374", + "resolved": "https://registry.npmjs.org/@ably/pubsub-device/-/pubsub-device-3.0.0-canary.20260917T1031.521a3374.tgz", + "integrity": "sha512-lGmu5B9ncJRb2YH5SyVOeMDBui+ouiyiZe/67bqsgqsVAM2N0Ra+CoMhp5PfVspsZpy/c95zg1Q2XhNtAt5PmA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ably/pubsub-core": "3.0.0-canary.20260917T1031.521a3374" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -1440,7 +1494,6 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "peer": true, "engines": { "node": ">=10" }, @@ -1452,7 +1505,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "peer": true, "dependencies": { "defer-to-connect": "^2.0.0" }, @@ -1551,7 +1603,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "peer": true, "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", @@ -1629,8 +1680,7 @@ "node_modules/@types/http-cache-semantics": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "peer": true + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" }, "node_modules/@types/http-errors": { "version": "2.0.5", @@ -1648,7 +1698,6 @@ "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "peer": true, "dependencies": { "@types/node": "*" } @@ -1714,7 +1763,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "peer": true, "dependencies": { "@types/node": "*" } @@ -2141,35 +2189,6 @@ "deprecated": "Use your platform's native atob() and btoa() methods instead", "dev": true }, - "node_modules/ably": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/ably/-/ably-2.9.0.tgz", - "integrity": "sha512-ddaurgvYHGmVVZkd5U2xJgLrbVdtAIw1RunfuZroE/ZTsmK2+vUnAZ7aKhR20cwOFP3QyLFYs6IfvwaijnIPlA==", - "peer": true, - "dependencies": { - "@ably/msgpack-js": "^0.4.0", - "dequal": "^2.0.3", - "fastestsmallesttextencoderdecoder": "^1.0.22", - "got": "^11.8.5", - "ulid": "^2.3.0", - "ws": "^8.17.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2497,7 +2516,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.0.2.tgz", "integrity": "sha512-ZXBDPMt/v/8fsIqn+Z5VwrhdR6jVka0bYobHdGia0Nxi7BJ9i/Uvml3AocHIBtIIBhZjBw5MR0aR4ROs/8+SNg==", - "peer": true, "engines": { "node": ">= 0.4" } @@ -2579,7 +2597,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/bops/-/bops-1.0.1.tgz", "integrity": "sha512-qCMBuZKP36tELrrgXpAfM+gHzqa0nLsWZ+L37ncsb8txYlnAoxOPpVp+g7fK0sGkMXfA0wl8uQkESqw3v4HNag==", - "peer": true, "dependencies": { "base64-js": "1.0.2", "to-utf8": "0.0.1" @@ -2637,7 +2654,6 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "peer": true, "engines": { "node": ">=10.6.0" } @@ -2646,7 +2662,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "peer": true, "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", @@ -2763,7 +2778,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "peer": true, "dependencies": { "mimic-response": "^1.0.0" }, @@ -2989,7 +3003,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "peer": true, "dependencies": { "mimic-response": "^3.1.0" }, @@ -3004,7 +3017,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "peer": true, "engines": { "node": ">=10" }, @@ -3073,7 +3085,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "peer": true, "engines": { "node": ">=10" } @@ -3134,7 +3145,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "peer": true, "engines": { "node": ">=6" } @@ -3235,7 +3245,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "peer": true, "dependencies": { "once": "^1.4.0" } @@ -3999,8 +4008,7 @@ "node_modules/fastestsmallesttextencoderdecoder": { "version": "1.0.22", "resolved": "https://registry.npmjs.org/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz", - "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==", - "peer": true + "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==" }, "node_modules/fastq": { "version": "1.19.1", @@ -4288,7 +4296,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "peer": true, "dependencies": { "pump": "^3.0.0" }, @@ -4397,7 +4404,6 @@ "version": "11.8.6", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "peer": true, "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", @@ -4533,8 +4539,7 @@ "node_modules/http-cache-semantics": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "peer": true + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==" }, "node_modules/http-errors": { "version": "2.0.0", @@ -4570,7 +4575,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "peer": true, "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" @@ -5362,7 +5366,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "peer": true, "engines": { "node": ">=8" } @@ -5584,7 +5587,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "peer": true, "engines": { "node": ">=4" } @@ -5666,7 +5668,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "peer": true, "engines": { "node": ">=10" }, @@ -5845,7 +5846,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "peer": true, "engines": { "node": ">=8" } @@ -6173,7 +6173,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "peer": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -6244,7 +6243,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "peer": true, "engines": { "node": ">=10" }, @@ -6419,8 +6417,7 @@ "node_modules/resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "peer": true + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, "node_modules/resolve-from": { "version": "4.0.0", @@ -6435,7 +6432,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "peer": true, "dependencies": { "lowercase-keys": "^2.0.0" }, @@ -7386,8 +7382,7 @@ "node_modules/to-utf8": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz", - "integrity": "sha512-zks18/TWT1iHO3v0vFp5qLKOG27m67ycq/Y7a7cTiRuUNlc4gf3HGnkRgMv0NyhnfTamtkYBJl+YeD1/j07gBQ==", - "peer": true + "integrity": "sha512-zks18/TWT1iHO3v0vFp5qLKOG27m67ycq/Y7a7cTiRuUNlc4gf3HGnkRgMv0NyhnfTamtkYBJl+YeD1/j07gBQ==" }, "node_modules/toidentifier": { "version": "1.0.1", @@ -7656,7 +7651,6 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.4.0.tgz", "integrity": "sha512-fIRiVTJNcSRmXKPZtGzFQv9WRrZ3M9eoptl/teFJvjOzmpU+/K/JH6HZ8deBfb5vMEpicJcLn7JmvdknlMq7Zg==", - "peer": true, "bin": { "ulid": "bin/cli.js" } diff --git a/package.json b/package.json index 6082e924..1cb778c9 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ }, "keywords": [], "devDependencies": { + "@ably/pubsub-device": "3.0.0-canary.20260917T1031.521a3374", "@playwright/test": "^1.53.0", "@rollup/plugin-node-resolve": "^15.3.1", "@rollup/plugin-terser": "^1.0.0", @@ -67,7 +68,7 @@ "nanoid": "^3.3.11" }, "peerDependencies": { - "ably": "^2.3.0", + "@ably/pubsub-core": "3.0.0-canary.20260917T1031.521a3374", "react": ">=16.8.0", "react-dom": ">=16.8.0" }, diff --git a/rollup.config.mjs b/rollup.config.mjs index 313b7b5e..f846a53a 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -8,11 +8,11 @@ export default { name: 'Spaces', file: 'dist/iife/index.bundle.js', globals: { - ably: 'Ably', + '@ably/pubsub-core': 'Ably', }, compact: true, plugins: [terser()], }, - external: ['ably'], + external: ['@ably/pubsub-core'], plugins: [nodeResolve({ browser: true })], }; diff --git a/src/CursorBatching.ts b/src/CursorBatching.ts index d782b786..649fc0b2 100644 --- a/src/CursorBatching.ts +++ b/src/CursorBatching.ts @@ -1,4 +1,4 @@ -import { RealtimeChannel } from 'ably'; +import { RealtimeChannel } from '@ably/pubsub-core'; import { CURSOR_UPDATE } from './CursorConstants.js'; import type { CursorUpdate } from './types.js'; diff --git a/src/CursorHistory.ts b/src/CursorHistory.ts index 580226d1..ac644036 100644 --- a/src/CursorHistory.ts +++ b/src/CursorHistory.ts @@ -1,4 +1,4 @@ -import { InboundMessage, PaginatedResult, RealtimeChannel } from 'ably'; +import { InboundMessage, PaginatedResult, RealtimeChannel } from '@ably/pubsub-core'; import type { CursorUpdate } from './types.js'; import type { CursorsOptions } from './types.js'; diff --git a/src/Cursors.test.ts b/src/Cursors.test.ts index 383f4ae8..f4d68515 100644 --- a/src/Cursors.test.ts +++ b/src/Cursors.test.ts @@ -1,5 +1,5 @@ import { it, describe, expect, vi, beforeEach, vitest, afterEach } from 'vitest'; -import { Realtime, RealtimeClient, RealtimeChannel } from 'ably'; +import { Realtime, RealtimeClient, RealtimeChannel } from '@ably/pubsub-core'; import Space from './Space.js'; import Cursors from './Cursors.js'; @@ -25,7 +25,7 @@ interface CursorsTestContext { fakeMessageStub: RealtimeInboundMessage; } -vi.mock('ably'); +vi.mock('@ably/pubsub-core'); function createPresenceCount(length: number) { return async () => Array.from({ length }, (_, i) => createPresenceMessage('enter', { clientId: '' + i })); diff --git a/src/Cursors.ts b/src/Cursors.ts index 8cf17a16..106e815b 100644 --- a/src/Cursors.ts +++ b/src/Cursors.ts @@ -1,4 +1,4 @@ -import { RealtimeChannel } from 'ably'; +import { RealtimeChannel } from '@ably/pubsub-core'; import Space from './Space.js'; import CursorBatching from './CursorBatching.js'; diff --git a/src/Errors.ts b/src/Errors.ts index 5572191b..fb2d8a8c 100644 --- a/src/Errors.ts +++ b/src/Errors.ts @@ -1,4 +1,4 @@ -import { ErrorInfo } from 'ably'; +import { ErrorInfo } from '@ably/pubsub-core'; export const ERR_SPACE_NAME_MISSING = () => new ErrorInfo('must have a non-empty name for the space', 101000, 400); diff --git a/src/Locations.test.ts b/src/Locations.test.ts index c5509e3d..1a2c61f1 100644 --- a/src/Locations.test.ts +++ b/src/Locations.test.ts @@ -1,5 +1,5 @@ import { it, describe, expect, vi, beforeEach } from 'vitest'; -import { PresenceMessage, Realtime, RealtimeClient, RealtimePresence } from 'ably'; +import { PresenceMessage, Realtime, RealtimeClient, RealtimePresence } from '@ably/pubsub-core'; import Space from './Space.js'; @@ -17,7 +17,7 @@ interface SpaceTestContext { presenceMap: Map; } -vi.mock('ably'); +vi.mock('@ably/pubsub-core'); vi.mock('nanoid'); describe('Locations', () => { diff --git a/src/Locks.test.ts b/src/Locks.test.ts index 409bf00a..76c847d3 100644 --- a/src/Locks.test.ts +++ b/src/Locks.test.ts @@ -1,5 +1,5 @@ import { it, describe, expect, vi, beforeEach } from 'vitest'; -import { PresenceMessage, Realtime, RealtimeClient, RealtimePresence } from 'ably'; +import { PresenceMessage, Realtime, RealtimeClient, RealtimePresence } from '@ably/pubsub-core'; import Space from './Space.js'; import type { SpaceMember, LockStatus } from './types.js'; @@ -12,7 +12,7 @@ interface SpaceTestContext { presenceMap: Map; } -vi.mock('ably'); +vi.mock('@ably/pubsub-core'); describe('Locks', () => { beforeEach((context) => { diff --git a/src/Locks.ts b/src/Locks.ts index 8d73a21f..45b77702 100644 --- a/src/Locks.ts +++ b/src/Locks.ts @@ -1,4 +1,4 @@ -import { PresenceMessage } from 'ably'; +import { PresenceMessage } from '@ably/pubsub-core'; import Space from './Space.js'; import type { Lock, SpaceMember } from './types.js'; diff --git a/src/Members.test.ts b/src/Members.test.ts index 2cb1b853..94f0eb2f 100644 --- a/src/Members.test.ts +++ b/src/Members.test.ts @@ -1,5 +1,5 @@ import { it, describe, expect, vi, beforeEach, afterEach } from 'vitest'; -import { PresenceMessage, Realtime, RealtimeClient, RealtimePresence } from 'ably'; +import { PresenceMessage, Realtime, RealtimeClient, RealtimePresence } from '@ably/pubsub-core'; import Space from './Space.js'; @@ -12,7 +12,7 @@ interface SpaceTestContext { presenceMap: Map; } -vi.mock('ably'); +vi.mock('@ably/pubsub-core'); vi.mock('nanoid'); describe('Members', () => { diff --git a/src/Space.test.ts b/src/Space.test.ts index b6adfaa3..ecb8a88e 100644 --- a/src/Space.test.ts +++ b/src/Space.test.ts @@ -1,5 +1,5 @@ import { it, describe, expect, vi, beforeEach, expectTypeOf } from 'vitest'; -import { PresenceMessage, Realtime, RealtimeClient, RealtimePresence } from 'ably'; +import { PresenceMessage, Realtime, RealtimeClient, RealtimePresence } from '@ably/pubsub-core'; import Space from './Space.js'; import Locations from './Locations.js'; @@ -20,7 +20,7 @@ interface SpaceTestContext { presenceMap: Map; } -vi.mock('ably'); +vi.mock('@ably/pubsub-core'); vi.mock('nanoid'); describe('Space', () => { diff --git a/src/Space.ts b/src/Space.ts index 2e505dee..89096e82 100644 --- a/src/Space.ts +++ b/src/Space.ts @@ -1,4 +1,4 @@ -import { PresenceMessage, Realtime, RealtimeClient, RealtimeChannel } from 'ably'; +import { PresenceMessage, Realtime, RealtimeClient, RealtimeChannel } from '@ably/pubsub-core'; import EventEmitter, { InvalidArgumentError, inspect, type EventListener } from './utilities/EventEmitter.js'; import Locations from './Locations.js'; diff --git a/src/SpaceUpdate.ts b/src/SpaceUpdate.ts index 91e646a8..9a7ab353 100644 --- a/src/SpaceUpdate.ts +++ b/src/SpaceUpdate.ts @@ -1,5 +1,5 @@ import { nanoid } from 'nanoid'; -import { PresenceMessage } from 'ably'; +import { PresenceMessage } from '@ably/pubsub-core'; import type { SpaceMember, ProfileData } from './types.js'; import type { PresenceMember } from './utilities/types.js'; diff --git a/src/Spaces.test.ts b/src/Spaces.test.ts index 326fa4c8..a73b21a9 100644 --- a/src/Spaces.test.ts +++ b/src/Spaces.test.ts @@ -1,5 +1,5 @@ import { it, describe, expect, expectTypeOf, vi, beforeEach } from 'vitest'; -import { Realtime, RealtimeClient } from 'ably'; +import { Realtime, RealtimeClient } from '@ably/pubsub-core'; import Spaces, { type ClientWithOptions } from './Spaces.js'; @@ -7,7 +7,7 @@ interface SpacesTestContext { client: ClientWithOptions; } -vi.mock('ably'); +vi.mock('@ably/pubsub-core'); describe('Spaces', () => { beforeEach((context) => { diff --git a/src/Spaces.ts b/src/Spaces.ts index 1ffe3bef..bda4e3fb 100644 --- a/src/Spaces.ts +++ b/src/Spaces.ts @@ -1,4 +1,4 @@ -import { RealtimeClient, Connection } from 'ably'; +import { RealtimeClient, Connection } from '@ably/pubsub-core'; import { ERR_SPACE_NAME_MISSING } from './Errors.js'; import Space from './Space.js'; diff --git a/src/react/useChannelState.ts b/src/react/useChannelState.ts index 44c1bdf0..7a44f2a3 100644 --- a/src/react/useChannelState.ts +++ b/src/react/useChannelState.ts @@ -1,7 +1,7 @@ import { useState } from 'react'; import { useEventListener } from './useEventListener.js'; -import type { ChannelState, ChannelStateChange, ErrorInfo, EventEmitter } from 'ably'; +import type { ChannelState, ChannelStateChange, ErrorInfo, EventEmitter } from '@ably/pubsub-core'; type ChannelStateListener = (stateChange: ChannelStateChange) => void; @@ -9,7 +9,7 @@ const failedStateEvents: ChannelState[] = ['suspended', 'failed', 'detached']; const successStateEvents: ChannelState[] = ['attached']; /** - * todo use `ably/react` hooks instead + * todo use `@ably/pubsub-core/react` hooks instead */ export const useChannelState = ( emitter?: EventEmitter, diff --git a/src/react/useConnectionState.ts b/src/react/useConnectionState.ts index 4b5315b9..ab2c5230 100644 --- a/src/react/useConnectionState.ts +++ b/src/react/useConnectionState.ts @@ -1,7 +1,7 @@ import { useState } from 'react'; import { useEventListener } from './useEventListener.js'; -import type { ConnectionState, ConnectionStateChange, ErrorInfo, EventEmitter } from 'ably'; +import type { ConnectionState, ConnectionStateChange, ErrorInfo, EventEmitter } from '@ably/pubsub-core'; type ConnectionStateListener = (stateChange: ConnectionStateChange) => void; diff --git a/src/react/useCursors.test.tsx b/src/react/useCursors.test.tsx index 766df2af..e292709f 100644 --- a/src/react/useCursors.test.tsx +++ b/src/react/useCursors.test.tsx @@ -3,7 +3,7 @@ */ import React from 'react'; -import { Realtime } from 'ably'; +import { Realtime } from '@ably/pubsub-core'; import { it, beforeEach, describe, expect, vi } from 'vitest'; import { waitFor, renderHook, act } from '@testing-library/react'; import { SpacesProvider } from './contexts/SpacesContext.js'; @@ -12,7 +12,7 @@ import Spaces from '../index.js'; import Space from '../Space.js'; import { createPresenceEvent } from '../utilities/test/fakes.js'; import { useCursors } from './useCursors.js'; -import type { PresenceMessage } from 'ably'; +import type { PresenceMessage } from '@ably/pubsub-core'; interface SpaceTestContext { spaces: Spaces; @@ -20,7 +20,7 @@ interface SpaceTestContext { presenceMap: Map; } -vi.mock('ably'); +vi.mock('@ably/pubsub-core'); vi.mock('nanoid'); describe('useCursors', () => { diff --git a/src/react/useCursors.ts b/src/react/useCursors.ts index 72fd9b28..2d36feaf 100644 --- a/src/react/useCursors.ts +++ b/src/react/useCursors.ts @@ -6,7 +6,7 @@ import { useConnectionState } from './useConnectionState.js'; import { isFunction } from '../utilities/is.js'; import type { CursorUpdate, SpaceMember } from '../types.js'; -import type { ErrorInfo } from 'ably'; +import type { ErrorInfo } from '@ably/pubsub-core'; import type Cursors from '../Cursors.js'; import type { UseSpaceOptions } from './types.js'; import type { Space } from '..'; diff --git a/src/react/useEventListener.ts b/src/react/useEventListener.ts index d999e9b8..5cbe0ded 100644 --- a/src/react/useEventListener.ts +++ b/src/react/useEventListener.ts @@ -1,11 +1,17 @@ import { useEffect, useRef } from 'react'; -import type { ChannelState, ChannelStateChange, ConnectionState, ConnectionStateChange, EventEmitter } from 'ably'; +import type { + ChannelState, + ChannelStateChange, + ConnectionState, + ConnectionStateChange, + EventEmitter, +} from '@ably/pubsub-core'; type EventListener = (stateChange: T) => void; /** - * todo use `ably/react` hooks instead + * todo use `@ably/pubsub-core/react` hooks instead */ export const useEventListener = < S extends ConnectionState | ChannelState, diff --git a/src/react/useLocations.test.tsx b/src/react/useLocations.test.tsx index 2167571e..6f895721 100644 --- a/src/react/useLocations.test.tsx +++ b/src/react/useLocations.test.tsx @@ -3,12 +3,12 @@ */ import React from 'react'; -import { Realtime } from 'ably'; +import { Realtime } from '@ably/pubsub-core'; import { it, beforeEach, describe, expect, vi } from 'vitest'; import { waitFor, renderHook } from '@testing-library/react'; import { SpacesProvider } from './contexts/SpacesContext.js'; import { SpaceProvider } from './contexts/SpaceContext.js'; -import type { PresenceMessage } from 'ably'; +import type { PresenceMessage } from '@ably/pubsub-core'; import Spaces from '../index.js'; import { createLocationUpdate, createPresenceEvent } from '../utilities/test/fakes.js'; import Space from '../Space.js'; @@ -20,7 +20,7 @@ interface SpaceTestContext { presenceMap: Map; } -vi.mock('ably'); +vi.mock('@ably/pubsub-core'); vi.mock('nanoid'); describe('useLocations', () => { diff --git a/src/react/useLocks.test.tsx b/src/react/useLocks.test.tsx index ba27abfd..e8dcbc4a 100644 --- a/src/react/useLocks.test.tsx +++ b/src/react/useLocks.test.tsx @@ -3,12 +3,12 @@ */ import React from 'react'; -import { Realtime } from 'ably'; +import { Realtime } from '@ably/pubsub-core'; import { it, beforeEach, describe, expect, vi } from 'vitest'; import { waitFor, renderHook } from '@testing-library/react'; import { SpacesProvider } from './contexts/SpacesContext.js'; import { SpaceProvider } from './contexts/SpaceContext.js'; -import type { PresenceMessage } from 'ably'; +import type { PresenceMessage } from '@ably/pubsub-core'; import Spaces from '../index.js'; import { createPresenceEvent } from '../utilities/test/fakes.js'; import Space from '../Space.js'; @@ -20,7 +20,7 @@ interface SpaceTestContext { presenceMap: Map; } -vi.mock('ably'); +vi.mock('@ably/pubsub-core'); vi.mock('nanoid'); describe('useLocks', () => { diff --git a/src/react/useMembers.test.tsx b/src/react/useMembers.test.tsx index 44cf7cc7..541b2c4d 100644 --- a/src/react/useMembers.test.tsx +++ b/src/react/useMembers.test.tsx @@ -3,12 +3,12 @@ */ import React from 'react'; -import { Realtime } from 'ably'; +import { Realtime } from '@ably/pubsub-core'; import { it, beforeEach, describe, expect, vi } from 'vitest'; import { waitFor, renderHook } from '@testing-library/react'; import { SpacesProvider } from './contexts/SpacesContext.js'; import { SpaceProvider } from './contexts/SpaceContext.js'; -import type { PresenceMessage } from 'ably'; +import type { PresenceMessage } from '@ably/pubsub-core'; import Spaces from '../index.js'; import { useMembers } from './useMembers.js'; import { createLocationUpdate, createPresenceEvent } from '../utilities/test/fakes.js'; @@ -20,7 +20,7 @@ interface SpaceTestContext { presenceMap: Map; } -vi.mock('ably'); +vi.mock('@ably/pubsub-core'); vi.mock('nanoid'); describe('useMembers', () => { diff --git a/src/react/useMembers.ts b/src/react/useMembers.ts index 43da8b34..2a2eb96a 100644 --- a/src/react/useMembers.ts +++ b/src/react/useMembers.ts @@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from 'react'; import { useSpace } from './useSpace.js'; import { isArray, isFunction, isString } from '../utilities/is.js'; -import type { ErrorInfo } from 'ably'; +import type { ErrorInfo } from '@ably/pubsub-core'; import type { Space, SpaceMember } from '..'; import type { UseSpaceOptions } from './types.js'; import type { MembersEventMap } from '../Members.js'; diff --git a/src/react/useSpace.test.tsx b/src/react/useSpace.test.tsx index af12bd6a..b50be18c 100644 --- a/src/react/useSpace.test.tsx +++ b/src/react/useSpace.test.tsx @@ -3,7 +3,7 @@ */ import React from 'react'; -import { Realtime } from 'ably'; +import { Realtime } from '@ably/pubsub-core'; import { it, beforeEach, describe, expect, vi } from 'vitest'; import { waitFor, renderHook } from '@testing-library/react'; import { SpacesProvider } from './contexts/SpacesContext.js'; @@ -15,7 +15,7 @@ interface SpaceTestContext { spaces: Spaces; } -vi.mock('ably'); +vi.mock('@ably/pubsub-core'); vi.mock('nanoid'); describe('useSpace', () => { diff --git a/src/react/useSpace.ts b/src/react/useSpace.ts index edc34135..c655c0e5 100644 --- a/src/react/useSpace.ts +++ b/src/react/useSpace.ts @@ -3,7 +3,7 @@ import { SpaceContext } from './contexts/SpaceContext.js'; import { useChannelState } from './useChannelState.js'; import { useConnectionState } from './useConnectionState.js'; -import type { ErrorInfo } from 'ably'; +import type { ErrorInfo } from '@ably/pubsub-core'; import type { Space } from '..'; import type { UseSpaceCallback, UseSpaceOptions } from './types.js'; diff --git a/src/types.ts b/src/types.ts index e5866a48..f6928a0a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,4 @@ -import { ErrorInfo, PresenceAction } from 'ably'; +import { ErrorInfo, PresenceAction } from '@ably/pubsub-core'; import type { LockAttributes } from './Locks.js'; /** diff --git a/src/utilities/test/fakes.ts b/src/utilities/test/fakes.ts index 789ec52d..8708a401 100644 --- a/src/utilities/test/fakes.ts +++ b/src/utilities/test/fakes.ts @@ -1,4 +1,4 @@ -import { PresenceMessage } from 'ably'; +import { PresenceMessage } from '@ably/pubsub-core'; import Space from '../../Space.js'; diff --git a/src/utilities/types.ts b/src/utilities/types.ts index 22eada31..f58df5ac 100644 --- a/src/utilities/types.ts +++ b/src/utilities/types.ts @@ -1,4 +1,4 @@ -import type { InboundMessage, PresenceMessage } from 'ably'; +import type { InboundMessage, PresenceMessage } from '@ably/pubsub-core'; import type { ProfileData, Lock } from '../types.js'; diff --git a/test/cdn-bundle/resources/test.html b/test/cdn-bundle/resources/test.html index 556d75f5..005ad672 100644 --- a/test/cdn-bundle/resources/test.html +++ b/test/cdn-bundle/resources/test.html @@ -7,7 +7,7 @@