From a25b63ec43eefb45a2d586603c1159d8cddfed9d Mon Sep 17 00:00:00 2001 From: Mohit Tejani <60129002+mohitpubnub@users.noreply.github.com> Date: Fri, 16 Oct 2026 07:03:48 +0000 Subject: [PATCH 1/9] Revise README for SDK enhancements and installation Updated README to reflect SDK support for TypeScript and various environments, added installation instructions, and improved clarity on usage examples. --- README.md | 252 ++++++++++++++++++++++++------------------------------ 1 file changed, 112 insertions(+), 140 deletions(-) diff --git a/README.md b/README.md index 8ba2b8b31..5d7489a8c 100644 --- a/README.md +++ b/README.md @@ -1,170 +1,142 @@ image -# PubNub JavaScript SDK +# PubNub JavaScript and TypeScript SDK -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/2859917905c549b8bfa27630ff276fce)](https://www.codacy.com/app/PubNub/javascript?utm_source=github.com&utm_medium=referral&utm_content=pubnub/javascript&utm_campaign=Badge_Grade) -[![npm](https://img.shields.io/npm/v/pubnub.svg)]() -[![Bower](https://img.shields.io/bower/v/pubnub.svg)]() -[![Known Vulnerabilities](https://snyk.io/test/npm/pubnub/badge.svg)](https://snyk.io/test/npm/pubnub) +[![npm](https://img.shields.io/npm/v/pubnub.svg)](https://www.npmjs.com/package/pubnub) -This is the official PubNub JavaScript SDK repository. +This is the official PubNub SDK for browsers, Node.js, React, React Native, Angular, Vue, and other JavaScript or TypeScript applications. -PubNub takes care of the infrastructure and APIs needed for the realtime communication layer of your application. Work on your app's logic and let PubNub handle sending and receiving data across the world in less than 100ms. +[Documentation](https://www.pubnub.com/docs/sdks/javascript) · [API reference](https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe) · [Changelog](https://www.pubnub.com/docs/sdks/javascript/changelog) -## Get keys +## Requirements -You will need the publish and subscribe keys to authenticate your app. Get your keys from the [Admin Portal](https://dashboard.pubnub.com/login). +- **Node.js:** [22 or later](https://www.pubnub.com/docs/sdks/javascript/environment-setup) +- **Supported environments:** [Modern browsers, Node.js, React, React Native, Angular, Vue, and other JavaScript/TypeScript environments](https://www.pubnub.com/docs/sdks/javascript) +- **React Native:** Install `react-native-url-polyfill` alongside `pubnub` when using React Native. -## Tutorial Video +## Installation -[![Getting Started with PubNub JS SDK](https://replayable-api-production.herokuapp.com/replay/64ee0d2ca4bc310061f566ca/gif?shareKey=8YQoHC40jdzYpYGpcJhQ)](https://app.dashcam.io/replay/64ee0d2ca4bc310061f566ca?share=8YQoHC40jdzYpYGpcJhQ) +From your JavaScript project's root directory: -Watch [Getting Started with PubNub JS SDK](https://app.dashcam.io/replay/64ee0d2ca4bc310061f566ca?share=8YQoHC40jdzYpYGpcJhQ) on Dashcam - -## Configure PubNub +```sh +npm install pubnub +``` -1. Integrate the JavaScript SDK into your project: - * use `npm`: - ``` - npm install pubnub - ``` - * or download one of our builds from our CDN: - * https://cdn.pubnub.com/sdk/javascript/pubnub.13.1.2.js - * https://cdn.pubnub.com/sdk/javascript/pubnub.13.1.2.min.js +See [Environment setup](https://www.pubnub.com/docs/sdks/javascript/environment-setup) for toolchain and platform details. - > **React Native:** the SDK relies on a global `URL` implementation, which React Native does not - > provide, so it depends on [`react-native-url-polyfill`](https://www.npmjs.com/package/react-native-url-polyfill). - > This is declared as an **optional peer dependency** — only React Native projects need it, while - > Node.js and browser consumers are unaffected. Install it alongside the SDK: - > - > ``` - > npm install react-native-url-polyfill - > ``` - > - > The SDK loads the polyfill automatically (`import 'react-native-url-polyfill/auto'`), so no extra - > import is required once the package is installed. +## Example -2. Configure your keys: +This example runs on Node.js 22 or later. - ```javascript - pubnub = new PubNub({ - publishKey: 'myPublishKey', - subscribeKey: 'mySubscribeKey', - userId: 'myUniqueUserId', - }); - ``` +If Access Manager is enabled, obtain a token from your trusted backend and call `pubnub.setToken(token)` before accessing protected resources. Keep the secret key and token-granting logic on the backend. -## Add event listeners +Create `index.js` in the project root and add: ```javascript -// create a subscription from a channel entity -const channel = pubnub.channel('my_channel'); -const subscription = channel.subscription(); -subscription.subscribe(); +const PubNub = require("pubnub"); -// Event-specific listeners -subscription.onMessage = (messageEvent) => { console.log("Message event: ", messageEvent); }; -subscription.onPresence = (presenceEvent) => { console.log("Presence event: ", presenceEvent); }; -subscription.onMessage = (messageEvent) => { console.log("Message event: ", messageEvent); }; -subscription.onPresence = (presenceEvent) => { console.log("Presence event: ", presenceEvent); }; -subscription.onSignal = (signalEvent) => { console.log("Signal event: ", signalEvent); }; -subscription.onObjects = (objectsEvent) => { console.log("Objects event: ", objectsEvent); }; -subscription.onMessageAction = (messageActionEvent) => { console.log("Message Action event: ", messageActionEvent); }; -subscription.onFile = (fileEvent) => { console.log("File event: ", fileEvent); }; - -// Generic listeners -subscription.addListener({ - // Messages - message: function (m) { - const channelName = m.channel; // Channel on which the message was published - const channelGroup = m.subscription; // Channel group or wildcard subscription match (if exists) - const pubTT = m.timetoken; // Publish timetoken - const msg = m.message; // Message payload - const publisher = m.publisher; // Message publisher - }, - // Presence - // requires a subscription with presence - presence: function (p) { - const action = p.action; // Can be join, leave, state-change, or timeout - const channelName = p.channel; // Channel to which the message belongs - const occupancy = p.occupancy; // Number of users subscribed to the channel - const state = p.state; // User state - const channelGroup = p.subscription; // Channel group or wildcard subscription match, if any - const publishTime = p.timestamp; // Publish timetoken - const timetoken = p.timetoken; // Current timetoken - const uuid = p.uuid; // UUIDs of users who are subscribed to the channel - }, - // Signals - signal: function (s) { - const channelName = s.channel; // Channel to which the signal belongs - const channelGroup = s.subscription; // Channel group or wildcard subscription match, if any - const pubTT = s.timetoken; // Publish timetoken - const msg = s.message; // Payload - const publisher = s.publisher; // Message publisher - }, - // App Context - objects: (objectEvent) => { - const channel = objectEvent.channel; // Channel to which the event belongs - const channelGroup = objectEvent.subscription; // Channel group - const timetoken = objectEvent.timetoken; // Event timetoken - const publisher = objectEvent.publisher; // UUID that made the call - const event = objectEvent.event; // Name of the event that occurred - const type = objectEvent.type; // Type of the event that occurred - const data = objectEvent.data; // Data from the event that occurred - }, - // Message Reactions - messageAction: function (ma) { - const channelName = ma.channel; // Channel to which the message belongs - const publisher = ma.publisher; // Message publisher - const event = ma.event; // Message action added or removed - const type = ma.data.type; // Message action type - const value = ma.data.value; // Message action value - const messageTimetoken = ma.data.messageTimetoken; // Timetoken of the original message - const actionTimetoken = ma.data.actionTimetoken; // Timetoken of the message action +const pubnub = new PubNub({ + publishKey: "YOUR_PUBLISH_KEY", + subscribeKey: "YOUR_SUBSCRIBE_KEY", + userId: "hello-world-user", +}); + +const subscription = pubnub.channel("hello_world").subscription(); +let published = false; + +subscription.onMessage = (event) => { + console.log(event.message); + + subscription.unsubscribe(); + pubnub.removeAllListeners(); + pubnub.destroy(); +}; + +pubnub.addListener({ + status: async (status) => { + if (status.category === "PNConnectedCategory" && !published) { + published = true; + + await pubnub.publish({ + channel: "hello_world", + message: "Hello world", + }); + } }, - // File Sharing - file: function (event) { - const channelName = event.channel; // Channel to which the file belongs - const channelGroup = event.subscription; // Channel group or wildcard subscription match (if exists) - const publisher = event.publisher; // File publisher - const timetoken = event.timetoken; // Event timetoken - - const message = event.message; // Optional message attached to the file - const fileId = event.file.id; // File unique id - const fileName = event.file.name;// File name - const fileUrl = event.file.url; // File direct URL - } }); + +subscription.subscribe(); ``` -## Publish/subscribe +Run the example: -```javascript -const channel = pubnub.channel('my_channel'); -const subscription = channel.subscription(); -subscription.subscribe(); +```sh +node index.js +``` + +The terminal prints: -try { - const result = await pubnub.publish({ - message: { - such: "object", - }, - channel: "my_channel", - sendByPost: false, // true to send via post - storeInHistory: false, //override default Message Persistence options - meta: { - cool: "meta", - }, // publish extra meta with the request - }); -} catch (status) { - console.log(status); -} +```text +Hello world ``` -## Documentation +The example calls `subscription.unsubscribe()`, `pubnub.removeAllListeners()`, and `pubnub.destroy()` after receiving the message. Reuse one PubNub client for the user/session rather than creating a client for every operation. + +## Next steps + +See the [JavaScript SDK documentation](https://www.pubnub.com/docs/sdks/javascript). + +| Next step | Documentation | +| --- | --- | +| Configure the client | [Configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration) | +| Work with subscriptions and messages | [Publish & Subscribe](https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe) | +| Check channel occupancy | [Presence](https://www.pubnub.com/docs/sdks/javascript/api-reference/presence) | +| Read message history | [Message Persistence](https://www.pubnub.com/docs/sdks/javascript/api-reference/storage-and-playback) | + +## Access Manager + +[Access Manager](https://www.pubnub.com/docs/sdks/javascript/api-reference/access-manager) + +## Client lifetime + +Create one PubNub instance and reuse it for the lifetime of the user or application session. Call `subscription.unsubscribe()` when an individual subscription is no longer needed, `pubnub.unsubscribeAll()` to stop all subscriptions, `pubnub.removeAllListeners()` when registered listeners are no longer required, and `pubnub.destroy()` when the client itself is no longer needed. + +## Delivery + +Live delivery through PubNub SDKs is at-most-once. A subscriber can miss messages if its buffer overflows or if it is disconnected when a message is published. For recovery after longer gaps, see [Message Persistence](https://www.pubnub.com/docs/sdks/javascript/api-reference/storage-and-playback). + +## Troubleshooting + +### React Native reports URL-related errors + +Install `react-native-url-polyfill` alongside `pubnub`. The SDK no longer bundles this dependency. See [JavaScript Environment Setup](https://www.pubnub.com/docs/sdks/javascript/environment-setup). + +### Access Manager grant APIs are unavailable in a browser build + +Issue tokens from a trusted backend and call `pubnub.setToken(token)` in the client. The prebuilt browser SDK deliberately disables the Access Manager server module and secret-key functionality. See [Configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration). + +### Hot reload and server rendering + +Reuse the PubNub client and subscription across renders. In React, create them in lifecycle/application code and unsubscribe, remove listeners, and destroy an owned client from the corresponding cleanup instead of creating another client on every render. + +Further troubleshooting: [JavaScript SDK documentation](https://www.pubnub.com/docs/sdks/javascript). + +## Changelog and upgrades + +[Changelog](https://www.pubnub.com/docs/sdks/javascript/changelog) + +For a major version change, review the SDK-specific migration guidance linked from the JavaScript documentation and the [JavaScript SDK changelog](https://www.pubnub.com/docs/sdks/javascript/changelog) for breaking changes introduced after that guide. + +## Contributing + +Report bugs and request features in the [issue tracker](https://github.com/pubnub/javascript/issues). + +Install the repository dependencies, run the relevant build and test commands for the affected package/platform, and include tests for behavioral changes before opening a pull request. + +## License + +[PubNub Software Development Kit License Agreement](https://github.com/pubnub/javascript/blob/master/LICENSE) -* [Build your first realtime JS app with PubNub](https://www.pubnub.com/tutorials/real-time-data-streaming/) -* [API reference for JavaScript](https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe) ## Support From c46a35da54236b4b6b9f0e445aa65aff7b821cd0 Mon Sep 17 00:00:00 2001 From: Mohit Tejani <60129002+mohitpubnub@users.noreply.github.com> Date: Mon, 19 Oct 2026 10:40:44 +0530 Subject: [PATCH 2/9] Revise README.md for clarity and additional information Updated the README.md to enhance clarity and add new sections for quickstart, troubleshooting, and support. Improved formatting for better readability. --- README.md | 89 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 5d7489a8c..4244eeb86 100644 --- a/README.md +++ b/README.md @@ -3,16 +3,19 @@ # PubNub JavaScript and TypeScript SDK [![npm](https://img.shields.io/npm/v/pubnub.svg)](https://www.npmjs.com/package/pubnub) +PubNub provides global infrastructure for real-time, interactive applications. -This is the official PubNub SDK for browsers, Node.js, React, React Native, Angular, Vue, and other JavaScript or TypeScript applications. +Publish and receive messages in JavaScript and TypeScript. Use this SDK for browsers, Node.js, React, React Native, Angular, Vue, and other JavaScript or TypeScript applications. -[Documentation](https://www.pubnub.com/docs/sdks/javascript) · [API reference](https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe) · [Changelog](https://www.pubnub.com/docs/sdks/javascript/changelog) +[Documentation](https://www.pubnub.com/docs/sdks/javascript) · [API reference](https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe) · [Changelog](https://www.pubnub.com/docs/sdks/javascript/changelog) · [Support](https://support.pubnub.com/) ## Requirements -- **Node.js:** [22 or later](https://www.pubnub.com/docs/sdks/javascript/environment-setup) -- **Supported environments:** [Modern browsers, Node.js, React, React Native, Angular, Vue, and other JavaScript/TypeScript environments](https://www.pubnub.com/docs/sdks/javascript) -- **React Native:** Install `react-native-url-polyfill` alongside `pubnub` when using React Native. +| Requirement | Supported version or setup | +| --- | --- | +| Node.js | [22 or later](https://www.pubnub.com/docs/sdks/javascript/environment-setup) | +| Supported environments | [Modern browsers, Node.js, React, React Native, Angular, Vue, and other JavaScript/TypeScript environments](https://www.pubnub.com/docs/sdks/javascript) | +| React Native | Install `react-native-url-polyfill` alongside `pubnub` when using React Native. | ## Installation @@ -22,16 +25,33 @@ From your JavaScript project's root directory: npm install pubnub ``` -See [Environment setup](https://www.pubnub.com/docs/sdks/javascript/environment-setup) for toolchain and platform details. +Or download one of our builds from our CDN: + +- https://cdn.pubnub.com/sdk/javascript/pubnub.13.1.2.js +- https://cdn.pubnub.com/sdk/javascript/pubnub.13.1.2.min.js + +For other installation methods, see [environment setup](https://www.pubnub.com/docs/sdks/javascript/environment-setup). + +## Quickstart + +This example runs in Node.js 22 or later. It subscribes to hello_world, publishes one message, and prints the received text. + +### Get your keys -## Example +Open the [PubNub Admin Portal](https://admin.pubnub.com/). -This example runs on Node.js 22 or later. +Create an app and a keyset for development, or select an existing development keyset. + +Copy its publish key and subscribe key. If Access Manager is enabled, obtain a token from your trusted backend and call `pubnub.setToken(token)` before accessing protected resources. Keep the secret key and token-granting logic on the backend. +### Send and receive a message + Create `index.js` in the project root and add: +Replace the key placeholders. Use a User ID that identifies the user or device in your app. + ```javascript const PubNub = require("pubnub"); @@ -68,13 +88,13 @@ pubnub.addListener({ subscription.subscribe(); ``` -Run the example: +### Run the example ```sh node index.js ``` -The terminal prints: +The terminal should show: ```text Hello world @@ -82,60 +102,59 @@ Hello world The example calls `subscription.unsubscribe()`, `pubnub.removeAllListeners()`, and `pubnub.destroy()` after receiving the message. Reuse one PubNub client for the user/session rather than creating a client for every operation. -## Next steps +For a complete application, see the [getting started guide](https://www.pubnub.com/docs/sdks/javascript). -See the [JavaScript SDK documentation](https://www.pubnub.com/docs/sdks/javascript). +## Next steps -| Next step | Documentation | +| Task | Documentation | | --- | --- | | Configure the client | [Configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration) | | Work with subscriptions and messages | [Publish & Subscribe](https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe) | | Check channel occupancy | [Presence](https://www.pubnub.com/docs/sdks/javascript/api-reference/presence) | | Read message history | [Message Persistence](https://www.pubnub.com/docs/sdks/javascript/api-reference/storage-and-playback) | -## Access Manager +## Build with an AI coding assistant -[Access Manager](https://www.pubnub.com/docs/sdks/javascript/api-reference/access-manager) +The PubNub MCP server gives an AI coding assistant access to PubNub SDK documentation and PubNub APIs. Connect the assistant to the hosted server at https://mcp.pubnub.com, or run `npx @pubnub/mcp@latest` locally. -## Client lifetime +The [server repository](https://github.com/pubnub/pubnub-mcp-server) has setup steps for VS Code, Cursor, Claude Code, Claude Desktop, Codex, Gemini CLI, and OpenCode. -Create one PubNub instance and reuse it for the lifetime of the user or application session. Call `subscription.unsubscribe()` when an individual subscription is no longer needed, `pubnub.unsubscribeAll()` to stop all subscriptions, `pubnub.removeAllListeners()` when registered listeners are no longer required, and `pubnub.destroy()` when the client itself is no longer needed. +## Before production + +Use [Access Manager](https://www.pubnub.com/docs/sdks/javascript/api-reference/access-manager) to grant each client the permissions it needs. Keep the secret key on your backend. Never include it in a distributed client. -## Delivery +Create one PubNub instance and reuse it for the lifetime of the user or application session. Call `subscription.unsubscribe()` when an individual subscription is no longer needed, `pubnub.unsubscribeAll()` to stop all subscriptions, `pubnub.removeAllListeners()` when registered listeners are no longer required, and `pubnub.destroy()` when the client itself is no longer needed. Live delivery through PubNub SDKs is at-most-once. A subscriber can miss messages if its buffer overflows or if it is disconnected when a message is published. For recovery after longer gaps, see [Message Persistence](https://www.pubnub.com/docs/sdks/javascript/api-reference/storage-and-playback). ## Troubleshooting -### React Native reports URL-related errors - -Install `react-native-url-polyfill` alongside `pubnub`. The SDK no longer bundles this dependency. See [JavaScript Environment Setup](https://www.pubnub.com/docs/sdks/javascript/environment-setup). - -### Access Manager grant APIs are unavailable in a browser build - -Issue tokens from a trusted backend and call `pubnub.setToken(token)` in the client. The prebuilt browser SDK deliberately disables the Access Manager server module and secret-key functionality. See [Configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration). - -### Hot reload and server rendering - -Reuse the PubNub client and subscription across renders. In React, create them in lifecycle/application code and unsubscribe, remove listeners, and destroy an owned client from the corresponding cleanup instead of creating another client on every render. +| Symptom | Check | +| --- | --- | +| React Native reports URL-related errors | Install `react-native-url-polyfill` alongside `pubnub`. The SDK no longer bundles this dependency. See [JavaScript Environment Setup](https://www.pubnub.com/docs/sdks/javascript/environment-setup). | +| A publish succeeds but no message appears | Check the message handler, subscription readiness, keyset, and channel name. | +| Access Manager grant APIs are unavailable in a browser build | Issue tokens from a trusted backend and call `pubnub.setToken(token)` in the client. The prebuilt browser SDK deliberately disables the Access Manager server module and secret-key functionality. See [Configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration). | +| Extra clients or duplicate messages during development | Reuse the PubNub client and subscription across renders. In React, create them in lifecycle/application code and unsubscribe, remove listeners, and destroy an owned client from the corresponding cleanup instead of creating another client on every render. | -Further troubleshooting: [JavaScript SDK documentation](https://www.pubnub.com/docs/sdks/javascript). +For setup help, see [troubleshooting](https://www.pubnub.com/docs/sdks/javascript). Check [network status](https://status.pubnub.com/) for service incidents. -## Changelog and upgrades +## Releases -[Changelog](https://www.pubnub.com/docs/sdks/javascript/changelog) +Read the [changelog](https://www.pubnub.com/docs/sdks/javascript/changelog) before upgrading. For a major version change, review the SDK-specific migration guidance linked from the JavaScript documentation and the [JavaScript SDK changelog](https://www.pubnub.com/docs/sdks/javascript/changelog) for breaking changes introduced after that guide. -## Contributing +## Support and contributions + +For setup or account help, contact [PubNub Support](https://support.pubnub.com/). -Report bugs and request features in the [issue tracker](https://github.com/pubnub/javascript/issues). +For a reproducible SDK bug, use [GitHub Issues](https://github.com/pubnub/javascript/issues). Include the SDK version, runtime, and a small reproduction with credentials removed. Install the repository dependencies, run the relevant build and test commands for the affected package/platform, and include tests for behavioral changes before opening a pull request. ## License -[PubNub Software Development Kit License Agreement](https://github.com/pubnub/javascript/blob/master/LICENSE) +See the [PubNub Software Development Kit License Agreement](https://github.com/pubnub/javascript/blob/master/LICENSE). ## Support From 5d0b3bedd74f12085f6a377dced6a73ff4e99ae2 Mon Sep 17 00:00:00 2001 From: "mohit.tejani" Date: Mon, 19 Oct 2026 11:18:52 +0530 Subject: [PATCH 3/9] upgrade deps, updated package-lock file --- package-lock.json | 8982 +++++++++++++-------------------------------- package.json | 2 +- 2 files changed, 2474 insertions(+), 6510 deletions(-) diff --git a/package-lock.json b/package-lock.json index ff0145ad5..0d1438f9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pubnub", - "version": "13.0.3", + "version": "13.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pubnub", - "version": "13.0.3", + "version": "13.1.2", "license": "SEE LICENSE IN LICENSE", "dependencies": { "agentkeepalive": "^3.5.2", @@ -14,7 +14,7 @@ "cbor-js": "^0.1.0", "cbor-sync": "^1.0.4", "fast-text-encoding": "^1.0.6", - "fflate": "^0.8.2", + "fflate": "^0.8.3", "lil-uuid": "^0.1.1", "undici": "^7.29.0" }, @@ -95,54 +95,25 @@ } } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@asamuzakjp/css-color": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.1.tgz", - "integrity": "sha512-hpRD68SV2OMcZCsrbdkccTw5FXjNDLo5OuqSHyHZfwweGsDWZwDJ2+gONyNAbazZclobMirACLw0lk8WVxIqxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@csstools/css-calc": "^2.1.2", - "@csstools/css-color-parser": "^3.0.8", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "lru-cache": "^10.4.3" - } - }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "peer": true, @@ -151,23 +122,23 @@ } }, "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -194,47 +165,33 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", - "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-validator-option": "^7.25.9", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -265,51 +222,43 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz", - "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==", + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/helper-replace-supers": "^7.26.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/traverse": "^7.27.0", - "semver": "^6.3.1" - }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dev": true, - "license": "ISC", + "license": "MIT", "peer": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz", - "integrity": "sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "regexpu-core": "^6.2.0", - "semver": "^6.3.1" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -318,102 +267,74 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz", - "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", - "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "node_modules/@babel/helpers": { + "version": "7.29.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.10.tgz", + "integrity": "sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", - "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "node_modules/@babel/parser": { + "version": "7.29.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/types": "^7.25.9" + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "node_modules/@babel/runtime": { + "version": "7.29.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.10.tgz", + "integrity": "sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==", "dev": true, "license": "MIT", "peer": true, @@ -421,2288 +342,360 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", - "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-wrap-function": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", - "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", + "node_modules/@babel/traverse": { + "version": "7.29.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.10.tgz", + "integrity": "sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/traverse": "^7.26.5" + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.9", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", - "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=0.1.90" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "license": "MIT", - "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", - "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "node_modules/@cucumber/ci-environment": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@cucumber/ci-environment/-/ci-environment-13.0.0.tgz", + "integrity": "sha512-cs+3NzfNkGbcmHPddjEv4TKFiBpZRQ6WJEEufB9mw+ExS22V/4R/zpDSEG+fsJ/iSNCd6A2sATdY8PFOyY3YnA==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" - }, - "engines": { - "node": ">=6.9.0" - } + "peer": true }, - "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "node_modules/@cucumber/cucumber": { + "version": "12.9.0", + "resolved": "https://registry.npmjs.org/@cucumber/cucumber/-/cucumber-12.9.0.tgz", + "integrity": "sha512-QbgEo/DcKFMRGL+yULh8Kw6peEfdPJjhYjpKp0dYc+6Dv1Bmp6hvxIdTi2CIinYBCXhvCZzNO1Ct/n6Dk1yAtA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/types": "^7.27.0" + "@cucumber/ci-environment": "13.0.0", + "@cucumber/cucumber-expressions": "19.0.0", + "@cucumber/gherkin": "38.0.0", + "@cucumber/gherkin-streams": "6.0.0", + "@cucumber/gherkin-utils": "11.0.0", + "@cucumber/html-formatter": "23.1.0", + "@cucumber/junit-xml-formatter": "0.13.3", + "@cucumber/message-streams": "4.1.1", + "@cucumber/messages": "32.3.1", + "@cucumber/pretty-formatter": "1.0.1", + "@cucumber/tag-expressions": "9.1.0", + "assertion-error-formatter": "^3.0.0", + "capital-case": "^1.0.4", + "chalk": "^4.1.2", + "cli-table3": "0.6.5", + "commander": "^14.0.0", + "debug": "^4.3.4", + "error-stack-parser": "^2.1.4", + "figures": "^3.2.0", + "glob": "^13.0.0", + "has-ansi": "^4.0.1", + "indent-string": "^4.0.0", + "is-installed-globally": "^0.4.0", + "is-stream": "^2.0.0", + "knuth-shuffle-seeded": "^1.0.6", + "lodash.merge": "^4.6.2", + "lodash.mergewith": "^4.6.2", + "luxon": "3.7.2", + "mkdirp": "^3.0.0", + "mz": "^2.7.0", + "progress": "^2.0.3", + "read-package-up": "^12.0.0", + "semver": "7.7.4", + "string-argv": "0.3.1", + "supports-color": "^8.1.1", + "type-fest": "^4.41.0", + "util-arity": "^1.1.0", + "yaml": "^2.2.2", + "yup": "1.7.1" }, "bin": { - "parser": "bin/babel-parser.js" + "cucumber-js": "bin/cucumber.js" }, "engines": { - "node": ">=6.0.0" + "node": "20 || 22 || >=24" + }, + "funding": { + "url": "https://opencollective.com/cucumber" } }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", - "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", + "node_modules/@cucumber/cucumber-expressions": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@cucumber/cucumber-expressions/-/cucumber-expressions-19.0.0.tgz", + "integrity": "sha512-4FKoOQh2Uf6F6/Ln+1OxuK8LkTg6PyAqekhf2Ix8zqV2M54sH+m7XNJNLhOFOAW/t9nxzRbw2CcvXbCLjcvHZg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "regexp-match-indices": "1.0.2" } }, - "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", - "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", + "node_modules/@cucumber/cucumber/node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=20" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", - "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", + "node_modules/@cucumber/gherkin": { + "version": "38.0.0", + "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-38.0.0.tgz", + "integrity": "sha512-duEXK+KDfQUzu3vsSzXjkxQ2tirF5PRsc1Xrts6THKHJO6mjw4RjM8RV+vliuDasmhhrmdLcOcM7d9nurNTJKw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "@cucumber/messages": ">=31.0.0 <33" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", + "node_modules/@cucumber/gherkin-streams": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@cucumber/gherkin-streams/-/gherkin-streams-6.0.0.tgz", + "integrity": "sha512-HLSHMmdDH0vCr7vsVEURcDA4WwnRLdjkhqr6a4HQ3i4RFK1wiDGPjBGVdGJLyuXuRdJpJbFc6QxHvT8pU4t6jw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9" + "commander": "14.0.0", + "source-map-support": "0.5.21" }, - "engines": { - "node": ">=6.9.0" + "bin": { + "gherkin-javascript": "bin/gherkin" }, "peerDependencies": { - "@babel/core": "^7.13.0" + "@cucumber/gherkin": ">=22.0.0", + "@cucumber/message-streams": ">=4.0.0", + "@cucumber/messages": ">=17.1.1" } }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", - "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "node_modules/@cucumber/gherkin-streams/node_modules/commander": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=20" } }, - "node_modules/@babel/plugin-proposal-export-default-from": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz", - "integrity": "sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ==", + "node_modules/@cucumber/gherkin-utils": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@cucumber/gherkin-utils/-/gherkin-utils-11.0.0.tgz", + "integrity": "sha512-LJ+s4+TepHTgdKWDR4zbPyT7rQjmYIcukTwNbwNwgqr6i8Gjcmzf6NmtbYDA19m1ZFg6kWbFsmHnj37ZuX+kZA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" + "@cucumber/gherkin": "^38.0.0", + "@cucumber/messages": "^32.0.0", + "@teppeis/multimaps": "3.0.0", + "commander": "14.0.2", + "source-map-support": "^0.5.21" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "bin": { + "gherkin-utils": "bin/gherkin-utils" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "node_modules/@cucumber/gherkin-utils/node_modules/commander": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", + "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", "dev": true, "license": "MIT", "peer": true, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=20" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "node_modules/@cucumber/html-formatter": { + "version": "23.1.0", + "resolved": "https://registry.npmjs.org/@cucumber/html-formatter/-/html-formatter-23.1.0.tgz", + "integrity": "sha512-DcCSFoGs6jbwzXPgX1CwgJKEE+ZMcIEzq/0Memg0o24maNn9NJizBFHmoFWG4iv/OxHza+mvc+56cTHetfHndw==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@cucumber/messages": ">=18" } }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "node_modules/@cucumber/junit-xml-formatter": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/@cucumber/junit-xml-formatter/-/junit-xml-formatter-0.13.3.tgz", + "integrity": "sha512-w9ujOxiuKDtU6fLzJz+wp4Sgp5Xu6ba7ls00LHJccVmQU0Ba7zs+AHnv3iIgPjKZAQe1w8x93dr8Gaubh7Vqkg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@cucumber/query": "^15.0.1", + "@teppeis/multimaps": "^3.0.0", + "luxon": "^3.5.0", + "xmlbuilder": "^15.1.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@cucumber/messages": "*" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "node_modules/@cucumber/message-streams": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cucumber/message-streams/-/message-streams-4.1.1.tgz", + "integrity": "sha512-QCAntLajesWMyX+mZKrj63YghVAts7yKFlZe46XprLbdJZN0ddB+f/Mr9OnyWKC2DHhJ18jzCfKIFCaqpAmUxg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "mime": "^3.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@cucumber/messages": ">=17.1.1" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "node_modules/@cucumber/messages": { + "version": "32.3.1", + "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-32.3.1.tgz", + "integrity": "sha512-yNQq1KoXRYaEKrWMFmpUQX7TdeQuU9jeGgJAZ3dArTsC/T4NpJ6DnqaJIIgwPnz/wtQIQTNX7/h0rOuF5xY4qQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "class-transformer": "0.5.1", + "reflect-metadata": "0.2.2" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "node_modules/@cucumber/pretty-formatter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@cucumber/pretty-formatter/-/pretty-formatter-1.0.1.tgz", + "integrity": "sha512-A1lU4VVP0aUWdOTmpdzvXOyEYuPtBDI0xYwYJnmoMDplzxMdhcHk86lyyvYDoMoPzzq6OkOE3isuosvUU4X7IQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "ansi-styles": "^5.0.0", + "cli-table3": "^0.6.0", + "figures": "^3.2.0", + "ts-dedent": "^2.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@cucumber/cucumber": ">=7.0.0", + "@cucumber/messages": "*" } }, - "node_modules/@babel/plugin-syntax-export-default-from": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz", - "integrity": "sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ==", + "node_modules/@cucumber/query": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/@cucumber/query/-/query-15.0.1.tgz", + "integrity": "sha512-FMfT3orJblRsOxvU2doECBvQmauizYlj+5JsM8atAKKPbnQTj7v2/OrnuykvQpfZNBf19DYbRq1e832vllRP/g==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" + "@teppeis/multimaps": "3.0.0", + "lodash.sortby": "^4.7.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@cucumber/messages": "*" } }, - "node_modules/@babel/plugin-syntax-flow": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", - "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", + "node_modules/@cucumber/tag-expressions": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@cucumber/tag-expressions/-/tag-expressions-9.1.0.tgz", + "integrity": "sha512-bvHjcRFZ+J1TqIa9eFNO1wGHqwx4V9ZKV3hYgkuK/VahHx73uiP4rKV3JVrvWSMrwrFvJG6C8aEwnCWSvbyFdQ==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "peer": true }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", - "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", + "node_modules/@dual-bundle/import-meta-resolve": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.2.1.tgz", + "integrity": "sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", - "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", - "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", - "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-remap-async-to-generator": "^7.25.9", - "@babel/traverse": "^7.26.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", - "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-remap-async-to-generator": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz", - "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz", - "integrity": "sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", - "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", - "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", - "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9", - "@babel/traverse": "^7.25.9", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", - "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/template": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", - "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", - "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", - "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", - "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", - "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", - "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", - "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz", - "integrity": "sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/plugin-syntax-flow": "^7.26.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz", - "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", - "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", - "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", - "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", - "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", - "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", - "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", - "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", - "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", - "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", - "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", - "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.26.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz", - "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", - "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", - "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", - "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", - "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", - "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", - "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", - "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", - "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz", - "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", - "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-syntax-jsx": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", - "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", - "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.0.tgz", - "integrity": "sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", - "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", - "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.10.tgz", - "integrity": "sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.26.5", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.11.0", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", - "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", - "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", - "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz", - "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.0.tgz", - "integrity": "sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.0.tgz", - "integrity": "sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.27.0", - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/plugin-syntax-typescript": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", - "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", - "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", - "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", - "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz", - "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.26.0", - "@babel/plugin-syntax-import-attributes": "^7.26.0", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.25.9", - "@babel/plugin-transform-async-generator-functions": "^7.26.8", - "@babel/plugin-transform-async-to-generator": "^7.25.9", - "@babel/plugin-transform-block-scoped-functions": "^7.26.5", - "@babel/plugin-transform-block-scoping": "^7.25.9", - "@babel/plugin-transform-class-properties": "^7.25.9", - "@babel/plugin-transform-class-static-block": "^7.26.0", - "@babel/plugin-transform-classes": "^7.25.9", - "@babel/plugin-transform-computed-properties": "^7.25.9", - "@babel/plugin-transform-destructuring": "^7.25.9", - "@babel/plugin-transform-dotall-regex": "^7.25.9", - "@babel/plugin-transform-duplicate-keys": "^7.25.9", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-dynamic-import": "^7.25.9", - "@babel/plugin-transform-exponentiation-operator": "^7.26.3", - "@babel/plugin-transform-export-namespace-from": "^7.25.9", - "@babel/plugin-transform-for-of": "^7.26.9", - "@babel/plugin-transform-function-name": "^7.25.9", - "@babel/plugin-transform-json-strings": "^7.25.9", - "@babel/plugin-transform-literals": "^7.25.9", - "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", - "@babel/plugin-transform-member-expression-literals": "^7.25.9", - "@babel/plugin-transform-modules-amd": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.26.3", - "@babel/plugin-transform-modules-systemjs": "^7.25.9", - "@babel/plugin-transform-modules-umd": "^7.25.9", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-new-target": "^7.25.9", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", - "@babel/plugin-transform-numeric-separator": "^7.25.9", - "@babel/plugin-transform-object-rest-spread": "^7.25.9", - "@babel/plugin-transform-object-super": "^7.25.9", - "@babel/plugin-transform-optional-catch-binding": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9", - "@babel/plugin-transform-private-methods": "^7.25.9", - "@babel/plugin-transform-private-property-in-object": "^7.25.9", - "@babel/plugin-transform-property-literals": "^7.25.9", - "@babel/plugin-transform-regenerator": "^7.25.9", - "@babel/plugin-transform-regexp-modifiers": "^7.26.0", - "@babel/plugin-transform-reserved-words": "^7.25.9", - "@babel/plugin-transform-shorthand-properties": "^7.25.9", - "@babel/plugin-transform-spread": "^7.25.9", - "@babel/plugin-transform-sticky-regex": "^7.25.9", - "@babel/plugin-transform-template-literals": "^7.26.8", - "@babel/plugin-transform-typeof-symbol": "^7.26.7", - "@babel/plugin-transform-unicode-escapes": "^7.25.9", - "@babel/plugin-transform-unicode-property-regex": "^7.25.9", - "@babel/plugin-transform-unicode-regex": "^7.25.9", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.11.0", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.40.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/preset-flow": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.25.9.tgz", - "integrity": "sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-transform-flow-strip-types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-typescript": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.0.tgz", - "integrity": "sha512-vxaPFfJtHhgeOVXRKuHpHPAOgymmy8V8I65T1q53R7GCZlefKeCaTyDs3zOPHTTbmquvNlQYC5klEvWsBAtrBQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-syntax-jsx": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.26.3", - "@babel/plugin-transform-typescript": "^7.27.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/register": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.25.9.tgz", - "integrity": "sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "clone-deep": "^4.0.1", - "find-cache-dir": "^2.0.0", - "make-dir": "^2.1.0", - "pirates": "^4.0.6", - "source-map-support": "^0.5.16" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/runtime/node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse--for-generate-function-map": { - "name": "@babel/traverse", - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse--for-generate-function-map/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@csstools/color-helpers": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", - "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - } - }, - "node_modules/@csstools/css-calc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.2.tgz", - "integrity": "sha512-TklMyb3uBB28b5uQdxjReG4L80NxAqgrECqLZFQbyLekwwlcDDS8r3f07DKqeo8C4926Br0gf/ZDe17Zv4wIuw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" - } - }, - "node_modules/@csstools/css-color-parser": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.8.tgz", - "integrity": "sha512-pdwotQjCCnRPuNi06jFuP68cykU1f3ZWExLe/8MQ1LOs8Xq+fTkYgd+2V8mWUWMrOn9iS2HftPVaMZDaXzGbhQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "dependencies": { - "@csstools/color-helpers": "^5.0.2", - "@csstools/css-calc": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" - } - }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", - "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.3" - } - }, - "node_modules/@csstools/css-tokenizer": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", - "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@cucumber/ci-environment": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@cucumber/ci-environment/-/ci-environment-10.0.1.tgz", - "integrity": "sha512-/+ooDMPtKSmvcPMDYnMZt4LuoipfFfHaYspStI4shqw8FyKcfQAmekz6G+QKWjQQrvM+7Hkljwx58MEwPCwwzg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@cucumber/cucumber": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/@cucumber/cucumber/-/cucumber-10.9.0.tgz", - "integrity": "sha512-7XHJ6nmr9IkIag0nv6or82HfelbSInrEe3H4aT6dMHyTehwFLUifG6eQQ+uE4LZIOXAnzLPH37YmqygEO67vCA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@cucumber/ci-environment": "10.0.1", - "@cucumber/cucumber-expressions": "17.1.0", - "@cucumber/gherkin": "28.0.0", - "@cucumber/gherkin-streams": "5.0.1", - "@cucumber/gherkin-utils": "9.0.0", - "@cucumber/html-formatter": "21.6.0", - "@cucumber/message-streams": "4.0.1", - "@cucumber/messages": "24.1.0", - "@cucumber/tag-expressions": "6.1.0", - "assertion-error-formatter": "^3.0.0", - "capital-case": "^1.0.4", - "chalk": "^4.1.2", - "cli-table3": "0.6.3", - "commander": "^10.0.0", - "debug": "^4.3.4", - "error-stack-parser": "^2.1.4", - "figures": "^3.2.0", - "glob": "^10.3.10", - "has-ansi": "^4.0.1", - "indent-string": "^4.0.0", - "is-installed-globally": "^0.4.0", - "is-stream": "^2.0.0", - "knuth-shuffle-seeded": "^1.0.6", - "lodash.merge": "^4.6.2", - "lodash.mergewith": "^4.6.2", - "luxon": "3.2.1", - "mime": "^3.0.0", - "mkdirp": "^2.1.5", - "mz": "^2.7.0", - "progress": "^2.0.3", - "read-pkg-up": "^7.0.1", - "resolve-pkg": "^2.0.0", - "semver": "7.5.3", - "string-argv": "0.3.1", - "strip-ansi": "6.0.1", - "supports-color": "^8.1.1", - "tmp": "0.2.3", - "type-fest": "^4.8.3", - "util-arity": "^1.1.0", - "xmlbuilder": "^15.1.1", - "yaml": "^2.2.2", - "yup": "1.2.0" - }, - "bin": { - "cucumber-js": "bin/cucumber.js" - }, - "engines": { - "node": "18 || >=20" - }, - "funding": { - "url": "https://opencollective.com/cucumber" - } - }, - "node_modules/@cucumber/cucumber-expressions": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@cucumber/cucumber-expressions/-/cucumber-expressions-17.1.0.tgz", - "integrity": "sha512-PCv/ppsPynniKPWJr5v566daCVe+pbxQpHGrIu/Ev57cCH9Rv+X0F6lio4Id3Z64TaG7btCRLUGewIgLwmrwOA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "regexp-match-indices": "1.0.2" - } - }, - "node_modules/@cucumber/cucumber/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@cucumber/gherkin": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-28.0.0.tgz", - "integrity": "sha512-Ee6zJQq0OmIUPdW0mSnsCsrWA2PZAELNDPICD2pLfs0Oz7RAPgj80UsD2UCtqyAhw2qAR62aqlktKUlai5zl/A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@cucumber/messages": ">=19.1.4 <=24" - } - }, - "node_modules/@cucumber/gherkin-streams": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@cucumber/gherkin-streams/-/gherkin-streams-5.0.1.tgz", - "integrity": "sha512-/7VkIE/ASxIP/jd4Crlp4JHXqdNFxPGQokqWqsaCCiqBiu5qHoKMxcWNlp9njVL/n9yN4S08OmY3ZR8uC5x74Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "commander": "9.1.0", - "source-map-support": "0.5.21" - }, - "bin": { - "gherkin-javascript": "bin/gherkin" - }, - "peerDependencies": { - "@cucumber/gherkin": ">=22.0.0", - "@cucumber/message-streams": ">=4.0.0", - "@cucumber/messages": ">=17.1.1" - } - }, - "node_modules/@cucumber/gherkin-streams/node_modules/commander": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.1.0.tgz", - "integrity": "sha512-i0/MaqBtdbnJ4XQs4Pmyb+oFQl+q0lsAmokVUH92SlSw4fkeAcG3bVon+Qt7hmtF+u3Het6o4VgrcY3qAoEB6w==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/@cucumber/gherkin-utils": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@cucumber/gherkin-utils/-/gherkin-utils-9.0.0.tgz", - "integrity": "sha512-clk4q39uj7pztZuZtyI54V8lRsCUz0Y/p8XRjIeHh7ExeEztpWkp4ca9q1FjUOPfQQ8E7OgqFbqoQQXZ1Bx7fw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@cucumber/gherkin": "^28.0.0", - "@cucumber/messages": "^24.0.0", - "@teppeis/multimaps": "3.0.0", - "commander": "12.0.0", - "source-map-support": "^0.5.21" - }, - "bin": { - "gherkin-utils": "bin/gherkin-utils" - } - }, - "node_modules/@cucumber/gherkin-utils/node_modules/commander": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz", - "integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@cucumber/html-formatter": { - "version": "21.6.0", - "resolved": "https://registry.npmjs.org/@cucumber/html-formatter/-/html-formatter-21.6.0.tgz", - "integrity": "sha512-Qw1tdObBJrgXgXwVjKVjB3hFhFPI8WhIFb+ULy8g5lDl5AdnKDiyDXAMvAWRX+pphnRMMNdkPCt6ZXEfWvUuAA==", - "dev": true, - "license": "MIT", - "peer": true, - "peerDependencies": { - "@cucumber/messages": ">=18" - } - }, - "node_modules/@cucumber/message-streams": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@cucumber/message-streams/-/message-streams-4.0.1.tgz", - "integrity": "sha512-Kxap9uP5jD8tHUZVjTWgzxemi/0uOsbGjd4LBOSxcJoOCRbESFwemUzilJuzNTB8pcTQUh8D5oudUyxfkJOKmA==", - "dev": true, - "license": "MIT", - "peer": true, - "peerDependencies": { - "@cucumber/messages": ">=17.1.1" - } - }, - "node_modules/@cucumber/messages": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-24.1.0.tgz", - "integrity": "sha512-hxVHiBurORcobhVk80I9+JkaKaNXkW6YwGOEFIh/2aO+apAN+5XJgUUWjng9NwqaQrW1sCFuawLB1AuzmBaNdQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/uuid": "9.0.8", - "class-transformer": "0.5.1", - "reflect-metadata": "0.2.1", - "uuid": "9.0.1" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/JounQin" } }, - "node_modules/@cucumber/tag-expressions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@cucumber/tag-expressions/-/tag-expressions-6.1.0.tgz", - "integrity": "sha512-+3DwRumrCJG27AtzCIL37A/X+A/gSfxOPLg8pZaruh5SLumsTmpvilwroVWBT2fPzmno/tGXypeK5a7NHU4RzA==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", - "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", "cpu": [ "ppc64" ], @@ -2717,9 +710,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", - "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", "cpu": [ "arm" ], @@ -2734,9 +727,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", - "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", "cpu": [ "arm64" ], @@ -2751,9 +744,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", - "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", "cpu": [ "x64" ], @@ -2768,9 +761,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", - "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", "cpu": [ "arm64" ], @@ -2785,9 +778,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", - "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", "cpu": [ "x64" ], @@ -2802,9 +795,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", - "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", "cpu": [ "arm64" ], @@ -2819,9 +812,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", - "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", "cpu": [ "x64" ], @@ -2836,9 +829,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", - "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", "cpu": [ "arm" ], @@ -2853,9 +846,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", - "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", "cpu": [ "arm64" ], @@ -2870,9 +863,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", - "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", "cpu": [ "ia32" ], @@ -2887,9 +880,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", - "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", "cpu": [ "loong64" ], @@ -2904,9 +897,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", - "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", "cpu": [ "mips64el" ], @@ -2921,9 +914,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", - "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", "cpu": [ "ppc64" ], @@ -2938,9 +931,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", - "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", "cpu": [ "riscv64" ], @@ -2955,9 +948,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", - "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", "cpu": [ "s390x" ], @@ -2972,9 +965,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", - "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", "cpu": [ "x64" ], @@ -2989,9 +982,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", - "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", "cpu": [ "arm64" ], @@ -3006,9 +999,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", - "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", "cpu": [ "x64" ], @@ -3023,9 +1016,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", - "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", "cpu": [ "arm64" ], @@ -3040,9 +1033,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", - "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", "cpu": [ "x64" ], @@ -3056,10 +1049,27 @@ "node": ">=18" } }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", - "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", "cpu": [ "x64" ], @@ -3074,9 +1084,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", - "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", "cpu": [ "arm64" ], @@ -3091,9 +1101,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", - "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", "cpu": [ "ia32" ], @@ -3108,9 +1118,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", - "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", "cpu": [ "x64" ], @@ -3125,9 +1135,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", - "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", "dev": true, "license": "MIT", "dependencies": { @@ -3144,9 +1154,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -3184,73 +1194,17 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } + "license": "MIT" }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -3258,364 +1212,258 @@ "concat-map": "0.0.1" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">= 4" } }, - "node_modules/@isaacs/ttlcache": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", - "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", "dev": true, - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, - "license": "MIT", - "peer": true, + "license": "Apache-2.0", "dependencies": { - "p-locate": "^4.1.0" + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=8" + "node": ">=10.10.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@humanwhocodes/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, - "license": "MIT", - "peer": true, + "license": "ISC", "dependencies": { - "p-limit": "^2.2.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "MIT", - "peer": true, + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "dev": true, + "license": "ISC", "peer": true, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/@jest/create-cache-key-function": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", - "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "node_modules/@jest/diff-sequences": { + "version": "30.5.0", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.5.0.tgz", + "integrity": "sha512-OsqBjHXCn8cadasoAZBP6nWYvMsRhpMzGXTpxJ5aO04NlbdhIz+FVe3q49l0AwVhsz/cEmIpBes6gAFl1/dWQg==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "node_modules/@jest/expect-utils": { + "version": "30.5.2", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.5.2.tgz", + "integrity": "sha512-d/HOLSrJUlBIl6n3LzOa7cjW3xdePm5H5gQw2lixZ/0h157l9sw3mLblzFqnPcTbhDzhRQdBOX3A3KcG73nm5Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" + "@jest/get-type": "30.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "node_modules/@jest/get-type": { + "version": "30.5.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.5.0.tgz", + "integrity": "sha512-9/2VUPitAjmBzbvDvqrxmvB7BzWsBW0WmkkojX1ODuxX1NLGxx9gfaZpHB0z8DtJ9uhGNmZG/VXBhf8uO0OV8Q==", "dev": true, "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "node_modules/@jest/pattern": { + "version": "30.5.0", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.5.0.tgz", + "integrity": "sha512-HdNQYSdRTEBNrginaqzQtTjG0HRMfrra/z6Ok7uL3S87vSlarIVohEsJsSj5edu3MiHoHjAkvPROz5ZjoKai+w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "jest-regex-util": "30.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, + "node_modules/@jest/react-is-18": { + "name": "react-is", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/react-is-19": { + "name": "react-is", + "version": "19.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.3.1.tgz", + "integrity": "sha512-RRieF6IyxQBkcK6pP8xOHprLTPW6QjRkbGdImtqNme+/hYVwCZkLQLdlZGOhUqXwkS9IEynaGvPJtv6XB/cz0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "version": "30.5.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.5.0.tgz", + "integrity": "sha512-/hunigyNpc4RCjC0VaW3f5RCUZVM2+WQ65qP7z083Gmvac7or2LI50XVNOtE4YPgBpV0yxYiAgorAPGniCoJmg==", "dev": true, "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/@jest/types": { + "version": "30.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.5.1.tgz", + "integrity": "sha512-LvVYn83nnXPl+Rg98nvcFgjx6nRMTArhSn6RAX/w3ELn54S8A42TYZvsCMdGUqTM8S0wyXbtlQdU6Hi6dykj9g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" + "@jest/pattern": "30.5.0", + "@jest/schemas": "30.5.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -3628,20 +1476,10 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "license": "MIT", "dependencies": { @@ -3650,16 +1488,16 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -3668,9 +1506,9 @@ } }, "node_modules/@mswjs/interceptors": { - "version": "0.38.3", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.38.3.tgz", - "integrity": "sha512-3AMc2fTnX4q3qyO6K/LKwWXjUAFc3COC3bo5YCROIyQYJ8g/++5Col5fSIglIyUdBN787CTbL+c04KRwaaZ/UA==", + "version": "0.41.9", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.41.9.tgz", + "integrity": "sha512-VVPPgHyQ6ShqnrmDWuxjmUIsO9gWyOZFmuOfLd9LfBGQJwZfy0gvv9pbHSJuoFNIYC7ZDX9aoFwowjcdSC4E8w==", "dev": true, "license": "MIT", "dependencies": { @@ -3678,7 +1516,6 @@ "@open-draft/logger": "^0.3.0", "@open-draft/until": "^2.0.0", "is-node-process": "^1.2.0", - "jsdom": "^26.0.0", "outvariant": "^1.4.3", "strict-event-emitter": "^0.5.1" }, @@ -3749,229 +1586,73 @@ "dev": true, "license": "MIT" }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@pkgr/core": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.0.tgz", - "integrity": "sha512-vsJDAkYR6qCPu+ioGScGiMYR7LvZYIXh/dlQeviqoTWNCVfKTLYD/LkNWH4Mxsv2a5vpIRc77FN5DnmK1eBggQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@react-native/assets-registry": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.78.1.tgz", - "integrity": "sha512-SegfYQFuut05EQIQIVB/6QMGaxJ29jEtPmzFWJdIp/yc2mmhIq7MfWRjwOe6qbONzIdp6Ca8p835hiGiAGyeKQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/babel-plugin-codegen": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.78.1.tgz", - "integrity": "sha512-rD0tnct/yPEtoOc8eeFHIf8ZJJJEzLkmqLs8HZWSkt3w9VYWngqLXZxiDGqv0ngXjunAlC/Hpq+ULMVOvOnByw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/traverse": "^7.25.3", - "@react-native/codegen": "0.78.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/babel-preset": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.78.1.tgz", - "integrity": "sha512-yTVcHmEdNQH4Ju7lhvbiQaGxBpMcalgkBy/IvHowXKk/ex3nY1PolF16/mBG1BrefcUA/rtJpqTtk2Ii+7T/Lw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/core": "^7.25.2", - "@babel/plugin-proposal-export-default-from": "^7.24.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-default-from": "^7.24.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.4", - "@babel/plugin-transform-async-to-generator": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.25.0", - "@babel/plugin-transform-class-properties": "^7.25.4", - "@babel/plugin-transform-classes": "^7.25.4", - "@babel/plugin-transform-computed-properties": "^7.24.7", - "@babel/plugin-transform-destructuring": "^7.24.8", - "@babel/plugin-transform-flow-strip-types": "^7.25.2", - "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.25.1", - "@babel/plugin-transform-literals": "^7.25.2", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-numeric-separator": "^7.24.7", - "@babel/plugin-transform-object-rest-spread": "^7.24.7", - "@babel/plugin-transform-optional-catch-binding": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.8", - "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.24.7", - "@babel/plugin-transform-private-property-in-object": "^7.24.7", - "@babel/plugin-transform-react-display-name": "^7.24.7", - "@babel/plugin-transform-react-jsx": "^7.25.2", - "@babel/plugin-transform-react-jsx-self": "^7.24.7", - "@babel/plugin-transform-react-jsx-source": "^7.24.7", - "@babel/plugin-transform-regenerator": "^7.24.7", - "@babel/plugin-transform-runtime": "^7.24.7", - "@babel/plugin-transform-shorthand-properties": "^7.24.7", - "@babel/plugin-transform-spread": "^7.24.7", - "@babel/plugin-transform-sticky-regex": "^7.24.7", - "@babel/plugin-transform-typescript": "^7.25.2", - "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/template": "^7.25.0", - "@react-native/babel-plugin-codegen": "0.78.1", - "babel-plugin-syntax-hermes-parser": "0.25.1", - "babel-plugin-transform-flow-enums": "^0.0.2", - "react-refresh": "^0.14.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@babel/core": "*" - } - }, - "node_modules/@react-native/codegen": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.78.1.tgz", - "integrity": "sha512-kGG5qAM9JdFtxzUwe7c6CyJbsU2PnaTrtCHA2dF8VEiNX1K3yd9yKPzfkxA7HPvmHoAn3ga1941O79BStWcM3A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/parser": "^7.25.3", - "glob": "^7.1.1", - "hermes-parser": "0.25.1", - "invariant": "^2.2.4", - "jscodeshift": "^17.0.0", - "nullthrows": "^1.1.1", - "yargs": "^17.6.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@babel/preset-env": "^7.1.6" - } - }, - "node_modules/@react-native/codegen/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@react-native/codegen/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, + "node_modules/@pkgr/core": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", + "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" } }, - "node_modules/@react-native/codegen/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/@react-native/asset-utils": { + "version": "0.88.0", + "resolved": "https://registry.npmjs.org/@react-native/asset-utils/-/asset-utils-0.88.0.tgz", + "integrity": "sha512-Bj1DxQt5f4OrjdlgSVkZT37Z3hx5hUIN5AUDSqL/e99vgtTcqj5vnm067epZL1EF/QiqsniZO8Q1GSkItOakDg==", "dev": true, - "license": "ISC", + "license": "MIT", "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, - "node_modules/@react-native/codegen/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@react-native/codegen": { + "version": "0.88.0", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.88.0.tgz", + "integrity": "sha512-SAGg+XfzsrPiYTscbKa9bo2/H2ei2TjyxW8RTMq2Ps661kRK3AnmpMGVfrEFshEMr3FGEbuQIvj86X98kaXlRA==", "dev": true, - "license": "ISC", + "license": "MIT", "peer": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@babel/core": "^7.25.2", + "@babel/parser": "^7.29.0", + "flow-parser": "0.327.0", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "tinyglobby": "^0.2.15", + "yargs": "^17.6.2" }, "engines": { - "node": "*" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + }, + "peerDependencies": { + "@babel/core": "*" } }, - "node_modules/@react-native/codegen/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/@react-native/codegen/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "MIT", + "license": "ISC", "peer": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=12" } }, "node_modules/@react-native/codegen/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", "dev": true, "license": "MIT", "peer": true, @@ -4000,175 +1681,110 @@ } }, "node_modules/@react-native/community-cli-plugin": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.78.1.tgz", - "integrity": "sha512-S6vF4oWpFqThpt/dBLrqLQw5ED2M1kg5mVtiL6ZqpoYIg+/e0vg7LZ8EXNbcdMDH4obRnm2xbOd+qlC7mOzNBg==", + "version": "0.88.0", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.88.0.tgz", + "integrity": "sha512-WrQdXbjVt1gwAay8ZzYtpOi9ly99ksJ0VMYFdVcMe6nq3vtiRgqKRpHgCdN6ySIbtr5o+aJ+Vr7OTDY98ec/Ow==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@react-native/dev-middleware": "0.78.1", - "@react-native/metro-babel-transformer": "0.78.1", - "chalk": "^4.0.0", - "debug": "^2.2.0", + "@react-native/asset-utils": "0.88.0", + "@react-native/dev-middleware": "0.88.0", + "commander": "^12.0.0", + "debug": "^4.4.0", "invariant": "^2.2.4", - "metro": "^0.81.0", - "metro-config": "^0.81.0", - "metro-core": "^0.81.0", - "readline": "^1.3.0", + "metro": "^0.87.1", "semver": "^7.1.3" }, "engines": { - "node": ">=18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" }, "peerDependencies": { - "@react-native-community/cli": "*" + "@react-native-community/cli": "*", + "@react-native/metro-config": "0.88.0" }, "peerDependenciesMeta": { "@react-native-community/cli": { "optional": true + }, + "@react-native/metro-config": { + "optional": true } } }, - "node_modules/@react-native/community-cli-plugin/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/@react-native/debugger-frontend": { + "version": "0.88.0", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.88.0.tgz", + "integrity": "sha512-v5cnBaaWhDRPcQv8EC20zj53jOAKH7u2wnzzXS4JTNu+diPC+cA2+kC7rq3eKI5vGhlAcG2kDPoViRuC0AY0oA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "peer": true, - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, - "node_modules/@react-native/community-cli-plugin/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/@react-native/debugger-shell": { + "version": "0.88.0", + "resolved": "https://registry.npmjs.org/@react-native/debugger-shell/-/debugger-shell-0.88.0.tgz", + "integrity": "sha512-p82zT8ZKNx7nIm/8zf8pi55sxm5KQBm8td47kzoJysTdqHLyPsRMUvDXtvCJIWadHSv7RJ6t/yiCc+IoImLBtw==", "dev": true, "license": "MIT", - "peer": true - }, - "node_modules/@react-native/debugger-frontend": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.78.1.tgz", - "integrity": "sha512-xev/B++QLxSDpEBWsc74GyCuq9XOHYTBwcGSpsuhOJDUha6WZIbEEvZe3LpVW+OiFso4oGIdnVSQntwippZdWw==", - "dev": true, - "license": "BSD-3-Clause", "peer": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "debug": "^4.4.0", + "fb-dotslash": "0.5.8" + }, "engines": { - "node": ">=18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/@react-native/dev-middleware": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.78.1.tgz", - "integrity": "sha512-l8p7/dXa1vWPOdj0iuACkex8lgbLpYyPZ3QXGkocMcpl0bQ24K7hf3Bj02tfptP5PAm16b2RuEi04sjIGHUzzg==", + "version": "0.88.0", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.88.0.tgz", + "integrity": "sha512-sHLxVHOwfkF672ZzMepNh4d3IKbrZy3qXDKWSwN5LC5VJkzzZ5FdmSPP4N/CCn2pcKJ4oSqvojXwN4De3Xk92A==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.78.1", - "chrome-launcher": "^0.15.2", - "chromium-edge-launcher": "^0.2.0", + "@react-native/debugger-frontend": "0.88.0", + "@react-native/debugger-shell": "0.88.0", "connect": "^3.6.5", - "debug": "^2.2.0", + "debug": "^4.4.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", - "open": "^7.0.3", - "selfsigned": "^2.4.1", + "open": "^8.4.2", "serve-static": "^1.16.2", - "ws": "^6.2.3" + "ws": "^7.5.10" }, "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/dev-middleware/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@react-native/dev-middleware/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/dev-middleware/node_modules/ws": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", - "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "async-limiter": "~1.0.0" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/@react-native/gradle-plugin": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.78.1.tgz", - "integrity": "sha512-v8GJU+8DzQDWO3iuTFI1nbuQ/kzuqbXv07VVtSIMLbdofHzuuQT14DGBacBkrIDKBDTVaBGAc/baDNsyxCghng==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/js-polyfills": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.78.1.tgz", - "integrity": "sha512-Ogcv4QOA1o3IyErrf/i4cDnP+nfNcIfGTgw6iNQyAPry1xjPOz4ziajskLpWG/3ADeneIZuyZppKB4A28rZSvg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/metro-babel-transformer": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.78.1.tgz", - "integrity": "sha512-jQWf69D+QTMvSZSWLR+cr3VUF16rGB6sbD+bItD8Czdfn3hajzfMoHJTkVFP7991cjK5sIVekNiQIObou8JSQw==", + "version": "0.88.0", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.88.0.tgz", + "integrity": "sha512-4jPSKslOfJj8NKY/jv9qmWkxZYmqPyamoS3Vs0JOFxw9t4PM6L/ea0fUsjNV0LxC9zJlvWilPJOCTOf7h8wlyw==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "@babel/core": "^7.25.2", - "@react-native/babel-preset": "0.78.1", - "hermes-parser": "0.25.1", - "nullthrows": "^1.1.1" - }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@babel/core": "*" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/@react-native/normalize-colors": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.78.1.tgz", - "integrity": "sha512-h4wARnY4iBFgigN1NjnaKFtcegWwQyE9+CEBVG4nHmwMtr8lZBmc7ZKIM6hUc6lxqY/ugHg48aSQSynss7mJUg==", + "version": "0.88.0", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.88.0.tgz", + "integrity": "sha512-eZCu3tGAQCfvMCPQJVY4dmoMX8ZZYBvqIGHX7lwOYyzNK+Dl8e5ky7ZoXub1Rq75oSrQXNNmSP2CDjNNXXZpFQ==", "dev": true, "license": "MIT", "peer": true }, "node_modules/@react-native/virtualized-lists": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.78.1.tgz", - "integrity": "sha512-v0jqDNMFXpnRnSlkDVvwNxXgPhifzzTFlxTSnHj9erKJsKpE26gSU5qB4hmJkEsscLG/ygdJ1c88aqinSh/wRA==", + "version": "0.88.0", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.88.0.tgz", + "integrity": "sha512-zpZIOAbobdS93edwHkNUdGDzvElNeQJqukRERRPns3/ucPvuMd2G4fYpmVJSVjhxtGCcLLB1PFndLYYfwaYoBQ==", "dev": true, "license": "MIT", "peer": true, @@ -4177,12 +1793,12 @@ "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" }, "peerDependencies": { - "@types/react": "^19.0.0", + "@types/react": "^19.2.0", "react": "*", - "react-native": "*" + "react-native": "0.88.0" }, "peerDependenciesMeta": { "@types/react": { @@ -4216,11 +1832,28 @@ } } }, + "node_modules/@rollup/plugin-commonjs/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/plugin-commonjs/node_modules/brace-expansion": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@rollup/plugin-commonjs/node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -4238,9 +1871,9 @@ } }, "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, "license": "ISC", "dependencies": { @@ -4369,9 +2002,9 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", - "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", + "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", "dev": true, "license": "MIT", "dependencies": { @@ -4455,6 +2088,9 @@ "arm" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4469,6 +2105,9 @@ "arm" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4483,6 +2122,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4497,6 +2139,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4511,6 +2156,9 @@ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4525,6 +2173,9 @@ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4539,6 +2190,9 @@ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4553,6 +2207,9 @@ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4567,6 +2224,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4616,19 +2276,18 @@ ] }, "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "version": "0.34.52", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.52.tgz", + "integrity": "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==", "dev": true, "license": "MIT" }, "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "type-detect": "4.0.8" } @@ -4639,22 +2298,10 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=4" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, "node_modules/@sinonjs/formatio": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", @@ -4666,26 +2313,6 @@ "@sinonjs/samsam": "^3.1.0" } }, - "node_modules/@sinonjs/formatio/node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/formatio/node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/@sinonjs/samsam": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", @@ -4698,30 +2325,11 @@ "lodash": "^4.17.15" } }, - "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/samsam/node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/@sinonjs/text-encoding": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", + "deprecated": "Deprecated: no longer maintained and no longer used by Sinon packages. See\n https://github.com/sinonjs/nise/issues/243 for replacement details.", "dev": true, "license": "(Unlicense OR Apache-2.0)" }, @@ -4744,9 +2352,9 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.13.tgz", + "integrity": "sha512-gcLdvR9HO1ZJBypsOGqaP6TFEzb6vIta0KSTLt9NAQ6pXQO3cRgSVyCN6pzYqI9DlJgY71XKO0dpDhCf08b3pg==", "dev": true, "license": "MIT" }, @@ -4771,55 +2379,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", - "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, "node_modules/@types/cbor-js": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@types/cbor-js/-/cbor-js-0.1.1.tgz", @@ -4845,41 +2404,19 @@ } }, "node_modules/@types/cors": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", - "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" } }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, "license": "MIT" }, @@ -4901,17 +2438,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -4979,35 +2505,24 @@ } }, "node_modules/@types/node": { - "version": "22.13.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", - "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", + "version": "22.20.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.5.tgz", + "integrity": "sha512-U2+DNr+wSjpsTS/wZGYHq7GcwfuSmKiKvoPvK22zwTlRhU91yOniN4qRR5KhIjvif7ysw/dz/hKmfDH0Ris4aA==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", - "form-data": "^4.0.0" - } - }, - "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*" + "form-data": "^4.0.4" } }, "node_modules/@types/normalize-package-data": { @@ -5036,9 +2551,9 @@ } }, "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", - "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-15.0.1.tgz", + "integrity": "sha512-Ko2tjWJq8oozHzHV+reuvS5KYIRAokHnGbDwGh/J64LntgpbuylF74ipEL24HCyRjf9FOlBiBHWBR1RlVKsI1w==", "dev": true, "license": "MIT" }, @@ -5063,13 +2578,15 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "node_modules/@types/ws": { + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.2.tgz", + "integrity": "sha512-67MQl+fpWKVTT1NYdnmo3U4sc/xPo/zQBncVnI74qmQa0z/b+1g6iYqNmGCPbxO+zz2aklb08a0oHfegiVd0/w==", "dev": true, "license": "MIT", - "peer": true + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/wtfnode": { "version": "0.7.3", @@ -5079,9 +2596,9 @@ "license": "MIT" }, "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", "dev": true, "license": "MIT", "dependencies": { @@ -5096,21 +2613,20 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.28.0.tgz", - "integrity": "sha512-lvFK3TCGAHsItNdWZ/1FkvpzCxTHUVuFrdnOGLMa0GGCFIbCgQWVk3CzCGdA7kM3qGVc+dfW9tr0Z/sHnGDFyg==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.2.tgz", + "integrity": "sha512-K72/pvT7qpm8q3k8G5u93NCSN1RcLxX5h7Gw0bQpbMXviBHeY6Nx1WEwmk9wP+eKTSQ8ecxvcgt/ZX/rB938xQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.28.0", - "@typescript-eslint/type-utils": "8.28.0", - "@typescript-eslint/utils": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.71.2", + "@typescript-eslint/type-utils": "8.71.2", + "@typescript-eslint/utils": "8.71.2", + "@typescript-eslint/visitor-keys": "8.71.2", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5120,23 +2636,46 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "@typescript-eslint/parser": "^8.71.2", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.28.0.tgz", - "integrity": "sha512-LPcw1yHD3ToaDEoljFEfQ9j2xShY367h7FZ1sq5NJT9I3yj4LHer1Xd1yRSOdYy9BpsrxU7R+eoDokChYM53lQ==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.2.tgz", + "integrity": "sha512-aTtmZjp/x3gsGHkDs04/1I8kNogBJkpQaeGaN0PfiG43NzDEmW2n+OP5im9wfsvyX0yP1UZWBrAGtDBfH9jEVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.71.2", + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/typescript-estree": "8.71.2", + "@typescript-eslint/visitor-keys": "8.71.2", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.2.tgz", + "integrity": "sha512-Pd68GsLVh5ZXlcEccFPdhSOvtHZ/2WU0XsA8zmXOS3F158lVlcTLhfQ6qvtL1RzbMie0Kp8xtbVwAg4nejKPHw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.28.0", - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/typescript-estree": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0", - "debug": "^4.3.4" + "@typescript-eslint/tsconfig-utils": "^8.71.2", + "@typescript-eslint/types": "^8.71.2", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5146,19 +2685,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.28.0.tgz", - "integrity": "sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.2.tgz", + "integrity": "sha512-YF4wgg5iUX5Obywoac27B56FhozMNFhdJSbh11H5GBAwmBtfyRhmgTQqW9tRNNmHDvsZ2CX6UGzoz+YfYn2Leg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0" + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/visitor-keys": "8.71.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5168,17 +2706,35 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.2.tgz", + "integrity": "sha512-jz49TAWokm/7yWD9/o837nYax9DyALxIPOImdImvVzo6canBCZYzin8zJyqNR5k1j9K1DE0bVvr0XYB+99uAdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.28.0.tgz", - "integrity": "sha512-oRoXu2v0Rsy/VoOGhtWrOKDiIehvI+YNrDk5Oqj40Mwm0Yt01FC/Q7nFqg088d3yAsR1ZcZFVfPCTTFCe/KPwg==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.2.tgz", + "integrity": "sha512-cC8UaalCViJkb3rH/xLIvidEwoFRtMZMUqDjjJMGEKaTFwYRHYBcoczlEGHuvkHEO8svRDrgZ0yQgOArFmwang==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.28.0", - "@typescript-eslint/utils": "8.28.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/typescript-estree": "8.71.2", + "@typescript-eslint/utils": "8.71.2", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5188,14 +2744,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.28.0.tgz", - "integrity": "sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.2.tgz", + "integrity": "sha512-y5Ukl3oVp7e/VGxqIoEXoeb/Roj71PAJ4WG/N/RGj+eeDvKRLM15kGr9MijLbN0i03S52zxu31Z98E5gWChJKw==", "dev": true, "license": "MIT", "engines": { @@ -5207,20 +2763,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.28.0.tgz", - "integrity": "sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.2.tgz", + "integrity": "sha512-DgNOEsl4pdYzwSL+N/Cl33tX1Hlw3FvId73LnKXfq7jnrF2viOEn7X+P7RBkkSWCVm92gnWd28GIC5vJuLREeA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" + "@typescript-eslint/project-service": "8.71.2", + "@typescript-eslint/tsconfig-utils": "8.71.2", + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/visitor-keys": "8.71.2", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5230,33 +2787,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.28.0.tgz", - "integrity": "sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.2.tgz", + "integrity": "sha512-RyKa1G1M9rKHDhrk+HJtiF1MvLD5Ux2JW3TSkzw+02pRALdpJb+QzG1Y5em+LvCgzGwgg8H7mBRFKljNz7ImPw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.28.0", - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/typescript-estree": "8.28.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.71.2", + "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/typescript-estree": "8.71.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5266,19 +2810,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.28.0.tgz", - "integrity": "sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==", + "version": "8.71.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.2.tgz", + "integrity": "sha512-zozlN0UA32bSG2zkKAgQyRYSbEISVoyU6vvkKYo2aSny74D8Jh4e+POkJ6Lk0dlezZi5x7TtD+88Xb06IB8nhg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.28.0", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.71.2", + "eslint-visitor-keys": "^5.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5289,22 +2833,22 @@ } }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.4.0.tgz", + "integrity": "sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==", "dev": true, "license": "ISC" }, @@ -5483,58 +3027,61 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "event-target-shim": "^5.0.0" + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" }, "engines": { - "node": ">=6.5" + "node": ">= 0.6" } }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/accepts/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, + "peer": true, "engines": { "node": ">= 0.6" } }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "node_modules/accepts/node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "dev": true, "license": "MIT", - "bin": { - "acorn": "bin/acorn" + "peer": true, + "dependencies": { + "mime-db": "^1.54.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/acorn-import-phases": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.3.tgz", - "integrity": "sha512-jtKLnfoOzm28PazuQ4dVBcE9Jeo6ha1GAJvq3N0LlNOszmTfx+wSycBehn+FN0RnyeR77IBxN/qVYMw0Rlj0Xw==", + "node_modules/acorn": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.19.0.tgz", + "integrity": "sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10.13.0" + "bin": { + "acorn": "bin/acorn" }, - "peerDependencies": { - "acorn": "^8.14.0" + "engines": { + "node": ">=0.4.0" } }, "node_modules/acorn-jsx": { @@ -5548,9 +3095,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", "dev": true, "license": "MIT", "dependencies": { @@ -5561,11 +3108,12 @@ } }, "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 14" } @@ -5583,9 +3131,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -5600,9 +3148,9 @@ } }, "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5618,9 +3166,9 @@ } }, "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", "dependencies": { @@ -5671,16 +3219,13 @@ } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -5709,9 +3254,9 @@ } }, "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -5786,14 +3331,6 @@ "repeat-string": "^1.6.1" } }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -5817,195 +3354,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz", - "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.4", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", - "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3", - "core-js-compat": "^3.40.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.4.tgz", - "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.4" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-syntax-hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz", - "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "hermes-parser": "0.25.1" - } - }, - "node_modules/babel-plugin-transform-flow-enums": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", - "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/plugin-syntax-flow": "^7.12.1" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", - "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": "18 || 20 || >=22" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -6026,14 +3384,17 @@ ], "license": "MIT" }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "node_modules/baseline-browser-mapping": { + "version": "2.11.29", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.29.tgz", + "integrity": "sha512-YeesxhUmR4h5y5V8KF8iBCqJb8YFrBJ++XBTeGcWIaQOYXGN19JM0FoiOjAhwuDoln8owMgXcWBmgHtYSkky2w==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, "engines": { - "node": "^4.5.0 || >= 5.9" + "node": ">=6.0.0" } }, "node_modules/binary-extensions": { @@ -6050,24 +3411,24 @@ } }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.8", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.8.tgz", + "integrity": "sha512-JNcyFQ64OiijEkPzUBTCe+hyPXUD/3LEldGQ6iF5LR1w00mx9o7xtDWHXBY2iItjdCFGoilOLNQbH943ut7pHA==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.16.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", @@ -6092,13 +3453,16 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" } }, "node_modules/braces": { @@ -6122,9 +3486,9 @@ "license": "ISC" }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.29.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.3.tgz", + "integrity": "sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==", "dev": true, "funding": [ { @@ -6142,10 +3506,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "baseline-browser-mapping": "^2.11.26", + "caniuse-lite": "^1.0.30001813", + "electron-to-chromium": "^1.5.439", + "node-releases": "^2.0.57", + "update-browserslist-db": "^1.3.3" }, "bin": { "browserslist": "cli.js" @@ -6155,11 +3520,11 @@ } }, "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.2.tgz", + "integrity": "sha512-V2o8YS2EhrKMO9AumnkK0ynynfFlsajpYupwq7S46H5mhcanwxDkNTw3K67wPIcKTH1ffkA4vhMOtAc7gRmPZw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "peer": true, "dependencies": { "node-int64": "^0.4.0" @@ -6207,15 +3572,15 @@ } }, "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" }, "engines": { @@ -6253,46 +3618,7 @@ "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "callsites": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/caller-callsite/node_modules/callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "caller-callsite": "^2.0.0" - }, - "engines": { - "node": ">=4" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/callsites": { @@ -6306,20 +3632,22 @@ } }, "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001707", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz", - "integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==", + "version": "1.0.30001816", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001816.tgz", + "integrity": "sha512-+8Yx7BXCoqk6IF8yTicjfUR6D/ldJzdlsodlEOiOSPmhK844WIgk67/zIQaGAOxNkZyyvBlrRFnLvqKIoqbAFw==", "dev": true, "funding": [ { @@ -6422,6 +3750,22 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/chalk/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6486,26 +3830,6 @@ "node": ">= 6" } }, - "node_modules/chrome-launcher": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", - "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0" - }, - "bin": { - "print-chrome-path": "bin/print-chrome-path.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, "node_modules/chrome-trace-event": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", @@ -6516,40 +3840,10 @@ "node": ">=6.0" } }, - "node_modules/chromium-edge-launcher": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz", - "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0", - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "node_modules/chromium-edge-launcher/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", "dev": true, "funding": [ { @@ -6571,9 +3865,9 @@ "peer": true }, "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dev": true, "license": "MIT", "peer": true, @@ -6599,40 +3893,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -6761,25 +4021,10 @@ "node": ">= 0.6" } }, - "node_modules/core-js-compat": { - "version": "3.41.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz", - "integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "browserslist": "^4.24.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", "dev": true, "license": "MIT", "dependencies": { @@ -6788,49 +4033,10 @@ }, "engines": { "node": ">= 0.10" - } - }, - "node_modules/cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cosmiconfig/node_modules/import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cosmiconfig/node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/create-require": { @@ -6855,34 +4061,19 @@ "node": ">= 8" } }, - "node_modules/cssstyle": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.3.0.tgz", - "integrity": "sha512-6r0NiY0xizYqfBvWp1G7WXJ06/bZyrk7Dc6PHql82C/pKGUTKu4yAX4Y8JPamb1ob9nBKuxWzCGTRuGwU3yxJQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@asamuzakjp/css-color": "^3.1.1", - "rrweb-cssom": "^0.8.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/cucumber-tsflow": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/cucumber-tsflow/-/cucumber-tsflow-4.4.4.tgz", - "integrity": "sha512-oe2fPcAxWljZTc4+u0whbXIxZvjWzXfsieoY/TGuHY4aDLLOCFVLOVIxV8bKEI53PQhxJH809VugWHe2DB+nJg==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/cucumber-tsflow/-/cucumber-tsflow-4.6.1.tgz", + "integrity": "sha512-M4QMjM4FBVFnZN53uAj8IAprtcyfcKZ2eqO0d7YL/ZjcpI3F1PqTD4aKCmQuugtnqvrjIIo51tF6j91QAAcI7w==", "dev": true, "license": "MIT", "dependencies": { - "callsites": "^3.1.0", "log4js": "^6.3.0", "source-map-support": "^0.5.19", "underscore": "^1.8.3" }, "peerDependencies": { - "@cucumber/cucumber": "^7 || ^8 || ^9 || ^10" + "@cucumber/cucumber": "^7 || ^8 || ^9 || ^10 || ^11 || ^12" } }, "node_modules/custom-event": { @@ -6892,20 +4083,6 @@ "dev": true, "license": "MIT" }, - "node_modules/data-urls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/date-format": { "version": "4.0.14", "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", @@ -6917,9 +4094,9 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -6947,13 +4124,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decimal.js": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", - "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", - "dev": true, - "license": "MIT" - }, "node_modules/deep-eql": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", @@ -7023,6 +4193,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", @@ -7080,25 +4261,15 @@ "license": "MIT" }, "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -7140,14 +4311,6 @@ "node": ">= 0.4" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -7156,9 +4319,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.128", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.128.tgz", - "integrity": "sha512-bo1A4HH/NS522Ws0QNFIzyPcyUUNV/yyy70Ho1xqfGYzPUme2F/xr4tlEOuM6/A538U1vDA7a4XfCd1CKRegKQ==", + "version": "1.5.459", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.459.tgz", + "integrity": "sha512-4SC9HHSFjO/liAhifpdOL5hG9b4BP7/5G3y3UPZVO8trlAXr1CaUEEJL0gWK3kOcYcZrOA5rkwG45Gra/lTIgg==", "dev": true, "license": "ISC" }, @@ -7180,21 +4343,21 @@ } }, "node_modules/engine.io": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", - "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", + "version": "6.6.11", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.11.tgz", + "integrity": "sha512-z34mGpLoY/82ZbkX1LqGMIaf3wjVMPL6gVC681QDqnmzJ26synI8qAE32P+a7UazmpJZ8UGrFIeAavgRfXzYrg==", "dev": true, "license": "MIT", "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", + "@types/ws": "^8.5.12", "accepts": "~1.3.4", - "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", - "debug": "~4.3.1", + "debug": "~4.4.1", "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" + "ws": "~8.21.0" }, "engines": { "node": ">=10.2.0" @@ -7210,28 +4373,34 @@ "node": ">=10.0.0" } }, - "node_modules/engine.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "node_modules/engine.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, "node_modules/engine.io/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", "dev": true, "license": "MIT", "engines": { @@ -7251,14 +4420,14 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.26.0.tgz", + "integrity": "sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" }, "engines": { "node": ">=10.13.0" @@ -7280,30 +4449,6 @@ "node": ">= 0.4" } }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, "node_modules/error-stack-parser": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", @@ -7336,16 +4481,16 @@ } }, "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "dev": true, "license": "MIT", "dependencies": { @@ -7379,9 +4524,9 @@ "license": "MIT" }, "node_modules/esbuild": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", - "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7392,31 +4537,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.1", - "@esbuild/android-arm": "0.25.1", - "@esbuild/android-arm64": "0.25.1", - "@esbuild/android-x64": "0.25.1", - "@esbuild/darwin-arm64": "0.25.1", - "@esbuild/darwin-x64": "0.25.1", - "@esbuild/freebsd-arm64": "0.25.1", - "@esbuild/freebsd-x64": "0.25.1", - "@esbuild/linux-arm": "0.25.1", - "@esbuild/linux-arm64": "0.25.1", - "@esbuild/linux-ia32": "0.25.1", - "@esbuild/linux-loong64": "0.25.1", - "@esbuild/linux-mips64el": "0.25.1", - "@esbuild/linux-ppc64": "0.25.1", - "@esbuild/linux-riscv64": "0.25.1", - "@esbuild/linux-s390x": "0.25.1", - "@esbuild/linux-x64": "0.25.1", - "@esbuild/netbsd-arm64": "0.25.1", - "@esbuild/netbsd-x64": "0.25.1", - "@esbuild/openbsd-arm64": "0.25.1", - "@esbuild/openbsd-x64": "0.25.1", - "@esbuild/sunos-x64": "0.25.1", - "@esbuild/win32-arm64": "0.25.1", - "@esbuild/win32-ia32": "0.25.1", - "@esbuild/win32-x64": "0.25.1" + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" } }, "node_modules/escalade": { @@ -7525,14 +4671,14 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.5.tgz", - "integrity": "sha512-IKKP8R87pJyMl7WWamLgPkloB16dagPIdd2FjBDbyRYPKo93wS/NbCOPh6gH+ieNLC+XZrhJt/kWj0PS/DFdmg==", + "version": "5.5.7", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.7.tgz", + "integrity": "sha512-WjHyn3GrFd+ZR0rzsLiM4zJZ35PZMOE0SUIxzGmnWNG0126yNfJKJzObmmkYDwHJfGlkz3PSlzyG9ez/LJntwg==", "dev": true, "license": "MIT", "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.10.2" + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.12.3" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -7621,10 +4767,17 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -7632,11 +4785,31 @@ "concat-map": "0.0.1" } }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -7646,9 +4819,9 @@ } }, "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -7691,9 +4864,9 @@ } }, "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -7754,17 +4927,6 @@ "node": ">= 0.6" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -7783,26 +4945,27 @@ } }, "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "version": "30.5.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.5.2.tgz", + "integrity": "sha512-0LNuMvs8/5mRYhnCR4k+lGV7fqPMs6Bnksda4S3zsCUmdxBpAn4zU4NNzXdq1pMKe/H4W5t/zVIDSJ/H3e0vDA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" + "@jest/expect-utils": "30.5.2", + "@jest/get-type": "30.5.0", + "jest-matcher-utils": "30.5.2", + "jest-message-util": "30.5.1", + "jest-mock": "30.5.2", + "jest-util": "30.5.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/exponential-backoff": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", - "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", "dev": true, "license": "Apache-2.0", "peer": true @@ -7828,36 +4991,6 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -7896,30 +5029,62 @@ "license": "BSD-3-Clause" }, "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz", + "integrity": "sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==", "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, + "node_modules/fb-dotslash": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/fb-dotslash/-/fb-dotslash-0.5.8.tgz", + "integrity": "sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA==", + "dev": true, + "license": "(MIT OR Apache-2.0)", + "peer": true, + "bin": { + "dotslash": "bin/dotslash" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.4.tgz", + "integrity": "sha512-tGQtaoYisPDriJBN0mT5yZSyNETnJGA1gTYxaVRAE5KUO3LI9kPUc9WIu8JXcxaIci+faIKlzXqXyPgrmubtBQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "peer": true, "dependencies": { - "bser": "2.1.1" + "bser": "2.1.2" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", "license": "MIT" }, "node_modules/figures": { @@ -8025,22 +5190,6 @@ "node": ">= 0.8" } }, - "node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -8058,6 +5207,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -8084,9 +5247,9 @@ } }, "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", "dev": true, "license": "ISC" }, @@ -8098,21 +5261,35 @@ "license": "MIT", "peer": true }, + "node_modules/flow-estree": { + "version": "0.327.0", + "resolved": "https://registry.npmjs.org/flow-estree/-/flow-estree-0.327.0.tgz", + "integrity": "sha512-f9vK751YUzD0qaHSpKc5/qQM6gqOlgGS+4ZRqTNcZOpVqn3mC55yEQ6dUG2K1eaVm5FbKkz9CFWe6XNvrkQFQg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, "node_modules/flow-parser": { - "version": "0.266.1", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.266.1.tgz", - "integrity": "sha512-dON6h+yO7FGa/FO5NQCZuZHN0o3I23Ev6VYOJf9d8LpdrArHPt39wE++LLmueNV/hNY5hgWGIIrgnrDkRcXkPg==", + "version": "0.327.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.327.0.tgz", + "integrity": "sha512-/MYZ5hXWf5ozpbdfUDmazMgQXviLxWEiRLH3MppEGDdW0itRVqmB5UaU7QX+SBCDNiq+gEesSVn8nlxmPDyDkw==", "dev": true, "license": "MIT", "peer": true, + "dependencies": { + "flow-estree": "0.327.0" + }, "engines": { "node": ">=0.4.0" } }, "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.1.tgz", + "integrity": "sha512-FNvFGzoMLWmE6Yj9spb/zjd7yiNCHiAW9/Tg9CXrQ8wuu32HtlJOwWO11OJafl5FfY3DxTdQ0vj42zU1kvv5jg==", "dev": true, "funding": [ { @@ -8146,36 +5323,18 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -8249,6 +5408,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -8305,17 +5474,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", @@ -8330,36 +5488,20 @@ "node": ">= 0.4" } }, - "node_modules/get-tsconfig": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", - "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "peer": true, "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "engines": { + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -8378,13 +5520,6 @@ "node": ">=10.13.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause" - }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -8525,9 +5660,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "dev": true, "license": "MIT", "dependencies": { @@ -8547,67 +5682,53 @@ "he": "bin/he" } }, - "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "node_modules/hermes-compiler": { + "version": "260318099.0.4", + "resolved": "https://registry.npmjs.org/hermes-compiler/-/hermes-compiler-260318099.0.4.tgz", + "integrity": "sha512-8odcPFkPC82HlqCl0C5QI9mBN4rEAT+IAo55sJhzwKw//K3qZloiv3ex6J2O8CuBbhdmkJozfidNsset2KH25w==", "dev": true, "license": "MIT", "peer": true }, - "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "hermes-estree": "0.25.1" - } - }, "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.3.tgz", + "integrity": "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==", "dev": true, "license": "ISC", - "peer": true - }, - "node_modules/html-encoding-sniffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "dev": true, - "license": "MIT", + "peer": true, "dependencies": { - "whatwg-encoding": "^3.1.1" + "lru-cache": "^11.1.0" }, "engines": { - "node": ">=18" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "dev": true, "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, "license": "MIT", "engines": { @@ -8629,26 +5750,13 @@ "node": ">=8.0.0" } }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/https-proxy-agent": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "agent-base": "^7.1.2", "debug": "4" @@ -8700,32 +5808,15 @@ "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.12.tgz", + "integrity": "sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==", "dev": true, "license": "MIT", "engines": { "node": ">= 4" } }, - "node_modules/image-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.0.tgz", - "integrity": "sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "queue": "6.0.2" - }, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=16.x" - } - }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -8764,6 +5855,20 @@ "node": ">=8" } }, + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -8822,14 +5927,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -8857,13 +5954,13 @@ } }, "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.17.0.tgz", + "integrity": "sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "hasown": "^2.0.4" }, "engines": { "node": ">= 0.4" @@ -8889,17 +5986,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -8938,14 +6024,15 @@ } }, "node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" }, @@ -9031,27 +6118,6 @@ "node": ">=8" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true, - "license": "MIT" - }, "node_modules/is-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -9165,291 +6231,299 @@ "dev": true, "license": "ISC" }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "node_modules/jest-diff": { + "version": "30.5.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.5.2.tgz", + "integrity": "sha512-rBtHnI6BWTiWj3lM7fOLVfChx7R9B0u9VV3PRHawKs79x6ZjW1QoSrKenaigNGWlvhtoi2BqvDbABDie+Os3xQ==", "dev": true, "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "@jest/diff-sequences": "30.5.0", + "@jest/get-type": "30.5.0", + "chalk": "^4.1.2", + "pretty-format": "30.5.1" }, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, - "license": "ISC", + "license": "MIT", "peer": true, - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "node_modules/jest-matcher-utils": { + "version": "30.5.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.5.2.tgz", + "integrity": "sha512-lFkB365PTIHOhPzwrb9T6gvlDnPpOZ7/c3ewOKKB7bzztqjVrtlyRL2MkyfJXpyY2u2SKw001JKrTx14fBUFcQ==", "dev": true, - "license": "BlueOak-1.0.0", - "peer": true, + "license": "MIT", "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@jest/get-type": "30.5.0", + "chalk": "^4.1.2", + "jest-diff": "30.5.2", + "pretty-format": "30.5.1" }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "node_modules/jest-message-util": { + "version": "30.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.5.1.tgz", + "integrity": "sha512-UdQlLdd9wL/Ys7xRErckqwD6wPlSZYueosSWuHc1r2ztGLwlgPvtSJq2+BPEgaEY13WLvfFbmhTj8pba0Sd1jg==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.5.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-util": "30.5.1", + "picomatch": "^4.0.3", + "pretty-format": "30.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "node_modules/jest-mock": { + "version": "30.5.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.5.2.tgz", + "integrity": "sha512-KTHb37Fhj8xY8qPFvTFaFJHcdsumQp+ExsUlgoX232Agmc706gagBs53+CYvulV7MVQo9AgXOUxsqzzVBoJlrA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", + "@jest/expect-utils": "30.5.2", + "@jest/types": "30.5.1", "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "jest-util": "30.5.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "node_modules/jest-regex-util": { + "version": "30.5.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.5.0.tgz", + "integrity": "sha512-Mg0WK7A6xRHLSA1udJ8y9f3lM0uUhFTBnLKzwPmqB9AylvpleJ6BLemR8K9dK27DY+cesDryoA7yLZCAHsPG1A==", "dev": true, "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "node_modules/jest-util": { + "version": "30.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.5.1.tgz", + "integrity": "sha512-yKuxmNy2rSbTXw+3SIPanJo+nV4/BS1p26v44IYBFMsswSQySfMMcPHErnOncda7i9HEz0q605rIhSTBVgrZTg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", + "@jest/types": "30.5.1", "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-matcher-utils": { + "node_modules/jest-validate": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-diff": "^29.7.0", "jest-get-type": "^29.6.3", + "leven": "^3.1.0", "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "node_modules/jest-validate/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "node_modules/jest-validate/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@jest/types": "^29.6.3", + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "jest-util": "^29.7.0" + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "node_modules/jest-validate/node_modules/@sinclair/typebox": { + "version": "0.27.12", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz", + "integrity": "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/jest-validate/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", "peer": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-util": { + "node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@jest/types": "^29.6.3", "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-util/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/jest-worker/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8.6" + "peer": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "node_modules/jest-worker/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/jest-worker/node_modules/@sinclair/typebox": { + "version": "0.27.12", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz", + "integrity": "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/jest-worker/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", "peer": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/jest-worker": { + "node_modules/jest-worker/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-worker/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -9458,9 +6532,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.2.tgz", + "integrity": "sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==", "dev": true, "license": "MIT", "dependencies": { @@ -9479,103 +6553,6 @@ "license": "0BSD", "peer": true }, - "node_modules/jscodeshift": { - "version": "17.3.0", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-17.3.0.tgz", - "integrity": "sha512-LjFrGOIORqXBU+jwfC9nbkjmQfFldtMIoS6d9z2LG/lkmyNXsJAySPT+2SWXJEoE68/bCWcxKpXH37npftgmow==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/core": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/plugin-transform-class-properties": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.24.7", - "@babel/preset-flow": "^7.24.7", - "@babel/preset-typescript": "^7.24.7", - "@babel/register": "^7.24.6", - "flow-parser": "0.*", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.7", - "neo-async": "^2.5.0", - "picocolors": "^1.0.1", - "recast": "^0.23.11", - "tmp": "^0.2.3", - "write-file-atomic": "^5.0.1" - }, - "bin": { - "jscodeshift": "bin/jscodeshift.js" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@babel/preset-env": "^7.1.6" - }, - "peerDependenciesMeta": { - "@babel/preset-env": { - "optional": true - } - } - }, - "node_modules/jscodeshift/node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/jsdom": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", - "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssstyle": "^4.2.1", - "data-urls": "^5.0.0", - "decimal.js": "^10.5.0", - "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.6", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.16", - "parse5": "^7.2.1", - "rrweb-cssom": "^0.8.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^5.1.1", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^3.1.1", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.1.1", - "ws": "^8.18.0", - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "canvas": "^3.0.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -9597,21 +6574,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -9800,22 +6762,28 @@ "webpack": "^5.0.0" } }, + "node_modules/karma-webpack/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/karma-webpack/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/karma-webpack/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -9833,10 +6801,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/karma-webpack/node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/karma-webpack/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -9846,10 +6825,33 @@ "node": "*" } }, + "node_modules/karma-webpack/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/karma/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/karma/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -9861,7 +6863,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -9893,9 +6895,9 @@ } }, "node_modules/karma/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -9928,17 +6930,6 @@ "json-buffer": "3.0.1" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/knuth-shuffle-seeded": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/knuth-shuffle-seeded/-/knuth-shuffle-seeded-1.0.6.tgz", @@ -9975,61 +6966,12 @@ "node": ">= 0.8.0" } }, - "node_modules/lighthouse-logger": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", - "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "debug": "^2.6.9", - "marky": "^1.2.2" - } - }, - "node_modules/lighthouse-logger/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/lighthouse-logger/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/lil-uuid": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/lil-uuid/-/lil-uuid-0.1.1.tgz", "integrity": "sha512-GhWI8f61tBlMeqULZ1QWhFiiyFIFdPlg//S8Udq1wjq1FJhpFKTfnbduSxAQjueofeUtpr7UvQ/lIK/sKUF8dg==", "license": "MIT" }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.11.5" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -10047,20 +6989,12 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true, "license": "MIT" }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -10076,6 +7010,14 @@ "license": "MIT", "peer": true }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -10161,16 +7103,20 @@ } }, "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "version": "11.5.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", + "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", "dev": true, - "license": "ISC" + "license": "BlueOak-1.0.0", + "peer": true, + "engines": { + "node": "20 || >=22" + } }, "node_modules/luxon": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.2.1.tgz", - "integrity": "sha512-QrwPArQCNLAKGO/C+ZIilgIuDnEnKx5QYODdDtbFaxzsbZcc/a7WFq7MhsVYgRlwawLtvOUESTlfJ+hc/USqPg==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", "dev": true, "license": "MIT", "peer": true, @@ -10179,39 +7125,13 @@ } }, "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/make-error": { @@ -10221,25 +7141,6 @@ "dev": true, "license": "ISC" }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/marky": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", - "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", - "dev": true, - "license": "Apache-2.0", - "peer": true - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -10275,58 +7176,45 @@ "dev": true, "license": "MIT" }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/metro": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro/-/metro-0.81.4.tgz", - "integrity": "sha512-78f0aBNPuwXW7GFnSc+Y0vZhbuQorXxdgqQfvSRqcSizqwg9cwF27I05h47tL8AzQcizS1JZncvq4xf5u/Qykw==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.87.1.tgz", + "integrity": "sha512-1oyLU9elM7hPAsKIqKooEekwxiuWr27+MZBhUROPhzcbXhMDxK64GPF/hCXwBZVp1F89ODavCrBmJtLx9WtBoQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/code-frame": "^7.24.7", + "@babel/code-frame": "^7.29.0", "@babel/core": "^7.25.2", - "@babel/generator": "^7.25.0", - "@babel/parser": "^7.25.3", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.3", - "@babel/types": "^7.25.2", - "accepts": "^1.3.7", - "chalk": "^4.0.0", - "ci-info": "^2.0.0", + "@babel/generator": "^7.29.1", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "accepts": "^2.0.0", "connect": "^3.6.5", - "debug": "^2.2.0", + "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", + "flow-parser": "0.331.0", "graceful-fs": "^4.2.4", - "hermes-parser": "0.25.1", - "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", - "metro-babel-transformer": "0.81.4", - "metro-cache": "0.81.4", - "metro-cache-key": "0.81.4", - "metro-config": "0.81.4", - "metro-core": "0.81.4", - "metro-file-map": "0.81.4", - "metro-resolver": "0.81.4", - "metro-runtime": "0.81.4", - "metro-source-map": "0.81.4", - "metro-symbolicate": "0.81.4", - "metro-transform-plugins": "0.81.4", - "metro-transform-worker": "0.81.4", - "mime-types": "^2.1.27", + "metro-babel-transformer": "0.87.1", + "metro-cache": "0.87.1", + "metro-cache-key": "0.87.1", + "metro-config": "0.87.1", + "metro-core": "0.87.1", + "metro-file-map": "0.87.1", + "metro-resolver": "0.87.1", + "metro-runtime": "0.87.1", + "metro-source-map": "0.87.1", + "metro-symbolicate": "0.87.1", + "metro-transform-plugins": "0.87.1", + "metro-transform-worker": "0.87.1", + "mime-types": "^3.0.1", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", @@ -10338,46 +7226,73 @@ "metro": "src/cli.js" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/metro-babel-transformer": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.81.4.tgz", - "integrity": "sha512-WW0yswWrW+eTVK9sYD+b1HwWOiUlZlUoomiw9TIOk0C+dh2V90Wttn/8g62kYi0Y4i+cJfISerB2LbV4nuRGTA==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.87.1.tgz", + "integrity": "sha512-orvRIGpb0yK1yMbk5YP3dhVKjmoxUkRB9fdltGJxNppEqus/1tFpNuf9KnGFR3Qjg0izoUrJ4z6WgoBvdkXPrA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", - "hermes-parser": "0.25.1", + "flow-parser": "0.331.0", + "metro-cache-key": "0.87.1", "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + } + }, + "node_modules/metro-babel-transformer/node_modules/flow-estree": { + "version": "0.331.0", + "resolved": "https://registry.npmjs.org/flow-estree/-/flow-estree-0.331.0.tgz", + "integrity": "sha512-FVLYkSL/ITb/QXBEQvNWPjPooRGswuUtGOwrH+puSlMDneNkxy640+FZsk/TfKL+b7Wbw/Fg9FTUv2bMQDpj2w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-babel-transformer/node_modules/flow-parser": { + "version": "0.331.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.331.0.tgz", + "integrity": "sha512-vEZcHIlnKeN8JSVtYFczj8sWJfHIJOkz+YG00O/oul/Bete+t1ZhTi+O6JRRLFYvGW+yJkZ0YgL16iStnbkUqQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "flow-estree": "0.331.0" + }, + "engines": { + "node": ">=0.4.0" } }, "node_modules/metro-cache": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.81.4.tgz", - "integrity": "sha512-sxCPH3gowDxazSaZZrwdNPEpnxR8UeXDnvPjBF9+5btDBNN2DpWvDAXPvrohkYkFImhc0LajS2V7eOXvu9PnvQ==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.87.1.tgz", + "integrity": "sha512-juNPaj0Xi5tkLp8imXqvbSnEIijwKG36m7OiFFVJMqEkiURwAjkMFVek3/xpix1+LVQqO7kjVp3PvuvIM61mKQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", - "metro-core": "0.81.4" + "https-proxy-agent": "^7.0.5", + "metro-core": "0.87.1" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/metro-cache-key": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.81.4.tgz", - "integrity": "sha512-3SaWQybvf1ivasjBegIxzVKLJzOpcz+KsnGwXFOYADQq0VN4cnM7tT+u2jkOhk6yJiiO1WIjl68hqyMOQJRRLg==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.87.1.tgz", + "integrity": "sha512-scqVVPMA2c+RVO12I3wyMDp5xCkRPLsyrcG4Qc3xfU5JR0EW/0sz2tjty+5UjMUtG09uiM1KYQ8HjWg7OQXHtw==", "dev": true, "license": "MIT", "peer": true, @@ -10385,91 +7300,70 @@ "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/metro-config": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.81.4.tgz", - "integrity": "sha512-QnhMy3bRiuimCTy7oi5Ug60javrSa3lPh0gpMAspQZHY9h6y86jwHtZPLtlj8hdWQESIlrbeL8inMSF6qI/i9Q==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.87.1.tgz", + "integrity": "sha512-NmkDlc/qZAdo5gTkVTuO2AKE/khemRKRH5IA+SKfqUBJigI5GqZ5TOXhmEokhlkAqzjt8dyzKhzI6FHvXoXaTQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "connect": "^3.6.5", - "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", - "metro": "0.81.4", - "metro-cache": "0.81.4", - "metro-core": "0.81.4", - "metro-runtime": "0.81.4" + "metro": "0.87.1", + "metro-cache": "0.87.1", + "metro-core": "0.87.1", + "metro-runtime": "0.87.1" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/metro-core": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.81.4.tgz", - "integrity": "sha512-GdL4IgmgJhrMA/rTy2lRqXKeXfC77Rg+uvhUEkbhyfj/oz7PrdSgvIFzziapjdHwk1XYq0KyFh/CcVm8ZawG6A==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.87.1.tgz", + "integrity": "sha512-xizzky/4+c/Mkznege8OW05j7bSdM39VPoEps61Se4+hf32UQujmbvLvIE9+UnP6kNEPVomk0Fw8NsBK9iRQmw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", - "metro-resolver": "0.81.4" + "metro-resolver": "0.87.1" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/metro-file-map": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.81.4.tgz", - "integrity": "sha512-qUIBzkiqOi3qEuscu4cJ83OYQ4hVzjON19FAySWqYys9GKCmxlKa7LkmwqdpBso6lQl+JXZ7nCacX90w5wQvPA==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.87.1.tgz", + "integrity": "sha512-9sPuNCojC3pS4vj+ZPY7FXmHGpdJeckXuKXQrDAfJvZc60AF8owRFTkI8XdwlwrmPIB2w++KraK9FMEXvC4wJw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "debug": "^2.2.0", + "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", - "nullthrows": "^1.1.1", - "walker": "^1.0.7" + "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, - "node_modules/metro-file-map/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/metro-file-map/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/metro-minify-terser": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.81.4.tgz", - "integrity": "sha512-oVvq/AGvqmbhuijJDZZ9npeWzaVyeBwQKtdlnjcQ9fH7nR15RiBr5y2zTdgTEdynqOIb1Kc16l8CQIUSzOWVFA==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.87.1.tgz", + "integrity": "sha512-YK4k1oO1wV48hfE+Nbw2rJCnAgeabzrgT/xH5ha5n9gbK4p3HYFC898cERUiyTl9vRh58CNTiXRc88f7y6PfKg==", "dev": true, "license": "MIT", "peer": true, @@ -10478,13 +7372,13 @@ "terser": "^5.15.0" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/metro-resolver": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.81.4.tgz", - "integrity": "sha512-Ng7G2mXjSExMeRzj6GC19G6IJ0mfIbOLgjArsMWJgtt9ViZiluCwgWsMW9juBC5NSwjJxUMK2x6pC5NIMFLiHA==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.87.1.tgz", + "integrity": "sha512-FXH/brY69wT6sPxaSW8BhMmDGD/6irmBr/cL4rUi+VWwqR3pbvdcfUOfyjcHucgQ7pe5IW3xJY21eHKLVKNumQ==", "dev": true, "license": "MIT", "peer": true, @@ -10492,13 +7386,13 @@ "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/metro-runtime": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.81.4.tgz", - "integrity": "sha512-fBoRgqkF69CwyPtBNxlDi5ha26Zc8f85n2THXYoh13Jn/Bkg8KIDCdKPp/A1BbSeNnkH/++H2EIIfnmaff4uRg==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.87.1.tgz", + "integrity": "sha512-kjeuSvInsM6OzBjkCQsWxnkrKZFMKtnkCl38oXWRI9lDGs2L9hGs9Tak9sQYJ9h3gtDujneB7wZio+irgqJKDw==", "dev": true, "license": "MIT", "peer": true, @@ -10507,30 +7401,29 @@ "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/metro-source-map": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.81.4.tgz", - "integrity": "sha512-IOwVQ7mLqoqvsL70RZtl1EyE3f9jp43kVsAsb/B/zoWmu0/k4mwEhGLTxmjdXRkLJqPqPrh7WmFChAEf9trW4Q==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.87.1.tgz", + "integrity": "sha512-Bqpm0PBGdy53pigIJb4HRF7QxD2pUOdgSmVh/4AWbP635kSCv+Y6ltVxUZgSnzS/QbSmzyCGijmRPlXMj2/qHw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/traverse": "^7.25.3", - "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", - "@babel/types": "^7.25.2", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", - "metro-symbolicate": "0.81.4", + "metro-symbolicate": "0.87.1", "nullthrows": "^1.1.1", - "ob1": "0.81.4", + "ob1": "0.87.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/metro-source-map/node_modules/source-map": { @@ -10545,16 +7438,16 @@ } }, "node_modules/metro-symbolicate": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.81.4.tgz", - "integrity": "sha512-rWxTmYVN6/BOSaMDUHT8HgCuRf6acd0AjHkenYlHpmgxg7dqdnAG1hLq999q2XpW5rX+cMamZD5W5Ez2LqGaag==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.87.1.tgz", + "integrity": "sha512-rcGvwabrg0lbXGRGRKl14PY3My3+dkno2jZYhdJEuH2DmjTtTkV5bYwgto4JtV/Lbe+sXE6GO1UGg654430uow==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", - "metro-source-map": "0.81.4", + "metro-source-map": "0.87.1", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" @@ -10563,7 +7456,7 @@ "metro-symbolicate": "src/index.js" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/metro-symbolicate/node_modules/source-map": { @@ -10578,58 +7471,50 @@ } }, "node_modules/metro-transform-plugins": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.81.4.tgz", - "integrity": "sha512-nlP069nDXm4v28vbll4QLApAlvVtlB66rP6h+ml8Q/CCQCPBXu2JLaoxUmkIOJQjLhMRUcgTyQHq+TXWJhydOQ==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.87.1.tgz", + "integrity": "sha512-qMiJ/x+VfqumFJJSefKS6nj8uojzC29b2/aK8vlMuFABIqGjDucICEOXd2Yt6k/XMFAgAcaJvShUOT0HLyYaPw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", - "@babel/generator": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.3", + "@babel/generator": "^7.29.1", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/metro-transform-worker": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.81.4.tgz", - "integrity": "sha512-lKAeRZ8EUMtx2cA/Y4KvICr9bIr5SE03iK3lm+l9wyn2lkjLUuPjYVep159inLeDqC6AtSubsA8MZLziP7c03g==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.87.1.tgz", + "integrity": "sha512-VOzs3OV405FuOLYdAhqA2wsn1F9lvueDVxMDLvCKaQ44U+yknIqphJ9eMjjsGwLDZiJq9sW3DMLhjD27JxQgqQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", - "@babel/generator": "^7.25.0", - "@babel/parser": "^7.25.3", - "@babel/types": "^7.25.2", + "@babel/generator": "^7.29.1", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", - "metro": "0.81.4", - "metro-babel-transformer": "0.81.4", - "metro-cache": "0.81.4", - "metro-cache-key": "0.81.4", - "metro-minify-terser": "0.81.4", - "metro-source-map": "0.81.4", - "metro-transform-plugins": "0.81.4", + "metro": "0.87.1", + "metro-babel-transformer": "0.87.1", + "metro-cache": "0.87.1", + "metro-cache-key": "0.87.1", + "metro-minify-terser": "0.87.1", + "metro-source-map": "0.87.1", + "metro-transform-plugins": "0.87.1", "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, - "node_modules/metro/node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/metro/node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -10646,82 +7531,75 @@ "node": ">=12" } }, - "node_modules/metro/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/metro/node_modules/flow-estree": { + "version": "0.331.0", + "resolved": "https://registry.npmjs.org/flow-estree/-/flow-estree-0.331.0.tgz", + "integrity": "sha512-FVLYkSL/ITb/QXBEQvNWPjPooRGswuUtGOwrH+puSlMDneNkxy640+FZsk/TfKL+b7Wbw/Fg9FTUv2bMQDpj2w==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">=18" } }, - "node_modules/metro/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/metro/node_modules/flow-parser": { + "version": "0.331.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.331.0.tgz", + "integrity": "sha512-vEZcHIlnKeN8JSVtYFczj8sWJfHIJOkz+YG00O/oul/Bete+t1ZhTi+O6JRRLFYvGW+yJkZ0YgL16iStnbkUqQ==", "dev": true, "license": "MIT", - "peer": true + "peer": true, + "dependencies": { + "flow-estree": "0.331.0" + }, + "engines": { + "node": ">=0.4.0" + } }, - "node_modules/metro/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "node_modules/metro/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "peer": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/metro/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/metro/node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "mime-db": "^1.54.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/metro/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "node_modules/metro/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "peer": true, "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node": ">=0.10.0" } }, "node_modules/metro/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", "dev": true, "license": "MIT", "peer": true, @@ -10755,6 +7633,7 @@ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -10764,11 +7643,12 @@ } }, "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=8.6" }, @@ -10814,16 +7694,16 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^5.0.8" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -10839,21 +7719,109 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minimizer-webpack-plugin": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.13.1.tgz", + "integrity": "sha512-1mhAfvachWYYOm8tpmany5NLuvP+F2wxZWBSX8DC0uFS2wJpM9q3rWgN9wBooAH9d5V12wX0BjyJe4fMjHMarQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "jest-worker": "^27.4.5", + "schema-utils": "^4.6.0", + "terser": "^5.51.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@napi-rs/image": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "imagemin": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "sharp": { + "optional": true + }, + "svgo": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/minimizer-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "peer": true, "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/mkdirp": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", - "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "dev": true, "license": "MIT", "peer": true, @@ -10910,6 +7878,23 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/mocha/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/mocha/node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -10977,7 +7962,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -11043,6 +8028,25 @@ "randombytes": "^2.1.0" } }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -11070,21 +8074,37 @@ "license": "MIT" }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.1.0.tgz", + "integrity": "sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==", "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "content-type": "^2.1.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "node_modules/negotiator/node_modules/content-type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", + "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } }, "node_modules/nise": { "version": "1.5.3", @@ -11100,16 +8120,6 @@ "path-to-regexp": "^1.7.0" } }, - "node_modules/nise/node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, "node_modules/nise/node_modules/lolex": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", @@ -11120,16 +8130,6 @@ "@sinonjs/commons": "^1.7.0" } }, - "node_modules/nise/node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -11143,13 +8143,13 @@ } }, "node_modules/nock": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.3.tgz", - "integrity": "sha512-sJ9RNmCuYBqXDmGZZHgZ1D1441MqFOU4T5aeLGVGEB4OWI/2LM0mZlkfBQzQKdOfJypL+2nPPBugXKjixBn4kQ==", + "version": "14.0.17", + "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.17.tgz", + "integrity": "sha512-EjRr1weMa4ALQX35AgZTEnP+weJJjlW1KGDiNM2IQC2069YDHas4f4B4UUYR+TTLyKWxJvOz2wObDKQs/LNreA==", "dev": true, "license": "MIT", "dependencies": { - "@mswjs/interceptors": "^0.38.1", + "@mswjs/interceptors": "^0.41.0", "json-stringify-safe": "^5.0.1", "propagate": "^2.0.0" }, @@ -11178,42 +8178,6 @@ } } }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, - "license": "(BSD-3-Clause OR GPL-2.0)", - "peer": true, - "engines": { - "node": ">= 6.13.0" - } - }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -11223,35 +8187,29 @@ "peer": true }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.59", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.59.tgz", + "integrity": "sha512-5qr2okC4ItAI0hG5SaV0HoYMpnM/Y6+Oqr7AmPYy/2uEoGvS+GbSKLeRxSS1uAdu59yz0ouzcuXievSgg///WA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-8.0.0.tgz", + "integrity": "sha512-RWk+PI433eESQ7ounYxIp67CYuVsS1uYSonX3kA6ps/3LWfjVQa/ptEg6Y3T6uAMq1mWpX9PQ+qx+QaHpsc7gQ==", "dev": true, "license": "BSD-2-Clause", "peer": true, "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver" + "hosted-git-info": "^9.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/normalize-path": { @@ -11272,17 +8230,10 @@ "license": "MIT", "peer": true }, - "node_modules/nwsapi": { - "version": "2.2.20", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", - "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==", - "dev": true, - "license": "MIT" - }, "node_modules/ob1": { - "version": "0.81.4", - "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.81.4.tgz", - "integrity": "sha512-EZLYM8hfPraC2SYOR5EWLFAPV5e6g+p83m2Jth9bzCpFxP1NDQJYXdmXRB2bfbaWQSmm6NkIQlbzk7uU5lLfgg==", + "version": "0.87.1", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.87.1.tgz", + "integrity": "sha512-i8iA8uij0g1YQzS8uOJPSRCgwDjO9warIHUAu1Fqj877Wc3wlfxDYBioYWgKTBF2+URVJttyDWSEpmd99nlvtQ==", "dev": true, "license": "MIT", "peer": true, @@ -11290,7 +8241,7 @@ "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": ">=18.18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" } }, "node_modules/object-assign": { @@ -11367,18 +8318,19 @@ } }, "node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11441,25 +8393,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0", - "peer": true - }, "node_modules/pad-right": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/pad-right/-/pad-right-0.2.2.tgz", @@ -11488,31 +8421,22 @@ } }, "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^4.5.0" + "node": ">=18" }, "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/parseurl": { @@ -11538,193 +8462,86 @@ "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "peer": true, - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-to-regexp": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", - "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "locate-path": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", "peer": true, "dependencies": { - "p-try": "^2.0.0" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { - "node": ">=6" + "node": "18 || 20 || >=22" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "p-limit": "^2.0.0" - }, + "isarray": "0.0.1" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": "*" } }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/possible-typed-array-names": { @@ -11748,9 +8565,9 @@ } }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.10.tgz", + "integrity": "sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==", "dev": true, "license": "MIT", "bin": { @@ -11764,9 +8581,9 @@ } }, "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", "dev": true, "license": "MIT", "dependencies": { @@ -11777,31 +8594,19 @@ } }, "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "version": "30.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.5.1.tgz", + "integrity": "sha512-byhRAPguVKMQIj4kjJwJ5lAskVhfuiSdiYl/aLTWpgkGEmic2jYhJh1yE9ih8Ox44Xg9ccCT11/S6QrzSJuNrg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "@jest/react-is-18": "npm:react-is@^18.3.1", + "@jest/react-is-19": "npm:react-is@^19.2.5", + "@jest/schemas": "30.5.0", + "ansi-styles": "^5.2.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/process": { @@ -11872,13 +8677,14 @@ } }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.1.tgz", + "integrity": "sha512-5Px6J7rfHBAGUhNQ3es4YzcOdBBw0SDcVtThJml4RdnKw4tKs2epA0kPZ+K8X+WiHktT93RHVcQ/3ym5aTCgtg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" }, "engines": { "node": ">=0.6" @@ -11887,17 +8693,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "inherits": "~2.0.3" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -11937,35 +8732,39 @@ } }, "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.3.0.tgz", + "integrity": "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, "node_modules/react": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", - "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "version": "19.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.3.1.tgz", + "integrity": "sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==", "dev": true, "license": "MIT", "peer": true, @@ -11974,9 +8773,9 @@ } }, "node_modules/react-devtools-core": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.1.tgz", - "integrity": "sha512-TFo1MEnkqE6hzAbaztnyR5uLTMoz6wnEWwWBsCUzNt+sVXJycuRJdDqvL078M4/h65BI/YO5XWTaxZDWVsW0fw==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.5.tgz", + "integrity": "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==", "dev": true, "license": "MIT", "peer": true, @@ -11985,90 +8784,61 @@ "ws": "^7" } }, - "node_modules/react-devtools-core/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/react-native": { - "version": "0.78.1", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.78.1.tgz", - "integrity": "sha512-3CK/xxX02GeeVFyrXbsHvREZFVaXwHW43Km/EdYITn5G32cccWTGaqY9QdPddEBLw5O3BPip3LHbR1SywE0cpA==", + "version": "0.88.0", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.88.0.tgz", + "integrity": "sha512-v/wee0nYWcammMYBnSat/e3WY/5iaf9YQOMcBrfKT/wPApPPlHp94hgZovBtwhMuthR01yc/8cGn0FpFTE/C4A==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@jest/create-cache-key-function": "^29.6.3", - "@react-native/assets-registry": "0.78.1", - "@react-native/codegen": "0.78.1", - "@react-native/community-cli-plugin": "0.78.1", - "@react-native/gradle-plugin": "0.78.1", - "@react-native/js-polyfills": "0.78.1", - "@react-native/normalize-colors": "0.78.1", - "@react-native/virtualized-lists": "0.78.1", - "abort-controller": "^3.0.0", + "@react-native/asset-utils": "0.88.0", + "@react-native/codegen": "0.88.0", + "@react-native/community-cli-plugin": "0.88.0", + "@react-native/gradle-plugin": "0.88.0", + "@react-native/normalize-colors": "0.88.0", + "@react-native/virtualized-lists": "0.88.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", - "babel-jest": "^29.7.0", - "babel-plugin-syntax-hermes-parser": "0.25.1", "base64-js": "^1.5.1", - "chalk": "^4.0.0", - "commander": "^12.0.0", - "event-target-shim": "^5.0.1", "flow-enums-runtime": "^0.0.6", - "glob": "^7.1.1", + "flow-parser": "0.327.0", + "hermes-compiler": "260318099.0.4", "invariant": "^2.2.4", - "jest-environment-node": "^29.6.3", "memoize-one": "^5.0.0", - "metro-runtime": "^0.81.0", - "metro-source-map": "^0.81.0", + "metro-runtime": "^0.87.1", + "metro-source-map": "^0.87.1", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", - "react-devtools-core": "^6.0.1", + "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", - "scheduler": "0.25.0", + "scheduler": "0.28.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", + "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", - "ws": "^6.2.3", + "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "react-native": "cli.js" }, "engines": { - "node": ">=18" + "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" }, "peerDependencies": { - "@types/react": "^19.0.0", - "react": "^19.0.0" + "@types/react": "^19.1.1", + "react": "^19.3.0" }, "peerDependenciesMeta": { "@types/react": { @@ -12089,27 +8859,37 @@ "react-native": "*" } }, - "node_modules/react-native/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/react-native/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", "peer": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/react-native/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/react-native/node_modules/@sinclair/typebox": { + "version": "0.27.12", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz", + "integrity": "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/react-native/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=8" } }, "node_modules/react-native/node_modules/cliui": { @@ -12128,77 +8908,26 @@ "node": ">=12" } }, - "node_modules/react-native/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/react-native/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/react-native/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/react-native/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/react-native/node_modules/ws": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", - "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "async-limiter": "~1.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/react-native/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", "dev": true, "license": "MIT", "peer": true, @@ -12226,153 +8955,89 @@ "node": ">=12" } }, - "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "p-locate": "^4.1.0" - }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/read-package-up": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-12.0.0.tgz", + "integrity": "sha512-Q5hMVBYur/eQNWDdbF4/Wqqr9Bjvtrw2kjGxxBbKLbx8bVCL8gcArjTy8zDUuLGQicftpMuU0riQNcAsbtOVsw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "p-try": "^2.0.0" + "find-up-simple": "^1.0.1", + "read-pkg": "^10.0.0", + "type-fest": "^5.2.0" }, "engines": { - "node": ">=6" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/read-package-up/node_modules/type-fest": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.10.0.tgz", + "integrity": "sha512-NoSdpq/WEiAg5sjmBkmV/hfxv6HJH4NqPNrqjtSO5CwRmpsDfaf4begxW34KdJykH/l1yHtwBWQkCRdoXO8mPA==", "dev": true, - "license": "MIT", + "license": "(MIT OR CC0-1.0)", "peer": true, "dependencies": { - "p-limit": "^2.2.0" + "tagged-tag": "^1.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "peer": true, - "engines": { - "node": ">=8" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/read-pkg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-10.1.0.tgz", + "integrity": "sha512-I8g2lArQiP78ll51UeMZojewtYgIRCKCWqZEgOO8c/uefTI+XDXvCSXu3+YNUaTNvZzobrL5+SqHjBrByRRTdg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "@types/normalize-package-data": "^2.4.4", + "normalize-package-data": "^8.0.0", + "parse-json": "^8.3.0", + "type-fest": "^5.4.4", + "unicorn-magic": "^0.4.0" }, "engines": { - "node": ">=8" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.10.0.tgz", + "integrity": "sha512-NoSdpq/WEiAg5sjmBkmV/hfxv6HJH4NqPNrqjtSO5CwRmpsDfaf4begxW34KdJykH/l1yHtwBWQkCRdoXO8mPA==", "dev": true, "license": "(MIT OR CC0-1.0)", "peer": true, + "dependencies": { + "tagged-tag": "^1.0.0" + }, "engines": { - "node": ">=8" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/readdirp": { @@ -12389,9 +9054,9 @@ } }, "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -12401,77 +9066,14 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/readline": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", - "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==", - "dev": true, - "license": "BSD", - "peer": true - }, - "node_modules/recast": { - "version": "0.23.11", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", - "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ast-types": "^0.16.1", - "esprima": "~4.0.0", - "source-map": "~0.6.1", - "tiny-invariant": "^1.3.3", - "tslib": "^2.0.1" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/recast/node_modules/ast-types": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", - "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/reflect-metadata": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", - "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==", - "deprecated": "This version has a critical bug in fallback handling. Please upgrade to reflect-metadata@0.2.2 or newer.", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "dev": true, "license": "Apache-2.0", "peer": true }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", - "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", @@ -12480,17 +9082,6 @@ "license": "MIT", "peer": true }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, "node_modules/regexp-match-indices": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regexp-match-indices/-/regexp-match-indices-1.0.2.tgz", @@ -12534,61 +9125,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexpu-core": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", - "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.2.0", - "regjsgen": "^0.8.0", - "regjsparser": "^0.12.0", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/regjsparser": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", - "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "jsesc": "~3.0.2" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -12628,13 +9164,14 @@ "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.13", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.13.tgz", + "integrity": "sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "es-errors": "^1.3.0", + "is-core-module": "^2.17.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -12658,41 +9195,6 @@ "node": ">=4" } }, - "node_modules/resolve-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-2.0.0.tgz", - "integrity": "sha512-+1lzwXehGCXSeryaISr6WujZzowloigEofRB+dj75y9RRa/obVcYgbHJd53tdYw8pvZj8GojXaaENws8Ktw/hQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/resolve-pkg/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -12728,10 +9230,17 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -12743,7 +9252,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -12762,9 +9271,9 @@ } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -12857,13 +9366,6 @@ "dev": true, "license": "MIT" }, - "node_modules/rrweb-cssom": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", - "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", - "dev": true, - "license": "MIT" - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -12934,51 +9436,49 @@ "dev": true, "license": "MIT" }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "license": "ISC", - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, "node_modules/scheduler": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", - "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz", + "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==", "dev": true, "license": "MIT", "peer": true }, "node_modules/schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.8.1.tgz", + "integrity": "sha512-x39pYlJPyH7Uge5QO64B9XGP9zLDc9WNmiQZc+CE3IzZPvMu3lHOuAMGpYNoPixEL7MSWlGhYTg5UlLSL8G6iw==", "dev": true, "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", + "@types/json-schema": "^7.0.15", + "ajv": "^8.20.0", + "ajv-formats": "^3.0.1", "ajv-keywords": "^5.1.0" }, + "bin": { + "schema-utils": "bin/schema-utils.js" + }, "engines": { "node": ">= 10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.112.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, "node_modules/schema-utils/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", "dependencies": { @@ -13020,30 +9520,12 @@ "license": "MIT", "peer": true }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -13051,30 +9533,10 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", "dev": true, "license": "MIT", "peer": true, @@ -13082,16 +9544,16 @@ "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "range-parser": "~1.2.1", - "statuses": "2.0.1" + "statuses": "~2.0.2" }, "engines": { "node": ">= 0.8.0" @@ -13116,6 +9578,17 @@ "license": "MIT", "peer": true }, + "node_modules/send/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -13130,10 +9603,21 @@ "node": ">=4" } }, + "node_modules/send/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, "license": "MIT", "peer": true, @@ -13163,9 +9647,9 @@ } }, "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", "dev": true, "license": "MIT", "peer": true, @@ -13173,7 +9657,7 @@ "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.19.0" + "send": "~0.19.1" }, "engines": { "node": ">= 0.8.0" @@ -13231,20 +9715,6 @@ "dev": true, "license": "ISC" }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -13269,9 +9739,9 @@ } }, "node_modules/shell-quote": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", - "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.12.0.tgz", + "integrity": "sha512-PcByqNyT/38F2kDNi006HAMRJaULuBzq/FOsw3qdZvX/GA9W/jamDaRskgHjubHiftXK5sIFxLNkvrXUwcof6Q==", "dev": true, "license": "MIT", "peer": true, @@ -13283,15 +9753,15 @@ } }, "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" }, @@ -13303,14 +9773,14 @@ } }, "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "object-inspect": "^1.13.4" }, "engines": { "node": ">= 0.4" @@ -13358,20 +9828,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "peer": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/sinon": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", @@ -13393,27 +9849,17 @@ "version": "3.7.0", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "dev": true, - "license": "(BSD-2-Clause OR WTFPL)", - "peerDependencies": { - "chai": "^4.0.0", - "sinon": ">=4.0.0" - } - }, - "node_modules/sinon/node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" + "dev": true, + "license": "(BSD-2-Clause OR WTFPL)", + "peerDependencies": { + "chai": "^4.0.0", + "sinon": ">=4.0.0" } }, "node_modules/sinon/node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.1.tgz", + "integrity": "sha512-Z3u54A8qGyqFOSr2pk0ijYs8mOE9Qz8kTvtKeBI+upoG9j04Sq+oI7W8zAJiQybDcESET8/uIdHzs0p3k4fZlw==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -13443,16 +9889,6 @@ "node": ">=4" } }, - "node_modules/sinon/node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -13464,23 +9900,25 @@ } }, "node_modules/smob": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", - "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.6.2.tgz", + "integrity": "sha512-RQsvleCbF8cVHEv+xuDGaA4pOizFqJ0GgjtMSRo6oP8pnN7WsigHgVGey6aILRBKv4W2YOMHLqbKdnB6hpB9fw==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } }, "node_modules/socket.io": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", - "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.4.tgz", + "integrity": "sha512-9ZV9zg8vN8hO3Y25DhR7nUkJ1VDnBhq5O/JrXhFT9s6+F0gqytSASTHVfCFc2mJXaTfARroErplXlzFWwETZqQ==", "dev": true, "license": "MIT", "dependencies": { "accepts": "~1.3.4", - "base64id": "~2.0.0", "cors": "~2.8.5", - "debug": "~4.3.2", + "debug": "~4.4.1", "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" @@ -13490,38 +9928,20 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", - "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "~4.3.4", - "ws": "~8.17.1" - } - }, - "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.8.tgz", + "integrity": "sha512-6Oy52pbg+kvdCVvjcN+FnY7BvxZ7cIHNScbvztT/It5d0vbwoJoVZmF2gjJmnV0/4WlXRfG15zc45ySk9Ah8bw==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "debug": "~4.4.1", + "ws": "~8.21.0" } }, "node_modules/socket.io-adapter/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", "dev": true, "license": "MIT", "engines": { @@ -13541,53 +9961,41 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.7.tgz", + "integrity": "sha512-IH/iSeO9T6gz1KkFleGDWkG9N3dl4jXVYUtMhIqH10Md0ttMer8nUNWiP1DKuNrybD2xBrixLJdCC9J6ECoYkg==", "dev": true, "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" + "debug": "~4.4.1" }, "engines": { "node": ">=10.0.0" } }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "node_modules/socket.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 0.6" } }, - "node_modules/socket.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "node_modules/socket.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 0.6" } }, "node_modules/source-map": { @@ -13644,9 +10052,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.21", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", - "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", + "version": "3.0.24", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.24.tgz", + "integrity": "sha512-cLS9TtWkIQFyLkJ3/5aFQAOHOSKTlOs/7WDut/XPSdjom1fJhUdkepeJAKXa9Y05+FabHd0sti+Et559vDtkpQ==", "dev": true, "license": "CC0-1.0", "peer": true @@ -13772,23 +10180,6 @@ "node": ">=8" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -13802,32 +10193,6 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-ansi/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -13891,49 +10256,60 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true, - "license": "MIT" - }, "node_modules/synckit": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.10.3.tgz", - "integrity": "sha512-R1urvuyiTaWfeCggqEvpDJwAlDVdsT9NM+IP//Tk2x7qHCkSvBk/fwFgw/TLAHzZlrAnnazMcRw0ZD8HlYFTEQ==", + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.12.3.tgz", + "integrity": "sha512-U+/AXT6LWsxnj2vz9HeUuPWBNgdWxjyIEjEPdbJARC9txmgPzo2VEdqnFo4hHaNyMPtycyVJrSaQYeQv/PoyyA==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.2.0", - "tslib": "^2.8.1" + "@dual-bundle/import-meta-resolve": "^4.2.1", + "@pkgr/core": "^0.3.6" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tapable": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "dev": true, "license": "MIT", "engines": { "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/terser": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", - "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", + "version": "5.51.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.51.2.tgz", + "integrity": "sha512-bWnjSNscmuI+GJze6ZupnHP8G/cTcsJF+bXCeQknk2SHQsgbNJnLrqiH9jZ2W4STPVXH2mDKKRX3iwPhc9Cn/Q==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -13944,56 +10320,6 @@ "node": ">=10" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.14", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", - "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -14001,71 +10327,6 @@ "dev": true, "license": "MIT" }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -14114,52 +10375,33 @@ "license": "MIT", "peer": true }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/tldts": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", - "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.86" + "fdir": "^6.5.0", + "picomatch": "^4.0.4" }, - "bin": { - "tldts": "bin/cli.js" + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tldts-core": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", - "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", - "dev": true, - "license": "MIT" - }, "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", "dev": true, "license": "MIT", "engines": { "node": ">=14.14" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -14184,53 +10426,24 @@ } }, "node_modules/toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/tough-cookie": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", - "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tldts": "^6.1.32" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/tr46": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz", - "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/tr46/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" - } + "peer": true + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" }, "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { @@ -14240,35 +10453,50 @@ "typescript": ">=4.8.4" } }, + "node_modules/ts-dedent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.3.0.tgz", + "integrity": "sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.10" + } + }, "node_modules/ts-loader": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.2.tgz", - "integrity": "sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.6.2.tgz", + "integrity": "sha512-R4iuczmtgxvtuI556s+hTZ6/7Ee03VCAk/l/M8LY1OAsUgB7YydsCxkgq9D9pKRaD7GJqUi2u8fp9zZP/ufjKA==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4", + "picomatch": "^4.0.0", "source-map": "^0.7.4" }, "engines": { "node": ">=12.0.0" }, "peerDependencies": { + "loader-utils": "*", "typescript": "*", - "webpack": "^5.0.0" + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "loader-utils": { + "optional": true + } } }, "node_modules/ts-loader/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", "dev": true, "license": "BSD-3-Clause", "engines": { - "node": ">= 8" + "node": ">= 12" } }, "node_modules/ts-mocha": { @@ -14294,9 +10522,9 @@ } }, "node_modules/ts-mocha/node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.1.tgz", + "integrity": "sha512-Z3u54A8qGyqFOSr2pk0ijYs8mOE9Qz8kTvtKeBI+upoG9j04Sq+oI7W8zAJiQybDcESET8/uIdHzs0p3k4fZlw==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -14426,17 +10654,17 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "license": "0BSD" + "license": "0BSD", + "peer": true }, "node_modules/tsx": { - "version": "4.19.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", - "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", + "version": "4.23.15", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.15.tgz", + "integrity": "sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "~0.25.0", - "get-tsconfig": "^4.7.5" + "esbuild": "~0.28.0" }, "bin": { "tsx": "dist/cli.mjs" @@ -14472,9 +10700,9 @@ } }, "node_modules/type-fest": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.38.0.tgz", - "integrity": "sha512-2dBz5D5ycHIoliLYLi0Q2V7KRaDlH0uWIvmk7TYlAg5slqwiPv1ezJdZm1QEM0xgk29oYWMCbIG7E6gHpvChlg==", + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, "license": "(MIT OR CC0-1.0)", "peer": true, @@ -14500,9 +10728,9 @@ } }, "node_modules/typescript": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", - "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -14514,9 +10742,9 @@ } }, "node_modules/ua-parser-js": { - "version": "0.7.40", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.40.tgz", - "integrity": "sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ==", + "version": "0.7.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.41.tgz", + "integrity": "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==", "dev": true, "funding": [ { @@ -14541,74 +10769,40 @@ } }, "node_modules/underscore": { - "version": "1.13.7", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", - "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", "dev": true, "license": "MIT" }, "node_modules/undici": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.1.tgz", - "integrity": "sha512-RYONW2MeafgYlkVOKYKkA/Ag7BmXqgIWCa8t1m0JcxrQg9pI9lEqRhAOruOBCbAohOa/gkCF+iPi9hrgvTzu6Q==", + "version": "7.30.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.30.1.tgz", + "integrity": "sha512-03KrMbjIFDWQR5RNPrSw3bd1r12JpyFQl9/yxjUbJtqkjmllqC5lFjZh6ujeuJCKr8EOQvRW872Oy/az+nLYxg==", "license": "MIT", "engines": { "node": ">=20.18.1" } }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "node_modules/unicorn-magic": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.1.tgz", + "integrity": "sha512-lzlXPoVB0Uy/FvTaUgX39RbixYiSKoc3JSoSf01+0c2B6FR3qdYIPN7Qjo/AV7n6sqLCk0509cT3LRj1oSZ1+A==", "dev": true, "license": "MIT", "peer": true, "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "node": ">=20" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/universalify": { @@ -14632,9 +10826,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.4.tgz", + "integrity": "sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==", "dev": true, "funding": [ { @@ -14725,21 +10919,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "peer": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -14787,38 +10966,13 @@ "node": ">=0.10.0" } }, - "node_modules/w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "makeerror": "1.0.12" - } - }, "node_modules/watchpack": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", - "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.6.3.tgz", + "integrity": "sha512-s3NZy0QpTY9qGqzc0wtz4qI28z3+5qKbbAec4MV4G9N3CfgZ9wgvQRr0cl2jh/tqkWG1NWHkmVMHZpCamev5Wg==", "dev": true, "license": "MIT", "dependencies": { - "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" }, "engines": { @@ -14826,47 +10980,36 @@ } }, "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } + "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.100.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.100.0.tgz", - "integrity": "sha512-H8yBSBTk+BqxrINJnnRzaxU94SVP2bjd7WmA+PfCphoIdDpeQMJ77pq9/4I7xjLq38cB1bNKfzYPZu8pB3zKtg==", + "version": "5.112.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.112.0.tgz", + "integrity": "sha512-NIBpsRuCll036haDDt/CfcTDfsWNR9Z782nMRMI9D377BsGcYzZDTNU5TyzhCJzPIcihAxMBaMAhq2WSaDrH8Q==", "dev": true, "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.24.0", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.2", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", + "enhanced-resolve": "^5.26.0", + "es-module-lexer": "^2.1.0", "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.2", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.11", - "watchpack": "^2.4.1", - "webpack-sources": "^3.3.3" + "mime-db": "^1.54.0", + "minimizer-webpack-plugin": "^5.13.0", + "schema-utils": "^4.5.0", + "tapable": "^2.3.0", + "watchpack": "^2.6.1", + "webpack-sources": "^3.6.0" }, "bin": { "webpack": "bin/webpack.js" @@ -14895,63 +11038,23 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.6.0.tgz", + "integrity": "sha512-EIMmPVvNI0CYXyRPp34F2Qk7W37/BZVZIofS6LAUnrNjCVahS+hO4mxwFJDjQjODTGZDtVzLYoN2+1dYkhk9qA==", "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/webpack/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, "node_modules/whatwg-fetch": { @@ -14962,28 +11065,15 @@ "license": "MIT", "peer": true }, - "node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dev": true, "license": "MIT", "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, "node_modules/whatwg-url-without-unicode": { @@ -15063,14 +11153,14 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "version": "1.1.24", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.24.tgz", + "integrity": "sha512-wk4Mf4pR5mRP7eYuuTBCIQ9d0ud2Fv2jRLQpfgnRjbOxAFHmjKFValgTpitVKzJJS8ajnYQV2Du1SZ8j6b/EUQ==", "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", + "call-bind": "^1.0.9", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", @@ -15085,9 +11175,9 @@ } }, "node_modules/why-is-node-running": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-3.2.2.tgz", - "integrity": "sha512-NKUzAelcoCXhXL4dJzKIwXeR8iEVqsA0Lq6Vnd0UXvgaKbzVo4ZTHROF2Jidrv+SgxOQ03fMinnNhzZATxOD3A==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-3.2.3.tgz", + "integrity": "sha512-b+aWTM7Zz5Q82TurMbr034vAmyJo2pJFVXzUzuhJK8lP+XI6xUfvzXizZINaERhH3KwybDLt6iqh7pOXaVxjnQ==", "dev": true, "license": "MIT", "bin": { @@ -15115,32 +11205,11 @@ "license": "Apache-2.0" }, "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -15153,76 +11222,20 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "ansi-regex": "^6.0.1" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=12" + "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/wrappy": { @@ -15232,41 +11245,19 @@ "dev": true, "license": "ISC" }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC", - "peer": true - }, "node_modules/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "version": "7.5.13", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.13.tgz", + "integrity": "sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==", "dev": true, "license": "MIT", + "peer": true, "engines": { - "node": ">=10.0.0" + "node": ">=8.3.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "utf-8-validate": "^5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -15278,9 +11269,9 @@ } }, "node_modules/wtfnode": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/wtfnode/-/wtfnode-0.10.0.tgz", - "integrity": "sha512-/GxfQORu0SZZC8AQA4Eq1wH08Akz6W42OiqNGBzTHXCJWZFhKFBJNaUfEomWnLA2MXfpy6KbFerG8iNtFcPRdg==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/wtfnode/-/wtfnode-0.10.1.tgz", + "integrity": "sha512-4mcHdlvcdSytsbFueN6QYZxmh5K7REawBk//ZOrJrtVOe548Qsq4GNEm/OUfZATqDnsX4g8uBbzmN7NdEZx09Q==", "dev": true, "license": "ISC", "bin": { @@ -15290,16 +11281,6 @@ "node": ">=0.10.0" } }, - "node_modules/xml-name-validator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", - "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18" - } - }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", @@ -15311,13 +11292,6 @@ "node": ">=8.0" } }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true, - "license": "MIT" - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -15337,9 +11311,9 @@ "peer": true }, "node_modules/yaml": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", - "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", + "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", "dev": true, "license": "ISC", "peer": true, @@ -15347,13 +11321,16 @@ "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" } }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "16.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.2.tgz", + "integrity": "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==", "dev": true, "license": "MIT", "dependencies": { @@ -15395,19 +11372,6 @@ "node": ">=10" } }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -15432,9 +11396,9 @@ } }, "node_modules/yup": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/yup/-/yup-1.2.0.tgz", - "integrity": "sha512-PPqYKSAXjpRCgLgLKVGPA33v5c/WgEx3wi6NFjIiegz90zSwyMpvTFp/uGcVnnbx6to28pgnzp/q8ih3QRjLMQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.7.1.tgz", + "integrity": "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw==", "dev": true, "license": "MIT", "peer": true, diff --git a/package.json b/package.json index d5adecb1d..69de711b1 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "cbor-js": "^0.1.0", "cbor-sync": "^1.0.4", "fast-text-encoding": "^1.0.6", - "fflate": "^0.8.2", + "fflate": "^0.8.3", "lil-uuid": "^0.1.1", "undici": "^7.29.0" }, From 3cd620e43a5ae93b8c47120cdd4ba825945b0b48 Mon Sep 17 00:00:00 2001 From: "mohit.tejani" Date: Mon, 19 Oct 2026 11:40:47 +0530 Subject: [PATCH 4/9] restore package-lock version --- package-lock.json | 8986 ++++++++++++++++++++++++++++++++------------- 1 file changed, 6511 insertions(+), 2475 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0d1438f9d..586df7069 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "cbor-js": "^0.1.0", "cbor-sync": "^1.0.4", "fast-text-encoding": "^1.0.6", - "fflate": "^0.8.3", + "fflate": "^0.8.2", "lil-uuid": "^0.1.1", "undici": "^7.29.0" }, @@ -95,25 +95,54 @@ } } }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.1.tgz", + "integrity": "sha512-hpRD68SV2OMcZCsrbdkccTw5FXjNDLo5OuqSHyHZfwweGsDWZwDJ2+gONyNAbazZclobMirACLw0lk8WVxIqxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.2", + "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, "node_modules/@babel/code-frame": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", - "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.29.7", + "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", - "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", "dev": true, "license": "MIT", "peer": true, @@ -122,23 +151,23 @@ } }, "node_modules/@babel/core": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", - "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.7", - "@babel/helper-compilation-targets": "^7.29.7", - "@babel/helper-module-transforms": "^7.29.7", - "@babel/helpers": "^7.29.7", - "@babel/parser": "^7.29.7", - "@babel/template": "^7.29.7", - "@babel/traverse": "^7.29.7", - "@babel/types": "^7.29.7", - "@jridgewell/remapping": "^2.3.5", + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -165,33 +194,47 @@ } }, "node_modules/@babel/generator": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", - "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/parser": "^7.29.8", - "@babel/types": "^7.29.8", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", - "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", + "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/compat-data": "^7.29.7", - "@babel/helper-validator-option": "^7.29.7", + "@babel/compat-data": "^7.26.8", + "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -222,43 +265,51 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-globals": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", - "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz", + "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==", "dev": true, "license": "MIT", "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.27.0", + "semver": "^6.3.1" + }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", - "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT", + "license": "ISC", "peer": true, - "dependencies": { - "@babel/traverse": "^7.29.7", - "@babel/types": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", - "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz", + "integrity": "sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-module-imports": "^7.29.7", - "@babel/helper-validator-identifier": "^7.29.7", - "@babel/traverse": "^7.29.7" + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.2.0", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -267,74 +318,102 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", - "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz", + "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", "dev": true, "license": "MIT", "peer": true, - "engines": { - "node": ">=6.9.0" + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", - "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", - "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "license": "MIT", "peer": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helpers": { - "version": "7.29.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.10.tgz", - "integrity": "sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/template": "^7.29.7", - "@babel/types": "^7.29.8" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/parser": { - "version": "7.29.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz", - "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/types": "^7.29.8" - }, - "bin": { - "parser": "bin/babel-parser.js" + "@babel/types": "^7.25.9" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@babel/runtime": { - "version": "7.29.10", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.10.tgz", - "integrity": "sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "dev": true, "license": "MIT", "peer": true, @@ -342,360 +421,2288 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/template": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", - "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/parser": "^7.29.7", - "@babel/types": "^7.29.7" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/traverse": { - "version": "7.29.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.10.tgz", - "integrity": "sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==", + "node_modules/@babel/helper-replace-supers": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", + "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.8", - "@babel/helper-globals": "^7.29.7", - "@babel/parser": "^7.29.9", - "@babel/template": "^7.29.7", - "@babel/types": "^7.29.8", - "debug": "^4.3.1" + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/types": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", - "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-string-parser": "^7.29.7", - "@babel/helper-validator-identifier": "^7.29.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, "license": "MIT", + "peer": true, "engines": { - "node": ">=0.1.90" + "node": ">=6.9.0" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@cucumber/ci-environment": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@cucumber/ci-environment/-/ci-environment-13.0.0.tgz", - "integrity": "sha512-cs+3NzfNkGbcmHPddjEv4TKFiBpZRQ6WJEEufB9mw+ExS22V/4R/zpDSEG+fsJ/iSNCd6A2sATdY8PFOyY3YnA==", + "node_modules/@babel/helpers": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", "dev": true, "license": "MIT", - "peer": true + "peer": true, + "dependencies": { + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@cucumber/cucumber": { - "version": "12.9.0", - "resolved": "https://registry.npmjs.org/@cucumber/cucumber/-/cucumber-12.9.0.tgz", - "integrity": "sha512-QbgEo/DcKFMRGL+yULh8Kw6peEfdPJjhYjpKp0dYc+6Dv1Bmp6hvxIdTi2CIinYBCXhvCZzNO1Ct/n6Dk1yAtA==", + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@cucumber/ci-environment": "13.0.0", - "@cucumber/cucumber-expressions": "19.0.0", - "@cucumber/gherkin": "38.0.0", - "@cucumber/gherkin-streams": "6.0.0", - "@cucumber/gherkin-utils": "11.0.0", - "@cucumber/html-formatter": "23.1.0", - "@cucumber/junit-xml-formatter": "0.13.3", - "@cucumber/message-streams": "4.1.1", - "@cucumber/messages": "32.3.1", - "@cucumber/pretty-formatter": "1.0.1", - "@cucumber/tag-expressions": "9.1.0", - "assertion-error-formatter": "^3.0.0", - "capital-case": "^1.0.4", - "chalk": "^4.1.2", - "cli-table3": "0.6.5", - "commander": "^14.0.0", - "debug": "^4.3.4", - "error-stack-parser": "^2.1.4", - "figures": "^3.2.0", - "glob": "^13.0.0", - "has-ansi": "^4.0.1", - "indent-string": "^4.0.0", - "is-installed-globally": "^0.4.0", - "is-stream": "^2.0.0", - "knuth-shuffle-seeded": "^1.0.6", - "lodash.merge": "^4.6.2", - "lodash.mergewith": "^4.6.2", - "luxon": "3.7.2", - "mkdirp": "^3.0.0", - "mz": "^2.7.0", - "progress": "^2.0.3", - "read-package-up": "^12.0.0", - "semver": "7.7.4", - "string-argv": "0.3.1", - "supports-color": "^8.1.1", - "type-fest": "^4.41.0", - "util-arity": "^1.1.0", - "yaml": "^2.2.2", - "yup": "1.7.1" + "@babel/types": "^7.27.0" }, "bin": { - "cucumber-js": "bin/cucumber.js" + "parser": "bin/babel-parser.js" }, "engines": { - "node": "20 || 22 || >=24" - }, - "funding": { - "url": "https://opencollective.com/cucumber" + "node": ">=6.0.0" } }, - "node_modules/@cucumber/cucumber-expressions": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@cucumber/cucumber-expressions/-/cucumber-expressions-19.0.0.tgz", - "integrity": "sha512-4FKoOQh2Uf6F6/Ln+1OxuK8LkTg6PyAqekhf2Ix8zqV2M54sH+m7XNJNLhOFOAW/t9nxzRbw2CcvXbCLjcvHZg==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "regexp-match-indices": "1.0.2" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@cucumber/cucumber/node_modules/commander": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", - "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", "dev": true, "license": "MIT", "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, "engines": { - "node": ">=20" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@cucumber/gherkin": { - "version": "38.0.0", - "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-38.0.0.tgz", - "integrity": "sha512-duEXK+KDfQUzu3vsSzXjkxQ2tirF5PRsc1Xrts6THKHJO6mjw4RjM8RV+vliuDasmhhrmdLcOcM7d9nurNTJKw==", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@cucumber/messages": ">=31.0.0 <33" + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@cucumber/gherkin-streams": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@cucumber/gherkin-streams/-/gherkin-streams-6.0.0.tgz", - "integrity": "sha512-HLSHMmdDH0vCr7vsVEURcDA4WwnRLdjkhqr6a4HQ3i4RFK1wiDGPjBGVdGJLyuXuRdJpJbFc6QxHvT8pU4t6jw==", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "commander": "14.0.0", - "source-map-support": "0.5.21" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" }, - "bin": { - "gherkin-javascript": "bin/gherkin" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@cucumber/gherkin": ">=22.0.0", - "@cucumber/message-streams": ">=4.0.0", - "@cucumber/messages": ">=17.1.1" + "@babel/core": "^7.13.0" } }, - "node_modules/@cucumber/gherkin-streams/node_modules/commander": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", - "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", "dev": true, "license": "MIT", "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, "engines": { - "node": ">=20" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@cucumber/gherkin-utils": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@cucumber/gherkin-utils/-/gherkin-utils-11.0.0.tgz", - "integrity": "sha512-LJ+s4+TepHTgdKWDR4zbPyT7rQjmYIcukTwNbwNwgqr6i8Gjcmzf6NmtbYDA19m1ZFg6kWbFsmHnj37ZuX+kZA==", + "node_modules/@babel/plugin-proposal-export-default-from": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz", + "integrity": "sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@cucumber/gherkin": "^38.0.0", - "@cucumber/messages": "^32.0.0", - "@teppeis/multimaps": "3.0.0", - "commander": "14.0.2", - "source-map-support": "^0.5.21" + "@babel/helper-plugin-utils": "^7.25.9" }, - "bin": { - "gherkin-utils": "bin/gherkin-utils" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cucumber/gherkin-utils/node_modules/commander": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", - "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, "license": "MIT", "peer": true, "engines": { - "node": ">=20" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cucumber/html-formatter": { - "version": "23.1.0", - "resolved": "https://registry.npmjs.org/@cucumber/html-formatter/-/html-formatter-23.1.0.tgz", - "integrity": "sha512-DcCSFoGs6jbwzXPgX1CwgJKEE+ZMcIEzq/0Memg0o24maNn9NJizBFHmoFWG4iv/OxHza+mvc+56cTHetfHndw==", + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "license": "MIT", "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, "peerDependencies": { - "@cucumber/messages": ">=18" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cucumber/junit-xml-formatter": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/@cucumber/junit-xml-formatter/-/junit-xml-formatter-0.13.3.tgz", - "integrity": "sha512-w9ujOxiuKDtU6fLzJz+wp4Sgp5Xu6ba7ls00LHJccVmQU0Ba7zs+AHnv3iIgPjKZAQe1w8x93dr8Gaubh7Vqkg==", + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@cucumber/query": "^15.0.1", - "@teppeis/multimaps": "^3.0.0", - "luxon": "^3.5.0", - "xmlbuilder": "^15.1.1" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "@cucumber/messages": "*" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cucumber/message-streams": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@cucumber/message-streams/-/message-streams-4.1.1.tgz", - "integrity": "sha512-QCAntLajesWMyX+mZKrj63YghVAts7yKFlZe46XprLbdJZN0ddB+f/Mr9OnyWKC2DHhJ18jzCfKIFCaqpAmUxg==", + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "mime": "^3.0.0" + "@babel/helper-plugin-utils": "^7.12.13" }, "peerDependencies": { - "@cucumber/messages": ">=17.1.1" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cucumber/messages": { - "version": "32.3.1", - "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-32.3.1.tgz", - "integrity": "sha512-yNQq1KoXRYaEKrWMFmpUQX7TdeQuU9jeGgJAZ3dArTsC/T4NpJ6DnqaJIIgwPnz/wtQIQTNX7/h0rOuF5xY4qQ==", + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "class-transformer": "0.5.1", - "reflect-metadata": "0.2.2" + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cucumber/pretty-formatter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@cucumber/pretty-formatter/-/pretty-formatter-1.0.1.tgz", - "integrity": "sha512-A1lU4VVP0aUWdOTmpdzvXOyEYuPtBDI0xYwYJnmoMDplzxMdhcHk86lyyvYDoMoPzzq6OkOE3isuosvUU4X7IQ==", + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "ansi-styles": "^5.0.0", - "cli-table3": "^0.6.0", - "figures": "^3.2.0", - "ts-dedent": "^2.0.0" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "@cucumber/cucumber": ">=7.0.0", - "@cucumber/messages": "*" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cucumber/query": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@cucumber/query/-/query-15.0.1.tgz", - "integrity": "sha512-FMfT3orJblRsOxvU2doECBvQmauizYlj+5JsM8atAKKPbnQTj7v2/OrnuykvQpfZNBf19DYbRq1e832vllRP/g==", + "node_modules/@babel/plugin-syntax-export-default-from": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz", + "integrity": "sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@teppeis/multimaps": "3.0.0", - "lodash.sortby": "^4.7.0" + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@cucumber/messages": "*" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cucumber/tag-expressions": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/@cucumber/tag-expressions/-/tag-expressions-9.1.0.tgz", - "integrity": "sha512-bvHjcRFZ+J1TqIa9eFNO1wGHqwx4V9ZKV3hYgkuK/VahHx73uiP4rKV3JVrvWSMrwrFvJG6C8aEwnCWSvbyFdQ==", + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", + "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", "dev": true, "license": "MIT", - "peer": true + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@dual-bundle/import-meta-resolve": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.2.1.tgz", - "integrity": "sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==", + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/JounQin" - } + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", + "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.26.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz", + "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz", + "integrity": "sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", + "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz", + "integrity": "sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/plugin-syntax-flow": "^7.26.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz", + "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.26.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz", + "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz", + "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", + "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", + "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", + "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.0.tgz", + "integrity": "sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.10.tgz", + "integrity": "sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.11.0", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz", + "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.0.tgz", + "integrity": "sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.0.tgz", + "integrity": "sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.27.0", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz", + "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.26.8", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.26.8", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.26.5", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.26.3", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.26.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.26.8", + "@babel/plugin-transform-typeof-symbol": "^7.26.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.11.0", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.40.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-flow": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.25.9.tgz", + "integrity": "sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-transform-flow-strip-types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.0.tgz", + "integrity": "sha512-vxaPFfJtHhgeOVXRKuHpHPAOgymmy8V8I65T1q53R7GCZlefKeCaTyDs3zOPHTTbmquvNlQYC5klEvWsBAtrBQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-typescript": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.25.9.tgz", + "integrity": "sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@babel/template": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse--for-generate-function-map": { + "name": "@babel/traverse", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse--for-generate-function-map/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", + "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.2.tgz", + "integrity": "sha512-TklMyb3uBB28b5uQdxjReG4L80NxAqgrECqLZFQbyLekwwlcDDS8r3f07DKqeo8C4926Br0gf/ZDe17Zv4wIuw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.8.tgz", + "integrity": "sha512-pdwotQjCCnRPuNi06jFuP68cykU1f3ZWExLe/8MQ1LOs8Xq+fTkYgd+2V8mWUWMrOn9iS2HftPVaMZDaXzGbhQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", + "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", + "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cucumber/ci-environment": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cucumber/ci-environment/-/ci-environment-10.0.1.tgz", + "integrity": "sha512-/+ooDMPtKSmvcPMDYnMZt4LuoipfFfHaYspStI4shqw8FyKcfQAmekz6G+QKWjQQrvM+7Hkljwx58MEwPCwwzg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@cucumber/cucumber": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@cucumber/cucumber/-/cucumber-10.9.0.tgz", + "integrity": "sha512-7XHJ6nmr9IkIag0nv6or82HfelbSInrEe3H4aT6dMHyTehwFLUifG6eQQ+uE4LZIOXAnzLPH37YmqygEO67vCA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@cucumber/ci-environment": "10.0.1", + "@cucumber/cucumber-expressions": "17.1.0", + "@cucumber/gherkin": "28.0.0", + "@cucumber/gherkin-streams": "5.0.1", + "@cucumber/gherkin-utils": "9.0.0", + "@cucumber/html-formatter": "21.6.0", + "@cucumber/message-streams": "4.0.1", + "@cucumber/messages": "24.1.0", + "@cucumber/tag-expressions": "6.1.0", + "assertion-error-formatter": "^3.0.0", + "capital-case": "^1.0.4", + "chalk": "^4.1.2", + "cli-table3": "0.6.3", + "commander": "^10.0.0", + "debug": "^4.3.4", + "error-stack-parser": "^2.1.4", + "figures": "^3.2.0", + "glob": "^10.3.10", + "has-ansi": "^4.0.1", + "indent-string": "^4.0.0", + "is-installed-globally": "^0.4.0", + "is-stream": "^2.0.0", + "knuth-shuffle-seeded": "^1.0.6", + "lodash.merge": "^4.6.2", + "lodash.mergewith": "^4.6.2", + "luxon": "3.2.1", + "mime": "^3.0.0", + "mkdirp": "^2.1.5", + "mz": "^2.7.0", + "progress": "^2.0.3", + "read-pkg-up": "^7.0.1", + "resolve-pkg": "^2.0.0", + "semver": "7.5.3", + "string-argv": "0.3.1", + "strip-ansi": "6.0.1", + "supports-color": "^8.1.1", + "tmp": "0.2.3", + "type-fest": "^4.8.3", + "util-arity": "^1.1.0", + "xmlbuilder": "^15.1.1", + "yaml": "^2.2.2", + "yup": "1.2.0" + }, + "bin": { + "cucumber-js": "bin/cucumber.js" + }, + "engines": { + "node": "18 || >=20" + }, + "funding": { + "url": "https://opencollective.com/cucumber" + } + }, + "node_modules/@cucumber/cucumber-expressions": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@cucumber/cucumber-expressions/-/cucumber-expressions-17.1.0.tgz", + "integrity": "sha512-PCv/ppsPynniKPWJr5v566daCVe+pbxQpHGrIu/Ev57cCH9Rv+X0F6lio4Id3Z64TaG7btCRLUGewIgLwmrwOA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "regexp-match-indices": "1.0.2" + } + }, + "node_modules/@cucumber/cucumber/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@cucumber/gherkin": { + "version": "28.0.0", + "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-28.0.0.tgz", + "integrity": "sha512-Ee6zJQq0OmIUPdW0mSnsCsrWA2PZAELNDPICD2pLfs0Oz7RAPgj80UsD2UCtqyAhw2qAR62aqlktKUlai5zl/A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@cucumber/messages": ">=19.1.4 <=24" + } + }, + "node_modules/@cucumber/gherkin-streams": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@cucumber/gherkin-streams/-/gherkin-streams-5.0.1.tgz", + "integrity": "sha512-/7VkIE/ASxIP/jd4Crlp4JHXqdNFxPGQokqWqsaCCiqBiu5qHoKMxcWNlp9njVL/n9yN4S08OmY3ZR8uC5x74Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "commander": "9.1.0", + "source-map-support": "0.5.21" + }, + "bin": { + "gherkin-javascript": "bin/gherkin" + }, + "peerDependencies": { + "@cucumber/gherkin": ">=22.0.0", + "@cucumber/message-streams": ">=4.0.0", + "@cucumber/messages": ">=17.1.1" + } + }, + "node_modules/@cucumber/gherkin-streams/node_modules/commander": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.1.0.tgz", + "integrity": "sha512-i0/MaqBtdbnJ4XQs4Pmyb+oFQl+q0lsAmokVUH92SlSw4fkeAcG3bVon+Qt7hmtF+u3Het6o4VgrcY3qAoEB6w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/@cucumber/gherkin-utils": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@cucumber/gherkin-utils/-/gherkin-utils-9.0.0.tgz", + "integrity": "sha512-clk4q39uj7pztZuZtyI54V8lRsCUz0Y/p8XRjIeHh7ExeEztpWkp4ca9q1FjUOPfQQ8E7OgqFbqoQQXZ1Bx7fw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@cucumber/gherkin": "^28.0.0", + "@cucumber/messages": "^24.0.0", + "@teppeis/multimaps": "3.0.0", + "commander": "12.0.0", + "source-map-support": "^0.5.21" + }, + "bin": { + "gherkin-utils": "bin/gherkin-utils" + } + }, + "node_modules/@cucumber/gherkin-utils/node_modules/commander": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz", + "integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@cucumber/html-formatter": { + "version": "21.6.0", + "resolved": "https://registry.npmjs.org/@cucumber/html-formatter/-/html-formatter-21.6.0.tgz", + "integrity": "sha512-Qw1tdObBJrgXgXwVjKVjB3hFhFPI8WhIFb+ULy8g5lDl5AdnKDiyDXAMvAWRX+pphnRMMNdkPCt6ZXEfWvUuAA==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "@cucumber/messages": ">=18" + } + }, + "node_modules/@cucumber/message-streams": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cucumber/message-streams/-/message-streams-4.0.1.tgz", + "integrity": "sha512-Kxap9uP5jD8tHUZVjTWgzxemi/0uOsbGjd4LBOSxcJoOCRbESFwemUzilJuzNTB8pcTQUh8D5oudUyxfkJOKmA==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "@cucumber/messages": ">=17.1.1" + } + }, + "node_modules/@cucumber/messages": { + "version": "24.1.0", + "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-24.1.0.tgz", + "integrity": "sha512-hxVHiBurORcobhVk80I9+JkaKaNXkW6YwGOEFIh/2aO+apAN+5XJgUUWjng9NwqaQrW1sCFuawLB1AuzmBaNdQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/uuid": "9.0.8", + "class-transformer": "0.5.1", + "reflect-metadata": "0.2.1", + "uuid": "9.0.1" + } + }, + "node_modules/@cucumber/tag-expressions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@cucumber/tag-expressions/-/tag-expressions-6.1.0.tgz", + "integrity": "sha512-+3DwRumrCJG27AtzCIL37A/X+A/gSfxOPLg8pZaruh5SLumsTmpvilwroVWBT2fPzmno/tGXypeK5a7NHU4RzA==", + "dev": true, + "license": "MIT", + "peer": true }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", - "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", + "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", "cpu": [ "ppc64" ], @@ -710,9 +2717,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", - "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", + "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", "cpu": [ "arm" ], @@ -727,9 +2734,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", - "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", + "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", "cpu": [ "arm64" ], @@ -744,9 +2751,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", - "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", + "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", "cpu": [ "x64" ], @@ -761,9 +2768,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", - "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", + "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", "cpu": [ "arm64" ], @@ -778,9 +2785,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", - "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", + "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", "cpu": [ "x64" ], @@ -795,9 +2802,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", - "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", + "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", "cpu": [ "arm64" ], @@ -812,9 +2819,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", - "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", + "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", "cpu": [ "x64" ], @@ -829,9 +2836,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", - "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", + "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", "cpu": [ "arm" ], @@ -846,9 +2853,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", - "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", + "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", "cpu": [ "arm64" ], @@ -863,9 +2870,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", - "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", + "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", "cpu": [ "ia32" ], @@ -880,9 +2887,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", - "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", + "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", "cpu": [ "loong64" ], @@ -897,9 +2904,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", - "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", + "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", "cpu": [ "mips64el" ], @@ -914,9 +2921,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", - "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", + "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", "cpu": [ "ppc64" ], @@ -931,9 +2938,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", - "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", + "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", "cpu": [ "riscv64" ], @@ -948,9 +2955,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", - "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", + "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", "cpu": [ "s390x" ], @@ -965,9 +2972,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", - "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", + "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", "cpu": [ "x64" ], @@ -982,9 +2989,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", - "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", + "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", "cpu": [ "arm64" ], @@ -999,9 +3006,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", - "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", + "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", "cpu": [ "x64" ], @@ -1016,9 +3023,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", - "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", + "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", "cpu": [ "arm64" ], @@ -1033,9 +3040,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", - "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", + "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", "cpu": [ "x64" ], @@ -1049,27 +3056,10 @@ "node": ">=18" } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", - "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/sunos-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", - "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", + "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", "cpu": [ "x64" ], @@ -1084,9 +3074,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", - "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", + "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", "cpu": [ "arm64" ], @@ -1101,9 +3091,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", - "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", + "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", "cpu": [ "ia32" ], @@ -1118,9 +3108,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", - "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", + "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", "cpu": [ "x64" ], @@ -1135,9 +3125,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", - "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", + "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==", "dev": true, "license": "MIT", "dependencies": { @@ -1154,9 +3144,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "license": "MIT", "engines": { @@ -1194,17 +3184,10 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/@eslint/eslintrc/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { @@ -1212,31 +3195,11 @@ "concat-map": "0.0.1" } }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", - "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -1246,224 +3209,413 @@ } }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { - "node": "*" + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "peer": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "p-locate": "^4.1.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=8" } }, - "node_modules/@humanwhocodes/config-array/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "license": "ISC", + "license": "MIT", + "peer": true, "dependencies": { - "brace-expansion": "^1.1.7" + "p-limit": "^2.2.0" }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "peer": true, "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=8" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@isaacs/ttlcache": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", - "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "license": "ISC", + "license": "MIT", "peer": true, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@jest/diff-sequences": { - "version": "30.5.0", - "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.5.0.tgz", - "integrity": "sha512-OsqBjHXCn8cadasoAZBP6nWYvMsRhpMzGXTpxJ5aO04NlbdhIz+FVe3q49l0AwVhsz/cEmIpBes6gAFl1/dWQg==", + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3" + }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/expect-utils": { - "version": "30.5.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.5.2.tgz", - "integrity": "sha512-d/HOLSrJUlBIl6n3LzOa7cjW3xdePm5H5gQw2lixZ/0h157l9sw3mLblzFqnPcTbhDzhRQdBOX3A3KcG73nm5Q==", + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@jest/get-type": "30.5.0" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/get-type": { - "version": "30.5.0", - "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.5.0.tgz", - "integrity": "sha512-9/2VUPitAjmBzbvDvqrxmvB7BzWsBW0WmkkojX1ODuxX1NLGxx9gfaZpHB0z8DtJ9uhGNmZG/VXBhf8uO0OV8Q==", + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/pattern": { - "version": "30.5.0", - "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.5.0.tgz", - "integrity": "sha512-HdNQYSdRTEBNrginaqzQtTjG0HRMfrra/z6Ok7uL3S87vSlarIVohEsJsSj5edu3MiHoHjAkvPROz5ZjoKai+w==", + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-regex-util": "30.5.0" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/react-is-18": { - "name": "react-is", - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jest/react-is-19": { - "name": "react-is", - "version": "19.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.3.1.tgz", - "integrity": "sha512-RRieF6IyxQBkcK6pP8xOHprLTPW6QjRkbGdImtqNme+/hYVwCZkLQLdlZGOhUqXwkS9IEynaGvPJtv6XB/cz0Q==", - "dev": true, - "license": "MIT" - }, "node_modules/@jest/schemas": { - "version": "30.5.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.5.0.tgz", - "integrity": "sha512-/hunigyNpc4RCjC0VaW3f5RCUZVM2+WQ65qP7z083Gmvac7or2LI50XVNOtE4YPgBpV0yxYiAgorAPGniCoJmg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.34.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/types": { - "version": "30.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.5.1.tgz", - "integrity": "sha512-LvVYn83nnXPl+Rg98nvcFgjx6nRMTArhSn6RAX/w3ELn54S8A42TYZvsCMdGUqTM8S0wyXbtlQdU6Hi6dykj9g==", + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@jest/pattern": "30.5.0", - "@jest/schemas": "30.5.0", - "@types/istanbul-lib-coverage": "^2.0.6", - "@types/istanbul-reports": "^3.0.4", - "@types/node": "*", - "@types/yargs": "^17.0.33", - "chalk": "^4.1.2" + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -1476,10 +3628,20 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1488,16 +3650,16 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", - "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1506,9 +3668,9 @@ } }, "node_modules/@mswjs/interceptors": { - "version": "0.41.9", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.41.9.tgz", - "integrity": "sha512-VVPPgHyQ6ShqnrmDWuxjmUIsO9gWyOZFmuOfLd9LfBGQJwZfy0gvv9pbHSJuoFNIYC7ZDX9aoFwowjcdSC4E8w==", + "version": "0.38.3", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.38.3.tgz", + "integrity": "sha512-3AMc2fTnX4q3qyO6K/LKwWXjUAFc3COC3bo5YCROIyQYJ8g/++5Col5fSIglIyUdBN787CTbL+c04KRwaaZ/UA==", "dev": true, "license": "MIT", "dependencies": { @@ -1516,6 +3678,7 @@ "@open-draft/logger": "^0.3.0", "@open-draft/until": "^2.0.0", "is-node-process": "^1.2.0", + "jsdom": "^26.0.0", "outvariant": "^1.4.3", "strict-event-emitter": "^0.5.1" }, @@ -1586,51 +3749,151 @@ "dev": true, "license": "MIT" }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@pkgr/core": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", - "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.0.tgz", + "integrity": "sha512-vsJDAkYR6qCPu+ioGScGiMYR7LvZYIXh/dlQeviqoTWNCVfKTLYD/LkNWH4Mxsv2a5vpIRc77FN5DnmK1eBggQ==", "dev": true, "license": "MIT", "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/pkgr" + "url": "https://opencollective.com/unts" } }, - "node_modules/@react-native/asset-utils": { - "version": "0.88.0", - "resolved": "https://registry.npmjs.org/@react-native/asset-utils/-/asset-utils-0.88.0.tgz", - "integrity": "sha512-Bj1DxQt5f4OrjdlgSVkZT37Z3hx5hUIN5AUDSqL/e99vgtTcqj5vnm067epZL1EF/QiqsniZO8Q1GSkItOakDg==", + "node_modules/@react-native/assets-registry": { + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.78.1.tgz", + "integrity": "sha512-SegfYQFuut05EQIQIVB/6QMGaxJ29jEtPmzFWJdIp/yc2mmhIq7MfWRjwOe6qbONzIdp6Ca8p835hiGiAGyeKQ==", "dev": true, "license": "MIT", "peer": true, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18" } }, - "node_modules/@react-native/codegen": { - "version": "0.88.0", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.88.0.tgz", - "integrity": "sha512-SAGg+XfzsrPiYTscbKa9bo2/H2ei2TjyxW8RTMq2Ps661kRK3AnmpMGVfrEFshEMr3FGEbuQIvj86X98kaXlRA==", + "node_modules/@react-native/babel-plugin-codegen": { + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.78.1.tgz", + "integrity": "sha512-rD0tnct/yPEtoOc8eeFHIf8ZJJJEzLkmqLs8HZWSkt3w9VYWngqLXZxiDGqv0ngXjunAlC/Hpq+ULMVOvOnByw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/traverse": "^7.25.3", + "@react-native/codegen": "0.78.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-preset": { + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.78.1.tgz", + "integrity": "sha512-yTVcHmEdNQH4Ju7lhvbiQaGxBpMcalgkBy/IvHowXKk/ex3nY1PolF16/mBG1BrefcUA/rtJpqTtk2Ii+7T/Lw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", - "@babel/parser": "^7.29.0", - "flow-parser": "0.327.0", + "@babel/plugin-proposal-export-default-from": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-default-from": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-flow-strip-types": "^7.25.2", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.25.2", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/template": "^7.25.0", + "@react-native/babel-plugin-codegen": "0.78.1", + "babel-plugin-syntax-hermes-parser": "0.25.1", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/codegen": { + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.78.1.tgz", + "integrity": "sha512-kGG5qAM9JdFtxzUwe7c6CyJbsU2PnaTrtCHA2dF8VEiNX1K3yd9yKPzfkxA7HPvmHoAn3ga1941O79BStWcM3A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.25.3", + "glob": "^7.1.1", + "hermes-parser": "0.25.1", "invariant": "^2.2.4", + "jscodeshift": "^17.0.0", "nullthrows": "^1.1.1", - "tinyglobby": "^0.2.15", "yargs": "^17.6.2" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18" }, "peerDependencies": { - "@babel/core": "*" + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/@react-native/codegen/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/@react-native/codegen/node_modules/cliui": { @@ -1649,10 +3912,66 @@ "node": ">=12" } }, + "node_modules/@react-native/codegen/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@react-native/codegen/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@react-native/codegen/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@react-native/codegen/node_modules/yargs": { - "version": "17.7.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", - "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "license": "MIT", "peer": true, @@ -1681,110 +4000,175 @@ } }, "node_modules/@react-native/community-cli-plugin": { - "version": "0.88.0", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.88.0.tgz", - "integrity": "sha512-WrQdXbjVt1gwAay8ZzYtpOi9ly99ksJ0VMYFdVcMe6nq3vtiRgqKRpHgCdN6ySIbtr5o+aJ+Vr7OTDY98ec/Ow==", + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.78.1.tgz", + "integrity": "sha512-S6vF4oWpFqThpt/dBLrqLQw5ED2M1kg5mVtiL6ZqpoYIg+/e0vg7LZ8EXNbcdMDH4obRnm2xbOd+qlC7mOzNBg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@react-native/asset-utils": "0.88.0", - "@react-native/dev-middleware": "0.88.0", - "commander": "^12.0.0", - "debug": "^4.4.0", + "@react-native/dev-middleware": "0.78.1", + "@react-native/metro-babel-transformer": "0.78.1", + "chalk": "^4.0.0", + "debug": "^2.2.0", "invariant": "^2.2.4", - "metro": "^0.87.1", + "metro": "^0.81.0", + "metro-config": "^0.81.0", + "metro-core": "^0.81.0", + "readline": "^1.3.0", "semver": "^7.1.3" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18" }, "peerDependencies": { - "@react-native-community/cli": "*", - "@react-native/metro-config": "0.88.0" + "@react-native-community/cli": "*" }, "peerDependenciesMeta": { "@react-native-community/cli": { "optional": true - }, - "@react-native/metro-config": { - "optional": true } } }, - "node_modules/@react-native/debugger-frontend": { - "version": "0.88.0", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.88.0.tgz", - "integrity": "sha512-v5cnBaaWhDRPcQv8EC20zj53jOAKH7u2wnzzXS4JTNu+diPC+cA2+kC7rq3eKI5vGhlAcG2kDPoViRuC0AY0oA==", + "node_modules/@react-native/community-cli-plugin/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "peer": true, - "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/@react-native/debugger-shell": { - "version": "0.88.0", - "resolved": "https://registry.npmjs.org/@react-native/debugger-shell/-/debugger-shell-0.88.0.tgz", - "integrity": "sha512-p82zT8ZKNx7nIm/8zf8pi55sxm5KQBm8td47kzoJysTdqHLyPsRMUvDXtvCJIWadHSv7RJ6t/yiCc+IoImLBtw==", + "node_modules/@react-native/community-cli-plugin/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT", + "peer": true + }, + "node_modules/@react-native/debugger-frontend": { + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.78.1.tgz", + "integrity": "sha512-xev/B++QLxSDpEBWsc74GyCuq9XOHYTBwcGSpsuhOJDUha6WZIbEEvZe3LpVW+OiFso4oGIdnVSQntwippZdWw==", + "dev": true, + "license": "BSD-3-Clause", "peer": true, - "dependencies": { - "cross-spawn": "^7.0.6", - "debug": "^4.4.0", - "fb-dotslash": "0.5.8" - }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18" } }, "node_modules/@react-native/dev-middleware": { - "version": "0.88.0", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.88.0.tgz", - "integrity": "sha512-sHLxVHOwfkF672ZzMepNh4d3IKbrZy3qXDKWSwN5LC5VJkzzZ5FdmSPP4N/CCn2pcKJ4oSqvojXwN4De3Xk92A==", + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.78.1.tgz", + "integrity": "sha512-l8p7/dXa1vWPOdj0iuACkex8lgbLpYyPZ3QXGkocMcpl0bQ24K7hf3Bj02tfptP5PAm16b2RuEi04sjIGHUzzg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.88.0", - "@react-native/debugger-shell": "0.88.0", + "@react-native/debugger-frontend": "0.78.1", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", - "debug": "^4.4.0", + "debug": "^2.2.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", - "open": "^8.4.2", + "open": "^7.0.3", + "selfsigned": "^2.4.1", "serve-static": "^1.16.2", - "ws": "^7.5.10" + "ws": "^6.2.3" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/dev-middleware/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "async-limiter": "~1.0.0" } }, "node_modules/@react-native/gradle-plugin": { - "version": "0.88.0", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.88.0.tgz", - "integrity": "sha512-4jPSKslOfJj8NKY/jv9qmWkxZYmqPyamoS3Vs0JOFxw9t4PM6L/ea0fUsjNV0LxC9zJlvWilPJOCTOf7h8wlyw==", + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.78.1.tgz", + "integrity": "sha512-v8GJU+8DzQDWO3iuTFI1nbuQ/kzuqbXv07VVtSIMLbdofHzuuQT14DGBacBkrIDKBDTVaBGAc/baDNsyxCghng==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/js-polyfills": { + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.78.1.tgz", + "integrity": "sha512-Ogcv4QOA1o3IyErrf/i4cDnP+nfNcIfGTgw6iNQyAPry1xjPOz4ziajskLpWG/3ADeneIZuyZppKB4A28rZSvg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/metro-babel-transformer": { + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.78.1.tgz", + "integrity": "sha512-jQWf69D+QTMvSZSWLR+cr3VUF16rGB6sbD+bItD8Czdfn3hajzfMoHJTkVFP7991cjK5sIVekNiQIObou8JSQw==", "dev": true, "license": "MIT", "peer": true, + "dependencies": { + "@babel/core": "^7.25.2", + "@react-native/babel-preset": "0.78.1", + "hermes-parser": "0.25.1", + "nullthrows": "^1.1.1" + }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" } }, "node_modules/@react-native/normalize-colors": { - "version": "0.88.0", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.88.0.tgz", - "integrity": "sha512-eZCu3tGAQCfvMCPQJVY4dmoMX8ZZYBvqIGHX7lwOYyzNK+Dl8e5ky7ZoXub1Rq75oSrQXNNmSP2CDjNNXXZpFQ==", + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.78.1.tgz", + "integrity": "sha512-h4wARnY4iBFgigN1NjnaKFtcegWwQyE9+CEBVG4nHmwMtr8lZBmc7ZKIM6hUc6lxqY/ugHg48aSQSynss7mJUg==", "dev": true, "license": "MIT", "peer": true }, "node_modules/@react-native/virtualized-lists": { - "version": "0.88.0", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.88.0.tgz", - "integrity": "sha512-zpZIOAbobdS93edwHkNUdGDzvElNeQJqukRERRPns3/ucPvuMd2G4fYpmVJSVjhxtGCcLLB1PFndLYYfwaYoBQ==", + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.78.1.tgz", + "integrity": "sha512-v0jqDNMFXpnRnSlkDVvwNxXgPhifzzTFlxTSnHj9erKJsKpE26gSU5qB4hmJkEsscLG/ygdJ1c88aqinSh/wRA==", "dev": true, "license": "MIT", "peer": true, @@ -1793,12 +4177,12 @@ "nullthrows": "^1.1.1" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18" }, "peerDependencies": { - "@types/react": "^19.2.0", + "@types/react": "^19.0.0", "react": "*", - "react-native": "0.88.0" + "react-native": "*" }, "peerDependenciesMeta": { "@types/react": { @@ -1832,28 +4216,11 @@ } } }, - "node_modules/@rollup/plugin-commonjs/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/plugin-commonjs/node_modules/brace-expansion": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", - "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/@rollup/plugin-commonjs/node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -1871,9 +4238,9 @@ } }, "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "license": "ISC", "dependencies": { @@ -2002,9 +4369,9 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", - "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", + "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2088,9 +4455,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2105,9 +4469,6 @@ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2122,9 +4483,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2139,9 +4497,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2156,9 +4511,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2173,9 +4525,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2190,9 +4539,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2207,9 +4553,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2224,9 +4567,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2276,18 +4616,19 @@ ] }, "node_modules/@sinclair/typebox": { - "version": "0.34.52", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.52.tgz", - "integrity": "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==", + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true, "license": "MIT" }, "node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "dependencies": { "type-detect": "4.0.8" } @@ -2298,10 +4639,22 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=4" } }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, "node_modules/@sinonjs/formatio": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", @@ -2313,6 +4666,26 @@ "@sinonjs/samsam": "^3.1.0" } }, + "node_modules/@sinonjs/formatio/node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/formatio/node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@sinonjs/samsam": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", @@ -2325,11 +4698,30 @@ "lodash": "^4.17.15" } }, + "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/samsam/node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@sinonjs/text-encoding": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", - "deprecated": "Deprecated: no longer maintained and no longer used by Sinon packages. See\n https://github.com/sinonjs/nise/issues/243 for replacement details.", "dev": true, "license": "(Unlicense OR Apache-2.0)" }, @@ -2352,9 +4744,9 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.13.tgz", - "integrity": "sha512-gcLdvR9HO1ZJBypsOGqaP6TFEzb6vIta0KSTLt9NAQ6pXQO3cRgSVyCN6pzYqI9DlJgY71XKO0dpDhCf08b3pg==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true, "license": "MIT" }, @@ -2379,6 +4771,55 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, "node_modules/@types/cbor-js": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@types/cbor-js/-/cbor-js-0.1.1.tgz", @@ -2404,19 +4845,41 @@ } }, "node_modules/@types/cors": { - "version": "2.8.19", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", - "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" } }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, "node_modules/@types/estree": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", - "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, @@ -2438,6 +4901,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -2505,24 +4979,35 @@ } }, "node_modules/@types/node": { - "version": "22.20.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.5.tgz", - "integrity": "sha512-U2+DNr+wSjpsTS/wZGYHq7GcwfuSmKiKvoPvK22zwTlRhU91yOniN4qRR5KhIjvif7ysw/dz/hKmfDH0Ris4aA==", + "version": "22.13.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", + "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~6.20.0" } }, "node_modules/@types/node-fetch": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", - "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", - "form-data": "^4.0.4" + "form-data": "^4.0.0" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" } }, "node_modules/@types/normalize-package-data": { @@ -2551,9 +5036,9 @@ } }, "node_modules/@types/sinonjs__fake-timers": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-15.0.1.tgz", - "integrity": "sha512-Ko2tjWJq8oozHzHV+reuvS5KYIRAokHnGbDwGh/J64LntgpbuylF74ipEL24HCyRjf9FOlBiBHWBR1RlVKsI1w==", + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", "dev": true, "license": "MIT" }, @@ -2578,15 +5063,13 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/ws": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.2.tgz", - "integrity": "sha512-67MQl+fpWKVTT1NYdnmo3U4sc/xPo/zQBncVnI74qmQa0z/b+1g6iYqNmGCPbxO+zz2aklb08a0oHfegiVd0/w==", + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*" - } + "peer": true }, "node_modules/@types/wtfnode": { "version": "0.7.3", @@ -2596,9 +5079,9 @@ "license": "MIT" }, "node_modules/@types/yargs": { - "version": "17.0.35", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", - "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "dev": true, "license": "MIT", "dependencies": { @@ -2613,20 +5096,21 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.2.tgz", - "integrity": "sha512-K72/pvT7qpm8q3k8G5u93NCSN1RcLxX5h7Gw0bQpbMXviBHeY6Nx1WEwmk9wP+eKTSQ8ecxvcgt/ZX/rB938xQ==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.28.0.tgz", + "integrity": "sha512-lvFK3TCGAHsItNdWZ/1FkvpzCxTHUVuFrdnOGLMa0GGCFIbCgQWVk3CzCGdA7kM3qGVc+dfW9tr0Z/sHnGDFyg==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/type-utils": "8.71.2", - "@typescript-eslint/utils": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", - "ignore": "^7.0.5", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.28.0", + "@typescript-eslint/type-utils": "8.28.0", + "@typescript-eslint/utils": "8.28.0", + "@typescript-eslint/visitor-keys": "8.28.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.5.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2636,46 +5120,23 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.71.2", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.2.tgz", - "integrity": "sha512-aTtmZjp/x3gsGHkDs04/1I8kNogBJkpQaeGaN0PfiG43NzDEmW2n+OP5im9wfsvyX0yP1UZWBrAGtDBfH9jEVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.2.tgz", - "integrity": "sha512-Pd68GsLVh5ZXlcEccFPdhSOvtHZ/2WU0XsA8zmXOS3F158lVlcTLhfQ6qvtL1RzbMie0Kp8xtbVwAg4nejKPHw==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.28.0.tgz", + "integrity": "sha512-LPcw1yHD3ToaDEoljFEfQ9j2xShY367h7FZ1sq5NJT9I3yj4LHer1Xd1yRSOdYy9BpsrxU7R+eoDokChYM53lQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.71.2", - "@typescript-eslint/types": "^8.71.2", - "debug": "^4.4.3" + "@typescript-eslint/scope-manager": "8.28.0", + "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/typescript-estree": "8.28.0", + "@typescript-eslint/visitor-keys": "8.28.0", + "debug": "^4.3.4" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2685,18 +5146,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.2.tgz", - "integrity": "sha512-YF4wgg5iUX5Obywoac27B56FhozMNFhdJSbh11H5GBAwmBtfyRhmgTQqW9tRNNmHDvsZ2CX6UGzoz+YfYn2Leg==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.28.0.tgz", + "integrity": "sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2" + "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/visitor-keys": "8.28.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2706,35 +5168,17 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.2.tgz", - "integrity": "sha512-jz49TAWokm/7yWD9/o837nYax9DyALxIPOImdImvVzo6canBCZYzin8zJyqNR5k1j9K1DE0bVvr0XYB+99uAdg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.2.tgz", - "integrity": "sha512-cC8UaalCViJkb3rH/xLIvidEwoFRtMZMUqDjjJMGEKaTFwYRHYBcoczlEGHuvkHEO8svRDrgZ0yQgOArFmwang==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.28.0.tgz", + "integrity": "sha512-oRoXu2v0Rsy/VoOGhtWrOKDiIehvI+YNrDk5Oqj40Mwm0Yt01FC/Q7nFqg088d3yAsR1ZcZFVfPCTTFCe/KPwg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/utils": "8.71.2", - "debug": "^4.4.3", - "ts-api-utils": "^2.5.0" + "@typescript-eslint/typescript-estree": "8.28.0", + "@typescript-eslint/utils": "8.28.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2744,14 +5188,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.2.tgz", - "integrity": "sha512-y5Ukl3oVp7e/VGxqIoEXoeb/Roj71PAJ4WG/N/RGj+eeDvKRLM15kGr9MijLbN0i03S52zxu31Z98E5gWChJKw==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.28.0.tgz", + "integrity": "sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==", "dev": true, "license": "MIT", "engines": { @@ -2763,21 +5207,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.2.tgz", - "integrity": "sha512-DgNOEsl4pdYzwSL+N/Cl33tX1Hlw3FvId73LnKXfq7jnrF2viOEn7X+P7RBkkSWCVm92gnWd28GIC5vJuLREeA==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.28.0.tgz", + "integrity": "sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.71.2", - "@typescript-eslint/tsconfig-utils": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.0" + "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/visitor-keys": "8.28.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2787,20 +5230,33 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.2.tgz", - "integrity": "sha512-RyKa1G1M9rKHDhrk+HJtiF1MvLD5Ux2JW3TSkzw+02pRALdpJb+QzG1Y5em+LvCgzGwgg8H7mBRFKljNz7ImPw==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.28.0.tgz", + "integrity": "sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.28.0", + "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/typescript-estree": "8.28.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2810,19 +5266,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.2.tgz", - "integrity": "sha512-zozlN0UA32bSG2zkKAgQyRYSbEISVoyU6vvkKYo2aSny74D8Jh4e+POkJ6Lk0dlezZi5x7TtD+88Xb06IB8nhg==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.28.0.tgz", + "integrity": "sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", - "eslint-visitor-keys": "^5.0.0" + "@typescript-eslint/types": "8.28.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2833,22 +5289,22 @@ } }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@ungap/structured-clone": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.4.0.tgz", - "integrity": "sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "dev": true, "license": "ISC" }, @@ -3027,54 +5483,38 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/accepts/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "dev": true, "license": "MIT", "peer": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=6.5" } }, - "node_modules/accepts/node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "mime-db": "^1.54.0" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">= 0.6" } }, "node_modules/acorn": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.19.0.tgz", - "integrity": "sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "bin": { @@ -3084,6 +5524,19 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-phases": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.3.tgz", + "integrity": "sha512-jtKLnfoOzm28PazuQ4dVBcE9Jeo6ha1GAJvq3N0LlNOszmTfx+wSycBehn+FN0RnyeR77IBxN/qVYMw0Rlj0Xw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -3095,9 +5548,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.5", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", - "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, "license": "MIT", "dependencies": { @@ -3108,12 +5561,11 @@ } }, "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 14" } @@ -3131,9 +5583,9 @@ } }, "node_modules/ajv": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", "dependencies": { @@ -3148,9 +5600,9 @@ } }, "node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, "license": "MIT", "dependencies": { @@ -3166,9 +5618,9 @@ } }, "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", - "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", "dependencies": { @@ -3219,13 +5671,16 @@ } }, "node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -3254,9 +5709,9 @@ } }, "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { @@ -3331,6 +5786,14 @@ "repeat-string": "^1.6.1" } }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3354,16 +5817,195 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz", + "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.4", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", + "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.3", + "core-js-compat": "^3.40.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.4.tgz", + "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.4" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-syntax-hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz", + "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "hermes-parser": "0.25.1" + } + }, + "node_modules/babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", + "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, "engines": { - "node": "18 || 20 || >=22" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -3384,17 +6026,14 @@ ], "license": "MIT" }, - "node_modules/baseline-browser-mapping": { - "version": "2.11.29", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.29.tgz", - "integrity": "sha512-YeesxhUmR4h5y5V8KF8iBCqJb8YFrBJ++XBTeGcWIaQOYXGN19JM0FoiOjAhwuDoln8owMgXcWBmgHtYSkky2w==", + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, + "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": "^4.5.0 || >= 5.9" } }, "node_modules/binary-extensions": { @@ -3411,24 +6050,24 @@ } }, "node_modules/body-parser": { - "version": "1.20.8", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.8.tgz", - "integrity": "sha512-JNcyFQ64OiijEkPzUBTCe+hyPXUD/3LEldGQ6iF5LR1w00mx9o7xtDWHXBY2iItjdCFGoilOLNQbH943ut7pHA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "~3.1.2", + "bytes": "3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.16.0", - "raw-body": "~2.5.3", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", "type-is": "~1.6.18", - "unpipe": "~1.0.0" + "unpipe": "1.0.0" }, "engines": { "node": ">= 0.8", @@ -3453,16 +6092,13 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", - "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "20 || >=22" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -3486,9 +6122,9 @@ "license": "ISC" }, "node_modules/browserslist": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.3.tgz", - "integrity": "sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, "funding": [ { @@ -3506,11 +6142,10 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.11.26", - "caniuse-lite": "^1.0.30001813", - "electron-to-chromium": "^1.5.439", - "node-releases": "^2.0.57", - "update-browserslist-db": "^1.3.3" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -3520,11 +6155,11 @@ } }, "node_modules/bser": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.2.tgz", - "integrity": "sha512-V2o8YS2EhrKMO9AumnkK0ynynfFlsajpYupwq7S46H5mhcanwxDkNTw3K67wPIcKTH1ffkA4vhMOtAc7gRmPZw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "peer": true, "dependencies": { "node-int64": "^0.4.0" @@ -3572,15 +6207,15 @@ } }, "node_modules/call-bind": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", - "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "get-intrinsic": "^1.3.0", + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" }, "engines": { @@ -3621,6 +6256,45 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-callsite/node_modules/callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -3632,22 +6306,20 @@ } }, "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "license": "MIT", + "peer": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001816", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001816.tgz", - "integrity": "sha512-+8Yx7BXCoqk6IF8yTicjfUR6D/ldJzdlsodlEOiOSPmhK844WIgk67/zIQaGAOxNkZyyvBlrRFnLvqKIoqbAFw==", + "version": "1.0.30001707", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz", + "integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==", "dev": true, "funding": [ { @@ -3750,22 +6422,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/chalk/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3830,20 +6486,70 @@ "node": ">= 6" } }, - "node_modules/chrome-trace-event": { + "node_modules/chrome-launcher": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", + "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/chromium-edge-launcher": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz", + "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "node_modules/chromium-edge-launcher/node_modules/mkdirp": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "license": "MIT", + "peer": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, "engines": { - "node": ">=6.0" + "node": ">=10" } }, "node_modules/ci-info": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", - "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, "funding": [ { @@ -3865,9 +6571,9 @@ "peer": true }, "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", "dev": true, "license": "MIT", "peer": true, @@ -3893,6 +6599,40 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -4021,10 +6761,25 @@ "node": ">= 0.6" } }, + "node_modules/core-js-compat": { + "version": "3.41.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz", + "integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "browserslist": "^4.24.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/cors": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", - "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "dev": true, "license": "MIT", "dependencies": { @@ -4033,10 +6788,49 @@ }, "engines": { "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" } }, "node_modules/create-require": { @@ -4061,19 +6855,34 @@ "node": ">= 8" } }, + "node_modules/cssstyle": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.3.0.tgz", + "integrity": "sha512-6r0NiY0xizYqfBvWp1G7WXJ06/bZyrk7Dc6PHql82C/pKGUTKu4yAX4Y8JPamb1ob9nBKuxWzCGTRuGwU3yxJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^3.1.1", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/cucumber-tsflow": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/cucumber-tsflow/-/cucumber-tsflow-4.6.1.tgz", - "integrity": "sha512-M4QMjM4FBVFnZN53uAj8IAprtcyfcKZ2eqO0d7YL/ZjcpI3F1PqTD4aKCmQuugtnqvrjIIo51tF6j91QAAcI7w==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/cucumber-tsflow/-/cucumber-tsflow-4.4.4.tgz", + "integrity": "sha512-oe2fPcAxWljZTc4+u0whbXIxZvjWzXfsieoY/TGuHY4aDLLOCFVLOVIxV8bKEI53PQhxJH809VugWHe2DB+nJg==", "dev": true, "license": "MIT", "dependencies": { + "callsites": "^3.1.0", "log4js": "^6.3.0", "source-map-support": "^0.5.19", "underscore": "^1.8.3" }, "peerDependencies": { - "@cucumber/cucumber": "^7 || ^8 || ^9 || ^10 || ^11 || ^12" + "@cucumber/cucumber": "^7 || ^8 || ^9 || ^10" } }, "node_modules/custom-event": { @@ -4083,6 +6892,20 @@ "dev": true, "license": "MIT" }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/date-format": { "version": "4.0.14", "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", @@ -4094,9 +6917,9 @@ } }, "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "license": "MIT", "dependencies": { @@ -4124,6 +6947,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/decimal.js": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "dev": true, + "license": "MIT" + }, "node_modules/deep-eql": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", @@ -4193,17 +7023,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", @@ -4261,15 +7080,25 @@ "license": "MIT" }, "node_modules/diff": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", - "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4311,6 +7140,14 @@ "node": ">= 0.4" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -4319,9 +7156,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.459", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.459.tgz", - "integrity": "sha512-4SC9HHSFjO/liAhifpdOL5hG9b4BP7/5G3y3UPZVO8trlAXr1CaUEEJL0gWK3kOcYcZrOA5rkwG45Gra/lTIgg==", + "version": "1.5.128", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.128.tgz", + "integrity": "sha512-bo1A4HH/NS522Ws0QNFIzyPcyUUNV/yyy70Ho1xqfGYzPUme2F/xr4tlEOuM6/A538U1vDA7a4XfCd1CKRegKQ==", "dev": true, "license": "ISC" }, @@ -4343,21 +7180,21 @@ } }, "node_modules/engine.io": { - "version": "6.6.11", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.11.tgz", - "integrity": "sha512-z34mGpLoY/82ZbkX1LqGMIaf3wjVMPL6gVC681QDqnmzJ26synI8qAE32P+a7UazmpJZ8UGrFIeAavgRfXzYrg==", + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", + "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", "dev": true, "license": "MIT", "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", - "@types/ws": "^8.5.12", "accepts": "~1.3.4", + "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", - "debug": "~4.4.1", + "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.21.0" + "ws": "~8.17.1" }, "engines": { "node": ">=10.2.0" @@ -4373,34 +7210,28 @@ "node": ">=10.0.0" } }, - "node_modules/engine.io/node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "ms": "^2.1.3" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/engine.io/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/engine.io/node_modules/ws": { - "version": "8.21.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", - "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "license": "MIT", "engines": { @@ -4420,14 +7251,14 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.26.0.tgz", - "integrity": "sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==", + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", + "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.3.3" + "tapable": "^2.2.0" }, "engines": { "node": ">=10.13.0" @@ -4449,6 +7280,30 @@ "node": ">= 0.4" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/error-stack-parser": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", @@ -4481,16 +7336,16 @@ } }, "node_modules/es-module-lexer": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", - "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", - "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, "license": "MIT", "dependencies": { @@ -4524,9 +7379,9 @@ "license": "MIT" }, "node_modules/esbuild": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", - "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", + "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -4537,32 +7392,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.2", - "@esbuild/android-arm": "0.28.2", - "@esbuild/android-arm64": "0.28.2", - "@esbuild/android-x64": "0.28.2", - "@esbuild/darwin-arm64": "0.28.2", - "@esbuild/darwin-x64": "0.28.2", - "@esbuild/freebsd-arm64": "0.28.2", - "@esbuild/freebsd-x64": "0.28.2", - "@esbuild/linux-arm": "0.28.2", - "@esbuild/linux-arm64": "0.28.2", - "@esbuild/linux-ia32": "0.28.2", - "@esbuild/linux-loong64": "0.28.2", - "@esbuild/linux-mips64el": "0.28.2", - "@esbuild/linux-ppc64": "0.28.2", - "@esbuild/linux-riscv64": "0.28.2", - "@esbuild/linux-s390x": "0.28.2", - "@esbuild/linux-x64": "0.28.2", - "@esbuild/netbsd-arm64": "0.28.2", - "@esbuild/netbsd-x64": "0.28.2", - "@esbuild/openbsd-arm64": "0.28.2", - "@esbuild/openbsd-x64": "0.28.2", - "@esbuild/openharmony-arm64": "0.28.2", - "@esbuild/sunos-x64": "0.28.2", - "@esbuild/win32-arm64": "0.28.2", - "@esbuild/win32-ia32": "0.28.2", - "@esbuild/win32-x64": "0.28.2" + "@esbuild/aix-ppc64": "0.25.1", + "@esbuild/android-arm": "0.25.1", + "@esbuild/android-arm64": "0.25.1", + "@esbuild/android-x64": "0.25.1", + "@esbuild/darwin-arm64": "0.25.1", + "@esbuild/darwin-x64": "0.25.1", + "@esbuild/freebsd-arm64": "0.25.1", + "@esbuild/freebsd-x64": "0.25.1", + "@esbuild/linux-arm": "0.25.1", + "@esbuild/linux-arm64": "0.25.1", + "@esbuild/linux-ia32": "0.25.1", + "@esbuild/linux-loong64": "0.25.1", + "@esbuild/linux-mips64el": "0.25.1", + "@esbuild/linux-ppc64": "0.25.1", + "@esbuild/linux-riscv64": "0.25.1", + "@esbuild/linux-s390x": "0.25.1", + "@esbuild/linux-x64": "0.25.1", + "@esbuild/netbsd-arm64": "0.25.1", + "@esbuild/netbsd-x64": "0.25.1", + "@esbuild/openbsd-arm64": "0.25.1", + "@esbuild/openbsd-x64": "0.25.1", + "@esbuild/sunos-x64": "0.25.1", + "@esbuild/win32-arm64": "0.25.1", + "@esbuild/win32-ia32": "0.25.1", + "@esbuild/win32-x64": "0.25.1" } }, "node_modules/escalade": { @@ -4671,14 +7525,14 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.5.7", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.7.tgz", - "integrity": "sha512-WjHyn3GrFd+ZR0rzsLiM4zJZ35PZMOE0SUIxzGmnWNG0126yNfJKJzObmmkYDwHJfGlkz3PSlzyG9ez/LJntwg==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.5.tgz", + "integrity": "sha512-IKKP8R87pJyMl7WWamLgPkloB16dagPIdd2FjBDbyRYPKo93wS/NbCOPh6gH+ieNLC+XZrhJt/kWj0PS/DFdmg==", "dev": true, "license": "MIT", "dependencies": { - "prettier-linter-helpers": "^1.0.1", - "synckit": "^0.12.3" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.10.2" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -4767,17 +7621,10 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/eslint/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { @@ -4785,31 +7632,11 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/eslint/node_modules/js-yaml": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", - "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -4819,9 +7646,9 @@ } }, "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -4864,9 +7691,9 @@ } }, "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -4927,6 +7754,17 @@ "node": ">= 0.6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -4945,27 +7783,26 @@ } }, "node_modules/expect": { - "version": "30.5.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.5.2.tgz", - "integrity": "sha512-0LNuMvs8/5mRYhnCR4k+lGV7fqPMs6Bnksda4S3zsCUmdxBpAn4zU4NNzXdq1pMKe/H4W5t/zVIDSJ/H3e0vDA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.5.2", - "@jest/get-type": "30.5.0", - "jest-matcher-utils": "30.5.2", - "jest-message-util": "30.5.1", - "jest-mock": "30.5.2", - "jest-util": "30.5.1" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/exponential-backoff": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", - "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", + "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", "dev": true, "license": "Apache-2.0", "peer": true @@ -4991,6 +7828,36 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -5029,62 +7896,30 @@ "license": "BSD-3-Clause" }, "node_modules/fastq": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz", - "integrity": "sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, - "node_modules/fb-dotslash": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/fb-dotslash/-/fb-dotslash-0.5.8.tgz", - "integrity": "sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA==", - "dev": true, - "license": "(MIT OR Apache-2.0)", - "peer": true, - "bin": { - "dotslash": "bin/dotslash" - }, - "engines": { - "node": ">=20" - } - }, "node_modules/fb-watchman": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.4.tgz", - "integrity": "sha512-tGQtaoYisPDriJBN0mT5yZSyNETnJGA1gTYxaVRAE5KUO3LI9kPUc9WIu8JXcxaIci+faIKlzXqXyPgrmubtBQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "bser": "2.1.2" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "bser": "2.1.1" } }, "node_modules/fflate": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", - "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", "license": "MIT" }, "node_modules/figures": { @@ -5190,6 +8025,22 @@ "node": ">= 0.8" } }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -5207,20 +8058,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-up-simple": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", - "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -5247,9 +8084,9 @@ } }, "node_modules/flatted": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", - "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, "license": "ISC" }, @@ -5261,35 +8098,21 @@ "license": "MIT", "peer": true }, - "node_modules/flow-estree": { - "version": "0.327.0", - "resolved": "https://registry.npmjs.org/flow-estree/-/flow-estree-0.327.0.tgz", - "integrity": "sha512-f9vK751YUzD0qaHSpKc5/qQM6gqOlgGS+4ZRqTNcZOpVqn3mC55yEQ6dUG2K1eaVm5FbKkz9CFWe6XNvrkQFQg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, "node_modules/flow-parser": { - "version": "0.327.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.327.0.tgz", - "integrity": "sha512-/MYZ5hXWf5ozpbdfUDmazMgQXviLxWEiRLH3MppEGDdW0itRVqmB5UaU7QX+SBCDNiq+gEesSVn8nlxmPDyDkw==", + "version": "0.266.1", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.266.1.tgz", + "integrity": "sha512-dON6h+yO7FGa/FO5NQCZuZHN0o3I23Ev6VYOJf9d8LpdrArHPt39wE++LLmueNV/hNY5hgWGIIrgnrDkRcXkPg==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "flow-estree": "0.327.0" - }, "engines": { "node": ">=0.4.0" } }, "node_modules/follow-redirects": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.1.tgz", - "integrity": "sha512-FNvFGzoMLWmE6Yj9spb/zjd7yiNCHiAW9/Tg9CXrQ8wuu32HtlJOwWO11OJafl5FfY3DxTdQ0vj42zU1kvv5jg==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "dev": true, "funding": [ { @@ -5323,18 +8146,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", - "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.4", - "mime-types": "^2.1.35" + "hasown": "^2.0.2", + "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" @@ -5408,16 +8249,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/generator-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -5474,6 +8305,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", @@ -5488,20 +8330,36 @@ "node": ">= 0.4" } }, + "node_modules/get-tsconfig": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "ISC", "peer": true, "dependencies": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": "18 || 20 || >=22" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -5520,6 +8378,13 @@ "node": ">=10.13.0" } }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -5660,9 +8525,9 @@ } }, "node_modules/hasown": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5682,53 +8547,67 @@ "he": "bin/he" } }, - "node_modules/hermes-compiler": { - "version": "260318099.0.4", - "resolved": "https://registry.npmjs.org/hermes-compiler/-/hermes-compiler-260318099.0.4.tgz", - "integrity": "sha512-8odcPFkPC82HlqCl0C5QI9mBN4rEAT+IAo55sJhzwKw//K3qZloiv3ex6J2O8CuBbhdmkJozfidNsset2KH25w==", + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", "dev": true, "license": "MIT", "peer": true }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "hermes-estree": "0.25.1" + } + }, "node_modules/hosted-git-info": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.3.tgz", - "integrity": "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true, "license": "ISC", - "peer": true, + "peer": true + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", "dependencies": { - "lru-cache": "^11.1.0" + "whatwg-encoding": "^3.1.1" }, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "license": "MIT", "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" } }, "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "license": "MIT", "engines": { @@ -5750,13 +8629,26 @@ "node": ">=8.0.0" } }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/https-proxy-agent": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "agent-base": "^7.1.2", "debug": "4" @@ -5808,15 +8700,32 @@ "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.12.tgz", - "integrity": "sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { "node": ">= 4" } }, + "node_modules/image-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.0.tgz", + "integrity": "sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -5855,20 +8764,6 @@ "node": ">=8" } }, - "node_modules/index-to-position": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", - "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -5927,6 +8822,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -5954,13 +8857,13 @@ } }, "node_modules/is-core-module": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.17.0.tgz", - "integrity": "sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.4" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -5986,6 +8889,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -6024,15 +8938,14 @@ } }, "node_modules/is-generator-function": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" }, @@ -6118,6 +9031,27 @@ "node": ">=8" } }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -6231,297 +9165,289 @@ "dev": true, "license": "ISC" }, - "node_modules/jest-diff": { - "version": "30.5.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.5.2.tgz", - "integrity": "sha512-rBtHnI6BWTiWj3lM7fOLVfChx7R9B0u9VV3PRHawKs79x6ZjW1QoSrKenaigNGWlvhtoi2BqvDbABDie+Os3xQ==", + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/diff-sequences": "30.5.0", - "@jest/get-type": "30.5.0", - "chalk": "^4.1.2", - "pretty-format": "30.5.1" - }, + "peer": true, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "peer": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-matcher-utils": { - "version": "30.5.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.5.2.tgz", - "integrity": "sha512-lFkB365PTIHOhPzwrb9T6gvlDnPpOZ7/c3ewOKKB7bzztqjVrtlyRL2MkyfJXpyY2u2SKw001JKrTx14fBUFcQ==", + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", + "peer": true, "dependencies": { - "@jest/get-type": "30.5.0", - "chalk": "^4.1.2", - "jest-diff": "30.5.2", - "pretty-format": "30.5.1" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8" } }, - "node_modules/jest-message-util": { - "version": "30.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.5.1.tgz", - "integrity": "sha512-UdQlLdd9wL/Ys7xRErckqwD6wPlSZYueosSWuHc1r2ztGLwlgPvtSJq2+BPEgaEY13WLvfFbmhTj8pba0Sd1jg==", + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@jest/types": "30.5.1", - "@types/stack-utils": "^2.0.3", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "jest-util": "30.5.1", - "picomatch": "^4.0.3", - "pretty-format": "30.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/jest-mock": { - "version": "30.5.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.5.2.tgz", - "integrity": "sha512-KTHb37Fhj8xY8qPFvTFaFJHcdsumQp+ExsUlgoX232Agmc706gagBs53+CYvulV7MVQo9AgXOUxsqzzVBoJlrA==", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", + "peer": true, "dependencies": { - "@jest/expect-utils": "30.5.2", - "@jest/types": "30.5.1", - "@types/node": "*", - "jest-util": "30.5.1" + "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-regex-util": { - "version": "30.5.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.5.0.tgz", - "integrity": "sha512-Mg0WK7A6xRHLSA1udJ8y9f3lM0uUhFTBnLKzwPmqB9AylvpleJ6BLemR8K9dK27DY+cesDryoA7yLZCAHsPG1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jest-util": { - "version": "30.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.5.1.tgz", - "integrity": "sha512-yKuxmNy2rSbTXw+3SIPanJo+nV4/BS1p26v44IYBFMsswSQySfMMcPHErnOncda7i9HEz0q605rIhSTBVgrZTg==", + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.5.1", - "@types/node": "*", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "graceful-fs": "^4.2.11", - "picomatch": "^4.0.3" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-validate": { + "node_modules/jest-environment-node": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-validate/node_modules/@jest/schemas": { + "node_modules/jest-get-type": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-validate/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/jest-validate/node_modules/@sinclair/typebox": { - "version": "0.27.12", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz", - "integrity": "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==", + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "license": "MIT", - "peer": true + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/jest-validate/node_modules/pretty-format": { + "node_modules/jest-message-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-worker": { + "node_modules/jest-mock": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-worker/node_modules/@jest/schemas": { + "node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-worker/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-worker/node_modules/@sinclair/typebox": { - "version": "0.27.12", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz", - "integrity": "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/jest-worker/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "node_modules/jest-util/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], "license": "MIT", - "peer": true, "engines": { - "node": ">=8" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/jest-worker/node_modules/jest-util": { + "node_modules/jest-validate": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@jest/types": "^29.6.3", - "@types/node": "*", + "camelcase": "^6.2.0", "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-worker/node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", "peer": true, "engines": { - "node": ">=8.6" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/js-tokens": { @@ -6532,9 +9458,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "3.15.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.2.tgz", - "integrity": "sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "license": "MIT", "dependencies": { @@ -6553,6 +9479,103 @@ "license": "0BSD", "peer": true }, + "node_modules/jscodeshift": { + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-17.3.0.tgz", + "integrity": "sha512-LjFrGOIORqXBU+jwfC9nbkjmQfFldtMIoS6d9z2LG/lkmyNXsJAySPT+2SWXJEoE68/bCWcxKpXH37npftgmow==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/preset-flow": "^7.24.7", + "@babel/preset-typescript": "^7.24.7", + "@babel/register": "^7.24.6", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.7", + "neo-async": "^2.5.0", + "picocolors": "^1.0.1", + "recast": "^0.23.11", + "tmp": "^0.2.3", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true + } + } + }, + "node_modules/jscodeshift/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/jsdom": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", + "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.5.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.1.1", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.1", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -6574,6 +9597,21 @@ "dev": true, "license": "MIT" }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -6762,28 +9800,22 @@ "webpack": "^5.0.0" } }, - "node_modules/karma-webpack/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, "node_modules/karma-webpack/node_modules/brace-expansion": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", - "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/karma-webpack/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -6801,21 +9833,10 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/karma-webpack/node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/karma-webpack/node_modules/glob/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -6825,33 +9846,10 @@ "node": "*" } }, - "node_modules/karma-webpack/node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/karma/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, "node_modules/karma/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { @@ -6863,7 +9861,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -6895,9 +9893,9 @@ } }, "node_modules/karma/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -6930,6 +9928,17 @@ "json-buffer": "3.0.1" } }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/knuth-shuffle-seeded": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/knuth-shuffle-seeded/-/knuth-shuffle-seeded-1.0.6.tgz", @@ -6948,23 +9957,54 @@ "dev": true, "license": "MIT", "peer": true, - "engines": { - "node": ">=6" + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lighthouse-logger": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", + "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "node_modules/lighthouse-logger/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/lighthouse-logger/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } + "peer": true }, "node_modules/lil-uuid": { "version": "0.1.1", @@ -6972,6 +10012,24 @@ "integrity": "sha512-GhWI8f61tBlMeqULZ1QWhFiiyFIFdPlg//S8Udq1wjq1FJhpFKTfnbduSxAQjueofeUtpr7UvQ/lIK/sKUF8dg==", "license": "MIT" }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -6989,12 +10047,20 @@ } }, "node_modules/lodash": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", - "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true, "license": "MIT" }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -7010,14 +10076,6 @@ "license": "MIT", "peer": true }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -7103,20 +10161,16 @@ } }, "node_modules/lru-cache": { - "version": "11.5.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", - "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "BlueOak-1.0.0", - "peer": true, - "engines": { - "node": "20 || >=22" - } + "license": "ISC" }, "node_modules/luxon": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", - "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.2.1.tgz", + "integrity": "sha512-QrwPArQCNLAKGO/C+ZIilgIuDnEnKx5QYODdDtbFaxzsbZcc/a7WFq7MhsVYgRlwawLtvOUESTlfJ+hc/USqPg==", "dev": true, "license": "MIT", "peer": true, @@ -7125,13 +10179,39 @@ } }, "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver" } }, "node_modules/make-error": { @@ -7141,6 +10221,25 @@ "dev": true, "license": "ISC" }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/marky": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", + "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", + "dev": true, + "license": "Apache-2.0", + "peer": true + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -7176,45 +10275,58 @@ "dev": true, "license": "MIT" }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/metro": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro/-/metro-0.87.1.tgz", - "integrity": "sha512-1oyLU9elM7hPAsKIqKooEekwxiuWr27+MZBhUROPhzcbXhMDxK64GPF/hCXwBZVp1F89ODavCrBmJtLx9WtBoQ==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.81.4.tgz", + "integrity": "sha512-78f0aBNPuwXW7GFnSc+Y0vZhbuQorXxdgqQfvSRqcSizqwg9cwF27I05h47tL8AzQcizS1JZncvq4xf5u/Qykw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/code-frame": "^7.29.0", + "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", - "@babel/generator": "^7.29.1", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", - "accepts": "^2.0.0", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.3", + "@babel/types": "^7.25.2", + "accepts": "^1.3.7", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", "connect": "^3.6.5", - "debug": "^4.4.0", + "debug": "^2.2.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", - "flow-parser": "0.331.0", "graceful-fs": "^4.2.4", + "hermes-parser": "0.25.1", + "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", - "metro-babel-transformer": "0.87.1", - "metro-cache": "0.87.1", - "metro-cache-key": "0.87.1", - "metro-config": "0.87.1", - "metro-core": "0.87.1", - "metro-file-map": "0.87.1", - "metro-resolver": "0.87.1", - "metro-runtime": "0.87.1", - "metro-source-map": "0.87.1", - "metro-symbolicate": "0.87.1", - "metro-transform-plugins": "0.87.1", - "metro-transform-worker": "0.87.1", - "mime-types": "^3.0.1", + "metro-babel-transformer": "0.81.4", + "metro-cache": "0.81.4", + "metro-cache-key": "0.81.4", + "metro-config": "0.81.4", + "metro-core": "0.81.4", + "metro-file-map": "0.81.4", + "metro-resolver": "0.81.4", + "metro-runtime": "0.81.4", + "metro-source-map": "0.81.4", + "metro-symbolicate": "0.81.4", + "metro-transform-plugins": "0.81.4", + "metro-transform-worker": "0.81.4", + "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", @@ -7226,73 +10338,46 @@ "metro": "src/cli.js" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, "node_modules/metro-babel-transformer": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.87.1.tgz", - "integrity": "sha512-orvRIGpb0yK1yMbk5YP3dhVKjmoxUkRB9fdltGJxNppEqus/1tFpNuf9KnGFR3Qjg0izoUrJ4z6WgoBvdkXPrA==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.81.4.tgz", + "integrity": "sha512-WW0yswWrW+eTVK9sYD+b1HwWOiUlZlUoomiw9TIOk0C+dh2V90Wttn/8g62kYi0Y4i+cJfISerB2LbV4nuRGTA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", - "flow-parser": "0.331.0", - "metro-cache-key": "0.87.1", + "hermes-parser": "0.25.1", "nullthrows": "^1.1.1" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" - } - }, - "node_modules/metro-babel-transformer/node_modules/flow-estree": { - "version": "0.331.0", - "resolved": "https://registry.npmjs.org/flow-estree/-/flow-estree-0.331.0.tgz", - "integrity": "sha512-FVLYkSL/ITb/QXBEQvNWPjPooRGswuUtGOwrH+puSlMDneNkxy640+FZsk/TfKL+b7Wbw/Fg9FTUv2bMQDpj2w==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/metro-babel-transformer/node_modules/flow-parser": { - "version": "0.331.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.331.0.tgz", - "integrity": "sha512-vEZcHIlnKeN8JSVtYFczj8sWJfHIJOkz+YG00O/oul/Bete+t1ZhTi+O6JRRLFYvGW+yJkZ0YgL16iStnbkUqQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "flow-estree": "0.331.0" - }, - "engines": { - "node": ">=0.4.0" + "node": ">=18.18" } }, "node_modules/metro-cache": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.87.1.tgz", - "integrity": "sha512-juNPaj0Xi5tkLp8imXqvbSnEIijwKG36m7OiFFVJMqEkiURwAjkMFVek3/xpix1+LVQqO7kjVp3PvuvIM61mKQ==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.81.4.tgz", + "integrity": "sha512-sxCPH3gowDxazSaZZrwdNPEpnxR8UeXDnvPjBF9+5btDBNN2DpWvDAXPvrohkYkFImhc0LajS2V7eOXvu9PnvQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", - "https-proxy-agent": "^7.0.5", - "metro-core": "0.87.1" + "metro-core": "0.81.4" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, "node_modules/metro-cache-key": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.87.1.tgz", - "integrity": "sha512-scqVVPMA2c+RVO12I3wyMDp5xCkRPLsyrcG4Qc3xfU5JR0EW/0sz2tjty+5UjMUtG09uiM1KYQ8HjWg7OQXHtw==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.81.4.tgz", + "integrity": "sha512-3SaWQybvf1ivasjBegIxzVKLJzOpcz+KsnGwXFOYADQq0VN4cnM7tT+u2jkOhk6yJiiO1WIjl68hqyMOQJRRLg==", "dev": true, "license": "MIT", "peer": true, @@ -7300,70 +10385,91 @@ "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, "node_modules/metro-config": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.87.1.tgz", - "integrity": "sha512-NmkDlc/qZAdo5gTkVTuO2AKE/khemRKRH5IA+SKfqUBJigI5GqZ5TOXhmEokhlkAqzjt8dyzKhzI6FHvXoXaTQ==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.81.4.tgz", + "integrity": "sha512-QnhMy3bRiuimCTy7oi5Ug60javrSa3lPh0gpMAspQZHY9h6y86jwHtZPLtlj8hdWQESIlrbeL8inMSF6qI/i9Q==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "connect": "^3.6.5", + "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", - "metro": "0.87.1", - "metro-cache": "0.87.1", - "metro-core": "0.87.1", - "metro-runtime": "0.87.1" + "metro": "0.81.4", + "metro-cache": "0.81.4", + "metro-core": "0.81.4", + "metro-runtime": "0.81.4" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, "node_modules/metro-core": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.87.1.tgz", - "integrity": "sha512-xizzky/4+c/Mkznege8OW05j7bSdM39VPoEps61Se4+hf32UQujmbvLvIE9+UnP6kNEPVomk0Fw8NsBK9iRQmw==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.81.4.tgz", + "integrity": "sha512-GdL4IgmgJhrMA/rTy2lRqXKeXfC77Rg+uvhUEkbhyfj/oz7PrdSgvIFzziapjdHwk1XYq0KyFh/CcVm8ZawG6A==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", - "metro-resolver": "0.87.1" + "metro-resolver": "0.81.4" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, "node_modules/metro-file-map": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.87.1.tgz", - "integrity": "sha512-9sPuNCojC3pS4vj+ZPY7FXmHGpdJeckXuKXQrDAfJvZc60AF8owRFTkI8XdwlwrmPIB2w++KraK9FMEXvC4wJw==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.81.4.tgz", + "integrity": "sha512-qUIBzkiqOi3qEuscu4cJ83OYQ4hVzjON19FAySWqYys9GKCmxlKa7LkmwqdpBso6lQl+JXZ7nCacX90w5wQvPA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "debug": "^4.4.0", + "debug": "^2.2.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", - "nullthrows": "^1.1.1" + "nullthrows": "^1.1.1", + "walker": "^1.0.7" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" + } + }, + "node_modules/metro-file-map/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" } }, + "node_modules/metro-file-map/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/metro-minify-terser": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.87.1.tgz", - "integrity": "sha512-YK4k1oO1wV48hfE+Nbw2rJCnAgeabzrgT/xH5ha5n9gbK4p3HYFC898cERUiyTl9vRh58CNTiXRc88f7y6PfKg==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.81.4.tgz", + "integrity": "sha512-oVvq/AGvqmbhuijJDZZ9npeWzaVyeBwQKtdlnjcQ9fH7nR15RiBr5y2zTdgTEdynqOIb1Kc16l8CQIUSzOWVFA==", "dev": true, "license": "MIT", "peer": true, @@ -7372,13 +10478,13 @@ "terser": "^5.15.0" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, "node_modules/metro-resolver": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.87.1.tgz", - "integrity": "sha512-FXH/brY69wT6sPxaSW8BhMmDGD/6irmBr/cL4rUi+VWwqR3pbvdcfUOfyjcHucgQ7pe5IW3xJY21eHKLVKNumQ==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.81.4.tgz", + "integrity": "sha512-Ng7G2mXjSExMeRzj6GC19G6IJ0mfIbOLgjArsMWJgtt9ViZiluCwgWsMW9juBC5NSwjJxUMK2x6pC5NIMFLiHA==", "dev": true, "license": "MIT", "peer": true, @@ -7386,13 +10492,13 @@ "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, "node_modules/metro-runtime": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.87.1.tgz", - "integrity": "sha512-kjeuSvInsM6OzBjkCQsWxnkrKZFMKtnkCl38oXWRI9lDGs2L9hGs9Tak9sQYJ9h3gtDujneB7wZio+irgqJKDw==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.81.4.tgz", + "integrity": "sha512-fBoRgqkF69CwyPtBNxlDi5ha26Zc8f85n2THXYoh13Jn/Bkg8KIDCdKPp/A1BbSeNnkH/++H2EIIfnmaff4uRg==", "dev": true, "license": "MIT", "peer": true, @@ -7401,29 +10507,30 @@ "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, "node_modules/metro-source-map": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.87.1.tgz", - "integrity": "sha512-Bqpm0PBGdy53pigIJb4HRF7QxD2pUOdgSmVh/4AWbP635kSCv+Y6ltVxUZgSnzS/QbSmzyCGijmRPlXMj2/qHw==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.81.4.tgz", + "integrity": "sha512-IOwVQ7mLqoqvsL70RZtl1EyE3f9jp43kVsAsb/B/zoWmu0/k4mwEhGLTxmjdXRkLJqPqPrh7WmFChAEf9trW4Q==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/traverse": "^7.25.3", + "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", + "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", - "metro-symbolicate": "0.87.1", + "metro-symbolicate": "0.81.4", "nullthrows": "^1.1.1", - "ob1": "0.87.1", + "ob1": "0.81.4", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, "node_modules/metro-source-map/node_modules/source-map": { @@ -7438,16 +10545,16 @@ } }, "node_modules/metro-symbolicate": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.87.1.tgz", - "integrity": "sha512-rcGvwabrg0lbXGRGRKl14PY3My3+dkno2jZYhdJEuH2DmjTtTkV5bYwgto4JtV/Lbe+sXE6GO1UGg654430uow==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.81.4.tgz", + "integrity": "sha512-rWxTmYVN6/BOSaMDUHT8HgCuRf6acd0AjHkenYlHpmgxg7dqdnAG1hLq999q2XpW5rX+cMamZD5W5Ez2LqGaag==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", - "metro-source-map": "0.87.1", + "metro-source-map": "0.81.4", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" @@ -7456,7 +10563,7 @@ "metro-symbolicate": "src/index.js" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, "node_modules/metro-symbolicate/node_modules/source-map": { @@ -7471,50 +10578,58 @@ } }, "node_modules/metro-transform-plugins": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.87.1.tgz", - "integrity": "sha512-qMiJ/x+VfqumFJJSefKS6nj8uojzC29b2/aK8vlMuFABIqGjDucICEOXd2Yt6k/XMFAgAcaJvShUOT0HLyYaPw==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.81.4.tgz", + "integrity": "sha512-nlP069nDXm4v28vbll4QLApAlvVtlB66rP6h+ml8Q/CCQCPBXu2JLaoxUmkIOJQjLhMRUcgTyQHq+TXWJhydOQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", - "@babel/generator": "^7.29.1", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", + "@babel/generator": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.3", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, "node_modules/metro-transform-worker": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.87.1.tgz", - "integrity": "sha512-VOzs3OV405FuOLYdAhqA2wsn1F9lvueDVxMDLvCKaQ44U+yknIqphJ9eMjjsGwLDZiJq9sW3DMLhjD27JxQgqQ==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.81.4.tgz", + "integrity": "sha512-lKAeRZ8EUMtx2cA/Y4KvICr9bIr5SE03iK3lm+l9wyn2lkjLUuPjYVep159inLeDqC6AtSubsA8MZLziP7c03g==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", - "@babel/generator": "^7.29.1", - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", - "metro": "0.87.1", - "metro-babel-transformer": "0.87.1", - "metro-cache": "0.87.1", - "metro-cache-key": "0.87.1", - "metro-minify-terser": "0.87.1", - "metro-source-map": "0.87.1", - "metro-transform-plugins": "0.87.1", + "metro": "0.81.4", + "metro-babel-transformer": "0.81.4", + "metro-cache": "0.81.4", + "metro-cache-key": "0.81.4", + "metro-minify-terser": "0.81.4", + "metro-source-map": "0.81.4", + "metro-transform-plugins": "0.81.4", "nullthrows": "^1.1.1" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, + "node_modules/metro/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/metro/node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -7531,75 +10646,82 @@ "node": ">=12" } }, - "node_modules/metro/node_modules/flow-estree": { - "version": "0.331.0", - "resolved": "https://registry.npmjs.org/flow-estree/-/flow-estree-0.331.0.tgz", - "integrity": "sha512-FVLYkSL/ITb/QXBEQvNWPjPooRGswuUtGOwrH+puSlMDneNkxy640+FZsk/TfKL+b7Wbw/Fg9FTUv2bMQDpj2w==", + "node_modules/metro/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "peer": true, - "engines": { - "node": ">=18" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/metro/node_modules/flow-parser": { - "version": "0.331.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.331.0.tgz", - "integrity": "sha512-vEZcHIlnKeN8JSVtYFczj8sWJfHIJOkz+YG00O/oul/Bete+t1ZhTi+O6JRRLFYvGW+yJkZ0YgL16iStnbkUqQ==", + "node_modules/metro/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "flow-estree": "0.331.0" - }, - "engines": { - "node": ">=0.4.0" - } + "peer": true }, - "node_modules/metro/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "node_modules/metro/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "peer": true, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/metro/node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "node_modules/metro/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "mime-db": "^1.54.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/metro/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "node_modules/metro/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "peer": true, "engines": { - "node": ">=0.10.0" + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/metro/node_modules/yargs": { - "version": "17.7.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", - "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "license": "MIT", "peer": true, @@ -7633,7 +10755,6 @@ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -7643,12 +10764,11 @@ } }, "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8.6" }, @@ -7694,16 +10814,16 @@ } }, "node_modules/minimatch": { - "version": "10.2.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", - "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "ISC", "dependencies": { - "brace-expansion": "^5.0.8" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "18 || 20 || >=22" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -7711,117 +10831,29 @@ }, "node_modules/minimist": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minimizer-webpack-plugin": { - "version": "5.13.1", - "resolved": "https://registry.npmjs.org/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.13.1.tgz", - "integrity": "sha512-1mhAfvachWYYOm8tpmany5NLuvP+F2wxZWBSX8DC0uFS2wJpM9q3rWgN9wBooAH9d5V12wX0BjyJe4fMjHMarQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.31", - "jest-worker": "^27.4.5", - "schema-utils": "^4.6.0", - "terser": "^5.51.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@minify-html/node": { - "optional": true - }, - "@napi-rs/image": { - "optional": true - }, - "@swc/core": { - "optional": true - }, - "@swc/css": { - "optional": true - }, - "@swc/html": { - "optional": true - }, - "clean-css": { - "optional": true - }, - "cssnano": { - "optional": true - }, - "csso": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "html-minifier-terser": { - "optional": true - }, - "imagemin": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "postcss": { - "optional": true - }, - "sharp": { - "optional": true - }, - "svgo": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/minimizer-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "ISC", "peer": true, "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", + "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", "dev": true, "license": "MIT", "peer": true, @@ -7878,23 +10910,6 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/mocha/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", - "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/mocha/node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -7962,7 +10977,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -8028,25 +11043,6 @@ "randombytes": "^2.1.0" } }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -8074,37 +11070,21 @@ "license": "MIT" }, "node_modules/negotiator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.1.0.tgz", - "integrity": "sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "content-type": "^2.1.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">= 0.6" } }, - "node_modules/negotiator/node_modules/content-type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", - "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } + "license": "MIT" }, "node_modules/nise": { "version": "1.5.3", @@ -8120,6 +11100,16 @@ "path-to-regexp": "^1.7.0" } }, + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, "node_modules/nise/node_modules/lolex": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", @@ -8130,6 +11120,16 @@ "@sinonjs/commons": "^1.7.0" } }, + "node_modules/nise/node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -8143,13 +11143,13 @@ } }, "node_modules/nock": { - "version": "14.0.17", - "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.17.tgz", - "integrity": "sha512-EjRr1weMa4ALQX35AgZTEnP+weJJjlW1KGDiNM2IQC2069YDHas4f4B4UUYR+TTLyKWxJvOz2wObDKQs/LNreA==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.3.tgz", + "integrity": "sha512-sJ9RNmCuYBqXDmGZZHgZ1D1441MqFOU4T5aeLGVGEB4OWI/2LM0mZlkfBQzQKdOfJypL+2nPPBugXKjixBn4kQ==", "dev": true, "license": "MIT", "dependencies": { - "@mswjs/interceptors": "^0.41.0", + "@mswjs/interceptors": "^0.38.1", "json-stringify-safe": "^5.0.1", "propagate": "^2.0.0" }, @@ -8178,6 +11178,42 @@ } } }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "license": "(BSD-3-Clause OR GPL-2.0)", + "peer": true, + "engines": { + "node": ">= 6.13.0" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -8187,29 +11223,35 @@ "peer": true }, "node_modules/node-releases": { - "version": "2.0.59", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.59.tgz", - "integrity": "sha512-5qr2okC4ItAI0hG5SaV0HoYMpnM/Y6+Oqr7AmPYy/2uEoGvS+GbSKLeRxSS1uAdu59yz0ouzcuXievSgg///WA==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } + "license": "MIT" }, "node_modules/normalize-package-data": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-8.0.0.tgz", - "integrity": "sha512-RWk+PI433eESQ7ounYxIp67CYuVsS1uYSonX3kA6ps/3LWfjVQa/ptEg6Y3T6uAMq1mWpX9PQ+qx+QaHpsc7gQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "license": "BSD-2-Clause", "peer": true, "dependencies": { - "hosted-git-info": "^9.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver" } }, "node_modules/normalize-path": { @@ -8230,10 +11272,17 @@ "license": "MIT", "peer": true }, + "node_modules/nwsapi": { + "version": "2.2.20", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", + "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==", + "dev": true, + "license": "MIT" + }, "node_modules/ob1": { - "version": "0.87.1", - "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.87.1.tgz", - "integrity": "sha512-i8iA8uij0g1YQzS8uOJPSRCgwDjO9warIHUAu1Fqj877Wc3wlfxDYBioYWgKTBF2+URVJttyDWSEpmd99nlvtQ==", + "version": "0.81.4", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.81.4.tgz", + "integrity": "sha512-EZLYM8hfPraC2SYOR5EWLFAPV5e6g+p83m2Jth9bzCpFxP1NDQJYXdmXRB2bfbaWQSmm6NkIQlbzk7uU5lLfgg==", "dev": true, "license": "MIT", "peer": true, @@ -8241,7 +11290,7 @@ "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18.18" } }, "node_modules/object-assign": { @@ -8318,19 +11367,18 @@ } }, "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" }, "engines": { - "node": ">=12" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8393,6 +11441,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true + }, "node_modules/pad-right": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/pad-right/-/pad-right-0.2.2.tgz", @@ -8421,22 +11488,31 @@ } }, "node_modules/parse-json": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", - "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/code-frame": "^7.26.2", - "index-to-position": "^1.1.0", - "type-fest": "^4.39.1" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" }, "engines": { - "node": ">=18" + "node": ">=4" + } + }, + "node_modules/parse5": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^4.5.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, "node_modules/parseurl": { @@ -8459,89 +11535,196 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", - "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "peer": true, "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" + "p-try": "^2.0.0" }, "engines": { - "node": "18 || 20 || >=22" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-to-regexp": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", - "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "license": "MIT", + "p-limit": "^2.0.0" + }, "engines": { - "node": "*" + "node": ">=6" } }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", - "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=4" } }, "node_modules/possible-typed-array-names": { @@ -8565,9 +11748,9 @@ } }, "node_modules/prettier": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.10.tgz", - "integrity": "sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, "license": "MIT", "bin": { @@ -8581,9 +11764,9 @@ } }, "node_modules/prettier-linter-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", - "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "license": "MIT", "dependencies": { @@ -8594,19 +11777,31 @@ } }, "node_modules/pretty-format": { - "version": "30.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.5.1.tgz", - "integrity": "sha512-byhRAPguVKMQIj4kjJwJ5lAskVhfuiSdiYl/aLTWpgkGEmic2jYhJh1yE9ih8Ox44Xg9ccCT11/S6QrzSJuNrg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/react-is-18": "npm:react-is@^18.3.1", - "@jest/react-is-19": "npm:react-is@^19.2.5", - "@jest/schemas": "30.5.0", - "ansi-styles": "^5.2.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/process": { @@ -8677,14 +11872,13 @@ } }, "node_modules/qs": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.1.tgz", - "integrity": "sha512-5Px6J7rfHBAGUhNQ3es4YzcOdBBw0SDcVtThJml4RdnKw4tKs2epA0kPZ+K8X+WiHktT93RHVcQ/3ym5aTCgtg==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "es-define-property": "^1.0.1", - "side-channel": "^1.1.1" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -8693,6 +11887,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "inherits": "~2.0.3" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -8732,39 +11937,35 @@ } }, "node_modules/range-parser": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.3.0.tgz", - "integrity": "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" } }, "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { "node": ">= 0.8" } }, "node_modules/react": { - "version": "19.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-19.3.1.tgz", - "integrity": "sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "dev": true, "license": "MIT", "peer": true, @@ -8773,9 +11974,9 @@ } }, "node_modules/react-devtools-core": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.5.tgz", - "integrity": "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.1.tgz", + "integrity": "sha512-TFo1MEnkqE6hzAbaztnyR5uLTMoz6wnEWwWBsCUzNt+sVXJycuRJdDqvL078M4/h65BI/YO5XWTaxZDWVsW0fw==", "dev": true, "license": "MIT", "peer": true, @@ -8784,61 +11985,90 @@ "ws": "^7" } }, + "node_modules/react-devtools-core/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/react-native": { - "version": "0.88.0", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.88.0.tgz", - "integrity": "sha512-v/wee0nYWcammMYBnSat/e3WY/5iaf9YQOMcBrfKT/wPApPPlHp94hgZovBtwhMuthR01yc/8cGn0FpFTE/C4A==", + "version": "0.78.1", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.78.1.tgz", + "integrity": "sha512-3CK/xxX02GeeVFyrXbsHvREZFVaXwHW43Km/EdYITn5G32cccWTGaqY9QdPddEBLw5O3BPip3LHbR1SywE0cpA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@react-native/asset-utils": "0.88.0", - "@react-native/codegen": "0.88.0", - "@react-native/community-cli-plugin": "0.88.0", - "@react-native/gradle-plugin": "0.88.0", - "@react-native/normalize-colors": "0.88.0", - "@react-native/virtualized-lists": "0.88.0", + "@jest/create-cache-key-function": "^29.6.3", + "@react-native/assets-registry": "0.78.1", + "@react-native/codegen": "0.78.1", + "@react-native/community-cli-plugin": "0.78.1", + "@react-native/gradle-plugin": "0.78.1", + "@react-native/js-polyfills": "0.78.1", + "@react-native/normalize-colors": "0.78.1", + "@react-native/virtualized-lists": "0.78.1", + "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", + "babel-jest": "^29.7.0", + "babel-plugin-syntax-hermes-parser": "0.25.1", "base64-js": "^1.5.1", + "chalk": "^4.0.0", + "commander": "^12.0.0", + "event-target-shim": "^5.0.1", "flow-enums-runtime": "^0.0.6", - "flow-parser": "0.327.0", - "hermes-compiler": "260318099.0.4", + "glob": "^7.1.1", "invariant": "^2.2.4", + "jest-environment-node": "^29.6.3", "memoize-one": "^5.0.0", - "metro-runtime": "^0.87.1", - "metro-source-map": "^0.87.1", + "metro-runtime": "^0.81.0", + "metro-source-map": "^0.81.0", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", - "react-devtools-core": "^6.1.5", + "react-devtools-core": "^6.0.1", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", - "scheduler": "0.28.0", + "scheduler": "0.25.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", - "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", - "ws": "^7.5.10", + "ws": "^6.2.3", "yargs": "^17.6.2" }, "bin": { "react-native": "cli.js" }, "engines": { - "node": "^22.13.0 || ^24.3.0 || >= 26.0.0" + "node": ">=18" }, "peerDependencies": { - "@types/react": "^19.1.1", - "react": "^19.3.0" + "@types/react": "^19.0.0", + "react": "^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -8859,28 +12089,6 @@ "react-native": "*" } }, - "node_modules/react-native/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/react-native/node_modules/@sinclair/typebox": { - "version": "0.27.12", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz", - "integrity": "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/react-native/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -8892,6 +12100,18 @@ "node": ">=8" } }, + "node_modules/react-native/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/react-native/node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -8908,26 +12128,77 @@ "node": ">=12" } }, - "node_modules/react-native/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "node_modules/react-native/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/react-native/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/react-native/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/react-native/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "async-limiter": "~1.0.0" } }, "node_modules/react-native/node_modules/yargs": { - "version": "17.7.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", - "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "license": "MIT", "peer": true, @@ -8941,103 +12212,167 @@ "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=12" + "node": ">=12" + } + }, + "node_modules/react-native/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/react-native/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "ISC", + "license": "MIT", "peer": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", "peer": true, + "dependencies": { + "p-locate": "^4.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/read-package-up": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-12.0.0.tgz", - "integrity": "sha512-Q5hMVBYur/eQNWDdbF4/Wqqr9Bjvtrw2kjGxxBbKLbx8bVCL8gcArjTy8zDUuLGQicftpMuU0riQNcAsbtOVsw==", + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "find-up-simple": "^1.0.1", - "read-pkg": "^10.0.0", - "type-fest": "^5.2.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">=20" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-package-up/node_modules/type-fest": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.10.0.tgz", - "integrity": "sha512-NoSdpq/WEiAg5sjmBkmV/hfxv6HJH4NqPNrqjtSO5CwRmpsDfaf4begxW34KdJykH/l1yHtwBWQkCRdoXO8mPA==", + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", "peer": true, "dependencies": { - "tagged-tag": "^1.0.0" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/read-pkg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-10.1.0.tgz", - "integrity": "sha512-I8g2lArQiP78ll51UeMZojewtYgIRCKCWqZEgOO8c/uefTI+XDXvCSXu3+YNUaTNvZzobrL5+SqHjBrByRRTdg==", + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@types/normalize-package-data": "^2.4.4", - "normalize-package-data": "^8.0.0", - "parse-json": "^8.3.0", - "type-fest": "^5.4.4", - "unicorn-magic": "^0.4.0" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { - "node": ">=20" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/read-pkg/node_modules/type-fest": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.10.0.tgz", - "integrity": "sha512-NoSdpq/WEiAg5sjmBkmV/hfxv6HJH4NqPNrqjtSO5CwRmpsDfaf4begxW34KdJykH/l1yHtwBWQkCRdoXO8mPA==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, "license": "(MIT OR CC0-1.0)", "peer": true, - "dependencies": { - "tagged-tag": "^1.0.0" - }, "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/readdirp": { @@ -9054,9 +12389,9 @@ } }, "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { @@ -9066,14 +12401,77 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==", + "dev": true, + "license": "BSD", + "peer": true + }, + "node_modules/recast": { + "version": "0.23.11", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", + "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/recast/node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", + "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==", + "deprecated": "This version has a critical bug in fallback handling. Please upgrade to reflect-metadata@0.2.2 or newer.", "dev": true, "license": "Apache-2.0", "peer": true }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", @@ -9082,6 +12480,17 @@ "license": "MIT", "peer": true }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, "node_modules/regexp-match-indices": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regexp-match-indices/-/regexp-match-indices-1.0.2.tgz", @@ -9125,6 +12534,61 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexpu-core": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.12.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/regjsparser": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "jsesc": "~3.0.2" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -9164,14 +12628,13 @@ "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.13", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.13.tgz", - "integrity": "sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "is-core-module": "^2.17.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -9195,6 +12658,41 @@ "node": ">=4" } }, + "node_modules/resolve-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-2.0.0.tgz", + "integrity": "sha512-+1lzwXehGCXSeryaISr6WujZzowloigEofRB+dj75y9RRa/obVcYgbHJd53tdYw8pvZj8GojXaaENws8Ktw/hQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve-pkg/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -9230,17 +12728,10 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { @@ -9252,7 +12743,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -9271,9 +12762,9 @@ } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -9366,6 +12857,13 @@ "dev": true, "license": "MIT" }, + "node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true, + "license": "MIT" + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -9436,49 +12934,51 @@ "dev": true, "license": "MIT" }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/scheduler": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz", - "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", + "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", "dev": true, "license": "MIT", "peer": true }, "node_modules/schema-utils": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.8.1.tgz", - "integrity": "sha512-x39pYlJPyH7Uge5QO64B9XGP9zLDc9WNmiQZc+CE3IzZPvMu3lHOuAMGpYNoPixEL7MSWlGhYTg5UlLSL8G6iw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.15", - "ajv": "^8.20.0", - "ajv-formats": "^3.0.1", + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" }, - "bin": { - "schema-utils": "bin/schema-utils.js" - }, "engines": { "node": ">= 10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.112.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } } }, "node_modules/schema-utils/node_modules/ajv": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", - "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", "dependencies": { @@ -9520,12 +13020,30 @@ "license": "MIT", "peer": true }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", "dev": true, "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { "semver": "bin/semver.js" }, @@ -9533,10 +13051,30 @@ "node": ">=10" } }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/send": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "license": "MIT", "peer": true, @@ -9544,16 +13082,16 @@ "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", - "encodeurl": "~2.0.0", + "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "~2.4.1", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~2.0.2" + "statuses": "2.0.1" }, "engines": { "node": ">= 0.8.0" @@ -9578,17 +13116,6 @@ "license": "MIT", "peer": true }, - "node_modules/send/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/send/node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -9603,21 +13130,10 @@ "node": ">=4" } }, - "node_modules/send/node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/send/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "license": "MIT", "peer": true, @@ -9647,9 +13163,9 @@ } }, "node_modules/serve-static": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "license": "MIT", "peer": true, @@ -9657,7 +13173,7 @@ "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "~0.19.1" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -9715,6 +13231,20 @@ "dev": true, "license": "ISC" }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -9739,9 +13269,9 @@ } }, "node_modules/shell-quote": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.12.0.tgz", - "integrity": "sha512-PcByqNyT/38F2kDNi006HAMRJaULuBzq/FOsw3qdZvX/GA9W/jamDaRskgHjubHiftXK5sIFxLNkvrXUwcof6Q==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", + "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", "dev": true, "license": "MIT", "peer": true, @@ -9753,15 +13283,15 @@ } }, "node_modules/side-channel": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", - "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.4", - "side-channel-list": "^1.0.1", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" }, @@ -9773,14 +13303,14 @@ } }, "node_modules/side-channel-list": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", - "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.4" + "object-inspect": "^1.13.3" }, "engines": { "node": ">= 0.4" @@ -9822,10 +13352,24 @@ "side-channel-map": "^1.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/sinon": { @@ -9856,10 +13400,20 @@ "sinon": ">=4.0.0" } }, + "node_modules/sinon/node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, "node_modules/sinon/node_modules/diff": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.1.tgz", - "integrity": "sha512-Z3u54A8qGyqFOSr2pk0ijYs8mOE9Qz8kTvtKeBI+upoG9j04Sq+oI7W8zAJiQybDcESET8/uIdHzs0p3k4fZlw==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -9889,6 +13443,16 @@ "node": ">=4" } }, + "node_modules/sinon/node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -9900,25 +13464,23 @@ } }, "node_modules/smob": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/smob/-/smob-1.6.2.tgz", - "integrity": "sha512-RQsvleCbF8cVHEv+xuDGaA4pOizFqJ0GgjtMSRo6oP8pnN7WsigHgVGey6aILRBKv4W2YOMHLqbKdnB6hpB9fw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", + "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.0.0" - } + "license": "MIT" }, "node_modules/socket.io": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.4.tgz", - "integrity": "sha512-9ZV9zg8vN8hO3Y25DhR7nUkJ1VDnBhq5O/JrXhFT9s6+F0gqytSASTHVfCFc2mJXaTfARroErplXlzFWwETZqQ==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", "dev": true, "license": "MIT", "dependencies": { "accepts": "~1.3.4", + "base64id": "~2.0.0", "cors": "~2.8.5", - "debug": "~4.4.1", + "debug": "~4.3.2", "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" @@ -9928,20 +13490,38 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.8.tgz", - "integrity": "sha512-6Oy52pbg+kvdCVvjcN+FnY7BvxZ7cIHNScbvztT/It5d0vbwoJoVZmF2gjJmnV0/4WlXRfG15zc45ySk9Ah8bw==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", "dev": true, "license": "MIT", "dependencies": { - "debug": "~4.4.1", - "ws": "~8.21.0" + "debug": "~4.3.4", + "ws": "~8.17.1" + } + }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/socket.io-adapter/node_modules/ws": { - "version": "8.21.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", - "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "license": "MIT", "engines": { @@ -9961,41 +13541,53 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.7", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.7.tgz", - "integrity": "sha512-IH/iSeO9T6gz1KkFleGDWkG9N3dl4jXVYUtMhIqH10Md0ttMer8nUNWiP1DKuNrybD2xBrixLJdCC9J6ECoYkg==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dev": true, "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.4.1" + "debug": "~4.3.1" }, "engines": { "node": ">=10.0.0" } }, - "node_modules/socket.io/node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "ms": "^2.1.3" }, "engines": { - "node": ">= 0.6" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/socket.io/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": ">= 0.6" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/source-map": { @@ -10052,9 +13644,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.24", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.24.tgz", - "integrity": "sha512-cLS9TtWkIQFyLkJ3/5aFQAOHOSKTlOs/7WDut/XPSdjom1fJhUdkepeJAKXa9Y05+FabHd0sti+Et559vDtkpQ==", + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", "dev": true, "license": "CC0-1.0", "peer": true @@ -10180,6 +13772,23 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -10193,6 +13802,32 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -10256,60 +13891,49 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, "node_modules/synckit": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.12.3.tgz", - "integrity": "sha512-U+/AXT6LWsxnj2vz9HeUuPWBNgdWxjyIEjEPdbJARC9txmgPzo2VEdqnFo4hHaNyMPtycyVJrSaQYeQv/PoyyA==", + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.10.3.tgz", + "integrity": "sha512-R1urvuyiTaWfeCggqEvpDJwAlDVdsT9NM+IP//Tk2x7qHCkSvBk/fwFgw/TLAHzZlrAnnazMcRw0ZD8HlYFTEQ==", "dev": true, "license": "MIT", "dependencies": { - "@dual-bundle/import-meta-resolve": "^4.2.1", - "@pkgr/core": "^0.3.6" + "@pkgr/core": "^0.2.0", + "tslib": "^2.8.1" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/synckit" - } - }, - "node_modules/tagged-tag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", - "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/unts" } }, "node_modules/tapable": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", - "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" } }, "node_modules/terser": { - "version": "5.51.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.51.2.tgz", - "integrity": "sha512-bWnjSNscmuI+GJze6ZupnHP8G/cTcsJF+bXCeQknk2SHQsgbNJnLrqiH9jZ2W4STPVXH2mDKKRX3iwPhc9Cn/Q==", + "version": "5.39.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", + "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -10320,6 +13944,56 @@ "node": ">=10" } }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", + "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -10327,6 +14001,71 @@ "dev": true, "license": "MIT" }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -10375,33 +14114,52 @@ "license": "MIT", "peer": true }, - "node_modules/tinyglobby": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", - "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" + "tldts-core": "^6.1.86" }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "bin": { + "tldts": "bin/cli.js" } }, + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "dev": true, + "license": "MIT" + }, "node_modules/tmp": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", - "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, "license": "MIT", "engines": { "node": ">=14.14" } }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -10433,17 +14191,46 @@ "license": "MIT", "peer": true }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz", + "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tr46/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=6" + } }, "node_modules/ts-api-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", - "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "license": "MIT", "engines": { @@ -10453,50 +14240,35 @@ "typescript": ">=4.8.4" } }, - "node_modules/ts-dedent": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.3.0.tgz", - "integrity": "sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.10" - } - }, "node_modules/ts-loader": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.6.2.tgz", - "integrity": "sha512-R4iuczmtgxvtuI556s+hTZ6/7Ee03VCAk/l/M8LY1OAsUgB7YydsCxkgq9D9pKRaD7GJqUi2u8fp9zZP/ufjKA==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.2.tgz", + "integrity": "sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.0", - "picomatch": "^4.0.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", "source-map": "^0.7.4" }, "engines": { "node": ">=12.0.0" }, "peerDependencies": { - "loader-utils": "*", "typescript": "*", - "webpack": "^4.0.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "loader-utils": { - "optional": true - } + "webpack": "^5.0.0" } }, "node_modules/ts-loader/node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, "license": "BSD-3-Clause", "engines": { - "node": ">= 12" + "node": ">= 8" } }, "node_modules/ts-mocha": { @@ -10522,9 +14294,9 @@ } }, "node_modules/ts-mocha/node_modules/diff": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.1.tgz", - "integrity": "sha512-Z3u54A8qGyqFOSr2pk0ijYs8mOE9Qz8kTvtKeBI+upoG9j04Sq+oI7W8zAJiQybDcESET8/uIdHzs0p3k4fZlw==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -10654,17 +14426,17 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/tsx": { - "version": "4.23.15", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.15.tgz", - "integrity": "sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==", + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", + "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "~0.28.0" + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" }, "bin": { "tsx": "dist/cli.mjs" @@ -10700,9 +14472,9 @@ } }, "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.38.0.tgz", + "integrity": "sha512-2dBz5D5ycHIoliLYLi0Q2V7KRaDlH0uWIvmk7TYlAg5slqwiPv1ezJdZm1QEM0xgk29oYWMCbIG7E6gHpvChlg==", "dev": true, "license": "(MIT OR CC0-1.0)", "peer": true, @@ -10728,9 +14500,9 @@ } }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -10742,9 +14514,9 @@ } }, "node_modules/ua-parser-js": { - "version": "0.7.41", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.41.tgz", - "integrity": "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==", + "version": "0.7.40", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.40.tgz", + "integrity": "sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ==", "dev": true, "funding": [ { @@ -10769,40 +14541,74 @@ } }, "node_modules/underscore": { - "version": "1.13.8", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", - "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", "dev": true, "license": "MIT" }, "node_modules/undici": { - "version": "7.30.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.30.1.tgz", - "integrity": "sha512-03KrMbjIFDWQR5RNPrSw3bd1r12JpyFQl9/yxjUbJtqkjmllqC5lFjZh6ujeuJCKr8EOQvRW872Oy/az+nLYxg==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.1.tgz", + "integrity": "sha512-RYONW2MeafgYlkVOKYKkA/Ag7BmXqgIWCa8t1m0JcxrQg9pI9lEqRhAOruOBCbAohOa/gkCF+iPi9hrgvTzu6Q==", "license": "MIT", "engines": { "node": ">=20.18.1" } }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "dev": true, "license": "MIT" }, - "node_modules/unicorn-magic": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.1.tgz", - "integrity": "sha512-lzlXPoVB0Uy/FvTaUgX39RbixYiSKoc3JSoSf01+0c2B6FR3qdYIPN7Qjo/AV7n6sqLCk0509cT3LRj1oSZ1+A==", + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "dev": true, "license": "MIT", "peer": true, "engines": { - "node": ">=20" + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" } }, "node_modules/universalify": { @@ -10826,9 +14632,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.4.tgz", - "integrity": "sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { @@ -10919,6 +14725,21 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -10966,13 +14787,38 @@ "node": ">=0.10.0" } }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/watchpack": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.6.3.tgz", - "integrity": "sha512-s3NZy0QpTY9qGqzc0wtz4qI28z3+5qKbbAec4MV4G9N3CfgZ9wgvQRr0cl2jh/tqkWG1NWHkmVMHZpCamev5Wg==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", "dev": true, "license": "MIT", "dependencies": { + "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" }, "engines": { @@ -10980,36 +14826,47 @@ } }, "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", "dev": true, - "license": "BSD-2-Clause" + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } }, "node_modules/webpack": { - "version": "5.112.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.112.0.tgz", - "integrity": "sha512-NIBpsRuCll036haDDt/CfcTDfsWNR9Z782nMRMI9D377BsGcYzZDTNU5TyzhCJzPIcihAxMBaMAhq2WSaDrH8Q==", + "version": "5.100.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.100.0.tgz", + "integrity": "sha512-H8yBSBTk+BqxrINJnnRzaxU94SVP2bjd7WmA+PfCphoIdDpeQMJ77pq9/4I7xjLq38cB1bNKfzYPZu8pB3zKtg==", "dev": true, "license": "MIT", "dependencies": { + "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "browserslist": "^4.28.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.26.0", - "es-module-lexer": "^2.1.0", + "enhanced-resolve": "^5.17.2", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "mime-db": "^1.54.0", - "minimizer-webpack-plugin": "^5.13.0", - "schema-utils": "^4.5.0", - "tapable": "^2.3.0", - "watchpack": "^2.6.1", - "webpack-sources": "^3.6.0" + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.2", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.11", + "watchpack": "^2.4.1", + "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" @@ -11038,23 +14895,63 @@ } }, "node_modules/webpack-sources": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.6.0.tgz", - "integrity": "sha512-EIMmPVvNI0CYXyRPp34F2Qk7W37/BZVZIofS6LAUnrNjCVahS+hO4mxwFJDjQjODTGZDtVzLYoN2+1dYkhk9qA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, "engines": { - "node": ">= 0.6" + "node": ">=18" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, "node_modules/whatwg-fetch": { @@ -11065,15 +14962,28 @@ "license": "MIT", "peer": true }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", "dev": true, "license": "MIT", "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" } }, "node_modules/whatwg-url-without-unicode": { @@ -11153,14 +15063,14 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.24", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.24.tgz", - "integrity": "sha512-wk4Mf4pR5mRP7eYuuTBCIQ9d0ud2Fv2jRLQpfgnRjbOxAFHmjKFValgTpitVKzJJS8ajnYQV2Du1SZ8j6b/EUQ==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.9", + "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", @@ -11175,9 +15085,9 @@ } }, "node_modules/why-is-node-running": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-3.2.3.tgz", - "integrity": "sha512-b+aWTM7Zz5Q82TurMbr034vAmyJo2pJFVXzUzuhJK8lP+XI6xUfvzXizZINaERhH3KwybDLt6iqh7pOXaVxjnQ==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-3.2.2.tgz", + "integrity": "sha512-NKUzAelcoCXhXL4dJzKIwXeR8iEVqsA0Lq6Vnd0UXvgaKbzVo4ZTHROF2Jidrv+SgxOQ03fMinnNhzZATxOD3A==", "dev": true, "license": "MIT", "bin": { @@ -11205,11 +15115,32 @@ "license": "Apache-2.0" }, "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -11222,20 +15153,76 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "color-convert": "^2.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/wrappy": { @@ -11245,19 +15232,41 @@ "dev": true, "license": "ISC" }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC", + "peer": true + }, "node_modules/ws": { - "version": "7.5.13", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.13.tgz", - "integrity": "sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -11269,9 +15278,9 @@ } }, "node_modules/wtfnode": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/wtfnode/-/wtfnode-0.10.1.tgz", - "integrity": "sha512-4mcHdlvcdSytsbFueN6QYZxmh5K7REawBk//ZOrJrtVOe548Qsq4GNEm/OUfZATqDnsX4g8uBbzmN7NdEZx09Q==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/wtfnode/-/wtfnode-0.10.0.tgz", + "integrity": "sha512-/GxfQORu0SZZC8AQA4Eq1wH08Akz6W42OiqNGBzTHXCJWZFhKFBJNaUfEomWnLA2MXfpy6KbFerG8iNtFcPRdg==", "dev": true, "license": "ISC", "bin": { @@ -11281,6 +15290,16 @@ "node": ">=0.10.0" } }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", @@ -11292,6 +15311,13 @@ "node": ">=8.0" } }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -11311,9 +15337,9 @@ "peer": true }, "node_modules/yaml": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", - "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", + "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", "dev": true, "license": "ISC", "peer": true, @@ -11321,16 +15347,13 @@ "yaml": "bin.mjs" }, "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" + "node": ">= 14" } }, "node_modules/yargs": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.2.tgz", - "integrity": "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "license": "MIT", "dependencies": { @@ -11372,6 +15395,19 @@ "node": ">=10" } }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -11396,9 +15432,9 @@ } }, "node_modules/yup": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/yup/-/yup-1.7.1.tgz", - "integrity": "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.2.0.tgz", + "integrity": "sha512-PPqYKSAXjpRCgLgLKVGPA33v5c/WgEx3wi6NFjIiegz90zSwyMpvTFp/uGcVnnbx6to28pgnzp/q8ih3QRjLMQ==", "dev": true, "license": "MIT", "peer": true, From 88efa5d3ef11f1201a4fe5e63b7966603809f708 Mon Sep 17 00:00:00 2001 From: "mohit.tejani" Date: Mon, 19 Oct 2026 11:59:35 +0530 Subject: [PATCH 5/9] package-lock update --- package-lock.json | 40 +++++++++++----------------------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/package-lock.json b/package-lock.json index 586df7069..a1d44bb9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "cbor-js": "^0.1.0", "cbor-sync": "^1.0.4", "fast-text-encoding": "^1.0.6", - "fflate": "^0.8.2", + "fflate": "^0.8.3", "lil-uuid": "^0.1.1", "undici": "^7.29.0" }, @@ -6917,9 +6917,9 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -7917,9 +7917,9 @@ } }, "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", "license": "MIT" }, "node_modules/figures": { @@ -13541,37 +13541,19 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.7.tgz", + "integrity": "sha512-IH/iSeO9T6gz1KkFleGDWkG9N3dl4jXVYUtMhIqH10Md0ttMer8nUNWiP1DKuNrybD2xBrixLJdCC9J6ECoYkg==", "dev": true, "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" + "debug": "~4.4.1" }, "engines": { "node": ">=10.0.0" } }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/socket.io/node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", From d08d0745fda2f5e66c5ebcd789128cdd92f69a3a Mon Sep 17 00:00:00 2001 From: "mohit.tejani" Date: Tue, 20 Oct 2026 11:09:26 +0530 Subject: [PATCH 6/9] upgrade undici version 7.30.1 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index a1d44bb9e..f393329b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "fast-text-encoding": "^1.0.6", "fflate": "^0.8.3", "lil-uuid": "^0.1.1", - "undici": "^7.29.0" + "undici": "^7.30.1" }, "devDependencies": { "@rollup/plugin-commonjs": "^25.0.7", @@ -14530,9 +14530,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.1.tgz", - "integrity": "sha512-RYONW2MeafgYlkVOKYKkA/Ag7BmXqgIWCa8t1m0JcxrQg9pI9lEqRhAOruOBCbAohOa/gkCF+iPi9hrgvTzu6Q==", + "version": "7.30.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.30.1.tgz", + "integrity": "sha512-03KrMbjIFDWQR5RNPrSw3bd1r12JpyFQl9/yxjUbJtqkjmllqC5lFjZh6ujeuJCKr8EOQvRW872Oy/az+nLYxg==", "license": "MIT", "engines": { "node": ">=20.18.1" diff --git a/package.json b/package.json index 69de711b1..dcb03ce7a 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "fast-text-encoding": "^1.0.6", "fflate": "^0.8.3", "lil-uuid": "^0.1.1", - "undici": "^7.29.0" + "undici": "^7.30.1" }, "peerDependencies": { "react-native-url-polyfill": "^2.0.0" From ef89d91f74f23bd8fcb4c05dfc0caf9e6a395044 Mon Sep 17 00:00:00 2001 From: "mohit.tejani" Date: Tue, 20 Oct 2026 11:50:36 +0530 Subject: [PATCH 7/9] refactor: dataSync event type definition and parsing for delete relationship and membership events --- dist/web/pubnub.js | 42706 ++++++++-------- lib/core/endpoints/subscribe.js | 26 +- lib/types/index.d.ts | 46 +- src/core/endpoints/subscribe.ts | 70 +- src/core/types/api/subscription.ts | 2 + .../data_sync/events.membership.test.ts | 4 +- .../data_sync/events.relationship.test.ts | 8 +- .../endpoints/data_sync/helpers.ts | 37 +- .../data_sync/subscribe-event-parsing.test.ts | 72 +- 9 files changed, 21603 insertions(+), 21368 deletions(-) diff --git a/dist/web/pubnub.js b/dist/web/pubnub.js index c9d2b803a..41a71dd0e 100644 --- a/dist/web/pubnub.js +++ b/dist/web/pubnub.js @@ -1,17 +1,17 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.PubNub = factory()); -})(this, (function () { 'use strict'; - - var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - function getDefaultExportFromCjs (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; - } - - var cbor = {exports: {}}; - +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.PubNub = factory()); +})(this, (function () { 'use strict'; + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + } + + var cbor = {exports: {}}; + /* * The MIT License (MIT) * @@ -34,9 +34,9 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. - */ - - (function (module) { + */ + + (function (module) { (function(global, undefined$1) { var POW_2_24 = Math.pow(2, -24), POW_2_32 = Math.pow(2, 32), POW_2_53 = Math.pow(2, 53); @@ -415,12 +415,12 @@ else if (!global.CBOR) global.CBOR = obj; - })(commonjsGlobal); - } (cbor)); - - var cborExports = cbor.exports; - var CborReader = /*@__PURE__*/getDefaultExportFromCjs(cborExports); - + })(commonjsGlobal); + } (cbor)); + + var cborExports = cbor.exports; + var CborReader = /*@__PURE__*/getDefaultExportFromCjs(cborExports); + /****************************************************************************** Copyright (c) Microsoft Corporation. @@ -463,21321 +463,21345 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; - }; - - /** - * Crypto module. - */ - class AbstractCryptoModule { - // -------------------------------------------------------- - // --------------- Convenience functions ------------------ - // -------------------------------------------------------- - // region Convenience functions - /** - * Construct crypto module with legacy cryptor for encryption and both legacy and AES-CBC - * cryptors for decryption. - * - * @param config Cryptors configuration options. - * - * @returns Crypto module which encrypts data using legacy cryptor. - * - * @throws Error if `config.cipherKey` not set. - * - * @deprecated Use {@link aesCbcCryptoModule} for new applications. - */ - static legacyCryptoModule(config) { - throw new Error('Should be implemented by concrete crypto module implementation.'); - } - /** - * Construct crypto module with AES-CBC cryptor for encryption and both AES-CBC and legacy - * cryptors for decryption. - * - * @param config Cryptors configuration options. - * - * @returns Crypto module which encrypts data using AES-CBC cryptor. - * - * @throws Error if `config.cipherKey` not set. - */ - static aesCbcCryptoModule(config) { - throw new Error('Should be implemented by concrete crypto module implementation.'); - } - // endregion - constructor(configuration) { - var _a; - this.defaultCryptor = configuration.default; - this.cryptors = (_a = configuration.cryptors) !== null && _a !== void 0 ? _a : []; - } - /** - * Assign registered loggers' manager. - * - * @param _logger - Registered loggers' manager. - * - * @internal - */ - set logger(_logger) { - throw new Error('Method not implemented.'); - } - // endregion - // -------------------------------------------------------- - // ----------------------- Helpers ------------------------ - // -------------------------------------------------------- - // region Helpers - /** - * Retrieve list of module's cryptors. - * - * @internal - */ - getAllCryptors() { - return [this.defaultCryptor, ...this.cryptors]; - } - // endregion - /** - * Serialize crypto module information to string. - * - * @returns Serialized crypto module information. - */ - toString() { - return `AbstractCryptoModule { default: ${this.defaultCryptor.toString()}, cryptors: [${this.cryptors.map((c) => c.toString()).join(', ')}]}`; - } - } - /** - * `String` to {@link ArrayBuffer} response decoder. - * - * @internal - */ - AbstractCryptoModule.encoder = new TextEncoder(); - /** - * {@link ArrayBuffer} to {@link string} decoder. - * - * @internal - */ - AbstractCryptoModule.decoder = new TextDecoder(); - - /* global File, FileReader */ - /** - * Browser {@link PubNub} File object module. - */ - // endregion - /** - * Web implementation for {@link PubNub} File object. - * - * **Important:** Class should implement constructor and class fields from {@link PubNubFileConstructor}. - */ - class PubNubFile { - // endregion - static create(file) { - return new PubNubFile(file); - } - constructor(file) { - let contentLength; - let fileMimeType; - let fileName; - let fileData; - if (file instanceof File) { - fileData = file; - fileName = file.name; - fileMimeType = file.type; - contentLength = file.size; - } - else if ('data' in file) { - const contents = file.data; - fileMimeType = file.mimeType; - fileName = file.name; - fileData = new File([contents], fileName, { type: fileMimeType }); - contentLength = fileData.size; - } - if (fileData === undefined) - throw new Error("Couldn't construct a file out of supplied options."); - if (fileName === undefined) - throw new Error("Couldn't guess filename out of the options. Please provide one."); - if (contentLength) - this.contentLength = contentLength; - this.mimeType = fileMimeType; - this.data = fileData; - this.name = fileName; - } - /** - * Convert {@link PubNub} File object content to {@link Buffer}. - * - * @throws Error because {@link Buffer} not available in browser environment. - */ - toBuffer() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('This feature is only supported in Node.js environments.'); - }); - } - /** - * Convert {@link PubNub} File object content to {@link ArrayBuffer}. - * - * @returns Asynchronous results of conversion to the {@link ArrayBuffer}. - */ - toArrayBuffer() { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.addEventListener('load', () => { - if (reader.result instanceof ArrayBuffer) - return resolve(reader.result); - }); - reader.addEventListener('error', () => reject(reader.error)); - reader.readAsArrayBuffer(this.data); - }); - }); - } - /** - * Convert {@link PubNub} File object content to {@link string}. - * - * @returns Asynchronous results of conversion to the {@link string}. - */ - toString() { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.addEventListener('load', () => { - if (typeof reader.result === 'string') { - return resolve(reader.result); - } - }); - reader.addEventListener('error', () => { - reject(reader.error); - }); - reader.readAsBinaryString(this.data); - }); - }); - } - /** - * Convert {@link PubNub} File object content to {@link Readable} stream. - * - * @throws Error because {@link Readable} stream not available in browser environment. - */ - toStream() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('This feature is only supported in Node.js environments.'); - }); - } - /** - * Convert {@link PubNub} File object content to {@link File}. - * - * @returns Asynchronous results of conversion to the {@link File}. - */ - toFile() { - return __awaiter(this, void 0, void 0, function* () { - return this.data; - }); - } - /** - * Convert {@link PubNub} File object content to file `Uri`. - * - * @throws Error because file `Uri` not available in browser environment. - */ - toFileUri() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('This feature is only supported in React Native environments.'); - }); - } - /** - * Convert {@link PubNub} File object content to {@link Blob}. - * - * @returns Asynchronous results of conversion to the {@link Blob}. - */ - toBlob() { - return __awaiter(this, void 0, void 0, function* () { - return this.data; - }); - } - } - // region Class properties - /** - * Whether {@link Blob} data supported by platform or not. - */ - PubNubFile.supportsBlob = typeof Blob !== 'undefined'; - /** - * Whether {@link File} data supported by platform or not. - */ - PubNubFile.supportsFile = typeof File !== 'undefined'; - /** - * Whether {@link Buffer} data supported by platform or not. - */ - PubNubFile.supportsBuffer = false; - /** - * Whether {@link Stream} data supported by platform or not. - */ - PubNubFile.supportsStream = false; - /** - * Whether {@link String} data supported by platform or not. - */ - PubNubFile.supportsString = true; - /** - * Whether {@link ArrayBuffer} supported by platform or not. - */ - PubNubFile.supportsArrayBuffer = true; - /** - * Whether {@link PubNub} File object encryption supported or not. - */ - PubNubFile.supportsEncryptFile = true; - /** - * Whether `File Uri` data supported by platform or not. - */ - PubNubFile.supportsFileUri = false; - - /** - * Base64 support module. - * - * @internal - */ - const BASE64_CHARMAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - /** - * Decode a Base64 encoded string. - * - * @param paddedInput Base64 string with padding - * @returns ArrayBuffer with decoded data - * - * @internal - */ - function decode(paddedInput) { - // Remove up to last two equal signs. - const input = paddedInput.replace(/==?$/, ''); - const outputLength = Math.floor((input.length / 4) * 3); - // Prepare output buffer. - const data = new ArrayBuffer(outputLength); - const view = new Uint8Array(data); - let cursor = 0; - /** - * Returns the next integer representation of a sixtet of bytes from the input - * @returns sixtet of bytes - */ - function nextSixtet() { - const char = input.charAt(cursor++); - const index = BASE64_CHARMAP.indexOf(char); - if (index === -1) { - throw new Error(`Illegal character at ${cursor}: ${input.charAt(cursor - 1)}`); - } - return index; - } - for (let i = 0; i < outputLength; i += 3) { - // Obtain four sixtets - const sx1 = nextSixtet(); - const sx2 = nextSixtet(); - const sx3 = nextSixtet(); - const sx4 = nextSixtet(); - // Encode them as three octets - const oc1 = ((sx1 & 0b00111111) << 2) | (sx2 >> 4); - const oc2 = ((sx2 & 0b00001111) << 4) | (sx3 >> 2); - const oc3 = ((sx3 & 0b00000011) << 6) | (sx4 >> 0); - view[i] = oc1; - // Skip padding bytes. - if (sx3 != 64) - view[i + 1] = oc2; - if (sx4 != 64) - view[i + 2] = oc3; - } - return data; - } - /** - * Encode `ArrayBuffer` as a Base64 encoded string. - * - * @param input ArrayBuffer with source data. - * @returns Base64 string with padding. - * - * @internal - */ - function encode(input) { - let base64 = ''; - const encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - const bytes = new Uint8Array(input); - const byteLength = bytes.byteLength; - const byteRemainder = byteLength % 3; - const mainLength = byteLength - byteRemainder; - let a, b, c, d; - let chunk; - // Main loop deals with bytes in chunks of 3 - for (let i = 0; i < mainLength; i = i + 3) { - // Combine the three bytes into a single integer - chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; - // Use bitmasks to extract 6-bit segments from the triplet - a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18 - b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12 - c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6 - d = chunk & 63; // 63 = 2^6 - 1 - // Convert the raw binary segments to the appropriate ASCII encoding - base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]; - } - // Deal with the remaining bytes and padding - if (byteRemainder == 1) { - chunk = bytes[mainLength]; - a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2 - // Set the 4 least significant bits to zero - b = (chunk & 3) << 4; // 3 = 2^2 - 1 - base64 += encodings[a] + encodings[b] + '=='; - } - else if (byteRemainder == 2) { - chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]; - a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10 - b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4 - // Set the 2 least significant bits to zero - c = (chunk & 15) << 2; // 15 = 2^4 - 1 - base64 += encodings[a] + encodings[b] + encodings[c] + '='; - } - return base64; - } - - /** - * Request processing status categories. - */ - var StatusCategory; - (function (StatusCategory) { - /** - * Call failed when network was unable to complete the call. - */ - StatusCategory["PNNetworkIssuesCategory"] = "PNNetworkIssuesCategory"; - /** - * Network call timed out. - */ - StatusCategory["PNTimeoutCategory"] = "PNTimeoutCategory"; - /** - * Request has been cancelled. - */ - StatusCategory["PNCancelledCategory"] = "PNCancelledCategory"; - /** - * Server responded with bad response. - */ - StatusCategory["PNBadRequestCategory"] = "PNBadRequestCategory"; - /** - * Server responded with access denied. - */ - StatusCategory["PNAccessDeniedCategory"] = "PNAccessDeniedCategory"; - /** - * Incomplete parameters provided for used endpoint. - */ - StatusCategory["PNValidationErrorCategory"] = "PNValidationErrorCategory"; - /** - * PubNub request acknowledgment status. - * - * Some API endpoints respond with request processing status w/o useful data. - */ - StatusCategory["PNAcknowledgmentCategory"] = "PNAcknowledgmentCategory"; - /** - * PubNub service or intermediate "actor" returned unexpected response. - * - * There can be few sources of unexpected return with success code: - * - proxy server / VPN; - * - Wi-Fi hotspot authorization page. - */ - StatusCategory["PNMalformedResponseCategory"] = "PNMalformedResponseCategory"; - /** - * Server can't process request. - * - * There can be few sources of unexpected return with success code: - * - potentially an ongoing incident; - * - proxy server / VPN. - */ - StatusCategory["PNServerErrorCategory"] = "PNServerErrorCategory"; - /** - * Something strange happened; please check the logs. - */ - StatusCategory["PNUnknownCategory"] = "PNUnknownCategory"; - // -------------------------------------------------------- - // --------------------- Network status ------------------- - // -------------------------------------------------------- - /** - * SDK will announce when the network appears to be connected again. - */ - StatusCategory["PNNetworkUpCategory"] = "PNNetworkUpCategory"; - /** - * SDK will announce when the network appears to down. - */ - StatusCategory["PNNetworkDownCategory"] = "PNNetworkDownCategory"; - // -------------------------------------------------------- - // -------------------- Real-time events ------------------ - // -------------------------------------------------------- - /** - * PubNub client reconnected to the real-time updates stream. - */ - StatusCategory["PNReconnectedCategory"] = "PNReconnectedCategory"; - /** - * PubNub client connected to the real-time updates stream. - */ - StatusCategory["PNConnectedCategory"] = "PNConnectedCategory"; - /** - * Set of active channels and groups has been changed. - */ - StatusCategory["PNSubscriptionChangedCategory"] = "PNSubscriptionChangedCategory"; - /** - * Received real-time updates exceed specified threshold. - * - * After temporary disconnection and catchup, this category means that potentially some - * real-time updates have been pushed into `storage` and need to be requested separately. - */ - StatusCategory["PNRequestMessageCountExceededCategory"] = "PNRequestMessageCountExceededCategory"; - /** - * PubNub client disconnected from the real-time updates streams. - */ - StatusCategory["PNDisconnectedCategory"] = "PNDisconnectedCategory"; - /** - * PubNub client wasn't able to connect to the real-time updates streams. - */ - StatusCategory["PNConnectionErrorCategory"] = "PNConnectionErrorCategory"; - /** - * PubNub client unexpectedly disconnected from the real-time updates streams. - */ - StatusCategory["PNDisconnectedUnexpectedlyCategory"] = "PNDisconnectedUnexpectedlyCategory"; - // -------------------------------------------------------- - // ------------------ Shared worker events ---------------- - // -------------------------------------------------------- - /** - * SDK will announce when newer shared worker will be 'noticed'. - */ - StatusCategory["PNSharedWorkerUpdatedCategory"] = "PNSharedWorkerUpdatedCategory"; - })(StatusCategory || (StatusCategory = {})); - var StatusCategory$1 = StatusCategory; - - /** - * PubNub operation error module. - */ - /** - * PubNub operation error. - * - * When an operation can't be performed or there is an error from the server, this object will be returned. - */ - class PubNubError extends Error { - /** - * Create PubNub operation error. - * - * @param message - Message with details about why operation failed. - * @param [status] - Additional information about performed operation. - * - * @returns Configured and ready to use PubNub operation error. - * - * @internal - */ - constructor(message, status) { - super(message); - this.status = status; - this.name = 'PubNubError'; - this.message = message; - Object.setPrototypeOf(this, new.target.prototype); - } - } - /** - * Create error status object. - * - * @param errorPayload - Additional information which should be attached to the error status object. - * @param category - Occurred error category. - * - * @returns Error status object. - * - * @internal - */ - function createError(errorPayload, category) { - var _a; - (_a = errorPayload.statusCode) !== null && _a !== void 0 ? _a : (errorPayload.statusCode = 0); - return Object.assign(Object.assign({}, errorPayload), { statusCode: errorPayload.statusCode, category, error: true }); - } - /** - * Create operation arguments validation error status object. - * - * @param message - Information about failed validation requirement. - * @param [statusCode] - Operation HTTP status code. - * - * @returns Operation validation error status object. - * - * @internal - */ - function createValidationError(message, statusCode) { - return createError(Object.assign({ message }, ({})), StatusCategory$1.PNValidationErrorCategory); - } - /** - * Create malformed service response error status object. - * - * @param [responseText] - Stringified original service response. - * @param [statusCode] - Operation HTTP status code. - */ - function createMalformedResponseError(responseText, statusCode) { - return createError(Object.assign(Object.assign({ message: 'Unable to deserialize service response' }, (responseText !== undefined ? { responseText } : {})), (statusCode !== undefined ? { statusCode } : {})), StatusCategory$1.PNMalformedResponseCategory); - } - - /** - * CryptoJS implementation. - * - * @internal - */ - - /*eslint-disable */ - - /* - CryptoJS v3.1.2 - code.google.com/p/crypto-js - (c) 2009-2013 by Jeff Mott. All rights reserved. - code.google.com/p/crypto-js/wiki/License - */ - var CryptoJS = - CryptoJS || - (function (h, s) { - var f = {}, - g = (f.lib = {}), - q = function () {}, - m = (g.Base = { - extend: function (a) { - q.prototype = this; - var c = new q(); - a && c.mixIn(a); - c.hasOwnProperty('init') || - (c.init = function () { - c.$super.init.apply(this, arguments); - }); - c.init.prototype = c; - c.$super = this; - return c; - }, - create: function () { - var a = this.extend(); - a.init.apply(a, arguments); - return a; - }, - init: function () {}, - mixIn: function (a) { - for (var c in a) a.hasOwnProperty(c) && (this[c] = a[c]); - a.hasOwnProperty('toString') && (this.toString = a.toString); - }, - clone: function () { - return this.init.prototype.extend(this); - }, - }), - r = (g.WordArray = m.extend({ - init: function (a, c) { - a = this.words = a || []; - this.sigBytes = c != s ? c : 4 * a.length; - }, - toString: function (a) { - return (a || k).stringify(this); - }, - concat: function (a) { - var c = this.words, - d = a.words, - b = this.sigBytes; - a = a.sigBytes; - this.clamp(); - if (b % 4) - for (var e = 0; e < a; e++) - c[(b + e) >>> 2] |= ((d[e >>> 2] >>> (24 - 8 * (e % 4))) & 255) << (24 - 8 * ((b + e) % 4)); - else if (65535 < d.length) for (e = 0; e < a; e += 4) c[(b + e) >>> 2] = d[e >>> 2]; - else c.push.apply(c, d); - this.sigBytes += a; - return this; - }, - clamp: function () { - var a = this.words, - c = this.sigBytes; - a[c >>> 2] &= 4294967295 << (32 - 8 * (c % 4)); - a.length = h.ceil(c / 4); - }, - clone: function () { - var a = m.clone.call(this); - a.words = this.words.slice(0); - return a; - }, - random: function (a) { - for (var c = [], d = 0; d < a; d += 4) c.push((4294967296 * h.random()) | 0); - return new r.init(c, a); - }, - })), - l = (f.enc = {}), - k = (l.Hex = { - stringify: function (a) { - var c = a.words; - a = a.sigBytes; - for (var d = [], b = 0; b < a; b++) { - var e = (c[b >>> 2] >>> (24 - 8 * (b % 4))) & 255; - d.push((e >>> 4).toString(16)); - d.push((e & 15).toString(16)); - } - return d.join(''); - }, - parse: function (a) { - for (var c = a.length, d = [], b = 0; b < c; b += 2) - d[b >>> 3] |= parseInt(a.substr(b, 2), 16) << (24 - 4 * (b % 8)); - return new r.init(d, c / 2); - }, - }), - n = (l.Latin1 = { - stringify: function (a) { - var c = a.words; - a = a.sigBytes; - for (var d = [], b = 0; b < a; b++) d.push(String.fromCharCode((c[b >>> 2] >>> (24 - 8 * (b % 4))) & 255)); - return d.join(''); - }, - parse: function (a) { - for (var c = a.length, d = [], b = 0; b < c; b++) d[b >>> 2] |= (a.charCodeAt(b) & 255) << (24 - 8 * (b % 4)); - return new r.init(d, c); - }, - }), - j = (l.Utf8 = { - stringify: function (a) { - try { - return decodeURIComponent(escape(n.stringify(a))); - } catch (c) { - throw Error('Malformed UTF-8 data'); - } - }, - parse: function (a) { - return n.parse(unescape(encodeURIComponent(a))); - }, - }), - u = (g.BufferedBlockAlgorithm = m.extend({ - reset: function () { - this._data = new r.init(); - this._nDataBytes = 0; - }, - _append: function (a) { - 'string' == typeof a && (a = j.parse(a)); - this._data.concat(a); - this._nDataBytes += a.sigBytes; - }, - _process: function (a) { - var c = this._data, - d = c.words, - b = c.sigBytes, - e = this.blockSize, - f = b / (4 * e), - f = a ? h.ceil(f) : h.max((f | 0) - this._minBufferSize, 0); - a = f * e; - b = h.min(4 * a, b); - if (a) { - for (var g = 0; g < a; g += e) this._doProcessBlock(d, g); - g = d.splice(0, a); - c.sigBytes -= b; - } - return new r.init(g, b); - }, - clone: function () { - var a = m.clone.call(this); - a._data = this._data.clone(); - return a; - }, - _minBufferSize: 0, - })); - g.Hasher = u.extend({ - cfg: m.extend(), - init: function (a) { - this.cfg = this.cfg.extend(a); - this.reset(); - }, - reset: function () { - u.reset.call(this); - this._doReset(); - }, - update: function (a) { - this._append(a); - this._process(); - return this; - }, - finalize: function (a) { - a && this._append(a); - return this._doFinalize(); - }, - blockSize: 16, - _createHelper: function (a) { - return function (c, d) { - return new a.init(d).finalize(c); - }; - }, - _createHmacHelper: function (a) { - return function (c, d) { - return new t.HMAC.init(a, d).finalize(c); - }; - }, - }); - var t = (f.algo = {}); - return f; - })(Math); - - // SHA256 - (function (h) { - for ( - var s = CryptoJS, - f = s.lib, - g = f.WordArray, - q = f.Hasher, - f = s.algo, - m = [], - r = [], - l = function (a) { - return (4294967296 * (a - (a | 0))) | 0; - }, - k = 2, - n = 0; - 64 > n; - - ) { - var j; - a: { - j = k; - for (var u = h.sqrt(j), t = 2; t <= u; t++) - if (!(j % t)) { - j = !1; - break a; - } - j = !0; - } - j && (8 > n && (m[n] = l(h.pow(k, 0.5))), (r[n] = l(h.pow(k, 1 / 3))), n++); - k++; - } - var a = [], - f = (f.SHA256 = q.extend({ - _doReset: function () { - this._hash = new g.init(m.slice(0)); - }, - _doProcessBlock: function (c, d) { - for ( - var b = this._hash.words, - e = b[0], - f = b[1], - g = b[2], - j = b[3], - h = b[4], - m = b[5], - n = b[6], - q = b[7], - p = 0; - 64 > p; - p++ - ) { - if (16 > p) a[p] = c[d + p] | 0; - else { - var k = a[p - 15], - l = a[p - 2]; - a[p] = - (((k << 25) | (k >>> 7)) ^ ((k << 14) | (k >>> 18)) ^ (k >>> 3)) + - a[p - 7] + - (((l << 15) | (l >>> 17)) ^ ((l << 13) | (l >>> 19)) ^ (l >>> 10)) + - a[p - 16]; - } - k = - q + - (((h << 26) | (h >>> 6)) ^ ((h << 21) | (h >>> 11)) ^ ((h << 7) | (h >>> 25))) + - ((h & m) ^ (~h & n)) + - r[p] + - a[p]; - l = - (((e << 30) | (e >>> 2)) ^ ((e << 19) | (e >>> 13)) ^ ((e << 10) | (e >>> 22))) + - ((e & f) ^ (e & g) ^ (f & g)); - q = n; - n = m; - m = h; - h = (j + k) | 0; - j = g; - g = f; - f = e; - e = (k + l) | 0; - } - b[0] = (b[0] + e) | 0; - b[1] = (b[1] + f) | 0; - b[2] = (b[2] + g) | 0; - b[3] = (b[3] + j) | 0; - b[4] = (b[4] + h) | 0; - b[5] = (b[5] + m) | 0; - b[6] = (b[6] + n) | 0; - b[7] = (b[7] + q) | 0; - }, - _doFinalize: function () { - var a = this._data, - d = a.words, - b = 8 * this._nDataBytes, - e = 8 * a.sigBytes; - d[e >>> 5] |= 128 << (24 - (e % 32)); - d[(((e + 64) >>> 9) << 4) + 14] = h.floor(b / 4294967296); - d[(((e + 64) >>> 9) << 4) + 15] = b; - a.sigBytes = 4 * d.length; - this._process(); - return this._hash; - }, - clone: function () { - var a = q.clone.call(this); - a._hash = this._hash.clone(); - return a; - }, - })); - s.SHA256 = q._createHelper(f); - s.HmacSHA256 = q._createHmacHelper(f); - })(Math); - - // HMAC SHA256 - (function () { - var h = CryptoJS, - s = h.enc.Utf8; - h.algo.HMAC = h.lib.Base.extend({ - init: function (f, g) { - f = this._hasher = new f.init(); - 'string' == typeof g && (g = s.parse(g)); - var h = f.blockSize, - m = 4 * h; - g.sigBytes > m && (g = f.finalize(g)); - g.clamp(); - for (var r = (this._oKey = g.clone()), l = (this._iKey = g.clone()), k = r.words, n = l.words, j = 0; j < h; j++) - (k[j] ^= 1549556828), (n[j] ^= 909522486); - r.sigBytes = l.sigBytes = m; - this.reset(); - }, - reset: function () { - var f = this._hasher; - f.reset(); - f.update(this._iKey); - }, - update: function (f) { - this._hasher.update(f); - return this; - }, - finalize: function (f) { - var g = this._hasher; - f = g.finalize(f); - g.reset(); - return g.finalize(this._oKey.clone().concat(f)); - }, - }); - })(); - - // Base64 - (function () { - var u = CryptoJS, - p = u.lib.WordArray; - u.enc.Base64 = { - stringify: function (d) { - var l = d.words, - p = d.sigBytes, - t = this._map; - d.clamp(); - d = []; - for (var r = 0; r < p; r += 3) - for ( - var w = - (((l[r >>> 2] >>> (24 - 8 * (r % 4))) & 255) << 16) | - (((l[(r + 1) >>> 2] >>> (24 - 8 * ((r + 1) % 4))) & 255) << 8) | - ((l[(r + 2) >>> 2] >>> (24 - 8 * ((r + 2) % 4))) & 255), - v = 0; - 4 > v && r + 0.75 * v < p; - v++ - ) - d.push(t.charAt((w >>> (6 * (3 - v))) & 63)); - if ((l = t.charAt(64))) for (; d.length % 4; ) d.push(l); - return d.join(''); - }, - parse: function (d) { - var l = d.length, - s = this._map, - t = s.charAt(64); - t && ((t = d.indexOf(t)), -1 != t && (l = t)); - for (var t = [], r = 0, w = 0; w < l; w++) - if (w % 4) { - var v = s.indexOf(d.charAt(w - 1)) << (2 * (w % 4)), - b = s.indexOf(d.charAt(w)) >>> (6 - 2 * (w % 4)); - t[r >>> 2] |= (v | b) << (24 - 8 * (r % 4)); - r++; - } - return p.create(t, r); - }, - _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', - }; - })(); - - // BlockCipher - (function (u) { - function p(b, n, a, c, e, j, k) { - b = b + ((n & a) | (~n & c)) + e + k; - return ((b << j) | (b >>> (32 - j))) + n; - } - function d(b, n, a, c, e, j, k) { - b = b + ((n & c) | (a & ~c)) + e + k; - return ((b << j) | (b >>> (32 - j))) + n; - } - function l(b, n, a, c, e, j, k) { - b = b + (n ^ a ^ c) + e + k; - return ((b << j) | (b >>> (32 - j))) + n; - } - function s(b, n, a, c, e, j, k) { - b = b + (a ^ (n | ~c)) + e + k; - return ((b << j) | (b >>> (32 - j))) + n; - } - for (var t = CryptoJS, r = t.lib, w = r.WordArray, v = r.Hasher, r = t.algo, b = [], x = 0; 64 > x; x++) - b[x] = (4294967296 * u.abs(u.sin(x + 1))) | 0; - r = r.MD5 = v.extend({ - _doReset: function () { - this._hash = new w.init([1732584193, 4023233417, 2562383102, 271733878]); - }, - _doProcessBlock: function (q, n) { - for (var a = 0; 16 > a; a++) { - var c = n + a, - e = q[c]; - q[c] = (((e << 8) | (e >>> 24)) & 16711935) | (((e << 24) | (e >>> 8)) & 4278255360); - } - var a = this._hash.words, - c = q[n + 0], - e = q[n + 1], - j = q[n + 2], - k = q[n + 3], - z = q[n + 4], - r = q[n + 5], - t = q[n + 6], - w = q[n + 7], - v = q[n + 8], - A = q[n + 9], - B = q[n + 10], - C = q[n + 11], - u = q[n + 12], - D = q[n + 13], - E = q[n + 14], - x = q[n + 15], - f = a[0], - m = a[1], - g = a[2], - h = a[3], - f = p(f, m, g, h, c, 7, b[0]), - h = p(h, f, m, g, e, 12, b[1]), - g = p(g, h, f, m, j, 17, b[2]), - m = p(m, g, h, f, k, 22, b[3]), - f = p(f, m, g, h, z, 7, b[4]), - h = p(h, f, m, g, r, 12, b[5]), - g = p(g, h, f, m, t, 17, b[6]), - m = p(m, g, h, f, w, 22, b[7]), - f = p(f, m, g, h, v, 7, b[8]), - h = p(h, f, m, g, A, 12, b[9]), - g = p(g, h, f, m, B, 17, b[10]), - m = p(m, g, h, f, C, 22, b[11]), - f = p(f, m, g, h, u, 7, b[12]), - h = p(h, f, m, g, D, 12, b[13]), - g = p(g, h, f, m, E, 17, b[14]), - m = p(m, g, h, f, x, 22, b[15]), - f = d(f, m, g, h, e, 5, b[16]), - h = d(h, f, m, g, t, 9, b[17]), - g = d(g, h, f, m, C, 14, b[18]), - m = d(m, g, h, f, c, 20, b[19]), - f = d(f, m, g, h, r, 5, b[20]), - h = d(h, f, m, g, B, 9, b[21]), - g = d(g, h, f, m, x, 14, b[22]), - m = d(m, g, h, f, z, 20, b[23]), - f = d(f, m, g, h, A, 5, b[24]), - h = d(h, f, m, g, E, 9, b[25]), - g = d(g, h, f, m, k, 14, b[26]), - m = d(m, g, h, f, v, 20, b[27]), - f = d(f, m, g, h, D, 5, b[28]), - h = d(h, f, m, g, j, 9, b[29]), - g = d(g, h, f, m, w, 14, b[30]), - m = d(m, g, h, f, u, 20, b[31]), - f = l(f, m, g, h, r, 4, b[32]), - h = l(h, f, m, g, v, 11, b[33]), - g = l(g, h, f, m, C, 16, b[34]), - m = l(m, g, h, f, E, 23, b[35]), - f = l(f, m, g, h, e, 4, b[36]), - h = l(h, f, m, g, z, 11, b[37]), - g = l(g, h, f, m, w, 16, b[38]), - m = l(m, g, h, f, B, 23, b[39]), - f = l(f, m, g, h, D, 4, b[40]), - h = l(h, f, m, g, c, 11, b[41]), - g = l(g, h, f, m, k, 16, b[42]), - m = l(m, g, h, f, t, 23, b[43]), - f = l(f, m, g, h, A, 4, b[44]), - h = l(h, f, m, g, u, 11, b[45]), - g = l(g, h, f, m, x, 16, b[46]), - m = l(m, g, h, f, j, 23, b[47]), - f = s(f, m, g, h, c, 6, b[48]), - h = s(h, f, m, g, w, 10, b[49]), - g = s(g, h, f, m, E, 15, b[50]), - m = s(m, g, h, f, r, 21, b[51]), - f = s(f, m, g, h, u, 6, b[52]), - h = s(h, f, m, g, k, 10, b[53]), - g = s(g, h, f, m, B, 15, b[54]), - m = s(m, g, h, f, e, 21, b[55]), - f = s(f, m, g, h, v, 6, b[56]), - h = s(h, f, m, g, x, 10, b[57]), - g = s(g, h, f, m, t, 15, b[58]), - m = s(m, g, h, f, D, 21, b[59]), - f = s(f, m, g, h, z, 6, b[60]), - h = s(h, f, m, g, C, 10, b[61]), - g = s(g, h, f, m, j, 15, b[62]), - m = s(m, g, h, f, A, 21, b[63]); - a[0] = (a[0] + f) | 0; - a[1] = (a[1] + m) | 0; - a[2] = (a[2] + g) | 0; - a[3] = (a[3] + h) | 0; - }, - _doFinalize: function () { - var b = this._data, - n = b.words, - a = 8 * this._nDataBytes, - c = 8 * b.sigBytes; - n[c >>> 5] |= 128 << (24 - (c % 32)); - var e = u.floor(a / 4294967296); - n[(((c + 64) >>> 9) << 4) + 15] = (((e << 8) | (e >>> 24)) & 16711935) | (((e << 24) | (e >>> 8)) & 4278255360); - n[(((c + 64) >>> 9) << 4) + 14] = (((a << 8) | (a >>> 24)) & 16711935) | (((a << 24) | (a >>> 8)) & 4278255360); - b.sigBytes = 4 * (n.length + 1); - this._process(); - b = this._hash; - n = b.words; - for (a = 0; 4 > a; a++) - (c = n[a]), (n[a] = (((c << 8) | (c >>> 24)) & 16711935) | (((c << 24) | (c >>> 8)) & 4278255360)); - return b; - }, - clone: function () { - var b = v.clone.call(this); - b._hash = this._hash.clone(); - return b; - }, - }); - t.MD5 = v._createHelper(r); - t.HmacMD5 = v._createHmacHelper(r); - })(Math); - (function () { - var u = CryptoJS, - p = u.lib, - d = p.Base, - l = p.WordArray, - p = u.algo, - s = (p.EvpKDF = d.extend({ - cfg: d.extend({ keySize: 4, hasher: p.MD5, iterations: 1 }), - init: function (d) { - this.cfg = this.cfg.extend(d); - }, - compute: function (d, r) { - for ( - var p = this.cfg, s = p.hasher.create(), b = l.create(), u = b.words, q = p.keySize, p = p.iterations; - u.length < q; - - ) { - n && s.update(n); - var n = s.update(d).finalize(r); - s.reset(); - for (var a = 1; a < p; a++) (n = s.finalize(n)), s.reset(); - b.concat(n); - } - b.sigBytes = 4 * q; - return b; - }, - })); - u.EvpKDF = function (d, l, p) { - return s.create(p).compute(d, l); - }; - })(); - - // Cipher - CryptoJS.lib.Cipher || - (function (u) { - var p = CryptoJS, - d = p.lib, - l = d.Base, - s = d.WordArray, - t = d.BufferedBlockAlgorithm, - r = p.enc.Base64, - w = p.algo.EvpKDF, - v = (d.Cipher = t.extend({ - cfg: l.extend(), - createEncryptor: function (e, a) { - return this.create(this._ENC_XFORM_MODE, e, a); - }, - createDecryptor: function (e, a) { - return this.create(this._DEC_XFORM_MODE, e, a); - }, - init: function (e, a, b) { - this.cfg = this.cfg.extend(b); - this._xformMode = e; - this._key = a; - this.reset(); - }, - reset: function () { - t.reset.call(this); - this._doReset(); - }, - process: function (e) { - this._append(e); - return this._process(); - }, - finalize: function (e) { - e && this._append(e); - return this._doFinalize(); - }, - keySize: 4, - ivSize: 4, - _ENC_XFORM_MODE: 1, - _DEC_XFORM_MODE: 2, - _createHelper: function (e) { - return { - encrypt: function (b, k, d) { - return ('string' == typeof k ? c : a).encrypt(e, b, k, d); - }, - decrypt: function (b, k, d) { - return ('string' == typeof k ? c : a).decrypt(e, b, k, d); - }, - }; - }, - })); - d.StreamCipher = v.extend({ - _doFinalize: function () { - return this._process(!0); - }, - blockSize: 1, - }); - var b = (p.mode = {}), - x = function (e, a, b) { - var c = this._iv; - c ? (this._iv = u) : (c = this._prevBlock); - for (var d = 0; d < b; d++) e[a + d] ^= c[d]; - }, - q = (d.BlockCipherMode = l.extend({ - createEncryptor: function (e, a) { - return this.Encryptor.create(e, a); - }, - createDecryptor: function (e, a) { - return this.Decryptor.create(e, a); - }, - init: function (e, a) { - this._cipher = e; - this._iv = a; - }, - })).extend(); - q.Encryptor = q.extend({ - processBlock: function (e, a) { - var b = this._cipher, - c = b.blockSize; - x.call(this, e, a, c); - b.encryptBlock(e, a); - this._prevBlock = e.slice(a, a + c); - }, - }); - q.Decryptor = q.extend({ - processBlock: function (e, a) { - var b = this._cipher, - c = b.blockSize, - d = e.slice(a, a + c); - b.decryptBlock(e, a); - x.call(this, e, a, c); - this._prevBlock = d; - }, - }); - b = b.CBC = q; - q = (p.pad = {}).Pkcs7 = { - pad: function (a, b) { - for ( - var c = 4 * b, c = c - (a.sigBytes % c), d = (c << 24) | (c << 16) | (c << 8) | c, l = [], n = 0; - n < c; - n += 4 - ) - l.push(d); - c = s.create(l, c); - a.concat(c); - }, - unpad: function (a) { - a.sigBytes -= a.words[(a.sigBytes - 1) >>> 2] & 255; - }, - }; - d.BlockCipher = v.extend({ - cfg: v.cfg.extend({ mode: b, padding: q }), - reset: function () { - v.reset.call(this); - var a = this.cfg, - b = a.iv, - a = a.mode; - if (this._xformMode == this._ENC_XFORM_MODE) var c = a.createEncryptor; - else (c = a.createDecryptor), (this._minBufferSize = 1); - this._mode = c.call(a, this, b && b.words); - }, - _doProcessBlock: function (a, b) { - this._mode.processBlock(a, b); - }, - _doFinalize: function () { - var a = this.cfg.padding; - if (this._xformMode == this._ENC_XFORM_MODE) { - a.pad(this._data, this.blockSize); - var b = this._process(!0); - } else (b = this._process(!0)), a.unpad(b); - return b; - }, - blockSize: 4, - }); - var n = (d.CipherParams = l.extend({ - init: function (a) { - this.mixIn(a); - }, - toString: function (a) { - return (a || this.formatter).stringify(this); - }, - })), - b = ((p.format = {}).OpenSSL = { - stringify: function (a) { - var b = a.ciphertext; - a = a.salt; - return (a ? s.create([1398893684, 1701076831]).concat(a).concat(b) : b).toString(r); - }, - parse: function (a) { - a = r.parse(a); - var b = a.words; - if (1398893684 == b[0] && 1701076831 == b[1]) { - var c = s.create(b.slice(2, 4)); - b.splice(0, 4); - a.sigBytes -= 16; - } - return n.create({ ciphertext: a, salt: c }); - }, - }), - a = (d.SerializableCipher = l.extend({ - cfg: l.extend({ format: b }), - encrypt: function (a, b, c, d) { - d = this.cfg.extend(d); - var l = a.createEncryptor(c, d); - b = l.finalize(b); - l = l.cfg; - return n.create({ - ciphertext: b, - key: c, - iv: l.iv, - algorithm: a, - mode: l.mode, - padding: l.padding, - blockSize: a.blockSize, - formatter: d.format, - }); - }, - decrypt: function (a, b, c, d) { - d = this.cfg.extend(d); - b = this._parse(b, d.format); - return a.createDecryptor(c, d).finalize(b.ciphertext); - }, - _parse: function (a, b) { - return 'string' == typeof a ? b.parse(a, this) : a; - }, - })), - p = ((p.kdf = {}).OpenSSL = { - execute: function (a, b, c, d) { - d || (d = s.random(8)); - a = w.create({ keySize: b + c }).compute(a, d); - c = s.create(a.words.slice(b), 4 * c); - a.sigBytes = 4 * b; - return n.create({ key: a, iv: c, salt: d }); - }, - }), - c = (d.PasswordBasedCipher = a.extend({ - cfg: a.cfg.extend({ kdf: p }), - encrypt: function (b, c, d, l) { - l = this.cfg.extend(l); - d = l.kdf.execute(d, b.keySize, b.ivSize); - l.iv = d.iv; - b = a.encrypt.call(this, b, c, d.key, l); - b.mixIn(d); - return b; - }, - decrypt: function (b, c, d, l) { - l = this.cfg.extend(l); - c = this._parse(c, l.format); - d = l.kdf.execute(d, b.keySize, b.ivSize, c.salt); - l.iv = d.iv; - return a.decrypt.call(this, b, c, d.key, l); - }, - })); - })(); - - // AES - (function () { - for ( - var u = CryptoJS, - p = u.lib.BlockCipher, - d = u.algo, - l = [], - s = [], - t = [], - r = [], - w = [], - v = [], - b = [], - x = [], - q = [], - n = [], - a = [], - c = 0; - 256 > c; - c++ - ) - a[c] = 128 > c ? c << 1 : (c << 1) ^ 283; - for (var e = 0, j = 0, c = 0; 256 > c; c++) { - var k = j ^ (j << 1) ^ (j << 2) ^ (j << 3) ^ (j << 4), - k = (k >>> 8) ^ (k & 255) ^ 99; - l[e] = k; - s[k] = e; - var z = a[e], - F = a[z], - G = a[F], - y = (257 * a[k]) ^ (16843008 * k); - t[e] = (y << 24) | (y >>> 8); - r[e] = (y << 16) | (y >>> 16); - w[e] = (y << 8) | (y >>> 24); - v[e] = y; - y = (16843009 * G) ^ (65537 * F) ^ (257 * z) ^ (16843008 * e); - b[k] = (y << 24) | (y >>> 8); - x[k] = (y << 16) | (y >>> 16); - q[k] = (y << 8) | (y >>> 24); - n[k] = y; - e ? ((e = z ^ a[a[a[G ^ z]]]), (j ^= a[a[j]])) : (e = j = 1); - } - var H = [0, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54], - d = (d.AES = p.extend({ - _doReset: function () { - for ( - var a = this._key, - c = a.words, - d = a.sigBytes / 4, - a = 4 * ((this._nRounds = d + 6) + 1), - e = (this._keySchedule = []), - j = 0; - j < a; - j++ - ) - if (j < d) e[j] = c[j]; - else { - var k = e[j - 1]; - j % d - ? 6 < d && - 4 == j % d && - (k = (l[k >>> 24] << 24) | (l[(k >>> 16) & 255] << 16) | (l[(k >>> 8) & 255] << 8) | l[k & 255]) - : ((k = (k << 8) | (k >>> 24)), - (k = (l[k >>> 24] << 24) | (l[(k >>> 16) & 255] << 16) | (l[(k >>> 8) & 255] << 8) | l[k & 255]), - (k ^= H[(j / d) | 0] << 24)); - e[j] = e[j - d] ^ k; - } - c = this._invKeySchedule = []; - for (d = 0; d < a; d++) - (j = a - d), - (k = d % 4 ? e[j] : e[j - 4]), - (c[d] = - 4 > d || 4 >= j ? k : b[l[k >>> 24]] ^ x[l[(k >>> 16) & 255]] ^ q[l[(k >>> 8) & 255]] ^ n[l[k & 255]]); - }, - encryptBlock: function (a, b) { - this._doCryptBlock(a, b, this._keySchedule, t, r, w, v, l); - }, - decryptBlock: function (a, c) { - var d = a[c + 1]; - a[c + 1] = a[c + 3]; - a[c + 3] = d; - this._doCryptBlock(a, c, this._invKeySchedule, b, x, q, n, s); - d = a[c + 1]; - a[c + 1] = a[c + 3]; - a[c + 3] = d; - }, - _doCryptBlock: function (a, b, c, d, e, j, l, f) { - for ( - var m = this._nRounds, - g = a[b] ^ c[0], - h = a[b + 1] ^ c[1], - k = a[b + 2] ^ c[2], - n = a[b + 3] ^ c[3], - p = 4, - r = 1; - r < m; - r++ - ) - var q = d[g >>> 24] ^ e[(h >>> 16) & 255] ^ j[(k >>> 8) & 255] ^ l[n & 255] ^ c[p++], - s = d[h >>> 24] ^ e[(k >>> 16) & 255] ^ j[(n >>> 8) & 255] ^ l[g & 255] ^ c[p++], - t = d[k >>> 24] ^ e[(n >>> 16) & 255] ^ j[(g >>> 8) & 255] ^ l[h & 255] ^ c[p++], - n = d[n >>> 24] ^ e[(g >>> 16) & 255] ^ j[(h >>> 8) & 255] ^ l[k & 255] ^ c[p++], - g = q, - h = s, - k = t; - q = ((f[g >>> 24] << 24) | (f[(h >>> 16) & 255] << 16) | (f[(k >>> 8) & 255] << 8) | f[n & 255]) ^ c[p++]; - s = ((f[h >>> 24] << 24) | (f[(k >>> 16) & 255] << 16) | (f[(n >>> 8) & 255] << 8) | f[g & 255]) ^ c[p++]; - t = ((f[k >>> 24] << 24) | (f[(n >>> 16) & 255] << 16) | (f[(g >>> 8) & 255] << 8) | f[h & 255]) ^ c[p++]; - n = ((f[n >>> 24] << 24) | (f[(g >>> 16) & 255] << 16) | (f[(h >>> 8) & 255] << 8) | f[k & 255]) ^ c[p++]; - a[b] = q; - a[b + 1] = s; - a[b + 2] = t; - a[b + 3] = n; - }, - keySize: 8, - })); - u.AES = p._createHelper(d); - })(); - - // Mode ECB - CryptoJS.mode.ECB = (function () { - var ECB = CryptoJS.lib.BlockCipherMode.extend(); - - ECB.Encryptor = ECB.extend({ - processBlock: function (words, offset) { - this._cipher.encryptBlock(words, offset); - }, - }); - - ECB.Decryptor = ECB.extend({ - processBlock: function (words, offset) { - this._cipher.decryptBlock(words, offset); - }, - }); - - return ECB; - })(); - - var hmacSha256 = CryptoJS; - - var CryptoJS$1 = /*@__PURE__*/getDefaultExportFromCjs(hmacSha256); - - /** - * AES-CBC cryptor module. - */ - /** - * AES-CBC cryptor. - * - * AES-CBC cryptor with enhanced cipher strength. - */ - class AesCbcCryptor { - constructor({ cipherKey }) { - this.cipherKey = cipherKey; - this.CryptoJS = CryptoJS$1; - this.encryptedKey = this.CryptoJS.SHA256(cipherKey); - } - // -------------------------------------------------------- - // --------------------- Encryption ----------------------- - // -------------------------------------------------------- - // region Encryption - encrypt(data) { - const stringData = typeof data === 'string' ? data : AesCbcCryptor.decoder.decode(data); - if (stringData.length === 0) - throw new Error('encryption error. empty content'); - const abIv = this.getIv(); - return { - metadata: abIv, - data: decode(this.CryptoJS.AES.encrypt(data, this.encryptedKey, { - iv: this.bufferToWordArray(abIv), - mode: this.CryptoJS.mode.CBC, - }).ciphertext.toString(this.CryptoJS.enc.Base64)), - }; - } - encryptFileData(data) { - return __awaiter(this, void 0, void 0, function* () { - const key = yield this.getKey(); - const iv = this.getIv(); - return { - data: yield crypto.subtle.encrypt({ name: this.algo, iv: iv }, key, data), - metadata: iv, - }; - }); - } - // endregion - // -------------------------------------------------------- - // --------------------- Decryption ----------------------- - // -------------------------------------------------------- - // region Decryption - decrypt(encryptedData) { - if (typeof encryptedData.data === 'string') - throw new Error('Decryption error: data for decryption should be ArrayBuffed.'); - const iv = this.bufferToWordArray(new Uint8ClampedArray(encryptedData.metadata)); - const data = this.bufferToWordArray(new Uint8ClampedArray(encryptedData.data)); - return AesCbcCryptor.encoder.encode(this.CryptoJS.AES.decrypt({ ciphertext: data }, this.encryptedKey, { - iv, - mode: this.CryptoJS.mode.CBC, - }).toString(this.CryptoJS.enc.Utf8)).buffer; - } - decryptFileData(encryptedData) { - return __awaiter(this, void 0, void 0, function* () { - if (typeof encryptedData.data === 'string') - throw new Error('Decryption error: data for decryption should be ArrayBuffed.'); - const key = yield this.getKey(); - return crypto.subtle.decrypt({ name: this.algo, iv: encryptedData.metadata }, key, encryptedData.data); - }); - } - // endregion - // -------------------------------------------------------- - // ----------------------- Helpers ------------------------ - // -------------------------------------------------------- - // region Helpers - get identifier() { - return 'ACRH'; - } - /** - * Cryptor algorithm. - * - * @returns Cryptor module algorithm. - */ - get algo() { - return 'AES-CBC'; - } - /** - * Generate random initialization vector. - * - * @returns Random initialization vector. - */ - getIv() { - return crypto.getRandomValues(new Uint8Array(AesCbcCryptor.BLOCK_SIZE)); - } - /** - * Convert cipher key to the {@link Buffer}. - * - * @returns SHA256 encoded cipher key {@link Buffer}. - */ - getKey() { - return __awaiter(this, void 0, void 0, function* () { - const bKey = AesCbcCryptor.encoder.encode(this.cipherKey); - const abHash = yield crypto.subtle.digest('SHA-256', bKey.buffer); - return crypto.subtle.importKey('raw', abHash, this.algo, true, ['encrypt', 'decrypt']); - }); - } - /** - * Convert bytes array to words array. - * - * @param b - Bytes array (buffer) which should be converted. - * - * @returns Word sized array. - */ - bufferToWordArray(b) { - const wa = []; - let i; - for (i = 0; i < b.length; i += 1) { - wa[(i / 4) | 0] |= b[i] << (24 - 8 * i); - } - return this.CryptoJS.lib.WordArray.create(wa, b.length); - } - /** - * Serialize cryptor information to string. - * - * @returns Serialized cryptor information. - */ - toString() { - return 'AesCbcCryptor {}'; - } - } - /** - * Cryptor block size. - */ - AesCbcCryptor.BLOCK_SIZE = 16; - /** - * {@link string|String} to {@link ArrayBuffer} response decoder. - */ - AesCbcCryptor.encoder = new TextEncoder(); - /** - * {@link ArrayBuffer} to {@link string} decoder. - */ - AesCbcCryptor.decoder = new TextDecoder(); - - /** - * PubNub package utilities module. - * - * @internal - */ - /** - * Object log property names that must never appear in SDK logs. - * - * @internal - */ - const SENSITIVE_LOG_KEYS = new Set(['authKey', 'authKeys', 'secretKey', 'cipherKey', 'token', 'auth']); - /** - * Whether an object log key should be omitted because it may hold a secret. - * - * @param key - Property name from an object being logged. - * - * @returns `true` when the key should be filtered from log output. - * - * @internal - */ - const isSensitiveLogKey = (key) => SENSITIVE_LOG_KEYS.has(key); - /** - * Percent-encode input string. - * - * **Note:** Encode content in accordance of the `PubNub` service requirements. - * - * @param input - Source string or number for encoding. - * - * @returns Percent-encoded string. - * - * @internal - */ - const encodeString = (input) => { - return encodeURIComponent(input).replace(/[!~*'()]/g, (x) => `%${x.charCodeAt(0).toString(16).toUpperCase()}`); - }; - /** - * Percent-encode list of names (channels). - * - * @param names - List of names which should be encoded. - * - * @param [defaultString] - String which should be used in case if {@link names} is empty. - * - * @returns String which contains encoded names joined by non-encoded `,`. - * - * @internal - */ - const encodeNames = (names, defaultString) => { - const encodedNames = names.map((name) => encodeString(name)); - return encodedNames.length ? encodedNames.join(',') : (defaultString !== null && defaultString !== void 0 ? defaultString : ''); - }; - /** - * @internal - */ - const removeSingleOccurrence = (source, elementsToRemove) => { - const removed = Object.fromEntries(elementsToRemove.map((prop) => [prop, false])); - return source.filter((e) => { - if (elementsToRemove.includes(e) && !removed[e]) { - removed[e] = true; - return false; - } - return true; - }); - }; - /** - * @internal - */ - const findUniqueCommonElements = (a, b) => { - return [...a].filter((value) => b.includes(value) && a.indexOf(value) === a.lastIndexOf(value) && b.indexOf(value) === b.lastIndexOf(value)); - }; - /** - * Transform query key / value pairs to the string. - * - * @param query - Key / value pairs of the request query parameters. - * - * @returns Stringified query key / value pairs. - * - * @internal - */ - const queryStringFromObject = (query) => { - return Object.keys(query) - .map((key) => { - const queryValue = query[key]; - if (!Array.isArray(queryValue)) - return `${key}=${encodeString(queryValue)}`; - return queryValue.map((value) => `${key}=${encodeString(value)}`).join('&'); - }) - .join('&'); - }; - /** - * Adjust `timetoken` to represent current time in PubNub's high-precision time format. - * - * @param timetoken - Timetoken recently used for subscribe long-poll request. - * @param [referenceTimetoken] - Previously computed reference timetoken. - * - * @returns Adjusted timetoken if recent timetoken available. - */ - const subscriptionTimetokenFromReference = (timetoken, referenceTimetoken) => { - if (referenceTimetoken === '0' || timetoken === '0') - return undefined; - const timetokenDiff = adjustedTimetokenBy(`${Date.now()}0000`, referenceTimetoken, false); - return adjustedTimetokenBy(timetoken, timetokenDiff, true); - }; - /** - * Create reference timetoken based on subscribe timetoken and the user's local time. - * - * Subscription-based reference timetoken allows later computing approximate timetoken at any point in time. - * - * @param [serviceTimetoken] - Timetoken received from the PubNub subscribe service. - * @param [catchUpTimetoken] - Previously stored or user-provided catch-up timetoken. - * @param [referenceTimetoken] - Previously computed reference timetoken. **Important:** This value should be used - * in the case of restore because the actual time when service and catch-up timetokens are received is really - * different from the current local time. - * - * @returns Reference timetoken. - */ - const referenceSubscribeTimetoken = (serviceTimetoken, catchUpTimetoken, referenceTimetoken) => { - if (!serviceTimetoken || serviceTimetoken.length === 0) - return undefined; - if (catchUpTimetoken && catchUpTimetoken.length > 0 && catchUpTimetoken !== '0') { - // Compensate reference timetoken because catch-up timetoken has been used. - const timetokensDiff = adjustedTimetokenBy(serviceTimetoken, catchUpTimetoken, false); - return adjustedTimetokenBy(referenceTimetoken !== null && referenceTimetoken !== void 0 ? referenceTimetoken : `${Date.now()}0000`, timetokensDiff.replace('-', ''), Number(timetokensDiff) < 0); - } - else if (referenceTimetoken && referenceTimetoken.length > 0 && referenceTimetoken !== '0') - return referenceTimetoken; - else - return `${Date.now()}0000`; - }; - /** - * High-precision time token adjustment. - * - * @param timetoken - Source timetoken which should be adjusted. - * @param value - Value in nanoseconds which should be used for source timetoken adjustment. - * @param increment - Whether source timetoken should be incremented or decremented. - * - * @returns Adjusted high-precision PubNub timetoken. - */ - const adjustedTimetokenBy = (timetoken, value, increment) => { - // Normalize value to the PubNub's high-precision time format. - if (value.startsWith('-')) { - value = value.replace('-', ''); - increment = false; - } - value = value.padStart(17, '0'); - const secA = timetoken.slice(0, 10); - const tickA = timetoken.slice(10, 17); - const secB = value.slice(0, 10); - const tickB = value.slice(10, 17); - let seconds = Number(secA); - let ticks = Number(tickA); - seconds += Number(secB) * (increment ? 1 : -1); - ticks += Number(tickB) * (increment ? 1 : -1); - if (ticks >= 10000000) { - seconds += Math.floor(ticks / 10000000); - ticks %= 10000000; - } - else if (ticks < 0) { - if (seconds > 0) { - seconds -= 1; - ticks += 10000000; - } - else if (seconds < 0) - ticks *= -1; - } - else if (seconds < 0 && ticks > 0) { - seconds += 1; - ticks = 10000000 - ticks; - } - return seconds !== 0 ? `${seconds}${`${ticks}`.padStart(7, '0')}` : `${ticks}`; - }; - /** - * Compute received update (message, event) fingerprint. - * - * @param input - Data payload from subscribe API response. - * - * @returns Received update fingerprint. - */ - const messageFingerprint = (input) => { - const msg = typeof input !== 'string' ? JSON.stringify(input) : input; - const mfp = new Uint32Array(1); - let walk = 0; - let len = msg.length; - while (len-- > 0) - mfp[0] = (mfp[0] << 5) - mfp[0] + msg.charCodeAt(walk++); - return mfp[0].toString(16).padStart(8, '0'); - }; - - /** - * Legacy cryptography module. - * - * @internal - */ - /** - * Convert bytes array to words array. - * - * @param b - Bytes array (buffer) which should be converted. - * - * @returns Word sized array. - * - * @internal - */ - /* eslint-disable @typescript-eslint/no-explicit-any */ - function bufferToWordArray(b) { - const wa = []; - let i; - for (i = 0; i < b.length; i += 1) { - wa[(i / 4) | 0] |= b[i] << (24 - 8 * i); - } - // @ts-expect-error Bundled library without types. - return CryptoJS$1.lib.WordArray.create(wa, b.length); - } - /** - * Legacy cryptography module for files and signature. - * - * @internal - */ - class Crypto { - constructor(configuration) { - this.configuration = configuration; - /** - * Crypto initialization vector. - */ - this.iv = '0123456789012345'; - /** - * List os allowed cipher key encodings. - */ - this.allowedKeyEncodings = ['hex', 'utf8', 'base64', 'binary']; - /** - * Allowed cipher key lengths. - */ - this.allowedKeyLengths = [128, 256]; - /** - * Allowed crypto modes. - */ - this.allowedModes = ['ecb', 'cbc']; - this.logger = configuration.logger; - this.defaultOptions = { - encryptKey: true, - keyEncoding: 'utf8', - keyLength: 256, - mode: 'cbc', - }; - } - /** - * Update registered loggers' manager. - * - * @param [logger] - Logger, which crypto should use. - */ - set logger(logger) { - this._logger = logger; - if (this.logger) { - this.logger.debug('Crypto', () => ({ - messageType: 'object', - message: this.configuration, - details: 'Create with configuration:', - ignoredKeys(key, obj) { - return typeof obj[key] === 'function' || key === 'logger' || isSensitiveLogKey(key); - }, - })); - } - } - /** - * Get loggers' manager. - * - * @returns Loggers' manager (if set). - */ - get logger() { - return this._logger; - } - /** - * Generate HMAC-SHA256 hash from input data. - * - * @param data - Data from which hash should be generated. - * - * @returns HMAC-SHA256 hash from provided `data`. - */ - HMACSHA256(data) { - // @ts-expect-error Bundled library without types. - const hash = CryptoJS$1.HmacSHA256(data, this.configuration.secretKey); - // @ts-expect-error Bundled library without types. - return hash.toString(CryptoJS$1.enc.Base64); - } - /** - * Generate SHA256 hash from input data. - * - * @param data - Data from which hash should be generated. - * - * @returns SHA256 hash from provided `data`. - */ - SHA256(data) { - // @ts-expect-error Bundled library without types. - return CryptoJS$1.SHA256(data).toString(CryptoJS$1.enc.Hex); - } - /** - * Encrypt provided data. - * - * @param data - Source data which should be encrypted. - * @param [customCipherKey] - Custom cipher key (different from defined on client level). - * @param [options] - Specific crypto configuration options. - * - * @returns Encrypted `data`. - */ - encrypt(data, customCipherKey, options) { - if (this.configuration.customEncrypt) { - if (this.logger) - this.logger.warn('Crypto', "'customEncrypt' is deprecated. Consult docs for better alternative."); - return this.configuration.customEncrypt(data); - } - return this.pnEncrypt(data, customCipherKey, options); - } - /** - * Decrypt provided data. - * - * @param data - Encrypted data which should be decrypted. - * @param [customCipherKey] - Custom cipher key (different from defined on client level). - * @param [options] - Specific crypto configuration options. - * - * @returns Decrypted `data`. - */ - decrypt(data, customCipherKey, options) { - if (this.configuration.customDecrypt) { - if (this.logger) - this.logger.warn('Crypto', "'customDecrypt' is deprecated. Consult docs for better alternative."); - return this.configuration.customDecrypt(data); - } - return this.pnDecrypt(data, customCipherKey, options); - } - /** - * Encrypt provided data. - * - * @param data - Source data which should be encrypted. - * @param [customCipherKey] - Custom cipher key (different from defined on client level). - * @param [options] - Specific crypto configuration options. - * - * @returns Encrypted `data` as string. - */ - pnEncrypt(data, customCipherKey, options) { - const decidedCipherKey = customCipherKey !== null && customCipherKey !== void 0 ? customCipherKey : this.configuration.cipherKey; - if (!decidedCipherKey) - return data; - if (this.logger) { - this.logger.debug('Crypto', () => ({ - messageType: 'object', - message: Object.assign({ data }, (options !== null && options !== void 0 ? options : {})), - details: 'Encrypt with parameters:', - ignoredKeys: isSensitiveLogKey, - })); - } - options = this.parseOptions(options); - const mode = this.getMode(options); - const cipherKey = this.getPaddedKey(decidedCipherKey, options); - if (this.configuration.useRandomIVs) { - const waIv = this.getRandomIV(); - // @ts-expect-error Bundled library without types. - const waPayload = CryptoJS$1.AES.encrypt(data, cipherKey, { iv: waIv, mode }).ciphertext; - // @ts-expect-error Bundled library without types. - return waIv.clone().concat(waPayload.clone()).toString(CryptoJS$1.enc.Base64); - } - const iv = this.getIV(options); - // @ts-expect-error Bundled library without types. - const encryptedHexArray = CryptoJS$1.AES.encrypt(data, cipherKey, { iv, mode }).ciphertext; - // @ts-expect-error Bundled library without types. - const base64Encrypted = encryptedHexArray.toString(CryptoJS$1.enc.Base64); - return base64Encrypted || data; - } - /** - * Decrypt provided data. - * - * @param data - Encrypted data which should be decrypted. - * @param [customCipherKey] - Custom cipher key (different from defined on client level). - * @param [options] - Specific crypto configuration options. - * - * @returns Decrypted `data`. - */ - pnDecrypt(data, customCipherKey, options) { - const decidedCipherKey = customCipherKey !== null && customCipherKey !== void 0 ? customCipherKey : this.configuration.cipherKey; - if (!decidedCipherKey) - return data; - if (this.logger) { - this.logger.debug('Crypto', () => ({ - messageType: 'object', - message: Object.assign({ data }, (options !== null && options !== void 0 ? options : {})), - details: 'Decrypt with parameters:', - ignoredKeys: isSensitiveLogKey, - })); - } - options = this.parseOptions(options); - const mode = this.getMode(options); - const cipherKey = this.getPaddedKey(decidedCipherKey, options); - if (this.configuration.useRandomIVs) { - const ciphertext = new Uint8ClampedArray(decode(data)); - const iv = bufferToWordArray(ciphertext.slice(0, 16)); - const payload = bufferToWordArray(ciphertext.slice(16)); - try { - // @ts-expect-error Bundled library without types. - const plainJSON = CryptoJS$1.AES.decrypt({ ciphertext: payload }, cipherKey, { iv, mode }).toString( - // @ts-expect-error Bundled library without types. - CryptoJS$1.enc.Utf8); - return JSON.parse(plainJSON); - } - catch (e) { - if (this.logger) - this.logger.error('Crypto', () => ({ messageType: 'error', message: e })); - return null; - } - } - else { - const iv = this.getIV(options); - try { - // @ts-expect-error Bundled library without types. - const ciphertext = CryptoJS$1.enc.Base64.parse(data); - // @ts-expect-error Bundled library without types. - const plainJSON = CryptoJS$1.AES.decrypt({ ciphertext }, cipherKey, { iv, mode }).toString(CryptoJS$1.enc.Utf8); - return JSON.parse(plainJSON); - } - catch (e) { - if (this.logger) - this.logger.error('Crypto', () => ({ messageType: 'error', message: e })); - return null; - } - } - } - /** - * Pre-process provided custom crypto configuration. - * - * @param incomingOptions - Configuration which should be pre-processed before use. - * - * @returns Normalized crypto configuration options. - */ - parseOptions(incomingOptions) { - var _a, _b, _c, _d; - if (!incomingOptions) - return this.defaultOptions; - // Defaults - const options = { - encryptKey: (_a = incomingOptions.encryptKey) !== null && _a !== void 0 ? _a : this.defaultOptions.encryptKey, - keyEncoding: (_b = incomingOptions.keyEncoding) !== null && _b !== void 0 ? _b : this.defaultOptions.keyEncoding, - keyLength: (_c = incomingOptions.keyLength) !== null && _c !== void 0 ? _c : this.defaultOptions.keyLength, - mode: (_d = incomingOptions.mode) !== null && _d !== void 0 ? _d : this.defaultOptions.mode, - }; - // Validation - if (this.allowedKeyEncodings.indexOf(options.keyEncoding.toLowerCase()) === -1) - options.keyEncoding = this.defaultOptions.keyEncoding; - if (this.allowedKeyLengths.indexOf(options.keyLength) === -1) - options.keyLength = this.defaultOptions.keyLength; - if (this.allowedModes.indexOf(options.mode.toLowerCase()) === -1) - options.mode = this.defaultOptions.mode; - return options; - } - /** - * Decode provided cipher key. - * - * @param key - Key in `encoding` provided by `options`. - * @param options - Crypto configuration options with cipher key details. - * - * @returns Array buffer with decoded key. - */ - decodeKey(key, options) { - // @ts-expect-error Bundled library without types. - if (options.keyEncoding === 'base64') - return CryptoJS$1.enc.Base64.parse(key); - // @ts-expect-error Bundled library without types. - if (options.keyEncoding === 'hex') - return CryptoJS$1.enc.Hex.parse(key); - return key; - } - /** - * Add padding to the cipher key. - * - * @param key - Key which should be padded. - * @param options - Crypto configuration options with cipher key details. - * - * @returns Properly padded cipher key. - */ - getPaddedKey(key, options) { - key = this.decodeKey(key, options); - // @ts-expect-error Bundled library without types. - if (options.encryptKey) - return CryptoJS$1.enc.Utf8.parse(this.SHA256(key).slice(0, 32)); - return key; - } - /** - * Cipher mode. - * - * @param options - Crypto configuration with information about cipher mode. - * - * @returns Crypto cipher mode. - */ - getMode(options) { - // @ts-expect-error Bundled library without types. - if (options.mode === 'ecb') - return CryptoJS$1.mode.ECB; - // @ts-expect-error Bundled library without types. - return CryptoJS$1.mode.CBC; - } - /** - * Cipher initialization vector. - * - * @param options - Crypto configuration with information about cipher mode. - * - * @returns Initialization vector. - */ - getIV(options) { - // @ts-expect-error Bundled library without types. - return options.mode === 'cbc' ? CryptoJS$1.enc.Utf8.parse(this.iv) : null; - } - /** - * Random initialization vector. - * - * @returns Generated random initialization vector. - */ - getRandomIV() { - // @ts-expect-error Bundled library without types. - return CryptoJS$1.lib.WordArray.random(16); - } - } - - /** - * Legacy browser cryptography module. - * - * @internal - */ - /* global crypto */ - /** - * Legacy cryptography implementation for browser-based {@link PubNub} client. - * - * @internal - */ - class WebCryptography { - // -------------------------------------------------------- - // --------------------- Encryption ----------------------- - // -------------------------------------------------------- - // region Encryption - /** - * Encrypt provided source data using specific encryption {@link key}. - * - * @param key - Data encryption key.
**Note:** Same key should be used to `decrypt` data. - * @param input - Source data for encryption. - * - * @returns Encrypted data as object or stream (depending on from source data type). - * - * @throws Error if unknown data type has been passed. - */ - encrypt(key, input) { - return __awaiter(this, void 0, void 0, function* () { - if (!(input instanceof ArrayBuffer) && typeof input !== 'string') - throw new Error('Cannot encrypt this file. In browsers file encryption supports only string or ArrayBuffer'); - const cKey = yield this.getKey(key); - return input instanceof ArrayBuffer ? this.encryptArrayBuffer(cKey, input) : this.encryptString(cKey, input); - }); - } - /** - * Encrypt provided source {@link Buffer} using specific encryption {@link ArrayBuffer}. - * - * @param key - Data encryption key.
**Note:** Same key should be used to `decrypt` {@link ArrayBuffer}. - * @param buffer - Source {@link ArrayBuffer} for encryption. - * - * @returns Encrypted data as {@link ArrayBuffer} object. - */ - encryptArrayBuffer(key, buffer) { - return __awaiter(this, void 0, void 0, function* () { - const abIv = crypto.getRandomValues(new Uint8Array(16)); - return this.concatArrayBuffer(abIv.buffer, yield crypto.subtle.encrypt({ name: 'AES-CBC', iv: abIv }, key, buffer)); - }); - } - /** - * Encrypt provided source {@link string} using specific encryption {@link key}. - * - * @param key - Data encryption key.
**Note:** Same key should be used to `decrypt` {@link string}. - * @param text - Source {@link string} for encryption. - * - * @returns Encrypted data as byte {@link string}. - */ - encryptString(key, text) { - return __awaiter(this, void 0, void 0, function* () { - const abIv = crypto.getRandomValues(new Uint8Array(16)); - const abPlaintext = WebCryptography.encoder.encode(text).buffer; - const abPayload = yield crypto.subtle.encrypt({ name: 'AES-CBC', iv: abIv }, key, abPlaintext); - const ciphertext = this.concatArrayBuffer(abIv.buffer, abPayload); - return WebCryptography.decoder.decode(ciphertext); - }); - } - /** - * Encrypt provided {@link PubNub} File object using specific encryption {@link key}. - * - * @param key - Key for {@link PubNub} File object encryption.
**Note:** Same key should be - * used to `decrypt` data. - * @param file - Source {@link PubNub} File object for encryption. - * @param File - Class constructor for {@link PubNub} File object. - * - * @returns Encrypted data as {@link PubNub} File object. - * - * @throws Error if file is empty or contains unsupported data type. - */ - encryptFile(key, file, File) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b; - if (((_a = file.contentLength) !== null && _a !== void 0 ? _a : 0) <= 0) - throw new Error('encryption error. empty content'); - const bKey = yield this.getKey(key); - const abPlaindata = yield file.toArrayBuffer(); - const abCipherdata = yield this.encryptArrayBuffer(bKey, abPlaindata); - return File.create({ - name: file.name, - mimeType: (_b = file.mimeType) !== null && _b !== void 0 ? _b : 'application/octet-stream', - data: abCipherdata, - }); - }); - } - // endregion - // -------------------------------------------------------- - // --------------------- Decryption ----------------------- - // -------------------------------------------------------- - // region Decryption - /** - * Decrypt provided encrypted data using specific decryption {@link key}. - * - * @param key - Data decryption key.
**Note:** Should be the same as used to `encrypt` data. - * @param input - Encrypted data for decryption. - * - * @returns Decrypted data as object or stream (depending on from encrypted data type). - * - * @throws Error if unknown data type has been passed. - */ - decrypt(key, input) { - return __awaiter(this, void 0, void 0, function* () { - if (!(input instanceof ArrayBuffer) && typeof input !== 'string') - throw new Error('Cannot decrypt this file. In browsers file decryption supports only string or ArrayBuffer'); - const cKey = yield this.getKey(key); - return input instanceof ArrayBuffer ? this.decryptArrayBuffer(cKey, input) : this.decryptString(cKey, input); - }); - } - /** - * Decrypt provided encrypted {@link ArrayBuffer} using specific decryption {@link key}. - * - * @param key - Data decryption key.
**Note:** Should be the same as used to `encrypt` {@link ArrayBuffer}. - * @param buffer - Encrypted {@link ArrayBuffer} for decryption. - * - * @returns Decrypted data as {@link ArrayBuffer} object. - */ - decryptArrayBuffer(key, buffer) { - return __awaiter(this, void 0, void 0, function* () { - const abIv = buffer.slice(0, 16); - if (buffer.slice(WebCryptography.IV_LENGTH).byteLength <= 0) - throw new Error('decryption error: empty content'); - return yield crypto.subtle.decrypt({ name: 'AES-CBC', iv: abIv }, key, buffer.slice(WebCryptography.IV_LENGTH)); - }); - } - /** - * Decrypt provided encrypted {@link string} using specific decryption {@link key}. - * - * @param key - Data decryption key.
**Note:** Should be the same as used to `encrypt` {@link string}. - * @param text - Encrypted {@link string} for decryption. - * - * @returns Decrypted data as byte {@link string}. - */ - decryptString(key, text) { - return __awaiter(this, void 0, void 0, function* () { - const abCiphertext = WebCryptography.encoder.encode(text).buffer; - const abIv = abCiphertext.slice(0, 16); - const abPayload = abCiphertext.slice(16); - const abPlaintext = yield crypto.subtle.decrypt({ name: 'AES-CBC', iv: abIv }, key, abPayload); - return WebCryptography.decoder.decode(abPlaintext); - }); - } - /** - * Decrypt provided {@link PubNub} File object using specific decryption {@link key}. - * - * @param key - Key for {@link PubNub} File object decryption.
**Note:** Should be the same - * as used to `encrypt` data. - * @param file - Encrypted {@link PubNub} File object for decryption. - * @param File - Class constructor for {@link PubNub} File object. - * - * @returns Decrypted data as {@link PubNub} File object. - * - * @throws Error if file is empty or contains unsupported data type. - */ - decryptFile(key, file, File) { - return __awaiter(this, void 0, void 0, function* () { - const bKey = yield this.getKey(key); - const abCipherdata = yield file.toArrayBuffer(); - const abPlaindata = yield this.decryptArrayBuffer(bKey, abCipherdata); - return File.create({ - name: file.name, - mimeType: file.mimeType, - data: abPlaindata, - }); - }); - } - // endregion - // -------------------------------------------------------- - // ----------------------- Helpers ------------------------ - // -------------------------------------------------------- - // region Helpers - /** - * Convert cipher key to the {@link Buffer}. - * - * @param key - String cipher key. - * - * @returns SHA256 HEX encoded cipher key {@link CryptoKey}. - */ - getKey(key) { - return __awaiter(this, void 0, void 0, function* () { - const digest = yield crypto.subtle.digest('SHA-256', WebCryptography.encoder.encode(key)); - const hashHex = Array.from(new Uint8Array(digest)) - .map((b) => b.toString(16).padStart(2, '0')) - .join(''); - const abKey = WebCryptography.encoder.encode(hashHex.slice(0, 32)).buffer; - return crypto.subtle.importKey('raw', abKey, 'AES-CBC', true, ['encrypt', 'decrypt']); - }); - } - /** - * Join two `ArrayBuffer`s. - * - * @param ab1 - `ArrayBuffer` to which other buffer should be appended. - * @param ab2 - `ArrayBuffer` which should appended to the other buffer. - * - * @returns Buffer which starts with `ab1` elements and appended `ab2`. - */ - concatArrayBuffer(ab1, ab2) { - const tmp = new Uint8Array(ab1.byteLength + ab2.byteLength); - tmp.set(new Uint8Array(ab1), 0); - tmp.set(new Uint8Array(ab2), ab1.byteLength); - return tmp.buffer; - } - } - /** - * Random initialization vector size. - */ - WebCryptography.IV_LENGTH = 16; - /** - * {@link string|String} to {@link ArrayBuffer} response decoder. - */ - WebCryptography.encoder = new TextEncoder(); - /** - * {@link ArrayBuffer} to {@link string} decoder. - */ - WebCryptography.decoder = new TextDecoder(); - - /** - * Legacy cryptor module. - */ - /** - * Legacy cryptor. - */ - class LegacyCryptor { - constructor(config) { - this.config = config; - this.cryptor = new Crypto(Object.assign({}, config)); - this.fileCryptor = new WebCryptography(); - } - /** - * Update registered loggers' manager. - * - * @param [logger] - Logger, which crypto should use. - */ - set logger(logger) { - this.cryptor.logger = logger; - if (this.config.useRandomIVs === false) { - logger.warn('LegacyCryptor', `Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients. - Do not disable random IVs in new applications.`); - } - } - // -------------------------------------------------------- - // --------------------- Encryption ----------------------- - // -------------------------------------------------------- - // region Encryption - encrypt(data) { - const stringData = typeof data === 'string' ? data : LegacyCryptor.decoder.decode(data); - return { - data: this.cryptor.encrypt(stringData), - metadata: null, - }; - } - encryptFile(file, File) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - if (!this.config.cipherKey) - throw new PubNubError('File encryption error: cipher key not set.'); - return this.fileCryptor.encryptFile((_a = this.config) === null || _a === void 0 ? void 0 : _a.cipherKey, file, File); - }); - } - // endregion - // -------------------------------------------------------- - // --------------------- Decryption ----------------------- - // -------------------------------------------------------- - // region Decryption - decrypt(encryptedData) { - const data = typeof encryptedData.data === 'string' ? encryptedData.data : encode(encryptedData.data); - return this.cryptor.decrypt(data); - } - decryptFile(file, File) { - return __awaiter(this, void 0, void 0, function* () { - if (!this.config.cipherKey) - throw new PubNubError('File encryption error: cipher key not set.'); - return this.fileCryptor.decryptFile(this.config.cipherKey, file, File); - }); - } - // endregion - // -------------------------------------------------------- - // ----------------------- Helpers ------------------------ - // -------------------------------------------------------- - // region Helpers - get identifier() { - return ''; - } - // endregion - /** - * Serialize cryptor information to string. - * - * @returns Serialized cryptor information. - */ - toString() { - const configurationEntries = Object.entries(this.config).reduce((acc, [key, value]) => { - if (key === 'logger' || isSensitiveLogKey(key)) - return acc; - acc.push(`${key}: ${typeof value === 'function' ? '' : value}`); - return acc; - }, []); - return `LegacyCryptor { ${configurationEntries.join(', ')} }`; - } - } - /** - * `string` to {@link ArrayBuffer} response decoder. - */ - LegacyCryptor.encoder = new TextEncoder(); - /** - * {@link ArrayBuffer} to {@link string} decoder. - */ - LegacyCryptor.decoder = new TextDecoder(); - - /** - * Browser crypto module. - */ - /** - * CryptoModule for browser platform. - */ - class WebCryptoModule extends AbstractCryptoModule { - /** - * Assign registered loggers' manager. - * - * @param logger - Registered loggers' manager. - * - * @internal - */ - set logger(logger) { - if (this.defaultCryptor.identifier === WebCryptoModule.LEGACY_IDENTIFIER) { - logger.warn('CryptoModule', "'legacyCryptoModule' is deprecated. Use 'aesCbcCryptoModule' instead for new applications."); - this.defaultCryptor.logger = logger; - } - else { - const cryptor = this.cryptors.find((cryptor) => cryptor.identifier === WebCryptoModule.LEGACY_IDENTIFIER); - if (cryptor) - cryptor.logger = logger; - } - } - // -------------------------------------------------------- - // --------------- Convenience functions ------------------ - // ------------------------------------------------------- - // region Convenience functions - /** - * Construct crypto module with legacy cryptor for encryption and both legacy and AES-CBC - * cryptors for decryption. - * - * @deprecated Use {@link aesCbcCryptoModule} for new applications. - */ - static legacyCryptoModule(config) { - var _a; - if (!config.cipherKey) - throw new PubNubError('Crypto module error: cipher key not set.'); - if (config.logger) { - config.logger.warn('CryptoModule', "'legacyCryptoModule' is deprecated. Use 'aesCbcCryptoModule' instead for new applications."); - if (config.useRandomIVs === false) { - config.logger.warn('CryptoModule', `Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients. - Do not disable random IVs in new applications.`); - } - } - return new WebCryptoModule({ - default: new LegacyCryptor(Object.assign(Object.assign({}, config), { useRandomIVs: (_a = config.useRandomIVs) !== null && _a !== void 0 ? _a : true })), - cryptors: [new AesCbcCryptor({ cipherKey: config.cipherKey })], - }); - } - static aesCbcCryptoModule(config) { - var _a; - if (!config.cipherKey) - throw new PubNubError('Crypto module error: cipher key not set.'); - return new WebCryptoModule({ - default: new AesCbcCryptor({ cipherKey: config.cipherKey }), - cryptors: [ - new LegacyCryptor(Object.assign(Object.assign({}, config), { useRandomIVs: (_a = config.useRandomIVs) !== null && _a !== void 0 ? _a : true })), - ], - }); - } - /** - * Construct crypto module with `cryptor` as default for data encryption and decryption. - * - * @param defaultCryptor - Default cryptor for data encryption and decryption. - * - * @returns Crypto module with pre-configured default cryptor. - */ - static withDefaultCryptor(defaultCryptor) { - return new this({ default: defaultCryptor }); - } - // endregion - // -------------------------------------------------------- - // --------------------- Encryption ----------------------- - // -------------------------------------------------------- - // region Encryption - encrypt(data) { - // Encrypt data. - const encrypted = data instanceof ArrayBuffer && this.defaultCryptor.identifier === WebCryptoModule.LEGACY_IDENTIFIER - ? this.defaultCryptor.encrypt(WebCryptoModule.decoder.decode(data)) - : this.defaultCryptor.encrypt(data); - if (!encrypted.metadata) - return encrypted.data; - else if (typeof encrypted.data === 'string') - throw new Error('Encryption error: encrypted data should be ArrayBuffed.'); - const headerData = this.getHeaderData(encrypted); - return this.concatArrayBuffer(headerData, encrypted.data); - } - encryptFile(file, File) { - return __awaiter(this, void 0, void 0, function* () { - /** - * Files handled differently in case of Legacy cryptor. - * (as long as we support legacy need to check on instance type) - */ - if (this.defaultCryptor.identifier === CryptorHeader.LEGACY_IDENTIFIER) - return this.defaultCryptor.encryptFile(file, File); - const fileData = yield this.getFileData(file); - const encrypted = yield this.defaultCryptor.encryptFileData(fileData); - if (typeof encrypted.data === 'string') - throw new Error('Encryption error: encrypted data should be ArrayBuffed.'); - return File.create({ - name: file.name, - mimeType: 'application/octet-stream', - data: this.concatArrayBuffer(this.getHeaderData(encrypted), encrypted.data), - }); - }); - } - // endregion - // -------------------------------------------------------- - // --------------------- Decryption ----------------------- - // -------------------------------------------------------- - // region Decryption - decrypt(data) { - const encryptedData = typeof data === 'string' ? decode(data) : data; - const header = CryptorHeader.tryParse(encryptedData); - const cryptor = this.getCryptor(header); - const metadata = header.length > 0 - ? encryptedData.slice(header.length - header.metadataLength, header.length) - : null; - if (encryptedData.slice(header.length).byteLength <= 0) - throw new Error('Decryption error: empty content'); - return cryptor.decrypt({ - data: encryptedData.slice(header.length), - metadata: metadata, - }); - } - decryptFile(file, File) { - return __awaiter(this, void 0, void 0, function* () { - const data = yield file.data.arrayBuffer(); - const header = CryptorHeader.tryParse(data); - const cryptor = this.getCryptor(header); - /** - * Files handled differently in case of Legacy cryptor. - * (as long as we support legacy need to check on instance type) - */ - if ((cryptor === null || cryptor === void 0 ? void 0 : cryptor.identifier) === CryptorHeader.LEGACY_IDENTIFIER) - return cryptor.decryptFile(file, File); - const fileData = yield this.getFileData(data); - const metadata = fileData.slice(header.length - header.metadataLength, header.length); - return File.create({ - name: file.name, - data: yield this.defaultCryptor.decryptFileData({ - data: data.slice(header.length), - metadata: metadata, - }), - }); - }); - } - // endregion - // -------------------------------------------------------- - // ----------------------- Helpers ------------------------ - // -------------------------------------------------------- - // region Helpers - /** - * Retrieve registered cryptor by its identifier. - * - * @param id - Unique cryptor identifier. - * - * @returns Registered cryptor with specified identifier. - * - * @throws Error if cryptor with specified {@link id} can't be found. - */ - getCryptorFromId(id) { - const cryptor = this.getAllCryptors().find((cryptor) => id === cryptor.identifier); - if (cryptor) - return cryptor; - throw Error('Unknown cryptor error'); - } - /** - * Retrieve cryptor by its identifier. - * - * @param header - Header with cryptor-defined data or raw cryptor identifier. - * - * @returns Cryptor which correspond to provided {@link header}. - */ - getCryptor(header) { - if (typeof header === 'string') { - const cryptor = this.getAllCryptors().find((cryptor) => cryptor.identifier === header); - if (cryptor) - return cryptor; - throw new Error('Unknown cryptor error'); - } - else if (header instanceof CryptorHeaderV1) { - return this.getCryptorFromId(header.identifier); - } - } - /** - * Create cryptor header data. - * - * @param encrypted - Encryption data object as source for header data. - * - * @returns Binary representation of the cryptor header data. - */ - getHeaderData(encrypted) { - if (!encrypted.metadata) - return; - const header = CryptorHeader.from(this.defaultCryptor.identifier, encrypted.metadata); - const headerData = new Uint8Array(header.length); - let pos = 0; - headerData.set(header.data, pos); - pos += header.length - encrypted.metadata.byteLength; - headerData.set(new Uint8Array(encrypted.metadata), pos); - return headerData.buffer; - } - /** - * Merge two {@link ArrayBuffer} instances. - * - * @param ab1 - First {@link ArrayBuffer}. - * @param ab2 - Second {@link ArrayBuffer}. - * - * @returns Merged data as {@link ArrayBuffer}. - */ - concatArrayBuffer(ab1, ab2) { - const tmp = new Uint8Array(ab1.byteLength + ab2.byteLength); - tmp.set(new Uint8Array(ab1), 0); - tmp.set(new Uint8Array(ab2), ab1.byteLength); - return tmp.buffer; - } - /** - * Retrieve file content. - * - * @param file - Content of the {@link PubNub} File object. - * - * @returns Normalized file {@link data} as {@link ArrayBuffer}; - */ - getFileData(file) { - return __awaiter(this, void 0, void 0, function* () { - if (file instanceof ArrayBuffer) - return file; - else if (file instanceof PubNubFile) - return file.toArrayBuffer(); - throw new Error('Cannot decrypt/encrypt file. In browsers file encrypt/decrypt supported for string, ArrayBuffer or Blob'); - }); - } - } - /** - * {@link LegacyCryptor|Legacy} cryptor identifier. - */ - WebCryptoModule.LEGACY_IDENTIFIER = ''; - /** - * CryptorHeader Utility - */ - class CryptorHeader { - static from(id, metadata) { - if (id === CryptorHeader.LEGACY_IDENTIFIER) - return; - return new CryptorHeaderV1(id, metadata.byteLength); - } - static tryParse(data) { - const encryptedData = new Uint8Array(data); - let sentinel; - let version = null; - if (encryptedData.byteLength >= 4) { - sentinel = encryptedData.slice(0, 4); - if (this.decoder.decode(sentinel) !== CryptorHeader.SENTINEL) - return WebCryptoModule.LEGACY_IDENTIFIER; - } - if (encryptedData.byteLength >= 5) - version = encryptedData[4]; - else - throw new Error('Decryption error: invalid header version'); - if (version > CryptorHeader.MAX_VERSION) - throw new Error('Decryption error: Unknown cryptor error'); - let identifier; - let pos = 5 + CryptorHeader.IDENTIFIER_LENGTH; - if (encryptedData.byteLength >= pos) - identifier = encryptedData.slice(5, pos); - else - throw new Error('Decryption error: invalid crypto identifier'); - let metadataLength = null; - if (encryptedData.byteLength >= pos + 1) - metadataLength = encryptedData[pos]; - else - throw new Error('Decryption error: invalid metadata length'); - pos += 1; - if (metadataLength === 255 && encryptedData.byteLength >= pos + 2) { - metadataLength = new Uint16Array(encryptedData.slice(pos, pos + 2)).reduce((acc, val) => (acc << 8) + val, 0); - } - return new CryptorHeaderV1(this.decoder.decode(identifier), metadataLength); - } - } - CryptorHeader.SENTINEL = 'PNED'; - CryptorHeader.LEGACY_IDENTIFIER = ''; - CryptorHeader.IDENTIFIER_LENGTH = 4; - CryptorHeader.VERSION = 1; - CryptorHeader.MAX_VERSION = 1; - CryptorHeader.decoder = new TextDecoder(); - // v1 CryptorHeader - class CryptorHeaderV1 { - constructor(id, metadataLength) { - this._identifier = id; - this._metadataLength = metadataLength; - } - get identifier() { - return this._identifier; - } - set identifier(value) { - this._identifier = value; - } - get metadataLength() { - return this._metadataLength; - } - set metadataLength(value) { - this._metadataLength = value; - } - get version() { - return CryptorHeader.VERSION; - } - get length() { - return (CryptorHeader.SENTINEL.length + - 1 + - CryptorHeader.IDENTIFIER_LENGTH + - (this.metadataLength < 255 ? 1 : 3) + - this.metadataLength); - } - get data() { - let pos = 0; - const header = new Uint8Array(this.length); - const encoder = new TextEncoder(); - header.set(encoder.encode(CryptorHeader.SENTINEL)); - pos += CryptorHeader.SENTINEL.length; - header[pos] = this.version; - pos++; - if (this.identifier) - header.set(encoder.encode(this.identifier), pos); - const metadataLength = this.metadataLength; - pos += CryptorHeader.IDENTIFIER_LENGTH; - if (metadataLength < 255) - header[pos] = metadataLength; - else - header.set([255, metadataLength >> 8, metadataLength & 0xff], pos); - return header; - } - } - CryptorHeaderV1.IDENTIFIER_LENGTH = 4; - CryptorHeaderV1.SENTINEL = 'PNED'; - - /** - * REST API endpoint use error module. - * - * @internal - */ - /** - * PubNub REST API call error. - * - * @internal - */ - class PubNubAPIError extends Error { - /** - * Construct API from known error object or {@link PubNub} service error response. - * - * @param errorOrResponse - `Error` or service error response object from which error information - * should be extracted. - * @param [data] - Preprocessed service error response. - * - * @returns `PubNubAPIError` object with known error category and additional information (if - * available). - */ - static create(errorOrResponse, data) { - if (PubNubAPIError.isErrorObject(errorOrResponse)) - return PubNubAPIError.createFromError(errorOrResponse); - else - return PubNubAPIError.createFromServiceResponse(errorOrResponse, data); - } - /** - * Create API error instance from other error object. - * - * @param error - `Error` object provided by network provider (mostly) or other {@link PubNub} client components. - * - * @returns `PubNubAPIError` object with known error category and additional information (if - * available). - */ - static createFromError(error) { - let category = StatusCategory$1.PNUnknownCategory; - let message = 'Unknown error'; - let errorName = 'Error'; - if (!error) - return new PubNubAPIError(message, category, 0); - else if (error instanceof PubNubAPIError) - return error; - if (PubNubAPIError.isErrorObject(error)) { - message = error.message; - errorName = error.name; - } - if (errorName === 'AbortError' || message.indexOf('Aborted') !== -1) { - category = StatusCategory$1.PNCancelledCategory; - message = 'Request cancelled'; - } - else if (message.toLowerCase().indexOf('timeout') !== -1) { - category = StatusCategory$1.PNTimeoutCategory; - message = 'Request timeout'; - } - else if (message.toLowerCase().indexOf('network') !== -1) { - category = StatusCategory$1.PNNetworkIssuesCategory; - message = 'Network issues'; - } - else if (errorName === 'TypeError') { - if (message.indexOf('Load failed') !== -1 || message.indexOf('Failed to fetch') != -1) - category = StatusCategory$1.PNNetworkIssuesCategory; - else - category = StatusCategory$1.PNBadRequestCategory; - } - else if (errorName === 'FetchError') { - const errorCode = error.code; - if (['ECONNREFUSED', 'ENETUNREACH', 'ENOTFOUND', 'ECONNRESET', 'EAI_AGAIN'].includes(errorCode)) - category = StatusCategory$1.PNNetworkIssuesCategory; - if (errorCode === 'ECONNREFUSED') - message = 'Connection refused'; - else if (errorCode === 'ENETUNREACH') - message = 'Network not reachable'; - else if (errorCode === 'ENOTFOUND') - message = 'Server not found'; - else if (errorCode === 'ECONNRESET') - message = 'Connection reset by peer'; - else if (errorCode === 'EAI_AGAIN') - message = 'Name resolution error'; - else if (errorCode === 'ETIMEDOUT') { - category = StatusCategory$1.PNTimeoutCategory; - message = 'Request timeout'; - } - else - message = `Unknown system error: ${error}`; - } - else if (message === 'Request timeout') - category = StatusCategory$1.PNTimeoutCategory; - return new PubNubAPIError(message, category, 0, error); - } - /** - * Construct API from known {@link PubNub} service error response. - * - * @param response - Service error response object from which error information should be - * extracted. - * @param [data] - Preprocessed service error response. - * - * @returns `PubNubAPIError` object with known error category and additional information (if - * available). - */ - static createFromServiceResponse(response, data) { - let category = StatusCategory$1.PNUnknownCategory; - let errorData; - let message = 'Unknown error'; - let { status } = response; - data !== null && data !== void 0 ? data : (data = response.body); - if (status === 402) - message = 'Not available for used key set. Contact support@pubnub.com'; - else if (status === 404) - message = 'Resource not found'; - else if (status === 400) { - category = StatusCategory$1.PNBadRequestCategory; - message = 'Bad request'; - } - else if (status === 403) { - category = StatusCategory$1.PNAccessDeniedCategory; - message = 'Access denied'; - } - else if (status >= 500) { - category = StatusCategory$1.PNServerErrorCategory; - message = 'Internal server error'; - } - if (typeof response === 'object' && Object.keys(response).length === 0) { - category = StatusCategory$1.PNMalformedResponseCategory; - message = 'Malformed response (network issues)'; - status = 400; - } - // Try to get more information about error from service response. - if (data && data.byteLength > 0) { - const decoded = new TextDecoder().decode(data); - if (response.headers['content-type'].indexOf('text/javascript') !== -1 || - response.headers['content-type'].indexOf('application/json') !== -1) { - try { - const errorResponse = JSON.parse(decoded); - if (typeof errorResponse === 'object') { - if (!Array.isArray(errorResponse)) { - if ('error' in errorResponse && - (errorResponse.error === 1 || errorResponse.error === true) && - 'status' in errorResponse && - typeof errorResponse.status === 'number' && - 'message' in errorResponse && - 'service' in errorResponse) { - errorData = errorResponse; - status = errorResponse.status; - } - else - errorData = errorResponse; - if ('error' in errorResponse && errorResponse.error instanceof Error) - errorData = errorResponse.error; - } - else { - // Handling Publish API payload error. - if (typeof errorResponse[0] === 'number' && errorResponse[0] === 0) { - if (errorResponse.length > 1 && typeof errorResponse[1] === 'string') - errorData = errorResponse[1]; - } - } - } - } - catch (_) { - errorData = decoded; - } - } - else if (response.headers['content-type'].indexOf('xml') !== -1) { - const reason = /(.*)<\/Message>/gi.exec(decoded); - message = reason ? `Upload to bucket failed: ${reason[1]}` : 'Upload to bucket failed.'; - } - else { - errorData = decoded; - } - } - return new PubNubAPIError(message, category, status, errorData); - } - /** - * Construct PubNub endpoint error. - * - * @param message - Short API call error description. - * @param category - Error category. - * @param statusCode - Response HTTP status code. - * @param [errorData] - Error information. - */ - constructor(message, category, statusCode, errorData) { - super(message); - this.category = category; - this.statusCode = statusCode; - this.errorData = errorData; - this.name = 'PubNubAPIError'; - } - /** - * Convert API error object to API callback status object. - * - * @param operation - Request operation during which error happened. - * - * @returns Pre-formatted API callback status object. - */ - toStatus(operation) { - return { - error: true, - category: this.category, - operation, - statusCode: this.statusCode, - errorData: this.errorData, - // @ts-expect-error Inner helper for JSON.stringify. - toJSON: function () { - let normalizedErrorData; - const errorData = this.errorData; - if (errorData) { - try { - if (typeof errorData === 'object') { - const errorObject = Object.assign(Object.assign(Object.assign(Object.assign({}, ('name' in errorData ? { name: errorData.name } : {})), ('message' in errorData ? { message: errorData.message } : {})), ('stack' in errorData ? { stack: errorData.stack } : {})), errorData); - normalizedErrorData = JSON.parse(JSON.stringify(errorObject, PubNubAPIError.circularReplacer())); - } - else - normalizedErrorData = errorData; - } - catch (_) { - normalizedErrorData = { error: 'Could not serialize the error object' }; - } - } - // Make sure to exclude `toJSON` function from the final object. - const _a = this, status = __rest(_a, ["toJSON"]); - return JSON.stringify(Object.assign(Object.assign({}, status), { errorData: normalizedErrorData })); - }, - }; - } - /** - * Convert API error object to PubNub client error object. - * - * @param operation - Request operation during which error happened. - * @param [message] - Custom error message. - * - * @returns Client-facing pre-formatted endpoint call error. - */ - toPubNubError(operation, message) { - return new PubNubError(message !== null && message !== void 0 ? message : this.message, this.toStatus(operation)); - } - /** - * Function which handles circular references in serialized JSON. - * - * @returns Circular reference replacer function. - * - * @internal - */ - static circularReplacer() { - const visited = new WeakSet(); - return function (_, value) { - if (typeof value === 'object' && value !== null) { - if (visited.has(value)) - return '[Circular]'; - visited.add(value); - } - return value; - }; - } - /** - * Check whether provided `object` is an `Error` or not. - * - * This check is required because the error object may be tied to a different execution context (global - * environment) and won't pass `instanceof Error` from the main window. - * To protect against monkey-patching, the `fetch` function is taken from an invisible `iframe` and, as a result, - * it is bind to the separate execution context. Errors generated by `fetch` won't pass the simple - * `instanceof Error` test. - * - * @param object - Object which should be checked. - * - * @returns `true` if `object` looks like an `Error` object. - * - * @internal - */ - static isErrorObject(object) { - if (!object || typeof object !== 'object') - return false; - if (object instanceof Error) - return true; - if ('name' in object && - 'message' in object && - typeof object.name === 'string' && - typeof object.message === 'string') { - return true; - } - return Object.prototype.toString.call(object) === '[object Error]'; - } - } - - /** - * Endpoint API operation types. - */ - var RequestOperation; - (function (RequestOperation) { - // -------------------------------------------------------- - // ---------------------- Publish API --------------------- - // -------------------------------------------------------- - /** - * Data publish REST API operation. - */ - RequestOperation["PNPublishOperation"] = "PNPublishOperation"; - /** - * Signal sending REST API operation. - */ - RequestOperation["PNSignalOperation"] = "PNSignalOperation"; - // -------------------------------------------------------- - // --------------------- Subscribe API -------------------- - // -------------------------------------------------------- - /** - * Subscribe for real-time updates REST API operation. - * - * User's presence change on specified entities will trigger `join` event. - */ - RequestOperation["PNSubscribeOperation"] = "PNSubscribeOperation"; - /** - * Unsubscribe from real-time updates REST API operation. - * - * User's presence change on specified entities will trigger `leave` event. - */ - RequestOperation["PNUnsubscribeOperation"] = "PNUnsubscribeOperation"; - // -------------------------------------------------------- - // --------------------- Presence API --------------------- - // -------------------------------------------------------- - /** - * Fetch user's presence information REST API operation. - */ - RequestOperation["PNWhereNowOperation"] = "PNWhereNowOperation"; - /** - * Fetch channel's presence information REST API operation. - */ - RequestOperation["PNHereNowOperation"] = "PNHereNowOperation"; - /** - * Fetch global presence information REST API operation. - */ - RequestOperation["PNGlobalHereNowOperation"] = "PNGlobalHereNowOperation"; - /** - * Update user's information associated with specified channel REST API operation. - */ - RequestOperation["PNSetStateOperation"] = "PNSetStateOperation"; - /** - * Fetch user's information associated with the specified channel REST API operation. - */ - RequestOperation["PNGetStateOperation"] = "PNGetStateOperation"; - /** - * Announce presence on managed channels REST API operation. - */ - RequestOperation["PNHeartbeatOperation"] = "PNHeartbeatOperation"; - // -------------------------------------------------------- - // ----------------- Message Reaction API ----------------- - // -------------------------------------------------------- - /** - * Add a reaction to the specified message REST API operation. - */ - RequestOperation["PNAddMessageActionOperation"] = "PNAddActionOperation"; - /** - * Remove reaction from the specified message REST API operation. - */ - RequestOperation["PNRemoveMessageActionOperation"] = "PNRemoveMessageActionOperation"; - /** - * Fetch reactions for specific message REST API operation. - */ - RequestOperation["PNGetMessageActionsOperation"] = "PNGetMessageActionsOperation"; - RequestOperation["PNTimeOperation"] = "PNTimeOperation"; - // -------------------------------------------------------- - // ---------------------- Storage API --------------------- - // -------------------------------------------------------- - /** - * Channel history REST API operation. - */ - RequestOperation["PNHistoryOperation"] = "PNHistoryOperation"; - /** - * Delete messages from channel history REST API operation. - */ - RequestOperation["PNDeleteMessagesOperation"] = "PNDeleteMessagesOperation"; - /** - * History for channels REST API operation. - */ - RequestOperation["PNFetchMessagesOperation"] = "PNFetchMessagesOperation"; - /** - * Number of messages for channels in specified time frame REST API operation. - */ - RequestOperation["PNMessageCounts"] = "PNMessageCountsOperation"; - // -------------------------------------------------------- - // -------------------- App Context API ------------------- - // -------------------------------------------------------- - /** - * Fetch users metadata REST API operation. - */ - RequestOperation["PNGetAllUUIDMetadataOperation"] = "PNGetAllUUIDMetadataOperation"; - /** - * Fetch user metadata REST API operation. - */ - RequestOperation["PNGetUUIDMetadataOperation"] = "PNGetUUIDMetadataOperation"; - /** - * Set user metadata REST API operation. - */ - RequestOperation["PNSetUUIDMetadataOperation"] = "PNSetUUIDMetadataOperation"; - /** - * Remove user metadata REST API operation. - */ - RequestOperation["PNRemoveUUIDMetadataOperation"] = "PNRemoveUUIDMetadataOperation"; - /** - * Fetch channels metadata REST API operation. - */ - RequestOperation["PNGetAllChannelMetadataOperation"] = "PNGetAllChannelMetadataOperation"; - /** - * Fetch channel metadata REST API operation. - */ - RequestOperation["PNGetChannelMetadataOperation"] = "PNGetChannelMetadataOperation"; - /** - * Set channel metadata REST API operation. - */ - RequestOperation["PNSetChannelMetadataOperation"] = "PNSetChannelMetadataOperation"; - /** - * Remove channel metadata REST API operation. - */ - RequestOperation["PNRemoveChannelMetadataOperation"] = "PNRemoveChannelMetadataOperation"; - /** - * Fetch channel members REST API operation. - */ - RequestOperation["PNGetMembersOperation"] = "PNGetMembersOperation"; - /** - * Update channel members REST API operation. - */ - RequestOperation["PNSetMembersOperation"] = "PNSetMembersOperation"; - /** - * Fetch channel memberships REST API operation. - */ - RequestOperation["PNGetMembershipsOperation"] = "PNGetMembershipsOperation"; - /** - * Update channel memberships REST API operation. - */ - RequestOperation["PNSetMembershipsOperation"] = "PNSetMembershipsOperation"; - // -------------------------------------------------------- - // ------------------- DataSync API ---------------------- - // -------------------------------------------------------- - /** - * Create entity REST API operation. - */ - RequestOperation["PNCreateDataSyncEntityOperation"] = "PNCreateDataSyncEntityOperation"; - /** - * Get entity REST API operation. - */ - RequestOperation["PNGetDataSyncEntityOperation"] = "PNGetDataSyncEntityOperation"; - /** - * Get all entities REST API operation. - */ - RequestOperation["PNGetDataSyncEntitiesOperation"] = "PNGetDataSyncEntitiesOperation"; - /** - * Set entity REST API operation (full replacement via PUT). - */ - RequestOperation["PNSetDataSyncEntityOperation"] = "PNSetDataSyncEntityOperation"; - /** - * Update entity REST API operation (partial update via PATCH). - */ - RequestOperation["PNUpdateDataSyncEntityOperation"] = "PNUpdateDataSyncEntityOperation"; - /** - * Remove entity REST API operation. - */ - RequestOperation["PNRemoveDataSyncEntityOperation"] = "PNRemoveDataSyncEntityOperation"; - /** - * Create relationship REST API operation. - */ - RequestOperation["PNCreateDataSyncRelationshipOperation"] = "PNCreateDataSyncRelationshipOperation"; - /** - * Get relationship REST API operation. - */ - RequestOperation["PNGetDataSyncRelationshipOperation"] = "PNGetDataSyncRelationshipOperation"; - /** - * Get all relationships REST API operation. - */ - RequestOperation["PNGetDataSyncRelationshipsOperation"] = "PNGetDataSyncRelationshipsOperation"; - /** - * Set relationship REST API operation (full replacement via PUT). - */ - RequestOperation["PNSetDataSyncRelationshipOperation"] = "PNSetDataSyncRelationshipOperation"; - /** - * Update relationship REST API operation (partial update via PATCH). - */ - RequestOperation["PNUpdateDataSyncRelationshipOperation"] = "PNUpdateDataSyncRelationshipOperation"; - /** - * Remove relationship REST API operation. - */ - RequestOperation["PNRemoveDataSyncRelationshipOperation"] = "PNRemoveDataSyncRelationshipOperation"; - /** - * Create user REST API operation. - */ - RequestOperation["PNCreateDataSyncUserOperation"] = "PNCreateDataSyncUserOperation"; - /** - * Get user REST API operation. - */ - RequestOperation["PNGetDataSyncUserOperation"] = "PNGetDataSyncUserOperation"; - /** - * Get all users REST API operation. - */ - RequestOperation["PNGetDataSyncUsersOperation"] = "PNGetDataSyncUsersOperation"; - /** - * Set user REST API operation (full replacement via PUT). - */ - RequestOperation["PNSetDataSyncUserOperation"] = "PNSetDataSyncUserOperation"; - /** - * Update user REST API operation (partial update via PATCH). - */ - RequestOperation["PNUpdateDataSyncUserOperation"] = "PNUpdateDataSyncUserOperation"; - /** - * Remove user REST API operation. - */ - RequestOperation["PNRemoveDataSyncUserOperation"] = "PNRemoveDataSyncUserOperation"; - /** - * Create channel REST API operation. - */ - RequestOperation["PNCreateDataSyncChannelOperation"] = "PNCreateDataSyncChannelOperation"; - /** - * Get channel REST API operation. - */ - RequestOperation["PNGetDataSyncChannelOperation"] = "PNGetDataSyncChannelOperation"; - /** - * Get all channels REST API operation. - */ - RequestOperation["PNGetDataSyncChannelsOperation"] = "PNGetDataSyncChannelsOperation"; - /** - * Set channel REST API operation (full replacement via PUT). - */ - RequestOperation["PNSetDataSyncChannelOperation"] = "PNSetDataSyncChannelOperation"; - /** - * Update channel REST API operation (partial update via PATCH). - */ - RequestOperation["PNUpdateDataSyncChannelOperation"] = "PNUpdateDataSyncChannelOperation"; - /** - * Remove channel REST API operation. - */ - RequestOperation["PNRemoveDataSyncChannelOperation"] = "PNRemoveDataSyncChannelOperation"; - /** - * Create membership REST API operation. - */ - RequestOperation["PNCreateDataSyncMembershipOperation"] = "PNCreateDataSyncMembershipOperation"; - /** - * Get membership REST API operation. - */ - RequestOperation["PNGetDataSyncMembershipOperation"] = "PNGetDataSyncMembershipOperation"; - /** - * Get all memberships REST API operation. - */ - RequestOperation["PNGetDataSyncMembershipsOperation"] = "PNGetDataSyncMembershipsOperation"; - /** - * Set membership REST API operation (full replacement via PUT). - */ - RequestOperation["PNSetDataSyncMembershipOperation"] = "PNSetDataSyncMembershipOperation"; - /** - * Update membership REST API operation (partial update via PATCH). - */ - RequestOperation["PNUpdateDataSyncMembershipOperation"] = "PNUpdateDataSyncMembershipOperation"; - /** - * Remove membership REST API operation. - */ - RequestOperation["PNRemoveDataSyncMembershipOperation"] = "PNRemoveDataSyncMembershipOperation"; - // -------------------------------------------------------- - // -------------------- File Upload API ------------------- - // -------------------------------------------------------- - /** - * Fetch list of files sent to the channel REST API operation. - */ - RequestOperation["PNListFilesOperation"] = "PNListFilesOperation"; - /** - * Retrieve file upload URL REST API operation. - */ - RequestOperation["PNGenerateUploadUrlOperation"] = "PNGenerateUploadUrlOperation"; - /** - * Upload file to the channel REST API operation. - */ - RequestOperation["PNPublishFileOperation"] = "PNPublishFileOperation"; - /** - * Publish File Message to the channel REST API operation. - */ - RequestOperation["PNPublishFileMessageOperation"] = "PNPublishFileMessageOperation"; - /** - * Retrieve file download URL REST API operation. - */ - RequestOperation["PNGetFileUrlOperation"] = "PNGetFileUrlOperation"; - /** - * Download file from the channel REST API operation. - */ - RequestOperation["PNDownloadFileOperation"] = "PNDownloadFileOperation"; - /** - * Delete file sent to the channel REST API operation. - */ - RequestOperation["PNDeleteFileOperation"] = "PNDeleteFileOperation"; - // -------------------------------------------------------- - // -------------------- Mobile Push API ------------------- - // -------------------------------------------------------- - /** - * Register channels with device push notifications REST API operation. - */ - RequestOperation["PNAddPushNotificationEnabledChannelsOperation"] = "PNAddPushNotificationEnabledChannelsOperation"; - /** - * Unregister channels with device push notifications REST API operation. - */ - RequestOperation["PNRemovePushNotificationEnabledChannelsOperation"] = "PNRemovePushNotificationEnabledChannelsOperation"; - /** - * Fetch list of channels with enabled push notifications for device REST API operation. - */ - RequestOperation["PNPushNotificationEnabledChannelsOperation"] = "PNPushNotificationEnabledChannelsOperation"; - /** - * Disable push notifications for device REST API operation. - */ - RequestOperation["PNRemoveAllPushNotificationsOperation"] = "PNRemoveAllPushNotificationsOperation"; - // -------------------------------------------------------- - // ------------------ Channel Groups API ------------------ - // -------------------------------------------------------- - /** - * Fetch channels groups list REST API operation. - */ - RequestOperation["PNChannelGroupsOperation"] = "PNChannelGroupsOperation"; - /** - * Remove specified channel group REST API operation. - */ - RequestOperation["PNRemoveGroupOperation"] = "PNRemoveGroupOperation"; - /** - * Fetch list of channels for the specified channel group REST API operation. - */ - RequestOperation["PNChannelsForGroupOperation"] = "PNChannelsForGroupOperation"; - /** - * Add list of channels to the specified channel group REST API operation. - */ - RequestOperation["PNAddChannelsToGroupOperation"] = "PNAddChannelsToGroupOperation"; - /** - * Remove list of channels from the specified channel group REST API operation. - */ - RequestOperation["PNRemoveChannelsFromGroupOperation"] = "PNRemoveChannelsFromGroupOperation"; - // -------------------------------------------------------- - // ----------------------- PAM API ------------------------ - // -------------------------------------------------------- - /** - * Generate authorized token REST API operation. - */ - RequestOperation["PNAccessManagerGrant"] = "PNAccessManagerGrant"; - /** - * Generate authorized token REST API operation. - */ - RequestOperation["PNAccessManagerGrantToken"] = "PNAccessManagerGrantToken"; - RequestOperation["PNAccessManagerAudit"] = "PNAccessManagerAudit"; - /** - * Revoke authorized token REST API operation. - */ - RequestOperation["PNAccessManagerRevokeToken"] = "PNAccessManagerRevokeToken"; - // - // -------------------------------------------------------- - // ---------------- Subscription Utility ------------------ - // -------------------------------------------------------- - /** - * Initial event engine subscription handshake operation. - * - * @internal - */ - RequestOperation["PNHandshakeOperation"] = "PNHandshakeOperation"; - /** - * Event engine subscription loop operation. - * - * @internal - */ - RequestOperation["PNReceiveMessagesOperation"] = "PNReceiveMessagesOperation"; - })(RequestOperation || (RequestOperation = {})); - var RequestOperation$1 = RequestOperation; - - /** - * Subscription Worker transport middleware module. - * - * Middleware optimize subscription feature requests utilizing `Subscription Worker` if available and not disabled - * by user. - * - * @internal - */ - // endregion - /** - * Subscription Worker transport middleware. - */ - class SubscriptionWorkerMiddleware { - constructor(configuration) { - this.configuration = configuration; - /** - * Whether subscription worker has been initialized and ready to handle events. - */ - this.subscriptionWorkerReady = false; - /** - * Map of base64-encoded access tokens to their parsed representations. - */ - this.accessTokensMap = {}; - this.workerEventsQueue = []; - this.callbacks = new Map(); - this.setupSubscriptionWorker(); - } - /** - * Set status emitter from the PubNub client. - * - * @param emitter - Function which should be used to emit events. - */ - set emitStatus(emitter) { - this._emitStatus = emitter; - } - /** - * Update client's `userId`. - * - * @param userId - User ID which will be used by the PubNub client further. - */ - onUserIdChange(userId) { - this.configuration.userId = userId; - this.scheduleEventPost({ - type: 'client-update', - heartbeatInterval: this.configuration.heartbeatInterval, - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - userId: this.configuration.userId, - workerLogLevel: this.configuration.workerLogLevel, - }); - } - /** - * Update presence state associated with `userId`. - * - * @param state - Key-value pair of payloads (states) that should be associated with channels / groups specified as - * keys. - */ - onPresenceStateChange(state) { - this.scheduleEventPost({ - type: 'client-presence-state-update', - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - workerLogLevel: this.configuration.workerLogLevel, - state, - }); - } - /** - * Update client's heartbeat interval change. - * - * @param interval - Interval which should be used by timers for _backup_ heartbeat calls created in `SharedWorker`. - */ - onHeartbeatIntervalChange(interval) { - this.configuration.heartbeatInterval = interval; - this.scheduleEventPost({ - type: 'client-update', - heartbeatInterval: this.configuration.heartbeatInterval, - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - userId: this.configuration.userId, - workerLogLevel: this.configuration.workerLogLevel, - }); - } - /** - * Handle authorization key / token change. - * - * @param [token] - Authorization token which should be used. - */ - onTokenChange(token) { - const updateEvent = { - type: 'client-update', - heartbeatInterval: this.configuration.heartbeatInterval, - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - userId: this.configuration.userId, - workerLogLevel: this.configuration.workerLogLevel, - }; - // Trigger request processing by Service Worker. - this.parsedAccessToken(token) - .then((accessToken) => { - updateEvent.preProcessedToken = accessToken; - updateEvent.accessToken = token; - }) - .then(() => this.scheduleEventPost(updateEvent)); - } - /** - * Disconnect client and terminate ongoing long-poll requests (if needed). - */ - disconnect() { - this.scheduleEventPost({ - type: 'client-disconnect', - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - workerLogLevel: this.configuration.workerLogLevel, - }); - } - /** - * Terminate all ongoing long-poll requests. - */ - terminate() { - this.scheduleEventPost({ - type: 'client-unregister', - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - workerLogLevel: this.configuration.workerLogLevel, - }); - } - makeSendable(req) { - // Use default request flow for non-subscribe / presence leave requests. - if (!req.path.startsWith('/v2/subscribe') && !req.path.endsWith('/heartbeat') && !req.path.endsWith('/leave')) - return this.configuration.transport.makeSendable(req); - this.configuration.logger.debug('SubscriptionWorkerMiddleware', 'Process request with SharedWorker transport.'); - let controller; - const sendRequestEvent = { - type: 'send-request', - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - request: req, - workerLogLevel: this.configuration.workerLogLevel, - }; - if (req.cancellable) { - controller = { - abort: () => { - const cancelRequest = { - type: 'cancel-request', - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - identifier: req.identifier, - workerLogLevel: this.configuration.workerLogLevel, - }; - // Cancel active request with specified identifier. - this.scheduleEventPost(cancelRequest); - }, - }; - } - return [ - new Promise((resolve, reject) => { - // Associate Promise resolution / reject with a request identifier for future usage in - // the `onmessage ` handler block to return results. - this.callbacks.set(req.identifier, { resolve, reject }); - // Trigger request processing by Service Worker. - this.parsedAccessTokenForRequest(req) - .then((accessToken) => (sendRequestEvent.preProcessedToken = accessToken)) - .then(() => this.scheduleEventPost(sendRequestEvent)); - }), - controller, - ]; - } - request(req) { - return req; - } - /** - * Schedule {@link event} publish to the subscription worker. - * - * Subscription worker may not be ready for events processing and this method build queue for the time when worker - * will be ready. - * - * @param event - Event payload for the subscription worker. - * @param outOfOrder - Whether event should be processed first then enqueued queue. - */ - scheduleEventPost(event, outOfOrder = false) { - // Trigger request processing by a subscription worker. - const subscriptionWorker = this.sharedSubscriptionWorker; - if (subscriptionWorker) - subscriptionWorker.port.postMessage(event); - else { - if (outOfOrder) - this.workerEventsQueue.splice(0, 0, event); - else - this.workerEventsQueue.push(event); - } - } - /** - * Dequeue and post events from the queue to the subscription worker. - */ - flushScheduledEvents() { - // Trigger request processing by a subscription worker. - const subscriptionWorker = this.sharedSubscriptionWorker; - if (!subscriptionWorker || this.workerEventsQueue.length === 0) - return; - // Clean up from canceled events. - const outdatedEvents = []; - for (let i = 0; i < this.workerEventsQueue.length; i++) { - const event = this.workerEventsQueue[i]; - // Check whether found request cancel event to search for request send event it cancels. - if (event.type !== 'cancel-request' || i === 0) - continue; - for (let j = 0; j < i; j++) { - const otherEvent = this.workerEventsQueue[j]; - if (otherEvent.type !== 'send-request') - continue; - // Collect outdated events if identifiers match. - if (otherEvent.request.identifier === event.identifier) { - outdatedEvents.push(event, otherEvent); - break; - } - } - } - // Actualizing events queue. - this.workerEventsQueue = this.workerEventsQueue.filter((event) => !outdatedEvents.includes(event)); - this.workerEventsQueue.forEach((event) => subscriptionWorker.port.postMessage(event)); - this.workerEventsQueue = []; - } - /** - * Subscription worker. - * - * @returns Worker which has been registered by the PubNub SDK. - */ - get sharedSubscriptionWorker() { - return this.subscriptionWorkerReady ? this.subscriptionWorker : null; - } - setupSubscriptionWorker() { - if (typeof SharedWorker === 'undefined') - return; - try { - this.subscriptionWorker = new SharedWorker(this.configuration.workerUrl, `/pubnub-${this.configuration.sdkVersion}`); - } - catch (error) { - this.configuration.logger.error('SubscriptionWorkerMiddleware', () => ({ - messageType: 'error', - message: error, - })); - throw error; - } - this.subscriptionWorker.port.start(); - // Register PubNub client within subscription worker. - this.scheduleEventPost({ - type: 'client-register', - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - userId: this.configuration.userId, - heartbeatInterval: this.configuration.heartbeatInterval, - workerOfflineClientsCheckInterval: this.configuration.workerOfflineClientsCheckInterval, - workerUnsubscribeOfflineClients: this.configuration.workerUnsubscribeOfflineClients, - workerLogLevel: this.configuration.workerLogLevel, - }, true); - this.subscriptionWorker.port.onmessage = (event) => this.handleWorkerEvent(event); - if (this.shouldAnnounceNewerSharedWorkerVersionAvailability()) - localStorage.setItem('PNSubscriptionSharedWorkerVersion', this.configuration.sdkVersion); - window.addEventListener('storage', (event) => { - if (event.key !== 'PNSubscriptionSharedWorkerVersion' || !event.newValue) - return; - if (this._emitStatus && this.isNewerSharedWorkerVersion(event.newValue)) - this._emitStatus({ error: false, category: StatusCategory$1.PNSharedWorkerUpdatedCategory }); - }); - } - handleWorkerEvent(event) { - const { data } = event; - // Ignoring updates not related to this instance. - if (data.type !== 'shared-worker-ping' && - data.type !== 'shared-worker-connected' && - data.type !== 'shared-worker-console-log' && - data.type !== 'shared-worker-console-dir' && - data.clientIdentifier !== this.configuration.clientIdentifier) - return; - if (data.type === 'shared-worker-connected') { - this.configuration.logger.trace('SharedWorker', 'Ready for events processing.'); - this.subscriptionWorkerReady = true; - this.flushScheduledEvents(); - } - else if (data.type === 'shared-worker-console-log') { - this.configuration.logger.debug('SharedWorker', () => { - if (typeof data.message === 'string' || typeof data.message === 'number' || typeof data.message === 'boolean') { - return { - messageType: 'text', - message: data.message, - }; - } - return data.message; - }); - } - else if (data.type === 'shared-worker-console-dir') { - this.configuration.logger.debug('SharedWorker', () => { - return { - messageType: 'object', - message: data.data, - details: data.message ? data.message : undefined, - }; - }); - } - else if (data.type === 'shared-worker-ping') { - const { subscriptionKey, clientIdentifier } = this.configuration; - this.scheduleEventPost({ - type: 'client-pong', - subscriptionKey, - clientIdentifier, - workerLogLevel: this.configuration.workerLogLevel, - }); - } - else if (data.type === 'request-process-success' || data.type === 'request-process-error') { - if (this.callbacks.has(data.identifier)) { - const { resolve, reject } = this.callbacks.get(data.identifier); - this.callbacks.delete(data.identifier); - if (data.type === 'request-process-success') { - resolve({ - status: data.response.status, - url: data.url, - headers: data.response.headers, - body: data.response.body, - }); - } - else - reject(this.errorFromRequestSendingError(data)); - } - // Handling "backup" heartbeat which doesn't have registered callbacks. - else if (this._emitStatus && data.url.indexOf('/v2/presence') >= 0 && data.url.indexOf('/heartbeat') >= 0) { - if (data.type === 'request-process-success' && this.configuration.announceSuccessfulHeartbeats) { - this._emitStatus({ - statusCode: data.response.status, - error: false, - operation: RequestOperation$1.PNHeartbeatOperation, - category: StatusCategory$1.PNAcknowledgmentCategory, - }); - } - else if (data.type === 'request-process-error' && this.configuration.announceFailedHeartbeats) - this._emitStatus(this.errorFromRequestSendingError(data).toStatus(RequestOperation$1.PNHeartbeatOperation)); - } - } - } - /** - * Get parsed access token object from request. - * - * @param req - Transport request which may contain access token for processing. - * - * @returns Object with stringified access token information and expiration date information. - */ - parsedAccessTokenForRequest(req) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - return this.parsedAccessToken(req.queryParameters ? ((_a = req.queryParameters.auth) !== null && _a !== void 0 ? _a : '') : undefined); - }); - } - /** - * Get parsed access token object. - * - * @param accessToken - Access token for processing. - * - * @returns Object with stringified access token information and expiration date information. - */ - parsedAccessToken(accessToken) { - return __awaiter(this, void 0, void 0, function* () { - if (!accessToken) - return undefined; - else if (this.accessTokensMap[accessToken]) - return this.accessTokensMap[accessToken]; - return this.stringifyAccessToken(accessToken).then(([token, stringifiedToken]) => { - if (!token || !stringifiedToken) - return undefined; - return (this.accessTokensMap = { - [accessToken]: { token: stringifiedToken, expiration: token.timestamp + token.ttl * 60 }, - })[accessToken]; - }); - }); - } - /** - * Stringify access token content. - * - * Stringify information about resources with permissions. - * - * @param tokenString - Base64-encoded access token which should be parsed and stringified. - * - * @returns Tuple with parsed access token and its stringified content hash string. - */ - stringifyAccessToken(tokenString) { - return __awaiter(this, void 0, void 0, function* () { - if (!this.configuration.tokenManager) - return [undefined, undefined]; - const token = this.configuration.tokenManager.parseToken(tokenString); - if (!token) - return [undefined, undefined]; - // Translate permission to short string built from first chars of enabled permission. - const stringifyPermissions = (permission) => Object.entries(permission) - .filter(([_, v]) => v) - .map(([k]) => k[0]) - .sort() - .join(''); - const stringifyResources = (resource) => resource - ? Object.entries(resource) - .sort(([a], [b]) => a.localeCompare(b)) - .map(([type, entries]) => Object.entries(entries || {}) - .sort(([a], [b]) => a.localeCompare(b)) - .map(([name, perms]) => `${type}:${name}=${perms ? stringifyPermissions(perms) : ''}`) - .join(',')) - .join(';') - : ''; - let accessToken = [stringifyResources(token.resources), stringifyResources(token.patterns), token.authorized_uuid] - .filter(Boolean) - .join('|'); - if (typeof crypto !== 'undefined' && crypto.subtle) { - const hash = yield crypto.subtle.digest('SHA-256', new TextEncoder().encode(accessToken)); - accessToken = String.fromCharCode(...Array.from(new Uint8Array(hash))); - } - return [token, typeof btoa !== 'undefined' ? btoa(accessToken) : accessToken]; - }); - } - /** - * Create error from failure received from the `SharedWorker`. - * - * @param sendingError - Request sending error received from the `SharedWorker`. - * - * @returns `PubNubAPIError` instance with request processing failure information. - */ - errorFromRequestSendingError(sendingError) { - let category = StatusCategory$1.PNUnknownCategory; - let message = 'Unknown error'; - // Handle client-side issues (if any). - if (sendingError.error) { - if (sendingError.error.type === 'NETWORK_ISSUE') - category = StatusCategory$1.PNNetworkIssuesCategory; - else if (sendingError.error.type === 'TIMEOUT') - category = StatusCategory$1.PNTimeoutCategory; - else if (sendingError.error.type === 'ABORTED') - category = StatusCategory$1.PNCancelledCategory; - message = `${sendingError.error.message} (${sendingError.identifier})`; - } - // Handle service error response. - else if (sendingError.response) { - const { url, response } = sendingError; - return PubNubAPIError.create({ url, headers: response.headers, body: response.body, status: response.status }, response.body); - } - return new PubNubAPIError(message, category, 0, new Error(message)); - } - /** - * Check whether current subscription `SharedWorker` version should be announced or not. - * - * @returns `true` if local storage is empty (only newer version will add value) or stored version is smaller than - * current. - */ - shouldAnnounceNewerSharedWorkerVersionAvailability() { - const version = localStorage.getItem('PNSubscriptionSharedWorkerVersion'); - if (!version) - return true; - return !this.isNewerSharedWorkerVersion(version); - } - /** - * Check whether current subscription `SharedWorker` version should be announced or not. - * - * @param version - Stored (received on init or event) version of subscription shared worker. - * @returns `true` if provided `version` is newer than current client version. - */ - isNewerSharedWorkerVersion(version) { - const [currentMajor, currentMinor, currentPatch] = this.configuration.sdkVersion.split('.').map(Number); - const [storedMajor, storedMinor, storedPatch] = version.split('.').map(Number); - return storedMajor > currentMajor || storedMinor > currentMinor || storedPatch > currentPatch; - } - } - - /** - * CBOR support module. - * - * @internal - */ - /** - * Re-map CBOR object keys from potentially C buffer strings to actual strings. - * - * @param obj CBOR which should be remapped to stringified keys. - * @param nestingLevel PAM token structure nesting level. - * - * @returns Dictionary with stringified keys. - * - * @internal - */ - function stringifyBufferKeys(obj, nestingLevel = 0) { - const isObject = (value) => typeof value === 'object' && value !== null && value.constructor === Object; - const isString = (value) => typeof value === 'string' || value instanceof String; - const isNumber = (value) => typeof value === 'number' && isFinite(value); - if (!isObject(obj)) - return obj; - const normalizedObject = {}; - Object.keys(obj).forEach((key) => { - const keyIsString = isString(key); - let stringifiedKey = key; - const value = obj[key]; - if (nestingLevel < 2) { - if (keyIsString && key.indexOf(',') >= 0) { - const bytes = key.split(',').map(Number); - stringifiedKey = bytes.reduce((string, byte) => { - return string + String.fromCharCode(byte); - }, ''); - } - else if (isNumber(key) || (keyIsString && !isNaN(Number(key)))) { - stringifiedKey = String.fromCharCode(isNumber(key) ? key : parseInt(key, 10)); - } - } - normalizedObject[stringifiedKey] = isObject(value) ? stringifyBufferKeys(value, nestingLevel + 1) : value; - }); - return normalizedObject; - } - - /** - * {@link PubNub} client configuration module. - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether secured connection should be used by or not. - */ - const USE_SSL = true; - /** - * Whether PubNub client should catch up subscription after network issues. - */ - const RESTORE = true; - /** - * Whether network availability change should be announced with `PNNetworkDownCategory` and - * `PNNetworkUpCategory` state or not. - */ - const AUTO_NETWORK_DETECTION = false; - /** - * Whether messages should be de-duplicated before announcement or not. - */ - const DEDUPE_ON_SUBSCRIBE = false; - /** - * Maximum cache which should be used for message de-duplication functionality. - */ - const DEDUPE_CACHE_SIZE = 100; - /** - * Maximum number of file message publish retries. - */ - const FILE_PUBLISH_RETRY_LIMIT = 5; - /** - * Whether subscription event engine should be used or not. - */ - const ENABLE_EVENT_ENGINE = true; - /** - * Whether configured user presence state should be maintained by the PubNub client or not. - */ - const MAINTAIN_PRESENCE_STATE = true; - /** - * Whether heartbeat should be postponed on successful subscribe response or not. - */ - const USE_SMART_HEARTBEAT = false; - /** - * Whether PubNub client should try to utilize existing TCP connection for new requests or not. - */ - const KEEP_ALIVE$1 = false; - /** - * Whether leave events should be suppressed or not. - */ - const SUPPRESS_LEAVE_EVENTS = false; - /** - * Whether heartbeat request failure should be announced or not. - */ - const ANNOUNCE_HEARTBEAT_FAILURE = true; - /** - * Whether heartbeat request success should be announced or not. - */ - const ANNOUNCE_HEARTBEAT_SUCCESS = false; - /** - * Whether PubNub client instance id should be added to the requests or not. - */ - const USE_INSTANCE_ID = false; - /** - * Whether unique identifier should be added to the request or not. - */ - const USE_REQUEST_ID = true; - /** - * Transactional requests timeout. - */ - const TRANSACTIONAL_REQUEST_TIMEOUT = 15; - /** - * Subscription request timeout. - */ - const SUBSCRIBE_REQUEST_TIMEOUT = 310; - /** - * File upload / download request timeout. - */ - const FILE_REQUEST_TIMEOUT = 300; - /** - * Default user presence timeout. - */ - const PRESENCE_TIMEOUT = 300; - /** - * Maximum user presence timeout. - */ - const PRESENCE_TIMEOUT_MAXIMUM = 320; - /** - * Apply configuration default values. - * - * @param configuration - User-provided configuration. - * - * @internal - */ - const setDefaults$1 = (configuration) => { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; - // Copy configuration. - const configurationCopy = Object.assign({}, configuration); - (_a = configurationCopy.ssl) !== null && _a !== void 0 ? _a : (configurationCopy.ssl = USE_SSL); - (_b = configurationCopy.transactionalRequestTimeout) !== null && _b !== void 0 ? _b : (configurationCopy.transactionalRequestTimeout = TRANSACTIONAL_REQUEST_TIMEOUT); - (_c = configurationCopy.subscribeRequestTimeout) !== null && _c !== void 0 ? _c : (configurationCopy.subscribeRequestTimeout = SUBSCRIBE_REQUEST_TIMEOUT); - (_d = configurationCopy.fileRequestTimeout) !== null && _d !== void 0 ? _d : (configurationCopy.fileRequestTimeout = FILE_REQUEST_TIMEOUT); - (_e = configurationCopy.restore) !== null && _e !== void 0 ? _e : (configurationCopy.restore = RESTORE); - (_f = configurationCopy.useInstanceId) !== null && _f !== void 0 ? _f : (configurationCopy.useInstanceId = USE_INSTANCE_ID); - (_g = configurationCopy.suppressLeaveEvents) !== null && _g !== void 0 ? _g : (configurationCopy.suppressLeaveEvents = SUPPRESS_LEAVE_EVENTS); - (_h = configurationCopy.requestMessageCountThreshold) !== null && _h !== void 0 ? _h : (configurationCopy.requestMessageCountThreshold = DEDUPE_CACHE_SIZE); - (_j = configurationCopy.autoNetworkDetection) !== null && _j !== void 0 ? _j : (configurationCopy.autoNetworkDetection = AUTO_NETWORK_DETECTION); - (_k = configurationCopy.enableEventEngine) !== null && _k !== void 0 ? _k : (configurationCopy.enableEventEngine = ENABLE_EVENT_ENGINE); - (_l = configurationCopy.maintainPresenceState) !== null && _l !== void 0 ? _l : (configurationCopy.maintainPresenceState = MAINTAIN_PRESENCE_STATE); - (_m = configurationCopy.useSmartHeartbeat) !== null && _m !== void 0 ? _m : (configurationCopy.useSmartHeartbeat = USE_SMART_HEARTBEAT); - (_o = configurationCopy.keepAlive) !== null && _o !== void 0 ? _o : (configurationCopy.keepAlive = KEEP_ALIVE$1); - if (configurationCopy.userId && configurationCopy.uuid) - throw new PubNubError("PubNub client configuration error: use only 'userId'"); - (_p = configurationCopy.userId) !== null && _p !== void 0 ? _p : (configurationCopy.userId = configurationCopy.uuid); - if (!configurationCopy.userId) - throw new PubNubError("PubNub client configuration error: 'userId' not set"); - else if (((_q = configurationCopy.userId) === null || _q === void 0 ? void 0 : _q.trim().length) === 0) - throw new PubNubError("PubNub client configuration error: 'userId' is empty"); - // Generate default origin subdomains. - if (!configurationCopy.origin) - configurationCopy.origin = Array.from({ length: 20 }, (_, i) => `ps${i + 1}.pndsn.com`); - const keySet = { - subscribeKey: configurationCopy.subscribeKey, - publishKey: configurationCopy.publishKey, - secretKey: configurationCopy.secretKey, - }; - if (configurationCopy.presenceTimeout !== undefined) { - if (configurationCopy.presenceTimeout > PRESENCE_TIMEOUT_MAXIMUM) { - configurationCopy.presenceTimeout = PRESENCE_TIMEOUT_MAXIMUM; - // eslint-disable-next-line no-console - console.warn('WARNING: Presence timeout is larger than the maximum. Using maximum value: ', PRESENCE_TIMEOUT_MAXIMUM); - } - else if (configurationCopy.presenceTimeout <= 0) { - // eslint-disable-next-line no-console - console.warn('WARNING: Presence timeout should be larger than zero.'); - delete configurationCopy.presenceTimeout; - } - } - if (configurationCopy.presenceTimeout !== undefined) - configurationCopy.heartbeatInterval = configurationCopy.presenceTimeout / 2 - 1; - else - configurationCopy.presenceTimeout = PRESENCE_TIMEOUT; - // Apply extended configuration defaults. - let announceSuccessfulHeartbeats = ANNOUNCE_HEARTBEAT_SUCCESS; - let announceFailedHeartbeats = ANNOUNCE_HEARTBEAT_FAILURE; - let fileUploadPublishRetryLimit = FILE_PUBLISH_RETRY_LIMIT; - let dedupeOnSubscribe = DEDUPE_ON_SUBSCRIBE; - let maximumCacheSize = DEDUPE_CACHE_SIZE; - let useRequestId = USE_REQUEST_ID; - // @ts-expect-error Not documented legacy configuration options. - if (configurationCopy.dedupeOnSubscribe !== undefined && typeof configurationCopy.dedupeOnSubscribe === 'boolean') { - // @ts-expect-error Not documented legacy configuration options. - dedupeOnSubscribe = configurationCopy.dedupeOnSubscribe; - } - // @ts-expect-error Not documented legacy configuration options. - if (configurationCopy.maximumCacheSize !== undefined && typeof configurationCopy.maximumCacheSize === 'number') { - // @ts-expect-error Not documented legacy configuration options. - maximumCacheSize = configurationCopy.maximumCacheSize; - } - // @ts-expect-error Not documented legacy configuration options. - if (configurationCopy.useRequestId !== undefined && typeof configurationCopy.useRequestId === 'boolean') { - // @ts-expect-error Not documented legacy configuration options. - useRequestId = configurationCopy.useRequestId; - } - if ( - // @ts-expect-error Not documented legacy configuration options. - configurationCopy.announceSuccessfulHeartbeats !== undefined && - // @ts-expect-error Not documented legacy configuration options. - typeof configurationCopy.announceSuccessfulHeartbeats === 'boolean') { - // @ts-expect-error Not documented legacy configuration options. - announceSuccessfulHeartbeats = configurationCopy.announceSuccessfulHeartbeats; - } - if ( - // @ts-expect-error Not documented legacy configuration options. - configurationCopy.announceFailedHeartbeats !== undefined && - // @ts-expect-error Not documented legacy configuration options. - typeof configurationCopy.announceFailedHeartbeats === 'boolean') { - // @ts-expect-error Not documented legacy configuration options. - announceFailedHeartbeats = configurationCopy.announceFailedHeartbeats; - } - if ( - // @ts-expect-error Not documented legacy configuration options. - configurationCopy.fileUploadPublishRetryLimit !== undefined && - // @ts-expect-error Not documented legacy configuration options. - typeof configurationCopy.fileUploadPublishRetryLimit === 'number') { - // @ts-expect-error Not documented legacy configuration options. - fileUploadPublishRetryLimit = configurationCopy.fileUploadPublishRetryLimit; - } - return Object.assign(Object.assign({}, configurationCopy), { keySet, - dedupeOnSubscribe, - maximumCacheSize, - useRequestId, - announceSuccessfulHeartbeats, - announceFailedHeartbeats, - fileUploadPublishRetryLimit }); - }; - - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether PubNub client should update its state using browser's reachability events or not. - * - * If the browser fails to detect the network changes from Wi-Fi to LAN and vice versa, or you get - * reconnection issues, set the flag to `false`. This allows the SDK reconnection logic to take over. - */ - const LISTEN_TO_BROWSER_NETWORK_EVENTS = true; - /** - * Whether verbose logging should be enabled for `Subscription` worker to print debug messages or not. - */ - const SUBSCRIPTION_WORKER_LOG_VERBOSITY = false; - /** - * Interval at which Shared Worker should check whether PubNub instances which used it still active or not. - */ - const SUBSCRIPTION_WORKER_OFFLINE_CLIENTS_CHECK_INTERVAL = 10; - /** - * Whether `leave` request should be sent for _offline_ PubNub client or not. - */ - const SUBSCRIPTION_WORKER_UNSUBSCRIBE_OFFLINE_CLIENTS = false; - /** - * Use modern Web Fetch API for network requests by default. - */ - const TRANSPORT = 'fetch'; - /** - * Whether PubNub client should try to utilize existing TCP connection for new requests or not. - */ - const KEEP_ALIVE = true; - /** - * Apply configuration default values. - * - * @param configuration - User-provided configuration. - * - * @internal - */ - const setDefaults = (configuration) => { - var _a, _b, _c, _d, _e, _f; - // Force to disable service workers if the environment doesn't support them. - if (configuration.subscriptionWorkerUrl && typeof SharedWorker === 'undefined') { - configuration.subscriptionWorkerUrl = null; - } - return Object.assign(Object.assign({}, setDefaults$1(configuration)), { - // Set platform-specific options. - listenToBrowserNetworkEvents: (_a = configuration.listenToBrowserNetworkEvents) !== null && _a !== void 0 ? _a : LISTEN_TO_BROWSER_NETWORK_EVENTS, subscriptionWorkerUrl: configuration.subscriptionWorkerUrl, subscriptionWorkerOfflineClientsCheckInterval: (_b = configuration.subscriptionWorkerOfflineClientsCheckInterval) !== null && _b !== void 0 ? _b : SUBSCRIPTION_WORKER_OFFLINE_CLIENTS_CHECK_INTERVAL, subscriptionWorkerUnsubscribeOfflineClients: (_c = configuration.subscriptionWorkerUnsubscribeOfflineClients) !== null && _c !== void 0 ? _c : SUBSCRIPTION_WORKER_UNSUBSCRIBE_OFFLINE_CLIENTS, subscriptionWorkerLogVerbosity: (_d = configuration.subscriptionWorkerLogVerbosity) !== null && _d !== void 0 ? _d : SUBSCRIPTION_WORKER_LOG_VERBOSITY, transport: (_e = configuration.transport) !== null && _e !== void 0 ? _e : TRANSPORT, keepAlive: (_f = configuration.keepAlive) !== null && _f !== void 0 ? _f : KEEP_ALIVE }); - }; - - /** - * Enum with available log levels. - */ - var LogLevel; - (function (LogLevel) { - /** - * Used to notify about every last detail: - * - function calls, - * - full payloads, - * - internal variables, - * - state-machine hops. - */ - LogLevel[LogLevel["Trace"] = 0] = "Trace"; - /** - * Used to notify about broad strokes of your SDK’s logic: - * - inputs/outputs to public methods, - * - network request - * - network response - * - decision branches. - */ - LogLevel[LogLevel["Debug"] = 1] = "Debug"; - /** - * Used to notify summary of what the SDK is doing under the hood: - * - initialized, - * - connected, - * - entity created. - */ - LogLevel[LogLevel["Info"] = 2] = "Info"; - /** - * Used to notify about non-fatal events: - * - deprecations, - * - request retries. - */ - LogLevel[LogLevel["Warn"] = 3] = "Warn"; - /** - * Used to notify about: - * - exceptions, - * - HTTP failures, - * - invalid states. - */ - LogLevel[LogLevel["Error"] = 4] = "Error"; - /** - * Logging disabled. - */ - LogLevel[LogLevel["None"] = 5] = "None"; - })(LogLevel || (LogLevel = {})); - - /** - * Default console-based logger. - * - * **Important:** This logger is always added as part of {@link LoggerManager} instance configuration and can't be - * removed. - * - * @internal - */ - /** - * Custom {@link Logger} implementation to show a message in the native console. - */ - class ConsoleLogger { - /** - * Process a `debug` level message. - * - * @param message - Message which should be handled by custom logger implementation. - */ - debug(message) { - this.log(message); - } - /** - * Process a `error` level message. - * - * @param message - Message which should be handled by custom logger implementation. - */ - error(message) { - this.log(message); - } - /** - * Process an `info` level message. - * - * @param message - Message which should be handled by custom logger implementation. - */ - info(message) { - this.log(message); - } - /** - * Process a `trace` level message. - * - * @param message - Message which should be handled by custom logger implementation. - */ - trace(message) { - this.log(message); - } - /** - * Process an `warn` level message. - * - * @param message - Message which should be handled by custom logger implementation. - */ - warn(message) { - this.log(message); - } - /** - * Stringify logger object. - * - * @returns Serialized logger object. - */ - toString() { - return `ConsoleLogger {}`; - } - /** - * Process log message object. - * - * @param message - Object with information which can be used to identify level and prepare log entry payload. - */ - log(message) { - const logLevelString = LogLevel[message.level]; - const level = logLevelString.toLowerCase(); - console[level === 'trace' ? 'debug' : level](`${message.timestamp.toISOString()} PubNub-${message.pubNubId} ${logLevelString.padEnd(5, ' ')}${message.location ? ` ${message.location}` : ''} ${this.logMessage(message)}`); - } - /** - * Get a pre-formatted log message. - * - * @param message - Log message which should be stringified. - * - * @returns String formatted for log entry in console. - */ - logMessage(message) { - if (message.messageType === 'text') - return message.message; - else if (message.messageType === 'object') - return `${message.details ? `${message.details}\n` : ''}${this.formattedObject(message)}`; - else if (message.messageType === 'network-request') { - const showOnlyBasicInfo = !!message.canceled || !!message.failed; - const headersList = message.minimumLevel === LogLevel.Trace && !showOnlyBasicInfo ? this.formattedHeaders(message) : undefined; - const request = message.message; - const queryString = request.queryParameters && Object.keys(request.queryParameters).length > 0 - ? queryStringFromObject(request.queryParameters) - : undefined; - const url = `${request.origin}${request.path}${queryString ? `?${queryString}` : ''}`; - const formattedBody = !showOnlyBasicInfo ? this.formattedBody(message) : undefined; - let action = 'Sending'; - if (showOnlyBasicInfo) - action = `${!!message.canceled ? 'Canceled' : 'Failed'}${message.details ? ` (${message.details})` : ''}`; - const padding = ((formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.formData) ? 'FormData' : 'Method').length; - return `${action} HTTP request:\n ${this.paddedString('Method', padding)}: ${request.method}\n ${this.paddedString('URL', padding)}: ${url}${headersList ? `\n ${this.paddedString('Headers', padding)}:\n${headersList}` : ''}${(formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.formData) ? `\n ${this.paddedString('FormData', padding)}:\n${formattedBody.formData}` : ''}${(formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.body) ? `\n ${this.paddedString('Body', padding)}:\n${formattedBody.body}` : ''}`; - } - else if (message.messageType === 'network-response') { - const headersList = message.minimumLevel === LogLevel.Trace ? this.formattedHeaders(message) : undefined; - const formattedBody = this.formattedBody(message); - const padding = ((formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.formData) ? 'Headers' : 'Status').length; - const response = message.message; - return `Received HTTP response:\n ${this.paddedString('URL', padding)}: ${response.url}\n ${this.paddedString('Status', padding)}: ${response.status}${message.details ? `\n ${this.paddedString('Details', padding)}: ${message.details}` : ''}${headersList ? `\n ${this.paddedString('Headers', padding)}:\n${headersList}` : ''}${(formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.body) ? `\n ${this.paddedString('Body', padding)}:\n${formattedBody.body}` : ''}`; - } - else if (message.messageType === 'error') { - const formattedStatus = this.formattedErrorStatus(message); - const error = message.message; - return `${error.name}: ${error.message}${formattedStatus ? `\n${formattedStatus}` : ''}`; - } - return ''; - } - /** - * Get a pre-formatted object (dictionary / array). - * - * @param message - Log message which may contain an object for formatting. - * - * @returns String formatted for log entry in console or `undefined` if a log message doesn't have suitable data. - */ - formattedObject(message) { - const stringify = (obj, level = 1, skipIndentOnce = false) => { - const maxIndentReached = level === 10; - const targetIndent = ' '.repeat(level * 2); - const lines = []; - const isIgnored = (key, obj) => { - if (!message.ignoredKeys) - return false; - if (typeof message.ignoredKeys === 'function') - return message.ignoredKeys(key, obj); - return message.ignoredKeys.includes(key); - }; - if (typeof obj === 'string') - lines.push(`${targetIndent}- ${obj}`); - else if (typeof obj === 'number') - lines.push(`${targetIndent}- ${obj}`); - else if (typeof obj === 'boolean') - lines.push(`${targetIndent}- ${obj}`); - else if (obj === null) - lines.push(`${targetIndent}- null`); - else if (obj === undefined) - lines.push(`${targetIndent}- undefined`); - else if (typeof obj === 'function') - lines.push(`${targetIndent}- `); - else if (typeof obj === 'object') { - if (!Array.isArray(obj) && typeof obj.toString === 'function' && obj.toString().indexOf('[object') !== 0) { - lines.push(`${skipIndentOnce ? '' : targetIndent}${obj.toString()}`); - skipIndentOnce = false; - } - else if (Array.isArray(obj)) { - for (const element of obj) { - const indent = skipIndentOnce ? '' : targetIndent; - if (element === null) - lines.push(`${indent}- null`); - else if (element === undefined) - lines.push(`${indent}- undefined`); - else if (typeof element === 'function') - lines.push(`${indent}- `); - else if (typeof element === 'object') { - const isArray = Array.isArray(element); - const entry = maxIndentReached ? '...' : stringify(element, level + 1, !isArray); - lines.push(`${indent}-${isArray && !maxIndentReached ? '\n' : ' '}${entry}`); - } - else - lines.push(`${indent}- ${element}`); - skipIndentOnce = false; - } - } - else { - const object = obj; - const keys = Object.keys(object); - const maxKeyLen = keys.reduce((max, key) => Math.max(max, isIgnored(key, object) ? max : key.length), 0); - for (const key of keys) { - if (isIgnored(key, object)) - continue; - const indent = skipIndentOnce ? '' : targetIndent; - const raw = object[key]; - const paddedKey = key.padEnd(maxKeyLen, ' '); - if (raw === null) - lines.push(`${indent}${paddedKey}: null`); - else if (raw === undefined) - lines.push(`${indent}${paddedKey}: undefined`); - else if (typeof raw === 'function') - lines.push(`${indent}${paddedKey}: `); - else if (typeof raw === 'object') { - const isArray = Array.isArray(raw); - const isEmptyArray = isArray && raw.length === 0; - const isEmptyObject = !isArray && !(raw instanceof String) && Object.keys(raw).length === 0; - const hasToString = !isArray && typeof raw.toString === 'function' && raw.toString().indexOf('[object') !== 0; - const entry = maxIndentReached - ? '...' - : isEmptyArray - ? '[]' - : isEmptyObject - ? '{}' - : stringify(raw, level + 1, hasToString); - lines.push(`${indent}${paddedKey}:${maxIndentReached || hasToString || isEmptyArray || isEmptyObject ? ' ' : '\n'}${entry}`); - } - else - lines.push(`${indent}${paddedKey}: ${raw}`); - skipIndentOnce = false; - } - } - } - return lines.join('\n'); - }; - return stringify(message.message); - } - /** - * Get a pre-formatted headers list. - * - * @param message - Log message which may contain an object with headers to be used for formatting. - * - * @returns String formatted for log entry in console or `undefined` if a log message not related to the network data. - */ - formattedHeaders(message) { - if (!message.message.headers) - return undefined; - const headers = message.message.headers; - const maxHeaderLength = Object.keys(headers).reduce((max, key) => Math.max(max, key.length), 0); - return Object.keys(headers) - .map((key) => ` - ${key.toLowerCase().padEnd(maxHeaderLength, ' ')}: ${headers[key]}`) - .join('\n'); - } - /** - * Get a pre-formatted body. - * - * @param message - Log message which may contain an object with `body` (request or response). - * - * @returns Object with formatted string of form data and / or body for log entry in console or `undefined` if a log - * message not related to the network data. - */ - formattedBody(message) { - var _a; - if (!message.message.headers) - return undefined; - let stringifiedFormData; - let stringifiedBody; - const headers = message.message.headers; - const contentType = (_a = headers['content-type']) !== null && _a !== void 0 ? _a : headers['Content-Type']; - const formData = 'formData' in message.message ? message.message.formData : undefined; - const body = message.message.body; - // The presence of this object means that we are sending `multipart/form-data` (potentially uploading a file). - if (formData) { - const maxFieldLength = formData.reduce((max, { key }) => Math.max(max, key.length), 0); - stringifiedFormData = formData - .map(({ key, value }) => ` - ${key.padEnd(maxFieldLength, ' ')}: ${value}`) - .join('\n'); - } - if (!body) - return { formData: stringifiedFormData }; - if (typeof body === 'string') { - stringifiedBody = ` ${body}`; - } - else if (body instanceof ArrayBuffer || Object.prototype.toString.call(body) === '[object ArrayBuffer]') { - if (contentType && (contentType.indexOf('javascript') !== -1 || contentType.indexOf('json') !== -1)) - stringifiedBody = ` ${ConsoleLogger.decoder.decode(body)}`; - else - stringifiedBody = ` ArrayBuffer { byteLength: ${body.byteLength} }`; - } - else { - stringifiedBody = ` File { name: ${body.name}${body.contentLength ? `, contentLength: ${body.contentLength}` : ''}${body.mimeType ? `, mimeType: ${body.mimeType}` : ''} }`; - } - return { body: stringifiedBody, formData: stringifiedFormData }; - } - /** - * Get a pre-formatted status object. - * - * @param message - Log message which may contain a {@link Status} object. - * - * @returns String formatted for log entry in console or `undefined` if a log message doesn't have {@link Status} - * object. - */ - formattedErrorStatus(message) { - if (!message.message.status) - return undefined; - const status = message.message.status; - const errorData = status.errorData; - let stringifiedErrorData; - if (ConsoleLogger.isError(errorData)) { - stringifiedErrorData = ` ${errorData.name}: ${errorData.message}`; - if (errorData.stack) { - stringifiedErrorData += `\n${errorData.stack - .split('\n') - .map((line) => ` ${line}`) - .join('\n')}`; - } - } - else if (errorData) { - try { - stringifiedErrorData = ` ${JSON.stringify(errorData)}`; - } - catch (_) { - stringifiedErrorData = ` ${errorData}`; - } - } - return ` Category : ${status.category}\n Operation : ${status.operation}\n Status : ${status.statusCode}${stringifiedErrorData ? `\n Error data:\n${stringifiedErrorData}` : ''}`; - } - /** - * Append the required amount of space to provide proper padding. - * - * @param str - Source string which should be appended with necessary number of spaces. - * @param maxLength - Maximum length of the string to which source string should be padded. - * @returns End-padded string. - */ - paddedString(str, maxLength) { - return str.padEnd(maxLength - str.length, ' '); - } - /** - * Check whether passed object is {@link Error} instance. - * - * @param errorData - Object which should be checked. - * - * @returns `true` in case if an object actually {@link Error}. - */ - static isError(errorData) { - if (!errorData) - return false; - return errorData instanceof Error || Object.prototype.toString.call(errorData) === '[object Error]'; - } - } - /** - * Binary data decoder. - */ - ConsoleLogger.decoder = new TextDecoder(); - - /** - * HTTP status codes which represent definitive client-side outcomes and shouldn't be retried. - * - * @internal - */ - const NON_RETRIABLE_STATUS_CODES = [404, 409]; - // -------------------------------------------------------- - // ------------------------ Types ------------------------- - // -------------------------------------------------------- - // region Types - /** - * List of known endpoint groups (by context). - */ - var Endpoint; - (function (Endpoint) { - /** - * Unknown endpoint. - * - * @internal - */ - Endpoint["Unknown"] = "UnknownEndpoint"; - /** - * The endpoints to send messages. - * - * This is related to the following functionality: - * - `publish` - * - `signal` - * - `publish file` - * - `fire` - */ - Endpoint["MessageSend"] = "MessageSendEndpoint"; - /** - * The endpoint for real-time update retrieval. - * - * This is related to the following functionality: - * - `subscribe` - */ - Endpoint["Subscribe"] = "SubscribeEndpoint"; - /** - * The endpoint to access and manage `user_id` presence and fetch channel presence information. - * - * This is related to the following functionality: - * - `get presence state` - * - `set presence state` - * - `here now` - * - `where now` - * - `heartbeat` - */ - Endpoint["Presence"] = "PresenceEndpoint"; - /** - * The endpoint to access and manage files in channel-specific storage. - * - * This is related to the following functionality: - * - `send file` - * - `download file` - * - `list files` - * - `delete file` - */ - Endpoint["Files"] = "FilesEndpoint"; - /** - * The endpoint to access and manage messages for a specific channel(s) in the persistent storage. - * - * This is related to the following functionality: - * - `fetch messages / message actions` - * - `delete messages` - * - `messages count` - */ - Endpoint["MessageStorage"] = "MessageStorageEndpoint"; - /** - * The endpoint to access and manage channel groups. - * - * This is related to the following functionality: - * - `add channels to group` - * - `list channels in group` - * - `remove channels from group` - * - `list channel groups` - */ - Endpoint["ChannelGroups"] = "ChannelGroupsEndpoint"; - /** - * The endpoint to access and manage device registration for channel push notifications. - * - * This is related to the following functionality: - * - `enable channels for push notifications` - * - `list push notification enabled channels` - * - `disable push notifications for channels` - * - `disable push notifications for all channels` - */ - Endpoint["DevicePushNotifications"] = "DevicePushNotificationsEndpoint"; - /** - * The endpoint to access and manage App Context objects. - * - * This is related to the following functionality: - * - `set UUID metadata` - * - `get UUID metadata` - * - `remove UUID metadata` - * - `get all UUID metadata` - * - `set Channel metadata` - * - `get Channel metadata` - * - `remove Channel metadata` - * - `get all Channel metadata` - * - `manage members` - * - `list members` - * - `manage memberships` - * - `list memberships` - */ - Endpoint["AppContext"] = "AppContextEndpoint"; - /** - * The endpoint to access and manage reactions for a specific message. - * - * This is related to the following functionality: - * - `add message action` - * - `get message actions` - * - `remove message action` - */ - Endpoint["MessageReactions"] = "MessageReactionsEndpoint"; - })(Endpoint || (Endpoint = {})); - // endregion - /** - * Failed request retry policy. - */ - class RetryPolicy { - static None() { - return { - shouldRetry(_request, _response, _errorCategory, _attempt, _statusCode) { - return false; - }, - getDelay(_attempt, _response) { - return -1; - }, - validate() { - return true; - }, - }; - } - static LinearRetryPolicy(configuration) { - var _a; - return { - delay: configuration.delay, - maximumRetry: configuration.maximumRetry, - excluded: (_a = configuration.excluded) !== null && _a !== void 0 ? _a : [], - shouldRetry(request, response, error, attempt, statusCode) { - return isRetriableRequest(request, response, error, attempt !== null && attempt !== void 0 ? attempt : 0, this.maximumRetry, this.excluded, statusCode); - }, - getDelay(_, response) { - let delay = -1; - if (response && response.headers['retry-after'] !== undefined) - delay = parseInt(response.headers['retry-after'], 10); - if (delay === -1) - delay = this.delay; - return (delay + Math.random()) * 1000; - }, - validate() { - if (this.delay < 2) - throw new Error('Delay can not be set less than 2 seconds for retry'); - }, - }; - } - static ExponentialRetryPolicy(configuration) { - var _a; - return { - minimumDelay: configuration.minimumDelay, - maximumDelay: configuration.maximumDelay, - maximumRetry: configuration.maximumRetry, - excluded: (_a = configuration.excluded) !== null && _a !== void 0 ? _a : [], - shouldRetry(request, response, error, attempt, statusCode) { - return isRetriableRequest(request, response, error, attempt !== null && attempt !== void 0 ? attempt : 0, this.maximumRetry, this.excluded, statusCode); - }, - getDelay(attempt, response) { - let delay = -1; - if (response && response.headers['retry-after'] !== undefined) - delay = parseInt(response.headers['retry-after'], 10); - if (delay === -1) - delay = Math.min(this.minimumDelay * Math.pow(2, attempt), this.maximumDelay); - return (delay + Math.random()) * 1000; - }, - validate() { - if (this.minimumDelay < 2) - throw new Error('Minimum delay can not be set less than 2 seconds for retry'); - }, - }; - } - } - /** - * Check whether request can be retried or not. - * - * @param req - Request for which retry ability is checked. - * @param res - Service response which should be taken into consideration. - * @param errorCategory - Request processing error category. - * @param retryAttempt - Current retry attempt. - * @param maximumRetry - Maximum retry attempts count according to the retry policy. - * @param excluded - List of endpoints for which retry policy won't be applied. - * @param statusCode - Response HTTP status code (available when request failed with an error and hence there is no - * `res`). - * - * @return `true` if request can be retried. - * - * @internal - */ - const isRetriableRequest = (req, res, errorCategory, retryAttempt, maximumRetry, excluded, statusCode) => { - var _a; - if (errorCategory) { - if (errorCategory === StatusCategory$1.PNCancelledCategory || - errorCategory === StatusCategory$1.PNBadRequestCategory || - errorCategory === StatusCategory$1.PNAccessDeniedCategory) - return false; - } - if (isExcludedRequest(req, excluded)) - return false; - else if (retryAttempt > maximumRetry) - return false; - // Status code is reported separately from the `res` when the request failed with an error. - const status = (_a = res === null || res === void 0 ? void 0 : res.status) !== null && _a !== void 0 ? _a : statusCode; - if (status !== undefined && NON_RETRIABLE_STATUS_CODES.includes(status)) - return false; - return res ? res.status === 429 || res.status >= 500 : true; - }; - /** - * Check whether the provided request is in the list of endpoints for which retry is not allowed or not. - * - * @param req - Request which will be tested. - * @param excluded - List of excluded endpoints configured for retry policy. - * - * @returns `true` if request has been excluded and shouldn't be retried. - * - * @internal - */ - const isExcludedRequest = (req, excluded) => excluded && excluded.length > 0 ? excluded.includes(endpointFromRequest(req)) : false; - /** - * Identify API group from transport request. - * - * @param req - Request for which `path` will be analyzed to identify REST API group. - * - * @returns Endpoint group to which request belongs. - * - * @internal - */ - const endpointFromRequest = (req) => { - let endpoint = Endpoint.Unknown; - if (req.path.startsWith('/v2/subscribe')) - endpoint = Endpoint.Subscribe; - else if (req.path.startsWith('/publish/') || req.path.startsWith('/signal/')) - endpoint = Endpoint.MessageSend; - else if (req.path.startsWith('/v2/presence')) - endpoint = Endpoint.Presence; - else if (req.path.startsWith('/v2/history') || req.path.startsWith('/v3/history')) - endpoint = Endpoint.MessageStorage; - else if (req.path.startsWith('/v1/message-actions/')) - endpoint = Endpoint.MessageReactions; - else if (req.path.startsWith('/v1/channel-registration/')) - endpoint = Endpoint.ChannelGroups; - else if (req.path.startsWith('/v2/objects/')) - endpoint = Endpoint.ChannelGroups; - else if (req.path.startsWith('/v1/push/') || req.path.startsWith('/v2/push/')) - endpoint = Endpoint.DevicePushNotifications; - else if (req.path.startsWith('/v1/files/')) - endpoint = Endpoint.Files; - return endpoint; - }; - - /** - * Logging module manager. - * - * Manager responsible for log requests handling and forwarding to the registered {@link Logger logger} implementations. - */ - class LoggerManager { - /** - * Create and configure loggers' manager. - * - * @param pubNubId - Unique identifier of PubNub instance which will use this logger. - * @param minLogLevel - Minimum messages log level to be logged. - * @param loggers - List of additional loggers which should be used along with user-provided custom loggers. - * - * @internal - */ - constructor(pubNubId, minLogLevel, loggers) { - /** - * Keeping track of previous entry timestamp. - * - * This information will be used to make sure that multiple sequential entries doesn't have same timestamp. Adjustment - * on .001 will be done to make it possible to properly stort entries. - * - * @internal - */ - this.previousEntryTimestamp = 0; - this.pubNubId = pubNubId; - this.minLogLevel = minLogLevel; - this.loggers = loggers; - } - /** - * Get current log level. - * - * @returns Current log level. - * - * @internal - */ - get logLevel() { - return this.minLogLevel; - } - /** - * Process a `trace` level message. - * - * @param location - Call site from which a log message has been sent. - * @param messageFactory - Lazy message factory function or string for a text log message. - * - * @internal - */ - trace(location, messageFactory) { - this.log(LogLevel.Trace, location, messageFactory); - } - /** - * Process a `debug` level message. - * - * @param location - Call site from which a log message has been sent. - * @param messageFactory - Lazy message factory function or string for a text log message. - * - * @internal - */ - debug(location, messageFactory) { - this.log(LogLevel.Debug, location, messageFactory); - } - /** - * Process an `info` level message. - * - * @param location - Call site from which a log message has been sent. - * @param messageFactory - Lazy message factory function or string for a text log message. - * - * @internal - */ - info(location, messageFactory) { - this.log(LogLevel.Info, location, messageFactory); - } - /** - * Process a `warn` level message. - * - * @param location - Call site from which a log message has been sent. - * @param messageFactory - Lazy message factory function or string for a text log message. - * - * @internal - */ - warn(location, messageFactory) { - this.log(LogLevel.Warn, location, messageFactory); - } - /** - * Process an `error` level message. - * - * @param location - Call site from which a log message has been sent. - * @param messageFactory - Lazy message factory function or string for a text log message. - * - * @internal - */ - error(location, messageFactory) { - this.log(LogLevel.Error, location, messageFactory); - } - /** - * Process log message. - * - * @param logLevel - Logged message level. - * @param location - Call site from which a log message has been sent. - * @param messageFactory - Lazy message factory function or string for a text log message. - * - * @internal - */ - log(logLevel, location, messageFactory) { - // Check whether a log message should be handled at all or not. - if (logLevel < this.minLogLevel || this.loggers.length === 0) - return; - const date = new Date(); - if (date.getTime() <= this.previousEntryTimestamp) { - this.previousEntryTimestamp++; - date.setTime(this.previousEntryTimestamp); - } - else - this.previousEntryTimestamp = date.getTime(); - const level = LogLevel[logLevel].toLowerCase(); - const message = Object.assign({ timestamp: date, pubNubId: this.pubNubId, level: logLevel, minimumLevel: this.minLogLevel, location }, (typeof messageFactory === 'function' ? messageFactory() : { messageType: 'text', message: messageFactory })); - this.loggers.forEach((logger) => logger[level](message)); - } - } - - var uuid = {exports: {}}; - - /*! lil-uuid - v0.1 - MIT License - https://github.com/lil-js/uuid */ - uuid.exports; - - (function (module, exports) { - (function (root, factory) { - { - factory(exports); - if (module !== null) { - module.exports = exports.uuid; - } - } - }(commonjsGlobal, function (exports) { - var VERSION = '0.1.0'; - var uuidRegex = { - '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, - '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, - '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, - all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i - }; - - function uuid() { - var uuid = '', i, random; - for (i = 0; i < 32; i++) { - random = Math.random() * 16 | 0; - if (i === 8 || i === 12 || i === 16 || i === 20) uuid += '-'; - uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random)).toString(16); - } - return uuid - } - - function isUUID(str, version) { - var pattern = uuidRegex[version || 'all']; - return pattern && pattern.test(str) || false - } - - uuid.isUUID = isUUID; - uuid.VERSION = VERSION; - - exports.uuid = uuid; - exports.isUUID = isUUID; - })); - } (uuid, uuid.exports)); - - var uuidExports = uuid.exports; - var uuidGenerator$1 = /*@__PURE__*/getDefaultExportFromCjs(uuidExports); - - /** - * Random identifier generator helper module. - * - * @internal - */ - /** @internal */ - var uuidGenerator = { - createUUID() { - if (uuidGenerator$1.uuid) { - return uuidGenerator$1.uuid(); - } - // @ts-expect-error Depending on module type it may be callable. - return uuidGenerator$1(); - }, - }; - - /** - * {@link PubNub} client configuration module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether encryption (if set) should use random initialization vector or not. - * - * @internal - */ - const USE_RANDOM_INITIALIZATION_VECTOR = true; - /** - * Create {@link PubNub} client private configuration object. - * - * @param base - User- and platform-provided configuration. - * @param setupCryptoModule - Platform-provided {@link ICryptoModule} configuration block. - * - * @returns `PubNub` client private configuration. - * - * @internal - */ - const makeConfiguration = (base, setupCryptoModule) => { - var _a, _b, _c, _d; - // Set the default retry policy for subscribing (if new subscribe logic not used). - if (!base.retryConfiguration && base.enableEventEngine) { - base.retryConfiguration = RetryPolicy.ExponentialRetryPolicy({ - minimumDelay: 2, - maximumDelay: 150, - maximumRetry: 6, - excluded: [ - Endpoint.MessageSend, - Endpoint.Presence, - Endpoint.Files, - Endpoint.MessageStorage, - Endpoint.ChannelGroups, - Endpoint.DevicePushNotifications, - Endpoint.AppContext, - Endpoint.MessageReactions, - ], - }); - } - const instanceId = `pn-${uuidGenerator.createUUID()}`; - if (base.logVerbosity) - base.logLevel = LogLevel.Debug; - else if (base.logLevel === undefined) - base.logLevel = LogLevel.None; - // Prepare loggers manager. - const loggerManager = new LoggerManager(hashFromString(instanceId), base.logLevel, [ - ...((_a = base.loggers) !== null && _a !== void 0 ? _a : []), - new ConsoleLogger(), - ]); - if (base.logVerbosity !== undefined) - loggerManager.warn('Configuration', "'logVerbosity' is deprecated. Use 'logLevel' instead."); - // Ensure that retry policy has proper configuration (if has been set). - (_b = base.retryConfiguration) === null || _b === void 0 ? void 0 : _b.validate(); - const explicitUseRandomIVs = base.useRandomIVs; - (_c = base.useRandomIVs) !== null && _c !== void 0 ? _c : (base.useRandomIVs = USE_RANDOM_INITIALIZATION_VECTOR); - if (explicitUseRandomIVs !== undefined) { - loggerManager.warn('Configuration', "'useRandomIVs' is deprecated. Pass it to 'cryptoModule' instead."); - if (explicitUseRandomIVs === false) { - loggerManager.warn('Configuration', `Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients. - Do not disable random IVs in new applications.`); - } - } - // Override origin value. - base.origin = standardOrigin((_d = base.ssl) !== null && _d !== void 0 ? _d : false, base.origin); - const cryptoModule = base.cryptoModule; - if (cryptoModule) - delete base.cryptoModule; - const clientConfiguration = Object.assign(Object.assign({}, base), { _pnsdkSuffix: {}, _loggerManager: loggerManager, _instanceId: instanceId, _cryptoModule: undefined, _cipherKey: undefined, _setupCryptoModule: setupCryptoModule, get instanceId() { - if (base.useInstanceId) - return this._instanceId; - return undefined; - }, - getInstanceId() { - if (base.useInstanceId) - return this._instanceId; - return undefined; - }, - getUserId() { - return this.userId; - }, - setUserId(value) { - if (!value || typeof value !== 'string' || value.trim().length === 0) - throw new Error('Missing or invalid userId parameter. Provide a valid string userId'); - this.userId = value; - }, - logger() { - return this._loggerManager; - }, - getAuthKey() { - return this.authKey; - }, - setAuthKey(authKey) { - this.authKey = authKey; - }, - getFilterExpression() { - return this.filterExpression; - }, - setFilterExpression(expression) { - this.filterExpression = expression; - }, - getCipherKey() { - return this._cipherKey; - }, - setCipherKey(key) { - this._cipherKey = key; - if (!key && this._cryptoModule) { - this._cryptoModule = undefined; - return; - } - else if (!key || !this._setupCryptoModule) - return; - this._cryptoModule = this._setupCryptoModule({ - cipherKey: key, - useRandomIVs: base.useRandomIVs, - customEncrypt: this.getCustomEncrypt(), - customDecrypt: this.getCustomDecrypt(), - logger: this.logger(), - }); - }, - getCryptoModule() { - return this._cryptoModule; - }, - getUseRandomIVs() { - return base.useRandomIVs; - }, - isSharedWorkerEnabled() { - // @ts-expect-error: Access field from web-based SDK configuration. - return base.sdkFamily === 'Web' && base['subscriptionWorkerUrl']; - }, - getKeepPresenceChannelsInPresenceRequests() { - // @ts-expect-error: Access field from web-based SDK configuration. - return base.sdkFamily === 'Web' && base['subscriptionWorkerUrl']; - }, - setPresenceTimeout(value) { - this.heartbeatInterval = value / 2 - 1; - this.presenceTimeout = value; - }, - getPresenceTimeout() { - return this.presenceTimeout; - }, - getHeartbeatInterval() { - return this.heartbeatInterval; - }, - setHeartbeatInterval(interval) { - this.heartbeatInterval = interval; - }, - getTransactionTimeout() { - return this.transactionalRequestTimeout; - }, - getSubscribeTimeout() { - return this.subscribeRequestTimeout; - }, - getFileTimeout() { - return this.fileRequestTimeout; - }, - get PubNubFile() { - return base.PubNubFile; - }, - get version() { - return '13.1.2'; - }, - getVersion() { - return this.version; - }, - _addPnsdkSuffix(name, suffix) { - this._pnsdkSuffix[name] = `${suffix}`; - }, - _getPnsdkSuffix(separator) { - const sdk = Object.values(this._pnsdkSuffix).join(separator); - return sdk.length > 0 ? separator + sdk : ''; - }, - // -------------------------------------------------------- - // ---------------------- Deprecated ---------------------- - // -------------------------------------------------------- - // region Deprecated - getUUID() { - return this.getUserId(); - }, - setUUID(value) { - this.setUserId(value); - }, - getCustomEncrypt() { - return base.customEncrypt; - }, - getCustomDecrypt() { - return base.customDecrypt; - } }); - // Setup `CryptoModule` if possible. - if (base.cipherKey) { - loggerManager.warn('Configuration', "'cipherKey' is deprecated. Use 'cryptoModule' instead."); - clientConfiguration.setCipherKey(base.cipherKey); - } - else if (cryptoModule) - clientConfiguration._cryptoModule = cryptoModule; - return clientConfiguration; - }; - /** - * Decide {@lin PubNub} service REST API origin. - * - * @param secure - Whether preferred to use secured connection or not. - * @param origin - User-provided or default origin. - * - * @returns `PubNub` REST API endpoints origin. - */ - const standardOrigin = (secure, origin) => { - const protocol = secure ? 'https://' : 'http://'; - if (typeof origin === 'string') - return `${protocol}${origin}`; - return `${protocol}${origin[Math.floor(Math.random() * origin.length)]}`; - }; - /** - * Compute 32bit hash string from source value. - * - * @param value - String from which hash string should be computed. - * - * @returns Computed hash. - */ - const hashFromString = (value) => { - let basis = 0x811c9dc5; - for (let i = 0; i < value.length; i++) { - basis ^= value.charCodeAt(i); - basis = (basis + ((basis << 1) + (basis << 4) + (basis << 7) + (basis << 8) + (basis << 24))) >>> 0; - } - return basis.toString(16).padStart(8, '0'); - }; - - /** - * PubNub Access Token Manager module. - * - * @internal - */ - // endregion - /** - * REST API access token manager. - * - * Manager maintains active access token and let parse it to get information about permissions. - * - * @internal - */ - class TokenManager { - constructor(cbor) { - this.cbor = cbor; - } - /** - * Update REST API access token. - * - * **Note:** Token will be applied only for next requests and won't affect ongoing requests. - * - * @param [token] - Access token which should be used to access PubNub REST API. - */ - setToken(token) { - if (token && token.length > 0) - this.token = token; - else - this.token = undefined; - } - /** - * REST API access token. - * - * @returns Previously configured REST API access token. - */ - getToken() { - return this.token; - } - /** - * Parse Base64-encoded access token. - * - * @param tokenString - Base64-encoded access token. - * - * @returns Information about resources and permissions which has been granted for them. - */ - parseToken(tokenString) { - var _a, _b; - const parsed = this.cbor.decodeToken(tokenString); - if (parsed !== undefined) { - const uuidResourcePermissions = parsed.res.uuid ? Object.keys(parsed.res.uuid) : []; - const userResourcePermissions = parsed.res.usr ? Object.keys(parsed.res.usr) : []; - const channelResourcePermissions = Object.keys(parsed.res.chan); - const groupResourcePermissions = Object.keys(parsed.res.grp); - const uuidPatternPermissions = parsed.pat.uuid ? Object.keys(parsed.pat.uuid) : []; - const userPatternPermissions = parsed.pat.usr ? Object.keys(parsed.pat.usr) : []; - const channelPatternPermissions = Object.keys(parsed.pat.chan); - const groupPatternPermissions = Object.keys(parsed.pat.grp); - const result = { - version: parsed.v, - timestamp: parsed.t, - ttl: parsed.ttl, - authorized_uuid: parsed.uuid, - signature: parsed.sig, - }; - const uuidResources = uuidResourcePermissions.length > 0; - const userResources = userResourcePermissions.length > 0; - const channelResources = channelResourcePermissions.length > 0; - const groupResources = groupResourcePermissions.length > 0; - if (uuidResources || userResources || channelResources || groupResources) { - result.resources = {}; - if (uuidResources) { - const uuids = (result.resources.uuids = {}); - uuidResourcePermissions.forEach((id) => (uuids[id] = this.extractPermissions(parsed.res.uuid[id]))); - } - if (userResources) { - const users = (result.resources.users = {}); - userResourcePermissions.forEach((id) => (users[id] = this.extractCrudPermissions(parsed.res.usr[id]))); - } - if (channelResources) { - const channels = (result.resources.channels = {}); - channelResourcePermissions.forEach((id) => (channels[id] = this.extractPermissions(parsed.res.chan[id]))); - } - if (groupResources) { - const groups = (result.resources.groups = {}); - groupResourcePermissions.forEach((id) => (groups[id] = this.extractPermissions(parsed.res.grp[id]))); - } - } - const resourceDataSync = this.extractDataSyncScopes(parsed.res); - if (resourceDataSync) - ((_a = result.resources) !== null && _a !== void 0 ? _a : (result.resources = {})).dataSync = resourceDataSync; - const uuidPatterns = uuidPatternPermissions.length > 0; - const userPatterns = userPatternPermissions.length > 0; - const channelPatterns = channelPatternPermissions.length > 0; - const groupPatterns = groupPatternPermissions.length > 0; - if (uuidPatterns || userPatterns || channelPatterns || groupPatterns) { - result.patterns = {}; - if (uuidPatterns) { - const uuids = (result.patterns.uuids = {}); - uuidPatternPermissions.forEach((id) => (uuids[id] = this.extractPermissions(parsed.pat.uuid[id]))); - } - if (userPatterns) { - const users = (result.patterns.users = {}); - userPatternPermissions.forEach((id) => (users[id] = this.extractCrudPermissions(parsed.pat.usr[id]))); - } - if (channelPatterns) { - const channels = (result.patterns.channels = {}); - channelPatternPermissions.forEach((id) => (channels[id] = this.extractPermissions(parsed.pat.chan[id]))); - } - if (groupPatterns) { - const groups = (result.patterns.groups = {}); - groupPatternPermissions.forEach((id) => (groups[id] = this.extractPermissions(parsed.pat.grp[id]))); - } - } - const patternDataSync = this.extractDataSyncScopes(parsed.pat); - if (patternDataSync) - ((_b = result.patterns) !== null && _b !== void 0 ? _b : (result.patterns = {})).dataSync = patternDataSync; - const categories = this.extractCategories(parsed.cat); - if (categories) - result.categories = categories; - if (parsed.meta && Object.keys(parsed.meta).length > 0) - result.meta = parsed.meta; - return result; - } - return undefined; - } - /** - * Extract resource access permission information. - * - * @param permissions - Bit-encoded resource permissions. - * - * @returns Human-readable resource permissions. - */ - extractPermissions(permissions) { - const permissionsResult = { - read: false, - write: false, - manage: false, - delete: false, - get: false, - update: false, - join: false, - }; - if ((permissions & 128) === 128) - permissionsResult.join = true; - if ((permissions & 64) === 64) - permissionsResult.update = true; - if ((permissions & 32) === 32) - permissionsResult.get = true; - if ((permissions & 8) === 8) - permissionsResult.delete = true; - if ((permissions & 4) === 4) - permissionsResult.manage = true; - if ((permissions & 2) === 2) - permissionsResult.write = true; - if ((permissions & 1) === 1) - permissionsResult.read = true; - return permissionsResult; - } - /** - * Extract category-level permissions from the token `cat` section. - * - * `chan` maps to `channels` and `uuid` maps to `uuids`. `get` is set from the `32` bit. The - * section is omitted when `cat` is absent or empty. - * - * @param cat - Raw `cat` section decoded from the token. - * - * @returns Human-readable category permissions, or `undefined` when none are present. - */ - extractCategories(cat) { - if (!cat) - return undefined; - const result = {}; - if (typeof cat.chan === 'number') - result.channels = { get: (cat.chan & 32) === 32 }; - if (typeof cat.uuid === 'number') - result.uuids = { get: (cat.uuid & 32) === 32 }; - return Object.keys(result).length > 0 ? result : undefined; - } - /** - * Extract DataSync permission scopes from a token permissions section. - * - * The `datasync:*` wire keys are only present for tokens which granted DataSync permissions, so a - * result is returned only when at least one scope carries permissions. - * - * @param section - Raw `res` or `pat` permissions section decoded from the token. - * - * @returns Human-readable DataSync permission scopes, or `undefined` when none are granted. - */ - extractDataSyncScopes(section) { - const dataSyncScopes = [ - ['entities', 'datasync:entities'], - ['relationships', 'datasync:relationships'], - ['memberships', 'datasync:memberships'], - ]; - let result; - dataSyncScopes.forEach(([scope, wireKey]) => { - const permissions = section[wireKey]; - if (!permissions) - return; - const ids = Object.keys(permissions); - if (ids.length === 0) - return; - const scopeResult = ((result !== null && result !== void 0 ? result : (result = {}))[scope] = {}); - ids.forEach((id) => (scopeResult[id] = this.extractCrudPermissions(permissions[id]))); - }); - return result; - } - /** - * Extract CRUD-only access permission information. - * - * Shared by the `usr` wire key (which backs the `users` grant scope) and the `datasync:*` wire - * keys — both carry the same CRUD bit layout and none of the `read` / `write` / `manage` / `join` - * bits decoded by {@link extractPermissions}. - * - * @param permissions - Bit-encoded resource permissions. - * - * @returns Human-readable CRUD resource permissions. - */ - extractCrudPermissions(permissions) { - return { - create: (permissions & 16) === 16, - get: (permissions & 32) === 32, - update: (permissions & 64) === 64, - delete: (permissions & 8) === 8, - }; - } - } - - /** - * Enum representing possible transport methods for HTTP requests. - * - * @enum {number} - */ - var TransportMethod; - (function (TransportMethod) { - /** - * Request will be sent using `GET` method. - */ - TransportMethod["GET"] = "GET"; - /** - * Request will be sent using `POST` method. - */ - TransportMethod["POST"] = "POST"; - /** - * Request will be sent using `PATCH` method. - */ - TransportMethod["PATCH"] = "PATCH"; - /** - * Request will be sent using `PUT` method. - */ - TransportMethod["PUT"] = "PUT"; - /** - * Request will be sent using `DELETE` method. - */ - TransportMethod["DELETE"] = "DELETE"; - /** - * Local request. - * - * Request won't be sent to the service and probably used to compute URL. - */ - TransportMethod["LOCAL"] = "LOCAL"; - })(TransportMethod || (TransportMethod = {})); - - /** - * Common PubNub Network Provider middleware module. - * - * @internal - */ - /** - * Request signature generator. - * - * @internal - */ - class RequestSignature { - constructor(publishKey, secretKey, hasher, logger) { - this.publishKey = publishKey; - this.secretKey = secretKey; - this.hasher = hasher; - this.logger = logger; - } - /** - * Compute request signature. - * - * @param req - Request which will be used to compute signature. - * @returns {string} `v2` request signature. - */ - signature(req) { - const method = req.path.startsWith('/publish') ? TransportMethod.GET : req.method; - let signatureInput = `${method}\n${this.publishKey}\n${req.path}\n${this.queryParameters(req.queryParameters)}\n`; - if (method === TransportMethod.POST || method === TransportMethod.PATCH || method === TransportMethod.PUT) { - const body = req.body; - let payload; - if (body && body instanceof ArrayBuffer) { - payload = RequestSignature.textDecoder.decode(body); - } - else if (body && typeof body !== 'object') { - payload = body; - } - if (payload) - signatureInput += payload; - } - this.logger.trace('RequestSignature', () => ({ - messageType: 'text', - message: `Request signature input:\n${signatureInput}`, - })); - return `v2.${this.hasher(signatureInput, this.secretKey)}` - .replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/=+$/, ''); - } - /** - * Prepare request query parameters for signature. - * - * @param query - Key / value pair of the request query parameters. - * @private - */ - queryParameters(query) { - return Object.keys(query) - .sort() - .map((key) => { - const queryValue = query[key]; - if (!Array.isArray(queryValue)) - return `${key}=${encodeString(queryValue)}`; - return queryValue - .sort() - .map((value) => `${key}=${encodeString(value)}`) - .join('&'); - }) - .join('&'); - } - } - RequestSignature.textDecoder = new TextDecoder('utf-8'); - /** - * Common PubNub Network Provider middleware. - * - * @internal - */ - class PubNubMiddleware { - constructor(configuration) { - this.configuration = configuration; - const { clientConfiguration: { keySet }, shaHMAC, } = configuration; - { - if (keySet.secretKey && shaHMAC) - this.signatureGenerator = new RequestSignature(keySet.publishKey, keySet.secretKey, shaHMAC, this.logger); - } - } - /** - * Retrieve registered loggers' manager. - * - * @returns Registered loggers' manager. - */ - get logger() { - return this.configuration.clientConfiguration.logger(); - } - makeSendable(req) { - const retryPolicy = this.configuration.clientConfiguration.retryConfiguration; - const transport = this.configuration.transport; - // Make requests retryable. - if (retryPolicy !== undefined) { - let retryTimeout; - let activeCancellation; - let canceled = false; - let attempt = 0; - const cancellation = { - abort: (reason) => { - canceled = true; - if (retryTimeout) - clearTimeout(retryTimeout); - if (activeCancellation) - activeCancellation.abort(reason); - }, - }; - const retryableRequest = new Promise((resolve, reject) => { - const trySendRequest = () => { - // Check whether the request already has been canceled and there is no retry should proceed. - if (canceled) - return; - const [attemptPromise, attemptCancellation] = transport.makeSendable(this.request(req)); - activeCancellation = attemptCancellation; - const responseHandler = (res, error) => { - let delay = -1; - // Retry ability (error category, HTTP status code, excluded endpoints and attempts count) is entirely - // decided by the retry policy. - if (retryPolicy.shouldRetry(req, res, error === null || error === void 0 ? void 0 : error.category, attempt + 1, error === null || error === void 0 ? void 0 : error.statusCode)) - delay = retryPolicy.getDelay(attempt, res); - if (delay > 0) { - attempt++; - this.logger.warn('PubNubMiddleware', `HTTP request retry #${attempt} in ${delay}ms.`); - retryTimeout = setTimeout(() => trySendRequest(), delay); - } - else { - if (res) - resolve(res); - else if (error) - reject(error); - } - }; - attemptPromise - .then((res) => responseHandler(res)) - .catch((err) => responseHandler(undefined, err)); - }; - trySendRequest(); - }); - return [retryableRequest, activeCancellation ? cancellation : undefined]; - } - return transport.makeSendable(this.request(req)); - } - request(req) { - var _a; - const { clientConfiguration } = this.configuration; - // Get request patched by transport provider. - req = this.configuration.transport.request(req); - if (!req.queryParameters) - req.queryParameters = {}; - // Modify the request with required information. - if (clientConfiguration.useInstanceId) - req.queryParameters['instanceid'] = clientConfiguration.getInstanceId(); - if (!req.queryParameters['uuid']) - req.queryParameters['uuid'] = clientConfiguration.userId; - if (clientConfiguration.useRequestId) - req.queryParameters['requestid'] = req.identifier; - req.queryParameters['pnsdk'] = this.generatePNSDK(); - (_a = req.origin) !== null && _a !== void 0 ? _a : (req.origin = clientConfiguration.origin); - // Authenticate request if required. - this.authenticateRequest(req); - // Sign request if it is required. - this.signRequest(req); - return req; - } - authenticateRequest(req) { - var _a; - // Access management endpoints don't need authentication (signature required instead). - if (req.path.startsWith('/v2/auth/') || req.path.startsWith('/v3/pam/') || req.path.startsWith('/time')) - return; - const { clientConfiguration, tokenManager } = this.configuration; - const accessKey = (_a = (tokenManager && tokenManager.getToken())) !== null && _a !== void 0 ? _a : clientConfiguration.authKey; - if (accessKey) - req.queryParameters['auth'] = accessKey; - } - /** - * Compute and append request signature. - * - * @param req - Transport request with information which should be used to generate signature. - */ - signRequest(req) { - if (!this.signatureGenerator || req.path.startsWith('/time')) - return; - req.queryParameters['timestamp'] = String(Math.floor(new Date().getTime() / 1000)); - req.queryParameters['signature'] = this.signatureGenerator.signature(req); - } - /** - * Compose `pnsdk` query parameter. - * - * SDK provides ability to set custom name or append vendor information to the `pnsdk` query - * parameter. - * - * @returns Finalized `pnsdk` query parameter value. - */ - generatePNSDK() { - const { clientConfiguration } = this.configuration; - if (clientConfiguration.sdkName) - return clientConfiguration.sdkName; - let base = `PubNub-JS-${clientConfiguration.sdkFamily}`; - if (clientConfiguration.partnerId) - base += `-${clientConfiguration.partnerId}`; - base += `/${clientConfiguration.getVersion()}`; - const pnsdkSuffix = clientConfiguration._getPnsdkSuffix(' '); - if (pnsdkSuffix.length > 0) - base += pnsdkSuffix; - return base; - } - } - - /** - * Common browser and React Native Transport provider module. - * - * @internal - */ - /** - * Class representing a `fetch`-based browser and React Native transport provider. - * - * @internal - */ - class WebTransport { - /** - * Create and configure transport provider for Web and Rect environments. - * - * @param logger - Registered loggers' manager. - * @param [transport] - API, which should be used to make network requests. - * - * @internal - */ - constructor(logger, transport = 'fetch') { - this.logger = logger; - this.transport = transport; - logger.debug('WebTransport', `Create with configuration:\n - transport: ${transport}`); - // Check for `fetch` availability directly (works in DOM and DOM-less contexts such as service workers). - // because a bare `window` reference would throw in a service worker, and a partial `window = self` shim can - // define `window` without `fetch`, so probe the actual `fetch` global via `typeof`. - if (transport === 'fetch' && typeof fetch === 'undefined') { - logger.warn('WebTransport', `'${transport}' not supported in this browser. Fallback to the 'xhr' transport.`); - this.transport = 'xhr'; - } - if (this.transport !== 'fetch') - return; - // Storing reference on original `fetch` function implementation as protection against APM lib monkey patching. - // - // This is done unconditionally (not gated on `isFetchMonkeyPatched()`): APM libraries can defeat that - // detection by overriding stringification to report `[native code]` while still patching `fetch`, so we - // cannot rely on it to decide whether the workaround is needed. `getOriginalFetch()` itself decides how to - // obtain the reference based on the environment (iframe when a DOM is available, context `fetch` otherwise), - // which keeps construction safe in DOM-less contexts such as MV3 service workers. - WebTransport.originalFetch = WebTransport.getOriginalFetch(); - // Check whether `fetch` has been monkey patched or not. - if (this.isFetchMonkeyPatched()) - logger.warn('WebTransport', "Native Web Fetch API 'fetch' function monkey patched."); - } - makeSendable(req) { - const abortController = new AbortController(); - const cancellation = { - abortController, - abort: (reason) => { - if (!abortController.signal.aborted) { - this.logger.trace('WebTransport', `On-demand request aborting: ${reason}`); - abortController.abort(reason); - } - }, - }; - return [ - this.webTransportRequestFromTransportRequest(req).then((request) => { - this.logger.debug('WebTransport', () => ({ messageType: 'network-request', message: req })); - return this.sendRequest(request, cancellation) - .then((response) => response.arrayBuffer().then((arrayBuffer) => [response, arrayBuffer])) - .then((response) => { - const body = response[1].byteLength > 0 ? response[1] : undefined; - const { status, headers: requestHeaders } = response[0]; - const headers = {}; - // Copy Headers object content into plain Record. - requestHeaders.forEach((value, key) => (headers[key] = value.toLowerCase())); - const transportResponse = { status, url: request.url, headers, body }; - this.logger.debug('WebTransport', () => ({ - messageType: 'network-response', - message: transportResponse, - })); - if (status >= 400) - throw PubNubAPIError.create(transportResponse); - return transportResponse; - }) - .catch((error) => { - const errorMessage = (typeof error === 'string' ? error : error.message).toLowerCase(); - let fetchError = typeof error === 'string' ? new Error(error) : error; - if (errorMessage.includes('timeout')) { - this.logger.warn('WebTransport', () => ({ - messageType: 'network-request', - message: req, - details: 'Timeout', - canceled: true, - })); - } - else if (errorMessage.includes('cancel') || errorMessage.includes('abort')) { - this.logger.debug('WebTransport', () => ({ - messageType: 'network-request', - message: req, - details: 'Aborted', - canceled: true, - })); - fetchError = new Error('Aborted'); - fetchError.name = 'AbortError'; - } - else if (errorMessage.includes('network')) { - this.logger.warn('WebTransport', () => ({ - messageType: 'network-request', - message: req, - details: 'Network error', - failed: true, - })); - } - else { - this.logger.warn('WebTransport', () => ({ - messageType: 'network-request', - message: req, - details: PubNubAPIError.create(fetchError).message, - failed: true, - })); - } - throw PubNubAPIError.create(fetchError); - }); - }), - cancellation, - ]; - } - request(req) { - return req; - } - /** - * Send network request using preferred API. - * - * @param req - Transport API agnostic request object with prepared body and URL. - * @param controller - Request cancellation controller (for long-poll requests). - * - * @returns Promise which will be resolved or rejected at the end of network request processing. - * - * @internal - */ - sendRequest(req, controller) { - return __awaiter(this, void 0, void 0, function* () { - if (this.transport === 'fetch') - return this.sendFetchRequest(req, controller); - return this.sendXHRRequest(req, controller); - }); - } - /** - * Send network request using legacy XMLHttpRequest API. - * - * @param req - Transport API agnostic request object with prepared body and URL. - * @param controller - Request cancellation controller (for long-poll requests). - * - * @returns Promise which will be resolved or rejected at the end of network request processing. - * - * @internal - */ - sendFetchRequest(req, controller) { - return __awaiter(this, void 0, void 0, function* () { - let timeoutId; - const requestTimeout = new Promise((_, reject) => { - timeoutId = setTimeout(() => { - clearTimeout(timeoutId); - reject(new Error('Request timeout')); - controller.abort('Cancel because of timeout'); - }, req.timeout * 1000); - }); - const request = new Request(req.url, { - method: req.method, - headers: req.headers, - redirect: 'follow', - body: req.body, - }); - return Promise.race([ - WebTransport.originalFetch(request, { - signal: controller.abortController.signal, - credentials: 'omit', - cache: 'no-cache', - }).then((response) => { - if (timeoutId) - clearTimeout(timeoutId); - return response; - }), - requestTimeout, - ]); - }); - } - /** - * Send network request using legacy XMLHttpRequest API. - * - * @param req - Transport API agnostic request object with prepared body and URL. - * @param controller - Request cancellation controller (for long-poll requests). - * - * @returns Promise which will be resolved or rejected at the end of network request processing. - * - * @internal - */ - sendXHRRequest(req, controller) { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => { - var _a; - const xhr = new XMLHttpRequest(); - xhr.open(req.method, req.url, true); - let aborted = false; - // Setup request - xhr.responseType = 'arraybuffer'; - xhr.timeout = req.timeout * 1000; - controller.abortController.signal.onabort = () => { - if (xhr.readyState == XMLHttpRequest.DONE || xhr.readyState == XMLHttpRequest.UNSENT) - return; - aborted = true; - xhr.abort(); - }; - Object.entries((_a = req.headers) !== null && _a !== void 0 ? _a : {}).forEach(([key, value]) => xhr.setRequestHeader(key, value)); - // Setup handlers to match `fetch` results handling. - xhr.onabort = () => { - reject(new Error('Aborted')); - }; - xhr.ontimeout = () => { - reject(new Error('Request timeout')); - }; - xhr.onerror = () => { - if (!aborted) { - const response = this.transportResponseFromXHR(req.url, xhr); - reject(new Error(PubNubAPIError.create(response).message)); - } - }; - xhr.onload = () => { - const headers = new Headers(); - xhr - .getAllResponseHeaders() - .split('\r\n') - .forEach((header) => { - const [key, value] = header.split(': '); - if (key.length > 1 && value.length > 1) - headers.append(key, value); - }); - resolve(new Response(xhr.response, { status: xhr.status, headers, statusText: xhr.statusText })); - }; - xhr.send(req.body); - }); - }); - } - /** - * Creates a Web Request object from a given {@link TransportRequest} object. - * - * @param req - The {@link TransportRequest} object containing request information. - * - * @returns Request object generated from the {@link TransportRequest} object. - * - * @internal - */ - webTransportRequestFromTransportRequest(req) { - return __awaiter(this, void 0, void 0, function* () { - let body; - let path = req.path; - // Create a multipart request body. - if (req.formData && req.formData.length > 0) { - // Reset query parameters to conform to signed URL - req.queryParameters = {}; - const file = req.body; - const formData = new FormData(); - for (const { key, value } of req.formData) - formData.append(key, value); - try { - const fileData = yield file.toArrayBuffer(); - formData.append('file', new Blob([fileData], { type: 'application/octet-stream' }), file.name); - } - catch (toBufferError) { - this.logger.warn('WebTransport', () => ({ messageType: 'error', message: toBufferError })); - try { - const fileData = yield file.toFileUri(); - // @ts-expect-error React Native File Uri support. - formData.append('file', fileData, file.name); - } - catch (toFileURLError) { - this.logger.error('WebTransport', () => ({ messageType: 'error', message: toFileURLError })); - } - } - body = formData; - } - // Handle regular body payload (if passed). - else if (req.body && (typeof req.body === 'string' || req.body instanceof ArrayBuffer)) { - // Compressing body if the browser has native support. - if (req.compressible && typeof CompressionStream !== 'undefined') { - const bodyArrayBuffer = typeof req.body === 'string' ? WebTransport.encoder.encode(req.body) : req.body; - const initialBodySize = bodyArrayBuffer.byteLength; - const bodyStream = new ReadableStream({ - start(controller) { - controller.enqueue(bodyArrayBuffer); - controller.close(); - }, - }); - body = yield new Response(bodyStream.pipeThrough(new CompressionStream('deflate'))).arrayBuffer(); - this.logger.trace('WebTransport', () => { - const compressedSize = body.byteLength; - const ratio = (compressedSize / initialBodySize).toFixed(2); - return { - messageType: 'text', - message: `Body of ${initialBodySize} bytes, compressed by ${ratio}x to ${compressedSize} bytes.`, - }; - }); - } - else - body = req.body; - } - if (req.queryParameters && Object.keys(req.queryParameters).length !== 0) - path = `${path}?${queryStringFromObject(req.queryParameters)}`; - return { - url: `${req.origin}${path}`, - method: req.method, - headers: req.headers, - timeout: req.timeout, - body, - }; - }); - } - /** - * Check whether the original ` fetch ` has been monkey patched or not. - * - * @returns `true` if original `fetch` has been patched. - */ - isFetchMonkeyPatched(oFetch) { - const fetchString = (oFetch !== null && oFetch !== void 0 ? oFetch : fetch).toString(); - return !fetchString.includes('[native code]') && fetch.name !== 'fetch'; - } - /** - * Create service response from {@link XMLHttpRequest} processing result. - * - * @param url - Used endpoint url. - * @param xhr - `HTTPClient`, which has been used to make a request. - * - * @returns Pre-processed transport response. - */ - transportResponseFromXHR(url, xhr) { - const allHeaders = xhr.getAllResponseHeaders().split('\n'); - const headers = {}; - for (const header of allHeaders) { - const [key, value] = header.trim().split(':'); - if (key && value) - headers[key.toLowerCase()] = value.trim(); - } - return { status: xhr.status, url, headers, body: xhr.response }; - } - /** - * Retrieve the original ` fetch ` implementation. - * - * Retrieve implementation which hasn't been patched by APM tools. - * - * @returns Reference to the `fetch` function. - */ - static getOriginalFetch() { - // The iframe-based APM workaround requires a DOM. In DOM-less contexts (e.g. MV3 service workers) there is - // no `document`, and `fetch` cannot be reached through a fresh browsing context — return the context `fetch` - // directly. This is safe there: without a DOM there is no APM page script to monkey patch `fetch` in the - // first place. This environment check is what keeps the unconditional call in the constructor safe. - // - // `fetch` must be bound to the global scope: native `fetch` requires its `this` to be the `Window` / - // `WorkerGlobalScope`, and it is later invoked detached (`WebTransport.originalFetch(...)`). Without the bind - // a service worker throws "Failed to execute 'fetch' on 'WorkerGlobalScope': Illegal invocation". - if (typeof document === 'undefined' || !document.body) - return fetch.bind(globalThis); - let iframe = document.querySelector('iframe[name="pubnub-context-unpatched-fetch"]'); - if (!iframe) { - iframe = document.createElement('iframe'); - iframe.style.display = 'none'; - iframe.name = 'pubnub-context-unpatched-fetch'; - iframe.src = 'about:blank'; - document.body.appendChild(iframe); - } - if (iframe.contentWindow) - return iframe.contentWindow.fetch.bind(iframe.contentWindow); - return fetch.bind(globalThis); - } - } - /** - * Request body decoder. - * - * @internal - */ - WebTransport.encoder = new TextEncoder(); - /** - * Service {@link ArrayBuffer} response decoder. - * - * @internal - */ - WebTransport.decoder = new TextDecoder(); - - /** - * Network request module. - * - * @internal - */ - /** - * Base REST API request class. - * - * @internal - */ - class AbstractRequest { - /** - * Construct base request. - * - * Constructed request by default won't be cancellable and performed using `GET` HTTP method. - * - * @param params - Request configuration parameters. - */ - constructor(params) { - this.params = params; - /** - * Unique request identifier. - */ - this.requestIdentifier = uuidGenerator.createUUID(); - this._cancellationController = null; - } - /** - * Retrieve configured cancellation controller. - * - * @returns Cancellation controller. - */ - get cancellationController() { - return this._cancellationController; - } - /** - * Update request cancellation controller. - * - * Controller itself provided by transport provider implementation and set only when request - * sending has been scheduled. - * - * @param controller - Cancellation controller or `null` to reset it. - */ - set cancellationController(controller) { - this._cancellationController = controller; - } - /** - * Abort request if possible. - * - * @param [reason] Information about why request has been cancelled. - */ - abort(reason) { - if (this && this.cancellationController) - this.cancellationController.abort(reason); - } - /** - * Target REST API endpoint operation type. - */ - operation() { - throw Error('Should be implemented by subclass.'); - } - /** - * Validate user-provided data before scheduling request. - * - * @returns Error message if request can't be sent without missing or malformed parameters. - */ - validate() { - return undefined; - } - /** - * Parse service response. - * - * @param response - Raw service response which should be parsed. - */ - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return this.deserializeResponse(response); - }); - } - /** - * Create platform-agnostic request object. - * - * @returns Request object which can be processed using platform-specific requirements. - */ - request() { - var _a, _b, _c, _d, _e, _f; - const request = { - method: (_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.method) !== null && _b !== void 0 ? _b : TransportMethod.GET, - path: this.path, - queryParameters: this.queryParameters, - cancellable: (_d = (_c = this.params) === null || _c === void 0 ? void 0 : _c.cancellable) !== null && _d !== void 0 ? _d : false, - compressible: (_f = (_e = this.params) === null || _e === void 0 ? void 0 : _e.compressible) !== null && _f !== void 0 ? _f : false, - timeout: 10, - identifier: this.requestIdentifier, - }; - // Attach headers (if required). - const headers = this.headers; - if (headers) - request.headers = headers; - // Attach body (if required). - if (request.method === TransportMethod.POST || - request.method === TransportMethod.PATCH || - request.method === TransportMethod.PUT) { - const [body, formData] = [this.body, this.formData]; - if (formData) - request.formData = formData; - if (body) - request.body = body; - } - return request; - } - /** - * Target REST API endpoint request headers getter. - * - * @returns Key/value headers which should be used with request. - */ - get headers() { - var _a, _b; - return Object.assign({ 'Accept-Encoding': 'gzip, deflate' }, (((_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.compressible) !== null && _b !== void 0 ? _b : false) ? { 'Content-Encoding': 'deflate' } : {})); - } - /** - * Target REST API endpoint request path getter. - * - * @returns REST API path. - */ - get path() { - throw Error('`path` getter should be implemented by subclass.'); - } - /** - * Target REST API endpoint request query parameters getter. - * - * @returns Key/value pairs which should be appended to the REST API path. - */ - get queryParameters() { - return {}; - } - get formData() { - return undefined; - } - /** - * Target REST API Request body payload getter. - * - * @returns Buffer of stringified data which should be sent with `POST` or `PATCH` request. - */ - get body() { - return undefined; - } - /** - * Deserialize service response. - * - * @param response - Transparent response object with headers and body information. - * - * @returns Deserialized service response data. - * - * @throws {Error} if received service response can't be processed (has unexpected content-type or can't be parsed as - * JSON). - */ - deserializeResponse(response) { - const responseText = AbstractRequest.decoder.decode(response.body); - const contentType = response.headers['content-type']; - let parsedJson; - if (!contentType || (contentType.indexOf('javascript') === -1 && contentType.indexOf('json') === -1)) - throw new PubNubError('Service response error, check status for details', createMalformedResponseError(responseText, response.status)); - try { - parsedJson = JSON.parse(responseText); - } - catch (error) { - console.error('Error parsing JSON response:', error); - throw new PubNubError('Service response error, check status for details', createMalformedResponseError(responseText, response.status)); - } - // Throw and exception in case of client / server error. - if ('status' in parsedJson && typeof parsedJson.status === 'number' && parsedJson.status >= 400) - throw PubNubAPIError.create(response); - return parsedJson; - } - } - /** - * Service `ArrayBuffer` response decoder. - */ - AbstractRequest.decoder = new TextDecoder(); - - /** - * Subscription REST API module. - */ - // -------------------------------------------------------- - // ---------------------- Defaults ------------------------ - // -------------------------------------------------------- - // region Defaults - /** - * Whether should subscribe to channels / groups presence announcements or not. - */ - const WITH_PRESENCE = false; - // endregion - // -------------------------------------------------------- - // ------------------------ Types ------------------------- - // -------------------------------------------------------- - // region Types - /** - * PubNub-defined event types by payload. - */ - var PubNubEventType; - (function (PubNubEventType) { - /** - * Presence change event. - */ - PubNubEventType[PubNubEventType["Presence"] = -2] = "Presence"; - /** - * Regular message event. - * - * **Note:** This is default type assigned for non-presence events if `e` field is missing. - */ - PubNubEventType[PubNubEventType["Message"] = -1] = "Message"; - /** - * Signal data event. - */ - PubNubEventType[PubNubEventType["Signal"] = 1] = "Signal"; - /** - * App Context object event. - */ - PubNubEventType[PubNubEventType["AppContext"] = 2] = "AppContext"; - /** - * Message reaction event. - */ - PubNubEventType[PubNubEventType["MessageAction"] = 3] = "MessageAction"; - /** - * Files event. - */ - PubNubEventType[PubNubEventType["Files"] = 4] = "Files"; - /** - * DataSync object change event. - * - * **Note:** Value must equal `5` to match the service wire value (`e: 5`). - */ - PubNubEventType[PubNubEventType["DataSync"] = 5] = "DataSync"; - })(PubNubEventType || (PubNubEventType = {})); - /** - * Event types which this SDK version knows how to parse. - * - * Events with any other `e` value are ignored: they most likely originate from a service release newer than - * the SDK - */ - const KNOWN_EVENT_TYPES = new Set([ - PubNubEventType.Presence, - PubNubEventType.Message, - PubNubEventType.Signal, - PubNubEventType.AppContext, - PubNubEventType.MessageAction, - PubNubEventType.Files, - PubNubEventType.DataSync, - ]); - /** - * Reserved DataSync system class names (lower-cased) → normalized object kind. - * - * Only consulted when the wire {@link DataSyncData.type} is the generic `entity` / `relationship` - * kind, and only for classes the service marks as `Global` (see {@link DataSyncClassLevel}) — so a - * developer-defined class which happens to share one of these names is not mistaken for a typed - * resource. Keys are compared case-insensitively. - * - * @internal - */ - const DATA_SYNC_RESERVED_CLASSES = { - user: 'user', - channel: 'channel', - membership: 'membership', - }; - // endregion - /** - * Base subscription request implementation. - * - * Subscription request used in small variations in two cases: - * - subscription manager - * - event engine - * - * @internal - */ - class BaseSubscribeRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c; - var _d, _e, _f; - super({ cancellable: true }); - this.parameters = parameters; - // Apply default request parameters. - (_a = (_d = this.parameters).withPresence) !== null && _a !== void 0 ? _a : (_d.withPresence = WITH_PRESENCE); - (_b = (_e = this.parameters).channelGroups) !== null && _b !== void 0 ? _b : (_e.channelGroups = []); - (_c = (_f = this.parameters).channels) !== null && _c !== void 0 ? _c : (_f.channels = []); - } - operation() { - return RequestOperation$1.PNSubscribeOperation; - } - validate() { - const { keySet: { subscribeKey }, channels, channelGroups, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channels && !channelGroups) - return '`channels` and `channelGroups` both should not be empty'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - let serviceResponse; - let responseText; - try { - responseText = AbstractRequest.decoder.decode(response.body); - const parsedJson = JSON.parse(responseText); - serviceResponse = parsedJson; - } - catch (error) { - console.error('Error parsing JSON response:', error); - } - if (!serviceResponse) { - throw new PubNubError('Service response error, check status for details', createMalformedResponseError(responseText, response.status)); - } - const events = serviceResponse.m - .filter((envelope) => { - const subscribable = envelope.b === undefined ? envelope.c : envelope.b; - return ((this.parameters.channels && this.parameters.channels.includes(subscribable)) || - (this.parameters.channelGroups && this.parameters.channelGroups.includes(subscribable))); - }) - .map((envelope) => { - let { e: eventType } = envelope; - // Events delivered on a presence channel are always presence events: the `-pnpres` suffix wins over - // the service-reported type. `envelope.c` is the actual channel (`envelope.b` is the channel group - // name), so this also covers presence delivered through a subscribed channel group. - if (envelope.c.endsWith('-pnpres')) - eventType = PubNubEventType.Presence; - // Resolve missing event type. - else - eventType !== null && eventType !== void 0 ? eventType : (eventType = PubNubEventType.Message); - // Ignore an event type this SDK version cannot parse rather than delivering an unexpected payload. - if (!KNOWN_EVENT_TYPES.has(eventType)) - return undefined; - const pn_mfp = messageFingerprint(envelope.d); - // Check whether payload is string (potentially encrypted data). - if (eventType != PubNubEventType.Presence && - eventType != PubNubEventType.Signal && - typeof envelope.d === 'string') { - if (eventType == PubNubEventType.Message) { - return { - type: PubNubEventType.Message, - data: this.messageFromEnvelope(envelope), - pn_mfp, - }; - } - return { - type: PubNubEventType.Files, - data: this.fileFromEnvelope(envelope), - pn_mfp, - }; - } - else if (eventType == PubNubEventType.Message) { - return { - type: PubNubEventType.Message, - data: this.messageFromEnvelope(envelope), - pn_mfp, - }; - } - else if (eventType === PubNubEventType.Presence) { - return { - type: PubNubEventType.Presence, - data: this.presenceEventFromEnvelope(envelope), - pn_mfp, - }; - } - else if (eventType == PubNubEventType.Signal) { - return { - type: PubNubEventType.Signal, - data: this.signalFromEnvelope(envelope), - pn_mfp, - }; - } - else if (eventType === PubNubEventType.AppContext) { - return { - type: PubNubEventType.AppContext, - data: this.appContextFromEnvelope(envelope), - pn_mfp, - }; - } - else if (eventType === PubNubEventType.MessageAction) { - return { - type: PubNubEventType.MessageAction, - data: this.messageActionFromEnvelope(envelope), - pn_mfp, - }; - } - else if (eventType === PubNubEventType.DataSync) { - const dataSync = this.dataSyncFromEnvelope(envelope); - // Guard: only treat as DataSync when the service marks it so; otherwise fall back to message. - if (dataSync) - return { type: PubNubEventType.DataSync, data: dataSync, pn_mfp }; - return { type: PubNubEventType.Message, data: this.messageFromEnvelope(envelope), pn_mfp }; - } - // The only known event type left is a file event. - return { - type: PubNubEventType.Files, - data: this.fileFromEnvelope(envelope), - pn_mfp, - }; - }) - .filter((event) => event !== undefined); - return { - cursor: { timetoken: serviceResponse.t.t, region: serviceResponse.t.r }, - messages: events, - }; - }); - } - get headers() { - var _a; - return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { accept: 'text/javascript' }); - } - // -------------------------------------------------------- - // ------------------ Envelope parsing -------------------- - // -------------------------------------------------------- - // region Envelope parsing - presenceEventFromEnvelope(envelope) { - var _a; - const { d: payload } = envelope; - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - // Clean up channel and subscription name from presence suffix. - const trimmedChannel = channel.replace('-pnpres', ''); - // Backward compatibility with deprecated properties. - const actualChannel = subscription !== null ? trimmedChannel : null; - const subscribedChannel = subscription !== null ? subscription : trimmedChannel; - // Presence payloads are objects. A string can only reach here when a non-presence payload has been published - // on a `-pnpres` channel: try to read it as JSON and never spread a string (which would add character-indexed - // keys to the event). - let presenceData; - if (typeof payload === 'string') { - try { - const parsed = JSON.parse(payload); - if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) - presenceData = parsed; - } - catch (_b) { - // Not JSON (encrypted or plain-text publish): payload contributes no presence fields. - } - } - else - presenceData = payload; - if (presenceData) { - if ('data' in presenceData) { - // @ts-expect-error This is `state-change` object which should have `state` field. - presenceData['state'] = presenceData.data; - delete presenceData.data; - } - else if ('action' in presenceData && presenceData.action === 'interval') { - presenceData.hereNowRefresh = (_a = presenceData.here_now_refresh) !== null && _a !== void 0 ? _a : false; - delete presenceData.here_now_refresh; - } - } - return Object.assign({ channel: trimmedChannel, subscription, - actualChannel, - subscribedChannel, timetoken: envelope.p.t }, (presenceData !== null && presenceData !== void 0 ? presenceData : {})); - } - messageFromEnvelope(envelope) { - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - const [message, decryptionError] = this.decryptedData(envelope.d); - // Backward compatibility with deprecated properties. - const actualChannel = subscription !== null ? channel : null; - const subscribedChannel = subscription !== null ? subscription : channel; - // Basic message event payload. - const event = { - channel, - subscription, - actualChannel, - subscribedChannel, - timetoken: envelope.p.t, - publisher: envelope.i, - message, - }; - if (envelope.u) - event.userMetadata = envelope.u; - if (envelope.cmt) - event.customMessageType = envelope.cmt; - if (decryptionError) - event.error = decryptionError; - return event; - } - signalFromEnvelope(envelope) { - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - const event = { - channel, - subscription, - timetoken: envelope.p.t, - publisher: envelope.i, - message: envelope.d, - }; - if (envelope.u) - event.userMetadata = envelope.u; - if (envelope.cmt) - event.customMessageType = envelope.cmt; - return event; - } - messageActionFromEnvelope(envelope) { - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - const action = envelope.d; - return { - channel, - subscription, - timetoken: envelope.p.t, - publisher: envelope.i, - event: action.event, - data: Object.assign(Object.assign({}, action.data), { uuid: envelope.i }), - }; - } - appContextFromEnvelope(envelope) { - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - const object = envelope.d; - return { - channel, - subscription, - timetoken: envelope.p.t, - message: object, - }; - } - dataSyncFromEnvelope(envelope) { - var _a; - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - const payload = envelope.d; - const metadata = payload === null || payload === void 0 ? void 0 : payload.metadata; - // Only treat the envelope as DataSync when the service marks it and carries the required fields. - if (!metadata || metadata.source !== 'data-sync' || !metadata.event || !metadata.type) - return undefined; - // Wire `className` is a bare class name (`User`, `Membership`, `Customer`); the `:`-splitting below - // is only there to keep tolerating the retired positional composite (`User::` / `::Customer`). - const classSegments = metadata.className ? metadata.className.split(':') : []; - const nonEmptySegments = classSegments.filter((segment) => segment.length > 0); - const className = nonEmptySegments.length > 0 ? nonEmptySegments[nonEmptySegments.length - 1] : undefined; - const classLevel = metadata.classLevel; - // `classLevel` authoritatively separates the built-in classes from developer-defined ones, so a - // developer class named `User` / `Channel` / `Membership` is not mistaken for a typed resource. - // When it is absent (service predating the field) fall back to the legacy positional heuristic, - // where the system class was the first segment. - const systemClass = classLevel === undefined ? classSegments[0] : classLevel === 'Global' ? className : undefined; - // The service reports the semantic kind directly; the class-name lookup only fills it in for a - // service which still sends the built-in classes under the generic `entity` / `relationship` kind. - const genericType = metadata.type === 'entity' || metadata.type === 'relationship'; - const objectType = genericType - ? (systemClass && DATA_SYNC_RESERVED_CLASSES[systemClass.toLowerCase()]) || metadata.type - : metadata.type; - const parsedVersion = metadata.classVersion !== undefined ? Number.parseInt(`${metadata.classVersion}`, 10) : NaN; - const classVersion = Number.isNaN(parsedVersion) ? undefined : parsedVersion; - const raw = ((_a = payload.data) !== null && _a !== void 0 ? _a : {}); - // Class identity is reported once, on the event, so it is shared by every event shape. - const common = { - version: payload.version, - source: metadata.source, - type: metadata.type, - className, - classLevel, - classVersion, - }; - // `data` mirrors the object as sent by the service, and its shape is tied to `event` / - // `objectType` — which is what makes `message` a discriminated union for the consumer. - let message; - if (metadata.event === 'delete') - message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: { id: raw.id, deletedAt: raw.deletedAt } }); - else if (objectType === 'membership') - message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); - else if (objectType === 'relationship') - message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); - else - message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); - return { - channel, - subscription, - timetoken: envelope.p.t, - message, - }; - } - fileFromEnvelope(envelope) { - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - const [file, decryptionError] = this.decryptedData(envelope.d); - let errorMessage = decryptionError; - // Basic file event payload. - const event = { - channel, - subscription, - timetoken: envelope.p.t, - publisher: envelope.i, - }; - if (envelope.u) - event.userMetadata = envelope.u; - if (!file) - errorMessage !== null && errorMessage !== void 0 ? errorMessage : (errorMessage = `File information payload is missing.`); - else if (typeof file === 'string') - errorMessage !== null && errorMessage !== void 0 ? errorMessage : (errorMessage = `Unexpected file information payload data type.`); - else { - event.message = file.message; - if (file.file) { - event.file = { - id: file.file.id, - name: file.file.name, - url: this.parameters.getFileUrl({ id: file.file.id, name: file.file.name, channel }), - }; - } - } - if (envelope.cmt) - event.customMessageType = envelope.cmt; - if (errorMessage) - event.error = errorMessage; - return event; - } - // endregion - subscriptionChannelFromEnvelope(envelope) { - return [envelope.c, envelope.b === undefined ? envelope.c : envelope.b]; - } - /** - * Decrypt provided `data`. - * - * @param [data] - Message or file information which should be decrypted if possible. - * - * @returns Tuple with decrypted data and decryption error (if any). - */ - decryptedData(data) { - if (!this.parameters.crypto || typeof data !== 'string') - return [data, undefined]; - let payload; - let error; - try { - const decryptedData = this.parameters.crypto.decrypt(data); - payload = - decryptedData instanceof ArrayBuffer - ? JSON.parse(SubscribeRequest.decoder.decode(decryptedData)) - : decryptedData; - } - catch (err) { - payload = null; - error = `Error while decrypting message content: ${err.message}`; - } - return [(payload !== null && payload !== void 0 ? payload : data), error]; - } - } - /** - * Subscribe request. - * - * @internal - */ - class SubscribeRequest extends BaseSubscribeRequest { - get path() { - var _a; - const { keySet: { subscribeKey }, channels, } = this.parameters; - return `/v2/subscribe/${subscribeKey}/${encodeNames((_a = channels === null || channels === void 0 ? void 0 : channels.sort()) !== null && _a !== void 0 ? _a : [], ',')}/0`; - } - get queryParameters() { - const { channelGroups, filterExpression, heartbeat, state, timetoken, region, onDemand } = this.parameters; - const query = {}; - if (onDemand) - query['on-demand'] = 1; - if (channelGroups && channelGroups.length > 0) - query['channel-group'] = channelGroups.sort().join(','); - if (filterExpression && filterExpression.length > 0) - query['filter-expr'] = filterExpression; - if (heartbeat) - query.heartbeat = heartbeat; - if (state && Object.keys(state).length > 0) - query['state'] = JSON.stringify(state); - if (timetoken !== undefined && typeof timetoken === 'string') { - if (timetoken.length > 0 && timetoken !== '0') - query['tt'] = timetoken; - } - else if (timetoken !== undefined && timetoken > 0) - query['tt'] = timetoken; - if (region) - query['tr'] = region; - return query; - } - } - - /** - * Events dispatcher module. - */ - /** - * Real-time events dispatcher. - * - * Class responsible for listener management and invocation. - * - * @internal - */ - class EventDispatcher { - constructor() { - /** - * Whether listeners has been added or not. - */ - this.hasListeners = false; - /** - * List of registered event handlers. - * - * **Note:** the First element is reserved for type-based event handlers. - */ - this.listeners = [{ count: -1, listener: {} }]; - } - /** - * Set a connection status change event handler. - * - * @param listener - Listener function, which will be called each time when the connection status changes. - */ - set onStatus(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'status' }); - } - /** - * Set a new message handler. - * - * @param listener - Listener function, which will be called each time when a new message - * is received from the real-time network. - */ - set onMessage(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'message' }); - } - /** - * Set a new presence events handler. - * - * @param listener - Listener function, which will be called each time when a new - * presence event is received from the real-time network. - */ - set onPresence(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'presence' }); - } - /** - * Set a new signal handler. - * - * @param listener - Listener function, which will be called each time when a new signal - * is received from the real-time network. - */ - set onSignal(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'signal' }); - } - /** - * Set a new app context event handler. - * - * @param listener - Listener function, which will be called each time when a new - * app context event is received from the real-time network. - */ - set onObjects(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'objects' }); - } - /** - * Set a new message reaction event handler. - * - * @param listener - Listener function, which will be called each time when a - * new message reaction event is received from the real-time network. - */ - set onMessageAction(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'messageAction' }); - } - /** - * Set a new file handler. - * - * @param listener - Listener function, which will be called each time when a new file - * is received from the real-time network. - */ - set onFile(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'file' }); - } - /** - * Set a new DataSync event handler. - * - * @param listener - Listener function, which will be called each time when a new - * DataSync event is received from the real-time network. - */ - set onDataSync(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'dataSync' }); - } - /** - * Dispatch received a real-time update. - * - * @param event - A real-time event from multiplexed subscription. - */ - handleEvent(event) { - if (!this.hasListeners) - return; - if (event.type === PubNubEventType.Message) - this.announce('message', event.data); - else if (event.type === PubNubEventType.Signal) - this.announce('signal', event.data); - else if (event.type === PubNubEventType.Presence) - this.announce('presence', event.data); - else if (event.type === PubNubEventType.AppContext) { - const { data: objectEvent } = event; - const { message: object } = objectEvent; - this.announce('objects', objectEvent); - if (object.type === 'uuid') { - const { message, channel } = objectEvent, restEvent = __rest(objectEvent, ["message", "channel"]); - const { event, type } = object, restObject = __rest(object, ["event", "type"]); - const userEvent = Object.assign(Object.assign({}, restEvent), { spaceId: channel, message: Object.assign(Object.assign({}, restObject), { event: event === 'set' ? 'updated' : 'removed', type: 'user' }) }); - this.announce('user', userEvent); - } - else if (object.type === 'channel') { - const { message, channel } = objectEvent, restEvent = __rest(objectEvent, ["message", "channel"]); - const { event, type } = object, restObject = __rest(object, ["event", "type"]); - const spaceEvent = Object.assign(Object.assign({}, restEvent), { spaceId: channel, message: Object.assign(Object.assign({}, restObject), { event: event === 'set' ? 'updated' : 'removed', type: 'space' }) }); - this.announce('space', spaceEvent); - } - else if (object.type === 'membership') { - const { message, channel } = objectEvent, restEvent = __rest(objectEvent, ["message", "channel"]); - const { event, data } = object, restObject = __rest(object, ["event", "data"]); - const { uuid, channel: channelMeta } = data, restData = __rest(data, ["uuid", "channel"]); - const membershipEvent = Object.assign(Object.assign({}, restEvent), { spaceId: channel, message: Object.assign(Object.assign({}, restObject), { event: event === 'set' ? 'updated' : 'removed', data: Object.assign(Object.assign({}, restData), { user: uuid, space: channelMeta }) }) }); - this.announce('membership', membershipEvent); - } - } - else if (event.type === PubNubEventType.MessageAction) - this.announce('messageAction', event.data); - else if (event.type === PubNubEventType.Files) - this.announce('file', event.data); - else if (event.type === PubNubEventType.DataSync) - this.announce('dataSync', event.data); - } - /** - * Dispatch received connection status change. - * - * @param status - Status object which should be emitter for all status listeners. - */ - handleStatus(status) { - if (!this.hasListeners) - return; - this.announce('status', status); - } - /** - * Add events handler. - * - * @param listener - Events listener configuration object, which lets specify handlers for multiple types of events. - */ - addListener(listener) { - this.updateTypeOrObjectListener({ add: true, listener }); - } - removeListener(listener) { - this.updateTypeOrObjectListener({ add: false, listener }); - } - removeAllListeners() { - this.listeners = [{ count: -1, listener: {} }]; - this.hasListeners = false; - } - updateTypeOrObjectListener(parameters) { - if (parameters.type) { - if (typeof parameters.listener === 'function') - this.listeners[0].listener[parameters.type] = parameters.listener; - else - delete this.listeners[0].listener[parameters.type]; - } - else if (parameters.listener && typeof parameters.listener !== 'function') { - let listenerObject; - let listenerExists = false; - for (listenerObject of this.listeners) { - if (listenerObject.listener === parameters.listener) { - if (parameters.add) { - listenerObject.count++; - listenerExists = true; - } - else { - listenerObject.count--; - if (listenerObject.count === 0) - this.listeners.splice(this.listeners.indexOf(listenerObject), 1); - } - break; - } - } - if (parameters.add && !listenerExists) - this.listeners.push({ count: 1, listener: parameters.listener }); - } - this.hasListeners = this.listeners.length > 1 || Object.keys(this.listeners[0]).length > 0; - } - /** - * Announce a real-time event to all listeners. - * - * @param type - Type of event which should be announced. - * @param event - Announced real-time event payload. - */ - announce(type, event) { - this.listeners.forEach(({ listener }) => { - const typedListener = listener[type]; - // @ts-expect-error Dynamic events mapping. - if (typedListener) - typedListener(event); - }); - } - } - - /** - * Subscription reconnection-manager. - * - * **Note:** Reconnection manger rely on legacy time-based availability check. - * - * @internal - */ - /** - * Network "discovery" manager. - * - * Manager perform periodic `time` API calls to identify network availability. - * - * @internal - */ - class ReconnectionManager { - constructor(time) { - this.time = time; - } - /** - * Configure reconnection handler. - * - * @param callback - Successful availability check notify callback. - */ - onReconnect(callback) { - this.callback = callback; - } - /** - * Start periodic "availability" check. - */ - startPolling() { - this.timeTimer = setInterval(() => this.callTime(), 3000); - } - /** - * Stop periodic "availability" check. - */ - stopPolling() { - if (this.timeTimer) - clearInterval(this.timeTimer); - this.timeTimer = null; - } - callTime() { - this.time((status) => { - if (!status.error) { - this.stopPolling(); - if (this.callback) - this.callback(); - } - }); - } - } - - /** - * Messages de-duplication manager module. - * - * @internal - */ - /** - * Real-time events deduplication manager. - * - * @internal - */ - class DedupingManager { - /** - * Create and configure real-time events de-duplication manager. - * - * @param config - PubNub client configuration object. - */ - constructor(config) { - this.config = config; - config.logger().debug('DedupingManager', () => ({ - messageType: 'object', - message: { maximumCacheSize: config.maximumCacheSize }, - details: 'Create with configuration:', - })); - this.maximumCacheSize = config.maximumCacheSize; - this.hashHistory = []; - } - /** - * Compute unique real-time event payload key. - * - * @param message - Received real-time event payload for which unique key should be computed. - * @returns Unique real-time event payload key in messages cache. - */ - getKey(message) { - var _a; - return `${message.timetoken}-${this.hashCode(JSON.stringify((_a = message.message) !== null && _a !== void 0 ? _a : '')).toString()}`; - } - /** - * Check whether there is similar message already received or not. - * - * @param message - Received real-time event payload which should be checked for duplicates. - * @returns `true` in case if similar payload already has been received before. - */ - isDuplicate(message) { - return this.hashHistory.includes(this.getKey(message)); - } - /** - * Store received message to be used later for duplicate detection. - * - * @param message - Received real-time event payload. - */ - addEntry(message) { - if (this.hashHistory.length >= this.maximumCacheSize) { - this.hashHistory.shift(); - } - this.hashHistory.push(this.getKey(message)); - } - /** - * Clean up cached messages. - */ - clearHistory() { - this.hashHistory = []; - } - /** - * Compute message hash sum. - * - * @param payload - Received payload for which hash sum should be computed. - * @returns {number} - Resulting hash sum. - */ - hashCode(payload) { - let hash = 0; - if (payload.length === 0) - return hash; - for (let i = 0; i < payload.length; i += 1) { - const character = payload.charCodeAt(i); - hash = (hash << 5) - hash + character; // eslint-disable-line - hash = hash & hash; // eslint-disable-line - } - return hash; - } - } - - /** - * Subscription manager module. - * - * @internal - */ - /** - * Subscription loop manager. - * - * @internal - */ - class SubscriptionManager { - constructor(configuration, emitEvent, emitStatus, subscribeCall, heartbeatCall, leaveCall, time) { - this.configuration = configuration; - this.emitEvent = emitEvent; - this.emitStatus = emitStatus; - this.subscribeCall = subscribeCall; - this.heartbeatCall = heartbeatCall; - this.leaveCall = leaveCall; - /** - * Whether user code in event handlers requested disconnection or not. - * - * Won't continue subscription loop if user requested disconnection/unsubscribe from all in response to received - * event. - */ - this.disconnectedWhileHandledEvent = false; - configuration.logger().trace('SubscriptionManager', 'Create manager.'); - this.reconnectionManager = new ReconnectionManager(time); - this.dedupingManager = new DedupingManager(this.configuration); - this.heartbeatChannelGroups = {}; - this.heartbeatChannels = {}; - this.presenceChannelGroups = {}; - this.presenceChannels = {}; - this.heartbeatTimer = null; - this.presenceState = {}; - this.pendingChannelGroupSubscriptions = new Set(); - this.pendingChannelSubscriptions = new Set(); - this.channelGroups = {}; - this.channels = {}; - this.currentTimetoken = '0'; - this.lastTimetoken = '0'; - this.storedTimetoken = null; - this.referenceTimetoken = null; - this.subscriptionStatusAnnounced = false; - this.isOnline = true; - } - // region Information - /** - * Subscription-based current timetoken. - * - * @returns Timetoken based on current timetoken plus diff between current and loop start time. - */ - get subscriptionTimetoken() { - var _a; - return subscriptionTimetokenFromReference(this.currentTimetoken, (_a = this.referenceTimetoken) !== null && _a !== void 0 ? _a : '0'); - } - get subscribedChannels() { - return Object.keys(this.channels); - } - get subscribedChannelGroups() { - return Object.keys(this.channelGroups); - } - get abort() { - return this._subscribeAbort; - } - set abort(call) { - this._subscribeAbort = call; - } - // endregion - // region Subscription - disconnect() { - // Potentially called during received events handling. - // Mark to prevent subscription loop continuation in subscribe response handler. - this.disconnectedWhileHandledEvent = true; - this.stopSubscribeLoop(); - this.stopHeartbeatTimer(); - this.reconnectionManager.stopPolling(); - } - /** - * Restart subscription loop with current state. - * - * @param forUnsubscribe - Whether restarting subscription loop as part of channels list change on - * unsubscribe or not. - */ - reconnect(forUnsubscribe = false) { - this.startSubscribeLoop(forUnsubscribe); - // Starting heartbeat loop for provided channels and groups. - if (!forUnsubscribe && !this.configuration.useSmartHeartbeat) - this.startHeartbeatTimer(); - } - /** - * Update channels and groups used in subscription loop. - * - * @param parameters - Subscribe configuration parameters. - */ - subscribe(parameters) { - const { channels, channelGroups, timetoken, withPresence = false, withHeartbeats = false } = parameters; - if (timetoken) { - this.lastTimetoken = this.currentTimetoken; - this.currentTimetoken = `${timetoken}`; - } - if (this.currentTimetoken !== '0') { - this.storedTimetoken = this.currentTimetoken; - this.currentTimetoken = '0'; - } - channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => { - this.pendingChannelSubscriptions.add(channel); - this.channels[channel] = {}; - if (withPresence) - this.presenceChannels[channel] = {}; - if (withHeartbeats || this.configuration.getHeartbeatInterval()) - this.heartbeatChannels[channel] = {}; - }); - channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => { - this.pendingChannelGroupSubscriptions.add(group); - this.channelGroups[group] = {}; - if (withPresence) - this.presenceChannelGroups[group] = {}; - if (withHeartbeats || this.configuration.getHeartbeatInterval()) - this.heartbeatChannelGroups[group] = {}; - }); - this.subscriptionStatusAnnounced = false; - this.reconnect(); - } - unsubscribe(parameters, isOffline = false) { - let { channels, channelGroups } = parameters; - const actualChannelGroups = new Set(); - const actualChannels = new Set(); - channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => { - if (channel in this.channels) { - delete this.channels[channel]; - actualChannels.add(channel); - if (channel in this.heartbeatChannels) - delete this.heartbeatChannels[channel]; - } - if (channel in this.presenceState) - delete this.presenceState[channel]; - if (channel in this.presenceChannels) { - delete this.presenceChannels[channel]; - actualChannels.add(channel); - } - }); - channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => { - if (group in this.channelGroups) { - delete this.channelGroups[group]; - actualChannelGroups.add(group); - if (group in this.heartbeatChannelGroups) - delete this.heartbeatChannelGroups[group]; - } - if (group in this.presenceState) - delete this.presenceState[group]; - if (group in this.presenceChannelGroups) { - delete this.presenceChannelGroups[group]; - actualChannelGroups.add(group); - } - }); - // There is no need to unsubscribe to empty list of data sources. - if (actualChannels.size === 0 && actualChannelGroups.size === 0) - return; - const lastTimetoken = this.lastTimetoken; - const currentTimetoken = this.currentTimetoken; - if (Object.keys(this.channels).length === 0 && - Object.keys(this.presenceChannels).length === 0 && - Object.keys(this.channelGroups).length === 0 && - Object.keys(this.presenceChannelGroups).length === 0) { - this.lastTimetoken = '0'; - this.currentTimetoken = '0'; - this.referenceTimetoken = null; - this.storedTimetoken = null; - this.region = null; - this.reconnectionManager.stopPolling(); - } - this.reconnect(true); - // Send leave request after long-poll connection closed and loop restarted (the same way as it happens in new - // subscription flow). - if (this.configuration.suppressLeaveEvents === false && !isOffline) { - channelGroups = Array.from(actualChannelGroups); - channels = Array.from(actualChannels); - this.leaveCall({ channels, channelGroups }, (status) => { - const { error } = status, restOfStatus = __rest(status, ["error"]); - let errorMessage; - if (error) { - if (status.errorData && - typeof status.errorData === 'object' && - 'message' in status.errorData && - typeof status.errorData.message === 'string') - errorMessage = status.errorData.message; - else if ('message' in status && typeof status.message === 'string') - errorMessage = status.message; - } - this.emitStatus(Object.assign(Object.assign({}, restOfStatus), { error: errorMessage !== null && errorMessage !== void 0 ? errorMessage : false, affectedChannels: channels, affectedChannelGroups: channelGroups, currentTimetoken, - lastTimetoken })); - }); - } - } - unsubscribeAll(isOffline = false) { - this.disconnectedWhileHandledEvent = true; - this.unsubscribe({ - channels: this.subscribedChannels, - channelGroups: this.subscribedChannelGroups, - }, isOffline); - } - /** - * Start next subscription loop. - * - * @param restartOnUnsubscribe - Whether restarting subscription loop as part of channels list change on - * unsubscribe or not. - * - * @internal - */ - startSubscribeLoop(restartOnUnsubscribe = false) { - this.disconnectedWhileHandledEvent = false; - this.stopSubscribeLoop(); - const channelGroups = [...Object.keys(this.channelGroups)]; - const channels = [...Object.keys(this.channels)]; - Object.keys(this.presenceChannelGroups).forEach((group) => channelGroups.push(`${group}-pnpres`)); - Object.keys(this.presenceChannels).forEach((channel) => channels.push(`${channel}-pnpres`)); - // There is no need to start subscription loop for an empty list of data sources. - if (channels.length === 0 && channelGroups.length === 0) - return; - this.subscribeCall(Object.assign(Object.assign(Object.assign({ channels, - channelGroups, state: this.presenceState, heartbeat: this.configuration.getPresenceTimeout(), timetoken: this.currentTimetoken }, (this.region !== null ? { region: this.region } : {})), (this.configuration.filterExpression ? { filterExpression: this.configuration.filterExpression } : {})), { onDemand: !this.subscriptionStatusAnnounced || restartOnUnsubscribe }), (status, result) => { - this.processSubscribeResponse(status, result); - }); - if (!restartOnUnsubscribe && this.configuration.useSmartHeartbeat) - this.startHeartbeatTimer(); - } - stopSubscribeLoop() { - if (this._subscribeAbort) { - this._subscribeAbort(); - this._subscribeAbort = null; - } - } - /** - * Process subscribe REST API endpoint response. - */ - processSubscribeResponse(status, result) { - if (status.error) { - // Ignore aborted request. - if ((typeof status.errorData === 'object' && - 'name' in status.errorData && - status.errorData.name === 'AbortError') || - status.category === StatusCategory$1.PNCancelledCategory) - return; - if (status.category === StatusCategory$1.PNTimeoutCategory) { - this.startSubscribeLoop(); - } - else if (status.category === StatusCategory$1.PNNetworkIssuesCategory || - status.category === StatusCategory$1.PNMalformedResponseCategory) { - this.disconnect(); - if (status.error && this.configuration.autoNetworkDetection && this.isOnline) { - this.isOnline = false; - this.emitStatus({ category: StatusCategory$1.PNNetworkDownCategory }); - } - this.reconnectionManager.onReconnect(() => { - if (this.configuration.autoNetworkDetection && !this.isOnline) { - this.isOnline = true; - this.emitStatus({ category: StatusCategory$1.PNNetworkUpCategory }); - } - this.reconnect(); - this.subscriptionStatusAnnounced = true; - const reconnectedAnnounce = { - category: StatusCategory$1.PNReconnectedCategory, - operation: status.operation, - lastTimetoken: this.lastTimetoken, - currentTimetoken: this.currentTimetoken, - }; - this.emitStatus(reconnectedAnnounce); - }); - this.reconnectionManager.startPolling(); - this.emitStatus(Object.assign(Object.assign({}, status), { category: StatusCategory$1.PNNetworkIssuesCategory })); - } - else if (status.category === StatusCategory$1.PNBadRequestCategory) { - this.stopHeartbeatTimer(); - this.emitStatus(status); - } - else - this.emitStatus(status); - return; - } - this.referenceTimetoken = referenceSubscribeTimetoken(result.cursor.timetoken, this.storedTimetoken); - if (this.storedTimetoken) { - this.currentTimetoken = this.storedTimetoken; - this.storedTimetoken = null; - } - else { - this.lastTimetoken = this.currentTimetoken; - this.currentTimetoken = result.cursor.timetoken; - } - if (!this.subscriptionStatusAnnounced) { - const connected = { - category: StatusCategory$1.PNConnectedCategory, - operation: status.operation, - affectedChannels: Array.from(this.pendingChannelSubscriptions), - subscribedChannels: this.subscribedChannels, - affectedChannelGroups: Array.from(this.pendingChannelGroupSubscriptions), - lastTimetoken: this.lastTimetoken, - currentTimetoken: this.currentTimetoken, - }; - this.subscriptionStatusAnnounced = true; - this.emitStatus(connected); - // Clear pending channels and groups. - this.pendingChannelGroupSubscriptions.clear(); - this.pendingChannelSubscriptions.clear(); - } - const { messages } = result; - const { requestMessageCountThreshold, dedupeOnSubscribe } = this.configuration; - if (requestMessageCountThreshold && messages.length >= requestMessageCountThreshold) { - this.emitStatus({ - category: StatusCategory$1.PNRequestMessageCountExceededCategory, - operation: status.operation, - }); - } - try { - const cursor = { - timetoken: this.currentTimetoken, - region: this.region ? this.region : undefined, - }; - this.configuration.logger().debug('SubscriptionManager', () => { - const hashedEvents = messages.map((event) => ({ - type: event.type, - data: Object.assign(Object.assign({}, event.data), { pn_mfp: event.pn_mfp }), - })); - return { messageType: 'object', message: hashedEvents, details: 'Received events:' }; - }); - messages.forEach((message) => { - if (dedupeOnSubscribe && 'message' in message.data && 'timetoken' in message.data) { - if (this.dedupingManager.isDuplicate(message.data)) { - this.configuration.logger().warn('SubscriptionManager', () => ({ - messageType: 'object', - message: message.data, - details: 'Duplicate message detected (skipped):', - })); - return; - } - this.dedupingManager.addEntry(message.data); - } - this.emitEvent(cursor, message); - }); - } - catch (e) { - const errorStatus = { - error: true, - category: StatusCategory$1.PNUnknownCategory, - errorData: e, - statusCode: 0, - }; - this.emitStatus(errorStatus); - } - this.region = result.cursor.region; - if (!this.disconnectedWhileHandledEvent) - this.startSubscribeLoop(); - else - this.disconnectedWhileHandledEvent = false; - } - // endregion - // region Presence - /** - * Update `uuid` state which should be sent with subscribe request. - * - * @param parameters - Channels and groups with state which should be associated to `uuid`. - */ - setState(parameters) { - const { state, channels, channelGroups } = parameters; - channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => channel in this.channels && (this.presenceState[channel] = state)); - channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => group in this.channelGroups && (this.presenceState[group] = state)); - } - /** - * Manual presence management. - * - * @param parameters - Desired presence state for provided list of channels and groups. - */ - changePresence(parameters) { - const { connected, channels, channelGroups } = parameters; - if (connected) { - channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => (this.heartbeatChannels[channel] = {})); - channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => (this.heartbeatChannelGroups[group] = {})); - } - else { - channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => { - if (channel in this.heartbeatChannels) - delete this.heartbeatChannels[channel]; - }); - channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => { - if (group in this.heartbeatChannelGroups) - delete this.heartbeatChannelGroups[group]; - }); - if (this.configuration.suppressLeaveEvents === false) { - this.leaveCall({ channels, channelGroups }, (status) => this.emitStatus(status)); - } - } - this.reconnect(); - } - startHeartbeatTimer() { - this.stopHeartbeatTimer(); - const heartbeatInterval = this.configuration.getHeartbeatInterval(); - if (!heartbeatInterval || heartbeatInterval === 0) - return; - // Sending immediate heartbeat only if not working as a smart heartbeat. - if (!this.configuration.useSmartHeartbeat) - this.sendHeartbeat(); - this.heartbeatTimer = setInterval(() => this.sendHeartbeat(), heartbeatInterval * 1000); - } - /** - * Stop heartbeat. - * - * Stop timer which trigger {@link HeartbeatRequest} sending with configured presence intervals. - */ - stopHeartbeatTimer() { - if (!this.heartbeatTimer) - return; - clearInterval(this.heartbeatTimer); - this.heartbeatTimer = null; - } - /** - * Send heartbeat request. - */ - sendHeartbeat() { - const heartbeatChannelGroups = Object.keys(this.heartbeatChannelGroups); - const heartbeatChannels = Object.keys(this.heartbeatChannels); - // There is no need to start heartbeat loop if there is no channels and groups to use. - if (heartbeatChannels.length === 0 && heartbeatChannelGroups.length === 0) - return; - this.heartbeatCall({ - channels: heartbeatChannels, - channelGroups: heartbeatChannelGroups, - heartbeat: this.configuration.getPresenceTimeout(), - state: this.presenceState, - }, (status) => { - if (status.error && this.configuration.announceFailedHeartbeats) - this.emitStatus(status); - if (status.error && this.configuration.autoNetworkDetection && this.isOnline) { - this.isOnline = false; - this.disconnect(); - this.emitStatus({ category: StatusCategory$1.PNNetworkDownCategory }); - this.reconnect(); - } - if (!status.error && this.configuration.announceSuccessfulHeartbeats) - this.emitStatus(status); - }); - } - } - - // endregion - /** - * Base notification payload object. - */ - class BaseNotificationPayload { - /** - * Base notification provider payload object. - * - * @internal - * - * @param payload - Object which contains vendor-specific preformatted push notification payload. - * @param title - Notification main title. - * @param body - Notification body (main messages). - */ - constructor(payload, title, body) { - this._payload = payload; - this.setDefaultPayloadStructure(); - this.title = title; - this.body = body; - } - /** - * Retrieve resulting notification payload content for message. - * - * @returns Preformatted push notification payload data. - */ - get payload() { - return this._payload; - } - /** - * Update notification title. - * - * @param value - New notification title. - */ - set title(value) { - this._title = value; - } - /** - * Update notification subtitle. - * - * @param value - New second-line notification title. - */ - set subtitle(value) { - this._subtitle = value; - } - /** - * Update notification body. - * - * @param value - Update main notification message (shown when expanded). - */ - set body(value) { - this._body = value; - } - /** - * Update application badge number. - * - * @param value - Number which should be shown in application badge upon receiving notification. - */ - set badge(value) { - this._badge = value; - } - /** - * Update notification sound. - * - * @param value - Name of the sound file which should be played upon notification receive. - */ - set sound(value) { - this._sound = value; - } - /** - * Platform-specific structure initialization. - * - * @internal - */ - setDefaultPayloadStructure() { } - /** - * Translate data object into PubNub push notification payload object. - * - * @internal - * - * @returns Preformatted push notification payload. - */ - toObject() { - return {}; - } - } - /** - * Message payload for Apple Push Notification Service. - */ - class APNSNotificationPayload extends BaseNotificationPayload { - constructor() { - super(...arguments); - /** - * Type of push notification service for which payload will be created. - * - * @internal - */ - this._apnsPushType = 'apns'; - /** - * Whether resulting payload should trigger silent notification or not. - * - * @internal - */ - this._isSilent = false; - } - get payload() { - return this._payload; - } - /** - * Update notification receivers configuration. - * - * @param value - New APNS2 configurations. - */ - set configurations(value) { - if (!value || !value.length) - return; - this._configurations = value; - } - /** - * Notification payload. - * - * @returns Platform-specific part of PubNub notification payload. - */ - get notification() { - return this.payload.aps; - } - /** - * Notification title. - * - * @returns Main notification title. - */ - get title() { - return this._title; - } - /** - * Update notification title. - * - * @param value - New notification title. - */ - set title(value) { - if (!value || !value.length) - return; - this.payload.aps.alert.title = value; - this._title = value; - } - /** - * Notification subtitle. - * - * @returns Second-line notification title. - */ - get subtitle() { - return this._subtitle; - } - /** - * Update notification subtitle. - * - * @param value - New second-line notification title. - */ - set subtitle(value) { - if (!value || !value.length) - return; - this.payload.aps.alert.subtitle = value; - this._subtitle = value; - } - /** - * Notification body. - * - * @returns Main notification message (shown when expanded). - */ - get body() { - return this._body; - } - /** - * Update notification body. - * - * @param value - Update main notification message (shown when expanded). - */ - set body(value) { - if (!value || !value.length) - return; - this.payload.aps.alert.body = value; - this._body = value; - } - /** - * Retrieve unread notifications number. - * - * @returns Number of unread notifications which should be shown on application badge. - */ - get badge() { - return this._badge; - } - /** - * Update application badge number. - * - * @param value - Number which should be shown in application badge upon receiving notification. - */ - set badge(value) { - if (value === undefined || value === null) - return; - this.payload.aps.badge = value; - this._badge = value; - } - /** - * Retrieve notification sound file. - * - * @returns Notification sound file name from resource bundle. - */ - get sound() { - return this._sound; - } - /** - * Update notification sound. - * - * @param value - Name of the sound file which should be played upon notification receive. - */ - set sound(value) { - if (!value || !value.length) - return; - this.payload.aps.sound = value; - this._sound = value; - } - /** - * Set whether notification should be silent or not. - * - * `content-available` notification type will be used to deliver silent notification if set to `true`. - * - * @param value - Whether notification should be sent as silent or not. - */ - set silent(value) { - this._isSilent = value; - } - /** - * Setup push notification payload default content. - * - * @internal - */ - setDefaultPayloadStructure() { - this.payload.aps = { alert: {} }; - } - /** - * Translate data object into PubNub push notification payload object. - * - * @internal - * - * @returns Preformatted push notification payload. - */ - toObject() { - const payload = Object.assign({}, this.payload); - const { aps } = payload; - let { alert } = aps; - if (this._isSilent) - aps['content-available'] = 1; - if (this._apnsPushType === 'apns2') { - if (!this._configurations || !this._configurations.length) - throw new ReferenceError('APNS2 configuration is missing'); - const configurations = []; - this._configurations.forEach((configuration) => { - configurations.push(this.objectFromAPNS2Configuration(configuration)); - }); - if (configurations.length) - payload.pn_push = configurations; - } - if (!alert || !Object.keys(alert).length) - delete aps.alert; - if (this._isSilent) { - delete aps.alert; - delete aps.badge; - delete aps.sound; - alert = {}; - } - return this._isSilent || (alert && Object.keys(alert).length) ? payload : null; - } - /** - * Create PubNub push notification service APNS2 configuration information object. - * - * @internal - * - * @param configuration - Source user-provided APNS2 configuration. - * - * @returns Preformatted for PubNub service APNS2 configuration information. - */ - objectFromAPNS2Configuration(configuration) { - if (!configuration.targets || !configuration.targets.length) - throw new ReferenceError('At least one APNS2 target should be provided'); - const { collapseId, expirationDate } = configuration; - const objectifiedConfiguration = { - auth_method: 'token', - targets: configuration.targets.map((target) => this.objectFromAPNSTarget(target)), - version: 'v2', - }; - if (collapseId && collapseId.length) - objectifiedConfiguration.collapse_id = collapseId; - if (expirationDate) - objectifiedConfiguration.expiration = expirationDate.toISOString(); - return objectifiedConfiguration; - } - /** - * Create PubNub push notification service APNS2 target information object. - * - * @internal - * - * @param target - Source user-provided data. - * - * @returns Preformatted for PubNub service APNS2 target information. - */ - objectFromAPNSTarget(target) { - if (!target.topic || !target.topic.length) - throw new TypeError("Target 'topic' undefined."); - const { topic, environment = 'development', excludedDevices = [] } = target; - const objectifiedTarget = { topic, environment }; - if (excludedDevices.length) - objectifiedTarget.excluded_devices = excludedDevices; - return objectifiedTarget; - } - } - /** - * Message payload for Firebase Cloud Messaging service. - */ - class FCMNotificationPayload extends BaseNotificationPayload { - get payload() { - return this._payload; - } - /** - * Notification payload. - * - * @returns Platform-specific part of PubNub notification payload. - */ - get notification() { - return this.payload.notification; - } - /** - * Silent notification payload. - * - * @returns Silent notification payload (data notification). - */ - get data() { - return this.payload.data; - } - /** - * Retrieve Android notification payload and initialize required structure. - * - * @returns Android specific notification payload. - */ - get androidNotification() { - var _c; - return (_c = this.payload.android) === null || _c === void 0 ? void 0 : _c.notification; - } - /** - * Notification title. - * - * @returns Main notification title. - */ - get title() { - return this._title; - } - /** - * Update notification title. - * - * @param value - New notification title. - */ - set title(value) { - if (!value || !value.length) - return; - this.payload.notification.title = value; - this.androidNotification.title = value; - this._title = value; - } - /** - * Notification body. - * - * @returns Main notification message (shown when expanded). - */ - get body() { - return this._body; - } - /** - * Update notification body. - * - * @param value - Update main notification message (shown when expanded). - */ - set body(value) { - if (!value || !value.length) - return; - this.payload.notification.body = value; - this.androidNotification.body = value; - this._body = value; - } - /** - * Retrieve unread notifications number. - * - * @returns Number of unread notifications which should be shown on application badge. - */ - get badge() { - return this._badge; - } - /** - * Update application badge number. - * - * @param value - Number which should be shown in application badge upon receiving notification. - */ - set badge(value) { - if (value === undefined || value === null) - return; - this.androidNotification.notification_count = value; - this._badge = value; - } - /** - * Retrieve notification sound file. - * - * @returns Notification sound file name from resource bundle. - */ - get sound() { - return this._sound; - } - /** - * Update notification sound. - * - * @param value - Name of the sound file which should be played upon notification receive. - */ - set sound(value) { - if (!value || !value.length) - return; - this.androidNotification.sound = value; - this._sound = value; - } - /** - * Retrieve notification icon file. - * - * @returns Notification icon file name from resource bundle. - */ - get icon() { - return this._icon; - } - /** - * Update notification icon. - * - * @param value - Name of the icon file set for `android.notification.icon`. - */ - set icon(value) { - if (!value || !value.length) - return; - this.androidNotification.icon = value; - this._icon = value; - } - /** - * Retrieve notifications grouping tag. - * - * @returns Notifications grouping tag. - */ - get tag() { - return this._tag; - } - /** - * Update notifications grouping tag. - * - * @param value - String set for `android.notification.tag` to group similar notifications. - */ - set tag(value) { - if (!value || !value.length) - return; - this.androidNotification.tag = value; - this._tag = value; - } - /** - * Set whether notification should be silent or not. - * - * All notification data will be sent under `data` field if set to `true`. - * - * @param value - Whether notification should be sent as silent or not. - */ - set silent(value) { - this._isSilent = value; - } - /** - * Setup push notification payload default content. - * - * @internal - */ - setDefaultPayloadStructure() { - this.payload.notification = {}; - this.payload.data = {}; - this.payload.android = { notification: {} }; - } - /** - * Translate data object into PubNub push notification payload object. - * - * @internal - * - * @returns Preformatted push notification payload. - */ - toObject() { - var _c, _e; - const payload = {}; - const notification = Object.assign({}, this.payload.notification); - const android = Object.assign({}, this.payload.android); - const androidNotification = Object.assign({}, ((_c = android.notification) !== null && _c !== void 0 ? _c : {})); - // Strip title/body from android.notification — they belong in top-level notification (or data for silent). - const androidSpecificFields = __rest(androidNotification, ["title", "body"]); - if (this._isSilent) { - // For silent (data-only) notifications, strip all `notification` fields - // (both root and android) and move everything into the root `data` object. - const data = {}; - if (this._title) - data.title = this._title; - if (this._body) - data.body = this._body; - // Merge android-specific notification fields (sound, icon, tag, etc.) into data. - for (const [key, value] of Object.entries(androidSpecificFields)) { - if (value !== undefined && value !== null) - data[key] = String(value); - } - // Merge any existing user-provided custom data. - if (this.payload.data) - Object.assign(data, this.payload.data); - if (Object.keys(data).length) - payload.data = data; - // Exclude `notification` entirely from android — only keep non-notification android fields. - delete android.notification; - if (Object.keys(android).length) { - payload.android = android; - } - } - else { - if (Object.keys(notification).length) - payload.notification = notification; - // Include top-level data if present. - if (this.payload.data && Object.keys(this.payload.data).length) - payload.data = Object.assign({}, this.payload.data); - // android.notification should only contain android-specific fields (sound, icon, tag, etc.). - if (Object.keys(androidSpecificFields).length) { - const androidWithoutNotification = __rest(android, ["notification"]); - payload.android = Object.assign(Object.assign({}, androidWithoutNotification), { notification: androidSpecificFields }); - } - else { - const androidWithoutNotification = __rest(android, ["notification"]); - if (Object.keys(androidWithoutNotification).length) { - payload.android = androidWithoutNotification; - } - } - } - // Preserve other top-level FCM fields (apns, webpush, fcm_options, etc.). - const _f = this.payload, otherFields = __rest(_f, ["notification", "android", "data", "pn_exceptions"]); - Object.assign(payload, otherFields); - if ((_e = this.payload.pn_exceptions) === null || _e === void 0 ? void 0 : _e.length) - payload.pn_exceptions = this.payload.pn_exceptions; - return Object.keys(payload).length ? payload : null; - } - } - class NotificationsPayload { - /** - * Create push notification payload holder. - * - * @internal - * - * @param title - String which will be shown at the top of the notification (below app name). - * @param body - String with message which should be shown when user will check notification. - */ - constructor(title, body) { - this._payload = { apns: {}, fcm: {} }; - this._title = title; - this._body = body; - this.apns = new APNSNotificationPayload(this._payload.apns, title, body); - this.fcm = new FCMNotificationPayload(this._payload.fcm, title, body); - } - /** - * Enable or disable push notification debugging message. - * - * @param value - Whether debug message from push notification scheduler should be published to the specific - * channel or not. - */ - set debugging(value) { - this._debugging = value; - } - /** - * Notification title. - * - * @returns Main notification title. - */ - get title() { - return this._title; - } - /** - * Notification subtitle. - * - * @returns Second-line notification title. - */ - get subtitle() { - return this._subtitle; - } - /** - * Update notification subtitle. - * - * @param value - New second-line notification title. - */ - set subtitle(value) { - this._subtitle = value; - this.apns.subtitle = value; - this.fcm.subtitle = value; - } - /** - * Notification body. - * - * @returns Main notification message (shown when expanded). - */ - get body() { - return this._body; - } - /** - * Retrieve unread notifications number. - * - * @returns Number of unread notifications which should be shown on application badge. - */ - get badge() { - return this._badge; - } - /** - * Update application badge number. - * - * @param value - Number which should be shown in application badge upon receiving notification. - */ - set badge(value) { - this._badge = value; - this.apns.badge = value; - this.fcm.badge = value; - } - /** - * Retrieve notification sound file. - * - * @returns Notification sound file name from resource bundle. - */ - get sound() { - return this._sound; - } - /** - * Update notification sound. - * - * @param value - Name of the sound file which should be played upon notification receive. - */ - set sound(value) { - this._sound = value; - this.apns.sound = value; - this.fcm.sound = value; - } - /** - * Build notifications platform for requested platforms. - * - * @param platforms - List of platforms for which payload should be added to final dictionary. Supported values: - * fcm, apns, and apns2. - * - * @returns Object with data, which can be sent with publish method call and trigger remote notifications for - * specified platforms. - */ - buildPayload(platforms) { - const payload = {}; - if (platforms.includes('apns') || platforms.includes('apns2')) { - // @ts-expect-error Override APNS version. - this.apns._apnsPushType = platforms.includes('apns') ? 'apns' : 'apns2'; - const apnsPayload = this.apns.toObject(); - if (apnsPayload && Object.keys(apnsPayload).length) - payload.pn_apns = apnsPayload; - } - if (platforms.includes('fcm')) { - const fcmPayload = this.fcm.toObject(); - if (fcmPayload && Object.keys(fcmPayload).length) - payload.pn_fcm = fcmPayload; - } - if (Object.keys(payload).length && this._debugging) - payload.pn_debug = true; - return payload; - } - } - - /** - * Event Engine terminate signal listener module. - * - * @internal - */ - /** - * @internal - */ - class Subject { - constructor(sync = false) { - this.sync = sync; - this.listeners = new Set(); - } - subscribe(listener) { - this.listeners.add(listener); - return () => { - this.listeners.delete(listener); - }; - } - notify(event) { - const wrapper = () => { - this.listeners.forEach((listener) => { - listener(event); - }); - }; - if (this.sync) { - wrapper(); - } - else { - setTimeout(wrapper, 0); - } - } - } - - /** - * Event Engine Core state module. - * - * @internal - */ - /** - * Event engine current state object. - * - * State contains current context and list of invocations which should be performed by the Event Engine. - * - * @internal - */ - class State { - transition(context, event) { - var _a; - if (this.transitionMap.has(event.type)) { - return (_a = this.transitionMap.get(event.type)) === null || _a === void 0 ? void 0 : _a(context, event); - } - return undefined; - } - constructor(label) { - this.label = label; - this.transitionMap = new Map(); - this.enterEffects = []; - this.exitEffects = []; - } - on(eventType, transition) { - this.transitionMap.set(eventType, transition); - return this; - } - with(context, effects) { - return [this, context, effects !== null && effects !== void 0 ? effects : []]; - } - onEnter(effect) { - this.enterEffects.push(effect); - return this; - } - onExit(effect) { - this.exitEffects.push(effect); - return this; - } - } - - /** - * Event Engine Core module. - * - * @internal - */ - /** - * Generic event engine. - * - * @internal - */ - class Engine extends Subject { - constructor(logger) { - super(true); - this.logger = logger; - this._pendingEvents = []; - this._inTransition = false; - } - get currentState() { - return this._currentState; - } - get currentContext() { - return this._currentContext; - } - describe(label) { - return new State(label); - } - start(initialState, initialContext) { - this._currentState = initialState; - this._currentContext = initialContext; - this.notify({ - type: 'engineStarted', - state: initialState, - context: initialContext, - }); - return; - } - transition(event) { - if (!this._currentState) { - this.logger.error('Engine', 'Finite state machine is not started'); - throw new Error('Start the engine first'); - } - if (this._inTransition) { - this.logger.trace('Engine', () => ({ - messageType: 'object', - message: event, - details: 'Event engine in transition. Enqueue received event:', - })); - this._pendingEvents.push(event); - return; - } - else - this._inTransition = true; - this.logger.trace('Engine', () => ({ - messageType: 'object', - message: event, - details: 'Event engine received event:', - })); - this.notify({ - type: 'eventReceived', - event: event, - }); - const transition = this._currentState.transition(this._currentContext, event); - if (transition) { - const [newState, newContext, effects] = transition; - this.logger.trace('Engine', `Exiting state: ${this._currentState.label}`); - for (const effect of this._currentState.exitEffects) { - this.notify({ - type: 'invocationDispatched', - invocation: effect(this._currentContext), - }); - } - this.logger.trace('Engine', () => ({ - messageType: 'object', - details: `Entering '${newState.label}' state with context:`, - message: newContext, - })); - const oldState = this._currentState; - this._currentState = newState; - const oldContext = this._currentContext; - this._currentContext = newContext; - this.notify({ - type: 'transitionDone', - fromState: oldState, - fromContext: oldContext, - toState: newState, - toContext: newContext, - event: event, - }); - for (const effect of effects) { - this.notify({ - type: 'invocationDispatched', - invocation: effect, - }); - } - for (const effect of this._currentState.enterEffects) { - this.notify({ - type: 'invocationDispatched', - invocation: effect(this._currentContext), - }); - } - } - else - this.logger.warn('Engine', `No transition from '${this._currentState.label}' found for event: ${event.type}`); - this._inTransition = false; - // Check whether a pending task should be dequeued. - if (this._pendingEvents.length > 0) { - const nextEvent = this._pendingEvents.shift(); - if (nextEvent) { - this.logger.trace('Engine', () => ({ - messageType: 'object', - message: nextEvent, - details: 'De-queueing pending event:', - })); - this.transition(nextEvent); - } - } - } - } - - /** - * Event Engine Core Effects dispatcher module. - * - * @internal - */ - /** - * Event Engine effects dispatcher. - * - * Dispatcher responsible for invocation enqueue and dequeue for processing. - * - * @internal - */ - class Dispatcher { - constructor(dependencies, logger) { - this.dependencies = dependencies; - this.logger = logger; - this.instances = new Map(); - this.handlers = new Map(); - } - on(type, handlerCreator) { - this.handlers.set(type, handlerCreator); - } - dispatch(invocation) { - this.logger.trace('Dispatcher', `Process invocation: ${invocation.type}`); - if (invocation.type === 'CANCEL') { - if (this.instances.has(invocation.payload)) { - const instance = this.instances.get(invocation.payload); - instance === null || instance === void 0 ? void 0 : instance.cancel(); - this.instances.delete(invocation.payload); - } - return; - } - const handlerCreator = this.handlers.get(invocation.type); - if (!handlerCreator) { - this.logger.error('Dispatcher', `Unhandled invocation '${invocation.type}'`); - throw new Error(`Unhandled invocation '${invocation.type}'`); - } - const instance = handlerCreator(invocation.payload, this.dependencies); - this.logger.trace('Dispatcher', () => ({ - messageType: 'object', - details: 'Call invocation handler with parameters:', - message: invocation.payload, - ignoredKeys: ['abortSignal'], - })); - if (invocation.managed) { - this.instances.set(invocation.type, instance); - } - instance.start(); - } - dispose() { - for (const [key, instance] of this.instances.entries()) { - instance.cancel(); - this.instances.delete(key); - } - } - } - - /** - * Event Engine Core types module. - * - * @internal - */ - /** - * Create and configure event engine event. - * - * @internal - */ - function createEvent(type, fn) { - const creator = function (...args) { - return { - type, - payload: fn === null || fn === void 0 ? void 0 : fn(...args), - }; - }; - creator.type = type; - return creator; - } - /** - * Create and configure short-term effect invocation. - * - * @internal - */ - function createEffect(type, fn) { - const creator = (...args) => { - return { type, payload: fn(...args), managed: false }; - }; - creator.type = type; - return creator; - } - /** - * Create and configure long-running effect invocation. - * - * @internal - */ - function createManagedEffect(type, fn) { - const creator = (...args) => { - return { type, payload: fn(...args), managed: true }; - }; - creator.type = type; - creator.cancel = { type: 'CANCEL', payload: type, managed: false }; - return creator; - } - - /** - * Event Engine managed effects terminate signal module. - * - * @internal - */ - class AbortError extends Error { - constructor() { - super('The operation was aborted.'); - this.name = 'AbortError'; - Object.setPrototypeOf(this, new.target.prototype); - } - } - /** - * Event Engine stored effect processing cancellation signal. - * - * @internal - */ - class AbortSignal extends Subject { - constructor() { - super(...arguments); - this._aborted = false; - } - get aborted() { - return this._aborted; - } - throwIfAborted() { - if (this._aborted) { - throw new AbortError(); - } - } - abort() { - this._aborted = true; - this.notify(new AbortError()); - } - } - - /** - * Event Engine Core Effects handler module. - * - * @internal - */ - /** - * Synchronous (short-term) effect invocation handler. - * - * Handler manages effect execution on behalf of effect dispatcher. - * - * @internal - */ - class Handler { - constructor(payload, dependencies) { - this.payload = payload; - this.dependencies = dependencies; - } - } - /** - * Asynchronous (long-running) effect invocation handler. - * - * Handler manages effect execution on behalf of effect dispatcher. - * - * @internal - */ - class AsyncHandler extends Handler { - constructor(payload, dependencies, asyncFunction) { - super(payload, dependencies); - this.asyncFunction = asyncFunction; - this.abortSignal = new AbortSignal(); - } - start() { - this.asyncFunction(this.payload, this.abortSignal, this.dependencies).catch((error) => { - // swallow the error - }); - } - cancel() { - this.abortSignal.abort(); - } - } - /** - * Asynchronous effect invocation handler constructor. - * - * @param handlerFunction - Function which performs asynchronous action and should be called on `start`. - * - * @internal - */ - const asyncHandler = (handlerFunction) => (payload, dependencies) => new AsyncHandler(payload, dependencies, handlerFunction); - - /** - * Presence Event Engine effects module. - * - * @internal - */ - /** - * Presence heartbeat effect. - * - * Performs presence heartbeat REST API call. - * - * @internal - */ - const heartbeat = createManagedEffect('HEARTBEAT', (channels, groups) => ({ - channels, - groups, - })); - /** - * Presence leave effect. - * - * Performs presence leave REST API call. - * - * @internal - */ - const leave = createEffect('LEAVE', (channels, groups) => ({ - channels, - groups, - })); - /** - * Emit presence heartbeat REST API call result status effect. - * - * Notify status change event listeners. - * - * @internal - */ - /* eslint-disable @typescript-eslint/no-explicit-any */ - const emitStatus$1 = createEffect('EMIT_STATUS', (status) => status); - /** - * Heartbeat delay effect. - * - * Delay of configured length (heartbeat interval) before another heartbeat REST API call will be done. - * - * @internal - */ - const wait = createManagedEffect('WAIT', () => ({})); - - /** - * Presence Event Engine events module. - * - * @internal - */ - /** - * Reconnect event. - * - * Event is sent each time when user restores real-time updates processing and notifies other present subscribers - * about joining back. - * - * @internal - */ - const reconnect$1 = createEvent('RECONNECT', () => ({})); - /** - * Disconnect event. - * - * Event is sent when user wants to temporarily stop real-time updates processing and notifies other present - * subscribers about leaving. - * - * @internal - */ - const disconnect$1 = createEvent('DISCONNECT', (isOffline = false) => ({ isOffline })); - /** - * Channel / group join event. - * - * Event is sent when user adds new channels / groups to the active channels / groups list and notifies other present - * subscribers about joining. - * - * @internal - */ - const joined = createEvent('JOINED', (channels, groups) => ({ - channels, - groups, - })); - /** - * Channel / group leave event. - * - * Event is sent when user removes channels / groups from the active channels / groups list and notifies other present - * subscribers about leaving. - * - * @internal - */ - const left = createEvent('LEFT', (channels, groups) => ({ - channels, - groups, - })); - /** - * Leave all event. - * - * Event is sent when user doesn't want to receive any real-time updates anymore and notifies other - * subscribers on previously active channels / groups about leaving. - * - * @internal - */ - const leftAll = createEvent('LEFT_ALL', (isOffline = false) => ({ isOffline })); - /** - * Presence heartbeat success event. - * - * Event is sent by corresponding effect handler if REST API call was successful. - * - * @internal - */ - const heartbeatSuccess = createEvent('HEARTBEAT_SUCCESS', (statusCode) => ({ statusCode })); - /** - * Presence heartbeat did fail event. - * - * Event is sent by corresponding effect handler if REST API call failed. - * - * @internal - */ - const heartbeatFailure = createEvent('HEARTBEAT_FAILURE', (error) => error); - /** - * Delayed presence heartbeat event. - * - * Event is sent by corresponding effect handler when delay timer between heartbeat calls fired. - * - * @internal - */ - const timesUp = createEvent('TIMES_UP', () => ({})); - - /** - * Presence Event Engine effects dispatcher. - * - * @internal - */ - /** - * Presence Event Engine dispatcher. - * - * Dispatcher responsible for presence events handling and corresponding effects execution. - * - * @internal - */ - class PresenceEventEngineDispatcher extends Dispatcher { - constructor(engine, dependencies) { - super(dependencies, dependencies.config.logger()); - this.on(heartbeat.type, asyncHandler((payload_1, abortSignal_1, _a) => __awaiter(this, [payload_1, abortSignal_1, _a], void 0, function* (payload, abortSignal, { heartbeat, presenceState, config }) { - abortSignal.throwIfAborted(); - try { - const result = yield heartbeat(Object.assign(Object.assign({ abortSignal: abortSignal, channels: payload.channels, channelGroups: payload.groups }, (config.maintainPresenceState && { state: presenceState })), { heartbeat: config.presenceTimeout })); - engine.transition(heartbeatSuccess(200)); - } - catch (e) { - if (e instanceof PubNubError) { - if (e.status && e.status.category == StatusCategory$1.PNCancelledCategory) - return; - engine.transition(heartbeatFailure(e)); - } - } - }))); - this.on(leave.type, asyncHandler((payload_1, _1, _a) => __awaiter(this, [payload_1, _1, _a], void 0, function* (payload, _, { leave, config }) { - if (!config.suppressLeaveEvents) { - try { - leave({ - channels: payload.channels, - channelGroups: payload.groups, - }); - } - catch (e) { } - } - }))); - this.on(wait.type, asyncHandler((_1, abortSignal_1, _a) => __awaiter(this, [_1, abortSignal_1, _a], void 0, function* (_, abortSignal, { heartbeatDelay }) { - const { cancelDelay, promise } = heartbeatDelay(); - abortSignal.throwIfAborted(); - const unsubscribeAbortListener = abortSignal.subscribe(() => cancelDelay()); - yield promise; - unsubscribeAbortListener(); - abortSignal.throwIfAborted(); - return engine.transition(timesUp()); - }))); - this.on(emitStatus$1.type, asyncHandler((payload_1, _1, _a) => __awaiter(this, [payload_1, _1, _a], void 0, function* (payload, _, { emitStatus, config }) { - if (config.announceFailedHeartbeats && (payload === null || payload === void 0 ? void 0 : payload.error) === true) { - emitStatus(Object.assign(Object.assign({}, payload), { operation: RequestOperation$1.PNHeartbeatOperation })); - } - else if (config.announceSuccessfulHeartbeats && payload.statusCode === 200) { - emitStatus(Object.assign(Object.assign({}, payload), { error: false, operation: RequestOperation$1.PNHeartbeatOperation, category: StatusCategory$1.PNAcknowledgmentCategory })); - } - }))); - } - } - - /** - * Presence Event Engine state instances. - * - * Isolated from transition handlers so state modules can import sibling states - * without creating circular dependencies. - * - * @internal - */ - /** @internal */ - const HeartbeatInactiveState = new State('HEARTBEAT_INACTIVE'); - /** @internal */ - const HeartbeatingState = new State('HEARTBEATING'); - /** @internal */ - const HeartbeatCooldownState = new State('HEARTBEAT_COOLDOWN'); - /** @internal */ - const HeartbeatStoppedState = new State('HEARTBEAT_STOPPED'); - /** @internal */ - const HeartbeatFailedState = new State('HEARTBEAT_FAILED'); - - /** - * Inactive heratbeating state module. - * - * @internal - */ - /** - * Inactive heratbeating state - * - * State in which Presence Event Engine doesn't process any heartbeat requests (initial state). - * - * @internal - */ - HeartbeatInactiveState.on(joined.type, (_, event) => HeartbeatingState.with({ - channels: event.payload.channels, - groups: event.payload.groups, - })); - - /** - * Heartbeating state module. - * - * @internal - */ - /** - * Heartbeating state module. - * - * State in which Presence Event Engine send heartbeat REST API call. - * - * @internal - */ - HeartbeatingState.onEnter((context) => heartbeat(context.channels, context.groups)); - HeartbeatingState.onExit(() => heartbeat.cancel); - HeartbeatingState.on(heartbeatSuccess.type, (context, event) => HeartbeatCooldownState.with({ channels: context.channels, groups: context.groups }, [ - emitStatus$1(Object.assign({}, event.payload)), - ])); - HeartbeatingState.on(joined.type, (context, event) => HeartbeatingState.with({ - channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], - groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], - })); - HeartbeatingState.on(left.type, (context, event) => { - return HeartbeatingState.with({ - channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), - groups: context.groups.filter((group) => !event.payload.groups.includes(group)), - }, [leave(event.payload.channels, event.payload.groups)]); - }); - HeartbeatingState.on(heartbeatFailure.type, (context, event) => HeartbeatFailedState.with(Object.assign({}, context), [ - ...(event.payload.status ? [emitStatus$1(Object.assign({}, event.payload.status))] : []), - ])); - HeartbeatingState.on(disconnect$1.type, (context, event) => HeartbeatStoppedState.with({ channels: context.channels, groups: context.groups }, [ - ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), - ])); - HeartbeatingState.on(leftAll.type, (context, event) => HeartbeatInactiveState.with(undefined, [ - ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), - ])); - - /** - * Waiting next heartbeat state module. - * - * @internal - */ - /** - * Waiting next heartbeat state. - * - * State in which Presence Event Engine is waiting when delay will run out and next heartbeat call should be done. - * - * @internal - */ - HeartbeatCooldownState.onEnter(() => wait()); - HeartbeatCooldownState.onExit(() => wait.cancel); - HeartbeatCooldownState.on(timesUp.type, (context, _) => HeartbeatingState.with({ - channels: context.channels, - groups: context.groups, - })); - HeartbeatCooldownState.on(joined.type, (context, event) => HeartbeatingState.with({ - channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], - groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], - })); - HeartbeatCooldownState.on(left.type, (context, event) => HeartbeatingState.with({ - channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), - groups: context.groups.filter((group) => !event.payload.groups.includes(group)), - }, [leave(event.payload.channels, event.payload.groups)])); - HeartbeatCooldownState.on(disconnect$1.type, (context, event) => HeartbeatStoppedState.with({ channels: context.channels, groups: context.groups }, [ - ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), - ])); - HeartbeatCooldownState.on(leftAll.type, (context, event) => HeartbeatInactiveState.with(undefined, [ - ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), - ])); - - /** - * Heartbeat stopped state module. - * - * @internal - */ - /** - * Heartbeat stopped state. - * - * State in which Presence Event Engine still has information about active channels / groups, but doesn't wait for - * delayed heartbeat request sending. - * - * @internal - */ - HeartbeatStoppedState.on(joined.type, (context, event) => HeartbeatStoppedState.with({ - channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], - groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], - })); - HeartbeatStoppedState.on(left.type, (context, event) => HeartbeatStoppedState.with({ - channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), - groups: context.groups.filter((group) => !event.payload.groups.includes(group)), - })); - HeartbeatStoppedState.on(reconnect$1.type, (context, _) => HeartbeatingState.with({ - channels: context.channels, - groups: context.groups, - })); - HeartbeatStoppedState.on(leftAll.type, (context, _) => HeartbeatInactiveState.with(undefined)); - - /** - * Failed to heartbeat state module. - * - * @internal - */ - /** - * Failed to heartbeat state. - * - * State in which Subscription Event Engine waits for user to try to reconnect after all retry attempts has been - * exhausted. - * - * @internal - */ - HeartbeatFailedState.on(joined.type, (context, event) => HeartbeatingState.with({ - channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], - groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], - })); - HeartbeatFailedState.on(left.type, (context, event) => HeartbeatingState.with({ - channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), - groups: context.groups.filter((group) => !event.payload.groups.includes(group)), - }, [leave(event.payload.channels, event.payload.groups)])); - HeartbeatFailedState.on(reconnect$1.type, (context, _) => HeartbeatingState.with({ - channels: context.channels, - groups: context.groups, - })); - HeartbeatFailedState.on(disconnect$1.type, (context, event) => HeartbeatStoppedState.with({ channels: context.channels, groups: context.groups }, [ - ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), - ])); - HeartbeatFailedState.on(leftAll.type, (context, event) => HeartbeatInactiveState.with(undefined, [ - ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), - ])); - - /** - * Presence Event Engine module. - * - * @internal - */ - /** - * Presence Event Engine Core. - * - * @internal - */ - class PresenceEventEngine { - get _engine() { - return this.engine; - } - constructor(dependencies) { - this.dependencies = dependencies; - this.channels = []; - this.groups = []; - this.engine = new Engine(dependencies.config.logger()); - this.dispatcher = new PresenceEventEngineDispatcher(this.engine, dependencies); - dependencies.config.logger().debug('PresenceEventEngine', 'Create presence event engine.'); - this._unsubscribeEngine = this.engine.subscribe((change) => { - if (change.type === 'invocationDispatched') { - this.dispatcher.dispatch(change.invocation); - } - }); - this.engine.start(HeartbeatInactiveState, undefined); - } - join({ channels, groups }) { - this.channels = [...this.channels, ...(channels !== null && channels !== void 0 ? channels : []).filter((channel) => !this.channels.includes(channel))]; - this.groups = [...this.groups, ...(groups !== null && groups !== void 0 ? groups : []).filter((group) => !this.groups.includes(group))]; - // Don't make any transitions if there is no channels and groups. - if (this.channels.length === 0 && this.groups.length === 0) - return; - this.engine.transition(joined(this.channels.slice(0), this.groups.slice(0))); - } - leave({ channels, groups }) { - // Update internal channel tracking to prevent stale heartbeat requests - if (channels) - this.channels = this.channels.filter((channel) => !channels.includes(channel)); - if (groups) - this.groups = this.groups.filter((group) => !groups.includes(group)); - if (this.dependencies.presenceState) { - channels === null || channels === void 0 ? void 0 : channels.forEach((c) => delete this.dependencies.presenceState[c]); - groups === null || groups === void 0 ? void 0 : groups.forEach((g) => delete this.dependencies.presenceState[g]); - } - this.engine.transition(left(channels !== null && channels !== void 0 ? channels : [], groups !== null && groups !== void 0 ? groups : [])); - } - leaveAll(isOffline = false) { - // Clear presence state for all current channels and groups - if (this.dependencies.presenceState) { - this.channels.forEach((c) => delete this.dependencies.presenceState[c]); - this.groups.forEach((g) => delete this.dependencies.presenceState[g]); - } - // Reset internal channel and group tracking - this.channels = []; - this.groups = []; - this.engine.transition(leftAll(isOffline)); - } - reconnect() { - this.engine.transition(reconnect$1()); - } - disconnect(isOffline = false) { - this.engine.transition(disconnect$1(isOffline)); - } - dispose() { - this.disconnect(true); - this._unsubscribeEngine(); - this.dispatcher.dispose(); - } - } - - /** - * Subscribe Event Engine events module. - * - * @internal - */ - /** - * Subscription list change event. - * - * Event is sent each time when the user would like to change a list of active channels / groups. - * - * @internal - */ - const subscriptionChange = createEvent('SUBSCRIPTION_CHANGED', (channels, groups, isOffline = false) => ({ - channels, - groups, - isOffline, - })); - /** - * Subscription loop restore. - * - * Event is sent when a user would like to try to catch up on missed updates by providing specific timetoken. - * - * @internal - */ - const restore = createEvent('SUBSCRIPTION_RESTORED', (channels, groups, timetoken, region) => ({ - channels, - groups, - cursor: { - timetoken: timetoken, - region: region !== null && region !== void 0 ? region : 0, - }, - })); - /** - * Initial subscription handshake success event. - * - * Event is sent by the corresponding effect handler if the REST API call was successful. - * - * @internal - */ - const handshakeSuccess = createEvent('HANDSHAKE_SUCCESS', (cursor) => cursor); - /** - * The initial subscription handshake did fail event. - * - * Event is sent by the corresponding effect handler if the REST API call failed. - * - * @internal - */ - const handshakeFailure = createEvent('HANDSHAKE_FAILURE', (error) => error); - /** - * Subscription successfully received real-time updates event. - * - * Event is sent by the corresponding effect handler if the REST API call was successful. - * - * @internal - */ - const receiveSuccess = createEvent('RECEIVE_SUCCESS', (cursor, events) => ({ - cursor, - events, - })); - /** - * Subscription did fail to receive real-time updates event. - * - * Event is sent by the corresponding effect handler if the REST API call failed. - * - * @internal - */ - const receiveFailure = createEvent('RECEIVE_FAILURE', (error) => error); - /** - * Client disconnect event. - * - * Event is sent when the user wants to temporarily stop real-time updates receive. - * - * @internal - */ - const disconnect = createEvent('DISCONNECT', (isOffline = false) => ({ isOffline })); - /** - * Client reconnect event. - * - * Event is sent when the user wants to restore real-time updates receive. - * - * @internal - */ - const reconnect = createEvent('RECONNECT', (timetoken, region) => ({ - cursor: { - timetoken: timetoken !== null && timetoken !== void 0 ? timetoken : '', - region: region !== null && region !== void 0 ? region : 0, - }, - })); - /** - * Completely stop real-time updates receive event. - * - * Event is sent when the user doesn't want to receive any real-time updates anymore. - * - * @internal - */ - const unsubscribeAll = createEvent('UNSUBSCRIBE_ALL', () => ({})); - - /** - * Subscribe Event Engine state instances. - * - * Isolated from transition handlers so state modules can import sibling states - * without creating circular dependencies. - * - * @internal - */ - /** @internal */ - const UnsubscribedState = new State('UNSUBSCRIBED'); - /** @internal */ - const HandshakingState = new State('HANDSHAKING'); - /** @internal */ - const HandshakeStoppedState = new State('HANDSHAKE_STOPPED'); - /** @internal */ - const HandshakeFailedState = new State('HANDSHAKE_FAILED'); - /** @internal */ - const ReceivingState = new State('RECEIVING'); - /** @internal */ - const ReceiveStoppedState = new State('RECEIVE_STOPPED'); - /** @internal */ - const ReceiveFailedState = new State('RECEIVE_FAILED'); - - /** - * Unsubscribed / disconnected state module. - * - * @internal - */ - /** - * Unsubscribed / disconnected state. - * - * State in which Subscription Event Engine doesn't process any real-time updates. - * - * @internal - */ - UnsubscribedState.on(subscriptionChange.type, (_, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ channels: payload.channels, groups: payload.groups, onDemand: true }); - }); - UnsubscribedState.on(restore.type, (_, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region }, - onDemand: true, - }); - }); - - /** - * Subscribe Event Engine effects module. - * - * @internal - */ - /** - * Initial subscription effect. - * - * Performs subscribe REST API call with `tt=0`. - * - * @internal - */ - const handshake = createManagedEffect('HANDSHAKE', (channels, groups, onDemand) => ({ - channels, - groups, - onDemand, - })); - /** - * Real-time updates receive effect. - * - * Performs sequential subscribe REST API call with `tt` set to the value received from the previous subscribe - * REST API call. - * - * @internal - */ - const receiveMessages = createManagedEffect('RECEIVE_MESSAGES', (channels, groups, cursor, onDemand) => ({ - channels, - groups, - cursor, - onDemand, - })); - /** - * Emit real-time updates effect. - * - * Notify event listeners about updates for which listener handlers has been provided. - * - * @internal - */ - const emitMessages = createEffect('EMIT_MESSAGES', (cursor, events) => ({ - cursor, - events, - })); - /** - * Emit subscription status change effect. - * - * Notify status change event listeners. - * - * @internal - */ - const emitStatus = createEffect('EMIT_STATUS', (status) => status); - - /** - * Initial subscription handshake (disconnected) state. - * - * @internal - */ - /** - * Initial subscription handshake (disconnected) state. - * - * State in which Subscription Event Engine tries to receive the subscription cursor for the next sequential - * subscribe REST API calls. - * - * @internal - */ - HandshakingState.onEnter((context) => { var _a; return handshake(context.channels, context.groups, (_a = context.onDemand) !== null && _a !== void 0 ? _a : false); }); - HandshakingState.onExit(() => handshake.cancel); - HandshakingState.on(subscriptionChange.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: context.cursor, - onDemand: true, - }); - }); - HandshakingState.on(handshakeSuccess.type, (context, { payload }) => { - var _a, _b, _c, _d, _e; - return ReceivingState.with({ - channels: context.channels, - groups: context.groups, - cursor: { - timetoken: !!((_a = context.cursor) === null || _a === void 0 ? void 0 : _a.timetoken) ? (_b = context.cursor) === null || _b === void 0 ? void 0 : _b.timetoken : payload.timetoken, - region: payload.region, - }, - referenceTimetoken: referenceSubscribeTimetoken(payload.timetoken, (_c = context.cursor) === null || _c === void 0 ? void 0 : _c.timetoken), - }, [ - emitStatus({ - category: StatusCategory$1.PNConnectedCategory, - affectedChannels: context.channels.slice(0), - affectedChannelGroups: context.groups.slice(0), - operation: RequestOperation$1.PNSubscribeOperation, - currentTimetoken: !!((_d = context.cursor) === null || _d === void 0 ? void 0 : _d.timetoken) ? (_e = context.cursor) === null || _e === void 0 ? void 0 : _e.timetoken : payload.timetoken, - }), - ]); - }); - HandshakingState.on(handshakeFailure.type, (context, event) => { - var _a; - return HandshakeFailedState.with(Object.assign(Object.assign({}, context), { reason: event.payload }), [ - emitStatus({ category: StatusCategory$1.PNConnectionErrorCategory, error: (_a = event.payload.status) === null || _a === void 0 ? void 0 : _a.category }), - ]); - }); - HandshakingState.on(disconnect.type, (context, event) => { - var _a; - if (!event.payload.isOffline) - return HandshakeStoppedState.with(Object.assign({}, context)); - else { - const errorReason = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation); - return HandshakeFailedState.with(Object.assign(Object.assign({}, context), { reason: errorReason }), [ - emitStatus({ - category: StatusCategory$1.PNConnectionErrorCategory, - error: (_a = errorReason.status) === null || _a === void 0 ? void 0 : _a.category, - }), - ]); - } - }); - HandshakingState.on(restore.type, (context, { payload }) => { - var _a; - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || ((_a = context === null || context === void 0 ? void 0 : context.cursor) === null || _a === void 0 ? void 0 : _a.region) || 0 }, - onDemand: true, - }); - }); - HandshakingState.on(unsubscribeAll.type, (_) => UnsubscribedState.with()); - - /** - * Stopped initial subscription handshake (disconnected) state. - * - * @internal - */ - /** - * Stopped initial subscription handshake (disconnected) state. - * - * State in which Subscription Event Engine still has information about subscription but doesn't have subscription - * cursor for next sequential subscribe REST API call. - * - * @internal - */ - HandshakeStoppedState.on(subscriptionChange.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakeStoppedState.with({ channels: payload.channels, groups: payload.groups, cursor: context.cursor }); - }); - HandshakeStoppedState.on(reconnect.type, (context, { payload }) => HandshakingState.with(Object.assign(Object.assign({}, context), { cursor: payload.cursor || context.cursor, onDemand: true }))); - HandshakeStoppedState.on(restore.type, (context, { payload }) => { - var _a; - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakeStoppedState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || ((_a = context.cursor) === null || _a === void 0 ? void 0 : _a.region) || 0 }, - }); - }); - HandshakeStoppedState.on(unsubscribeAll.type, (_) => UnsubscribedState.with()); - - /** - * Failed initial subscription handshake (disconnected) state. - * - * @internal - */ - /** - * Failed initial subscription handshake (disconnected) state. - * - * State in which Subscription Event Engine waits for user to try to reconnect after all retry attempts has been - * exhausted. - * - * @internal - */ - HandshakeFailedState.on(subscriptionChange.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: context.cursor, - onDemand: true, - }); - }); - HandshakeFailedState.on(reconnect.type, (context, { payload }) => HandshakingState.with(Object.assign(Object.assign({}, context), { cursor: payload.cursor || context.cursor, onDemand: true }))); - HandshakeFailedState.on(restore.type, (context, { payload }) => { - var _a, _b; - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { - timetoken: `${payload.cursor.timetoken}`, - region: payload.cursor.region ? payload.cursor.region : ((_b = (_a = context === null || context === void 0 ? void 0 : context.cursor) === null || _a === void 0 ? void 0 : _a.region) !== null && _b !== void 0 ? _b : 0), - }, - onDemand: true, - }); - }); - HandshakeFailedState.on(unsubscribeAll.type, (_) => UnsubscribedState.with()); - - /** - * Receiving real-time updates (connected) state module. - * - * @internal - */ - /** - * Receiving real-time updates (connected) state. - * - * State in which Subscription Event Engine processes any real-time updates. - * - * @internal - */ - ReceivingState.onEnter((context) => { var _a; return receiveMessages(context.channels, context.groups, context.cursor, (_a = context.onDemand) !== null && _a !== void 0 ? _a : false); }); - ReceivingState.onExit(() => receiveMessages.cancel); - ReceivingState.on(receiveSuccess.type, (context, { payload }) => ReceivingState.with({ - channels: context.channels, - groups: context.groups, - cursor: payload.cursor, - referenceTimetoken: referenceSubscribeTimetoken(payload.cursor.timetoken), - }, [emitMessages(context.cursor, payload.events)])); - ReceivingState.on(subscriptionChange.type, (context, { payload }) => { - var _a; - if (payload.channels.length === 0 && payload.groups.length === 0) { - let errorCategory; - if (payload.isOffline) - errorCategory = (_a = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation).status) === null || _a === void 0 ? void 0 : _a.category; - return UnsubscribedState.with(undefined, [ - emitStatus(Object.assign({ category: !payload.isOffline - ? StatusCategory$1.PNDisconnectedCategory - : StatusCategory$1.PNDisconnectedUnexpectedlyCategory, operation: RequestOperation$1.PNUnsubscribeOperation }, (errorCategory ? { error: errorCategory } : {}))), - ]); - } - return ReceivingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: context.cursor, - referenceTimetoken: context.referenceTimetoken, - onDemand: true, - }, [ - emitStatus({ - category: StatusCategory$1.PNSubscriptionChangedCategory, - affectedChannels: payload.channels.slice(0), - affectedChannelGroups: payload.groups.slice(0), - currentTimetoken: context.cursor.timetoken, - }), - ]); - }); - ReceivingState.on(restore.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined, [emitStatus({ category: StatusCategory$1.PNDisconnectedCategory })]); - return ReceivingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || context.cursor.region }, - referenceTimetoken: referenceSubscribeTimetoken(context.cursor.timetoken, `${payload.cursor.timetoken}`, context.referenceTimetoken), - onDemand: true, - }, [ - emitStatus({ - category: StatusCategory$1.PNSubscriptionChangedCategory, - affectedChannels: payload.channels.slice(0), - affectedChannelGroups: payload.groups.slice(0), - currentTimetoken: payload.cursor.timetoken, - }), - ]); - }); - ReceivingState.on(receiveFailure.type, (context, { payload }) => { - var _a; - return ReceiveFailedState.with(Object.assign(Object.assign({}, context), { reason: payload }), [ - emitStatus({ category: StatusCategory$1.PNDisconnectedUnexpectedlyCategory, error: (_a = payload.status) === null || _a === void 0 ? void 0 : _a.category }), - ]); - }); - ReceivingState.on(disconnect.type, (context, event) => { - var _a; - if (!event.payload.isOffline) { - return ReceiveStoppedState.with(Object.assign({}, context), [ - emitStatus({ - category: StatusCategory$1.PNDisconnectedCategory, - operation: RequestOperation$1.PNSubscribeOperation, - }), - ]); - } - else { - const errorReason = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation); - return ReceiveFailedState.with(Object.assign(Object.assign({}, context), { reason: errorReason }), [ - emitStatus({ - category: StatusCategory$1.PNDisconnectedUnexpectedlyCategory, - operation: RequestOperation$1.PNSubscribeOperation, - error: (_a = errorReason.status) === null || _a === void 0 ? void 0 : _a.category, - }), - ]); - } - }); - ReceivingState.on(unsubscribeAll.type, (_) => UnsubscribedState.with(undefined, [ - emitStatus({ - category: StatusCategory$1.PNDisconnectedCategory, - operation: RequestOperation$1.PNUnsubscribeOperation, - }), - ])); - - /** - * Stopped real-time updates (disconnected) state module. - * - * @internal - */ - /** - * Stopped real-time updates (disconnected) state. - * - * State in which Subscription Event Engine still has information about subscription but doesn't process real-time - * updates. - * - * @internal - */ - ReceiveStoppedState.on(subscriptionChange.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return ReceiveStoppedState.with({ channels: payload.channels, groups: payload.groups, cursor: context.cursor }); - }); - ReceiveStoppedState.on(restore.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return ReceiveStoppedState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || context.cursor.region }, - }); - }); - ReceiveStoppedState.on(reconnect.type, (context, { payload }) => { - var _a; - return HandshakingState.with({ - channels: context.channels, - groups: context.groups, - cursor: { - timetoken: !!payload.cursor.timetoken ? (_a = payload.cursor) === null || _a === void 0 ? void 0 : _a.timetoken : context.cursor.timetoken, - region: payload.cursor.region || context.cursor.region, - }, - onDemand: true, - }); - }); - ReceiveStoppedState.on(unsubscribeAll.type, () => UnsubscribedState.with(undefined)); - - /** - * Failed to receive real-time updates (disconnected) state. - * - * @internal - */ - /** - * Failed to receive real-time updates (disconnected) state. - * - * State in which Subscription Event Engine waits for user to try to reconnect after all retry attempts has been - * exhausted. - * - * @internal - */ - ReceiveFailedState.on(reconnect.type, (context, { payload }) => { - var _a; - return HandshakingState.with({ - channels: context.channels, - groups: context.groups, - cursor: { - timetoken: !!payload.cursor.timetoken ? (_a = payload.cursor) === null || _a === void 0 ? void 0 : _a.timetoken : context.cursor.timetoken, - region: payload.cursor.region || context.cursor.region, - }, - onDemand: true, - }); - }); - ReceiveFailedState.on(subscriptionChange.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: context.cursor, - onDemand: true, - }); - }); - ReceiveFailedState.on(restore.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || context.cursor.region }, - onDemand: true, - }); - }); - ReceiveFailedState.on(unsubscribeAll.type, (_) => UnsubscribedState.with(undefined)); - - /** - * Subscribe Event Engine effects dispatcher. - * - * @internal - */ - /** - * Subscribe Event Engine dispatcher. - * - * Dispatcher responsible for subscription events handling and corresponding effects execution. - * - * @internal - */ - class EventEngineDispatcher extends Dispatcher { - constructor(engine, dependencies) { - super(dependencies, dependencies.config.logger()); - this.on(handshake.type, asyncHandler((payload_1, abortSignal_1, _a) => __awaiter(this, [payload_1, abortSignal_1, _a], void 0, function* (payload, abortSignal, { handshake, presenceState, config }) { - abortSignal.throwIfAborted(); - try { - const result = yield handshake(Object.assign(Object.assign({ abortSignal: abortSignal, channels: payload.channels, channelGroups: payload.groups, filterExpression: config.filterExpression }, (config.maintainPresenceState && { state: presenceState })), { onDemand: payload.onDemand })); - return engine.transition(handshakeSuccess(result)); - } - catch (e) { - if (e instanceof PubNubError) { - if (e.status && e.status.category == StatusCategory$1.PNCancelledCategory) - return; - return engine.transition(handshakeFailure(e)); - } - } - }))); - this.on(receiveMessages.type, asyncHandler((payload_1, abortSignal_1, _a) => __awaiter(this, [payload_1, abortSignal_1, _a], void 0, function* (payload, abortSignal, { receiveMessages, config }) { - abortSignal.throwIfAborted(); - try { - const result = yield receiveMessages({ - abortSignal: abortSignal, - channels: payload.channels, - channelGroups: payload.groups, - timetoken: payload.cursor.timetoken, - region: payload.cursor.region, - filterExpression: config.filterExpression, - onDemand: payload.onDemand, - }); - engine.transition(receiveSuccess(result.cursor, result.messages)); - } - catch (error) { - if (error instanceof PubNubError) { - if (error.status && error.status.category == StatusCategory$1.PNCancelledCategory) - return; - if (!abortSignal.aborted) - return engine.transition(receiveFailure(error)); - } - } - }))); - this.on(emitMessages.type, asyncHandler((_a, _1, _b) => __awaiter(this, [_a, _1, _b], void 0, function* ({ cursor, events }, _, { emitMessages }) { - if (events.length > 0) - emitMessages(cursor, events); - }))); - this.on(emitStatus.type, asyncHandler((payload_1, _1, _a) => __awaiter(this, [payload_1, _1, _a], void 0, function* (payload, _, { emitStatus }) { return emitStatus(payload); }))); - } - } - - /** - * Subscribe Event Engine module. - * - * @internal - */ - /** - * Subscribe Event Engine Core. - * - * @internal - */ - class EventEngine { - get _engine() { - return this.engine; - } - constructor(dependencies) { - this.channels = []; - this.groups = []; - this.dependencies = dependencies; - this.engine = new Engine(dependencies.config.logger()); - this.dispatcher = new EventEngineDispatcher(this.engine, dependencies); - dependencies.config.logger().debug('EventEngine', 'Create subscribe event engine.'); - this._unsubscribeEngine = this.engine.subscribe((change) => { - if (change.type === 'invocationDispatched') { - this.dispatcher.dispatch(change.invocation); - } - }); - this.engine.start(UnsubscribedState, undefined); - } - /** - * Subscription-based current timetoken. - * - * @returns Timetoken based on current timetoken plus diff between current and loop start time. - */ - get subscriptionTimetoken() { - const currentState = this.engine.currentState; - if (!currentState) - return undefined; - let referenceTimetoken; - let currentTimetoken = '0'; - if (currentState.label === ReceivingState.label) { - const context = this.engine.currentContext; - currentTimetoken = context.cursor.timetoken; - referenceTimetoken = context.referenceTimetoken; - } - return subscriptionTimetokenFromReference(currentTimetoken, referenceTimetoken !== null && referenceTimetoken !== void 0 ? referenceTimetoken : '0'); - } - subscribe({ channels, channelGroups, timetoken, withPresence, }) { - var _a; - // check if the channels and groups are already subscribed - const hasNewChannels = channels === null || channels === void 0 ? void 0 : channels.some((channel) => !this.channels.includes(channel)); - const hasNewGroups = channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.some((group) => !this.groups.includes(group)); - const hasNewSubscriptions = hasNewChannels || hasNewGroups; - this.channels = [...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])]; - this.groups = [...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])]; - if (withPresence) { - this.channels.map((c) => this.channels.push(`${c}-pnpres`)); - this.groups.map((g) => this.groups.push(`${g}-pnpres`)); - } - if (timetoken) { - this.engine.transition(restore(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])])), timetoken)); - } - else { - if (hasNewSubscriptions) { - this.engine.transition(subscriptionChange(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])])))); - } - else { - this.dependencies.config - .logger() - .debug('EventEngine', 'Skipping state transition - all channels/groups already subscribed. Emitting SubscriptionChanged event.'); - // Get current timetoken from state context - const currentState = this.engine.currentState; - const currentContext = this.engine.currentContext; - let currentTimetoken = '0'; - if ((currentState === null || currentState === void 0 ? void 0 : currentState.label) === ReceivingState.label && currentContext) { - const receivingContext = currentContext; - currentTimetoken = (_a = receivingContext.cursor) === null || _a === void 0 ? void 0 : _a.timetoken; - } - // Manually emit SubscriptionChanged status event - this.dependencies.emitStatus({ - category: StatusCategory$1.PNSubscriptionChangedCategory, - affectedChannels: Array.from(new Set(this.channels)), - affectedChannelGroups: Array.from(new Set(this.groups)), - currentTimetoken, - }); - } - } - if (this.dependencies.join) { - this.dependencies.join({ - channels: Array.from(new Set(this.channels.filter((c) => !c.endsWith('-pnpres')))), - groups: Array.from(new Set(this.groups.filter((g) => !g.endsWith('-pnpres')))), - }); - } - } - unsubscribe({ channels = [], channelGroups = [] }) { - const filteredChannels = removeSingleOccurrence(this.channels, [ - ...channels, - ...channels.map((c) => `${c}-pnpres`), - ]); - const filteredGroups = removeSingleOccurrence(this.groups, [ - ...channelGroups, - ...channelGroups.map((c) => `${c}-pnpres`), - ]); - if (new Set(this.channels).size !== new Set(filteredChannels).size || - new Set(this.groups).size !== new Set(filteredGroups).size) { - const channelsToLeave = findUniqueCommonElements(this.channels, channels); - const groupsToLeave = findUniqueCommonElements(this.groups, channelGroups); - if (this.dependencies.presenceState) { - channelsToLeave === null || channelsToLeave === void 0 ? void 0 : channelsToLeave.forEach((c) => delete this.dependencies.presenceState[c]); - groupsToLeave === null || groupsToLeave === void 0 ? void 0 : groupsToLeave.forEach((g) => delete this.dependencies.presenceState[g]); - } - this.channels = filteredChannels; - this.groups = filteredGroups; - this.engine.transition(subscriptionChange(Array.from(new Set(this.channels.slice(0))), Array.from(new Set(this.groups.slice(0))))); - if (this.dependencies.leave) { - this.dependencies.leave({ - channels: channelsToLeave.slice(0), - groups: groupsToLeave.slice(0), - }); - } - } - } - unsubscribeAll(isOffline = false) { - const channelGroups = this.getSubscribedChannelGroups(); - const channels = this.getSubscribedChannels(); - this.channels = []; - this.groups = []; - if (this.dependencies.presenceState) { - Object.keys(this.dependencies.presenceState).forEach((objectName) => { - delete this.dependencies.presenceState[objectName]; - }); - } - this.engine.transition(subscriptionChange(this.channels.slice(0), this.groups.slice(0), isOffline)); - if (this.dependencies.leaveAll) - this.dependencies.leaveAll({ channels, groups: channelGroups, isOffline }); - } - reconnect({ timetoken, region }) { - const channelGroups = this.getSubscribedChannels(); - const channels = this.getSubscribedChannels(); - this.engine.transition(reconnect(timetoken, region)); - if (this.dependencies.presenceReconnect) - this.dependencies.presenceReconnect({ channels, groups: channelGroups }); - } - disconnect(isOffline = false) { - const channelGroups = this.getSubscribedChannels(); - const channels = this.getSubscribedChannels(); - this.engine.transition(disconnect(isOffline)); - if (this.dependencies.presenceDisconnect) - this.dependencies.presenceDisconnect({ channels, groups: channelGroups, isOffline }); - } - getSubscribedChannels() { - return Array.from(new Set(this.channels.slice(0))); - } - getSubscribedChannelGroups() { - return Array.from(new Set(this.groups.slice(0))); - } - dispose() { - this.disconnect(true); - this._unsubscribeEngine(); - this.dispatcher.dispose(); - } - } - - /** - * Publish REST API module. - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether data is published used `POST` body or not. - */ - const SEND_BY_POST = false; - // endregion - /** - * Data publish request. - * - * Request will normalize and encrypt (if required) provided data and push it to the specified - * channel. - * - * @internal - */ - class PublishRequest extends AbstractRequest { - /** - * Construct data publish request. - * - * @param parameters - Request configuration. - */ - constructor(parameters) { - var _a; - const sendByPost = (_a = parameters.sendByPost) !== null && _a !== void 0 ? _a : SEND_BY_POST; - super({ method: sendByPost ? TransportMethod.POST : TransportMethod.GET, compressible: sendByPost }); - this.parameters = parameters; - // Apply default request parameters. - this.parameters.sendByPost = sendByPost; - } - operation() { - return RequestOperation$1.PNPublishOperation; - } - validate() { - const { message, channel, keySet: { publishKey }, } = this.parameters; - if (!channel) - return "Missing 'channel'"; - if (!message) - return "Missing 'message'"; - if (!publishKey) - return "Missing 'publishKey'"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { timetoken: this.deserializeResponse(response)[2] }; - }); - } - get path() { - const { message, channel, keySet } = this.parameters; - const stringifiedPayload = this.prepareMessagePayload(message); - return `/publish/${keySet.publishKey}/${keySet.subscribeKey}/0/${encodeString(channel)}/0${!this.parameters.sendByPost ? `/${encodeString(stringifiedPayload)}` : ''}`; - } - get queryParameters() { - const { customMessageType, meta, replicate, storeInHistory, ttl } = this.parameters; - const query = {}; - if (customMessageType) - query.custom_message_type = customMessageType; - if (storeInHistory !== undefined) - query.store = storeInHistory ? '1' : '0'; - if (ttl !== undefined) - query.ttl = ttl; - if (replicate !== undefined && !replicate) - query.norep = 'true'; - if (meta && typeof meta === 'object') - query.meta = JSON.stringify(meta); - return query; - } - get headers() { - var _a; - if (!this.parameters.sendByPost) - return super.headers; - return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); - } - get body() { - return this.prepareMessagePayload(this.parameters.message); - } - /** - * Pre-process provided data. - * - * Data will be "normalized" and encrypted if `cryptoModule` has been provided. - * - * @param payload - User-provided data which should be pre-processed before use. - * - * @returns Payload which can be used as part of request URL or body. - * - * @throws {Error} in case if provided `payload` or results of `encryption` can't be stringified. - */ - prepareMessagePayload(payload) { - const { crypto } = this.parameters; - if (!crypto) - return JSON.stringify(payload) || ''; - const encrypted = crypto.encrypt(JSON.stringify(payload)); - return JSON.stringify(typeof encrypted === 'string' ? encrypted : encode(encrypted)); - } - } - - /** - * Signal REST API module. - */ - // endregion - /** - * Signal data (size-limited) publish request. - * - * @internal - */ - class SignalRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSignalOperation; - } - validate() { - const { message, channel, keySet: { publishKey }, } = this.parameters; - if (!channel) - return "Missing 'channel'"; - if (!message) - return "Missing 'message'"; - if (!publishKey) - return "Missing 'publishKey'"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { timetoken: this.deserializeResponse(response)[2] }; - }); - } - get path() { - const { keySet: { publishKey, subscribeKey }, channel, message, } = this.parameters; - const stringifiedPayload = JSON.stringify(message); - return `/signal/${publishKey}/${subscribeKey}/0/${encodeString(channel)}/0/${encodeString(stringifiedPayload)}`; - } - get queryParameters() { - const { customMessageType } = this.parameters; - const query = {}; - if (customMessageType) - query.custom_message_type = customMessageType; - return query; - } - } - - /** - * Receive messages subscribe REST API module. - * - * @internal - */ - /** - * Receive messages subscribe request. - * - * @internal - */ - class ReceiveMessagesSubscribeRequest extends BaseSubscribeRequest { - operation() { - return RequestOperation$1.PNReceiveMessagesOperation; - } - validate() { - const validationResult = super.validate(); - if (validationResult) - return validationResult; - if (!this.parameters.timetoken) - return 'timetoken can not be empty'; - if (!this.parameters.region) - return 'region can not be empty'; - } - get path() { - const { keySet: { subscribeKey }, channels = [], } = this.parameters; - return `/v2/subscribe/${subscribeKey}/${encodeNames(channels.sort(), ',')}/0`; - } - get queryParameters() { - const { channelGroups, filterExpression, timetoken, region, heartbeat, onDemand } = this - .parameters; - const query = { ee: '' }; - if (onDemand) - query['on-demand'] = 1; - if (channelGroups && channelGroups.length > 0) - query['channel-group'] = channelGroups.sort().join(','); - if (filterExpression && filterExpression.length > 0) - query['filter-expr'] = filterExpression; - if (typeof timetoken === 'string') { - if (timetoken && timetoken !== '0' && timetoken.length > 0) - query['tt'] = timetoken; - } - else if (timetoken && timetoken > 0) - query['tt'] = timetoken; - if (region) - query['tr'] = region; - if (heartbeat) - query.heartbeat = heartbeat; - return query; - } - } - - /** - * Handshake subscribe REST API module. - * - * @internal - */ - /** - * Handshake subscribe request. - * - * Separate subscribe request required by Event Engine. - * - * @internal - */ - class HandshakeSubscribeRequest extends BaseSubscribeRequest { - operation() { - return RequestOperation$1.PNHandshakeOperation; - } - get path() { - const { keySet: { subscribeKey }, channels = [], } = this.parameters; - return `/v2/subscribe/${subscribeKey}/${encodeNames(channels.sort(), ',')}/0`; - } - get queryParameters() { - const { channelGroups, heartbeat, filterExpression, state, onDemand } = this - .parameters; - const query = { ee: '' }; - if (onDemand) - query['on-demand'] = 1; - if (channelGroups && channelGroups.length > 0) - query['channel-group'] = channelGroups.sort().join(','); - if (filterExpression && filterExpression.length > 0) - query['filter-expr'] = filterExpression; - if (state && Object.keys(state).length > 0) - query['state'] = JSON.stringify(state); - if (heartbeat) - query.heartbeat = heartbeat; - return query; - } - } - - /** - * SubscriptionCapable entity type. - * - * @internal - */ - var SubscriptionType; - (function (SubscriptionType) { - /** - * Channel identifier, which is part of the URI path. - */ - SubscriptionType[SubscriptionType["Channel"] = 0] = "Channel"; - /** - * Channel group identifiers, which is part of the query parameters. - */ - SubscriptionType[SubscriptionType["ChannelGroup"] = 1] = "ChannelGroup"; - })(SubscriptionType || (SubscriptionType = {})); - - /** - * User-provided channels and groups for subscription. - * - * Object contains information about channels and groups for which real-time updates should be retrieved from the - * PubNub network. - * - * @internal - */ - class SubscriptionInput { - /** - * Create a subscription input object. - * - * @param channels - List of channels which will be used with subscribe REST API to receive real-time updates. - * @param channelGroups - List of channel groups which will be used with subscribe REST API to receive real-time - * updates. - */ - constructor({ channels, channelGroups }) { - /** - * Whether the user input is empty or not. - */ - this.isEmpty = true; - this._channelGroups = new Set((channelGroups !== null && channelGroups !== void 0 ? channelGroups : []).filter((value) => value.length > 0)); - this._channels = new Set((channels !== null && channels !== void 0 ? channels : []).filter((value) => value.length > 0)); - this.isEmpty = this._channels.size === 0 && this._channelGroups.size === 0; - } - /** - * Retrieve total length of subscription input. - * - * @returns Number of channels and groups in subscription input. - */ - get length() { - if (this.isEmpty) - return 0; - return this._channels.size + this._channelGroups.size; - } - /** - * Retrieve a list of user-provided channel names. - * - * @returns List of user-provided channel names. - */ - get channels() { - if (this.isEmpty) - return []; - return Array.from(this._channels); - } - /** - * Retrieve a list of user-provided channel group names. - * - * @returns List of user-provided channel group names. - */ - get channelGroups() { - if (this.isEmpty) - return []; - return Array.from(this._channelGroups); - } - /** - * Check if the given name is contained in the channel or channel group. - * - * @param name - Containing the name to be checked. - * - * @returns `true` if the name is found in the channel or channel group, `false` otherwise. - */ - contains(name) { - if (this.isEmpty) - return false; - return this._channels.has(name) || this._channelGroups.has(name); - } - /** - * Create a new subscription input which will contain all channels and channel groups from both inputs. - * - * @param input - Another subscription input that should be used to aggregate data in new instance. - * - * @returns New subscription input instance with combined channels and channel groups. - */ - with(input) { - return new SubscriptionInput({ - channels: [...this._channels, ...input._channels], - channelGroups: [...this._channelGroups, ...input._channelGroups], - }); - } - /** - * Create a new subscription input which will contain only channels and groups which not present in the input. - * - * @param input - Another subscription input which should be used to filter data in new instance. - * - * @returns New subscription input instance with filtered channels and channel groups. - */ - without(input) { - return new SubscriptionInput({ - channels: [...this._channels].filter((value) => !input._channels.has(value)), - channelGroups: [...this._channelGroups].filter((value) => !input._channelGroups.has(value)), - }); - } - /** - * Add data from another subscription input to the receiver. - * - * @param input - Another subscription input whose data should be added to the receiver. - * - * @returns Receiver instance with updated channels and channel groups. - */ - add(input) { - if (input._channelGroups.size > 0) - this._channelGroups = new Set([...this._channelGroups, ...input._channelGroups]); - if (input._channels.size > 0) - this._channels = new Set([...this._channels, ...input._channels]); - this.isEmpty = this._channels.size === 0 && this._channelGroups.size === 0; - return this; - } - /** - * Remove data from another subscription input from the receiver. - * - * @param input - Another subscription input whose data should be removed from the receiver. - * - * @returns Receiver instance with updated channels and channel groups. - */ - remove(input) { - if (input._channelGroups.size > 0) - this._channelGroups = new Set([...this._channelGroups].filter((value) => !input._channelGroups.has(value))); - if (input._channels.size > 0) - this._channels = new Set([...this._channels].filter((value) => !input._channels.has(value))); - return this; - } - /** - * Remove all data from subscription input. - * - * @returns Receiver instance with updated channels and channel groups. - */ - removeAll() { - this._channels.clear(); - this._channelGroups.clear(); - this.isEmpty = true; - return this; - } - /** - * Serialize a subscription input to string. - * - * @returns Printable string representation of a subscription input. - */ - toString() { - return `SubscriptionInput { channels: [${this.channels.join(', ')}], channelGroups: [${this.channelGroups.join(', ')}], is empty: ${this.isEmpty ? 'true' : 'false'}} }`; - } - } - // endregion - - /** - * Subscription state object. - * - * State object used across multiple subscription object clones. - * - * @internal - */ - class SubscriptionBaseState { - /** - * Create a base subscription state object. - * - * @param client - PubNub client which will work with a subscription object. - * @param subscriptionInput - User's input to be used with subscribe REST API. - * @param options - Subscription behavior options. - * @param referenceTimetoken - High-precision timetoken of the moment when subscription was created for entity. - */ - constructor(client, subscriptionInput, options, referenceTimetoken) { - /** - * Whether a subscribable object subscribed or not. - */ - this._isSubscribed = false; - /** - * The list of references to all {@link SubscriptionBase} clones created for this reference. - */ - this.clones = {}; - /** - * List of a parent subscription state objects list. - * - * List is used to track usage of a subscription object in other subscription object sets. - * - * **Important:** Tracking is required to prevent unexpected unsubscriptions if an object still has a parent. - */ - this.parents = []; - /** - * Unique subscription object identifier. - */ - this._id = uuidGenerator.createUUID(); - this.referenceTimetoken = referenceTimetoken; - this.subscriptionInput = subscriptionInput; - this.options = options; - this.client = client; - } - /** - * Get unique subscription object identifier. - * - * @returns Unique subscription object identifier. - */ - get id() { - return this._id; - } - /** - * Check whether a subscription object is the last clone or not. - * - * @returns `true` if a subscription object is the last clone. - */ - get isLastClone() { - return Object.keys(this.clones).length === 1; - } - /** - * Get whether a subscribable object subscribed or not. - * - * **Warning:** This method shouldn't be overridden by {@link SubscriptionSet}. - * - * @returns Whether a subscribable object subscribed or not. - */ - get isSubscribed() { - if (this._isSubscribed) - return true; - // Checking whether any of "parents" is subscribed. - return this.parents.length > 0 && this.parents.some((state) => state.isSubscribed); - } - /** - * Update active subscription state. - * - * @param value - New subscription state. - */ - set isSubscribed(value) { - if (this.isSubscribed === value) - return; - this._isSubscribed = value; - } - /** - * Add a parent subscription state object to mark the linkage. - * - * @param parent - Parent subscription state object. - * - * @internal - */ - addParentState(parent) { - if (!this.parents.includes(parent)) - this.parents.push(parent); - } - /** - * Remove a parent subscription state object. - * - * @param parent - Parent object for which linkage should be broken. - * - * @internal - */ - removeParentState(parent) { - const parentStateIndex = this.parents.indexOf(parent); - if (parentStateIndex !== -1) - this.parents.splice(parentStateIndex, 1); - } - /** - * Store a clone of a {@link SubscriptionBase} instance with a given instance ID. - * - * @param id - The instance ID to associate with clone. - * @param instance - Reference to the subscription instance to store as a clone. - */ - storeClone(id, instance) { - if (!this.clones[id]) - this.clones[id] = instance; - } - } - /** - * Base subscribe object. - * - * Implementation of base functionality used by {@link SubscriptionObject Subscription} and {@link SubscriptionSet}. - */ - class SubscriptionBase { - /** - * Create a subscription object from the state. - * - * @param state - Subscription state object. - * @param subscriptionType - Actual subscription object type. - * - * @internal - */ - constructor(state, subscriptionType = 'Subscription') { - this.subscriptionType = subscriptionType; - /** - * Unique subscription object identifier. - * - * @internal - */ - this.id = uuidGenerator.createUUID(); - /** - * Event emitter, which will notify listeners about updates received for channels / groups. - * - * @internal - */ - this.eventDispatcher = new EventDispatcher(); - this._state = state; - } - /** - * Subscription state. - * - * @returns Subscription state object. - * - * @internal - */ - get state() { - return this._state; - } - /** - * Get a list of channels which is used for subscription. - * - * @returns List of channel names. - */ - get channels() { - return this.state.subscriptionInput.channels.slice(0); - } - /** - * Get a list of channel groups which is used for subscription. - * - * @returns List of channel group names. - */ - get channelGroups() { - return this.state.subscriptionInput.channelGroups.slice(0); - } - // -------------------------------------------------------- - // -------------------- Event emitter --------------------- - // -------------------------------------------------------- - // region Event emitter - /** - * Set a new message handler. - * - * @param listener - Listener function, which will be called each time when a new message - * is received from the real-time network. - */ - set onMessage(listener) { - this.eventDispatcher.onMessage = listener; - } - /** - * Set a new presence events handler. - * - * @param listener - Listener function, which will be called each time when a new - * presence event is received from the real-time network. - */ - set onPresence(listener) { - this.eventDispatcher.onPresence = listener; - } - /** - * Set a new signal handler. - * - * @param listener - Listener function, which will be called each time when a new signal - * is received from the real-time network. - */ - set onSignal(listener) { - this.eventDispatcher.onSignal = listener; - } - /** - * Set a new app context event handler. - * - * @param listener - Listener function, which will be called each time when a new - * app context event is received from the real-time network. - */ - set onObjects(listener) { - this.eventDispatcher.onObjects = listener; - } - /** - * Set a new message reaction event handler. - * - * @param listener - Listener function, which will be called each time when a - * new message reaction event is received from the real-time network. - */ - set onMessageAction(listener) { - this.eventDispatcher.onMessageAction = listener; - } - /** - * Set a new file handler. - * - * @param listener - Listener function, which will be called each time when a new file - * is received from the real-time network. - */ - set onFile(listener) { - this.eventDispatcher.onFile = listener; - } - /** - * Set a new DataSync event handler. - * - * @param listener - Listener function, which will be called each time when a new - * DataSync event is received from the real-time network. - */ - set onDataSync(listener) { - this.eventDispatcher.onDataSync = listener; - } - /** - * Set events handler. - * - * @param listener - Events listener configuration object, which lets specify handlers for multiple - * types of events. - */ - addListener(listener) { - this.eventDispatcher.addListener(listener); - } - /** - * Remove events handler. - * - * @param listener - Event listener configuration, which should be removed from the list of notified - * listeners. **Important:** Should be the same object which has been passed to the {@link addListener}. - */ - removeListener(listener) { - this.eventDispatcher.removeListener(listener); - } - /** - * Remove all events listeners. - */ - removeAllListeners() { - this.eventDispatcher.removeAllListeners(); - } - /** - * Dispatch received a real-time update. - * - * @param cursor - A time cursor for the next portion of events. - * @param event - A real-time event from multiplexed subscription. - * - * @return `true` if receiver has consumed event. - * - * @internal - */ - handleEvent(cursor, event) { - var _a; - if (!this.state.cursor || cursor > this.state.cursor) - this.state.cursor = cursor; - // Check whether this is an old `old` event and it should be ignored or not. - if (this.state.referenceTimetoken && event.data.timetoken < this.state.referenceTimetoken) { - this.state.client.logger.trace(this.subscriptionType, () => ({ - messageType: 'text', - message: `Event timetoken (${event.data.timetoken}) is older than reference timetoken (${this.state.referenceTimetoken}) for ${this.id} subscription object. Ignoring event.`, - })); - return; - } - // Don't pass events which are filtered out by the user-provided function. - if (((_a = this.state.options) === null || _a === void 0 ? void 0 : _a.filter) && !this.state.options.filter(event)) { - this.state.client.logger.trace(this.subscriptionType, `Event filtered out by filter function for ${this.id} subscription object. Ignoring event.`); - return; - } - const clones = Object.values(this.state.clones); - if (clones.length > 0) { - this.state.client.logger.trace(this.subscriptionType, `Notify ${this.id} subscription object clones (count: ${clones.length}) about received event.`); - } - clones.forEach((subscription) => subscription.eventDispatcher.handleEvent(event)); - } - /** - * Graceful object destruction. - * - * This is an instance destructor, which will properly deinitialize it: - * - remove and unset all listeners, - * - try to unsubscribe (if subscribed and there are no more instances interested in the same data stream). - * - * **Important:** {@link SubscriptionBase#dispose dispose} won't have any effect if a subscription object is part of - * set. To gracefully dispose an object, it should be removed from the set using - * {@link SubscriptionSet#removeSubscription removeSubscription} (in this case call of - * {@link SubscriptionBase#dispose dispose} not required. - * - * **Note:** Disposed instance won't call the dispatcher to deliver updates to the listeners. - */ - dispose() { - const keys = Object.keys(this.state.clones); - if (keys.length > 1) { - this.state.client.logger.debug(this.subscriptionType, `Remove subscription object clone on dispose: ${this.id}`); - delete this.state.clones[this.id]; - } - else if (keys.length === 1 && this.state.clones[this.id]) { - this.state.client.logger.debug(this.subscriptionType, `Unsubscribe subscription object on dispose: ${this.id}`); - this.unsubscribe(); - } - } - /** - * Invalidate subscription object. - * - * Clean up resources used by a subscription object. - * - * **Note:** An invalidated instance won't call the dispatcher to deliver updates to the listeners. - * - * @param forDestroy - Whether subscription object invalidated as part of PubNub client destroy process or not. - * - * @internal - */ - invalidate(forDestroy = false) { - this.state._isSubscribed = false; - if (forDestroy) { - delete this.state.clones[this.id]; - if (Object.keys(this.state.clones).length === 0) { - this.state.client.logger.trace(this.subscriptionType, 'Last clone removed. Reset shared subscription state.'); - this.state.subscriptionInput.removeAll(); - this.state.parents = []; - } - } - } - /** - * Start receiving real-time updates. - * - * @param parameters - Additional subscription configuration options which should be used - * for request. - */ - subscribe(parameters) { - if (this.state.isSubscribed) { - this.state.client.logger.trace(this.subscriptionType, 'Already subscribed. Ignoring subscribe request.'); - return; - } - this.state.client.logger.debug(this.subscriptionType, () => { - if (!parameters) - return { messageType: 'text', message: 'Subscribe' }; - return { messageType: 'object', message: parameters, details: 'Subscribe with parameters:' }; - }); - this.state.isSubscribed = true; - this.updateSubscription({ subscribing: true, timetoken: parameters === null || parameters === void 0 ? void 0 : parameters.timetoken }); - } - /** - * Stop real-time events processing. - * - * **Important:** {@link SubscriptionBase#unsubscribe unsubscribe} won't have any effect if a subscription object - * is part of active (subscribed) set. To unsubscribe an object, it should be removed from the set using - * {@link SubscriptionSet#removeSubscription removeSubscription} (in this case call of - * {@link SubscriptionBase#unsubscribe unsubscribe} not required. - * - * **Note:** Unsubscribed instance won't call the dispatcher to deliver updates to the listeners. - */ - unsubscribe() { - // Check whether an instance-level subscription flag not set or parent has active subscription. - if (!this.state._isSubscribed || this.state.isSubscribed) { - // Warn if a user tries to unsubscribe using specific subscription which subscribed as part of a subscription set. - if (!this.state._isSubscribed && this.state.parents.length > 0 && this.state.isSubscribed) { - this.state.client.logger.warn(this.subscriptionType, () => ({ - messageType: 'object', - details: 'Subscription is subscribed as part of a subscription set. Remove from active sets to unsubscribe:', - message: this.state.parents.filter((subscriptionSet) => subscriptionSet.isSubscribed), - })); - return; - } - else if (!this.state._isSubscribed) { - this.state.client.logger.trace(this.subscriptionType, 'Not subscribed. Ignoring unsubscribe request.'); - return; - } - } - this.state.client.logger.debug(this.subscriptionType, 'Unsubscribe'); - this.state.isSubscribed = false; - delete this.state.cursor; - this.updateSubscription({ subscribing: false }); - } - /** - * Update channels and groups used by subscription loop. - * - * @param parameters - Subscription loop update parameters. - * @param parameters.subscribing - Whether subscription updates as part of subscription or unsubscription. - * @param [parameters.timetoken] - Subscription catch-up timetoken. - * @param [parameters.subscriptions] - List of subscriptions which should be used to modify a subscription loop - * object. - * - * @internal - */ - updateSubscription(parameters) { - var _a, _b; - if (parameters === null || parameters === void 0 ? void 0 : parameters.timetoken) { - if (((_a = this.state.cursor) === null || _a === void 0 ? void 0 : _a.timetoken) && ((_b = this.state.cursor) === null || _b === void 0 ? void 0 : _b.timetoken) !== '0') { - if (parameters.timetoken !== '0' && parameters.timetoken > this.state.cursor.timetoken) - this.state.cursor.timetoken = parameters.timetoken; - } - else - this.state.cursor = { timetoken: parameters.timetoken }; - } - const subscriptions = parameters.subscriptions && parameters.subscriptions.length > 0 ? parameters.subscriptions : undefined; - if (parameters.subscribing) { - this.register(Object.assign(Object.assign({}, (parameters.timetoken ? { cursor: this.state.cursor } : {})), (subscriptions ? { subscriptions } : {}))); - } - else - this.unregister(subscriptions); - } - } - - /** - * {@link SubscriptionSet} state object. - * - * State object used across multiple {@link SubscriptionSet} object clones. - * - * @internal - */ - class SubscriptionSetState extends SubscriptionBaseState { - /** - * Create a subscription state object. - * - * @param parameters - State configuration options - * @param parameters.client - PubNub client which will work with a subscription object. - * @param parameters.subscriptions - List of subscriptions managed by set. - * @param [parameters.options] - Subscription behavior options. - */ - constructor(parameters) { - const subscriptionInput = new SubscriptionInput({}); - parameters.subscriptions.forEach((subscription) => subscriptionInput.add(subscription.state.subscriptionInput)); - super(parameters.client, subscriptionInput, parameters.options, parameters.client.subscriptionTimetoken); - this.subscriptions = parameters.subscriptions; - } - /** - * Add a single subscription object to the set. - * - * @param subscription - Another entity's subscription object, which should be added. - */ - addSubscription(subscription) { - if (this.subscriptions.includes(subscription)) - return; - subscription.state.addParentState(this); - this.subscriptions.push(subscription); - // Update subscription input. - this.subscriptionInput.add(subscription.state.subscriptionInput); - } - /** - * Remove a single subscription object from the set. - * - * @param subscription - Another entity's subscription object, which should be removed. - * @param clone - Whether a target subscription is a clone. - */ - removeSubscription(subscription, clone) { - const index = this.subscriptions.indexOf(subscription); - if (index === -1) - return; - this.subscriptions.splice(index, 1); - if (!clone) - subscription.state.removeParentState(this); - // Update subscription input. - this.subscriptionInput.remove(subscription.state.subscriptionInput); - } - /** - * Remove any registered subscription object. - */ - removeAllSubscriptions() { - this.subscriptions.forEach((subscription) => subscription.state.removeParentState(this)); - this.subscriptions.splice(0, this.subscriptions.length); - this.subscriptionInput.removeAll(); - } - } - /** - * Multiple entities subscription set object which can be used to receive and handle real-time - * updates. - * - * Subscription set object represents a collection of per-entity subscription objects and allows - * processing them at once for subscription loop and events handling. - */ - class SubscriptionSet extends SubscriptionBase { - /** - * Create entities' subscription set object. - * - * Subscription set object represents a collection of per-entity subscription objects and allows - * processing them at once for subscription loop and events handling. - * - * @param parameters - Subscription set object configuration. - * - * @returns Ready to use entities' subscription set object. - * - * @internal - */ - constructor(parameters) { - let state; - if ('client' in parameters) { - let subscriptions = []; - if (!parameters.subscriptions && parameters.entities) { - parameters.entities.forEach((entity) => subscriptions.push(entity.subscription(parameters.options))); - } - else if (parameters.subscriptions) - subscriptions = parameters.subscriptions; - state = new SubscriptionSetState({ client: parameters.client, subscriptions, options: parameters.options }); - subscriptions.forEach((subscription) => subscription.state.addParentState(state)); - state.client.logger.debug('SubscriptionSet', () => ({ - messageType: 'object', - details: 'Create subscription set with parameters:', - message: Object.assign({ subscriptions: state.subscriptions }, (parameters.options ? parameters.options : {})), - })); - } - else { - state = parameters.state; - state.client.logger.debug('SubscriptionSet', 'Create subscription set clone'); - } - super(state, 'SubscriptionSet'); - this.state.storeClone(this.id, this); - // Update a parent sets list for original set subscriptions. - state.subscriptions.forEach((subscription) => subscription.addParentSet(this)); - } - /** - * Get a {@link SubscriptionSet} object state. - * - * @returns: {@link SubscriptionSet} object state. - * - * @internal - */ - get state() { - return super.state; - } - /** - * Get a list of entities' subscription objects registered in a subscription set. - * - * @returns Entities' subscription objects list. - */ - get subscriptions() { - return this.state.subscriptions.slice(0); - } - // -------------------------------------------------------- - // -------------------- Event handler --------------------- - // -------------------------------------------------------- - // region Event handler - /** - * Dispatch received a real-time update. - * - * @param cursor - A time cursor for the next portion of events. - * @param event - A real-time event from multiplexed subscription. - * - * @return `true` if receiver has consumed event. - * - * @internal - */ - handleEvent(cursor, event) { - var _a; - // Check whether an event is not designated for this subscription set. - if (!this.state.subscriptionInput.contains((_a = event.data.subscription) !== null && _a !== void 0 ? _a : event.data.channel)) - return; - // Check whether `event` can be processed or not. - if (!this.state._isSubscribed) { - this.state.client.logger.trace(this.subscriptionType, `Subscription set ${this.id} is not subscribed. Ignoring event.`); - return; - } - super.handleEvent(cursor, event); - if (this.state.subscriptions.length > 0) { - this.state.client.logger.trace(this.subscriptionType, `Notify ${this.id} subscription set subscriptions (count: ${this.state.subscriptions.length}) about received event.`); - } - this.state.subscriptions.forEach((subscription) => subscription.handleEvent(cursor, event)); - } - // endregion - /** - User-provided subscription input associated with this {@link SubscriptionSet} object. - * - * @param forUnsubscribe - Whether list subscription input created for unsubscription (means entity should be free). - * - * @returns Subscription input object. - * - * @internal - */ - subscriptionInput(forUnsubscribe = false) { - let subscriptionInput = this.state.subscriptionInput; - this.state.subscriptions.forEach((subscription) => { - if (forUnsubscribe && subscription.state.entity.subscriptionsCount > 0) - subscriptionInput = subscriptionInput.without(subscription.state.subscriptionInput); - }); - return subscriptionInput; - } - /** - * Make a bare copy of the {@link SubscriptionSet} object. - * - * Copy won't have any type-specific listeners or added listener objects but will have the same internal state as - * the source object. - * - * @returns Bare copy of a {@link SubscriptionSet} object. - */ - cloneEmpty() { - return new SubscriptionSet({ state: this.state }); - } - /** - * Graceful {@link SubscriptionSet} destruction. - * - * This is an instance destructor, which will properly deinitialize it: - * - remove and unset all listeners, - * - try to unsubscribe (if subscribed and there are no more instances interested in the same data stream). - * - * **Note:** Disposed instance won't call the dispatcher to deliver updates to the listeners. - */ - dispose() { - const isLastClone = this.state.isLastClone; - this.state.subscriptions.forEach((subscription) => { - subscription.removeParentSet(this); - if (isLastClone) - subscription.state.removeParentState(this.state); - }); - super.dispose(); - } - /** - * Invalidate {@link SubscriptionSet} object. - * - * Clean up resources used by a subscription object. All {@link SubscriptionObject subscription} objects will be - * removed. - * - * **Important:** This method is used only when a global subscription set is used (backward compatibility). - * - * **Note:** An invalidated instance won't call the dispatcher to deliver updates to the listeners. - * - * @param forDestroy - Whether subscription object invalidated as part of PubNub client destroy process or not. - * - * @internal - */ - invalidate(forDestroy = false) { - const subscriptions = forDestroy ? this.state.subscriptions.slice(0) : this.state.subscriptions; - subscriptions.forEach((subscription) => { - if (forDestroy) { - subscription.state.entity.decreaseSubscriptionCount(this.state.id); - subscription.removeParentSet(this); - } - subscription.invalidate(forDestroy); - }); - if (forDestroy) - this.state.removeAllSubscriptions(); - super.invalidate(); - } - /** - * Add an entity's subscription to the subscription set. - * - * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. - * - * @param subscription - Another entity's subscription object, which should be added. - */ - addSubscription(subscription) { - this.addSubscriptions([subscription]); - } - /** - * Add an entity's subscriptions to the subscription set. - * - * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. - * - * @param subscriptions - List of entity's subscription objects, which should be added. - */ - addSubscriptions(subscriptions) { - const inactiveSubscriptions = []; - const activeSubscriptions = []; - this.state.client.logger.debug(this.subscriptionType, () => { - const ignoredSubscriptions = []; - const subscriptionsToAdd = []; - subscriptions.forEach((subscription) => { - if (!this.state.subscriptions.includes(subscription)) - subscriptionsToAdd.push(subscription); - else - ignoredSubscriptions.push(subscription); - }); - return { - messageType: 'object', - details: `Add subscriptions to ${this.id} (subscriptions count: ${this.state.subscriptions.length + subscriptionsToAdd.length}):`, - message: { addedSubscriptions: subscriptionsToAdd, ignoredSubscriptions }, - }; - }); - subscriptions - .filter((subscription) => !this.state.subscriptions.includes(subscription)) - .forEach((subscription) => { - if (subscription.state.isSubscribed) - activeSubscriptions.push(subscription); - else - inactiveSubscriptions.push(subscription); - subscription.addParentSet(this); - this.state.addSubscription(subscription); - }); - // Check whether there are any subscriptions for which the subscription loop should be changed or not. - if ((activeSubscriptions.length === 0 && inactiveSubscriptions.length === 0) || !this.state.isSubscribed) - return; - activeSubscriptions.forEach(({ state }) => state.entity.increaseSubscriptionCount(this.state.id)); - if (inactiveSubscriptions.length > 0) - this.updateSubscription({ subscribing: true, subscriptions: inactiveSubscriptions }); - } - /** - * Remove an entity's subscription object from the set. - * - * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. - * - * @param subscription - Another entity's subscription object, which should be removed. - */ - removeSubscription(subscription) { - this.removeSubscriptions([subscription]); - } - /** - * Remove an entity's subscription objects from the set. - * - * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. - * - * @param subscriptions - List entity's subscription objects, which should be removed. - */ - removeSubscriptions(subscriptions) { - const activeSubscriptions = []; - this.state.client.logger.debug(this.subscriptionType, () => { - const ignoredSubscriptions = []; - const subscriptionsToRemove = []; - subscriptions.forEach((subscription) => { - if (this.state.subscriptions.includes(subscription)) - subscriptionsToRemove.push(subscription); - else - ignoredSubscriptions.push(subscription); - }); - return { - messageType: 'object', - details: `Remove subscriptions from ${this.id} (subscriptions count: ${this.state.subscriptions.length}):`, - message: { removedSubscriptions: subscriptionsToRemove, ignoredSubscriptions }, - }; - }); - subscriptions - .filter((subscription) => this.state.subscriptions.includes(subscription)) - .forEach((subscription) => { - if (subscription.state.isSubscribed) - activeSubscriptions.push(subscription); - subscription.removeParentSet(this); - this.state.removeSubscription(subscription, subscription.parentSetsCount > 1); - }); - // Check whether there are any subscriptions for which the subscription loop should be changed or not. - if (activeSubscriptions.length === 0 || !this.state.isSubscribed) - return; - this.updateSubscription({ subscribing: false, subscriptions: activeSubscriptions }); - } - /** - * Merge with another {@link SubscriptionSet} object. - * - * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. - * - * @param subscriptionSet - Other entities' subscription set, which should be joined. - */ - addSubscriptionSet(subscriptionSet) { - this.addSubscriptions(subscriptionSet.subscriptions); - } - /** - * Subtract another {@link SubscriptionSet} object. - * - * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. - * - * @param subscriptionSet - Other entities' subscription set, which should be subtracted. - */ - removeSubscriptionSet(subscriptionSet) { - this.removeSubscriptions(subscriptionSet.subscriptions); - } - /** - * Register {@link SubscriptionSet} object for real-time events' retrieval. - * - * @param parameters - Object registration parameters. - * @param [parameters.cursor] - Subscription real-time events catch-up cursor. - * @param [parameters.subscriptions] - List of subscription objects which should be registered (in case of partial - * modification). - * - * @internal - */ - register(parameters) { - var _a; - const subscriptions = ((_a = parameters.subscriptions) !== null && _a !== void 0 ? _a : this.state.subscriptions); - subscriptions.forEach(({ state }) => state.entity.increaseSubscriptionCount(this.state.id)); - this.state.client.logger.trace(this.subscriptionType, () => ({ - messageType: 'text', - message: `Register subscription for real-time events: ${this}`, - })); - this.state.client.registerEventHandleCapable(this, parameters.cursor, subscriptions); - } - /** - * Unregister {@link SubscriptionSet} object from real-time events' retrieval. - * - * @param [subscriptions] - List of subscription objects which should be unregistered (in case of partial - * modification). - * - * @internal - */ - unregister(subscriptions) { - const activeSubscriptions = (subscriptions !== null && subscriptions !== void 0 ? subscriptions : this.state.subscriptions); - activeSubscriptions.forEach(({ state }) => state.entity.decreaseSubscriptionCount(this.state.id)); - this.state.client.logger.trace(this.subscriptionType, () => { - if (!subscriptions) { - return { - messageType: 'text', - message: `Unregister subscription from real-time events: ${this}`, - }; - } - else { - return { - messageType: 'object', - message: { - subscription: this, - subscriptions, - }, - details: 'Unregister subscriptions of subscription set from real-time events:', - }; - } - }); - this.state.client.unregisterEventHandleCapable(this, activeSubscriptions); - } - /** - * Stringify subscription object. - * - * @returns Serialized subscription object. - */ - toString() { - const state = this.state; - return `${this.subscriptionType} { id: ${this.id}, stateId: ${state.id}, clonesCount: ${Object.keys(this.state.clones).length}, isSubscribed: ${state.isSubscribed}, subscriptions: [${state.subscriptions - .map((sub) => sub.toString()) - .join(', ')}] }`; - } - } - - /** - * {@link Subscription} state object. - * - * State object used across multiple {@link Subscription} object clones. - * - * @internal - */ - class SubscriptionState extends SubscriptionBaseState { - /** - * Create a subscription state object. - * - * @param parameters - State configuration options - * @param parameters.client - PubNub client which will work with a subscription object. - * @param parameters.entity - Entity for which a subscription object has been created. - * @param [parameters.options] - Subscription behavior options. - */ - constructor(parameters) { - var _a, _b; - const names = parameters.entity.subscriptionNames((_b = (_a = parameters.options) === null || _a === void 0 ? void 0 : _a.receivePresenceEvents) !== null && _b !== void 0 ? _b : false); - const subscriptionInput = new SubscriptionInput({ - [parameters.entity.subscriptionType == SubscriptionType.Channel ? 'channels' : 'channelGroups']: names, - }); - super(parameters.client, subscriptionInput, parameters.options, parameters.client.subscriptionTimetoken); - this.entity = parameters.entity; - } - } - /** - * Single-entity subscription object which can be used to receive and handle real-time updates. - */ - class Subscription extends SubscriptionBase { - /** - * Create a subscribing capable object for entity. - * - * @param parameters - Subscription object configuration. - * - * @internal - */ - constructor(parameters) { - if ('client' in parameters) { - parameters.client.logger.debug('Subscription', () => ({ - messageType: 'object', - details: 'Create subscription with parameters:', - message: Object.assign({ entity: parameters.entity }, (parameters.options ? parameters.options : {})), - })); - } - else - parameters.state.client.logger.debug('Subscription', 'Create subscription clone'); - super('state' in parameters ? parameters.state : new SubscriptionState(parameters)); - /** - * List of subscription {@link SubscriptionSet sets} which contains {@link Subscription subscription}. - * - * List if used to track usage of a specific {@link Subscription subscription} in other subscription - * {@link SubscriptionSet sets}. - * - * **Important:** Tracking is required to prevent cloned instance dispose if there are sets that still use it. - * - * @internal - */ - this.parents = []; - /** - * List of fingerprints from updates which has been handled already. - * - * **Important:** Tracking is required to avoid repetitive call of the subscription object's listener when the object - * is part of multiple subscribed sets. Handler will be called once, and then the fingerprint will be stored in this - * list to avoid another listener call for it. - * - * @internal - */ - this.handledUpdates = []; - this.state.storeClone(this.id, this); - } - /** - * Get a {@link Subscription} object state. - * - * @returns: {@link Subscription} object state. - * - * @internal - */ - get state() { - return super.state; - } - /** - * Get number of {@link SubscriptionSet} which use this subscription object. - * - * @returns Number of {@link SubscriptionSet} which use this subscription object. - * - * @internal - */ - get parentSetsCount() { - return this.parents.length; - } - // -------------------------------------------------------- - // -------------------- Event handler --------------------- - // -------------------------------------------------------- - // region Event handler - /** - * Dispatch received a real-time update. - * - * @param cursor - A time cursor for the next portion of events. - * @param event - A real-time event from multiplexed subscription. - * - * @return `true` if receiver has consumed event. - * - * @internal - */ - handleEvent(cursor, event) { - var _a, _b; - if (!this.state.isSubscribed || - !this.state.subscriptionInput.contains((_a = event.data.subscription) !== null && _a !== void 0 ? _a : event.data.channel)) - return; - if (this.parentSetsCount > 0) { - // Creating from whole payload (not only for published messages). - const fingerprint = messageFingerprint(event.data); - if (this.handledUpdates.includes(fingerprint)) { - this.state.client.logger.trace(this.subscriptionType, `Event (${fingerprint}) already handled by ${this.id}. Ignoring.`); - return; - } - // Update a list of tracked messages and shrink it if too big. - this.handledUpdates.push(fingerprint); - if (this.handledUpdates.length > 10) - this.handledUpdates.shift(); - } - // Check whether an event is not designated for this subscription set. - if (!this.state.subscriptionInput.contains((_b = event.data.subscription) !== null && _b !== void 0 ? _b : event.data.channel)) - return; - super.handleEvent(cursor, event); - } - // endregion - /** - * User-provided subscription input associated with this {@link Subscription} object. - * - * @param forUnsubscribe - Whether list subscription input created for unsubscription (means entity should be free). - * - * @returns Subscription input object. - * - * @internal - */ - subscriptionInput(forUnsubscribe = false) { - if (forUnsubscribe && this.state.entity.subscriptionsCount > 0) - return new SubscriptionInput({}); - return this.state.subscriptionInput; - } - /** - * Make a bare copy of the {@link Subscription} object. - * - * Copy won't have any type-specific listeners or added listener objects but will have the same internal state as - * the source object. - * - * @returns Bare copy of a {@link Subscription} object. - */ - cloneEmpty() { - return new Subscription({ state: this.state }); - } - /** - * Graceful {@link Subscription} object destruction. - * - * This is an instance destructor, which will properly deinitialize it: - * - remove and unset all listeners, - * - try to unsubscribe (if subscribed and there are no more instances interested in the same data stream). - * - * **Important:** {@link Subscription#dispose dispose} won't have any effect if a subscription object is part of - * {@link SubscriptionSet set}. To gracefully dispose an object, it should be removed from the set using - * {@link SubscriptionSet#removeSubscription removeSubscription} (in this case call of - * {@link Subscription#dispose dispose} not required). - * - * **Note:** Disposed instance won't call the dispatcher to deliver updates to the listeners. - */ - dispose() { - if (this.parentSetsCount > 0) { - this.state.client.logger.debug(this.subscriptionType, () => ({ - messageType: 'text', - message: `'${this.state.entity.subscriptionNames()}' subscription still in use. Ignore dispose request.`, - })); - return; - } - this.handledUpdates.splice(0, this.handledUpdates.length); - super.dispose(); - } - /** - * Invalidate subscription object. - * - * Clean up resources used by a subscription object. - * - * **Note:** An invalidated instance won't call the dispatcher to deliver updates to the listeners. - * - * @param forDestroy - Whether subscription object invalidated as part of PubNub client destroy process or not. - * - * @internal - */ - invalidate(forDestroy = false) { - if (forDestroy) - this.state.entity.decreaseSubscriptionCount(this.state.id); - this.handledUpdates.splice(0, this.handledUpdates.length); - super.invalidate(forDestroy); - } - /** - * Add another {@link SubscriptionSet} into which subscription has been added. - * - * @param parent - {@link SubscriptionSet} which has been modified. - * - * @internal - */ - addParentSet(parent) { - if (!this.parents.includes(parent)) { - this.parents.push(parent); - this.state.client.logger.trace(this.subscriptionType, `Add parent subscription set for ${this.id}: ${parent.id}. Parent subscription set count: ${this.parentSetsCount}`); - } - } - /** - * Remove {@link SubscriptionSet} upon subscription removal from it. - * - * @param parent - {@link SubscriptionSet} which has been modified. - * - * @internal - */ - removeParentSet(parent) { - const parentIndex = this.parents.indexOf(parent); - if (parentIndex !== -1) { - this.parents.splice(parentIndex, 1); - this.state.client.logger.trace(this.subscriptionType, `Remove parent subscription set from ${this.id}: ${parent.id}. Parent subscription set count: ${this.parentSetsCount}`); - } - if (this.parentSetsCount === 0) - this.handledUpdates.splice(0, this.handledUpdates.length); - } - /** - * Merge entities' subscription objects into {@link SubscriptionSet}. - * - * @param subscription - Another entity's subscription object to be merged with receiver. - * - * @return {@link SubscriptionSet} which contains both receiver and other entities' subscription objects. - */ - addSubscription(subscription) { - this.state.client.logger.debug(this.subscriptionType, () => ({ - messageType: 'text', - message: `Create set with subscription: ${subscription}`, - })); - const subscriptionSet = new SubscriptionSet({ - client: this.state.client, - subscriptions: [this, subscription], - options: this.state.options, - }); - // Check whether a source subscription is already subscribed or not. - if (!this.state.isSubscribed && !subscription.state.isSubscribed) - return subscriptionSet; - this.state.client.logger.trace(this.subscriptionType, 'Subscribe resulting set because the receiver is already subscribed.'); - // Subscribing resulting subscription set because source subscription was subscribed. - subscriptionSet.subscribe(); - return subscriptionSet; - } - /** - * Register {@link Subscription} object for real-time events' retrieval. - * - * **Note:** Superclass calls this method only in response to a {@link Subscription.subscribe subscribe} method call. - * - * @param parameters - Object registration parameters. - * @param [parameters.cursor] - Subscription real-time events catch-up cursor. - * @param [parameters.subscriptions] - List of subscription objects which should be registered (in case of partial - * modification). - * - * @internal - */ - register(parameters) { - this.state.entity.increaseSubscriptionCount(this.state.id); - this.state.client.logger.trace(this.subscriptionType, () => ({ - messageType: 'text', - message: `Register subscription for real-time events: ${this}`, - })); - this.state.client.registerEventHandleCapable(this, parameters.cursor); - } - /** - * Unregister {@link Subscription} object from real-time events' retrieval. - * - * **Note:** Superclass calls this method only in response to a {@link Subscription.unsubscribe unsubscribe} method - * call. - * - * @param [_subscriptions] - List of subscription objects which should be unregistered (in case of partial - * modification). - * - * @internal - */ - unregister(_subscriptions) { - this.state.entity.decreaseSubscriptionCount(this.state.id); - this.state.client.logger.trace(this.subscriptionType, () => ({ - messageType: 'text', - message: `Unregister subscription from real-time events: ${this}`, - })); - this.handledUpdates.splice(0, this.handledUpdates.length); - this.state.client.unregisterEventHandleCapable(this); - } - /** - * Stringify subscription object. - * - * @returns Serialized subscription object. - */ - toString() { - const state = this.state; - return `${this.subscriptionType} { id: ${this.id}, stateId: ${state.id}, entity: ${state.entity - .subscriptionNames(false) - .pop()}, clonesCount: ${Object.keys(state.clones).length}, isSubscribed: ${state.isSubscribed}, parentSetsCount: ${this.parentSetsCount}, cursor: ${state.cursor ? state.cursor.timetoken : 'not set'}, referenceTimetoken: ${state.referenceTimetoken ? state.referenceTimetoken : 'not set'} }`; - } - } - - /** - * Get Presence State REST API module. - * - * @internal - */ - // endregion - /** - * Get `uuid` presence state request. - * - * @internal - */ - class GetPresenceStateRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b; - var _c, _d; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = (_c = this.parameters).channels) !== null && _a !== void 0 ? _a : (_c.channels = []); - (_b = (_d = this.parameters).channelGroups) !== null && _b !== void 0 ? _b : (_d.channelGroups = []); - } - operation() { - return RequestOperation$1.PNGetStateOperation; - } - validate() { - const { keySet: { subscribeKey }, channels, channelGroups, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - const serviceResponse = this.deserializeResponse(response); - const { channels = [], channelGroups = [] } = this.parameters; - const state = { channels: {} }; - if (channels.length === 1 && channelGroups.length === 0) - state.channels[channels[0]] = serviceResponse.payload; - else - state.channels = serviceResponse.payload; - return state; - }); - } - get path() { - const { keySet: { subscribeKey }, uuid, channels, } = this.parameters; - return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}/uuid/${encodeString(uuid !== null && uuid !== void 0 ? uuid : '')}`; - } - get queryParameters() { - const { channelGroups } = this.parameters; - if (!channelGroups || channelGroups.length === 0) - return {}; - return { 'channel-group': channelGroups.join(',') }; - } - } - - /** - * Set Presence State REST API module. - * - * @internal - */ - // endregion - /** - * Set `uuid` presence state request. - * - * @internal - */ - class SetPresenceStateRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSetStateOperation; - } - validate() { - const { keySet: { subscribeKey }, state, channels = [], channelGroups = [], } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (state === undefined) - return 'Missing State'; - if ((channels === null || channels === void 0 ? void 0 : channels.length) === 0 && (channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.length) === 0) - return 'Please provide a list of channels and/or channel-groups'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { state: this.deserializeResponse(response).payload }; - }); - } - get path() { - const { keySet: { subscribeKey }, uuid, channels, } = this.parameters; - return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}/uuid/${encodeString(uuid)}/data`; - } - get queryParameters() { - const { channelGroups, state } = this.parameters; - const query = { state: JSON.stringify(state) }; - if (channelGroups && channelGroups.length !== 0) - query['channel-group'] = channelGroups.join(','); - return query; - } - } - - /** - * Announce heartbeat REST API module. - * - * @internal - */ - // endregion - /** - * Announce `uuid` presence request. - * - * @internal - */ - class HeartbeatRequest extends AbstractRequest { - constructor(parameters) { - super({ cancellable: true }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNHeartbeatOperation; - } - validate() { - const { keySet: { subscribeKey }, channels = [], channelGroups = [], } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (channels.length === 0 && channelGroups.length === 0) - return 'Please provide a list of channels and/or channel-groups'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - get path() { - const { keySet: { subscribeKey }, channels, } = this.parameters; - return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}/heartbeat`; - } - get queryParameters() { - const { channelGroups, state, heartbeat } = this.parameters; - const query = { heartbeat: `${heartbeat}` }; - if (channelGroups && channelGroups.length !== 0) - query['channel-group'] = channelGroups.join(','); - if (state !== undefined) - query.state = JSON.stringify(state); - return query; - } - } - - /** - * Announce leave REST API module. - * - * @internal - */ - // endregion - /** - * Announce user leave request. - * - * @internal - */ - class PresenceLeaveRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - if (this.parameters.channelGroups) - this.parameters.channelGroups = Array.from(new Set(this.parameters.channelGroups)); - if (this.parameters.channels) - this.parameters.channels = Array.from(new Set(this.parameters.channels)); - } - operation() { - return RequestOperation$1.PNUnsubscribeOperation; - } - validate() { - const { keySet: { subscribeKey }, channels = [], channelGroups = [], } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (channels.length === 0 && channelGroups.length === 0) - return 'At least one `channel` or `channel group` should be provided.'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - get path() { - var _a; - const { keySet: { subscribeKey }, channels, } = this.parameters; - return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames((_a = channels === null || channels === void 0 ? void 0 : channels.sort()) !== null && _a !== void 0 ? _a : [], ',')}/leave`; - } - get queryParameters() { - const { channelGroups } = this.parameters; - if (!channelGroups || channelGroups.length === 0) - return {}; - return { 'channel-group': channelGroups.sort().join(',') }; - } - } - - /** - * `uuid` presence REST API module. - * - * @internal - */ - // endregion - /** - * Get `uuid` presence request. - * - * @internal - */ - class WhereNowRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNWhereNowOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - const serviceResponse = this.deserializeResponse(response); - if (!serviceResponse.payload) - return { channels: [] }; - return { channels: serviceResponse.payload.channels }; - }); - } - get path() { - const { keySet: { subscribeKey }, uuid, } = this.parameters; - return `/v2/presence/sub-key/${subscribeKey}/uuid/${encodeString(uuid)}`; - } - } - - /** - * Channels / channel groups presence REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `uuid` should be included in response or not. - */ - const INCLUDE_UUID$1 = true; - /** - * Whether state associated with `uuid` should be included in response or not. - */ - const INCLUDE_STATE = false; - /** - * Maximum number of participants which can be returned with single response. - */ - const MAXIMUM_COUNT = 1000; - // endregion - /** - * Channel presence request. - * - * @internal - */ - class HereNowRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d; - var _e, _f, _g, _h; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = (_e = this.parameters).queryParameters) !== null && _a !== void 0 ? _a : (_e.queryParameters = {}); - (_b = (_f = this.parameters).includeUUIDs) !== null && _b !== void 0 ? _b : (_f.includeUUIDs = INCLUDE_UUID$1); - (_c = (_g = this.parameters).includeState) !== null && _c !== void 0 ? _c : (_g.includeState = INCLUDE_STATE); - (_d = (_h = this.parameters).limit) !== null && _d !== void 0 ? _d : (_h.limit = MAXIMUM_COUNT); - } - operation() { - const { channels = [], channelGroups = [] } = this.parameters; - return channels.length === 0 && channelGroups.length === 0 - ? RequestOperation$1.PNGlobalHereNowOperation - : RequestOperation$1.PNHereNowOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b; - const serviceResponse = this.deserializeResponse(response); - // Extract general presence information. - const totalChannels = 'occupancy' in serviceResponse ? 1 : serviceResponse.payload.total_channels; - const totalOccupancy = 'occupancy' in serviceResponse ? serviceResponse.occupancy : serviceResponse.payload.total_occupancy; - const channelsPresence = {}; - let channels = {}; - const limit = this.parameters.limit; - let occupancyMatchLimit = false; - // Remap single channel presence to multiple channels presence response. - if ('occupancy' in serviceResponse) { - const channel = this.parameters.channels[0]; - channels[channel] = { uuids: (_a = serviceResponse.uuids) !== null && _a !== void 0 ? _a : [], occupancy: totalOccupancy }; - } - else - channels = (_b = serviceResponse.payload.channels) !== null && _b !== void 0 ? _b : {}; - Object.keys(channels).forEach((channel) => { - const channelEntry = channels[channel]; - channelsPresence[channel] = { - occupants: this.parameters.includeUUIDs - ? channelEntry.uuids.map((uuid) => { - if (typeof uuid === 'string') - return { uuid, state: null }; - return uuid; - }) - : [], - name: channel, - occupancy: channelEntry.occupancy, - }; - if (!occupancyMatchLimit && channelEntry.occupancy === limit) - occupancyMatchLimit = true; - }); - return { - totalChannels, - totalOccupancy, - channels: channelsPresence, - }; - }); - } - get path() { - const { keySet: { subscribeKey }, channels, channelGroups, } = this.parameters; - let path = `/v2/presence/sub-key/${subscribeKey}`; - if ((channels && channels.length > 0) || (channelGroups && channelGroups.length > 0)) - path += `/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}`; - return path; - } - get queryParameters() { - const { channelGroups, includeUUIDs, includeState, limit, offset, queryParameters } = this.parameters; - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (this.operation() === RequestOperation$1.PNHereNowOperation ? { limit } : {})), (this.operation() === RequestOperation$1.PNHereNowOperation && (offset !== null && offset !== void 0 ? offset : 0 > 0) ? { offset } : {})), (!includeUUIDs ? { disable_uuids: '1' } : {})), ((includeState !== null && includeState !== void 0 ? includeState : false) ? { state: '1' } : {})), (channelGroups && channelGroups.length > 0 ? { 'channel-group': channelGroups.join(',') } : {})), queryParameters); - } - } - - /** - * Delete messages REST API module. - * - * @internal - */ - // endregion - /** - * Delete messages from channel history. - * - * @internal - */ - class DeleteMessageRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNDeleteMessagesOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - if (!this.parameters.channel) - return 'Missing channel'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v3/history/sub-key/${subscribeKey}/channel/${encodeString(channel)}`; - } - get queryParameters() { - const { start, end } = this.parameters; - return Object.assign(Object.assign({}, (start ? { start } : {})), (end ? { end } : {})); - } - } - - /** - * Messages count REST API module. - * - * @internal - */ - // endregion - /** - * Count messages request. - * - * @internal - */ - class MessageCountRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNMessageCounts; - } - validate() { - const { keySet: { subscribeKey }, channels, timetoken, channelTimetokens, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channels) - return 'Missing channels'; - if (timetoken && channelTimetokens) - return '`timetoken` and `channelTimetokens` are incompatible together'; - if (!timetoken && !channelTimetokens) - return '`timetoken` or `channelTimetokens` need to be set'; - if (channelTimetokens && channelTimetokens.length > 1 && channelTimetokens.length !== channels.length) - return 'Length of `channelTimetokens` and `channels` do not match'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { channels: this.deserializeResponse(response).channels }; - }); - } - get path() { - return `/v3/history/sub-key/${this.parameters.keySet.subscribeKey}/message-counts/${encodeNames(this.parameters.channels)}`; - } - get queryParameters() { - let { channelTimetokens } = this.parameters; - if (this.parameters.timetoken) - channelTimetokens = [this.parameters.timetoken]; - return Object.assign(Object.assign({}, (channelTimetokens.length === 1 ? { timetoken: channelTimetokens[0] } : {})), (channelTimetokens.length > 1 ? { channelsTimetoken: channelTimetokens.join(',') } : {})); - } - } - - /** - * Get history REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ---------------------- Defaults ------------------------ - // -------------------------------------------------------- - // region Defaults - /** - * Whether verbose logging enabled or not. - */ - const LOG_VERBOSITY$1 = false; - /** - * Whether associated message metadata should be returned or not. - */ - const INCLUDE_METADATA = false; - /** - * Whether timetokens should be returned as strings by default or not. - */ - const STRINGIFY_TIMETOKENS$1 = false; - /** - * Default and maximum number of messages which should be returned. - */ - const MESSAGES_COUNT = 100; - // endregion - /** - * Get single channel messages request. - * - * @internal - */ - class GetHistoryRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c; - super(); - this.parameters = parameters; - // Apply defaults. - if (parameters.count) - parameters.count = Math.min(parameters.count, MESSAGES_COUNT); - else - parameters.count = MESSAGES_COUNT; - (_a = parameters.stringifiedTimeToken) !== null && _a !== void 0 ? _a : (parameters.stringifiedTimeToken = STRINGIFY_TIMETOKENS$1); - (_b = parameters.includeMeta) !== null && _b !== void 0 ? _b : (parameters.includeMeta = INCLUDE_METADATA); - (_c = parameters.logVerbosity) !== null && _c !== void 0 ? _c : (parameters.logVerbosity = LOG_VERBOSITY$1); - } - operation() { - return RequestOperation$1.PNHistoryOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - if (!this.parameters.channel) - return 'Missing channel'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - const serviceResponse = this.deserializeResponse(response); - const messages = serviceResponse[0]; - const startTimeToken = serviceResponse[1]; - const endTimeToken = serviceResponse[2]; - // Handle malformed get history response. - if (!Array.isArray(messages)) - return { messages: [], startTimeToken, endTimeToken }; - return { - messages: messages.map((payload) => { - const processedPayload = this.processPayload(payload.message); - const item = { - entry: processedPayload.payload, - timetoken: payload.timetoken, - }; - if (processedPayload.error) - item.error = processedPayload.error; - if (payload.meta) - item.meta = payload.meta; - return item; - }), - startTimeToken, - endTimeToken, - }; - }); - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v2/history/sub-key/${subscribeKey}/channel/${encodeString(channel)}`; - } - get queryParameters() { - const { start, end, reverse, count, stringifiedTimeToken, includeMeta } = this.parameters; - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: count, include_token: 'true' }, (start ? { start } : {})), (end ? { end } : {})), (stringifiedTimeToken ? { string_message_token: 'true' } : {})), (reverse !== undefined && reverse !== null ? { reverse: reverse.toString() } : {})), (includeMeta ? { include_meta: 'true' } : {})); - } - processPayload(payload) { - const { crypto, logVerbosity } = this.parameters; - if (!crypto || typeof payload !== 'string') - return { payload }; - let decryptedPayload; - let error; - try { - const decryptedData = crypto.decrypt(payload); - decryptedPayload = - decryptedData instanceof ArrayBuffer - ? JSON.parse(GetHistoryRequest.decoder.decode(decryptedData)) - : decryptedData; - } - catch (err) { - if (logVerbosity) - console.log(`decryption error`, err.message); - decryptedPayload = payload; - error = `Error while decrypting message content: ${err.message}`; - } - return { - payload: decryptedPayload, - error, - }; - } - } - - // endregion - // -------------------------------------------------------- - // -------------------- Fetch Messages -------------------- - // -------------------------------------------------------- - // region Fetch Messages - /** - * PubNub-defined message type. - * - * Types of messages which can be retrieved with fetch messages REST API. - */ - var PubNubMessageType; - (function (PubNubMessageType) { - /** - * Regular message. - */ - PubNubMessageType[PubNubMessageType["Message"] = -1] = "Message"; - /** - * File message. - */ - PubNubMessageType[PubNubMessageType["Files"] = 4] = "Files"; - })(PubNubMessageType || (PubNubMessageType = {})); - // endregion - - /** - * Fetch messages REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ---------------------- Defaults ------------------------ - // -------------------------------------------------------- - // region Defaults - /** - * Whether verbose logging enabled or not. - */ - const LOG_VERBOSITY = false; - /** - * Whether message type should be returned or not. - */ - const INCLUDE_MESSAGE_TYPE = true; - /** - * Whether timetokens should be returned as strings by default or not. - */ - const STRINGIFY_TIMETOKENS = false; - /** - * Whether message publisher `uuid` should be returned or not. - */ - const INCLUDE_UUID = true; - /** - * Default number of messages which can be returned for single channel, and it is maximum as well. - */ - const SINGLE_CHANNEL_MESSAGES_COUNT = 100; - /** - * Default number of messages which can be returned for multiple channels or when fetched - * message actions. - */ - const MULTIPLE_CHANNELS_MESSAGES_COUNT = 25; - // endregion - /** - * Fetch messages from channels request. - * - * @internal - */ - class FetchMessagesRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d, _e; - super(); - this.parameters = parameters; - // Apply defaults. - const includeMessageActions = (_a = parameters.includeMessageActions) !== null && _a !== void 0 ? _a : false; - const defaultCount = parameters.channels.length > 1 || includeMessageActions - ? MULTIPLE_CHANNELS_MESSAGES_COUNT - : SINGLE_CHANNEL_MESSAGES_COUNT; - if (!parameters.count) - parameters.count = defaultCount; - else - parameters.count = Math.min(parameters.count, defaultCount); - if (parameters.includeUuid) - parameters.includeUUID = parameters.includeUuid; - else - (_b = parameters.includeUUID) !== null && _b !== void 0 ? _b : (parameters.includeUUID = INCLUDE_UUID); - (_c = parameters.stringifiedTimeToken) !== null && _c !== void 0 ? _c : (parameters.stringifiedTimeToken = STRINGIFY_TIMETOKENS); - (_d = parameters.includeMessageType) !== null && _d !== void 0 ? _d : (parameters.includeMessageType = INCLUDE_MESSAGE_TYPE); - (_e = parameters.logVerbosity) !== null && _e !== void 0 ? _e : (parameters.logVerbosity = LOG_VERBOSITY); - } - operation() { - return RequestOperation$1.PNFetchMessagesOperation; - } - validate() { - const { keySet: { subscribeKey }, channels, includeMessageActions, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channels) - return 'Missing channels'; - if (includeMessageActions !== undefined && includeMessageActions && channels.length > 1) - return ('History can return actions data for a single channel only. Either pass a single channel ' + - 'or disable the includeMessageActions flag.'); - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - const serviceResponse = this.deserializeResponse(response); - const responseChannels = (_a = serviceResponse.channels) !== null && _a !== void 0 ? _a : {}; - const channels = {}; - Object.keys(responseChannels).forEach((channel) => { - // Map service response to expected data object type structure. - channels[channel] = responseChannels[channel].map((payload) => { - // `null` message type means regular message. - if (payload.message_type === null) - payload.message_type = PubNubMessageType.Message; - const processedPayload = this.processPayload(channel, payload); - const item = Object.assign(Object.assign({ channel, timetoken: payload.timetoken, message: processedPayload.payload, messageType: payload.message_type }, (payload.custom_message_type ? { customMessageType: payload.custom_message_type } : {})), { uuid: payload.uuid }); - if (payload.actions) { - const itemWithActions = item; - itemWithActions.actions = payload.actions; - // Backward compatibility for existing users. - // TODO: Remove in next release. - itemWithActions.data = payload.actions; - } - if (payload.meta) - item.meta = payload.meta; - if (processedPayload.error) - item.error = processedPayload.error; - return item; - }); - }); - if (serviceResponse.more) - return { channels, more: serviceResponse.more }; - return { channels }; - }); - } - get path() { - const { keySet: { subscribeKey }, channels, includeMessageActions, } = this.parameters; - const endpoint = !includeMessageActions ? 'history' : 'history-with-actions'; - return `/v3/${endpoint}/sub-key/${subscribeKey}/channel/${encodeNames(channels)}`; - } - get queryParameters() { - const { start, end, count, includeCustomMessageType, includeMessageType, includeMeta, includeUUID, stringifiedTimeToken, } = this.parameters; - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ max: count }, (start ? { start } : {})), (end ? { end } : {})), (stringifiedTimeToken ? { string_message_token: 'true' } : {})), (includeMeta !== undefined && includeMeta ? { include_meta: 'true' } : {})), (includeUUID ? { include_uuid: 'true' } : {})), (includeCustomMessageType !== undefined && includeCustomMessageType !== null - ? { include_custom_message_type: includeCustomMessageType ? 'true' : 'false' } - : {})), (includeMessageType ? { include_message_type: 'true' } : {})); - } - /** - * Parse single channel data entry. - * - * @param channel - Channel for which {@link payload} should be processed. - * @param payload - Source payload which should be processed and parsed to expected type. - * - * @returns - */ - processPayload(channel, payload) { - const { crypto, logVerbosity } = this.parameters; - if (!crypto || typeof payload.message !== 'string') - return { payload: payload.message }; - let decryptedPayload; - let error; - try { - const decryptedData = crypto.decrypt(payload.message); - decryptedPayload = - decryptedData instanceof ArrayBuffer - ? JSON.parse(FetchMessagesRequest.decoder.decode(decryptedData)) - : decryptedData; - } - catch (err) { - if (logVerbosity) - console.log(`decryption error`, err.message); - decryptedPayload = payload.message; - error = `Error while decrypting message content: ${err.message}`; - } - if (!error && - decryptedPayload && - payload.message_type == PubNubMessageType.Files && - typeof decryptedPayload === 'object' && - this.isFileMessage(decryptedPayload)) { - const fileMessage = decryptedPayload; - return { - payload: { - message: fileMessage.message, - file: Object.assign(Object.assign({}, fileMessage.file), { url: this.parameters.getFileUrl({ channel, id: fileMessage.file.id, name: fileMessage.file.name }) }), - }, - error, - }; - } - return { payload: decryptedPayload, error }; - } - /** - * Check whether `payload` potentially represents file message. - * - * @param payload - Fetched message payload. - * - * @returns `true` if payload can be {@link History#FileMessage|FileMessage}. - */ - isFileMessage(payload) { - return payload.file !== undefined; - } - } - - /** - * Get Message Actions REST API module. - * - * @internal - */ - // endregion - /** - * Fetch channel message actions request. - * - * @internal - */ - class GetMessageActionsRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetMessageActionsOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - if (!this.parameters.channel) - return 'Missing message channel'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - const serviceResponse = this.deserializeResponse(response); - let start = null; - let end = null; - if (serviceResponse.data.length > 0) { - start = serviceResponse.data[0].actionTimetoken; - end = serviceResponse.data[serviceResponse.data.length - 1].actionTimetoken; - } - return { - data: serviceResponse.data, - more: serviceResponse.more, - start, - end, - }; - }); - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v1/message-actions/${subscribeKey}/channel/${encodeString(channel)}`; - } - get queryParameters() { - const { limit, start, end } = this.parameters; - return Object.assign(Object.assign(Object.assign({}, (start ? { start } : {})), (end ? { end } : {})), (limit ? { limit } : {})); - } - } - - /** - * Add Message Action REST API module. - * - * @internal - */ - // endregion - /** - * Add Message Reaction request. - * - * @internal - */ - class AddMessageActionRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNAddMessageActionOperation; - } - validate() { - const { keySet: { subscribeKey }, action, channel, messageTimetoken, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channel) - return 'Missing message channel'; - if (!messageTimetoken) - return 'Missing message timetoken'; - if (!action) - return 'Missing Action'; - if (!action.value) - return 'Missing Action.value'; - if (!action.type) - return 'Missing Action.type'; - if (action.type.length > 15) - return 'Action.type value exceed maximum length of 15'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then(({ data }) => ({ data })); - }); - } - get path() { - const { keySet: { subscribeKey }, channel, messageTimetoken, } = this.parameters; - return `/v1/message-actions/${subscribeKey}/channel/${encodeString(channel)}/message/${messageTimetoken}`; - } - get headers() { - var _a; - return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); - } - get body() { - return JSON.stringify(this.parameters.action); - } - } - - /** - * Remove Message Action REST API module. - * - * @internal - */ - // endregion - /** - * Remove specific message action request. - * - * @internal - */ - class RemoveMessageAction extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveMessageActionOperation; - } - validate() { - const { keySet: { subscribeKey }, channel, messageTimetoken, actionTimetoken, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channel) - return 'Missing message action channel'; - if (!messageTimetoken) - return 'Missing message timetoken'; - if (!actionTimetoken) - return 'Missing action timetoken'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then(({ data }) => ({ data })); - }); - } - get path() { - const { keySet: { subscribeKey }, channel, actionTimetoken, messageTimetoken, } = this.parameters; - return `/v1/message-actions/${subscribeKey}/channel/${encodeString(channel)}/message/${messageTimetoken}/action/${actionTimetoken}`; - } - } - - /** - * Publish File Message REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether published file messages should be stored in the channel's history. - */ - const STORE_IN_HISTORY = true; - // endregion - /** - * Publish shared file information request. - * - * @internal - */ - class PublishFileMessageRequest extends AbstractRequest { - constructor(parameters) { - var _a; - var _b; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = (_b = this.parameters).storeInHistory) !== null && _a !== void 0 ? _a : (_b.storeInHistory = STORE_IN_HISTORY); - } - operation() { - return RequestOperation$1.PNPublishFileMessageOperation; - } - validate() { - const { channel, fileId, fileName } = this.parameters; - if (!channel) - return "channel can't be empty"; - if (!fileId) - return "file id can't be empty"; - if (!fileName) - return "file name can't be empty"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { timetoken: this.deserializeResponse(response)[2] }; - }); - } - get path() { - const { message, channel, keySet: { publishKey, subscribeKey }, fileId, fileName, } = this.parameters; - const fileMessage = Object.assign({ file: { - name: fileName, - id: fileId, - } }, (message ? { message } : {})); - return `/v1/files/publish-file/${publishKey}/${subscribeKey}/0/${encodeString(channel)}/0/${encodeString(this.prepareMessagePayload(fileMessage))}`; - } - get queryParameters() { - const { customMessageType, storeInHistory, ttl, meta } = this.parameters; - return Object.assign(Object.assign(Object.assign({ store: storeInHistory ? '1' : '0' }, (customMessageType ? { custom_message_type: customMessageType } : {})), (ttl ? { ttl } : {})), (meta && typeof meta === 'object' ? { meta: JSON.stringify(meta) } : {})); - } - /** - * Pre-process provided data. - * - * Data will be "normalized" and encrypted if `cryptoModule` has been provided. - * - * @param payload - User-provided data which should be pre-processed before use. - * - * @returns Payload which can be used as part of request URL or body. - * - * @throws {Error} in case if provided `payload` or results of `encryption` can't be stringified. - */ - prepareMessagePayload(payload) { - const { crypto } = this.parameters; - if (!crypto) - return JSON.stringify(payload) || ''; - const encrypted = crypto.encrypt(JSON.stringify(payload)); - return JSON.stringify(typeof encrypted === 'string' ? encrypted : encode(encrypted)); - } - } - - /** - * File sharing REST API module. - * - * @internal - */ - // endregion - /** - * File download Url generation request. - * - * Local request which generates Url to download shared file from the specific channel. - * - * @internal - */ - class GetFileDownloadUrlRequest extends AbstractRequest { - /** - * Construct file download Url generation request. - * - * @param parameters - Request configuration. - */ - constructor(parameters) { - super({ method: TransportMethod.LOCAL }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetFileUrlOperation; - } - validate() { - const { channel, id, name } = this.parameters; - if (!channel) - return "channel can't be empty"; - if (!id) - return "file id can't be empty"; - if (!name) - return "file name can't be empty"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return response.url; - }); - } - get path() { - const { channel, id, name, keySet: { subscribeKey }, } = this.parameters; - return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files/${encodeString(id)}/${encodeString(name)}`; - } - } - - /** - * Delete file REST API module. - * - * @internal - */ - // endregion - /** - * Delete File request. - * - * @internal - */ - class DeleteFileRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNDeleteFileOperation; - } - validate() { - const { channel, id, name } = this.parameters; - if (!channel) - return "channel can't be empty"; - if (!id) - return "file id can't be empty"; - if (!name) - return "file name can't be empty"; - } - get path() { - const { keySet: { subscribeKey }, id, channel, name, } = this.parameters; - return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files/${encodeString(id)}/${encodeString(name)}`; - } - } - - /** - * List Files REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Number of files to return in response. - */ - const LIMIT$6 = 100; - // endregion - /** - * Files List request. - * - * @internal - */ - class FilesListRequest extends AbstractRequest { - constructor(parameters) { - var _a; - var _b; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = (_b = this.parameters).limit) !== null && _a !== void 0 ? _a : (_b.limit = LIMIT$6); - } - operation() { - return RequestOperation$1.PNListFilesOperation; - } - validate() { - if (!this.parameters.channel) - return "channel can't be empty"; - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files`; - } - get queryParameters() { - const { limit, next } = this.parameters; - return Object.assign({ limit: limit }, (next ? { next } : {})); - } - } - - /** - * Generate file upload URL REST API request. - * - * @internal - */ - // endregion - /** - * Generate File Upload Url request. - * - * @internal - */ - class GenerateFileUploadUrlRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGenerateUploadUrlOperation; - } - validate() { - if (!this.parameters.channel) - return "channel can't be empty"; - if (!this.parameters.name) - return "'name' can't be empty"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - const serviceResponse = this.deserializeResponse(response); - return { - id: serviceResponse.data.id, - name: serviceResponse.data.name, - url: serviceResponse.file_upload_request.url, - formFields: serviceResponse.file_upload_request.form_fields, - }; - }); - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/generate-upload-url`; - } - get headers() { - var _a; - return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); - } - get body() { - return JSON.stringify({ name: this.parameters.name }); - } - } - - /** - * Upload file REST API request. - * - * @internal - */ - /** - * File Upload request. - * - * @internal - */ - class UploadFileRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - // Use file's actual mime type if available. - const mimeType = parameters.file.mimeType; - if (mimeType) { - parameters.formFields = parameters.formFields.map((entry) => { - if (entry.name === 'Content-Type') - return { name: entry.name, value: mimeType }; - return entry; - }); - } - } - operation() { - return RequestOperation$1.PNPublishFileOperation; - } - validate() { - const { fileId, fileName, file, uploadUrl } = this.parameters; - if (!fileId) - return "Validation failed: file 'id' can't be empty"; - if (!fileName) - return "Validation failed: file 'name' can't be empty"; - if (!file) - return "Validation failed: 'file' can't be empty"; - if (!uploadUrl) - return "Validation failed: file upload 'url' can't be empty"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { - status: response.status, - message: response.body ? UploadFileRequest.decoder.decode(response.body) : 'OK', - }; - }); - } - request() { - return Object.assign(Object.assign({}, super.request()), { origin: new URL(this.parameters.uploadUrl).origin, timeout: 300 }); - } - get path() { - const { pathname, search } = new URL(this.parameters.uploadUrl); - return `${pathname}${search}`; - } - get body() { - return this.parameters.file; - } - get formData() { - return this.parameters.formFields; - } - } - - /** - * Share File API module. - * - * @internal - */ - // endregion - /** - * Send file composed request. - * - * @internal - */ - class SendFileRequest { - constructor(parameters) { - var _a; - this.parameters = parameters; - this.file = (_a = this.parameters.PubNubFile) === null || _a === void 0 ? void 0 : _a.create(parameters.file); - if (!this.file) - throw new Error('File upload error: unable to create File object.'); - } - /** - * Process user-input and upload file. - * - * @returns File upload request response. - */ - process() { - return __awaiter(this, void 0, void 0, function* () { - let fileName; - let fileId; - return this.generateFileUploadUrl() - .then((result) => { - fileName = result.name; - fileId = result.id; - return this.uploadFile(result); - }) - .then((result) => { - if (result.status !== 204) { - throw new PubNubError('Upload to bucket was unsuccessful', { - error: true, - statusCode: result.status, - category: StatusCategory$1.PNUnknownCategory, - operation: RequestOperation$1.PNPublishFileOperation, - errorData: { message: result.message }, - }); - } - }) - .then(() => this.publishFileMessage(fileId, fileName)) - .catch((error) => { - if (error instanceof PubNubError) - throw error; - const apiError = !(error instanceof PubNubAPIError) ? PubNubAPIError.create(error) : error; - throw new PubNubError('File upload error.', apiError.toStatus(RequestOperation$1.PNPublishFileOperation)); - }); - }); - } - /** - * Generate pre-signed file upload Url. - * - * @returns File upload credentials. - */ - generateFileUploadUrl() { - return __awaiter(this, void 0, void 0, function* () { - const request = new GenerateFileUploadUrlRequest(Object.assign(Object.assign({}, this.parameters), { name: this.file.name, keySet: this.parameters.keySet })); - return this.parameters.sendRequest(request); - }); - } - /** - * Prepare and upload {@link PubNub} File object to remote storage. - * - * @param uploadParameters - File upload request parameters. - * - * @returns - */ - uploadFile(uploadParameters) { - return __awaiter(this, void 0, void 0, function* () { - const { cipherKey, PubNubFile, crypto, cryptography } = this.parameters; - const { id, name, url, formFields } = uploadParameters; - // Encrypt file if possible. - if (this.parameters.PubNubFile.supportsEncryptFile) { - if (!cipherKey && crypto) - this.file = (yield crypto.encryptFile(this.file, PubNubFile)); - else if (cipherKey && cryptography) - this.file = (yield cryptography.encryptFile(cipherKey, this.file, PubNubFile)); - } - return this.parameters.sendRequest(new UploadFileRequest({ - fileId: id, - fileName: name, - file: this.file, - uploadUrl: url, - formFields, - })); - }); - } - publishFileMessage(fileId, fileName) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b, _c, _d; - let result = { timetoken: '0' }; - let retries = this.parameters.fileUploadPublishRetryLimit; - let publishError; - let wasSuccessful = false; - do { - try { - result = yield this.parameters.publishFile(Object.assign(Object.assign({}, this.parameters), { fileId, fileName })); - wasSuccessful = true; - } - catch (error) { - if (error instanceof PubNubError) - publishError = error; - retries -= 1; - } - } while (!wasSuccessful && retries > 0); - if (!wasSuccessful) { - throw new PubNubError('Publish failed. You may want to execute that operation manually using pubnub.publishFile', { - error: true, - category: (_b = (_a = publishError.status) === null || _a === void 0 ? void 0 : _a.category) !== null && _b !== void 0 ? _b : StatusCategory$1.PNUnknownCategory, - statusCode: (_d = (_c = publishError.status) === null || _c === void 0 ? void 0 : _c.statusCode) !== null && _d !== void 0 ? _d : 0, - channel: this.parameters.channel, - id: fileId, - name: fileName, - }); - } - else - return { status: 200, timetoken: result.timetoken, id: fileId, name: fileName }; - }); - } - } - - /** - * Common entity interface. - */ - class Entity { - /** - * Create an entity instance. - * - * @param nameOrId - Identifier which will be used with subscription loop. - * @param client - PubNub instance which has been used to create this entity. - * - * @internal - */ - constructor(nameOrId, client) { - /** - * List of subscription state object IDs which are using this entity. - * - * @internal - */ - this.subscriptionStateIds = []; - this.client = client; - this._nameOrId = nameOrId; - } - /** - * Retrieve entity type. - * - * @return One of known {@link EntityType entity types}. - * - * @internal - */ - get entityType() { - return 'Channel'; - } - /** - * Type of subscription entity. - * - * Type defines where it will be used with multiplexed subscribe REST API calls. - * - * @retuerns One of {@link SubscriptionType} enum fields. - * - * @internal - */ - get subscriptionType() { - return SubscriptionType.Channel; - } - /** - * Names for an object to be used in subscription. - * - * Provided strings will be used with multiplexed subscribe REST API calls. - * - * @param receivePresenceEvents - Whether presence events should be observed or not. - * - * @returns List of names with multiplexed subscribe REST API calls (may include additional names to receive presence - * updates). - * - * @internal - */ - subscriptionNames(receivePresenceEvents) { - { - return [ - this._nameOrId, - ...(receivePresenceEvents && !this._nameOrId.endsWith('-pnpres') ? [`${this._nameOrId}-pnpres`] : []), - ]; - } - } - /** - * Create a subscribable's subscription object for real-time updates. - * - * Create a subscription object which can be used to subscribe to the real-time updates sent to the specific data - * stream. - * - * @param [subscriptionOptions] - Subscription object behavior customization options. - * - * @returns Configured and ready to use subscribable's subscription object. - */ - subscription(subscriptionOptions) { - { - return new Subscription({ - client: this.client, - entity: this, - options: subscriptionOptions, - }); - } - } - /** - * How many active subscriptions use this entity. - * - * @internal - */ - get subscriptionsCount() { - return this.subscriptionStateIds.length; - } - /** - * Increase the number of active subscriptions. - * - * @param subscriptionStateId - Unique identifier of the subscription state object which doesn't use entity anymore. - * - * @internal - */ - increaseSubscriptionCount(subscriptionStateId) { - { - if (!this.subscriptionStateIds.includes(subscriptionStateId)) - this.subscriptionStateIds.push(subscriptionStateId); - } - } - /** - * Decrease the number of active subscriptions. - * - * **Note:** As long as the entity is used by at least one subscription, it can't be removed from the subscription. - * - * @param subscriptionStateId - Unique identifier of the subscription state object which doesn't use entity anymore. - * - * @internal - */ - decreaseSubscriptionCount(subscriptionStateId) { - { - const index = this.subscriptionStateIds.indexOf(subscriptionStateId); - if (index >= 0) - this.subscriptionStateIds.splice(index, 1); - } - } - /** - * Stringify entity object. - * - * @returns Serialized entity object. - */ - toString() { - return `${this.entityType} { nameOrId: ${this._nameOrId}, subscriptionsCount: ${this.subscriptionsCount} }`; - } - } - - /** - * Projection names which are observed on the object's base (un-prefixed) data channel. - * - * @internal - */ - const BASE_PROJECTIONS = ['default', '__default__']; - /** - * Key under which the base (un-prefixed) projection is stored in the variants registry. - * - * @internal - */ - const BASE_PROJECTION_KEY = ''; - /** - * Normalize a user-provided DataSync projection name. - * - * **Note:** Only the projection name is normalized. A DataSync object identifier is always used - * verbatim (so wildcard identifiers keep working by construction). - * - * @param [projection] - Projection name as provided by the user. - * - * @returns Trimmed projection name or `undefined` when the base projection is requested. - * - * @internal - */ - const normalizedProjection = (projection) => { - if (!projection) - return undefined; - const trimmed = projection.trim(); - if (trimmed.length === 0 || BASE_PROJECTIONS.includes(trimmed.toLowerCase())) - return undefined; - return trimmed; - }; - /** - * Base class for DataSync objects which can be observed with the subscribe REST API. - * - * A DataSync object is observed on a data channel named after its identifier, optionally prefixed - * with the name of an observed projection: `__{projection}__{id}`. - * - * **Note:** The identifier is used verbatim, so an identifier which already looks prefixed - * (`__admin__u1`) will be prefixed again when a projection is requested (`__admin____admin__u1`). - */ - class DataSyncSubscribable extends Entity { - /** - * Create a DataSync object entity. - * - * @param nameOrId - Unique DataSync object identifier (used verbatim). - * @param client - PubNub instance which has been used to create this entity. - * @param [projection] - Name of the projection which should be observed by this entity. - * - * @internal - */ - constructor(nameOrId, client, projection) { - super(nameOrId, client); - this._projection = normalizedProjection(projection); - } - /** - * Get unique DataSync object identifier. - * - * @returns DataSync object identifier. - */ - get id() { - return this._nameOrId; - } - /** - * Get the name of the projection which is observed by this entity. - * - * **Note:** A projection is chosen per subscription - * ({@link DataSyncSubscriptionOptions#projection}), so an entity created by the PubNub client - * always reports `undefined` here: it is the base-projection entity, and the entities bound to - * other projections are internal to it. - * - * @returns Observed projection name or `undefined` when the object is observed through its base - * projection. - */ - get projection() { - return this._projection; - } - /** - * Name of the data channel which is used with multiplexed subscribe REST API calls. - * - * @returns Name of the observed data channel. - * - * @internal - */ - get subscriptionChannel() { - return this._projection ? `__${this._projection}__${this._nameOrId}` : this._nameOrId; - } - /** - * Names for an object to be used in subscription. - * - * **Note:** A DataSync object is observed on a single data channel; presence events are not - * supported for it and `_receivePresenceEvents` is ignored. - * - * @param _receivePresenceEvents - Whether presence events should be observed or not. - * - * @returns List of names with multiplexed subscribe REST API calls. - * - * @internal - */ - subscriptionNames(_receivePresenceEvents) { - return [this.subscriptionChannel]; - } - /** - * Create a DataSync object's subscription object for real-time updates. - * - * @param [subscriptionOptions] - Subscription object behavior customization options. - * - * @returns Configured and ready to use DataSync object's subscription object. - * - * @example - * ```typescript - * // Observe the object itself. - * pubnub.dataSyncUser('u1').subscription().subscribe(); - * - * // Observe the `admin` projection of the object (the `__admin__u1` data channel). - * pubnub.dataSyncUser('u1').subscription({ projection: 'admin' }).subscribe(); - * ``` - */ - subscription(subscriptionOptions) { - { - const entity = this.entityForProjection(normalizedProjection(subscriptionOptions === null || subscriptionOptions === void 0 ? void 0 : subscriptionOptions.projection)); - // Each projection is observed on its own data channel, so it must be represented by its own - // entity instance (see `variants`). Let the entity which owns the requested projection create - // the subscription object for itself: it resolves that same projection to itself, so this - // delegation is always a single hop. - if (entity !== this) - return entity.subscription(subscriptionOptions); - return super.subscription(subscriptionOptions); - } - } - /** - * Resolve the entity which observes the same DataSync object through `projection`. - * - * @param [projection] - Normalized name of the projection to observe. - * - * @returns Receiver itself, or the memoized sibling entity bound to `projection`. - * - * @internal - */ - entityForProjection(projection) { - var _a, _b, _c; - var _d; - if (projection === this._projection) - return this; - // Register the receiver in the shared registry, so that it can be resolved back from siblings. - // - // Note: the receiver is added with an element assignment and never as part of an object literal - // which is assigned to `variants`. Declaration files for this module are inferred from the - // compiled JavaScript (`allowJs`), where a `this.variants = { ...: this }` statement would make - // the inferred member type reference the inaccessible polymorphic `this` type (TS2527). - const variants = ((_a = this.variants) !== null && _a !== void 0 ? _a : (this.variants = {})); - (_c = variants[_d = (_b = this._projection) !== null && _b !== void 0 ? _b : BASE_PROJECTION_KEY]) !== null && _c !== void 0 ? _c : (variants[_d] = this); - const key = projection !== null && projection !== void 0 ? projection : BASE_PROJECTION_KEY; - let entity = variants[key]; - if (!entity) { - entity = variants[key] = this.withProjection(projection); - entity.variants = variants; - } - return entity; - } - /** - * Stringify entity object. - * - * @returns Serialized entity object. - */ - toString() { - var _a; - return (`${this.entityType} { id: ${this._nameOrId}, projection: ${(_a = this._projection) !== null && _a !== void 0 ? _a : 'none'}, ` + - `channel: ${this.subscriptionChannel}, subscriptionsCount: ${this.subscriptionsCount} }`); - } - } - - /** - * First-class object which provides access to the real-time updates of a DataSync `Relationship` - * object. - * - * **Important:** The service delivers relationship changes on the data channels of **both linked - * entities** (`entityAId` and `entityBId`), and never on the relationship's own identifier. Observe - * `pubnub.dataSyncEntity(...)` for the linked entities to receive relationship updates; this entity - * is only useful if a key set is configured to publish relationship changes on the relationship - * identifier itself. - */ - class DataSyncRelationship extends DataSyncSubscribable { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'DataSyncRelationship'; - } - /** - * Create a copy of the receiver which observes `projection` of the same DataSync `Relationship` - * object. - * - * @param [projection] - Normalized name of the projection to observe. - * - * @returns `DataSyncRelationship` entity bound to `projection`. - * - * @internal - */ - withProjection(projection) { - return new DataSyncRelationship(this._nameOrId, this.client, projection); - } - } - - /** - * First-class object which provides access to the real-time updates of a DataSync `Membership` - * object. - * - * **Note:** A membership identifier is composite (`{userId}:{channelId}`) and is used verbatim as - * the name of the observed data channel. - * - * **Important:** The service delivers membership changes on the data channels of **both linked - * entities** (the user identifier and the channel identifier), and never on the membership's own - * identifier. Observe `pubnub.dataSyncUser(...)` and/or `pubnub.dataSyncChannel(...)` to receive - * membership updates; this entity is only useful if a key set is configured to publish membership - * changes on the membership identifier itself. - */ - class DataSyncMembership extends DataSyncSubscribable { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'DataSyncMembership'; - } - /** - * Create a copy of the receiver which observes `projection` of the same DataSync `Membership` - * object. - * - * @param [projection] - Normalized name of the projection to observe. - * - * @returns `DataSyncMembership` entity bound to `projection`. - * - * @internal - */ - withProjection(projection) { - return new DataSyncMembership(this._nameOrId, this.client, projection); - } - } - - /** - * First-class object which provides access to the real-time updates of a DataSync `Channel` object. - */ - class DataSyncChannel extends DataSyncSubscribable { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'DataSyncChannel'; - } - /** - * Create a copy of the receiver which observes `projection` of the same DataSync `Channel` object. - * - * @param [projection] - Normalized name of the projection to observe. - * - * @returns `DataSyncChannel` entity bound to `projection`. - * - * @internal - */ - withProjection(projection) { - return new DataSyncChannel(this._nameOrId, this.client, projection); - } - } - - /** - * First-class object which provides access to the real-time updates of a DataSync `Entity` object. - */ - class DataSyncEntity extends DataSyncSubscribable { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'DataSyncEntity'; - } - /** - * Create a copy of the receiver which observes `projection` of the same DataSync `Entity` object. - * - * @param [projection] - Normalized name of the projection to observe. - * - * @returns `DataSyncEntity` entity bound to `projection`. - * - * @internal - */ - withProjection(projection) { - return new DataSyncEntity(this._nameOrId, this.client, projection); - } - } - - /** - * First-class objects which provides access to the channel app context object-specific APIs. - */ - class ChannelMetadata extends Entity { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'ChannelMetadata'; - } - /** - * Get unique channel metadata object identifier. - * - * @returns Channel metadata identifier. - */ - get id() { - return this._nameOrId; - } - /** - * Names for an object to be used in subscription. - * - * Provided strings will be used with multiplexed subscribe REST API calls. - * - * @param _receivePresenceEvents - Whether presence events should be observed or not. - * - * @returns List of names with multiplexed subscribe REST API calls (may include additional names to receive presence - * updates). - * - * @internal - */ - subscriptionNames(_receivePresenceEvents) { - return [this.id]; - } - } - - /** - * First-class object which provides access to the real-time updates of a DataSync `User` object. - */ - class DataSyncUser extends DataSyncSubscribable { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'DataSyncUser'; - } - /** - * Create a copy of the receiver which observes `projection` of the same DataSync `User` object. - * - * @param [projection] - Normalized name of the projection to observe. - * - * @returns `DataSyncUser` entity bound to `projection`. - * - * @internal - */ - withProjection(projection) { - return new DataSyncUser(this._nameOrId, this.client, projection); - } - } - - /** - * First-class objects which provides access to the channel group-specific APIs. - */ - class ChannelGroup extends Entity { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'ChannelGroups'; - } - /** - * Get a unique channel group name. - * - * @returns Channel group name. - */ - get name() { - return this._nameOrId; - } - /** - * Type of subscription entity. - * - * Type defines where it will be used with multiplexed subscribe REST API calls. - * - * @retuerns One of {@link SubscriptionType} enum fields. - * - * @internal - */ - get subscriptionType() { - return SubscriptionType.ChannelGroup; - } - } - - /** - * First-class objects which provides access to the user app context object-specific APIs. - */ - class UserMetadata extends Entity { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'UserMetadata'; - } - /** - * Get unique user metadata object identifier. - * - * @returns User metadata identifier. - */ - get id() { - return this._nameOrId; - } - /** - * Names for an object to be used in subscription. - * - * Provided strings will be used with multiplexed subscribe REST API calls. - * - * @param _receivePresenceEvents - Whether presence events should be observed or not. - * - * @returns List of names with multiplexed subscribe REST API calls (may include additional names to receive presence - * updates). - * - * @internal - */ - subscriptionNames(_receivePresenceEvents) { - return [this.id]; - } - } - - /** - * First-class objects which provides access to the channel-specific APIs. - */ - class Channel extends Entity { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'Channel'; - } - /** - * Get a unique channel name. - * - * @returns Channel name. - */ - get name() { - return this._nameOrId; - } - } - - /** - * Remove channel group channels REST API module. - * - * @internal - */ - // endregion - /** - * Remove channel group channels request. - * - * @internal - */ - // prettier-ignore - class RemoveChannelGroupChannelsRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveChannelsFromGroupOperation; - } - validate() { - const { keySet: { subscribeKey }, channels, channelGroup, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channelGroup) - return 'Missing Channel Group'; - if (!channels) - return 'Missing channels'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - get path() { - const { keySet: { subscribeKey }, channelGroup, } = this.parameters; - return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}`; - } - get queryParameters() { - return { remove: this.parameters.channels.join(',') }; - } - } - - /** - * Add channel group channels REST API module. - * - * @internal - */ - // endregion - /** - * Add channel group channels request. - * - * @internal - */ - class AddChannelGroupChannelsRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNAddChannelsToGroupOperation; - } - validate() { - const { keySet: { subscribeKey }, channels, channelGroup, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channelGroup) - return 'Missing Channel Group'; - if (!channels) - return 'Missing channels'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - get path() { - const { keySet: { subscribeKey }, channelGroup, } = this.parameters; - return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}`; - } - get queryParameters() { - return { add: this.parameters.channels.join(',') }; - } - } - - /** - * List channel group channels REST API module. - * - * @internal - */ - // endregion - /** - * List Channel Group Channels request. - * - * @internal - */ - class ListChannelGroupChannels extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNChannelsForGroupOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - if (!this.parameters.channelGroup) - return 'Missing Channel Group'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { channels: this.deserializeResponse(response).payload.channels }; - }); - } - get path() { - const { keySet: { subscribeKey }, channelGroup, } = this.parameters; - return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}`; - } - } - - /** - * Delete channel group REST API module. - * - * @internal - */ - // endregion - /** - * Channel group delete request. - * - * @internal - */ - class DeleteChannelGroupRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveGroupOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - if (!this.parameters.channelGroup) - return 'Missing Channel Group'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - get path() { - const { keySet: { subscribeKey }, channelGroup, } = this.parameters; - return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}/remove`; - } - } - - /** - * List All Channel Groups REST API module. - * - * @internal - */ - // endregion - /** - * List all channel groups request. - * - * @internal - */ - class ListChannelGroupsRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNChannelGroupsOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { groups: this.deserializeResponse(response).payload.groups }; - }); - } - get path() { - return `/v1/channel-registration/sub-key/${this.parameters.keySet.subscribeKey}/channel-group`; - } - } - - /** - * PubNub Channel Groups API module. - */ - /** - * PubNub Stream / Channel group API interface. - */ - class PubNubChannelGroups { - /** - * Create stream / channel group API access object. - * - * @param logger - Registered loggers' manager. - * @param keySet - PubNub account keys set which should be used for REST API calls. - * @param sendRequest - Function which should be used to send REST API calls. - * - * @internal - */ - constructor(logger, keySet, - /* eslint-disable @typescript-eslint/no-explicit-any */ - sendRequest) { - this.sendRequest = sendRequest; - this.logger = logger; - this.keySet = keySet; - } - /** - * Fetch channel group channels. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get channel group channels response or `void` in case if `callback` - * provided. - */ - listChannels(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'List channel group channels with parameters:', - })); - const request = new ListChannelGroupChannels(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `List channel group channels success. Received ${response.channels.length} channels.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Fetch all channel groups. - * - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all channel groups response or `void` in case if `callback` provided. - * - * @deprecated - */ - listGroups(callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', 'List all channel groups.'); - const request = new ListChannelGroupsRequest({ keySet: this.keySet }); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `List all channel groups success. Received ${response.groups.length} groups.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Add channels to the channel group. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous add channels to the channel group response or `void` in case if - * `callback` provided. - */ - addChannels(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Add channels to the channel group with parameters:', - })); - const request = new AddChannelGroupChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = () => { - this.logger.debug('PubNub', `Add channels to the channel group success.`); - }; - if (callback) - return this.sendRequest(request, (status) => { - if (!status.error) - logResponse(); - callback(status); - }); - return this.sendRequest(request).then((response) => { - logResponse(); - return response; - }); - }); - } - /** - * Remove channels from the channel group. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove channels from the channel group response or `void` in - * case if `callback` provided. - */ - removeChannels(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove channels from the channel group with parameters:', - })); - const request = new RemoveChannelGroupChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = () => { - this.logger.debug('PubNub', `Remove channels from the channel group success.`); - }; - if (callback) - return this.sendRequest(request, (status) => { - if (!status.error) - logResponse(); - callback(status); - }); - return this.sendRequest(request).then((response) => { - logResponse(); - return response; - }); - }); - } - /** - * Remove a channel group. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove channel group response or `void` in case if `callback` provided. - */ - deleteGroup(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove a channel group with parameters:', - })); - const request = new DeleteChannelGroupRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = () => { - this.logger.debug('PubNub', `Remove a channel group success. Removed '${parameters.channelGroup}' channel group.'`); - }; - if (callback) - return this.sendRequest(request, (status) => { - if (!status.error) - logResponse(); - callback(status); - }); - return this.sendRequest(request).then((response) => { - logResponse(); - return response; - }); - }); - } - } - - /** - * Manage channels enabled for device push REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Environment for which APNS2 notifications - */ - const ENVIRONMENT = 'development'; - /** - * Maximum number of channels in `list` response. - */ - const MAX_COUNT = 1000; - // endregion - /** - * Base push notification request. - * - * @internal - */ - class BasePushNotificationChannelsRequest extends AbstractRequest { - constructor(parameters) { - var _a; - var _b; - super(); - this.parameters = parameters; - // Apply request defaults - if (this.parameters.pushGateway === 'apns2') - (_a = (_b = this.parameters).environment) !== null && _a !== void 0 ? _a : (_b.environment = ENVIRONMENT); - if (this.parameters.count && this.parameters.count > MAX_COUNT) - this.parameters.count = MAX_COUNT; - } - operation() { - throw Error('Should be implemented in subclass.'); - } - validate() { - const { keySet: { subscribeKey }, action, device, pushGateway, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!device) - return 'Missing Device ID (device)'; - if ((action === 'add' || action === 'remove') && - (!('channels' in this.parameters) || this.parameters.channels.length === 0)) - return 'Missing Channels'; - if (!pushGateway) - return 'Missing GW Type (pushGateway: fcm or apns2)'; - if (this.parameters.pushGateway === 'apns2' && !this.parameters.topic) - return 'Missing APNS2 topic'; - } - get path() { - const { keySet: { subscribeKey }, action, device, pushGateway, } = this.parameters; - let path = pushGateway === 'apns2' - ? `/v2/push/sub-key/${subscribeKey}/devices-apns2/${device}` - : `/v1/push/sub-key/${subscribeKey}/devices/${device}`; - if (action === 'remove-device') - path = `${path}/remove`; - return path; - } - get queryParameters() { - const { start, count } = this.parameters; - let query = Object.assign(Object.assign({ type: this.parameters.pushGateway }, (start ? { start } : {})), (count && count > 0 ? { count } : {})); - if ('channels' in this.parameters) - query[this.parameters.action] = this.parameters.channels.join(','); - if (this.parameters.pushGateway === 'apns2') { - const { environment, topic } = this.parameters; - query = Object.assign(Object.assign({}, query), { environment: environment, topic }); - } - return query; - } - } - - /** - * Unregister Channels from Device push REST API module. - * - * @internal - */ - // endregion - /** - * Unregister channels from device push request. - * - * @internal - */ - // prettier-ignore - class RemoveDevicePushNotificationChannelsRequest extends BasePushNotificationChannelsRequest { - constructor(parameters) { - super(Object.assign(Object.assign({}, parameters), { action: 'remove' })); - } - operation() { - return RequestOperation$1.PNRemovePushNotificationEnabledChannelsOperation; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - } - - /** - * List Device push enabled channels REST API module. - * - * @internal - */ - // endregion - /** - * List device push enabled channels request. - * - * @internal - */ - // prettier-ignore - class ListDevicePushNotificationChannelsRequest extends BasePushNotificationChannelsRequest { - constructor(parameters) { - super(Object.assign(Object.assign({}, parameters), { action: 'list' })); - } - operation() { - return RequestOperation$1.PNPushNotificationEnabledChannelsOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { channels: this.deserializeResponse(response) }; - }); - } - } - - /** - * Register Channels with Device push REST API module. - * - * @internal - */ - // endregion - /** - * Register channels with device push request. - * - * @internal - */ - // prettier-ignore - class AddDevicePushNotificationChannelsRequest extends BasePushNotificationChannelsRequest { - constructor(parameters) { - super(Object.assign(Object.assign({}, parameters), { action: 'add' })); - } - operation() { - return RequestOperation$1.PNAddPushNotificationEnabledChannelsOperation; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - } - - /** - * Unregister Device push REST API module. - * - * @internal - */ - // endregion - /** - * Unregister device push notifications request. - * - * @internal - */ - // prettier-ignore - class RemoveDevicePushNotificationRequest extends BasePushNotificationChannelsRequest { - constructor(parameters) { - super(Object.assign(Object.assign({}, parameters), { action: 'remove-device' })); - } - operation() { - return RequestOperation$1.PNRemoveAllPushNotificationsOperation; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - } - - /** - * PubNub Push Notifications API module. - */ - /** - * PubNub Push Notifications API interface. - */ - class PubNubPushNotifications { - /** - * Create mobile push notifications API access object. - * - * @param logger - Registered loggers' manager. - * @param keySet - PubNub account keys set which should be used for REST API calls. - * @param sendRequest - Function which should be used to send REST API calls. - * - * @internal - */ - constructor(logger, keySet, - /* eslint-disable @typescript-eslint/no-explicit-any */ - sendRequest) { - this.sendRequest = sendRequest; - this.logger = logger; - this.keySet = keySet; - } - /** - * Fetch device's push notification enabled channels. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get device channels response or `void` in case if `callback` provided. - */ - listChannels(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `List push-enabled channels with parameters:`, - })); - const request = new ListDevicePushNotificationChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `List push-enabled channels success. Received ${response.channels.length} channels.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Enable push notifications on channels for device. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - */ - addChannels(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Add push-enabled channels with parameters:`, - })); - const request = new AddDevicePushNotificationChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = () => { - this.logger.debug('PubNub', `Add push-enabled channels success.`); - }; - if (callback) - return this.sendRequest(request, (status) => { - if (!status.error) - logResponse(); - callback(status); - }); - return this.sendRequest(request).then((response) => { - logResponse(); - return response; - }); - }); - } - /** - * Disable push notifications on channels for device. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - */ - removeChannels(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove push-enabled channels with parameters:`, - })); - const request = new RemoveDevicePushNotificationChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = () => { - this.logger.debug('PubNub', `Remove push-enabled channels success.`); - }; - if (callback) - return this.sendRequest(request, (status) => { - if (!status.error) - logResponse(); - callback(status); - }); - return this.sendRequest(request).then((response) => { - logResponse(); - return response; - }); - }); - } - /** - * Disable push notifications for device. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - */ - deleteDevice(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove push notifications for device with parameters:`, - })); - const request = new RemoveDevicePushNotificationRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = () => { - this.logger.debug('PubNub', `Remove push notifications for device success.`); - }; - if (callback) - return this.sendRequest(request, (status) => { - if (!status.error) - logResponse(); - callback(status); - }); - return this.sendRequest(request).then((response) => { - logResponse(); - return response; - }); - }); - } - } - - /** - * Get All Channel Metadata REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Channel` custom fields should be included in response or not. - */ - const INCLUDE_CUSTOM_FIELDS$9 = false; - /** - * Whether total number of channels should be included in response or not. - */ - const INCLUDE_TOTAL_COUNT$4 = false; - /** - * Number of objects to return in response. - */ - const LIMIT$5 = 100; - // endregion - /** - * Get All Channels Metadata request. - * - * @internal - */ - class GetAllChannelsMetadataRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d; - var _e, _f; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_e = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_e.customFields = INCLUDE_CUSTOM_FIELDS$9); - (_c = (_f = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_f.totalCount = INCLUDE_TOTAL_COUNT$4); - (_d = parameters.limit) !== null && _d !== void 0 ? _d : (parameters.limit = LIMIT$5); - } - operation() { - return RequestOperation$1.PNGetAllChannelMetadataOperation; - } - get path() { - return `/v2/objects/${this.parameters.keySet.subscribeKey}/channels`; - } - get queryParameters() { - const { include, page, filter, sort, limit } = this.parameters; - let sorting = ''; - if (typeof sort === 'string') - sorting = sort; - else - sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ include: ['status', 'type', ...(include.customFields ? ['custom'] : [])].join(','), count: `${include.totalCount}` }, (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Remove Channel Metadata REST API module. - * - * @internal - */ - // endregion - /** - * Remove Channel Metadata request. - * - * @internal - */ - class RemoveChannelMetadataRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveChannelMetadataOperation; - } - validate() { - if (!this.parameters.channel) - return 'Channel cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}`; - } - } - - /** - * Get UUID Memberships REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Membership` custom field should be included in response or not. - */ - const INCLUDE_CUSTOM_FIELDS$8 = false; - /** - * Whether membership's `status` field should be included in response or not. - */ - const INCLUDE_STATUS$3 = false; - /** - * Whether membership's `type` field should be included in response or not. - */ - const INCLUDE_TYPE$3 = false; - /** - * Whether total number of memberships should be included in response or not. - */ - const INCLUDE_TOTAL_COUNT$3 = false; - /** - * Whether `Channel` fields should be included in response or not. - */ - const INCLUDE_CHANNEL_FIELDS$1 = false; - /** - * Whether `Channel` status field should be included in response or not. - */ - const INCLUDE_CHANNEL_STATUS_FIELD$1 = false; - /** - * Whether `Channel` type field should be included in response or not. - */ - const INCLUDE_CHANNEL_TYPE_FIELD$1 = false; - /** - * Whether `Channel` custom field should be included in response or not. - */ - const INCLUDE_CHANNEL_CUSTOM_FIELDS$1 = false; - /** - * Number of objects to return in response. - */ - const LIMIT$4 = 100; - // endregion - /** - * Get UUID Memberships request. - * - * @internal - */ - class GetUUIDMembershipsRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; - var _l, _m, _o, _p, _q, _r, _s, _t; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$8); - (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT$3); - (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS$3); - (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE$3); - (_f = (_q = parameters.include).channelFields) !== null && _f !== void 0 ? _f : (_q.channelFields = INCLUDE_CHANNEL_FIELDS$1); - (_g = (_r = parameters.include).customChannelFields) !== null && _g !== void 0 ? _g : (_r.customChannelFields = INCLUDE_CHANNEL_CUSTOM_FIELDS$1); - (_h = (_s = parameters.include).channelStatusField) !== null && _h !== void 0 ? _h : (_s.channelStatusField = INCLUDE_CHANNEL_STATUS_FIELD$1); - (_j = (_t = parameters.include).channelTypeField) !== null && _j !== void 0 ? _j : (_t.channelTypeField = INCLUDE_CHANNEL_TYPE_FIELD$1); - (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT$4); - // Remap for backward compatibility. - if (this.parameters.userId) - this.parameters.uuid = this.parameters.userId; - } - operation() { - return RequestOperation$1.PNGetMembershipsOperation; - } - validate() { - if (!this.parameters.uuid) - return "'uuid' cannot be empty"; - } - get path() { - const { keySet: { subscribeKey }, uuid, } = this.parameters; - return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}/channels`; - } - get queryParameters() { - const { include, page, filter, sort, limit } = this.parameters; - let sorting = ''; - if (typeof sort === 'string') - sorting = sort; - else - sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - const includeFlags = []; - if (include.statusField) - includeFlags.push('status'); - if (include.typeField) - includeFlags.push('type'); - if (include.customFields) - includeFlags.push('custom'); - if (include.channelFields) - includeFlags.push('channel'); - if (include.channelStatusField) - includeFlags.push('channel.status'); - if (include.channelTypeField) - includeFlags.push('channel.type'); - if (include.customChannelFields) - includeFlags.push('channel.custom'); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set UUID Memberships REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Membership` custom field should be included in response or not. - */ - const INCLUDE_CUSTOM_FIELDS$7 = false; - /** - * Whether membership's `status` field should be included in response or not. - */ - const INCLUDE_STATUS$2 = false; - /** - * Whether membership's `type` field should be included in response or not. - */ - const INCLUDE_TYPE$2 = false; - /** - * Whether total number of memberships should be included in response or not. - */ - const INCLUDE_TOTAL_COUNT$2 = false; - /** - * Whether `Channel` fields should be included in response or not. - */ - const INCLUDE_CHANNEL_FIELDS = false; - /** - * Whether `Channel` status field should be included in response or not. - */ - const INCLUDE_CHANNEL_STATUS_FIELD = false; - /** - * Whether `Channel` type field should be included in response or not. - */ - const INCLUDE_CHANNEL_TYPE_FIELD = false; - /** - * Whether `Channel` custom field should be included in response or not. - */ - const INCLUDE_CHANNEL_CUSTOM_FIELDS = false; - /** - * Number of objects to return in response. - */ - const LIMIT$3 = 100; - // endregion - /** - * Set UUID Memberships request. - * - * @internal - */ - class SetUUIDMembershipsRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; - var _l, _m, _o, _p, _q, _r, _s, _t; - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$7); - (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT$2); - (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS$2); - (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE$2); - (_f = (_q = parameters.include).channelFields) !== null && _f !== void 0 ? _f : (_q.channelFields = INCLUDE_CHANNEL_FIELDS); - (_g = (_r = parameters.include).customChannelFields) !== null && _g !== void 0 ? _g : (_r.customChannelFields = INCLUDE_CHANNEL_CUSTOM_FIELDS); - (_h = (_s = parameters.include).channelStatusField) !== null && _h !== void 0 ? _h : (_s.channelStatusField = INCLUDE_CHANNEL_STATUS_FIELD); - (_j = (_t = parameters.include).channelTypeField) !== null && _j !== void 0 ? _j : (_t.channelTypeField = INCLUDE_CHANNEL_TYPE_FIELD); - (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT$3); - // Remap for backward compatibility. - if (this.parameters.userId) - this.parameters.uuid = this.parameters.userId; - } - operation() { - return RequestOperation$1.PNSetMembershipsOperation; - } - validate() { - const { uuid, channels } = this.parameters; - if (!uuid) - return "'uuid' cannot be empty"; - if (!channels || channels.length === 0) - return 'Channels cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, uuid, } = this.parameters; - return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}/channels`; - } - get queryParameters() { - const { include, page, filter, sort, limit } = this.parameters; - let sorting = ''; - if (typeof sort === 'string') - sorting = sort; - else - sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - const includeFlags = ['channel.status', 'channel.type', 'status']; - if (include.statusField) - includeFlags.push('status'); - if (include.typeField) - includeFlags.push('type'); - if (include.customFields) - includeFlags.push('custom'); - if (include.channelFields) - includeFlags.push('channel'); - if (include.channelStatusField) - includeFlags.push('channel.status'); - if (include.channelTypeField) - includeFlags.push('channel.type'); - if (include.customChannelFields) - includeFlags.push('channel.custom'); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); - } - get headers() { - var _a; - return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); - } - get body() { - const { channels, type } = this.parameters; - return JSON.stringify({ - [`${type}`]: channels.map((channel) => { - if (typeof channel === 'string') { - return { channel: { id: channel } }; - } - else { - return { channel: { id: channel.id }, status: channel.status, type: channel.type, custom: channel.custom }; - } - }), - }); - } - } - - /** - * Get All UUID Metadata REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Channel` custom field should be included by default or not. - */ - const INCLUDE_CUSTOM_FIELDS$6 = false; - /** - * Number of objects to return in response. - */ - const LIMIT$2 = 100; - // endregion - /** - * Get All UUIDs Metadata request. - * - * @internal - */ - class GetAllUUIDMetadataRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c; - var _d; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_d = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_d.customFields = INCLUDE_CUSTOM_FIELDS$6); - (_c = parameters.limit) !== null && _c !== void 0 ? _c : (parameters.limit = LIMIT$2); - } - operation() { - return RequestOperation$1.PNGetAllUUIDMetadataOperation; - } - get path() { - return `/v2/objects/${this.parameters.keySet.subscribeKey}/uuids`; - } - get queryParameters() { - const { include, page, filter, sort, limit } = this.parameters; - let sorting = ''; - if (typeof sort === 'string') - sorting = sort; - else - sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ include: ['status', 'type', ...(include.customFields ? ['custom'] : [])].join(',') }, (include.totalCount !== undefined ? { count: `${include.totalCount}` } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Get Channel Metadata REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Channel` custom field should be included by default or not. - */ - const INCLUDE_CUSTOM_FIELDS$5 = true; - // endregion - /** - * Get Channel Metadata request. - * - * @internal - */ - class GetChannelMetadataRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b; - var _c; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS$5); - } - operation() { - return RequestOperation$1.PNGetChannelMetadataOperation; - } - validate() { - if (!this.parameters.channel) - return 'Channel cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}`; - } - get queryParameters() { - return { - include: ['status', 'type', ...(this.parameters.include.customFields ? ['custom'] : [])].join(','), - }; - } - } - - /** - * Set Channel Metadata REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Channel` custom field should be included by default or not. - */ - const INCLUDE_CUSTOM_FIELDS$4 = true; - // endregion - /** - * Set Channel Metadata request. - * - * @internal - */ - class SetChannelMetadataRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b; - var _c; - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS$4); - } - operation() { - return RequestOperation$1.PNSetChannelMetadataOperation; - } - validate() { - if (!this.parameters.channel) - return 'Channel cannot be empty'; - if (!this.parameters.data) - return 'Data cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json' }); - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}`; - } - get queryParameters() { - return { - include: ['status', 'type', ...(this.parameters.include.customFields ? ['custom'] : [])].join(','), - }; - } - get body() { - return JSON.stringify(this.parameters.data); - } - } - - /** - * Remove UUID Metadata REST API module. - * - * @internal - */ - // endregion - /** - * Remove UUID Metadata request. - * - * @internal - */ - class RemoveUUIDMetadataRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - // Remap for backward compatibility. - if (this.parameters.userId) - this.parameters.uuid = this.parameters.userId; - } - operation() { - return RequestOperation$1.PNRemoveUUIDMetadataOperation; - } - validate() { - if (!this.parameters.uuid) - return "'uuid' cannot be empty"; - } - get path() { - const { keySet: { subscribeKey }, uuid, } = this.parameters; - return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}`; - } - } - - /** - * Get Channel Members REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Member` custom field should be included in response or not. - */ - const INCLUDE_CUSTOM_FIELDS$3 = false; - /** - * Whether member's `status` field should be included in response or not. - */ - const INCLUDE_STATUS$1 = false; - /** - * Whether member's `type` field should be included in response or not. - */ - const INCLUDE_TYPE$1 = false; - /** - * Whether total number of members should be included in response or not. - */ - const INCLUDE_TOTAL_COUNT$1 = false; - /** - * Whether `UUID` fields should be included in response or not. - */ - const INCLUDE_UUID_FIELDS$1 = false; - /** - * Whether `UUID` status field should be included in response or not. - */ - const INCLUDE_UUID_STATUS_FIELD$1 = false; - /** - * Whether `UUID` type field should be included in response or not. - */ - const INCLUDE_UUID_TYPE_FIELD$1 = false; - /** - * Whether `UUID` custom field should be included in response or not. - */ - const INCLUDE_UUID_CUSTOM_FIELDS$1 = false; - /** - * Number of objects to return in response. - */ - const LIMIT$1 = 100; - // endregion - /** - * Get Channel Members request. - * - * @internal - */ - class GetChannelMembersRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; - var _l, _m, _o, _p, _q, _r, _s, _t; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$3); - (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT$1); - (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS$1); - (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE$1); - (_f = (_q = parameters.include).UUIDFields) !== null && _f !== void 0 ? _f : (_q.UUIDFields = INCLUDE_UUID_FIELDS$1); - (_g = (_r = parameters.include).customUUIDFields) !== null && _g !== void 0 ? _g : (_r.customUUIDFields = INCLUDE_UUID_CUSTOM_FIELDS$1); - (_h = (_s = parameters.include).UUIDStatusField) !== null && _h !== void 0 ? _h : (_s.UUIDStatusField = INCLUDE_UUID_STATUS_FIELD$1); - (_j = (_t = parameters.include).UUIDTypeField) !== null && _j !== void 0 ? _j : (_t.UUIDTypeField = INCLUDE_UUID_TYPE_FIELD$1); - (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT$1); - } - operation() { - return RequestOperation$1.PNSetMembersOperation; - } - validate() { - if (!this.parameters.channel) - return 'Channel cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}/uuids`; - } - get queryParameters() { - const { include, page, filter, sort, limit } = this.parameters; - let sorting = ''; - if (typeof sort === 'string') - sorting = sort; - else - sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - const includeFlags = []; - if (include.statusField) - includeFlags.push('status'); - if (include.typeField) - includeFlags.push('type'); - if (include.customFields) - includeFlags.push('custom'); - if (include.UUIDFields) - includeFlags.push('uuid'); - if (include.UUIDStatusField) - includeFlags.push('uuid.status'); - if (include.UUIDTypeField) - includeFlags.push('uuid.type'); - if (include.customUUIDFields) - includeFlags.push('uuid.custom'); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set Channel Members REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Member` custom field should be included in response or not. - */ - const INCLUDE_CUSTOM_FIELDS$2 = false; - /** - * Whether member's `status` field should be included in response or not. - */ - const INCLUDE_STATUS = false; - /** - * Whether member's `type` field should be included in response or not. - */ - const INCLUDE_TYPE = false; - /** - * Whether total number of members should be included in response or not. - */ - const INCLUDE_TOTAL_COUNT = false; - /** - * Whether `UUID` fields should be included in response or not. - */ - const INCLUDE_UUID_FIELDS = false; - /** - * Whether `UUID` status field should be included in response or not. - */ - const INCLUDE_UUID_STATUS_FIELD = false; - /** - * Whether `UUID` type field should be included in response or not. - */ - const INCLUDE_UUID_TYPE_FIELD = false; - /** - * Whether `UUID` custom field should be included in response or not. - */ - const INCLUDE_UUID_CUSTOM_FIELDS = false; - /** - * Number of objects to return in response. - */ - const LIMIT = 100; - // endregion - /** - * Set Channel Members request. - * - * @internal - */ - class SetChannelMembersRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; - var _l, _m, _o, _p, _q, _r, _s, _t; - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$2); - (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT); - (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS); - (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE); - (_f = (_q = parameters.include).UUIDFields) !== null && _f !== void 0 ? _f : (_q.UUIDFields = INCLUDE_UUID_FIELDS); - (_g = (_r = parameters.include).customUUIDFields) !== null && _g !== void 0 ? _g : (_r.customUUIDFields = INCLUDE_UUID_CUSTOM_FIELDS); - (_h = (_s = parameters.include).UUIDStatusField) !== null && _h !== void 0 ? _h : (_s.UUIDStatusField = INCLUDE_UUID_STATUS_FIELD); - (_j = (_t = parameters.include).UUIDTypeField) !== null && _j !== void 0 ? _j : (_t.UUIDTypeField = INCLUDE_UUID_TYPE_FIELD); - (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT); - } - operation() { - return RequestOperation$1.PNSetMembersOperation; - } - validate() { - const { channel, uuids } = this.parameters; - if (!channel) - return 'Channel cannot be empty'; - if (!uuids || uuids.length === 0) - return 'UUIDs cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}/uuids`; - } - get queryParameters() { - const { include, page, filter, sort, limit } = this.parameters; - let sorting = ''; - if (typeof sort === 'string') - sorting = sort; - else - sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - const includeFlags = ['uuid.status', 'uuid.type', 'type']; - if (include.statusField) - includeFlags.push('status'); - if (include.typeField) - includeFlags.push('type'); - if (include.customFields) - includeFlags.push('custom'); - if (include.UUIDFields) - includeFlags.push('uuid'); - if (include.UUIDStatusField) - includeFlags.push('uuid.status'); - if (include.UUIDTypeField) - includeFlags.push('uuid.type'); - if (include.customUUIDFields) - includeFlags.push('uuid.custom'); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); - } - get headers() { - var _a; - return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); - } - get body() { - const { uuids, type } = this.parameters; - return JSON.stringify({ - [`${type}`]: uuids.map((uuid) => { - if (typeof uuid === 'string') { - return { uuid: { id: uuid } }; - } - else { - return { uuid: { id: uuid.id }, status: uuid.status, type: uuid.type, custom: uuid.custom }; - } - }), - }); - } - } - - /** - * Get UUID Metadata REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether UUID custom field should be included by default or not. - */ - const INCLUDE_CUSTOM_FIELDS$1 = true; - // endregion - /** - * Get UUID Metadata request. - * - * @internal - */ - class GetUUIDMetadataRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b; - var _c; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS$1); - // Remap for backward compatibility. - if (this.parameters.userId) - this.parameters.uuid = this.parameters.userId; - } - operation() { - return RequestOperation$1.PNGetUUIDMetadataOperation; - } - validate() { - if (!this.parameters.uuid) - return "'uuid' cannot be empty"; - } - get path() { - const { keySet: { subscribeKey }, uuid, } = this.parameters; - return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}`; - } - get queryParameters() { - const { include } = this.parameters; - return { include: ['status', 'type', ...(include.customFields ? ['custom'] : [])].join(',') }; - } - } - - /** - * Set UUID Metadata REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Channel` custom field should be included by default or not. - */ - const INCLUDE_CUSTOM_FIELDS = true; - // endregion - /** - * Set UUID Metadata request. - * - * @internal - */ - class SetUUIDMetadataRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b; - var _c; - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS); - // Remap for backward compatibility. - if (this.parameters.userId) - this.parameters.uuid = this.parameters.userId; - } - operation() { - return RequestOperation$1.PNSetUUIDMetadataOperation; - } - validate() { - if (!this.parameters.uuid) - return "'uuid' cannot be empty"; - if (!this.parameters.data) - return 'Data cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json' }); - } - get path() { - const { keySet: { subscribeKey }, uuid, } = this.parameters; - return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}`; - } - get queryParameters() { - return { - include: ['status', 'type', ...(this.parameters.include.customFields ? ['custom'] : [])].join(','), - }; - } - get body() { - return JSON.stringify(this.parameters.data); - } - } - - /** - * PubNub Objects API module. - */ - /** - * PubNub App Context API interface. - */ - class PubNubObjects { - /** - * Create app context API access object. - * - * @param configuration - Extended PubNub client configuration object. - * @param sendRequest - Function which should be used to send REST API calls. - * - * @internal - */ - constructor(configuration, - /* eslint-disable @typescript-eslint/no-explicit-any */ - sendRequest) { - this.keySet = configuration.keySet; - this.configuration = configuration; - this.sendRequest = sendRequest; - } - /** - * Get registered loggers' manager. - * - * @returns Registered loggers' manager. - * - * @internal - */ - get logger() { - return this.configuration.logger(); - } - /** - * Fetch a paginated list of UUID Metadata objects. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all UUID metadata response or `void` in case if `callback` provided. - */ - getAllUUIDMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, - details: `Get all UUID metadata objects with parameters:`, - })); - return this._getAllUUIDMetadata(parametersOrCallback, callback); - }); - } - /** - * Fetch a paginated list of UUID Metadata objects. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all UUID metadata response or `void` in case if `callback` provided. - * - * @internal - */ - _getAllUUIDMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - // Get user request parameters. - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - const request = new GetAllUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get all UUID metadata success. Received ${response.totalCount} UUID metadata objects.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Fetch a specific UUID Metadata object. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get UUID metadata response or `void` in case if `callback` provided. - */ - getUUIDMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' - ? { uuid: this.configuration.userId } - : parametersOrCallback, - details: `Get ${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} UUID metadata object with parameters:`, - })); - return this._getUUIDMetadata(parametersOrCallback, callback); - }); - } - /** - * Fetch a specific UUID Metadata object. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get UUID metadata response or `void` in case if `callback` provided. - * - * @internal - */ - _getUUIDMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - // Get user request parameters. - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - if (parameters.userId) { - this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); - parameters.uuid = parameters.userId; - } - (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); - const request = new GetUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get UUID metadata object success. Received '${parameters.uuid}' UUID metadata object.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Update a specific UUID Metadata object. - * - * @param parameters - Request configuration parameters. Will set UUID metadata for currently - * configured PubNub client `uuid` if not set. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set UUID metadata response or `void` in case if `callback` provided. - */ - setUUIDMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Set UUID metadata object with parameters:`, - })); - return this._setUUIDMetadata(parameters, callback); - }); - } - /** - * Update a specific UUID Metadata object. - * - * @internal - * - * @param parameters - Request configuration parameters. Will set UUID metadata for currently - * configured PubNub client `uuid` if not set. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set UUID metadata response or `void` in case if `callback` provided. - */ - _setUUIDMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - if (parameters.userId) { - this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); - parameters.uuid = parameters.userId; - } - (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); - const request = new SetUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Set UUID metadata object success. Updated '${parameters.uuid}' UUID metadata object.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Remove a specific UUID Metadata object. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous UUID metadata remove response or `void` in case if `callback` provided. - */ - removeUUIDMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' - ? { uuid: this.configuration.userId } - : parametersOrCallback, - details: `Remove${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} UUID metadata object with parameters:`, - })); - return this._removeUUIDMetadata(parametersOrCallback, callback); - }); - } - /** - * Remove a specific UUID Metadata object. - * - * @internal - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous UUID metadata remove response or `void` in case if `callback` provided. - */ - _removeUUIDMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - // Get user request parameters. - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - if (parameters.userId) { - this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); - parameters.uuid = parameters.userId; - } - (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); - const request = new RemoveUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Remove UUID metadata object success. Removed '${parameters.uuid}' UUID metadata object.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Fetch a paginated list of Channel Metadata objects. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all Channel metadata response or `void` in case if `callback` - * provided. - */ - getAllChannelMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, - details: `Get all Channel metadata objects with parameters:`, - })); - return this._getAllChannelMetadata(parametersOrCallback, callback); - }); - } - /** - * Fetch a paginated list of Channel Metadata objects. - * - * @internal - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all Channel metadata response or `void` in case if `callback` - * provided. - */ - _getAllChannelMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - // Get user request parameters. - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - const request = new GetAllChannelsMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get all Channel metadata objects success. Received ${response.totalCount} Channel metadata objects.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Fetch Channel Metadata object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get Channel metadata response or `void` in case if `callback` provided. - */ - getChannelMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Get Channel metadata object with parameters:`, - })); - return this._getChannelMetadata(parameters, callback); - }); - } - /** - * Fetch Channel Metadata object. - * - * @internal - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get Channel metadata response or `void` in case if `callback` provided. - */ - _getChannelMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - const request = new GetChannelMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get Channel metadata object success. Received '${parameters.channel}' Channel metadata object.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Update specific Channel Metadata object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set Channel metadata response or `void` in case if `callback` provided. - */ - setChannelMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Set Channel metadata object with parameters:`, - })); - return this._setChannelMetadata(parameters, callback); - }); - } - /** - * Update specific Channel Metadata object. - * - * @internal - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set Channel metadata response or `void` in case if `callback` provided. - */ - _setChannelMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - const request = new SetChannelMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Set Channel metadata object success. Updated '${parameters.channel}' Channel metadata object.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Remove a specific Channel Metadata object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous Channel metadata remove response or `void` in case if `callback` - * provided. - */ - removeChannelMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove Channel metadata object with parameters:`, - })); - return this._removeChannelMetadata(parameters, callback); - }); - } - /** - * Remove a specific Channel Metadata object. - * - * @internal - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous Channel metadata remove response or `void` in case if `callback` - * provided. - */ - _removeChannelMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - const request = new RemoveChannelMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Remove Channel metadata object success. Removed '${parameters.channel}' Channel metadata object.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Fetch a paginated list of Channel Member objects. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get Channel Members response or `void` in case if `callback` provided. - */ - getChannelMembers(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Get channel members with parameters:`, - })); - const request = new GetChannelMembersRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get channel members success. Received ${response.totalCount} channel members.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Update specific Channel Members list. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update Channel members list response or `void` in case if `callback` - * provided. - */ - setChannelMembers(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Set channel members with parameters:`, - })); - const request = new SetChannelMembersRequest(Object.assign(Object.assign({}, parameters), { type: 'set', keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Set channel members success. There are ${response.totalCount} channel members now.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Remove Members from the Channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous Channel Members remove response or `void` in case if `callback` provided. - */ - removeChannelMembers(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove channel members with parameters:`, - })); - const request = new SetChannelMembersRequest(Object.assign(Object.assign({}, parameters), { type: 'delete', keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Remove channel members success. There are ${response.totalCount} channel members now.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Fetch a specific UUID Memberships list. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get UUID Memberships response or `void` in case if `callback` provided. - */ - getMemberships(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - // Get user request parameters. - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - if (parameters.userId) { - this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); - parameters.uuid = parameters.userId; - } - (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Get memberships with parameters:`, - })); - const request = new GetUUIDMembershipsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get memberships success. Received ${response.totalCount} memberships.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Update specific UUID Memberships list. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update UUID Memberships list response or `void` in case if `callback` - * provided. - */ - setMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - if (parameters.userId) { - this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); - parameters.uuid = parameters.userId; - } - (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Set memberships with parameters:`, - })); - const request = new SetUUIDMembershipsRequest(Object.assign(Object.assign({}, parameters), { type: 'set', keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Set memberships success. There are ${response.totalCount} memberships now.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Remove a specific UUID Memberships. - * - * @param parameters - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous UUID Memberships remove response or `void` in case if `callback` - * provided. - */ - removeMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - if (parameters.userId) { - this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); - parameters.uuid = parameters.userId; - } - (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove memberships with parameters:`, - })); - const request = new SetUUIDMembershipsRequest(Object.assign(Object.assign({}, parameters), { type: 'delete', keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Remove memberships success. There are ${response.totalCount} memberships now.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - // endregion - // endregion - // -------------------------------------------------------- - // --------------------- Deprecated API ------------------- - // -------------------------------------------------------- - // region Deprecated - /** - * Fetch paginated list of specific Space members or specific User memberships. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get specific Space members or specific User memberships response. - * - * @deprecated Use {@link PubNubObjects#getChannelMembers getChannelMembers} or - * {@link PubNubObjects#getMemberships getMemberships} methods instead. - */ - fetchMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b; - this.logger.warn('PubNub', "'fetchMemberships' is deprecated. Use 'pubnub.objects.getChannelMembers' or 'pubnub.objects.getMemberships'" + - ' instead.'); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Fetch memberships with parameters:`, - })); - if ('spaceId' in parameters) { - const spaceParameters = parameters; - const mappedParameters = { - channel: (_a = spaceParameters.spaceId) !== null && _a !== void 0 ? _a : spaceParameters.channel, - filter: spaceParameters.filter, - limit: spaceParameters.limit, - page: spaceParameters.page, - include: Object.assign({}, spaceParameters.include), - sort: spaceParameters.sort - ? Object.fromEntries(Object.entries(spaceParameters.sort).map(([key, value]) => [key.replace('user', 'uuid'), value])) - : undefined, - }; - // Map Members object to the older version. - const mapMembers = (response) => ({ - status: response.status, - data: response.data.map((members) => ({ - user: members.uuid, - custom: members.custom, - updated: members.updated, - eTag: members.eTag, - })), - totalCount: response.totalCount, - next: response.next, - prev: response.prev, - }); - if (callback) - return this.getChannelMembers(mappedParameters, (status, result) => { - callback(status, result ? mapMembers(result) : result); - }); - return this.getChannelMembers(mappedParameters).then(mapMembers); - } - const userParameters = parameters; - const mappedParameters = { - uuid: (_b = userParameters.userId) !== null && _b !== void 0 ? _b : userParameters.uuid, - filter: userParameters.filter, - limit: userParameters.limit, - page: userParameters.page, - include: Object.assign({}, userParameters.include), - sort: userParameters.sort - ? Object.fromEntries(Object.entries(userParameters.sort).map(([key, value]) => [key.replace('space', 'channel'), value])) - : undefined, - }; - // Map Memberships object to the older version. - const mapMemberships = (response) => ({ - status: response.status, - data: response.data.map((membership) => ({ - space: membership.channel, - custom: membership.custom, - updated: membership.updated, - eTag: membership.eTag, - })), - totalCount: response.totalCount, - next: response.next, - prev: response.prev, - }); - if (callback) - return this.getMemberships(mappedParameters, (status, result) => { - callback(status, result ? mapMemberships(result) : result); - }); - return this.getMemberships(mappedParameters).then(mapMemberships); - }); - } - /** - * Add members to specific Space or memberships specific User. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous add members to specific Space or memberships specific User response or - * `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubObjects#setChannelMembers setChannelMembers} or - * {@link PubNubObjects#setMemberships setMemberships} methods instead. - */ - addMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b, _c, _d, _e, _f; - this.logger.warn('PubNub', "'addMemberships' is deprecated. Use 'pubnub.objects.setChannelMembers' or 'pubnub.objects.setMemberships'" + - ' instead.'); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Add memberships with parameters:`, - })); - if ('spaceId' in parameters) { - const spaceParameters = parameters; - const mappedParameters = { - channel: (_a = spaceParameters.spaceId) !== null && _a !== void 0 ? _a : spaceParameters.channel, - uuids: (_c = (_b = spaceParameters.users) === null || _b === void 0 ? void 0 : _b.map((user) => { - if (typeof user === 'string') - return user; - return { id: user.userId, custom: user.custom }; - })) !== null && _c !== void 0 ? _c : spaceParameters.uuids, - limit: 0, - }; - if (callback) - return this.setChannelMembers(mappedParameters, callback); - return this.setChannelMembers(mappedParameters); - } - const userParameters = parameters; - const mappedParameters = { - uuid: (_d = userParameters.userId) !== null && _d !== void 0 ? _d : userParameters.uuid, - channels: (_f = (_e = userParameters.spaces) === null || _e === void 0 ? void 0 : _e.map((space) => { - if (typeof space === 'string') - return space; - return { - id: space.spaceId, - custom: space.custom, - }; - })) !== null && _f !== void 0 ? _f : userParameters.channels, - limit: 0, - }; - if (callback) - return this.setMemberships(mappedParameters, callback); - return this.setMemberships(mappedParameters); - }); - } - } - - /** - * Create User REST API module. - * - * @internal - */ - // endregion - /** - * Create User request. - * - * @internal - */ - class CreateUserRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNCreateDataSyncUserOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.data) - return 'User data cannot be empty'; - if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) - return 'Entity class version cannot be empty'; - } - get headers() { - var _a; - const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.user+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/users`; - } - get body() { - const { id, class: entityClass, classLevel, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), (entityClass !== undefined ? { entityClass } : {})), { entityClassVersion: data.classVersion }), (classLevel !== undefined ? { entityClassLevel: classLevel } : {})), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * PubNub DataSync API type definitions. - * - * Types for Entity Class CRUD operations. - */ - /** - * Serialize a {@link DataSyncSort} into the query value the service expects. - * - * A raw string is passed through unchanged. An object is turned into a list of `field:order` - * entries (a `null` direction emits the bare field name, letting the service apply its default - * ascending order). Mirrors the App Context `getAllChannelMetadata` sort handling. - * - * @internal - */ - function serializeDataSyncSort(sort) { - if (typeof sort === 'string') - return sort; - return Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - } - /** - * Convert user-friendly patch input to JSON Patch operations (request format). - * - * `path`/`from` are passed through verbatim — callers supply the exact RFC 6901 pointer. Do not - * reintroduce dot-notation translation here: splitting on `.` makes stored field names that - * contain a `.` unaddressable. - * - * - Each key in `add` becomes an "add" operation. - * - Each key in `replace` becomes a "replace" operation. - * - Each entry in `remove` becomes a "remove" operation. - * - Each `{ from, path }` pair in `move` becomes a "move" operation. - * - Each `{ from, path }` pair in `copy` becomes a "copy" operation. - * - Each key in `test` becomes a "test" operation. - * - * @internal - */ - function toJsonPatchOperations(input) { - const { add, replace, remove, move, copy, test } = input; - const ops = []; - if (add) { - for (const [path, value] of Object.entries(add)) { - ops.push({ op: 'add', path, value }); - } - } - if (replace) { - for (const [path, value] of Object.entries(replace)) { - ops.push({ op: 'replace', path, value }); - } - } - if (remove) { - for (const path of remove) { - ops.push({ op: 'remove', path }); - } - } - if (move) { - for (const { from, path } of move) { - ops.push({ op: 'move', from, path }); - } - } - if (copy) { - for (const { from, path } of copy) { - ops.push({ op: 'copy', from, path }); - } - } - if (test) { - for (const [path, value] of Object.entries(test)) { - ops.push({ op: 'test', path, value }); - } - } - return ops; - } - - /** - * Get Users REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Default number of items per page. - */ - const DEFAULT_LIMIT$4 = 20; - // endregion - /** - * Get Users request. - * - * @internal - */ - class GetUsersRequest extends AbstractRequest { - constructor(parameters) { - var _a; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$4); - } - operation() { - return RequestOperation$1.PNGetDataSyncUsersOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - get path() { - return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/users`; - } - get queryParameters() { - const { class: entityClass, classVersion, classLevel, cursor, limit, filter, filterFast, sort } = this.parameters; - const sorting = serializeDataSyncSort(sort); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (entityClass ? { entity_class: entityClass } : {})), (classVersion !== undefined ? { entity_class_version: `${classVersion}` } : {})), (classLevel ? { entity_class_level: classLevel } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set User REST API module. - * - * Full resource replacement via PUT. - * - * @internal - */ - // endregion - /** - * Set User request. - * - * @internal - */ - class SetUserRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PUT }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSetDataSyncUserOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'User id cannot be empty'; - if (!this.parameters.data) - return 'User data cannot be empty'; - if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) - return 'Entity class version cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.user+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; - } - get body() { - const { data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign({ entityClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Remove User REST API module. - * - * @internal - */ - // endregion - /** - * Remove User request. - * - * @internal - */ - class RemoveUserRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveDataSyncUserOperation; - } - validate() { - if (!this.parameters.id) - return 'User id cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.keys(headers).length > 0 ? headers : undefined; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { status: response.status }; - }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; - } - } - - /** - * Update User REST API module. - * - * Partial update via JSON Patch (RFC 6902). - * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` - * (JSON Pointer paths), and `move`/`copy` (JSON Pointer `{ from, path }` pairs) - * and converts them to JSON Patch operations. Paths are sent verbatim. - * - * @internal - */ - // endregion - /** - * Update User request. - * - * @internal - */ - class UpdateUserRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNUpdateDataSyncUserOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'User id cannot be empty'; - const { add, replace, remove, move, copy, test } = this.parameters; - const hasAdd = add && Object.keys(add).length > 0; - const hasReplace = replace && Object.keys(replace).length > 0; - const hasRemove = remove && remove.length > 0; - const hasMove = move && move.length > 0; - const hasCopy = copy && copy.length > 0; - const hasTest = test && Object.keys(test).length > 0; - if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) - return 'At least one of add, replace, remove, move, copy, or test must be provided'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; - } - get body() { - const { add, replace, remove, move, copy, test } = this.parameters; - const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); - return JSON.stringify(jsonPatchOps); - } - } - - /** - * Get User REST API module. - * - * @internal - */ - // endregion - /** - * Get User request. - * - * @internal - */ - class GetUserRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetDataSyncUserOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'User id cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; - } - } - - /** - * Create Channel REST API module. - * - * @internal - */ - // endregion - /** - * Create Channel request. - * - * @internal - */ - class CreateChannelRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNCreateDataSyncChannelOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.data) - return 'Channel data cannot be empty'; - if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) - return 'Entity class version cannot be empty'; - } - get headers() { - var _a; - const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.channel+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/channels`; - } - get body() { - const { id, class: entityClass, classLevel, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), (entityClass !== undefined ? { entityClass } : {})), { entityClassVersion: data.classVersion }), (classLevel !== undefined ? { entityClassLevel: classLevel } : {})), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Get Channels REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Default number of items per page. - */ - const DEFAULT_LIMIT$3 = 20; - // endregion - /** - * Get Channels request. - * - * @internal - */ - class GetChannelsRequest extends AbstractRequest { - constructor(parameters) { - var _a; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$3); - } - operation() { - return RequestOperation$1.PNGetDataSyncChannelsOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - get path() { - return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/channels`; - } - get queryParameters() { - const { class: entityClass, classVersion, classLevel, cursor, limit, filter, filterFast, sort } = this.parameters; - const sorting = serializeDataSyncSort(sort); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (entityClass ? { entity_class: entityClass } : {})), (classVersion !== undefined ? { entity_class_version: `${classVersion}` } : {})), (classLevel ? { entity_class_level: classLevel } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set Channel REST API module. - * - * Full resource replacement via PUT. - * - * @internal - */ - // endregion - /** - * Set Channel request. - * - * @internal - */ - class SetChannelRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PUT }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSetDataSyncChannelOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Channel id cannot be empty'; - if (!this.parameters.data) - return 'Channel data cannot be empty'; - if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) - return 'Entity class version cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.channel+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; - } - get body() { - const { data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign({ entityClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Remove Channel REST API module. - * - * @internal - */ - // endregion - /** - * Remove Channel request. - * - * @internal - */ - class RemoveChannelRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveDataSyncChannelOperation; - } - validate() { - if (!this.parameters.id) - return 'Channel id cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.keys(headers).length > 0 ? headers : undefined; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { status: response.status }; - }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; - } - } - - /** - * Update Channel REST API module. - * - * Partial update via JSON Patch (RFC 6902). - * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` - * (JSON Pointer paths), and `move`/`copy` (JSON Pointer from → path pairs), - * converting them to JSON Patch operations. Paths are sent verbatim. - * - * @internal - */ - // endregion - /** - * Update Channel request. - * - * @internal - */ - class UpdateChannelRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNUpdateDataSyncChannelOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Channel id cannot be empty'; - const { add, replace, remove, move, copy, test } = this.parameters; - const hasAdd = add && Object.keys(add).length > 0; - const hasReplace = replace && Object.keys(replace).length > 0; - const hasRemove = remove && remove.length > 0; - const hasMove = move && move.length > 0; - const hasCopy = copy && copy.length > 0; - const hasTest = test && Object.keys(test).length > 0; - if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) - return 'At least one of add, replace, remove, move, copy, or test must be provided'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; - } - get body() { - const { add, replace, remove, move, copy, test } = this.parameters; - const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); - return JSON.stringify(jsonPatchOps); - } - } - - /** - * Get Channel REST API module. - * - * @internal - */ - // endregion - /** - * Get Channel request. - * - * @internal - */ - class GetChannelRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetDataSyncChannelOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Channel id cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; - } - } - - /** - * Create Membership REST API module. - * - * @internal - */ - // endregion - /** - * Create Membership request. - * - * @internal - */ - class CreateMembershipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNCreateDataSyncMembershipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.userId) - return 'User id cannot be empty'; - if (!this.parameters.channelId) - return 'Channel id cannot be empty'; - if (!this.parameters.data) - return 'Membership data cannot be empty'; - if (!this.parameters.data.classVersion) - return 'Membership class version cannot be empty'; - } - get headers() { - var _a; - const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.membership+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/memberships`; - } - get body() { - const { id, userId, channelId, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), { userId, - channelId, relationshipClassVersion: data.classVersion }), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Get Memberships REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Default number of items per page. - */ - const DEFAULT_LIMIT$2 = 20; - // endregion - /** - * Get Memberships request. - * - * @internal - */ - class GetMembershipsRequest extends AbstractRequest { - constructor(parameters) { - var _a; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$2); - } - operation() { - return RequestOperation$1.PNGetDataSyncMembershipsOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - get path() { - return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/memberships`; - } - get queryParameters() { - const { userId, channelId, classVersion, cursor, limit, filter, filterFast, sort } = this.parameters; - const sorting = serializeDataSyncSort(sort); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (userId ? { user_id: userId } : {})), (channelId ? { channel_id: channelId } : {})), (classVersion !== undefined ? { relationship_class_version: `${classVersion}` } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set Membership REST API module. - * - * Full resource replacement via PUT. - * - * @internal - */ - // endregion - /** - * Set Membership request. - * - * @internal - */ - class SetMembershipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PUT }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSetDataSyncMembershipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Membership id cannot be empty'; - if (!this.parameters.userId) - return 'User id cannot be empty'; - if (!this.parameters.channelId) - return 'Channel id cannot be empty'; - if (!this.parameters.data) - return 'Membership data cannot be empty'; - if (!this.parameters.data.classVersion) - return 'Membership class version cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.membership+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; - } - get body() { - const { userId, channelId, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign({ userId, - channelId, relationshipClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Remove Membership REST API module. - * - * @internal - */ - // endregion - /** - * Remove Membership request. - * - * @internal - */ - class RemoveMembershipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveDataSyncMembershipOperation; - } - validate() { - if (!this.parameters.id) - return 'Membership id cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.keys(headers).length > 0 ? headers : undefined; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { status: response.status }; - }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; - } - } - - /** - * Update Membership REST API module. - * - * Partial update via JSON Patch (RFC 6902). - * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` - * (JSON Pointer paths), and `move`/`copy` (JSON Pointer `{ from, path }` pairs) - * and converts them to JSON Patch operations. Paths are sent verbatim. - * - * @internal - */ - // endregion - /** - * Update Membership request. - * - * @internal - */ - class UpdateMembershipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNUpdateDataSyncMembershipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Membership id cannot be empty'; - const { add, replace, remove, move, copy, test } = this.parameters; - const hasAdd = add && Object.keys(add).length > 0; - const hasReplace = replace && Object.keys(replace).length > 0; - const hasRemove = remove && remove.length > 0; - const hasMove = move && move.length > 0; - const hasCopy = copy && copy.length > 0; - const hasTest = test && Object.keys(test).length > 0; - if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) - return 'At least one of add, replace, remove, move, copy, or test must be provided'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; - } - get body() { - const { add, replace, remove, move, copy, test } = this.parameters; - const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); - return JSON.stringify(jsonPatchOps); - } - } - - /** - * Get Membership REST API module. - * - * @internal - */ - // endregion - /** - * Get Membership request. - * - * @internal - */ - class GetMembershipRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetDataSyncMembershipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Membership id cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; - } - } - - /** - * Create Relationship REST API module. - * - * @internal - */ - // endregion - /** - * Create Relationship request. - * - * @internal - */ - class CreateRelationshipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNCreateDataSyncRelationshipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.entityAId) - return 'Entity A id cannot be empty'; - if (!this.parameters.entityBId) - return 'Entity B id cannot be empty'; - if (!this.parameters.class) - return 'Relationship class cannot be empty'; - if (!this.parameters.data) - return 'Relationship data cannot be empty'; - if (!this.parameters.data.classVersion) - return 'Relationship class version cannot be empty'; - } - get headers() { - var _a; - const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.relationship+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/relationships`; - } - get body() { - const { id, class: relationshipClass, entityAId, entityBId, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), { entityAId, - entityBId, - relationshipClass, relationshipClassVersion: data.classVersion }), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Get Relationships REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Default number of items per page. - */ - const DEFAULT_LIMIT$1 = 20; - // endregion - /** - * Get Relationships request. - * - * @internal - */ - class GetRelationshipsRequest extends AbstractRequest { - constructor(parameters) { - var _a; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$1); - } - operation() { - return RequestOperation$1.PNGetDataSyncRelationshipsOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.class) - return 'Relationship class cannot be empty'; - } - get path() { - return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/relationships`; - } - get queryParameters() { - const { class: relationshipClass, classVersion, entityAId, entityBId, cursor, limit, filter, filterFast, sort, } = this.parameters; - const sorting = serializeDataSyncSort(sort); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ relationship_class: relationshipClass }, (classVersion !== undefined ? { relationship_class_version: `${classVersion}` } : {})), (entityAId ? { entity_a_id: entityAId } : {})), (entityBId ? { entity_b_id: entityBId } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set Relationship REST API module. - * - * Full resource replacement via PUT. - * - * @internal - */ - // endregion - /** - * Set Relationship request. - * - * @internal - */ - class SetRelationshipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PUT }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSetDataSyncRelationshipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Relationship id cannot be empty'; - if (!this.parameters.entityAId) - return 'Entity A id cannot be empty'; - if (!this.parameters.entityBId) - return 'Entity B id cannot be empty'; - if (!this.parameters.data) - return 'Relationship data cannot be empty'; - if (!this.parameters.data.classVersion) - return 'Relationship class version cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.relationship+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; - } - get body() { - const { entityAId, entityBId, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign({ entityAId, - entityBId, relationshipClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Remove Relationship REST API module. - * - * @internal - */ - // endregion - /** - * Remove Relationship request. - * - * @internal - */ - class RemoveRelationshipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveDataSyncRelationshipOperation; - } - validate() { - if (!this.parameters.id) - return 'Relationship id cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.keys(headers).length > 0 ? headers : undefined; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { status: response.status }; - }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; - } - } - - /** - * Update Relationship REST API module. - * - * Partial update via JSON Patch (RFC 6902). - * Accepts `add` and `replace` (JSON Pointer key-value pairs), `remove` - * (JSON Pointer paths), `move` and `copy` (`{ from, path }` JSON Pointer pairs), - * and `test` (JSON Pointer key-value pairs) and converts them to JSON Patch - * operations. Paths are sent verbatim. - * - * @internal - */ - // endregion - /** - * Update Relationship request. - * - * @internal - */ - class UpdateRelationshipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNUpdateDataSyncRelationshipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Relationship id cannot be empty'; - const { add, replace, remove, move, copy, test } = this.parameters; - const hasAdd = add && Object.keys(add).length > 0; - const hasReplace = replace && Object.keys(replace).length > 0; - const hasRemove = remove && remove.length > 0; - const hasMove = move && move.length > 0; - const hasCopy = copy && copy.length > 0; - const hasTest = test && Object.keys(test).length > 0; - if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) - return 'At least one of add, replace, remove, move, copy, or test must be provided'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; - } - get body() { - const { add, replace, remove, move, copy, test } = this.parameters; - const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); - return JSON.stringify(jsonPatchOps); - } - } - - /** - * Get Relationship REST API module. - * - * @internal - */ - // endregion - /** - * Get Relationship request. - * - * @internal - */ - class GetRelationshipRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetDataSyncRelationshipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Relationship id cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; - } - } - - /** - * Create Entity REST API module. - * - * @internal - */ - // endregion - /** - * Create Entity request. - * - * @internal - */ - class CreateEntityRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNCreateDataSyncEntityOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.class) - return 'Entity class cannot be empty'; - if (!this.parameters.data) - return 'Entity data cannot be empty'; - if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) - return 'Entity class version cannot be empty'; - } - get headers() { - var _a; - const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.entity+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/entities`; - } - get body() { - const { id, class: entityClass, classLevel, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), { entityClass, entityClassVersion: data.classVersion }), (classLevel !== undefined ? { entityClassLevel: classLevel } : {})), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Get Entities REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Default number of items per page. - */ - const DEFAULT_LIMIT = 20; - // endregion - /** - * Get Entities request. - * - * @internal - */ - class GetEntitiesRequest extends AbstractRequest { - constructor(parameters) { - var _a; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT); - } - operation() { - return RequestOperation$1.PNGetDataSyncEntitiesOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.class) - return 'Entity class cannot be empty'; - } - get path() { - return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/entities`; - } - get queryParameters() { - const { class: entityClass, classVersion, classLevel, cursor, limit, filter, filterFast, sort } = this.parameters; - const sorting = serializeDataSyncSort(sort); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ entity_class: entityClass }, (classVersion !== undefined ? { entity_class_version: `${classVersion}` } : {})), (classLevel ? { entity_class_level: classLevel } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set Entity REST API module. - * - * Full resource replacement via PUT. - * Note: `entityClass` is immutable and cannot be changed via update. - * - * @internal - */ - // endregion - /** - * Set Entity request. - * - * @internal - */ - class SetEntityRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PUT }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSetDataSyncEntityOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Entity id cannot be empty'; - if (!this.parameters.data) - return 'Entity data cannot be empty'; - if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) - return 'Entity class version cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.entity+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; - } - get body() { - const { data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign({ entityClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Remove Entity REST API module. - * - * @internal - */ - // endregion - /** - * Remove Entity request. - * - * @internal - */ - class RemoveEntityRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveDataSyncEntityOperation; - } - validate() { - if (!this.parameters.id) - return 'Entity id cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.keys(headers).length > 0 ? headers : undefined; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { status: response.status }; - }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; - } - } - - /** - * Update Entity REST API module. - * - * Partial update via JSON Patch (RFC 6902). - * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` - * (JSON Pointer paths), and `move`/`copy` (JSON Pointer from/path pairs), and - * converts them to JSON Patch operations. Paths are sent verbatim. - * - * @internal - */ - // endregion - /** - * Update Entity request. - * - * @internal - */ - class UpdateEntityRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNUpdateDataSyncEntityOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Entity id cannot be empty'; - const { add, replace, remove, move, copy, test } = this.parameters; - const hasAdd = add && Object.keys(add).length > 0; - const hasReplace = replace && Object.keys(replace).length > 0; - const hasRemove = remove && remove.length > 0; - const hasMove = move && move.length > 0; - const hasCopy = copy && copy.length > 0; - const hasTest = test && Object.keys(test).length > 0; - if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) - return 'At least one of add, replace, remove, move, copy, or test must be provided'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; - } - get body() { - const { add, replace, remove, move, copy, test } = this.parameters; - const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); - return JSON.stringify(jsonPatchOps); - } - } - - /** - * Get Entity REST API module. - * - * @internal - */ - // endregion - /** - * Get Entity request. - * - * @internal - */ - class GetEntityRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetDataSyncEntityOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Entity id cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; - } - } - - /** - * PubNub DataSync API module. - */ - /** - * PubNub DataSync API interface. - */ - class PubNubDataSync { - /** - * Create DataSync API access object. - * - * @param configuration - Extended PubNub client configuration object. - * @param sendRequest - Function which should be used to send REST API calls. - * - * @internal - */ - constructor(configuration, - /* eslint-disable @typescript-eslint/no-explicit-any */ - sendRequest) { - this.keySet = configuration.keySet; - this.configuration = configuration; - this.sendRequest = sendRequest; - } - /** - * Get registered loggers' manager. - * - * @returns Registered loggers' manager. - * - * @internal - */ - get logger() { - return this.configuration.logger(); - } - /** - * Create a new Entity. - * - * To change a field later with `updateEntity`, address it by its JSON Pointer: `classVersion` is - * patched as `/entityClassVersion`, `status` as `/status`, and payload fields as - * `/payload/`. `class` and `classLevel` are immutable and cannot be patched. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create entity response or `void` in case if `callback` provided. - */ - createEntity(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Create Entity with parameters:', - })); - const request = new CreateEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a specific Entity. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get entity response or `void` in case if `callback` provided. - */ - getEntity(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Entity with parameters:', - })); - const request = new GetEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a paginated list of Entities for a given Entity Class. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get entities response or `void` in case if `callback` provided. - */ - getEntities(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Entities with parameters:', - })); - const request = new GetEntitiesRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Set an Entity (full replacement via PUT). - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set entity response or `void` in case if `callback` provided. - */ - setEntity(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Set Entity with parameters:', - })); - const request = new SetEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Update an Entity (partial update via JSON Patch RFC 6902). - * - * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which - * is the name an entity carries in responses and real-time events: - * - * - `classVersion` → `/entityClassVersion` - * - `status` → `/status` - * - a payload field → `/payload/`; nest deeper with more segments, e.g. - * `/payload/address/city`. A field name that contains a `.` is written as-is - * (`/payload/user.name`). - * - * `entityClass` and `entityClassLevel` are immutable and cannot be patched. - * - * @example - * ```typescript - * await pubnub.dataSync.updateEntity({ - * id, - * replace: { '/status': 'inactive', '/payload/creditScore': 810 }, - * remove: ['/payload/legacyField'], - * }); - * ``` - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update entity response or `void` in case if `callback` provided. - */ - updateEntity(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Update Entity with parameters:', - })); - const request = new UpdateEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Remove an Entity. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove entity response or `void` in case if `callback` provided. - */ - removeEntity(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove Entity with parameters:', - })); - const request = new RemoveEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Create a new Relationship. - * - * To change a field later with `updateRelationship`, address it by its JSON Pointer: - * `classVersion` is patched as `/relationshipClassVersion`, `status` as `/status`, and payload - * fields as `/payload/`. `class`, `entityAId`, and `entityBId` are immutable and - * cannot be patched. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create relationship response or `void` in case if `callback` provided. - */ - createRelationship(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Create Relationship with parameters:', - })); - const request = new CreateRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a specific Relationship. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get relationship response or `void` in case if `callback` provided. - */ - getRelationship(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Relationship with parameters:', - })); - const request = new GetRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a paginated list of Relationships. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get relationships response or `void` in case if `callback` provided. - */ - getRelationships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Relationships with parameters:', - })); - const request = new GetRelationshipsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Set a Relationship (full replacement via PUT). - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set relationship response or `void` in case if `callback` provided. - */ - setRelationship(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Set Relationship with parameters:', - })); - const request = new SetRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Update a Relationship (partial update via JSON Patch RFC 6902). - * - * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which - * is the name a relationship carries in responses and real-time events: - * - * - `classVersion` → `/relationshipClassVersion` - * - `status` → `/status` - * - a payload field → `/payload/`; nest deeper with more segments, e.g. - * `/payload/address/city`. A field name that contains a `.` is written as-is - * (`/payload/user.name`). - * - * `relationshipClass`, `entityAId`, and `entityBId` are immutable and cannot be patched. - * - * @example - * ```typescript - * await pubnub.dataSync.updateRelationship({ - * id, - * replace: { '/status': 'inactive', '/payload/label': 'primary' }, - * remove: ['/payload/legacyField'], - * }); - * ``` - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update relationship response or `void` in case if `callback` provided. - */ - updateRelationship(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Update Relationship with parameters:', - })); - const request = new UpdateRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Remove a Relationship. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove relationship response or `void` in case if `callback` provided. - */ - removeRelationship(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove Relationship with parameters:', - })); - const request = new RemoveRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Create a new User. - * - * To change a field later with `updateUser`, address it by its JSON Pointer: `classVersion` is - * patched as `/entityClassVersion`, `status` as `/status`, and payload fields as - * `/payload/`. `class` and `classLevel` are immutable and cannot be patched. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create user response or `void` in case if `callback` provided. - */ - createUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Create User with parameters:', - })); - const request = new CreateUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a specific User. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get user response or `void` in case if `callback` provided. - */ - getUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get User with parameters:', - })); - const request = new GetUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a paginated list of Users. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get users response or `void` in case if `callback` provided. - */ - getUsers(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Users with parameters:', - })); - const request = new GetUsersRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Set a User (full replacement via PUT). - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set user response or `void` in case if `callback` provided. - */ - setUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Set User with parameters:', - })); - const request = new SetUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Update a User (partial update via JSON Patch RFC 6902). - * - * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which - * is the name a user carries in responses and real-time events: - * - * - `classVersion` → `/entityClassVersion` - * - `status` → `/status` - * - a payload field → `/payload/`; nest deeper with more segments, e.g. - * `/payload/address/city`. A field name that contains a `.` is written as-is - * (`/payload/user.name`). - * - * `entityClass` and `entityClassLevel` are immutable and cannot be patched. - * - * @example - * ```typescript - * await pubnub.dataSync.updateUser({ - * id, - * replace: { '/status': 'inactive', '/payload/email': 'alice.v@acme.test' }, - * remove: ['/payload/legacyField'], - * }); - * ``` - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update user response or `void` in case if `callback` provided. - */ - updateUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Update User with parameters:', - })); - const request = new UpdateUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Remove a User. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove user response or `void` in case if `callback` provided. - */ - removeUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove User with parameters:', - })); - const request = new RemoveUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Create a new Channel. - * - * To change a field later with `updateChannel`, address it by its JSON Pointer: `classVersion` - * is patched as `/entityClassVersion`, `status` as `/status`, and payload fields as - * `/payload/`. `class` and `classLevel` are immutable and cannot be patched. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create channel response or `void` in case if `callback` provided. - */ - createChannel(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Create Channel with parameters:', - })); - const request = new CreateChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a specific Channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get channel response or `void` in case if `callback` provided. - */ - getChannel(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Channel with parameters:', - })); - const request = new GetChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a paginated list of Channels. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get channels response or `void` in case if `callback` provided. - */ - getChannels(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Channels with parameters:', - })); - const request = new GetChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Set a Channel (full replacement via PUT). - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set channel response or `void` in case if `callback` provided. - */ - setChannel(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Set Channel with parameters:', - })); - const request = new SetChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Update a Channel (partial update via JSON Patch RFC 6902). - * - * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which - * is the name a channel carries in responses and real-time events: - * - * - `classVersion` → `/entityClassVersion` - * - `status` → `/status` - * - a payload field → `/payload/`; nest deeper with more segments, e.g. - * `/payload/address/city`. A field name that contains a `.` is written as-is - * (`/payload/user.name`). - * - * `entityClass` and `entityClassLevel` are immutable and cannot be patched. - * - * @example - * ```typescript - * await pubnub.dataSync.updateChannel({ - * id, - * replace: { '/status': 'inactive', '/payload/memberCount': 42 }, - * remove: ['/payload/legacyField'], - * }); - * ``` - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update channel response or `void` in case if `callback` provided. - */ - updateChannel(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Update Channel with parameters:', - })); - const request = new UpdateChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Remove a Channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove channel response or `void` in case if `callback` provided. - */ - removeChannel(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove Channel with parameters:', - })); - const request = new RemoveChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Create a new Membership (associates a User with a Channel). - * - * To change a field later with `updateMembership`, address it by its JSON Pointer: - * `classVersion` is patched as `/relationshipClassVersion`, `status` as `/status`, and payload - * fields as `/payload/`. `userId` and `channelId` are immutable and cannot be patched. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create membership response or `void` in case if `callback` provided. - */ - createMembership(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Create Membership with parameters:', - })); - const request = new CreateMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a specific Membership. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get membership response or `void` in case if `callback` provided. - */ - getMembership(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Membership with parameters:', - })); - const request = new GetMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a paginated list of Memberships. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get memberships response or `void` in case if `callback` provided. - */ - getMemberships(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Memberships with parameters:', - })); - const request = new GetMembershipsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Set a Membership (full replacement via PUT). - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set membership response or `void` in case if `callback` provided. - */ - setMembership(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Set Membership with parameters:', - })); - const request = new SetMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Update a Membership (partial update via JSON Patch RFC 6902). - * - * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which - * is the name a membership carries in responses and real-time events: - * - * - `classVersion` → `/relationshipClassVersion` - * - `status` → `/status` - * - a payload field → `/payload/`; nest deeper with more segments, e.g. - * `/payload/address/city`. A field name that contains a `.` is written as-is - * (`/payload/user.name`). - * - * `userId` and `channelId` are immutable and cannot be patched. - * - * @example - * ```typescript - * await pubnub.dataSync.updateMembership({ - * id, - * replace: { '/status': 'inactive', '/payload/role': 'moderator' }, - * remove: ['/payload/legacyField'], - * }); - * ``` - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update membership response or `void` in case if `callback` provided. - */ - updateMembership(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Update Membership with parameters:', - })); - const request = new UpdateMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Remove a Membership. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove membership response or `void` in case if `callback` provided. - */ - removeMembership(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove Membership with parameters:', - })); - const request = new RemoveMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - } - - /** - * Time REST API module. - */ - // endregion - /** - * Get current PubNub high-precision time request. - * - * @internal - */ - class TimeRequest extends AbstractRequest { - constructor() { - super(); - } - operation() { - return RequestOperation$1.PNTimeOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { timetoken: this.deserializeResponse(response)[0] }; - }); - } - get path() { - return '/time/0'; - } - } - - /** - * Download File REST API module. - * - * @internal - */ - // endregion - /** - * Download File request. - * - * @internal - */ - class DownloadFileRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNDownloadFileOperation; - } - validate() { - const { channel, id, name } = this.parameters; - if (!channel) - return "channel can't be empty"; - if (!id) - return "file id can't be empty"; - if (!name) - return "file name can't be empty"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - const { cipherKey, crypto, cryptography, name, PubNubFile } = this.parameters; - const mimeType = response.headers['content-type']; - let decryptedFile; - let body = response.body; - if (PubNubFile.supportsEncryptFile && (cipherKey || crypto)) { - if (cipherKey && cryptography) - body = yield cryptography.decrypt(cipherKey, body); - else if (!cipherKey && crypto) - decryptedFile = yield crypto.decryptFile(PubNubFile.create({ data: body, name: name, mimeType }), PubNubFile); - } - return (decryptedFile - ? decryptedFile - : PubNubFile.create({ - data: body, - name, - mimeType, - })); - }); - } - get path() { - const { keySet: { subscribeKey }, channel, id, name, } = this.parameters; - return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files/${encodeString(id)}/${encodeString(name)}`; - } - } - - /** - * Core PubNub API module. - */ - // endregion - /** - * Platform-agnostic PubNub client core. - */ - class PubNubCore { - /** - * Construct notification payload which will trigger push notification. - * - * @param title - Title which will be shown on notification. - * @param body - Payload which will be sent as part of notification. - * - * @returns Pre-formatted message payload which will trigger push notification. - */ - static notificationPayload(title, body) { - { - return new NotificationsPayload(title, body); - } - } - /** - * Generate unique identifier. - * - * @returns Unique identifier. - */ - static generateUUID() { - return uuidGenerator.createUUID(); - } - // endregion - /** - * Create and configure PubNub client core. - * - * @param configuration - PubNub client core configuration. - * @returns Configured and ready to use PubNub client. - * - * @internal - */ - constructor(configuration) { - /** - * List of subscribe capable objects with active subscriptions. - * - * Track list of {@link Subscription} and {@link SubscriptionSet} objects with active - * subscription. - * - * @internal - */ - this.eventHandleCapable = {}; - /** - * Created entities. - * - * Map of entities which have been created to access. - * - * @internal - */ - this.entities = {}; - this._configuration = configuration.configuration; - this.cryptography = configuration.cryptography; - this.tokenManager = configuration.tokenManager; - this.transport = configuration.transport; - this.crypto = configuration.crypto; - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: configuration.configuration, - details: 'Create with configuration:', - ignoredKeys(key, obj) { - return typeof obj[key] === 'function' || key.startsWith('_') || key === 'keySet' || isSensitiveLogKey(key); - }, - })); - // API group entry points initialization. - this._objects = new PubNubObjects(this._configuration, this.sendRequest.bind(this)); - this._dataSync = new PubNubDataSync(this._configuration, this.sendRequest.bind(this)); - this._channelGroups = new PubNubChannelGroups(this._configuration.logger(), this._configuration.keySet, this.sendRequest.bind(this)); - this._push = new PubNubPushNotifications(this._configuration.logger(), this._configuration.keySet, this.sendRequest.bind(this)); - { - // Prepare for a real-time events announcement. - this.eventDispatcher = new EventDispatcher(); - if (this._configuration.enableEventEngine) { - { - this.logger.debug('PubNub', 'Using new subscription loop management.'); - let heartbeatInterval = this._configuration.getHeartbeatInterval(); - this.presenceState = {}; - { - if (heartbeatInterval) { - this.presenceEventEngine = new PresenceEventEngine({ - heartbeat: (parameters, callback) => { - this.logger.trace('PresenceEventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Heartbeat with parameters:', - })); - return this.heartbeat(parameters, callback); - }, - leave: (parameters) => { - this.logger.trace('PresenceEventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Leave with parameters:', - })); - this.makeUnsubscribe(parameters, () => { }); - }, - heartbeatDelay: () => { - let cancelDelay = () => { }; - const promise = new Promise((resolve, reject) => { - heartbeatInterval = this._configuration.getHeartbeatInterval(); - if (!heartbeatInterval) - reject(new PubNubError('Heartbeat interval has been reset.')); - else { - const timeoutId = setTimeout(() => { - resolve(); - }, heartbeatInterval * 1000); - cancelDelay = () => { - clearTimeout(timeoutId); - reject(new PubNubError('Heartbeat interval has been cancelled.')); - }; - } - }); - return { cancelDelay, promise }; - }, - emitStatus: (status) => this.emitStatus(status), - config: this._configuration, - presenceState: this.presenceState, - }); - } - } - this.eventEngine = new EventEngine({ - handshake: (parameters) => { - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Handshake with parameters:', - ignoredKeys: ['abortSignal', 'crypto', 'timeout', 'keySet', 'getFileUrl'], - })); - return this.subscribeHandshake(parameters); - }, - receiveMessages: (parameters) => { - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Receive messages with parameters:', - ignoredKeys: ['abortSignal', 'crypto', 'timeout', 'keySet', 'getFileUrl'], - })); - return this.subscribeReceiveMessages(parameters); - }, - join: (parameters) => { - var _a, _b; - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Join with parameters:', - })); - if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { - this.logger.trace('EventEngine', "Ignoring 'join' announcement request."); - return; - } - this.join(parameters); - }, - leave: (parameters) => { - var _a, _b; - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Leave with parameters:', - })); - if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { - this.logger.trace('EventEngine', "Ignoring 'leave' announcement request."); - return; - } - this.leave(parameters); - }, - leaveAll: (parameters) => { - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Leave all with parameters:', - })); - this.leaveAll(parameters); - }, - presenceReconnect: (parameters) => { - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Reconnect with parameters:', - })); - this.presenceReconnect(parameters); - }, - presenceDisconnect: (parameters) => { - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Disconnect with parameters:', - })); - this.presenceDisconnect(parameters); - }, - presenceState: this.presenceState, - config: this._configuration, - emitMessages: (cursor, events) => { - try { - this.logger.debug('EventEngine', () => { - const hashedEvents = events.map((event) => { - const pn_mfp = event.type === PubNubEventType.Message || event.type === PubNubEventType.Signal - ? messageFingerprint(event.data.message) - : undefined; - return pn_mfp ? { type: event.type, data: Object.assign(Object.assign({}, event.data), { pn_mfp }) } : event; - }); - return { messageType: 'object', message: hashedEvents, details: 'Received events:' }; - }); - events.forEach((event) => this.emitEvent(cursor, event)); - } - catch (e) { - const errorStatus = { - error: true, - category: StatusCategory$1.PNUnknownCategory, - errorData: e, - statusCode: 0, - }; - this.emitStatus(errorStatus); - } - }, - emitStatus: (status) => this.emitStatus(status), - }); - } - } - else { - { - this.logger.debug('PubNub', 'Using legacy subscription loop management.'); - this.subscriptionManager = new SubscriptionManager(this._configuration, (cursor, event) => { - try { - this.emitEvent(cursor, event); - } - catch (e) { - const errorStatus = { - error: true, - category: StatusCategory$1.PNUnknownCategory, - errorData: e, - statusCode: 0, - }; - this.emitStatus(errorStatus); - } - }, this.emitStatus.bind(this), (parameters, callback) => { - this.logger.trace('SubscriptionManager', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Subscribe with parameters:', - ignoredKeys: ['crypto', 'timeout', 'keySet', 'getFileUrl'], - })); - this.makeSubscribe(parameters, callback); - }, (parameters, callback) => { - this.logger.trace('SubscriptionManager', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Heartbeat with parameters:', - ignoredKeys: ['crypto', 'timeout', 'keySet', 'getFileUrl'], - })); - return this.heartbeat(parameters, callback); - }, (parameters, callback) => { - this.logger.trace('SubscriptionManager', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Leave with parameters:', - })); - this.makeUnsubscribe(parameters, callback); - }, this.time.bind(this)); - } - } - } - } - // -------------------------------------------------------- - // -------------------- Configuration ---------------------- - // -------------------------------------------------------- - // region Configuration - /** - * PubNub client configuration. - * - * @returns Currently user PubNub client configuration. - */ - get configuration() { - return this._configuration; - } - /** - * Current PubNub client configuration. - * - * @returns Currently user PubNub client configuration. - * - * @deprecated Use {@link configuration} getter instead. - */ - get _config() { - return this.configuration; - } - /** - * REST API endpoint access authorization key. - * - * It is required to have `authorization key` with required permissions to access REST API - * endpoints when `PAM` enabled for user key set. - */ - get authKey() { - var _a; - return (_a = this._configuration.authKey) !== null && _a !== void 0 ? _a : undefined; - } - /** - * REST API endpoint access authorization key. - * - * It is required to have `authorization key` with required permissions to access REST API - * endpoints when `PAM` enabled for user key set. - */ - getAuthKey() { - return this.authKey; - } - /** - * Change REST API endpoint access authorization key. - * - * @param authKey - New authorization key which should be used with new requests. - */ - setAuthKey(authKey) { - this.logger.debug('PubNub', 'Auth key updated.'); - this._configuration.setAuthKey(authKey); - if (this.onAuthenticationChange) - this.onAuthenticationChange(authKey); - } - /** - * Get a PubNub client user identifier. - * - * @returns Current PubNub client user identifier. - */ - get userId() { - return this._configuration.userId; - } - /** - * Change the current PubNub client user identifier. - * - * **Important:** Change won't affect ongoing REST API calls. - * **Warning:** Because ongoing REST API calls won't be canceled there could happen unexpected events like implicit - * `join` event for the previous `userId` after a long-poll subscribe request will receive a response. To avoid this - * it is advised to unsubscribe from all/disconnect before changing `userId`. - * - * @param value - New PubNub client user identifier. - * - * @throws Error empty user identifier has been provided. - */ - set userId(value) { - if (!value || typeof value !== 'string' || value.trim().length === 0) { - const error = new Error('Missing or invalid userId parameter. Provide a valid string userId'); - this.logger.error('PubNub', () => ({ messageType: 'error', message: error })); - throw error; - } - this.logger.debug('PubNub', `Set user ID: ${value}`); - this._configuration.userId = value; - if (this.onUserIdChange) - this.onUserIdChange(this._configuration.userId); - } - /** - * Get a PubNub client user identifier. - * - * @returns Current PubNub client user identifier. - */ - getUserId() { - return this._configuration.userId; - } - /** - * Change the current PubNub client user identifier. - * - * **Important:** Change won't affect ongoing REST API calls. - * - * @param value - New PubNub client user identifier. - * - * @throws Error empty user identifier has been provided. - */ - setUserId(value) { - this.userId = value; - } - /** - * Real-time updates filtering expression. - * - * @returns Filtering expression. - */ - get filterExpression() { - var _a; - return (_a = this._configuration.getFilterExpression()) !== null && _a !== void 0 ? _a : undefined; - } - /** - * Real-time updates filtering expression. - * - * @returns Filtering expression. - */ - getFilterExpression() { - return this.filterExpression; - } - /** - * Update real-time updates filtering expression. - * - * @param expression - New expression which should be used or `undefined` to disable filtering. - */ - set filterExpression(expression) { - this.logger.debug('PubNub', `Set filter expression: ${expression}`); - this._configuration.setFilterExpression(expression); - } - /** - * Update real-time updates filtering expression. - * - * @param expression - New expression which should be used or `undefined` to disable filtering. - */ - setFilterExpression(expression) { - this.logger.debug('PubNub', `Set filter expression: ${expression}`); - this.filterExpression = expression; - } - /** - * Dta encryption / decryption key. - * - * @returns Currently used key for data encryption / decryption. - */ - get cipherKey() { - return this._configuration.getCipherKey(); - } - /** - * Change data encryption / decryption key. - * - * @param key - New key which should be used for data encryption / decryption. - */ - set cipherKey(key) { - this._configuration.setCipherKey(key); - } - /** - * Change data encryption / decryption key. - * - * @param key - New key which should be used for data encryption / decryption. - */ - setCipherKey(key) { - this.logger.debug('PubNub', 'Cipher key updated.'); - this.cipherKey = key; - } - /** - * Change a heartbeat requests interval. - * - * @param interval - New presence request heartbeat intervals. - */ - set heartbeatInterval(interval) { - var _a; - this.logger.debug('PubNub', `Set heartbeat interval: ${interval}`); - this._configuration.setHeartbeatInterval(interval); - if (this.onHeartbeatIntervalChange) - this.onHeartbeatIntervalChange((_a = this._configuration.getHeartbeatInterval()) !== null && _a !== void 0 ? _a : 0); - } - /** - * Change a heartbeat requests interval. - * - * @param interval - New presence request heartbeat intervals. - */ - setHeartbeatInterval(interval) { - this.heartbeatInterval = interval; - } - /** - * Get registered loggers' manager. - * - * @returns Registered loggers' manager. - */ - get logger() { - return this._configuration.logger(); - } - /** - * Get PubNub SDK version. - * - * @returns Current SDK version. - */ - getVersion() { - return this._configuration.getVersion(); - } - /** - * Add framework's prefix. - * - * @param name - Name of the framework which would want to add own data into `pnsdk` suffix. - * @param suffix - Suffix with information about a framework. - */ - _addPnsdkSuffix(name, suffix) { - this.logger.debug('PubNub', `Add '${name}' 'pnsdk' suffix: ${suffix}`); - this._configuration._addPnsdkSuffix(name, suffix); - } - // -------------------------------------------------------- - // ---------------------- Deprecated ---------------------- - // -------------------------------------------------------- - // region Deprecated - /** - * Get a PubNub client user identifier. - * - * @returns Current PubNub client user identifier. - * - * @deprecated Use the {@link getUserId} or {@link userId} getter instead. - */ - getUUID() { - return this.userId; - } - /** - * Change the current PubNub client user identifier. - * - * **Important:** Change won't affect ongoing REST API calls. - * - * @param value - New PubNub client user identifier. - * - * @throws Error empty user identifier has been provided. - * - * @deprecated Use the {@link PubNubCore#setUserId setUserId} or {@link PubNubCore#userId userId} setter instead. - */ - setUUID(value) { - this.logger.warn('PubNub', "'setUserId` is deprecated, please use 'setUserId' or 'userId' setter instead."); - this.logger.debug('PubNub', `Set UUID: ${value}`); - this.userId = value; - } - /** - * Custom data encryption method. - * - * @deprecated Instead use {@link cryptoModule} for data encryption. - */ - get customEncrypt() { - return this._configuration.getCustomEncrypt(); - } - /** - * Custom data decryption method. - * - * @deprecated Instead use {@link cryptoModule} for data decryption. - */ - get customDecrypt() { - return this._configuration.getCustomDecrypt(); - } - // endregion - // endregion - // -------------------------------------------------------- - // ---------------------- Entities ------------------------ - // -------------------------------------------------------- - // region Entities - /** - * Create a `Channel` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param name - Unique channel name. - * @returns `Channel` entity. - */ - channel(name) { - let channel = this.entities[`${name}_ch`]; - if (!channel) - channel = this.entities[`${name}_ch`] = new Channel(name, this); - return channel; - } - /** - * Create a `ChannelGroup` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param name - Unique channel group name. - * @returns `ChannelGroup` entity. - */ - channelGroup(name) { - let channelGroup = this.entities[`${name}_chg`]; - if (!channelGroup) - channelGroup = this.entities[`${name}_chg`] = new ChannelGroup(name, this); - return channelGroup; - } - /** - * Create a `ChannelMetadata` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param id - Unique channel metadata object identifier. - * @returns `ChannelMetadata` entity. - */ - channelMetadata(id) { - let metadata = this.entities[`${id}_chm`]; - if (!metadata) - metadata = this.entities[`${id}_chm`] = new ChannelMetadata(id, this); - return metadata; - } - /** - * Create a `UserMetadata` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param id - Unique user metadata object identifier. - * @returns `UserMetadata` entity. - */ - userMetadata(id) { - let metadata = this.entities[`${id}_um`]; - if (!metadata) - metadata = this.entities[`${id}_um`] = new UserMetadata(id, this); - return metadata; - } - /** - * Create a `DataSyncUser` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param id - Unique DataSync `User` object identifier (used verbatim, so wildcard identifiers - * like `user.*` are supported). - * @returns `DataSyncUser` entity. - */ - dataSyncUser(id) { - let entity = this.entities[`${id}_dsu`]; - if (!entity) - entity = this.entities[`${id}_dsu`] = new DataSyncUser(id, this); - return entity; - } - /** - * Create a `DataSyncChannel` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param id - Unique DataSync `Channel` object identifier (used verbatim, so wildcard identifiers - * like `channel.*` are supported). - * @returns `DataSyncChannel` entity. - */ - dataSyncChannel(id) { - let entity = this.entities[`${id}_dsc`]; - if (!entity) - entity = this.entities[`${id}_dsc`] = new DataSyncChannel(id, this); - return entity; - } - /** - * Create a `DataSyncMembership` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * **Important:** Membership changes are delivered on the data channels of both linked entities - * (the user and the channel identifier), not on the membership identifier — use - * {@link PubNubCore#dataSyncUser dataSyncUser} / {@link PubNubCore#dataSyncChannel - * dataSyncChannel} to observe them. - * - * @param id - Unique DataSync `Membership` object identifier (`{userId}:{channelId}`, used - * verbatim, so wildcard identifiers like `user-123:*` are supported). - * @returns `DataSyncMembership` entity. - */ - dataSyncMembership(id) { - let entity = this.entities[`${id}_dsm`]; - if (!entity) - entity = this.entities[`${id}_dsm`] = new DataSyncMembership(id, this); - return entity; - } - /** - * Create a `DataSyncEntity` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param id - Unique DataSync `Entity` object identifier (used verbatim, so wildcard identifiers - * like `customer.*` are supported). - * @returns `DataSyncEntity` entity. - */ - dataSyncEntity(id) { - let entity = this.entities[`${id}_dse`]; - if (!entity) - entity = this.entities[`${id}_dse`] = new DataSyncEntity(id, this); - return entity; - } - /** - * Create a `DataSyncRelationship` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * **Important:** Relationship changes are delivered on the data channels of both linked entities - * (`entityAId` and `entityBId`), not on the relationship identifier — use - * {@link PubNubCore#dataSyncEntity dataSyncEntity} to observe them. - * - * @param id - Unique DataSync `Relationship` object identifier (used verbatim, so wildcard - * identifiers like `owns.*` are supported). - * @returns `DataSyncRelationship` entity. - */ - dataSyncRelationship(id) { - let entity = this.entities[`${id}_dsr`]; - if (!entity) - entity = this.entities[`${id}_dsr`] = new DataSyncRelationship(id, this); - return entity; - } - /** - * Create subscriptions set object. - * - * @param parameters - Subscriptions set configuration parameters. - */ - subscriptionSet(parameters) { - var _a, _b; - { - // Prepare a list of entities for a set. - const entities = []; - (_a = parameters.channels) === null || _a === void 0 ? void 0 : _a.forEach((name) => entities.push(this.channel(name))); - (_b = parameters.channelGroups) === null || _b === void 0 ? void 0 : _b.forEach((name) => entities.push(this.channelGroup(name))); - return new SubscriptionSet({ client: this, entities, options: parameters.subscriptionOptions }); - } - } - /** - * Schedule request execution. - * - * @internal - * - * @param request - REST API request. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous request execution and response parsing result or `void` in case if - * `callback` provided. - * - * @throws PubNubError in case of request processing error. - */ - sendRequest(request, callback) { - return __awaiter(this, void 0, void 0, function* () { - // Validate user-input. - const validationResult = request.validate(); - if (validationResult) { - const validationError = createValidationError(validationResult); - this.logger.error('PubNub', () => ({ messageType: 'error', message: validationError })); - if (callback) - return callback(validationError, null); - throw new PubNubError('Validation failed, check status for details', validationError); - } - // Complete request configuration. - const transportRequest = request.request(); - const operation = request.operation(); - if ((transportRequest.formData && transportRequest.formData.length > 0) || - operation === RequestOperation$1.PNDownloadFileOperation) { - // Set file upload / download request delay. - transportRequest.timeout = this._configuration.getFileTimeout(); - } - else { - if (operation === RequestOperation$1.PNSubscribeOperation || - operation === RequestOperation$1.PNReceiveMessagesOperation) - transportRequest.timeout = this._configuration.getSubscribeTimeout(); - else - transportRequest.timeout = this._configuration.getTransactionTimeout(); - } - // API request processing status. - const status = { - error: false, - operation, - category: StatusCategory$1.PNAcknowledgmentCategory, - statusCode: 0, - }; - const [sendableRequest, cancellationController] = this.transport.makeSendable(transportRequest); - /** - * **Important:** Because of multiple environments where JS SDK can be used, control over - * cancellation had to be inverted to let the transport provider solve a request cancellation task - * more efficiently. As a result, cancellation controller can be retrieved and used only after - * the request will be scheduled by the transport provider. - */ - request.cancellationController = cancellationController ? cancellationController : null; - return sendableRequest - .then((response) => { - status.statusCode = response.status; - // Handle a special case when request completed but not fully processed by PubNub service. - if (response.status !== 200 && response.status !== 204) { - const responseText = PubNubCore.decoder.decode(response.body); - const contentType = response.headers['content-type']; - if (contentType || contentType.indexOf('javascript') !== -1 || contentType.indexOf('json') !== -1) { - const json = JSON.parse(responseText); - if (typeof json === 'object' && 'error' in json && json.error && typeof json.error === 'object') - status.errorData = json.error; - } - else - status.responseText = responseText; - } - return request.parse(response); - }) - .then((parsed) => { - // Notify callback (if possible). - if (callback) - return callback(status, parsed); - return parsed; - }) - .catch((error) => { - const apiError = !(error instanceof PubNubAPIError) ? PubNubAPIError.create(error) : error; - // Notify callback (if possible). - if (callback) { - if (apiError.category !== StatusCategory$1.PNCancelledCategory) { - this.logger.error('PubNub', () => ({ - messageType: 'error', - message: apiError.toPubNubError(operation, 'REST API request processing error, check status for details'), - })); - } - return callback(apiError.toStatus(operation), null); - } - const pubNubError = apiError.toPubNubError(operation, 'REST API request processing error, check status for details'); - if (apiError.category !== StatusCategory$1.PNCancelledCategory) - this.logger.error('PubNub', () => ({ messageType: 'error', message: pubNubError })); - throw pubNubError; - }); - }); - } - /** - * Unsubscribe from all channels and groups. - * - * @param [isOffline] - Whether `offline` presence should be notified or not. - */ - destroy(isOffline = false) { - this.logger.info('PubNub', 'Destroying PubNub client.'); - { - if (this._globalSubscriptionSet) { - this._globalSubscriptionSet.invalidate(true); - this._globalSubscriptionSet = undefined; - } - Object.values(this.eventHandleCapable).forEach((subscription) => subscription.invalidate(true)); - this.eventHandleCapable = {}; - if (this.subscriptionManager) { - this.subscriptionManager.unsubscribeAll(isOffline); - this.subscriptionManager.disconnect(); - } - else if (this.eventEngine) - this.eventEngine.unsubscribeAll(isOffline); - } - { - if (this.presenceEventEngine) - this.presenceEventEngine.leaveAll(isOffline); - } - } - /** - * Unsubscribe from all channels and groups. - * - * @deprecated Use {@link destroy} method instead. - */ - stop() { - this.logger.warn('PubNub', "'stop' is deprecated, please use 'destroy' instead."); - this.destroy(); - } - /** - * Publish data to a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous publish data response or `void` in case if `callback` provided. - */ - publish(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Publish with parameters:', - })); - const isFireRequest = parameters.replicate === false && parameters.storeInHistory === false; - const request = new PublishRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule() })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `${isFireRequest ? 'Fire' : 'Publish'} success with timetoken: ${response.timetoken}`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Signal data to a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous signal data response or `void` in case if `callback` provided. - */ - signal(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Signal with parameters:', - })); - const request = new SignalRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Publish success with timetoken: ${response.timetoken}`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * `Fire` a data to a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous signal data response or `void` in case if `callback` provided. - * - * @deprecated Use {@link publish} method instead. - */ - fire(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Fire with parameters:', - })); - callback !== null && callback !== void 0 ? callback : (callback = () => { }); - return this.publish(Object.assign(Object.assign({}, parameters), { replicate: false, storeInHistory: false }), callback); - }); - } - // endregion - // -------------------------------------------------------- - // -------------------- Subscribe API --------------------- - // -------------------------------------------------------- - // region Subscribe API - /** - * Global subscription set which supports legacy subscription interface. - * - * @returns Global subscription set. - * - * @internal - */ - get globalSubscriptionSet() { - if (!this._globalSubscriptionSet) - this._globalSubscriptionSet = this.subscriptionSet({}); - return this._globalSubscriptionSet; - } - /** - * Subscription-based current timetoken. - * - * @returns Timetoken based on current timetoken plus diff between current and loop start time. - * - * @internal - */ - get subscriptionTimetoken() { - { - if (this.subscriptionManager) - return this.subscriptionManager.subscriptionTimetoken; - else if (this.eventEngine) - return this.eventEngine.subscriptionTimetoken; - } - return undefined; - } - /** - * Get list of channels on which PubNub client currently subscribed. - * - * @returns List of active channels. - */ - getSubscribedChannels() { - { - if (this.subscriptionManager) - return this.subscriptionManager.subscribedChannels; - else if (this.eventEngine) - return this.eventEngine.getSubscribedChannels(); - } - return []; - } - /** - * Get list of channel groups on which PubNub client currently subscribed. - * - * @returns List of active channel groups. - */ - getSubscribedChannelGroups() { - { - if (this.subscriptionManager) - return this.subscriptionManager.subscribedChannelGroups; - else if (this.eventEngine) - return this.eventEngine.getSubscribedChannelGroups(); - } - return []; - } - /** - * Register an events handler object ({@link Subscription} or {@link SubscriptionSet}) with an active subscription. - * - * @param subscription - {@link Subscription} or {@link SubscriptionSet} object. - * @param [cursor] - Subscription catchup timetoken. - * @param [subscriptions] - List of subscriptions for partial subscription loop update. - * - * @internal - */ - registerEventHandleCapable(subscription, cursor, subscriptions) { - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign(Object.assign({ subscription: subscription }, (cursor ? { cursor } : [])), (subscriptions ? { subscriptions } : {})), - details: `Register event handle capable:`, - })); - if (!this.eventHandleCapable[subscription.state.id]) - this.eventHandleCapable[subscription.state.id] = subscription; - let subscriptionInput; - if (!subscriptions || subscriptions.length === 0) - subscriptionInput = subscription.subscriptionInput(false); - else { - subscriptionInput = new SubscriptionInput({}); - subscriptions.forEach((subscription) => subscriptionInput.add(subscription.subscriptionInput(false))); - } - const parameters = {}; - parameters.channels = subscriptionInput.channels; - parameters.channelGroups = subscriptionInput.channelGroups; - if (cursor) - parameters.timetoken = cursor.timetoken; - if (this.subscriptionManager) - this.subscriptionManager.subscribe(parameters); - else if (this.eventEngine) - this.eventEngine.subscribe(parameters); - } - } - /** - * Unregister an events handler object ({@link Subscription} or {@link SubscriptionSet}) with inactive subscription. - * - * @param subscription - {@link Subscription} or {@link SubscriptionSet} object. - * @param [subscriptions] - List of subscriptions for partial subscription loop update. - * - * @internal - */ - unregisterEventHandleCapable(subscription, subscriptions) { - { - if (!this.eventHandleCapable[subscription.state.id]) - return; - const inUseSubscriptions = []; - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: { subscription: subscription, subscriptions }, - details: `Unregister event handle capable:`, - })); - // Check whether only subscription object has been passed to be unregistered. - let shouldDeleteEventHandler = !subscriptions || subscriptions.length === 0; - // Check whether subscription set is unregistering with all managed Subscription objects, - if (!shouldDeleteEventHandler && - subscription instanceof SubscriptionSet && - subscription.subscriptions.length === (subscriptions === null || subscriptions === void 0 ? void 0 : subscriptions.length)) - shouldDeleteEventHandler = subscription.subscriptions.every((sub) => subscriptions.includes(sub)); - if (shouldDeleteEventHandler) - delete this.eventHandleCapable[subscription.state.id]; - let subscriptionInput; - if (!subscriptions || subscriptions.length === 0) { - subscriptionInput = subscription.subscriptionInput(true); - if (subscriptionInput.isEmpty) - inUseSubscriptions.push(subscription); - } - else { - subscriptionInput = new SubscriptionInput({}); - subscriptions.forEach((subscription) => { - const input = subscription.subscriptionInput(true); - if (input.isEmpty) - inUseSubscriptions.push(subscription); - else - subscriptionInput.add(input); - }); - } - if (inUseSubscriptions.length > 0) { - this.logger.trace('PubNub', () => { - const entities = []; - if (inUseSubscriptions[0] instanceof SubscriptionSet) { - inUseSubscriptions[0].subscriptions.forEach((subscription) => entities.push(subscription.state.entity)); - } - else - inUseSubscriptions.forEach((subscription) => entities.push(subscription.state.entity)); - return { - messageType: 'object', - message: { entities }, - details: `Can't unregister event handle capable because entities still in use:`, - }; - }); - } - if (subscriptionInput.isEmpty) - return; - else { - const _channelGroupsInUse = []; - const _channelsInUse = []; - Object.values(this.eventHandleCapable).forEach((_subscription) => { - const _subscriptionInput = _subscription.subscriptionInput(false); - const _subscriptionChannelGroups = _subscriptionInput.channelGroups; - const _subscriptionChannels = _subscriptionInput.channels; - _channelGroupsInUse.push(...subscriptionInput.channelGroups.filter((channel) => _subscriptionChannelGroups.includes(channel))); - _channelsInUse.push(...subscriptionInput.channels.filter((channel) => _subscriptionChannels.includes(channel))); - }); - if (_channelsInUse.length > 0 || _channelGroupsInUse.length > 0) { - this.logger.trace('PubNub', () => { - const _entitiesInUse = []; - const addEntityIfInUse = (entity) => { - const namesOrIds = entity.subscriptionNames(true); - const checkList = entity.subscriptionType === SubscriptionType.Channel ? _channelsInUse : _channelGroupsInUse; - if (namesOrIds.some((id) => checkList.includes(id))) - _entitiesInUse.push(entity); - }; - Object.values(this.eventHandleCapable).forEach((_subscription) => { - if (_subscription instanceof SubscriptionSet) { - _subscription.subscriptions.forEach((_subscriptionInSet) => { - addEntityIfInUse(_subscriptionInSet.state.entity); - }); - } - else if (_subscription instanceof Subscription) - addEntityIfInUse(_subscription.state.entity); - }); - let details = 'Some entities still in use:'; - if (_channelsInUse.length + _channelGroupsInUse.length === subscriptionInput.length) - details = "Can't unregister event handle capable because entities still in use:"; - return { messageType: 'object', message: { entities: _entitiesInUse }, details }; - }); - subscriptionInput.remove(new SubscriptionInput({ channels: _channelsInUse, channelGroups: _channelGroupsInUse })); - if (subscriptionInput.isEmpty) - return; - } - } - const parameters = {}; - parameters.channels = subscriptionInput.channels; - parameters.channelGroups = subscriptionInput.channelGroups; - if (this.subscriptionManager) - this.subscriptionManager.unsubscribe(parameters); - else if (this.eventEngine) - this.eventEngine.unsubscribe(parameters); - } - } - /** - * Subscribe to specified channels and groups real-time events. - * - * @param parameters - Request configuration parameters. - */ - subscribe(parameters) { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Subscribe with parameters:', - })); - // The addition of a new subscription set into the subscribed global subscription set will update the active - // subscription loop with new channels and groups. - const subscriptionSet = this.subscriptionSet(Object.assign(Object.assign({}, parameters), { subscriptionOptions: { receivePresenceEvents: parameters.withPresence } })); - this.globalSubscriptionSet.addSubscriptionSet(subscriptionSet); - subscriptionSet.dispose(); - const timetoken = typeof parameters.timetoken === 'number' ? `${parameters.timetoken}` : parameters.timetoken; - this.globalSubscriptionSet.subscribe({ timetoken }); - } - } - /** - * Perform subscribe request. - * - * **Note:** Method passed into managers to let them use it when required. - * - * @internal - * - * @param parameters - Request configuration parameters. - * @param callback - Request completion handler callback. - */ - makeSubscribe(parameters, callback) { - { - // `on-demand` query parameter not required for non-SharedWorker environment. - if (!this._configuration.isSharedWorkerEnabled()) - parameters.onDemand = false; - const request = new SubscribeRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); - this.sendRequest(request, (status, result) => { - var _a; - if (this.subscriptionManager && ((_a = this.subscriptionManager.abort) === null || _a === void 0 ? void 0 : _a.identifier) === request.requestIdentifier) - this.subscriptionManager.abort = null; - callback(status, result); - }); - /** - * Allow subscription cancellation. - * - * **Note:** Had to be done after scheduling because the transport provider returns the cancellation - * controller only when schedule new request. - */ - if (this.subscriptionManager) { - // Creating an identifiable abort caller. - const callableAbort = () => request.abort('Cancel long-poll subscribe request'); - callableAbort.identifier = request.requestIdentifier; - this.subscriptionManager.abort = callableAbort; - } - } - } - /** - * Unsubscribe from specified channels and groups real-time events. - * - * @param parameters - Request configuration parameters. - */ - unsubscribe(parameters) { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Unsubscribe with parameters:', - })); - if (!this._globalSubscriptionSet) { - this.logger.debug('PubNub', 'There are no active subscriptions. Ignore.'); - return; - } - const subscriptions = this.globalSubscriptionSet.subscriptions.filter((subscription) => { - var _a, _b; - const subscriptionInput = subscription.subscriptionInput(false); - if (subscriptionInput.isEmpty) - return false; - for (const channel of (_a = parameters.channels) !== null && _a !== void 0 ? _a : []) - if (subscriptionInput.contains(channel)) - return true; - for (const group of (_b = parameters.channelGroups) !== null && _b !== void 0 ? _b : []) - if (subscriptionInput.contains(group)) - return true; - }); - // Removal from the active subscription also will cause `unsubscribe`. - if (subscriptions.length > 0) - this.globalSubscriptionSet.removeSubscriptions(subscriptions); - } - } - /** - * Perform unsubscribe request. - * - * **Note:** Method passed into managers to let them use it when required. - * - * @internal - * - * @param parameters - Request configuration parameters. - * @param callback - Request completion handler callback. - */ - makeUnsubscribe(parameters, callback) { - { - // Filtering out presence channels and groups. - let { channels, channelGroups } = parameters; - // Remove `-pnpres` channels / groups if they not acceptable in the current PubNub client configuration. - if (!this._configuration.getKeepPresenceChannelsInPresenceRequests()) { - if (channelGroups) - channelGroups = channelGroups.filter((channelGroup) => !channelGroup.endsWith('-pnpres')); - if (channels) - channels = channels.filter((channel) => !channel.endsWith('-pnpres')); - } - // Complete immediately request only for presence channels. - if ((channelGroups !== null && channelGroups !== void 0 ? channelGroups : []).length === 0 && (channels !== null && channels !== void 0 ? channels : []).length === 0) { - return callback({ - error: false, - operation: RequestOperation$1.PNUnsubscribeOperation, - category: StatusCategory$1.PNAcknowledgmentCategory, - statusCode: 200, - }); - } - this.sendRequest(new PresenceLeaveRequest({ channels, channelGroups, keySet: this._configuration.keySet }), callback); - } - } - /** - * Unsubscribe from all channels and groups. - */ - unsubscribeAll() { - { - this.logger.debug('PubNub', 'Unsubscribe all channels and groups'); - // Keeping a subscription set instance after invalidation so to make it possible to deliver the expected - // disconnection status. - if (this._globalSubscriptionSet) - this._globalSubscriptionSet.invalidate(false); - Object.values(this.eventHandleCapable).forEach((subscription) => subscription.invalidate(false)); - this.eventHandleCapable = {}; - if (this.subscriptionManager) - this.subscriptionManager.unsubscribeAll(); - else if (this.eventEngine) - this.eventEngine.unsubscribeAll(); - } - } - /** - * Temporarily disconnect from the real-time events stream. - * - * **Note:** `isOffline` is set to `true` only when a client experiences network issues. - * - * @param [isOffline] - Whether `offline` presence should be notified or not. - */ - disconnect(isOffline = false) { - { - this.logger.debug('PubNub', `Disconnect (while offline? ${!!isOffline ? 'yes' : 'no'})`); - if (this.subscriptionManager) - this.subscriptionManager.disconnect(); - else if (this.eventEngine) - this.eventEngine.disconnect(isOffline); - } - } - /** - * Restore connection to the real-time events stream. - * - * @param parameters - Reconnection catch-up configuration. **Note:** available only with the enabled event engine. - */ - reconnect(parameters) { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Reconnect with parameters:', - })); - if (this.subscriptionManager) - this.subscriptionManager.reconnect(); - else if (this.eventEngine) - this.eventEngine.reconnect(parameters !== null && parameters !== void 0 ? parameters : {}); - } - } - /** - * Event engine handshake subscribe. - * - * @internal - * - * @param parameters - Request configuration parameters. - */ - subscribeHandshake(parameters) { - return __awaiter(this, void 0, void 0, function* () { - { - // `on-demand` query parameter not required for non-SharedWorker environment. - if (!this._configuration.isSharedWorkerEnabled()) - parameters.onDemand = false; - if (!parameters.heartbeat) - parameters.heartbeat = this._configuration.getPresenceTimeout(); - const request = new HandshakeSubscribeRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); - const abortUnsubscribe = parameters.abortSignal.subscribe((err) => { - request.abort('Cancel subscribe handshake request'); - }); - /** - * Allow subscription cancellation. - * - * **Note:** Had to be done after scheduling because the transport provider returns the cancellation - * controller only when schedule new request. - */ - const handshakeResponse = this.sendRequest(request); - return handshakeResponse.then((response) => { - abortUnsubscribe(); - return response.cursor; - }); - } - }); - } - /** - * Event engine receive messages subscribe. - * - * @internal - * - * @param parameters - Request configuration parameters. - */ - subscribeReceiveMessages(parameters) { - return __awaiter(this, void 0, void 0, function* () { - { - // `on-demand` query parameter not required for non-SharedWorker environment. - if (!this._configuration.isSharedWorkerEnabled()) - parameters.onDemand = false; - if (!parameters.heartbeat) - parameters.heartbeat = this._configuration.getPresenceTimeout(); - const request = new ReceiveMessagesSubscribeRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); - const abortUnsubscribe = parameters.abortSignal.subscribe((err) => { - request.abort('Cancel long-poll subscribe request'); - }); - /** - * Allow subscription cancellation. - * - * **Note:** Had to be done after scheduling because the transport provider returns the cancellation - * controller only when schedule new request. - */ - const receiveResponse = this.sendRequest(request); - return receiveResponse.then((response) => { - abortUnsubscribe(); - return response; - }); - } - }); - } - /** - * Get reactions to a specific message. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get reactions response or `void` in case if `callback` provided. - */ - getMessageActions(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get message actions with parameters:', - })); - const request = new GetMessageActionsRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get message actions success. Received ${response.data.length} message actions.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Add a reaction to a specific message. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous add a reaction response or `void` in case if `callback` provided. - */ - addMessageAction(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Add message action with parameters:', - })); - const request = new AddMessageActionRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Message action add success. Message action added with timetoken: ${response.data.actionTimetoken}`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Remove a reaction from a specific message. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove a reaction response or `void` in case if `callback` provided. - */ - removeMessageAction(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove message action with parameters:', - })); - const request = new RemoveMessageAction(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Message action remove success. Removed message action with ${parameters.actionTimetoken} timetoken.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Fetch messages history for channels. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous fetch messages response or `void` in case if `callback` provided. - */ - fetchMessages(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Fetch messages with parameters:', - })); - const request = new FetchMessagesRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); - const logResponse = (response) => { - if (!response) - return; - const messagesCount = Object.values(response.channels).reduce((acc, message) => acc + message.length, 0); - this.logger.debug('PubNub', `Fetch messages success. Received ${messagesCount} messages.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Delete messages from the channel history. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous delete messages response or `void` in case if `callback` provided. - * - */ - deleteMessages(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Delete messages with parameters:', - })); - const request = new DeleteMessageRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Delete messages success.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Count messages from the channels' history. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous count messages response or `void` in case if `callback` provided. - */ - messageCounts(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get messages count with parameters:', - })); - const request = new MessageCountRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - const messagesCount = Object.values(response.channels).reduce((acc, messagesCount) => acc + messagesCount, 0); - this.logger.debug('PubNub', `Get messages count success. There are ${messagesCount} messages since provided reference timetoken${parameters.channelTimetokens ? parameters.channelTimetokens.join(',') : ''.length > 1 ? 's' : ''}.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Fetch single channel history. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous fetch channel history response or `void` in case if `callback` provided. - * - * @deprecated - */ - history(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Fetch history with parameters:', - })); - const request = new GetHistoryRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule() })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Fetch history success. Received ${response.messages.length} messages.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Get channel's presence information. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get channel's presence response or `void` in case if `callback` provided. - */ - hereNow(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Here now with parameters:', - })); - const request = new HereNowRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Here now success. There are ${response.totalOccupancy} participants in ${response.totalChannels} channels.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Get user's presence information. - * - * Get list of channels to which `uuid` currently subscribed. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get user's presence response or `void` in case if `callback` provided. - */ - whereNow(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Where now with parameters:', - })); - const request = new WhereNowRequest({ - uuid: (_a = parameters.uuid) !== null && _a !== void 0 ? _a : this._configuration.userId, - keySet: this._configuration.keySet, - }); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Where now success. Currently present in ${response.channels.length} channels.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Get associated user's data for channels and groups. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get user's data response or `void` in case if `callback` provided. - */ - getState(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get presence state with parameters:', - })); - const request = new GetPresenceStateRequest(Object.assign(Object.assign({}, parameters), { uuid: (_a = parameters.uuid) !== null && _a !== void 0 ? _a : this._configuration.userId, keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get presence state success. Received presence state for ${Object.keys(response.channels).length} channels.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Set associated user's data for channels and groups. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set user's data response or `void` in case if `callback` provided. - */ - setState(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b; - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Set presence state with parameters:', - })); - const { keySet, userId: userId } = this._configuration; - const heartbeat = this._configuration.getPresenceTimeout(); - let request; - // Maintain presence information (if required). - if (this._configuration.enableEventEngine && this.presenceState) { - const presenceState = this.presenceState; - (_a = parameters.channels) === null || _a === void 0 ? void 0 : _a.forEach((channel) => (presenceState[channel] = parameters.state)); - if ('channelGroups' in parameters) { - (_b = parameters.channelGroups) === null || _b === void 0 ? void 0 : _b.forEach((group) => (presenceState[group] = parameters.state)); - } - if (this.onPresenceStateChange) - this.onPresenceStateChange(this.presenceState); - } - // Check whether the state should be set with heartbeat or not. - if ('withHeartbeat' in parameters && parameters.withHeartbeat) { - request = new HeartbeatRequest(Object.assign(Object.assign({}, parameters), { keySet, heartbeat })); - } - else { - request = new SetPresenceStateRequest(Object.assign(Object.assign({}, parameters), { keySet, uuid: userId })); - } - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Set presence state success.${request instanceof HeartbeatRequest ? ' Presence state has been set using heartbeat endpoint.' : ''}`); - }; - // Update state used by subscription manager. - if (this.subscriptionManager) { - this.subscriptionManager.setState(parameters); - if (this.onPresenceStateChange) - this.onPresenceStateChange(this.subscriptionManager.presenceState); - } - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - // endregion - // region Change presence state - /** - * Manual presence management. - * - * @param parameters - Desired presence state for a provided list of channels and groups. - */ - presence(parameters) { - var _a; - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Change presence with parameters:', - })); - (_a = this.subscriptionManager) === null || _a === void 0 ? void 0 : _a.changePresence(parameters); - } - } - // endregion - // region Heartbeat - /** - * Announce user presence - * - * @internal - * - * @param parameters - Desired presence state for provided list of channels and groups. - * @param callback - Request completion handler callback. - */ - heartbeat(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Heartbeat with parameters:', - })); - // Filtering out presence channels and groups. - let { channels, channelGroups } = parameters; - // Remove `-pnpres` channels / groups if they not acceptable in the current PubNub client configuration. - if (channelGroups) - channelGroups = channelGroups.filter((channelGroup) => !channelGroup.endsWith('-pnpres')); - if (channels) - channels = channels.filter((channel) => !channel.endsWith('-pnpres')); - // Complete immediately request only for presence channels. - if ((channelGroups !== null && channelGroups !== void 0 ? channelGroups : []).length === 0 && (channels !== null && channels !== void 0 ? channels : []).length === 0) { - const responseStatus = { - error: false, - operation: RequestOperation$1.PNHeartbeatOperation, - category: StatusCategory$1.PNAcknowledgmentCategory, - statusCode: 200, - }; - this.logger.trace('PubNub', 'There are no active subscriptions. Ignore.'); - if (callback) - return callback(responseStatus, {}); - return Promise.resolve(responseStatus); - } - const request = new HeartbeatRequest(Object.assign(Object.assign({}, parameters), { channels: [...new Set(channels)], channelGroups: [...new Set(channelGroups)], keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.trace('PubNub', 'Heartbeat success.'); - }; - const abortUnsubscribe = (_a = parameters.abortSignal) === null || _a === void 0 ? void 0 : _a.subscribe((err) => { - request.abort('Cancel long-poll subscribe request'); - }); - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - if (abortUnsubscribe) - abortUnsubscribe(); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - if (abortUnsubscribe) - abortUnsubscribe(); - return response; - }); - } - }); - } - // endregion - // region Join - /** - * Announce user `join` on specified list of channels and groups. - * - * @internal - * - * @param parameters - List of channels and groups where `join` event should be sent. - */ - join(parameters) { - var _a, _b; - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Join with parameters:', - })); - if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { - this.logger.trace('PubNub', "Ignoring 'join' announcement request."); - return; - } - if (this.presenceEventEngine) - this.presenceEventEngine.join(parameters); - else { - this.heartbeat(Object.assign(Object.assign({ channels: parameters.channels, channelGroups: parameters.groups }, (this._configuration.maintainPresenceState && - this.presenceState && - Object.keys(this.presenceState).length > 0 && { state: this.presenceState })), { heartbeat: this._configuration.getPresenceTimeout() }), () => { }); - } - } - } - /** - * Reconnect presence event engine after network issues. - * - * @param parameters - List of channels and groups where `join` event should be sent. - * - * @internal - */ - presenceReconnect(parameters) { - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Presence reconnect with parameters:', - })); - if (this.presenceEventEngine) - this.presenceEventEngine.reconnect(); - else { - this.heartbeat(Object.assign(Object.assign({ channels: parameters.channels, channelGroups: parameters.groups }, (this._configuration.maintainPresenceState && { state: this.presenceState })), { heartbeat: this._configuration.getPresenceTimeout() }), () => { }); - } - } - } - // endregion - // region Leave - /** - * Announce user `leave` on specified list of channels and groups. - * - * @internal - * - * @param parameters - List of channels and groups where `leave` event should be sent. - */ - leave(parameters) { - var _a, _b, _c; - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Leave with parameters:', - })); - if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { - this.logger.trace('PubNub', "Ignoring 'leave' announcement request."); - return; - } - if (this.presenceEventEngine) - (_c = this.presenceEventEngine) === null || _c === void 0 ? void 0 : _c.leave(parameters); - else - this.makeUnsubscribe({ channels: parameters.channels, channelGroups: parameters.groups }, () => { }); - } - } - /** - * Announce user `leave` on all subscribed channels. - * - * @internal - * - * @param parameters - List of channels and groups where `leave` event should be sent. - */ - leaveAll(parameters = {}) { - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Leave all with parameters:', - })); - if (this.presenceEventEngine) - this.presenceEventEngine.leaveAll(!!parameters.isOffline); - else if (!parameters.isOffline) - this.makeUnsubscribe({ channels: parameters.channels, channelGroups: parameters.groups }, () => { }); - } - } - /** - * Announce user `leave` on disconnection. - * - * @internal - * - * @param parameters - List of channels and groups where `leave` event should be sent. - */ - presenceDisconnect(parameters) { - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Presence disconnect parameters:', - })); - if (this.presenceEventEngine) - this.presenceEventEngine.disconnect(!!parameters.isOffline); - else if (!parameters.isOffline) - this.makeUnsubscribe({ channels: parameters.channels, channelGroups: parameters.groups }, () => { }); - } - } - /** - * Grant token permission. - * - * Generate an access token with requested permissions. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous grant token response or `void` in case if `callback` provided. - */ - grantToken(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('Grant Token error: PAM module disabled'); - }); - } - /** - * Revoke token permission. - * - * @param token - Access token for which permissions should be revoked. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous revoke token response or `void` in case if `callback` provided. - */ - revokeToken(token, callback) { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('Revoke Token error: PAM module disabled'); - }); - } - // endregion - // region Token Manipulation - /** - * Get a current access token. - * - * @returns Previously configured access token using {@link setToken} method. - */ - get token() { - return this.tokenManager && this.tokenManager.getToken(); - } - /** - * Get a current access token. - * - * @returns Previously configured access token using {@link setToken} method. - */ - getToken() { - return this.token; - } - /** - * Set current access token. - * - * @param token - New access token which should be used with next REST API endpoint calls. - */ - set token(token) { - if (this.tokenManager) - this.tokenManager.setToken(token); - if (this.onAuthenticationChange) - this.onAuthenticationChange(token); - } - /** - * Set current access token. - * - * @param token - New access token which should be used with next REST API endpoint calls. - */ - setToken(token) { - this.logger.debug('PubNub', 'Access token updated.'); - this.token = token; - } - /** - * Parse access token. - * - * Parse token to see what permissions token owner has. - * - * @param token - Token which should be parsed. - * - * @returns Token's permissions information for the resources. - */ - parseToken(token) { - this.logger.debug('PubNub', 'Parse access token.'); - return this.tokenManager && this.tokenManager.parseToken(token); - } - /** - * Grant auth key(s) permission. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous grant auth key(s) permissions or `void` in case if `callback` provided. - * - * @deprecated Use {@link grantToken} and {@link setToken} methods instead. - */ - grant(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('Grant error: PAM module disabled'); - }); - } - /** - * Audit auth key(s) permission. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @deprecated - * - * @deprecated Use {@link grantToken} and {@link setToken} methods instead. - */ - audit(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('Grant Permissions error: PAM module disabled'); - }); - } - // endregion - // endregion - // endregion - // -------------------------------------------------------- - // ------------------- App Context API -------------------- - // -------------------------------------------------------- - // region App Context API - /** - * PubNub App Context API group. - */ - get objects() { - return this._objects; - } - // -------------------------------------------------------- - // -------------------- DataSync API --------------------- - // -------------------------------------------------------- - // region DataSync API - /** - * PubNub DataSync API group. - */ - get dataSync() { - return this._dataSync; - } - /** - Fetch a paginated list of User objects. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all User objects response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.getAllUUIDMetadata getAllUUIDMetadata} method instead. - */ - fetchUsers(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'fetchUsers' is deprecated. Use 'pubnub.objects.getAllUUIDMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, - details: `Fetch all User objects with parameters:`, - })); - return this.objects._getAllUUIDMetadata(parametersOrCallback, callback); - } - }); - } - /** - * Fetch User object for a currently configured PubNub client `uuid`. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get User object response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.getUUIDMetadata getUUIDMetadata} method instead. - */ - fetchUser(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'fetchUser' is deprecated. Use 'pubnub.objects.getUUIDMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' - ? { uuid: this.userId } - : parametersOrCallback, - details: `Fetch${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} User object with parameters:`, - })); - return this.objects._getUUIDMetadata(parametersOrCallback, callback); - } - }); - } - /** - * Create a User object. - * - * @param parameters - Request configuration parameters. Will create a User object for a currently - * configured PubNub client `uuid` if not set. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create User object response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.setUUIDMetadata setUUIDMetadata} method instead. - */ - createUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'createUser' is deprecated. Use 'pubnub.objects.setUUIDMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Create User object with parameters:`, - })); - return this.objects._setUUIDMetadata(parameters, callback); - } - }); - } - /** - * Update a User object. - * - * @param parameters - Request configuration parameters. Will update a User object for a currently - * configured PubNub client `uuid` if not set. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update User object response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.setUUIDMetadata setUUIDMetadata} method instead. - */ - updateUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.warn('PubNub', "'updateUser' is deprecated. Use 'pubnub.objects.setUUIDMetadata' instead."); - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Update User object with parameters:`, - })); - return this.objects._setUUIDMetadata(parameters, callback); - } - }); - } - /** - * Remove a specific User object. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous User object removes response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.removeUUIDMetadata removeUUIDMetadata} method instead. - */ - removeUser(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'removeUser' is deprecated. Use 'pubnub.objects.removeUUIDMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' - ? { uuid: this.userId } - : parametersOrCallback, - details: `Remove${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} User object with parameters:`, - })); - return this.objects._removeUUIDMetadata(parametersOrCallback, callback); - } - }); - } - /** - * Fetch a paginated list of Space objects. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all Space objects response or `void` in case if `callback` - * provided. - * - * @deprecated Use {@link PubNubCore#objects.getAllChannelMetadata getAllChannelMetadata} method instead. - */ - fetchSpaces(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'fetchSpaces' is deprecated. Use 'pubnub.objects.getAllChannelMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, - details: `Fetch all Space objects with parameters:`, - })); - return this.objects._getAllChannelMetadata(parametersOrCallback, callback); - } - }); - } - /** - * Fetch a specific Space object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get Space object response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.getChannelMetadata getChannelMetadata} method instead. - */ - fetchSpace(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'fetchSpace' is deprecated. Use 'pubnub.objects.getChannelMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Fetch Space object with parameters:`, - })); - return this.objects._getChannelMetadata(parameters, callback); - } - }); - } - /** - * Create specific Space object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create Space object response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.setChannelMetadata setChannelMetadata} method instead. - */ - createSpace(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'createSpace' is deprecated. Use 'pubnub.objects.setChannelMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Create Space object with parameters:`, - })); - return this.objects._setChannelMetadata(parameters, callback); - } - }); - } - /** - * Update specific Space object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update Space object response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.setChannelMetadata setChannelMetadata} method instead. - */ - updateSpace(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'updateSpace' is deprecated. Use 'pubnub.objects.setChannelMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Update Space object with parameters:`, - })); - return this.objects._setChannelMetadata(parameters, callback); - } - }); - } - /** - * Remove a specific Space object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous Space object remove response or `void` in case if `callback` - * provided. - * - * @deprecated Use {@link PubNubCore#objects.removeChannelMetadata removeChannelMetadata} method instead. - */ - removeSpace(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'removeSpace' is deprecated. Use 'pubnub.objects.removeChannelMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove Space object with parameters:`, - })); - return this.objects._removeChannelMetadata(parameters, callback); - } - }); - } - /** - * Fetch a paginated list of specific Space members or specific User memberships. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get specific Space members or specific User memberships response or - * `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.getChannelMembers getChannelMembers} or - * {@link PubNubCore#objects.getMemberships getMemberships} methods instead. - */ - fetchMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - return this.objects.fetchMemberships(parameters, callback); - }); - } - /** - * Add members to specific Space or memberships specific User. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous add members to specific Space or memberships specific User response or - * `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.setChannelMembers setChannelMembers} or - * {@link PubNubCore#objects.setMemberships setMemberships} methods instead. - */ - addMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - return this.objects.addMemberships(parameters, callback); - }); - } - /** - * Update specific Space members or User memberships. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update Space members or User memberships response or `void` in case - * if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.setChannelMembers setChannelMembers} or - * {@link PubNubCore#objects.setMemberships setMemberships} methods instead. - */ - updateMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'addMemberships' is deprecated. Use 'pubnub.objects.setChannelMembers' or 'pubnub.objects.setMemberships'" + - ' instead.'); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Update memberships with parameters:`, - })); - return this.objects.addMemberships(parameters, callback); - } - }); - } - /** - * Remove User membership. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous memberships modification response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.removeMemberships removeMemberships} or - * {@link PubNubCore#objects.removeChannelMembers removeChannelMembers} methods instead from `objects` API group. - */ - removeMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b, _c; - { - this.logger.warn('PubNub', "'removeMemberships' is deprecated. Use 'pubnub.objects.removeMemberships' or" + - " 'pubnub.objects.removeChannelMembers' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove memberships with parameters:`, - })); - if ('spaceId' in parameters) { - const spaceParameters = parameters; - const requestParameters = { - channel: (_a = spaceParameters.spaceId) !== null && _a !== void 0 ? _a : spaceParameters.channel, - uuids: (_b = spaceParameters.userIds) !== null && _b !== void 0 ? _b : spaceParameters.uuids, - limit: 0, - }; - if (callback) - return this.objects.removeChannelMembers(requestParameters, callback); - return this.objects.removeChannelMembers(requestParameters); - } - const userParameters = parameters; - const requestParameters = { - uuid: userParameters.userId, - channels: (_c = userParameters.spaceIds) !== null && _c !== void 0 ? _c : userParameters.channels, - limit: 0, - }; - if (callback) - return this.objects.removeMemberships(requestParameters, callback); - return this.objects.removeMemberships(requestParameters); - } - }); - } - // endregion - // endregion - // -------------------------------------------------------- - // ----------------- Channel Groups API ------------------- - // -------------------------------------------------------- - // region Channel Groups API - /** - * PubNub Channel Groups API group. - */ - get channelGroups() { - return this._channelGroups; - } - // endregion - // -------------------------------------------------------- - // ---------------- Push Notifications API ----------------- - // -------------------------------------------------------- - // region Push Notifications API - /** - * PubNub Push Notifications API group. - */ - get push() { - return this._push; - } - /** - * Share file to a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous file sharing response or `void` in case if `callback` provided. - */ - sendFile(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - if (!this._configuration.PubNubFile) - throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Send file with parameters:`, - })); - const sendFileRequest = new SendFileRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, PubNubFile: this._configuration.PubNubFile, fileUploadPublishRetryLimit: this._configuration.fileUploadPublishRetryLimit, file: parameters.file, sendRequest: this.sendRequest.bind(this), publishFile: this.publishFile.bind(this), crypto: this._configuration.getCryptoModule(), cryptography: this.cryptography ? this.cryptography : undefined })); - const status = { - error: false, - operation: RequestOperation$1.PNPublishFileOperation, - category: StatusCategory$1.PNAcknowledgmentCategory, - statusCode: 0, - }; - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Send file success. File shared with ${response.id} ID.`); - }; - return sendFileRequest - .process() - .then((response) => { - status.statusCode = response.status; - logResponse(response); - if (callback) - return callback(status, response); - return response; - }) - .catch((error) => { - let errorStatus; - if (error instanceof PubNubError) - errorStatus = error.status; - else if (error instanceof PubNubAPIError) - errorStatus = error.toStatus(status.operation); - this.logger.error('PubNub', () => ({ - messageType: 'error', - message: new PubNubError('File sending error. Check status for details', errorStatus), - })); - // Notify callback (if possible). - if (callback && errorStatus) - callback(errorStatus, null); - throw new PubNubError('REST API request processing error. Check status for details', errorStatus); - }); - } - }); - } - /** - * Publish file message to a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous publish file message response or `void` in case if `callback` provided. - */ - publishFile(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - if (!this._configuration.PubNubFile) - throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Publish file message with parameters:`, - })); - const request = new PublishFileMessageRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule() })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Publish file message success. File message published with timetoken: ${response.timetoken}`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Retrieve list of shared files in specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous shared files list response or `void` in case if `callback` provided. - */ - listFiles(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `List files with parameters:`, - })); - const request = new FilesListRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `List files success. There are ${response.count} uploaded files.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - // endregion - // region Get Download Url - /** - * Get file download Url. - * - * @param parameters - Request configuration parameters. - * - * @returns File download Url. - */ - getFileUrl(parameters) { - var _a; - { - const request = this.transport.request(new GetFileDownloadUrlRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })).request()); - const query = (_a = request.queryParameters) !== null && _a !== void 0 ? _a : {}; - const queryString = Object.keys(query) - .map((key) => { - const queryValue = query[key]; - if (!Array.isArray(queryValue)) - return `${key}=${encodeString(queryValue)}`; - return queryValue.map((value) => `${key}=${encodeString(value)}`).join('&'); - }) - .join('&'); - return `${request.origin}${request.path}?${queryString}`; - } - } - /** - * Download a shared file from a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous download shared file response or `void` in case if `callback` provided. - */ - downloadFile(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - if (!this._configuration.PubNubFile) - throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Download file with parameters:`, - })); - const request = new DownloadFileRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, PubNubFile: this._configuration.PubNubFile, cryptography: this.cryptography ? this.cryptography : undefined, crypto: this._configuration.getCryptoModule() })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Download file success.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return (yield this.sendRequest(request).then((response) => { - logResponse(response); - return response; - })); - } - }); - } - /** - * Delete a shared file from a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous delete shared file response or `void` in case if `callback` provided. - */ - deleteFile(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Delete file with parameters:`, - })); - const request = new DeleteFileRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Delete file success. Deleted file with ${parameters.id} ID.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - Get current high-precision timetoken. - * - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get current timetoken response or `void` in case if `callback` provided. - */ - time(callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', 'Get service time.'); - const request = new TimeRequest(); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get service time success. Current timetoken: ${response.timetoken}`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - // endregion - // -------------------------------------------------------- - // -------------------- Event emitter --------------------- - // -------------------------------------------------------- - // region Event emitter - /** - * Emit received a status update. - * - * Use global and local event dispatchers to deliver a status object. - * - * @param status - Status object which should be emitted through the listeners. - * - * @internal - */ - emitStatus(status) { - var _a; - (_a = this.eventDispatcher) === null || _a === void 0 ? void 0 : _a.handleStatus(status); - } - /** - * Emit receiver real-time event. - * - * Use global and local event dispatchers to deliver an event object. - * - * @param cursor - Next subscription loop timetoken. - * @param event - Event object which should be emitted through the listeners. - * - * @internal - */ - emitEvent(cursor, event) { - var _a; - { - if (this._globalSubscriptionSet) - this._globalSubscriptionSet.handleEvent(cursor, event); - (_a = this.eventDispatcher) === null || _a === void 0 ? void 0 : _a.handleEvent(event); - Object.values(this.eventHandleCapable).forEach((eventHandleCapable) => { - if (eventHandleCapable !== this._globalSubscriptionSet) - eventHandleCapable.handleEvent(cursor, event); - }); - } - } - /** - * Set a connection status change event handler. - * - * @param listener - Listener function, which will be called each time when the connection status changes. - */ - set onStatus(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onStatus = listener; - } - } - /** - * Set a new message handler. - * - * @param listener - Listener function, which will be called each time when a new message - * is received from the real-time network. - */ - set onMessage(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onMessage = listener; - } - } - /** - * Set a new presence events handler. - * - * @param listener - Listener function, which will be called each time when a new - * presence event is received from the real-time network. - */ - set onPresence(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onPresence = listener; - } - } - /** - * Set a new signal handler. - * - * @param listener - Listener function, which will be called each time when a new signal - * is received from the real-time network. - */ - set onSignal(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onSignal = listener; - } - } - /** - * Set a new app context event handler. - * - * @param listener - Listener function, which will be called each time when a new - * app context event is received from the real-time network. - */ - set onObjects(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onObjects = listener; - } - } - /** - * Set a new message reaction event handler. - * - * @param listener - Listener function, which will be called each time when a - * new message reaction event is received from the real-time network. - */ - set onMessageAction(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onMessageAction = listener; - } - } - /** - * Set a new file handler. - * - * @param listener - Listener function, which will be called each time when a new file - * is received from the real-time network. - */ - set onFile(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onFile = listener; - } - } - /** - * Set a new DataSync event handler. - * - * @param listener - Listener function, which will be called each time when a new - * DataSync event is received from the real-time network. - */ - set onDataSync(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onDataSync = listener; - } - } - /** - * Set events handler. - * - * @param listener - Events listener configuration object, which lets specify handlers for multiple - * types of events. - */ - addListener(listener) { - { - if (this.eventDispatcher) { - this.eventDispatcher.addListener(listener); - } - } - } - /** - * Remove real-time event listener. - * - * @param listener - Event listener configuration, which should be removed from the list of notified - * listeners. **Important:** Should be the same object which has been passed to the - * {@link addListener}. - */ - removeListener(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.removeListener(listener); - } - } - /** - * Clear all real-time event listeners. - */ - removeAllListeners() { - { - if (this.eventDispatcher) - this.eventDispatcher.removeAllListeners(); - } - } - // endregion - // -------------------------------------------------------- - // ------------------ Cryptography API -------------------- - // -------------------------------------------------------- - // region Cryptography - // region Common - /** - * Encrypt data. - * - * @param data - Stringified data which should be encrypted using `CryptoModule`. - * @param [customCipherKey] - Cipher key which should be used to encrypt data. **Deprecated:** - * use {@link Configuration#cryptoModule|cryptoModule} instead. - * - * @returns Data encryption result as a string. - * - * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. - */ - encrypt(data, customCipherKey) { - this.logger.warn('PubNub', "'encrypt' is deprecated. Use cryptoModule instead."); - const cryptoModule = this._configuration.getCryptoModule(); - if (!customCipherKey && cryptoModule && typeof data === 'string') { - const encrypted = cryptoModule.encrypt(data); - return typeof encrypted === 'string' ? encrypted : encode(encrypted); - } - if (!this.crypto) - throw new Error('Encryption error: cypher key not set'); - { - return this.crypto.encrypt(data, customCipherKey); - } - } - /** - * Decrypt data. - * - * @param data - Stringified data which should be encrypted using `CryptoModule`. - * @param [customCipherKey] - Cipher key which should be used to decrypt data. **Deprecated:** - * use {@link Configuration#cryptoModule|cryptoModule} instead. - * - * @returns Data decryption result as an object. - * - * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. - */ - decrypt(data, customCipherKey) { - this.logger.warn('PubNub', "'decrypt' is deprecated. Use cryptoModule instead."); - const cryptoModule = this._configuration.getCryptoModule(); - if (!customCipherKey && cryptoModule) { - const decrypted = cryptoModule.decrypt(data); - return decrypted instanceof ArrayBuffer ? JSON.parse(new TextDecoder().decode(decrypted)) : decrypted; - } - if (!this.crypto) - throw new Error('Decryption error: cypher key not set'); - { - return this.crypto.decrypt(data, customCipherKey); - } - } - /** - * Encrypt file content. - * - * @param keyOrFile - Cipher key which should be used to encrypt data or file which should be - * encrypted using `CryptoModule`. - * @param [file] - File which should be encrypted using legacy cryptography. - * - * @returns Asynchronous file encryption result. - * - * @throws Error if a source file isn't provided. - * @throws File constructor not provided. - * @throws Crypto module is missing (if non-legacy flow used). - * - * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. - */ - encryptFile(keyOrFile, file) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - if (typeof keyOrFile !== 'string') - file = keyOrFile; - if (!file) - throw new Error('File encryption error. Source file is missing.'); - if (!this._configuration.PubNubFile) - throw new Error('File encryption error. File constructor not configured.'); - if (typeof keyOrFile !== 'string' && !this._configuration.getCryptoModule()) - throw new Error('File encryption error. Crypto module not configured.'); - if (typeof keyOrFile === 'string') { - if (!this.cryptography) - throw new Error('File encryption error. File encryption not available'); - return this.cryptography.encryptFile(keyOrFile, file, this._configuration.PubNubFile); - } - return (_a = this._configuration.getCryptoModule()) === null || _a === void 0 ? void 0 : _a.encryptFile(file, this._configuration.PubNubFile); - }); - } - /** - * Decrypt file content. - * - * @param keyOrFile - Cipher key which should be used to decrypt data or file which should be - * decrypted using `CryptoModule`. - * @param [file] - File which should be decrypted using legacy cryptography. - * - * @returns Asynchronous file decryption result. - * - * @throws Error if source file isn't provided. - * @throws File constructor not provided. - * @throws Crypto module is missing (if non-legacy flow used). - * - * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. - */ - decryptFile(keyOrFile, file) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - if (typeof keyOrFile !== 'string') - file = keyOrFile; - if (!file) - throw new Error('File encryption error. Source file is missing.'); - if (!this._configuration.PubNubFile) - throw new Error('File decryption error. File constructor' + ' not configured.'); - if (typeof keyOrFile === 'string' && !this._configuration.getCryptoModule()) - throw new Error('File decryption error. Crypto module not configured.'); - if (typeof keyOrFile === 'string') { - if (!this.cryptography) - throw new Error('File decryption error. File decryption not available'); - return this.cryptography.decryptFile(keyOrFile, file, this._configuration.PubNubFile); - } - return (_a = this._configuration.getCryptoModule()) === null || _a === void 0 ? void 0 : _a.decryptFile(file, this._configuration.PubNubFile); - }); - } - } - /** - * {@link ArrayBuffer} to {@link string} decoder. - * - * @internal - */ - PubNubCore.decoder = new TextDecoder(); - // -------------------------------------------------------- - // ----------------------- Static ------------------------- - // -------------------------------------------------------- - // region Static - /** - * Type of REST API endpoint which reported status. - */ - PubNubCore.OPERATIONS = RequestOperation$1; - /** - * API call status category. - */ - PubNubCore.CATEGORIES = StatusCategory$1; - /** - * Enum with API endpoint groups which can be used with retry policy to set up exclusions (which shouldn't be - * retried). - */ - PubNubCore.Endpoint = Endpoint; - /** - * Exponential retry policy constructor. - */ - PubNubCore.ExponentialRetryPolicy = RetryPolicy.ExponentialRetryPolicy; - /** - * Linear retry policy constructor. - */ - PubNubCore.LinearRetryPolicy = RetryPolicy.LinearRetryPolicy; - /** - * Disabled / inactive retry policy. - * - * **Note:** By default `ExponentialRetryPolicy` is set for subscribe requests and this one can be used to disable - * retry policy for all requests (setting `undefined` for retry configuration will set default policy). - */ - PubNubCore.NoneRetryPolicy = RetryPolicy.None; - /** - * Available minimum log levels. - */ - PubNubCore.LogLevel = LogLevel; - - /** - * Cbor decoder module. - * - * @internal - */ - /** - * CBOR data decoder. - * - * @internal - */ - class Cbor { - constructor(decode, base64ToBinary) { - this.decode = decode; - this.base64ToBinary = base64ToBinary; - } - /** - * Decode CBOR base64-encoded object. - * - * @param tokenString - Base64-encoded token. - * - * @returns Token object decoded from CBOR. - */ - decodeToken(tokenString) { - let padding = ''; - if (tokenString.length % 4 === 3) - padding = '='; - else if (tokenString.length % 4 === 2) - padding = '=='; - const cleaned = tokenString.replace(/-/gi, '+').replace(/_/gi, '/') + padding; - const result = this.decode(this.base64ToBinary(cleaned)); - return typeof result === 'object' ? result : undefined; - } - } - - /* eslint no-bitwise: ["error", { "allow": ["~", "&", ">>"] }] */ - /* global navigator */ - /** - * PubNub client for browser platform. - */ - class PubNub extends PubNubCore { - /** - * Create and configure the PubNub client core. - * - * @param configuration - User-provided PubNub client configuration. - * - * @returns Configured and ready to use PubNub client. - */ - constructor(configuration) { - var _a; - const sharedWorkerRequested = configuration.subscriptionWorkerUrl !== undefined; - const configurationCopy = setDefaults(configuration); - const platformConfiguration = Object.assign(Object.assign({}, configurationCopy), { sdkFamily: 'Web' }); - platformConfiguration.PubNubFile = PubNubFile; - // Prepare full client configuration. - const clientConfiguration = makeConfiguration(platformConfiguration, (cryptoConfiguration) => { - if (!cryptoConfiguration.cipherKey) - return undefined; - { - const cryptoModule = new WebCryptoModule({ - default: new LegacyCryptor(Object.assign(Object.assign({}, cryptoConfiguration), (!cryptoConfiguration.logger ? { logger: clientConfiguration.logger() } : {}))), - cryptors: [new AesCbcCryptor({ cipherKey: cryptoConfiguration.cipherKey })], - }); - return cryptoModule; - } - }); - if (configuration.subscriptionWorkerLogVerbosity) - configuration.subscriptionWorkerLogLevel = LogLevel.Debug; - else if (configuration.subscriptionWorkerLogLevel === undefined) - configuration.subscriptionWorkerLogLevel = LogLevel.None; - if (configuration.subscriptionWorkerLogVerbosity !== undefined) { - clientConfiguration - .logger() - .warn('Configuration', "'subscriptionWorkerLogVerbosity' is deprecated. Use 'subscriptionWorkerLogLevel' instead."); - } - { - // Ensure that the logger has been passed to the user-provided crypto module. - if (clientConfiguration.getCryptoModule()) - clientConfiguration.getCryptoModule().logger = clientConfiguration.logger(); - } - // Prepare Token manager. - let tokenManager; - { - tokenManager = new TokenManager(new Cbor((arrayBuffer) => stringifyBufferKeys(CborReader.decode(arrayBuffer)), decode)); - } - // Legacy crypto (legacy data encryption / decryption and request signature support). - let crypto; - { - if (clientConfiguration.getCipherKey() || clientConfiguration.secretKey) { - crypto = new Crypto({ - secretKey: clientConfiguration.secretKey, - cipherKey: clientConfiguration.getCipherKey(), - useRandomIVs: clientConfiguration.getUseRandomIVs(), - customEncrypt: clientConfiguration.getCustomEncrypt(), - customDecrypt: clientConfiguration.getCustomDecrypt(), - logger: clientConfiguration.logger(), - }); - } - } - // Settings change handlers - let heartbeatIntervalChangeHandler = () => { }; - let presenceStateChangeHandler = () => { }; - let authenticationChangeHandler = () => { }; - let userIdChangeHandler = () => { }; - let cryptography; - cryptography = new WebCryptography(); - // Setup transport provider. - let transport = new WebTransport(clientConfiguration.logger(), platformConfiguration.transport); - { - if (configurationCopy.subscriptionWorkerUrl) { - try { - // Inject subscription worker into the transport provider stack. - const middleware = new SubscriptionWorkerMiddleware({ - clientIdentifier: clientConfiguration._instanceId, - subscriptionKey: clientConfiguration.subscribeKey, - userId: clientConfiguration.getUserId(), - workerUrl: configurationCopy.subscriptionWorkerUrl, - sdkVersion: clientConfiguration.getVersion(), - heartbeatInterval: clientConfiguration.getHeartbeatInterval(), - announceSuccessfulHeartbeats: clientConfiguration.announceSuccessfulHeartbeats, - announceFailedHeartbeats: clientConfiguration.announceFailedHeartbeats, - workerOfflineClientsCheckInterval: platformConfiguration.subscriptionWorkerOfflineClientsCheckInterval, - workerUnsubscribeOfflineClients: platformConfiguration.subscriptionWorkerUnsubscribeOfflineClients, - workerLogLevel: platformConfiguration.subscriptionWorkerLogLevel, - tokenManager, - transport, - logger: clientConfiguration.logger(), - }); - presenceStateChangeHandler = (state) => middleware.onPresenceStateChange(state); - heartbeatIntervalChangeHandler = (interval) => middleware.onHeartbeatIntervalChange(interval); - authenticationChangeHandler = (auth) => middleware.onTokenChange(auth); - userIdChangeHandler = (userId) => middleware.onUserIdChange(userId); - transport = middleware; - if (configurationCopy.subscriptionWorkerUnsubscribeOfflineClients && - typeof window !== 'undefined' && - window.addEventListener) { - window.addEventListener('pagehide', (event) => { - if (!event.persisted) - middleware.terminate(); - }, { once: true }); - } - } - catch (e) { - clientConfiguration.logger().error('PubNub', () => ({ - messageType: 'error', - message: e, - })); - } - } - else if (sharedWorkerRequested) { - clientConfiguration - .logger() - .warn('PubNub', 'SharedWorker not supported in this browser. Fallback to the original transport.'); - } - } - const transportMiddleware = new PubNubMiddleware({ - clientConfiguration, - tokenManager, - transport, - }); - super({ - configuration: clientConfiguration, - transport: transportMiddleware, - cryptography, - tokenManager, - crypto, - }); - /** - * PubNub File constructor. - */ - this.File = PubNubFile; - this.onHeartbeatIntervalChange = heartbeatIntervalChangeHandler; - this.onAuthenticationChange = authenticationChangeHandler; - this.onPresenceStateChange = presenceStateChangeHandler; - this.onUserIdChange = userIdChangeHandler; - { - if (transport instanceof SubscriptionWorkerMiddleware) { - transport.emitStatus = this.emitStatus.bind(this); - const disconnect = this.disconnect.bind(this); - this.disconnect = (isOffline) => { - transport.disconnect(); - disconnect(); - }; - } - } - // `window` is unavailable in DOM-less contexts (e.g. MV3 service workers); only attach network - // listeners when a `window` with event support actually exists. - if (((_a = configuration.listenToBrowserNetworkEvents) !== null && _a !== void 0 ? _a : true) && - typeof window !== 'undefined' && - window.addEventListener) { - window.addEventListener('offline', () => { - this.networkDownDetected(); - }); - window.addEventListener('online', () => { - this.networkUpDetected(); - }); - } - } - networkDownDetected() { - this.logger.debug('PubNub', 'Network down detected'); - this.emitStatus({ category: PubNub.CATEGORIES.PNNetworkDownCategory }); - if (this._configuration.restore) - this.disconnect(true); - else - this.destroy(true); - } - networkUpDetected() { - this.logger.debug('PubNub', 'Network up detected'); - this.emitStatus({ category: PubNub.CATEGORIES.PNNetworkUpCategory }); - this.reconnect(); - } - } - /** - * Data encryption / decryption module constructor. - */ - PubNub.CryptoModule = WebCryptoModule ; - - return PubNub; - -})); + }; + + /** + * Crypto module. + */ + class AbstractCryptoModule { + // -------------------------------------------------------- + // --------------- Convenience functions ------------------ + // -------------------------------------------------------- + // region Convenience functions + /** + * Construct crypto module with legacy cryptor for encryption and both legacy and AES-CBC + * cryptors for decryption. + * + * @param config Cryptors configuration options. + * + * @returns Crypto module which encrypts data using legacy cryptor. + * + * @throws Error if `config.cipherKey` not set. + * + * @deprecated Use {@link aesCbcCryptoModule} for new applications. + */ + static legacyCryptoModule(config) { + throw new Error('Should be implemented by concrete crypto module implementation.'); + } + /** + * Construct crypto module with AES-CBC cryptor for encryption and both AES-CBC and legacy + * cryptors for decryption. + * + * @param config Cryptors configuration options. + * + * @returns Crypto module which encrypts data using AES-CBC cryptor. + * + * @throws Error if `config.cipherKey` not set. + */ + static aesCbcCryptoModule(config) { + throw new Error('Should be implemented by concrete crypto module implementation.'); + } + // endregion + constructor(configuration) { + var _a; + this.defaultCryptor = configuration.default; + this.cryptors = (_a = configuration.cryptors) !== null && _a !== void 0 ? _a : []; + } + /** + * Assign registered loggers' manager. + * + * @param _logger - Registered loggers' manager. + * + * @internal + */ + set logger(_logger) { + throw new Error('Method not implemented.'); + } + // endregion + // -------------------------------------------------------- + // ----------------------- Helpers ------------------------ + // -------------------------------------------------------- + // region Helpers + /** + * Retrieve list of module's cryptors. + * + * @internal + */ + getAllCryptors() { + return [this.defaultCryptor, ...this.cryptors]; + } + // endregion + /** + * Serialize crypto module information to string. + * + * @returns Serialized crypto module information. + */ + toString() { + return `AbstractCryptoModule { default: ${this.defaultCryptor.toString()}, cryptors: [${this.cryptors.map((c) => c.toString()).join(', ')}]}`; + } + } + /** + * `String` to {@link ArrayBuffer} response decoder. + * + * @internal + */ + AbstractCryptoModule.encoder = new TextEncoder(); + /** + * {@link ArrayBuffer} to {@link string} decoder. + * + * @internal + */ + AbstractCryptoModule.decoder = new TextDecoder(); + + /* global File, FileReader */ + /** + * Browser {@link PubNub} File object module. + */ + // endregion + /** + * Web implementation for {@link PubNub} File object. + * + * **Important:** Class should implement constructor and class fields from {@link PubNubFileConstructor}. + */ + class PubNubFile { + // endregion + static create(file) { + return new PubNubFile(file); + } + constructor(file) { + let contentLength; + let fileMimeType; + let fileName; + let fileData; + if (file instanceof File) { + fileData = file; + fileName = file.name; + fileMimeType = file.type; + contentLength = file.size; + } + else if ('data' in file) { + const contents = file.data; + fileMimeType = file.mimeType; + fileName = file.name; + fileData = new File([contents], fileName, { type: fileMimeType }); + contentLength = fileData.size; + } + if (fileData === undefined) + throw new Error("Couldn't construct a file out of supplied options."); + if (fileName === undefined) + throw new Error("Couldn't guess filename out of the options. Please provide one."); + if (contentLength) + this.contentLength = contentLength; + this.mimeType = fileMimeType; + this.data = fileData; + this.name = fileName; + } + /** + * Convert {@link PubNub} File object content to {@link Buffer}. + * + * @throws Error because {@link Buffer} not available in browser environment. + */ + toBuffer() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('This feature is only supported in Node.js environments.'); + }); + } + /** + * Convert {@link PubNub} File object content to {@link ArrayBuffer}. + * + * @returns Asynchronous results of conversion to the {@link ArrayBuffer}. + */ + toArrayBuffer() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.addEventListener('load', () => { + if (reader.result instanceof ArrayBuffer) + return resolve(reader.result); + }); + reader.addEventListener('error', () => reject(reader.error)); + reader.readAsArrayBuffer(this.data); + }); + }); + } + /** + * Convert {@link PubNub} File object content to {@link string}. + * + * @returns Asynchronous results of conversion to the {@link string}. + */ + toString() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.addEventListener('load', () => { + if (typeof reader.result === 'string') { + return resolve(reader.result); + } + }); + reader.addEventListener('error', () => { + reject(reader.error); + }); + reader.readAsBinaryString(this.data); + }); + }); + } + /** + * Convert {@link PubNub} File object content to {@link Readable} stream. + * + * @throws Error because {@link Readable} stream not available in browser environment. + */ + toStream() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('This feature is only supported in Node.js environments.'); + }); + } + /** + * Convert {@link PubNub} File object content to {@link File}. + * + * @returns Asynchronous results of conversion to the {@link File}. + */ + toFile() { + return __awaiter(this, void 0, void 0, function* () { + return this.data; + }); + } + /** + * Convert {@link PubNub} File object content to file `Uri`. + * + * @throws Error because file `Uri` not available in browser environment. + */ + toFileUri() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('This feature is only supported in React Native environments.'); + }); + } + /** + * Convert {@link PubNub} File object content to {@link Blob}. + * + * @returns Asynchronous results of conversion to the {@link Blob}. + */ + toBlob() { + return __awaiter(this, void 0, void 0, function* () { + return this.data; + }); + } + } + // region Class properties + /** + * Whether {@link Blob} data supported by platform or not. + */ + PubNubFile.supportsBlob = typeof Blob !== 'undefined'; + /** + * Whether {@link File} data supported by platform or not. + */ + PubNubFile.supportsFile = typeof File !== 'undefined'; + /** + * Whether {@link Buffer} data supported by platform or not. + */ + PubNubFile.supportsBuffer = false; + /** + * Whether {@link Stream} data supported by platform or not. + */ + PubNubFile.supportsStream = false; + /** + * Whether {@link String} data supported by platform or not. + */ + PubNubFile.supportsString = true; + /** + * Whether {@link ArrayBuffer} supported by platform or not. + */ + PubNubFile.supportsArrayBuffer = true; + /** + * Whether {@link PubNub} File object encryption supported or not. + */ + PubNubFile.supportsEncryptFile = true; + /** + * Whether `File Uri` data supported by platform or not. + */ + PubNubFile.supportsFileUri = false; + + /** + * Base64 support module. + * + * @internal + */ + const BASE64_CHARMAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + /** + * Decode a Base64 encoded string. + * + * @param paddedInput Base64 string with padding + * @returns ArrayBuffer with decoded data + * + * @internal + */ + function decode(paddedInput) { + // Remove up to last two equal signs. + const input = paddedInput.replace(/==?$/, ''); + const outputLength = Math.floor((input.length / 4) * 3); + // Prepare output buffer. + const data = new ArrayBuffer(outputLength); + const view = new Uint8Array(data); + let cursor = 0; + /** + * Returns the next integer representation of a sixtet of bytes from the input + * @returns sixtet of bytes + */ + function nextSixtet() { + const char = input.charAt(cursor++); + const index = BASE64_CHARMAP.indexOf(char); + if (index === -1) { + throw new Error(`Illegal character at ${cursor}: ${input.charAt(cursor - 1)}`); + } + return index; + } + for (let i = 0; i < outputLength; i += 3) { + // Obtain four sixtets + const sx1 = nextSixtet(); + const sx2 = nextSixtet(); + const sx3 = nextSixtet(); + const sx4 = nextSixtet(); + // Encode them as three octets + const oc1 = ((sx1 & 0b00111111) << 2) | (sx2 >> 4); + const oc2 = ((sx2 & 0b00001111) << 4) | (sx3 >> 2); + const oc3 = ((sx3 & 0b00000011) << 6) | (sx4 >> 0); + view[i] = oc1; + // Skip padding bytes. + if (sx3 != 64) + view[i + 1] = oc2; + if (sx4 != 64) + view[i + 2] = oc3; + } + return data; + } + /** + * Encode `ArrayBuffer` as a Base64 encoded string. + * + * @param input ArrayBuffer with source data. + * @returns Base64 string with padding. + * + * @internal + */ + function encode(input) { + let base64 = ''; + const encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + const bytes = new Uint8Array(input); + const byteLength = bytes.byteLength; + const byteRemainder = byteLength % 3; + const mainLength = byteLength - byteRemainder; + let a, b, c, d; + let chunk; + // Main loop deals with bytes in chunks of 3 + for (let i = 0; i < mainLength; i = i + 3) { + // Combine the three bytes into a single integer + chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; + // Use bitmasks to extract 6-bit segments from the triplet + a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18 + b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12 + c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6 + d = chunk & 63; // 63 = 2^6 - 1 + // Convert the raw binary segments to the appropriate ASCII encoding + base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]; + } + // Deal with the remaining bytes and padding + if (byteRemainder == 1) { + chunk = bytes[mainLength]; + a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2 + // Set the 4 least significant bits to zero + b = (chunk & 3) << 4; // 3 = 2^2 - 1 + base64 += encodings[a] + encodings[b] + '=='; + } + else if (byteRemainder == 2) { + chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]; + a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10 + b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4 + // Set the 2 least significant bits to zero + c = (chunk & 15) << 2; // 15 = 2^4 - 1 + base64 += encodings[a] + encodings[b] + encodings[c] + '='; + } + return base64; + } + + /** + * Request processing status categories. + */ + var StatusCategory; + (function (StatusCategory) { + /** + * Call failed when network was unable to complete the call. + */ + StatusCategory["PNNetworkIssuesCategory"] = "PNNetworkIssuesCategory"; + /** + * Network call timed out. + */ + StatusCategory["PNTimeoutCategory"] = "PNTimeoutCategory"; + /** + * Request has been cancelled. + */ + StatusCategory["PNCancelledCategory"] = "PNCancelledCategory"; + /** + * Server responded with bad response. + */ + StatusCategory["PNBadRequestCategory"] = "PNBadRequestCategory"; + /** + * Server responded with access denied. + */ + StatusCategory["PNAccessDeniedCategory"] = "PNAccessDeniedCategory"; + /** + * Incomplete parameters provided for used endpoint. + */ + StatusCategory["PNValidationErrorCategory"] = "PNValidationErrorCategory"; + /** + * PubNub request acknowledgment status. + * + * Some API endpoints respond with request processing status w/o useful data. + */ + StatusCategory["PNAcknowledgmentCategory"] = "PNAcknowledgmentCategory"; + /** + * PubNub service or intermediate "actor" returned unexpected response. + * + * There can be few sources of unexpected return with success code: + * - proxy server / VPN; + * - Wi-Fi hotspot authorization page. + */ + StatusCategory["PNMalformedResponseCategory"] = "PNMalformedResponseCategory"; + /** + * Server can't process request. + * + * There can be few sources of unexpected return with success code: + * - potentially an ongoing incident; + * - proxy server / VPN. + */ + StatusCategory["PNServerErrorCategory"] = "PNServerErrorCategory"; + /** + * Something strange happened; please check the logs. + */ + StatusCategory["PNUnknownCategory"] = "PNUnknownCategory"; + // -------------------------------------------------------- + // --------------------- Network status ------------------- + // -------------------------------------------------------- + /** + * SDK will announce when the network appears to be connected again. + */ + StatusCategory["PNNetworkUpCategory"] = "PNNetworkUpCategory"; + /** + * SDK will announce when the network appears to down. + */ + StatusCategory["PNNetworkDownCategory"] = "PNNetworkDownCategory"; + // -------------------------------------------------------- + // -------------------- Real-time events ------------------ + // -------------------------------------------------------- + /** + * PubNub client reconnected to the real-time updates stream. + */ + StatusCategory["PNReconnectedCategory"] = "PNReconnectedCategory"; + /** + * PubNub client connected to the real-time updates stream. + */ + StatusCategory["PNConnectedCategory"] = "PNConnectedCategory"; + /** + * Set of active channels and groups has been changed. + */ + StatusCategory["PNSubscriptionChangedCategory"] = "PNSubscriptionChangedCategory"; + /** + * Received real-time updates exceed specified threshold. + * + * After temporary disconnection and catchup, this category means that potentially some + * real-time updates have been pushed into `storage` and need to be requested separately. + */ + StatusCategory["PNRequestMessageCountExceededCategory"] = "PNRequestMessageCountExceededCategory"; + /** + * PubNub client disconnected from the real-time updates streams. + */ + StatusCategory["PNDisconnectedCategory"] = "PNDisconnectedCategory"; + /** + * PubNub client wasn't able to connect to the real-time updates streams. + */ + StatusCategory["PNConnectionErrorCategory"] = "PNConnectionErrorCategory"; + /** + * PubNub client unexpectedly disconnected from the real-time updates streams. + */ + StatusCategory["PNDisconnectedUnexpectedlyCategory"] = "PNDisconnectedUnexpectedlyCategory"; + // -------------------------------------------------------- + // ------------------ Shared worker events ---------------- + // -------------------------------------------------------- + /** + * SDK will announce when newer shared worker will be 'noticed'. + */ + StatusCategory["PNSharedWorkerUpdatedCategory"] = "PNSharedWorkerUpdatedCategory"; + })(StatusCategory || (StatusCategory = {})); + var StatusCategory$1 = StatusCategory; + + /** + * PubNub operation error module. + */ + /** + * PubNub operation error. + * + * When an operation can't be performed or there is an error from the server, this object will be returned. + */ + class PubNubError extends Error { + /** + * Create PubNub operation error. + * + * @param message - Message with details about why operation failed. + * @param [status] - Additional information about performed operation. + * + * @returns Configured and ready to use PubNub operation error. + * + * @internal + */ + constructor(message, status) { + super(message); + this.status = status; + this.name = 'PubNubError'; + this.message = message; + Object.setPrototypeOf(this, new.target.prototype); + } + } + /** + * Create error status object. + * + * @param errorPayload - Additional information which should be attached to the error status object. + * @param category - Occurred error category. + * + * @returns Error status object. + * + * @internal + */ + function createError(errorPayload, category) { + var _a; + (_a = errorPayload.statusCode) !== null && _a !== void 0 ? _a : (errorPayload.statusCode = 0); + return Object.assign(Object.assign({}, errorPayload), { statusCode: errorPayload.statusCode, category, error: true }); + } + /** + * Create operation arguments validation error status object. + * + * @param message - Information about failed validation requirement. + * @param [statusCode] - Operation HTTP status code. + * + * @returns Operation validation error status object. + * + * @internal + */ + function createValidationError(message, statusCode) { + return createError(Object.assign({ message }, ({})), StatusCategory$1.PNValidationErrorCategory); + } + /** + * Create malformed service response error status object. + * + * @param [responseText] - Stringified original service response. + * @param [statusCode] - Operation HTTP status code. + */ + function createMalformedResponseError(responseText, statusCode) { + return createError(Object.assign(Object.assign({ message: 'Unable to deserialize service response' }, (responseText !== undefined ? { responseText } : {})), (statusCode !== undefined ? { statusCode } : {})), StatusCategory$1.PNMalformedResponseCategory); + } + + /** + * CryptoJS implementation. + * + * @internal + */ + + /*eslint-disable */ + + /* + CryptoJS v3.1.2 + code.google.com/p/crypto-js + (c) 2009-2013 by Jeff Mott. All rights reserved. + code.google.com/p/crypto-js/wiki/License + */ + var CryptoJS = + CryptoJS || + (function (h, s) { + var f = {}, + g = (f.lib = {}), + q = function () {}, + m = (g.Base = { + extend: function (a) { + q.prototype = this; + var c = new q(); + a && c.mixIn(a); + c.hasOwnProperty('init') || + (c.init = function () { + c.$super.init.apply(this, arguments); + }); + c.init.prototype = c; + c.$super = this; + return c; + }, + create: function () { + var a = this.extend(); + a.init.apply(a, arguments); + return a; + }, + init: function () {}, + mixIn: function (a) { + for (var c in a) a.hasOwnProperty(c) && (this[c] = a[c]); + a.hasOwnProperty('toString') && (this.toString = a.toString); + }, + clone: function () { + return this.init.prototype.extend(this); + }, + }), + r = (g.WordArray = m.extend({ + init: function (a, c) { + a = this.words = a || []; + this.sigBytes = c != s ? c : 4 * a.length; + }, + toString: function (a) { + return (a || k).stringify(this); + }, + concat: function (a) { + var c = this.words, + d = a.words, + b = this.sigBytes; + a = a.sigBytes; + this.clamp(); + if (b % 4) + for (var e = 0; e < a; e++) + c[(b + e) >>> 2] |= ((d[e >>> 2] >>> (24 - 8 * (e % 4))) & 255) << (24 - 8 * ((b + e) % 4)); + else if (65535 < d.length) for (e = 0; e < a; e += 4) c[(b + e) >>> 2] = d[e >>> 2]; + else c.push.apply(c, d); + this.sigBytes += a; + return this; + }, + clamp: function () { + var a = this.words, + c = this.sigBytes; + a[c >>> 2] &= 4294967295 << (32 - 8 * (c % 4)); + a.length = h.ceil(c / 4); + }, + clone: function () { + var a = m.clone.call(this); + a.words = this.words.slice(0); + return a; + }, + random: function (a) { + for (var c = [], d = 0; d < a; d += 4) c.push((4294967296 * h.random()) | 0); + return new r.init(c, a); + }, + })), + l = (f.enc = {}), + k = (l.Hex = { + stringify: function (a) { + var c = a.words; + a = a.sigBytes; + for (var d = [], b = 0; b < a; b++) { + var e = (c[b >>> 2] >>> (24 - 8 * (b % 4))) & 255; + d.push((e >>> 4).toString(16)); + d.push((e & 15).toString(16)); + } + return d.join(''); + }, + parse: function (a) { + for (var c = a.length, d = [], b = 0; b < c; b += 2) + d[b >>> 3] |= parseInt(a.substr(b, 2), 16) << (24 - 4 * (b % 8)); + return new r.init(d, c / 2); + }, + }), + n = (l.Latin1 = { + stringify: function (a) { + var c = a.words; + a = a.sigBytes; + for (var d = [], b = 0; b < a; b++) d.push(String.fromCharCode((c[b >>> 2] >>> (24 - 8 * (b % 4))) & 255)); + return d.join(''); + }, + parse: function (a) { + for (var c = a.length, d = [], b = 0; b < c; b++) d[b >>> 2] |= (a.charCodeAt(b) & 255) << (24 - 8 * (b % 4)); + return new r.init(d, c); + }, + }), + j = (l.Utf8 = { + stringify: function (a) { + try { + return decodeURIComponent(escape(n.stringify(a))); + } catch (c) { + throw Error('Malformed UTF-8 data'); + } + }, + parse: function (a) { + return n.parse(unescape(encodeURIComponent(a))); + }, + }), + u = (g.BufferedBlockAlgorithm = m.extend({ + reset: function () { + this._data = new r.init(); + this._nDataBytes = 0; + }, + _append: function (a) { + 'string' == typeof a && (a = j.parse(a)); + this._data.concat(a); + this._nDataBytes += a.sigBytes; + }, + _process: function (a) { + var c = this._data, + d = c.words, + b = c.sigBytes, + e = this.blockSize, + f = b / (4 * e), + f = a ? h.ceil(f) : h.max((f | 0) - this._minBufferSize, 0); + a = f * e; + b = h.min(4 * a, b); + if (a) { + for (var g = 0; g < a; g += e) this._doProcessBlock(d, g); + g = d.splice(0, a); + c.sigBytes -= b; + } + return new r.init(g, b); + }, + clone: function () { + var a = m.clone.call(this); + a._data = this._data.clone(); + return a; + }, + _minBufferSize: 0, + })); + g.Hasher = u.extend({ + cfg: m.extend(), + init: function (a) { + this.cfg = this.cfg.extend(a); + this.reset(); + }, + reset: function () { + u.reset.call(this); + this._doReset(); + }, + update: function (a) { + this._append(a); + this._process(); + return this; + }, + finalize: function (a) { + a && this._append(a); + return this._doFinalize(); + }, + blockSize: 16, + _createHelper: function (a) { + return function (c, d) { + return new a.init(d).finalize(c); + }; + }, + _createHmacHelper: function (a) { + return function (c, d) { + return new t.HMAC.init(a, d).finalize(c); + }; + }, + }); + var t = (f.algo = {}); + return f; + })(Math); + + // SHA256 + (function (h) { + for ( + var s = CryptoJS, + f = s.lib, + g = f.WordArray, + q = f.Hasher, + f = s.algo, + m = [], + r = [], + l = function (a) { + return (4294967296 * (a - (a | 0))) | 0; + }, + k = 2, + n = 0; + 64 > n; + + ) { + var j; + a: { + j = k; + for (var u = h.sqrt(j), t = 2; t <= u; t++) + if (!(j % t)) { + j = !1; + break a; + } + j = !0; + } + j && (8 > n && (m[n] = l(h.pow(k, 0.5))), (r[n] = l(h.pow(k, 1 / 3))), n++); + k++; + } + var a = [], + f = (f.SHA256 = q.extend({ + _doReset: function () { + this._hash = new g.init(m.slice(0)); + }, + _doProcessBlock: function (c, d) { + for ( + var b = this._hash.words, + e = b[0], + f = b[1], + g = b[2], + j = b[3], + h = b[4], + m = b[5], + n = b[6], + q = b[7], + p = 0; + 64 > p; + p++ + ) { + if (16 > p) a[p] = c[d + p] | 0; + else { + var k = a[p - 15], + l = a[p - 2]; + a[p] = + (((k << 25) | (k >>> 7)) ^ ((k << 14) | (k >>> 18)) ^ (k >>> 3)) + + a[p - 7] + + (((l << 15) | (l >>> 17)) ^ ((l << 13) | (l >>> 19)) ^ (l >>> 10)) + + a[p - 16]; + } + k = + q + + (((h << 26) | (h >>> 6)) ^ ((h << 21) | (h >>> 11)) ^ ((h << 7) | (h >>> 25))) + + ((h & m) ^ (~h & n)) + + r[p] + + a[p]; + l = + (((e << 30) | (e >>> 2)) ^ ((e << 19) | (e >>> 13)) ^ ((e << 10) | (e >>> 22))) + + ((e & f) ^ (e & g) ^ (f & g)); + q = n; + n = m; + m = h; + h = (j + k) | 0; + j = g; + g = f; + f = e; + e = (k + l) | 0; + } + b[0] = (b[0] + e) | 0; + b[1] = (b[1] + f) | 0; + b[2] = (b[2] + g) | 0; + b[3] = (b[3] + j) | 0; + b[4] = (b[4] + h) | 0; + b[5] = (b[5] + m) | 0; + b[6] = (b[6] + n) | 0; + b[7] = (b[7] + q) | 0; + }, + _doFinalize: function () { + var a = this._data, + d = a.words, + b = 8 * this._nDataBytes, + e = 8 * a.sigBytes; + d[e >>> 5] |= 128 << (24 - (e % 32)); + d[(((e + 64) >>> 9) << 4) + 14] = h.floor(b / 4294967296); + d[(((e + 64) >>> 9) << 4) + 15] = b; + a.sigBytes = 4 * d.length; + this._process(); + return this._hash; + }, + clone: function () { + var a = q.clone.call(this); + a._hash = this._hash.clone(); + return a; + }, + })); + s.SHA256 = q._createHelper(f); + s.HmacSHA256 = q._createHmacHelper(f); + })(Math); + + // HMAC SHA256 + (function () { + var h = CryptoJS, + s = h.enc.Utf8; + h.algo.HMAC = h.lib.Base.extend({ + init: function (f, g) { + f = this._hasher = new f.init(); + 'string' == typeof g && (g = s.parse(g)); + var h = f.blockSize, + m = 4 * h; + g.sigBytes > m && (g = f.finalize(g)); + g.clamp(); + for (var r = (this._oKey = g.clone()), l = (this._iKey = g.clone()), k = r.words, n = l.words, j = 0; j < h; j++) + (k[j] ^= 1549556828), (n[j] ^= 909522486); + r.sigBytes = l.sigBytes = m; + this.reset(); + }, + reset: function () { + var f = this._hasher; + f.reset(); + f.update(this._iKey); + }, + update: function (f) { + this._hasher.update(f); + return this; + }, + finalize: function (f) { + var g = this._hasher; + f = g.finalize(f); + g.reset(); + return g.finalize(this._oKey.clone().concat(f)); + }, + }); + })(); + + // Base64 + (function () { + var u = CryptoJS, + p = u.lib.WordArray; + u.enc.Base64 = { + stringify: function (d) { + var l = d.words, + p = d.sigBytes, + t = this._map; + d.clamp(); + d = []; + for (var r = 0; r < p; r += 3) + for ( + var w = + (((l[r >>> 2] >>> (24 - 8 * (r % 4))) & 255) << 16) | + (((l[(r + 1) >>> 2] >>> (24 - 8 * ((r + 1) % 4))) & 255) << 8) | + ((l[(r + 2) >>> 2] >>> (24 - 8 * ((r + 2) % 4))) & 255), + v = 0; + 4 > v && r + 0.75 * v < p; + v++ + ) + d.push(t.charAt((w >>> (6 * (3 - v))) & 63)); + if ((l = t.charAt(64))) for (; d.length % 4; ) d.push(l); + return d.join(''); + }, + parse: function (d) { + var l = d.length, + s = this._map, + t = s.charAt(64); + t && ((t = d.indexOf(t)), -1 != t && (l = t)); + for (var t = [], r = 0, w = 0; w < l; w++) + if (w % 4) { + var v = s.indexOf(d.charAt(w - 1)) << (2 * (w % 4)), + b = s.indexOf(d.charAt(w)) >>> (6 - 2 * (w % 4)); + t[r >>> 2] |= (v | b) << (24 - 8 * (r % 4)); + r++; + } + return p.create(t, r); + }, + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', + }; + })(); + + // BlockCipher + (function (u) { + function p(b, n, a, c, e, j, k) { + b = b + ((n & a) | (~n & c)) + e + k; + return ((b << j) | (b >>> (32 - j))) + n; + } + function d(b, n, a, c, e, j, k) { + b = b + ((n & c) | (a & ~c)) + e + k; + return ((b << j) | (b >>> (32 - j))) + n; + } + function l(b, n, a, c, e, j, k) { + b = b + (n ^ a ^ c) + e + k; + return ((b << j) | (b >>> (32 - j))) + n; + } + function s(b, n, a, c, e, j, k) { + b = b + (a ^ (n | ~c)) + e + k; + return ((b << j) | (b >>> (32 - j))) + n; + } + for (var t = CryptoJS, r = t.lib, w = r.WordArray, v = r.Hasher, r = t.algo, b = [], x = 0; 64 > x; x++) + b[x] = (4294967296 * u.abs(u.sin(x + 1))) | 0; + r = r.MD5 = v.extend({ + _doReset: function () { + this._hash = new w.init([1732584193, 4023233417, 2562383102, 271733878]); + }, + _doProcessBlock: function (q, n) { + for (var a = 0; 16 > a; a++) { + var c = n + a, + e = q[c]; + q[c] = (((e << 8) | (e >>> 24)) & 16711935) | (((e << 24) | (e >>> 8)) & 4278255360); + } + var a = this._hash.words, + c = q[n + 0], + e = q[n + 1], + j = q[n + 2], + k = q[n + 3], + z = q[n + 4], + r = q[n + 5], + t = q[n + 6], + w = q[n + 7], + v = q[n + 8], + A = q[n + 9], + B = q[n + 10], + C = q[n + 11], + u = q[n + 12], + D = q[n + 13], + E = q[n + 14], + x = q[n + 15], + f = a[0], + m = a[1], + g = a[2], + h = a[3], + f = p(f, m, g, h, c, 7, b[0]), + h = p(h, f, m, g, e, 12, b[1]), + g = p(g, h, f, m, j, 17, b[2]), + m = p(m, g, h, f, k, 22, b[3]), + f = p(f, m, g, h, z, 7, b[4]), + h = p(h, f, m, g, r, 12, b[5]), + g = p(g, h, f, m, t, 17, b[6]), + m = p(m, g, h, f, w, 22, b[7]), + f = p(f, m, g, h, v, 7, b[8]), + h = p(h, f, m, g, A, 12, b[9]), + g = p(g, h, f, m, B, 17, b[10]), + m = p(m, g, h, f, C, 22, b[11]), + f = p(f, m, g, h, u, 7, b[12]), + h = p(h, f, m, g, D, 12, b[13]), + g = p(g, h, f, m, E, 17, b[14]), + m = p(m, g, h, f, x, 22, b[15]), + f = d(f, m, g, h, e, 5, b[16]), + h = d(h, f, m, g, t, 9, b[17]), + g = d(g, h, f, m, C, 14, b[18]), + m = d(m, g, h, f, c, 20, b[19]), + f = d(f, m, g, h, r, 5, b[20]), + h = d(h, f, m, g, B, 9, b[21]), + g = d(g, h, f, m, x, 14, b[22]), + m = d(m, g, h, f, z, 20, b[23]), + f = d(f, m, g, h, A, 5, b[24]), + h = d(h, f, m, g, E, 9, b[25]), + g = d(g, h, f, m, k, 14, b[26]), + m = d(m, g, h, f, v, 20, b[27]), + f = d(f, m, g, h, D, 5, b[28]), + h = d(h, f, m, g, j, 9, b[29]), + g = d(g, h, f, m, w, 14, b[30]), + m = d(m, g, h, f, u, 20, b[31]), + f = l(f, m, g, h, r, 4, b[32]), + h = l(h, f, m, g, v, 11, b[33]), + g = l(g, h, f, m, C, 16, b[34]), + m = l(m, g, h, f, E, 23, b[35]), + f = l(f, m, g, h, e, 4, b[36]), + h = l(h, f, m, g, z, 11, b[37]), + g = l(g, h, f, m, w, 16, b[38]), + m = l(m, g, h, f, B, 23, b[39]), + f = l(f, m, g, h, D, 4, b[40]), + h = l(h, f, m, g, c, 11, b[41]), + g = l(g, h, f, m, k, 16, b[42]), + m = l(m, g, h, f, t, 23, b[43]), + f = l(f, m, g, h, A, 4, b[44]), + h = l(h, f, m, g, u, 11, b[45]), + g = l(g, h, f, m, x, 16, b[46]), + m = l(m, g, h, f, j, 23, b[47]), + f = s(f, m, g, h, c, 6, b[48]), + h = s(h, f, m, g, w, 10, b[49]), + g = s(g, h, f, m, E, 15, b[50]), + m = s(m, g, h, f, r, 21, b[51]), + f = s(f, m, g, h, u, 6, b[52]), + h = s(h, f, m, g, k, 10, b[53]), + g = s(g, h, f, m, B, 15, b[54]), + m = s(m, g, h, f, e, 21, b[55]), + f = s(f, m, g, h, v, 6, b[56]), + h = s(h, f, m, g, x, 10, b[57]), + g = s(g, h, f, m, t, 15, b[58]), + m = s(m, g, h, f, D, 21, b[59]), + f = s(f, m, g, h, z, 6, b[60]), + h = s(h, f, m, g, C, 10, b[61]), + g = s(g, h, f, m, j, 15, b[62]), + m = s(m, g, h, f, A, 21, b[63]); + a[0] = (a[0] + f) | 0; + a[1] = (a[1] + m) | 0; + a[2] = (a[2] + g) | 0; + a[3] = (a[3] + h) | 0; + }, + _doFinalize: function () { + var b = this._data, + n = b.words, + a = 8 * this._nDataBytes, + c = 8 * b.sigBytes; + n[c >>> 5] |= 128 << (24 - (c % 32)); + var e = u.floor(a / 4294967296); + n[(((c + 64) >>> 9) << 4) + 15] = (((e << 8) | (e >>> 24)) & 16711935) | (((e << 24) | (e >>> 8)) & 4278255360); + n[(((c + 64) >>> 9) << 4) + 14] = (((a << 8) | (a >>> 24)) & 16711935) | (((a << 24) | (a >>> 8)) & 4278255360); + b.sigBytes = 4 * (n.length + 1); + this._process(); + b = this._hash; + n = b.words; + for (a = 0; 4 > a; a++) + (c = n[a]), (n[a] = (((c << 8) | (c >>> 24)) & 16711935) | (((c << 24) | (c >>> 8)) & 4278255360)); + return b; + }, + clone: function () { + var b = v.clone.call(this); + b._hash = this._hash.clone(); + return b; + }, + }); + t.MD5 = v._createHelper(r); + t.HmacMD5 = v._createHmacHelper(r); + })(Math); + (function () { + var u = CryptoJS, + p = u.lib, + d = p.Base, + l = p.WordArray, + p = u.algo, + s = (p.EvpKDF = d.extend({ + cfg: d.extend({ keySize: 4, hasher: p.MD5, iterations: 1 }), + init: function (d) { + this.cfg = this.cfg.extend(d); + }, + compute: function (d, r) { + for ( + var p = this.cfg, s = p.hasher.create(), b = l.create(), u = b.words, q = p.keySize, p = p.iterations; + u.length < q; + + ) { + n && s.update(n); + var n = s.update(d).finalize(r); + s.reset(); + for (var a = 1; a < p; a++) (n = s.finalize(n)), s.reset(); + b.concat(n); + } + b.sigBytes = 4 * q; + return b; + }, + })); + u.EvpKDF = function (d, l, p) { + return s.create(p).compute(d, l); + }; + })(); + + // Cipher + CryptoJS.lib.Cipher || + (function (u) { + var p = CryptoJS, + d = p.lib, + l = d.Base, + s = d.WordArray, + t = d.BufferedBlockAlgorithm, + r = p.enc.Base64, + w = p.algo.EvpKDF, + v = (d.Cipher = t.extend({ + cfg: l.extend(), + createEncryptor: function (e, a) { + return this.create(this._ENC_XFORM_MODE, e, a); + }, + createDecryptor: function (e, a) { + return this.create(this._DEC_XFORM_MODE, e, a); + }, + init: function (e, a, b) { + this.cfg = this.cfg.extend(b); + this._xformMode = e; + this._key = a; + this.reset(); + }, + reset: function () { + t.reset.call(this); + this._doReset(); + }, + process: function (e) { + this._append(e); + return this._process(); + }, + finalize: function (e) { + e && this._append(e); + return this._doFinalize(); + }, + keySize: 4, + ivSize: 4, + _ENC_XFORM_MODE: 1, + _DEC_XFORM_MODE: 2, + _createHelper: function (e) { + return { + encrypt: function (b, k, d) { + return ('string' == typeof k ? c : a).encrypt(e, b, k, d); + }, + decrypt: function (b, k, d) { + return ('string' == typeof k ? c : a).decrypt(e, b, k, d); + }, + }; + }, + })); + d.StreamCipher = v.extend({ + _doFinalize: function () { + return this._process(!0); + }, + blockSize: 1, + }); + var b = (p.mode = {}), + x = function (e, a, b) { + var c = this._iv; + c ? (this._iv = u) : (c = this._prevBlock); + for (var d = 0; d < b; d++) e[a + d] ^= c[d]; + }, + q = (d.BlockCipherMode = l.extend({ + createEncryptor: function (e, a) { + return this.Encryptor.create(e, a); + }, + createDecryptor: function (e, a) { + return this.Decryptor.create(e, a); + }, + init: function (e, a) { + this._cipher = e; + this._iv = a; + }, + })).extend(); + q.Encryptor = q.extend({ + processBlock: function (e, a) { + var b = this._cipher, + c = b.blockSize; + x.call(this, e, a, c); + b.encryptBlock(e, a); + this._prevBlock = e.slice(a, a + c); + }, + }); + q.Decryptor = q.extend({ + processBlock: function (e, a) { + var b = this._cipher, + c = b.blockSize, + d = e.slice(a, a + c); + b.decryptBlock(e, a); + x.call(this, e, a, c); + this._prevBlock = d; + }, + }); + b = b.CBC = q; + q = (p.pad = {}).Pkcs7 = { + pad: function (a, b) { + for ( + var c = 4 * b, c = c - (a.sigBytes % c), d = (c << 24) | (c << 16) | (c << 8) | c, l = [], n = 0; + n < c; + n += 4 + ) + l.push(d); + c = s.create(l, c); + a.concat(c); + }, + unpad: function (a) { + a.sigBytes -= a.words[(a.sigBytes - 1) >>> 2] & 255; + }, + }; + d.BlockCipher = v.extend({ + cfg: v.cfg.extend({ mode: b, padding: q }), + reset: function () { + v.reset.call(this); + var a = this.cfg, + b = a.iv, + a = a.mode; + if (this._xformMode == this._ENC_XFORM_MODE) var c = a.createEncryptor; + else (c = a.createDecryptor), (this._minBufferSize = 1); + this._mode = c.call(a, this, b && b.words); + }, + _doProcessBlock: function (a, b) { + this._mode.processBlock(a, b); + }, + _doFinalize: function () { + var a = this.cfg.padding; + if (this._xformMode == this._ENC_XFORM_MODE) { + a.pad(this._data, this.blockSize); + var b = this._process(!0); + } else (b = this._process(!0)), a.unpad(b); + return b; + }, + blockSize: 4, + }); + var n = (d.CipherParams = l.extend({ + init: function (a) { + this.mixIn(a); + }, + toString: function (a) { + return (a || this.formatter).stringify(this); + }, + })), + b = ((p.format = {}).OpenSSL = { + stringify: function (a) { + var b = a.ciphertext; + a = a.salt; + return (a ? s.create([1398893684, 1701076831]).concat(a).concat(b) : b).toString(r); + }, + parse: function (a) { + a = r.parse(a); + var b = a.words; + if (1398893684 == b[0] && 1701076831 == b[1]) { + var c = s.create(b.slice(2, 4)); + b.splice(0, 4); + a.sigBytes -= 16; + } + return n.create({ ciphertext: a, salt: c }); + }, + }), + a = (d.SerializableCipher = l.extend({ + cfg: l.extend({ format: b }), + encrypt: function (a, b, c, d) { + d = this.cfg.extend(d); + var l = a.createEncryptor(c, d); + b = l.finalize(b); + l = l.cfg; + return n.create({ + ciphertext: b, + key: c, + iv: l.iv, + algorithm: a, + mode: l.mode, + padding: l.padding, + blockSize: a.blockSize, + formatter: d.format, + }); + }, + decrypt: function (a, b, c, d) { + d = this.cfg.extend(d); + b = this._parse(b, d.format); + return a.createDecryptor(c, d).finalize(b.ciphertext); + }, + _parse: function (a, b) { + return 'string' == typeof a ? b.parse(a, this) : a; + }, + })), + p = ((p.kdf = {}).OpenSSL = { + execute: function (a, b, c, d) { + d || (d = s.random(8)); + a = w.create({ keySize: b + c }).compute(a, d); + c = s.create(a.words.slice(b), 4 * c); + a.sigBytes = 4 * b; + return n.create({ key: a, iv: c, salt: d }); + }, + }), + c = (d.PasswordBasedCipher = a.extend({ + cfg: a.cfg.extend({ kdf: p }), + encrypt: function (b, c, d, l) { + l = this.cfg.extend(l); + d = l.kdf.execute(d, b.keySize, b.ivSize); + l.iv = d.iv; + b = a.encrypt.call(this, b, c, d.key, l); + b.mixIn(d); + return b; + }, + decrypt: function (b, c, d, l) { + l = this.cfg.extend(l); + c = this._parse(c, l.format); + d = l.kdf.execute(d, b.keySize, b.ivSize, c.salt); + l.iv = d.iv; + return a.decrypt.call(this, b, c, d.key, l); + }, + })); + })(); + + // AES + (function () { + for ( + var u = CryptoJS, + p = u.lib.BlockCipher, + d = u.algo, + l = [], + s = [], + t = [], + r = [], + w = [], + v = [], + b = [], + x = [], + q = [], + n = [], + a = [], + c = 0; + 256 > c; + c++ + ) + a[c] = 128 > c ? c << 1 : (c << 1) ^ 283; + for (var e = 0, j = 0, c = 0; 256 > c; c++) { + var k = j ^ (j << 1) ^ (j << 2) ^ (j << 3) ^ (j << 4), + k = (k >>> 8) ^ (k & 255) ^ 99; + l[e] = k; + s[k] = e; + var z = a[e], + F = a[z], + G = a[F], + y = (257 * a[k]) ^ (16843008 * k); + t[e] = (y << 24) | (y >>> 8); + r[e] = (y << 16) | (y >>> 16); + w[e] = (y << 8) | (y >>> 24); + v[e] = y; + y = (16843009 * G) ^ (65537 * F) ^ (257 * z) ^ (16843008 * e); + b[k] = (y << 24) | (y >>> 8); + x[k] = (y << 16) | (y >>> 16); + q[k] = (y << 8) | (y >>> 24); + n[k] = y; + e ? ((e = z ^ a[a[a[G ^ z]]]), (j ^= a[a[j]])) : (e = j = 1); + } + var H = [0, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54], + d = (d.AES = p.extend({ + _doReset: function () { + for ( + var a = this._key, + c = a.words, + d = a.sigBytes / 4, + a = 4 * ((this._nRounds = d + 6) + 1), + e = (this._keySchedule = []), + j = 0; + j < a; + j++ + ) + if (j < d) e[j] = c[j]; + else { + var k = e[j - 1]; + j % d + ? 6 < d && + 4 == j % d && + (k = (l[k >>> 24] << 24) | (l[(k >>> 16) & 255] << 16) | (l[(k >>> 8) & 255] << 8) | l[k & 255]) + : ((k = (k << 8) | (k >>> 24)), + (k = (l[k >>> 24] << 24) | (l[(k >>> 16) & 255] << 16) | (l[(k >>> 8) & 255] << 8) | l[k & 255]), + (k ^= H[(j / d) | 0] << 24)); + e[j] = e[j - d] ^ k; + } + c = this._invKeySchedule = []; + for (d = 0; d < a; d++) + (j = a - d), + (k = d % 4 ? e[j] : e[j - 4]), + (c[d] = + 4 > d || 4 >= j ? k : b[l[k >>> 24]] ^ x[l[(k >>> 16) & 255]] ^ q[l[(k >>> 8) & 255]] ^ n[l[k & 255]]); + }, + encryptBlock: function (a, b) { + this._doCryptBlock(a, b, this._keySchedule, t, r, w, v, l); + }, + decryptBlock: function (a, c) { + var d = a[c + 1]; + a[c + 1] = a[c + 3]; + a[c + 3] = d; + this._doCryptBlock(a, c, this._invKeySchedule, b, x, q, n, s); + d = a[c + 1]; + a[c + 1] = a[c + 3]; + a[c + 3] = d; + }, + _doCryptBlock: function (a, b, c, d, e, j, l, f) { + for ( + var m = this._nRounds, + g = a[b] ^ c[0], + h = a[b + 1] ^ c[1], + k = a[b + 2] ^ c[2], + n = a[b + 3] ^ c[3], + p = 4, + r = 1; + r < m; + r++ + ) + var q = d[g >>> 24] ^ e[(h >>> 16) & 255] ^ j[(k >>> 8) & 255] ^ l[n & 255] ^ c[p++], + s = d[h >>> 24] ^ e[(k >>> 16) & 255] ^ j[(n >>> 8) & 255] ^ l[g & 255] ^ c[p++], + t = d[k >>> 24] ^ e[(n >>> 16) & 255] ^ j[(g >>> 8) & 255] ^ l[h & 255] ^ c[p++], + n = d[n >>> 24] ^ e[(g >>> 16) & 255] ^ j[(h >>> 8) & 255] ^ l[k & 255] ^ c[p++], + g = q, + h = s, + k = t; + q = ((f[g >>> 24] << 24) | (f[(h >>> 16) & 255] << 16) | (f[(k >>> 8) & 255] << 8) | f[n & 255]) ^ c[p++]; + s = ((f[h >>> 24] << 24) | (f[(k >>> 16) & 255] << 16) | (f[(n >>> 8) & 255] << 8) | f[g & 255]) ^ c[p++]; + t = ((f[k >>> 24] << 24) | (f[(n >>> 16) & 255] << 16) | (f[(g >>> 8) & 255] << 8) | f[h & 255]) ^ c[p++]; + n = ((f[n >>> 24] << 24) | (f[(g >>> 16) & 255] << 16) | (f[(h >>> 8) & 255] << 8) | f[k & 255]) ^ c[p++]; + a[b] = q; + a[b + 1] = s; + a[b + 2] = t; + a[b + 3] = n; + }, + keySize: 8, + })); + u.AES = p._createHelper(d); + })(); + + // Mode ECB + CryptoJS.mode.ECB = (function () { + var ECB = CryptoJS.lib.BlockCipherMode.extend(); + + ECB.Encryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.encryptBlock(words, offset); + }, + }); + + ECB.Decryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.decryptBlock(words, offset); + }, + }); + + return ECB; + })(); + + var hmacSha256 = CryptoJS; + + var CryptoJS$1 = /*@__PURE__*/getDefaultExportFromCjs(hmacSha256); + + /** + * AES-CBC cryptor module. + */ + /** + * AES-CBC cryptor. + * + * AES-CBC cryptor with enhanced cipher strength. + */ + class AesCbcCryptor { + constructor({ cipherKey }) { + this.cipherKey = cipherKey; + this.CryptoJS = CryptoJS$1; + this.encryptedKey = this.CryptoJS.SHA256(cipherKey); + } + // -------------------------------------------------------- + // --------------------- Encryption ----------------------- + // -------------------------------------------------------- + // region Encryption + encrypt(data) { + const stringData = typeof data === 'string' ? data : AesCbcCryptor.decoder.decode(data); + if (stringData.length === 0) + throw new Error('encryption error. empty content'); + const abIv = this.getIv(); + return { + metadata: abIv, + data: decode(this.CryptoJS.AES.encrypt(data, this.encryptedKey, { + iv: this.bufferToWordArray(abIv), + mode: this.CryptoJS.mode.CBC, + }).ciphertext.toString(this.CryptoJS.enc.Base64)), + }; + } + encryptFileData(data) { + return __awaiter(this, void 0, void 0, function* () { + const key = yield this.getKey(); + const iv = this.getIv(); + return { + data: yield crypto.subtle.encrypt({ name: this.algo, iv: iv }, key, data), + metadata: iv, + }; + }); + } + // endregion + // -------------------------------------------------------- + // --------------------- Decryption ----------------------- + // -------------------------------------------------------- + // region Decryption + decrypt(encryptedData) { + if (typeof encryptedData.data === 'string') + throw new Error('Decryption error: data for decryption should be ArrayBuffed.'); + const iv = this.bufferToWordArray(new Uint8ClampedArray(encryptedData.metadata)); + const data = this.bufferToWordArray(new Uint8ClampedArray(encryptedData.data)); + return AesCbcCryptor.encoder.encode(this.CryptoJS.AES.decrypt({ ciphertext: data }, this.encryptedKey, { + iv, + mode: this.CryptoJS.mode.CBC, + }).toString(this.CryptoJS.enc.Utf8)).buffer; + } + decryptFileData(encryptedData) { + return __awaiter(this, void 0, void 0, function* () { + if (typeof encryptedData.data === 'string') + throw new Error('Decryption error: data for decryption should be ArrayBuffed.'); + const key = yield this.getKey(); + return crypto.subtle.decrypt({ name: this.algo, iv: encryptedData.metadata }, key, encryptedData.data); + }); + } + // endregion + // -------------------------------------------------------- + // ----------------------- Helpers ------------------------ + // -------------------------------------------------------- + // region Helpers + get identifier() { + return 'ACRH'; + } + /** + * Cryptor algorithm. + * + * @returns Cryptor module algorithm. + */ + get algo() { + return 'AES-CBC'; + } + /** + * Generate random initialization vector. + * + * @returns Random initialization vector. + */ + getIv() { + return crypto.getRandomValues(new Uint8Array(AesCbcCryptor.BLOCK_SIZE)); + } + /** + * Convert cipher key to the {@link Buffer}. + * + * @returns SHA256 encoded cipher key {@link Buffer}. + */ + getKey() { + return __awaiter(this, void 0, void 0, function* () { + const bKey = AesCbcCryptor.encoder.encode(this.cipherKey); + const abHash = yield crypto.subtle.digest('SHA-256', bKey.buffer); + return crypto.subtle.importKey('raw', abHash, this.algo, true, ['encrypt', 'decrypt']); + }); + } + /** + * Convert bytes array to words array. + * + * @param b - Bytes array (buffer) which should be converted. + * + * @returns Word sized array. + */ + bufferToWordArray(b) { + const wa = []; + let i; + for (i = 0; i < b.length; i += 1) { + wa[(i / 4) | 0] |= b[i] << (24 - 8 * i); + } + return this.CryptoJS.lib.WordArray.create(wa, b.length); + } + /** + * Serialize cryptor information to string. + * + * @returns Serialized cryptor information. + */ + toString() { + return 'AesCbcCryptor {}'; + } + } + /** + * Cryptor block size. + */ + AesCbcCryptor.BLOCK_SIZE = 16; + /** + * {@link string|String} to {@link ArrayBuffer} response decoder. + */ + AesCbcCryptor.encoder = new TextEncoder(); + /** + * {@link ArrayBuffer} to {@link string} decoder. + */ + AesCbcCryptor.decoder = new TextDecoder(); + + /** + * PubNub package utilities module. + * + * @internal + */ + /** + * Object log property names that must never appear in SDK logs. + * + * @internal + */ + const SENSITIVE_LOG_KEYS = new Set(['authKey', 'authKeys', 'secretKey', 'cipherKey', 'token', 'auth']); + /** + * Whether an object log key should be omitted because it may hold a secret. + * + * @param key - Property name from an object being logged. + * + * @returns `true` when the key should be filtered from log output. + * + * @internal + */ + const isSensitiveLogKey = (key) => SENSITIVE_LOG_KEYS.has(key); + /** + * Percent-encode input string. + * + * **Note:** Encode content in accordance of the `PubNub` service requirements. + * + * @param input - Source string or number for encoding. + * + * @returns Percent-encoded string. + * + * @internal + */ + const encodeString = (input) => { + return encodeURIComponent(input).replace(/[!~*'()]/g, (x) => `%${x.charCodeAt(0).toString(16).toUpperCase()}`); + }; + /** + * Percent-encode list of names (channels). + * + * @param names - List of names which should be encoded. + * + * @param [defaultString] - String which should be used in case if {@link names} is empty. + * + * @returns String which contains encoded names joined by non-encoded `,`. + * + * @internal + */ + const encodeNames = (names, defaultString) => { + const encodedNames = names.map((name) => encodeString(name)); + return encodedNames.length ? encodedNames.join(',') : (defaultString !== null && defaultString !== void 0 ? defaultString : ''); + }; + /** + * @internal + */ + const removeSingleOccurrence = (source, elementsToRemove) => { + const removed = Object.fromEntries(elementsToRemove.map((prop) => [prop, false])); + return source.filter((e) => { + if (elementsToRemove.includes(e) && !removed[e]) { + removed[e] = true; + return false; + } + return true; + }); + }; + /** + * @internal + */ + const findUniqueCommonElements = (a, b) => { + return [...a].filter((value) => b.includes(value) && a.indexOf(value) === a.lastIndexOf(value) && b.indexOf(value) === b.lastIndexOf(value)); + }; + /** + * Transform query key / value pairs to the string. + * + * @param query - Key / value pairs of the request query parameters. + * + * @returns Stringified query key / value pairs. + * + * @internal + */ + const queryStringFromObject = (query) => { + return Object.keys(query) + .map((key) => { + const queryValue = query[key]; + if (!Array.isArray(queryValue)) + return `${key}=${encodeString(queryValue)}`; + return queryValue.map((value) => `${key}=${encodeString(value)}`).join('&'); + }) + .join('&'); + }; + /** + * Adjust `timetoken` to represent current time in PubNub's high-precision time format. + * + * @param timetoken - Timetoken recently used for subscribe long-poll request. + * @param [referenceTimetoken] - Previously computed reference timetoken. + * + * @returns Adjusted timetoken if recent timetoken available. + */ + const subscriptionTimetokenFromReference = (timetoken, referenceTimetoken) => { + if (referenceTimetoken === '0' || timetoken === '0') + return undefined; + const timetokenDiff = adjustedTimetokenBy(`${Date.now()}0000`, referenceTimetoken, false); + return adjustedTimetokenBy(timetoken, timetokenDiff, true); + }; + /** + * Create reference timetoken based on subscribe timetoken and the user's local time. + * + * Subscription-based reference timetoken allows later computing approximate timetoken at any point in time. + * + * @param [serviceTimetoken] - Timetoken received from the PubNub subscribe service. + * @param [catchUpTimetoken] - Previously stored or user-provided catch-up timetoken. + * @param [referenceTimetoken] - Previously computed reference timetoken. **Important:** This value should be used + * in the case of restore because the actual time when service and catch-up timetokens are received is really + * different from the current local time. + * + * @returns Reference timetoken. + */ + const referenceSubscribeTimetoken = (serviceTimetoken, catchUpTimetoken, referenceTimetoken) => { + if (!serviceTimetoken || serviceTimetoken.length === 0) + return undefined; + if (catchUpTimetoken && catchUpTimetoken.length > 0 && catchUpTimetoken !== '0') { + // Compensate reference timetoken because catch-up timetoken has been used. + const timetokensDiff = adjustedTimetokenBy(serviceTimetoken, catchUpTimetoken, false); + return adjustedTimetokenBy(referenceTimetoken !== null && referenceTimetoken !== void 0 ? referenceTimetoken : `${Date.now()}0000`, timetokensDiff.replace('-', ''), Number(timetokensDiff) < 0); + } + else if (referenceTimetoken && referenceTimetoken.length > 0 && referenceTimetoken !== '0') + return referenceTimetoken; + else + return `${Date.now()}0000`; + }; + /** + * High-precision time token adjustment. + * + * @param timetoken - Source timetoken which should be adjusted. + * @param value - Value in nanoseconds which should be used for source timetoken adjustment. + * @param increment - Whether source timetoken should be incremented or decremented. + * + * @returns Adjusted high-precision PubNub timetoken. + */ + const adjustedTimetokenBy = (timetoken, value, increment) => { + // Normalize value to the PubNub's high-precision time format. + if (value.startsWith('-')) { + value = value.replace('-', ''); + increment = false; + } + value = value.padStart(17, '0'); + const secA = timetoken.slice(0, 10); + const tickA = timetoken.slice(10, 17); + const secB = value.slice(0, 10); + const tickB = value.slice(10, 17); + let seconds = Number(secA); + let ticks = Number(tickA); + seconds += Number(secB) * (increment ? 1 : -1); + ticks += Number(tickB) * (increment ? 1 : -1); + if (ticks >= 10000000) { + seconds += Math.floor(ticks / 10000000); + ticks %= 10000000; + } + else if (ticks < 0) { + if (seconds > 0) { + seconds -= 1; + ticks += 10000000; + } + else if (seconds < 0) + ticks *= -1; + } + else if (seconds < 0 && ticks > 0) { + seconds += 1; + ticks = 10000000 - ticks; + } + return seconds !== 0 ? `${seconds}${`${ticks}`.padStart(7, '0')}` : `${ticks}`; + }; + /** + * Compute received update (message, event) fingerprint. + * + * @param input - Data payload from subscribe API response. + * + * @returns Received update fingerprint. + */ + const messageFingerprint = (input) => { + const msg = typeof input !== 'string' ? JSON.stringify(input) : input; + const mfp = new Uint32Array(1); + let walk = 0; + let len = msg.length; + while (len-- > 0) + mfp[0] = (mfp[0] << 5) - mfp[0] + msg.charCodeAt(walk++); + return mfp[0].toString(16).padStart(8, '0'); + }; + + /** + * Legacy cryptography module. + * + * @internal + */ + /** + * Convert bytes array to words array. + * + * @param b - Bytes array (buffer) which should be converted. + * + * @returns Word sized array. + * + * @internal + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ + function bufferToWordArray(b) { + const wa = []; + let i; + for (i = 0; i < b.length; i += 1) { + wa[(i / 4) | 0] |= b[i] << (24 - 8 * i); + } + // @ts-expect-error Bundled library without types. + return CryptoJS$1.lib.WordArray.create(wa, b.length); + } + /** + * Legacy cryptography module for files and signature. + * + * @internal + */ + class Crypto { + constructor(configuration) { + this.configuration = configuration; + /** + * Crypto initialization vector. + */ + this.iv = '0123456789012345'; + /** + * List os allowed cipher key encodings. + */ + this.allowedKeyEncodings = ['hex', 'utf8', 'base64', 'binary']; + /** + * Allowed cipher key lengths. + */ + this.allowedKeyLengths = [128, 256]; + /** + * Allowed crypto modes. + */ + this.allowedModes = ['ecb', 'cbc']; + this.logger = configuration.logger; + this.defaultOptions = { + encryptKey: true, + keyEncoding: 'utf8', + keyLength: 256, + mode: 'cbc', + }; + } + /** + * Update registered loggers' manager. + * + * @param [logger] - Logger, which crypto should use. + */ + set logger(logger) { + this._logger = logger; + if (this.logger) { + this.logger.debug('Crypto', () => ({ + messageType: 'object', + message: this.configuration, + details: 'Create with configuration:', + ignoredKeys(key, obj) { + return typeof obj[key] === 'function' || key === 'logger' || isSensitiveLogKey(key); + }, + })); + } + } + /** + * Get loggers' manager. + * + * @returns Loggers' manager (if set). + */ + get logger() { + return this._logger; + } + /** + * Generate HMAC-SHA256 hash from input data. + * + * @param data - Data from which hash should be generated. + * + * @returns HMAC-SHA256 hash from provided `data`. + */ + HMACSHA256(data) { + // @ts-expect-error Bundled library without types. + const hash = CryptoJS$1.HmacSHA256(data, this.configuration.secretKey); + // @ts-expect-error Bundled library without types. + return hash.toString(CryptoJS$1.enc.Base64); + } + /** + * Generate SHA256 hash from input data. + * + * @param data - Data from which hash should be generated. + * + * @returns SHA256 hash from provided `data`. + */ + SHA256(data) { + // @ts-expect-error Bundled library without types. + return CryptoJS$1.SHA256(data).toString(CryptoJS$1.enc.Hex); + } + /** + * Encrypt provided data. + * + * @param data - Source data which should be encrypted. + * @param [customCipherKey] - Custom cipher key (different from defined on client level). + * @param [options] - Specific crypto configuration options. + * + * @returns Encrypted `data`. + */ + encrypt(data, customCipherKey, options) { + if (this.configuration.customEncrypt) { + if (this.logger) + this.logger.warn('Crypto', "'customEncrypt' is deprecated. Consult docs for better alternative."); + return this.configuration.customEncrypt(data); + } + return this.pnEncrypt(data, customCipherKey, options); + } + /** + * Decrypt provided data. + * + * @param data - Encrypted data which should be decrypted. + * @param [customCipherKey] - Custom cipher key (different from defined on client level). + * @param [options] - Specific crypto configuration options. + * + * @returns Decrypted `data`. + */ + decrypt(data, customCipherKey, options) { + if (this.configuration.customDecrypt) { + if (this.logger) + this.logger.warn('Crypto', "'customDecrypt' is deprecated. Consult docs for better alternative."); + return this.configuration.customDecrypt(data); + } + return this.pnDecrypt(data, customCipherKey, options); + } + /** + * Encrypt provided data. + * + * @param data - Source data which should be encrypted. + * @param [customCipherKey] - Custom cipher key (different from defined on client level). + * @param [options] - Specific crypto configuration options. + * + * @returns Encrypted `data` as string. + */ + pnEncrypt(data, customCipherKey, options) { + const decidedCipherKey = customCipherKey !== null && customCipherKey !== void 0 ? customCipherKey : this.configuration.cipherKey; + if (!decidedCipherKey) + return data; + if (this.logger) { + this.logger.debug('Crypto', () => ({ + messageType: 'object', + message: Object.assign({ data }, (options !== null && options !== void 0 ? options : {})), + details: 'Encrypt with parameters:', + ignoredKeys: isSensitiveLogKey, + })); + } + options = this.parseOptions(options); + const mode = this.getMode(options); + const cipherKey = this.getPaddedKey(decidedCipherKey, options); + if (this.configuration.useRandomIVs) { + const waIv = this.getRandomIV(); + // @ts-expect-error Bundled library without types. + const waPayload = CryptoJS$1.AES.encrypt(data, cipherKey, { iv: waIv, mode }).ciphertext; + // @ts-expect-error Bundled library without types. + return waIv.clone().concat(waPayload.clone()).toString(CryptoJS$1.enc.Base64); + } + const iv = this.getIV(options); + // @ts-expect-error Bundled library without types. + const encryptedHexArray = CryptoJS$1.AES.encrypt(data, cipherKey, { iv, mode }).ciphertext; + // @ts-expect-error Bundled library without types. + const base64Encrypted = encryptedHexArray.toString(CryptoJS$1.enc.Base64); + return base64Encrypted || data; + } + /** + * Decrypt provided data. + * + * @param data - Encrypted data which should be decrypted. + * @param [customCipherKey] - Custom cipher key (different from defined on client level). + * @param [options] - Specific crypto configuration options. + * + * @returns Decrypted `data`. + */ + pnDecrypt(data, customCipherKey, options) { + const decidedCipherKey = customCipherKey !== null && customCipherKey !== void 0 ? customCipherKey : this.configuration.cipherKey; + if (!decidedCipherKey) + return data; + if (this.logger) { + this.logger.debug('Crypto', () => ({ + messageType: 'object', + message: Object.assign({ data }, (options !== null && options !== void 0 ? options : {})), + details: 'Decrypt with parameters:', + ignoredKeys: isSensitiveLogKey, + })); + } + options = this.parseOptions(options); + const mode = this.getMode(options); + const cipherKey = this.getPaddedKey(decidedCipherKey, options); + if (this.configuration.useRandomIVs) { + const ciphertext = new Uint8ClampedArray(decode(data)); + const iv = bufferToWordArray(ciphertext.slice(0, 16)); + const payload = bufferToWordArray(ciphertext.slice(16)); + try { + // @ts-expect-error Bundled library without types. + const plainJSON = CryptoJS$1.AES.decrypt({ ciphertext: payload }, cipherKey, { iv, mode }).toString( + // @ts-expect-error Bundled library without types. + CryptoJS$1.enc.Utf8); + return JSON.parse(plainJSON); + } + catch (e) { + if (this.logger) + this.logger.error('Crypto', () => ({ messageType: 'error', message: e })); + return null; + } + } + else { + const iv = this.getIV(options); + try { + // @ts-expect-error Bundled library without types. + const ciphertext = CryptoJS$1.enc.Base64.parse(data); + // @ts-expect-error Bundled library without types. + const plainJSON = CryptoJS$1.AES.decrypt({ ciphertext }, cipherKey, { iv, mode }).toString(CryptoJS$1.enc.Utf8); + return JSON.parse(plainJSON); + } + catch (e) { + if (this.logger) + this.logger.error('Crypto', () => ({ messageType: 'error', message: e })); + return null; + } + } + } + /** + * Pre-process provided custom crypto configuration. + * + * @param incomingOptions - Configuration which should be pre-processed before use. + * + * @returns Normalized crypto configuration options. + */ + parseOptions(incomingOptions) { + var _a, _b, _c, _d; + if (!incomingOptions) + return this.defaultOptions; + // Defaults + const options = { + encryptKey: (_a = incomingOptions.encryptKey) !== null && _a !== void 0 ? _a : this.defaultOptions.encryptKey, + keyEncoding: (_b = incomingOptions.keyEncoding) !== null && _b !== void 0 ? _b : this.defaultOptions.keyEncoding, + keyLength: (_c = incomingOptions.keyLength) !== null && _c !== void 0 ? _c : this.defaultOptions.keyLength, + mode: (_d = incomingOptions.mode) !== null && _d !== void 0 ? _d : this.defaultOptions.mode, + }; + // Validation + if (this.allowedKeyEncodings.indexOf(options.keyEncoding.toLowerCase()) === -1) + options.keyEncoding = this.defaultOptions.keyEncoding; + if (this.allowedKeyLengths.indexOf(options.keyLength) === -1) + options.keyLength = this.defaultOptions.keyLength; + if (this.allowedModes.indexOf(options.mode.toLowerCase()) === -1) + options.mode = this.defaultOptions.mode; + return options; + } + /** + * Decode provided cipher key. + * + * @param key - Key in `encoding` provided by `options`. + * @param options - Crypto configuration options with cipher key details. + * + * @returns Array buffer with decoded key. + */ + decodeKey(key, options) { + // @ts-expect-error Bundled library without types. + if (options.keyEncoding === 'base64') + return CryptoJS$1.enc.Base64.parse(key); + // @ts-expect-error Bundled library without types. + if (options.keyEncoding === 'hex') + return CryptoJS$1.enc.Hex.parse(key); + return key; + } + /** + * Add padding to the cipher key. + * + * @param key - Key which should be padded. + * @param options - Crypto configuration options with cipher key details. + * + * @returns Properly padded cipher key. + */ + getPaddedKey(key, options) { + key = this.decodeKey(key, options); + // @ts-expect-error Bundled library without types. + if (options.encryptKey) + return CryptoJS$1.enc.Utf8.parse(this.SHA256(key).slice(0, 32)); + return key; + } + /** + * Cipher mode. + * + * @param options - Crypto configuration with information about cipher mode. + * + * @returns Crypto cipher mode. + */ + getMode(options) { + // @ts-expect-error Bundled library without types. + if (options.mode === 'ecb') + return CryptoJS$1.mode.ECB; + // @ts-expect-error Bundled library without types. + return CryptoJS$1.mode.CBC; + } + /** + * Cipher initialization vector. + * + * @param options - Crypto configuration with information about cipher mode. + * + * @returns Initialization vector. + */ + getIV(options) { + // @ts-expect-error Bundled library without types. + return options.mode === 'cbc' ? CryptoJS$1.enc.Utf8.parse(this.iv) : null; + } + /** + * Random initialization vector. + * + * @returns Generated random initialization vector. + */ + getRandomIV() { + // @ts-expect-error Bundled library without types. + return CryptoJS$1.lib.WordArray.random(16); + } + } + + /** + * Legacy browser cryptography module. + * + * @internal + */ + /* global crypto */ + /** + * Legacy cryptography implementation for browser-based {@link PubNub} client. + * + * @internal + */ + class WebCryptography { + // -------------------------------------------------------- + // --------------------- Encryption ----------------------- + // -------------------------------------------------------- + // region Encryption + /** + * Encrypt provided source data using specific encryption {@link key}. + * + * @param key - Data encryption key.
**Note:** Same key should be used to `decrypt` data. + * @param input - Source data for encryption. + * + * @returns Encrypted data as object or stream (depending on from source data type). + * + * @throws Error if unknown data type has been passed. + */ + encrypt(key, input) { + return __awaiter(this, void 0, void 0, function* () { + if (!(input instanceof ArrayBuffer) && typeof input !== 'string') + throw new Error('Cannot encrypt this file. In browsers file encryption supports only string or ArrayBuffer'); + const cKey = yield this.getKey(key); + return input instanceof ArrayBuffer ? this.encryptArrayBuffer(cKey, input) : this.encryptString(cKey, input); + }); + } + /** + * Encrypt provided source {@link Buffer} using specific encryption {@link ArrayBuffer}. + * + * @param key - Data encryption key.
**Note:** Same key should be used to `decrypt` {@link ArrayBuffer}. + * @param buffer - Source {@link ArrayBuffer} for encryption. + * + * @returns Encrypted data as {@link ArrayBuffer} object. + */ + encryptArrayBuffer(key, buffer) { + return __awaiter(this, void 0, void 0, function* () { + const abIv = crypto.getRandomValues(new Uint8Array(16)); + return this.concatArrayBuffer(abIv.buffer, yield crypto.subtle.encrypt({ name: 'AES-CBC', iv: abIv }, key, buffer)); + }); + } + /** + * Encrypt provided source {@link string} using specific encryption {@link key}. + * + * @param key - Data encryption key.
**Note:** Same key should be used to `decrypt` {@link string}. + * @param text - Source {@link string} for encryption. + * + * @returns Encrypted data as byte {@link string}. + */ + encryptString(key, text) { + return __awaiter(this, void 0, void 0, function* () { + const abIv = crypto.getRandomValues(new Uint8Array(16)); + const abPlaintext = WebCryptography.encoder.encode(text).buffer; + const abPayload = yield crypto.subtle.encrypt({ name: 'AES-CBC', iv: abIv }, key, abPlaintext); + const ciphertext = this.concatArrayBuffer(abIv.buffer, abPayload); + return WebCryptography.decoder.decode(ciphertext); + }); + } + /** + * Encrypt provided {@link PubNub} File object using specific encryption {@link key}. + * + * @param key - Key for {@link PubNub} File object encryption.
**Note:** Same key should be + * used to `decrypt` data. + * @param file - Source {@link PubNub} File object for encryption. + * @param File - Class constructor for {@link PubNub} File object. + * + * @returns Encrypted data as {@link PubNub} File object. + * + * @throws Error if file is empty or contains unsupported data type. + */ + encryptFile(key, file, File) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b; + if (((_a = file.contentLength) !== null && _a !== void 0 ? _a : 0) <= 0) + throw new Error('encryption error. empty content'); + const bKey = yield this.getKey(key); + const abPlaindata = yield file.toArrayBuffer(); + const abCipherdata = yield this.encryptArrayBuffer(bKey, abPlaindata); + return File.create({ + name: file.name, + mimeType: (_b = file.mimeType) !== null && _b !== void 0 ? _b : 'application/octet-stream', + data: abCipherdata, + }); + }); + } + // endregion + // -------------------------------------------------------- + // --------------------- Decryption ----------------------- + // -------------------------------------------------------- + // region Decryption + /** + * Decrypt provided encrypted data using specific decryption {@link key}. + * + * @param key - Data decryption key.
**Note:** Should be the same as used to `encrypt` data. + * @param input - Encrypted data for decryption. + * + * @returns Decrypted data as object or stream (depending on from encrypted data type). + * + * @throws Error if unknown data type has been passed. + */ + decrypt(key, input) { + return __awaiter(this, void 0, void 0, function* () { + if (!(input instanceof ArrayBuffer) && typeof input !== 'string') + throw new Error('Cannot decrypt this file. In browsers file decryption supports only string or ArrayBuffer'); + const cKey = yield this.getKey(key); + return input instanceof ArrayBuffer ? this.decryptArrayBuffer(cKey, input) : this.decryptString(cKey, input); + }); + } + /** + * Decrypt provided encrypted {@link ArrayBuffer} using specific decryption {@link key}. + * + * @param key - Data decryption key.
**Note:** Should be the same as used to `encrypt` {@link ArrayBuffer}. + * @param buffer - Encrypted {@link ArrayBuffer} for decryption. + * + * @returns Decrypted data as {@link ArrayBuffer} object. + */ + decryptArrayBuffer(key, buffer) { + return __awaiter(this, void 0, void 0, function* () { + const abIv = buffer.slice(0, 16); + if (buffer.slice(WebCryptography.IV_LENGTH).byteLength <= 0) + throw new Error('decryption error: empty content'); + return yield crypto.subtle.decrypt({ name: 'AES-CBC', iv: abIv }, key, buffer.slice(WebCryptography.IV_LENGTH)); + }); + } + /** + * Decrypt provided encrypted {@link string} using specific decryption {@link key}. + * + * @param key - Data decryption key.
**Note:** Should be the same as used to `encrypt` {@link string}. + * @param text - Encrypted {@link string} for decryption. + * + * @returns Decrypted data as byte {@link string}. + */ + decryptString(key, text) { + return __awaiter(this, void 0, void 0, function* () { + const abCiphertext = WebCryptography.encoder.encode(text).buffer; + const abIv = abCiphertext.slice(0, 16); + const abPayload = abCiphertext.slice(16); + const abPlaintext = yield crypto.subtle.decrypt({ name: 'AES-CBC', iv: abIv }, key, abPayload); + return WebCryptography.decoder.decode(abPlaintext); + }); + } + /** + * Decrypt provided {@link PubNub} File object using specific decryption {@link key}. + * + * @param key - Key for {@link PubNub} File object decryption.
**Note:** Should be the same + * as used to `encrypt` data. + * @param file - Encrypted {@link PubNub} File object for decryption. + * @param File - Class constructor for {@link PubNub} File object. + * + * @returns Decrypted data as {@link PubNub} File object. + * + * @throws Error if file is empty or contains unsupported data type. + */ + decryptFile(key, file, File) { + return __awaiter(this, void 0, void 0, function* () { + const bKey = yield this.getKey(key); + const abCipherdata = yield file.toArrayBuffer(); + const abPlaindata = yield this.decryptArrayBuffer(bKey, abCipherdata); + return File.create({ + name: file.name, + mimeType: file.mimeType, + data: abPlaindata, + }); + }); + } + // endregion + // -------------------------------------------------------- + // ----------------------- Helpers ------------------------ + // -------------------------------------------------------- + // region Helpers + /** + * Convert cipher key to the {@link Buffer}. + * + * @param key - String cipher key. + * + * @returns SHA256 HEX encoded cipher key {@link CryptoKey}. + */ + getKey(key) { + return __awaiter(this, void 0, void 0, function* () { + const digest = yield crypto.subtle.digest('SHA-256', WebCryptography.encoder.encode(key)); + const hashHex = Array.from(new Uint8Array(digest)) + .map((b) => b.toString(16).padStart(2, '0')) + .join(''); + const abKey = WebCryptography.encoder.encode(hashHex.slice(0, 32)).buffer; + return crypto.subtle.importKey('raw', abKey, 'AES-CBC', true, ['encrypt', 'decrypt']); + }); + } + /** + * Join two `ArrayBuffer`s. + * + * @param ab1 - `ArrayBuffer` to which other buffer should be appended. + * @param ab2 - `ArrayBuffer` which should appended to the other buffer. + * + * @returns Buffer which starts with `ab1` elements and appended `ab2`. + */ + concatArrayBuffer(ab1, ab2) { + const tmp = new Uint8Array(ab1.byteLength + ab2.byteLength); + tmp.set(new Uint8Array(ab1), 0); + tmp.set(new Uint8Array(ab2), ab1.byteLength); + return tmp.buffer; + } + } + /** + * Random initialization vector size. + */ + WebCryptography.IV_LENGTH = 16; + /** + * {@link string|String} to {@link ArrayBuffer} response decoder. + */ + WebCryptography.encoder = new TextEncoder(); + /** + * {@link ArrayBuffer} to {@link string} decoder. + */ + WebCryptography.decoder = new TextDecoder(); + + /** + * Legacy cryptor module. + */ + /** + * Legacy cryptor. + */ + class LegacyCryptor { + constructor(config) { + this.config = config; + this.cryptor = new Crypto(Object.assign({}, config)); + this.fileCryptor = new WebCryptography(); + } + /** + * Update registered loggers' manager. + * + * @param [logger] - Logger, which crypto should use. + */ + set logger(logger) { + this.cryptor.logger = logger; + if (this.config.useRandomIVs === false) { + logger.warn('LegacyCryptor', `Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients. + Do not disable random IVs in new applications.`); + } + } + // -------------------------------------------------------- + // --------------------- Encryption ----------------------- + // -------------------------------------------------------- + // region Encryption + encrypt(data) { + const stringData = typeof data === 'string' ? data : LegacyCryptor.decoder.decode(data); + return { + data: this.cryptor.encrypt(stringData), + metadata: null, + }; + } + encryptFile(file, File) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + if (!this.config.cipherKey) + throw new PubNubError('File encryption error: cipher key not set.'); + return this.fileCryptor.encryptFile((_a = this.config) === null || _a === void 0 ? void 0 : _a.cipherKey, file, File); + }); + } + // endregion + // -------------------------------------------------------- + // --------------------- Decryption ----------------------- + // -------------------------------------------------------- + // region Decryption + decrypt(encryptedData) { + const data = typeof encryptedData.data === 'string' ? encryptedData.data : encode(encryptedData.data); + return this.cryptor.decrypt(data); + } + decryptFile(file, File) { + return __awaiter(this, void 0, void 0, function* () { + if (!this.config.cipherKey) + throw new PubNubError('File encryption error: cipher key not set.'); + return this.fileCryptor.decryptFile(this.config.cipherKey, file, File); + }); + } + // endregion + // -------------------------------------------------------- + // ----------------------- Helpers ------------------------ + // -------------------------------------------------------- + // region Helpers + get identifier() { + return ''; + } + // endregion + /** + * Serialize cryptor information to string. + * + * @returns Serialized cryptor information. + */ + toString() { + const configurationEntries = Object.entries(this.config).reduce((acc, [key, value]) => { + if (key === 'logger' || isSensitiveLogKey(key)) + return acc; + acc.push(`${key}: ${typeof value === 'function' ? '' : value}`); + return acc; + }, []); + return `LegacyCryptor { ${configurationEntries.join(', ')} }`; + } + } + /** + * `string` to {@link ArrayBuffer} response decoder. + */ + LegacyCryptor.encoder = new TextEncoder(); + /** + * {@link ArrayBuffer} to {@link string} decoder. + */ + LegacyCryptor.decoder = new TextDecoder(); + + /** + * Browser crypto module. + */ + /** + * CryptoModule for browser platform. + */ + class WebCryptoModule extends AbstractCryptoModule { + /** + * Assign registered loggers' manager. + * + * @param logger - Registered loggers' manager. + * + * @internal + */ + set logger(logger) { + if (this.defaultCryptor.identifier === WebCryptoModule.LEGACY_IDENTIFIER) { + logger.warn('CryptoModule', "'legacyCryptoModule' is deprecated. Use 'aesCbcCryptoModule' instead for new applications."); + this.defaultCryptor.logger = logger; + } + else { + const cryptor = this.cryptors.find((cryptor) => cryptor.identifier === WebCryptoModule.LEGACY_IDENTIFIER); + if (cryptor) + cryptor.logger = logger; + } + } + // -------------------------------------------------------- + // --------------- Convenience functions ------------------ + // ------------------------------------------------------- + // region Convenience functions + /** + * Construct crypto module with legacy cryptor for encryption and both legacy and AES-CBC + * cryptors for decryption. + * + * @deprecated Use {@link aesCbcCryptoModule} for new applications. + */ + static legacyCryptoModule(config) { + var _a; + if (!config.cipherKey) + throw new PubNubError('Crypto module error: cipher key not set.'); + if (config.logger) { + config.logger.warn('CryptoModule', "'legacyCryptoModule' is deprecated. Use 'aesCbcCryptoModule' instead for new applications."); + if (config.useRandomIVs === false) { + config.logger.warn('CryptoModule', `Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients. + Do not disable random IVs in new applications.`); + } + } + return new WebCryptoModule({ + default: new LegacyCryptor(Object.assign(Object.assign({}, config), { useRandomIVs: (_a = config.useRandomIVs) !== null && _a !== void 0 ? _a : true })), + cryptors: [new AesCbcCryptor({ cipherKey: config.cipherKey })], + }); + } + static aesCbcCryptoModule(config) { + var _a; + if (!config.cipherKey) + throw new PubNubError('Crypto module error: cipher key not set.'); + return new WebCryptoModule({ + default: new AesCbcCryptor({ cipherKey: config.cipherKey }), + cryptors: [ + new LegacyCryptor(Object.assign(Object.assign({}, config), { useRandomIVs: (_a = config.useRandomIVs) !== null && _a !== void 0 ? _a : true })), + ], + }); + } + /** + * Construct crypto module with `cryptor` as default for data encryption and decryption. + * + * @param defaultCryptor - Default cryptor for data encryption and decryption. + * + * @returns Crypto module with pre-configured default cryptor. + */ + static withDefaultCryptor(defaultCryptor) { + return new this({ default: defaultCryptor }); + } + // endregion + // -------------------------------------------------------- + // --------------------- Encryption ----------------------- + // -------------------------------------------------------- + // region Encryption + encrypt(data) { + // Encrypt data. + const encrypted = data instanceof ArrayBuffer && this.defaultCryptor.identifier === WebCryptoModule.LEGACY_IDENTIFIER + ? this.defaultCryptor.encrypt(WebCryptoModule.decoder.decode(data)) + : this.defaultCryptor.encrypt(data); + if (!encrypted.metadata) + return encrypted.data; + else if (typeof encrypted.data === 'string') + throw new Error('Encryption error: encrypted data should be ArrayBuffed.'); + const headerData = this.getHeaderData(encrypted); + return this.concatArrayBuffer(headerData, encrypted.data); + } + encryptFile(file, File) { + return __awaiter(this, void 0, void 0, function* () { + /** + * Files handled differently in case of Legacy cryptor. + * (as long as we support legacy need to check on instance type) + */ + if (this.defaultCryptor.identifier === CryptorHeader.LEGACY_IDENTIFIER) + return this.defaultCryptor.encryptFile(file, File); + const fileData = yield this.getFileData(file); + const encrypted = yield this.defaultCryptor.encryptFileData(fileData); + if (typeof encrypted.data === 'string') + throw new Error('Encryption error: encrypted data should be ArrayBuffed.'); + return File.create({ + name: file.name, + mimeType: 'application/octet-stream', + data: this.concatArrayBuffer(this.getHeaderData(encrypted), encrypted.data), + }); + }); + } + // endregion + // -------------------------------------------------------- + // --------------------- Decryption ----------------------- + // -------------------------------------------------------- + // region Decryption + decrypt(data) { + const encryptedData = typeof data === 'string' ? decode(data) : data; + const header = CryptorHeader.tryParse(encryptedData); + const cryptor = this.getCryptor(header); + const metadata = header.length > 0 + ? encryptedData.slice(header.length - header.metadataLength, header.length) + : null; + if (encryptedData.slice(header.length).byteLength <= 0) + throw new Error('Decryption error: empty content'); + return cryptor.decrypt({ + data: encryptedData.slice(header.length), + metadata: metadata, + }); + } + decryptFile(file, File) { + return __awaiter(this, void 0, void 0, function* () { + const data = yield file.data.arrayBuffer(); + const header = CryptorHeader.tryParse(data); + const cryptor = this.getCryptor(header); + /** + * Files handled differently in case of Legacy cryptor. + * (as long as we support legacy need to check on instance type) + */ + if ((cryptor === null || cryptor === void 0 ? void 0 : cryptor.identifier) === CryptorHeader.LEGACY_IDENTIFIER) + return cryptor.decryptFile(file, File); + const fileData = yield this.getFileData(data); + const metadata = fileData.slice(header.length - header.metadataLength, header.length); + return File.create({ + name: file.name, + data: yield this.defaultCryptor.decryptFileData({ + data: data.slice(header.length), + metadata: metadata, + }), + }); + }); + } + // endregion + // -------------------------------------------------------- + // ----------------------- Helpers ------------------------ + // -------------------------------------------------------- + // region Helpers + /** + * Retrieve registered cryptor by its identifier. + * + * @param id - Unique cryptor identifier. + * + * @returns Registered cryptor with specified identifier. + * + * @throws Error if cryptor with specified {@link id} can't be found. + */ + getCryptorFromId(id) { + const cryptor = this.getAllCryptors().find((cryptor) => id === cryptor.identifier); + if (cryptor) + return cryptor; + throw Error('Unknown cryptor error'); + } + /** + * Retrieve cryptor by its identifier. + * + * @param header - Header with cryptor-defined data or raw cryptor identifier. + * + * @returns Cryptor which correspond to provided {@link header}. + */ + getCryptor(header) { + if (typeof header === 'string') { + const cryptor = this.getAllCryptors().find((cryptor) => cryptor.identifier === header); + if (cryptor) + return cryptor; + throw new Error('Unknown cryptor error'); + } + else if (header instanceof CryptorHeaderV1) { + return this.getCryptorFromId(header.identifier); + } + } + /** + * Create cryptor header data. + * + * @param encrypted - Encryption data object as source for header data. + * + * @returns Binary representation of the cryptor header data. + */ + getHeaderData(encrypted) { + if (!encrypted.metadata) + return; + const header = CryptorHeader.from(this.defaultCryptor.identifier, encrypted.metadata); + const headerData = new Uint8Array(header.length); + let pos = 0; + headerData.set(header.data, pos); + pos += header.length - encrypted.metadata.byteLength; + headerData.set(new Uint8Array(encrypted.metadata), pos); + return headerData.buffer; + } + /** + * Merge two {@link ArrayBuffer} instances. + * + * @param ab1 - First {@link ArrayBuffer}. + * @param ab2 - Second {@link ArrayBuffer}. + * + * @returns Merged data as {@link ArrayBuffer}. + */ + concatArrayBuffer(ab1, ab2) { + const tmp = new Uint8Array(ab1.byteLength + ab2.byteLength); + tmp.set(new Uint8Array(ab1), 0); + tmp.set(new Uint8Array(ab2), ab1.byteLength); + return tmp.buffer; + } + /** + * Retrieve file content. + * + * @param file - Content of the {@link PubNub} File object. + * + * @returns Normalized file {@link data} as {@link ArrayBuffer}; + */ + getFileData(file) { + return __awaiter(this, void 0, void 0, function* () { + if (file instanceof ArrayBuffer) + return file; + else if (file instanceof PubNubFile) + return file.toArrayBuffer(); + throw new Error('Cannot decrypt/encrypt file. In browsers file encrypt/decrypt supported for string, ArrayBuffer or Blob'); + }); + } + } + /** + * {@link LegacyCryptor|Legacy} cryptor identifier. + */ + WebCryptoModule.LEGACY_IDENTIFIER = ''; + /** + * CryptorHeader Utility + */ + class CryptorHeader { + static from(id, metadata) { + if (id === CryptorHeader.LEGACY_IDENTIFIER) + return; + return new CryptorHeaderV1(id, metadata.byteLength); + } + static tryParse(data) { + const encryptedData = new Uint8Array(data); + let sentinel; + let version = null; + if (encryptedData.byteLength >= 4) { + sentinel = encryptedData.slice(0, 4); + if (this.decoder.decode(sentinel) !== CryptorHeader.SENTINEL) + return WebCryptoModule.LEGACY_IDENTIFIER; + } + if (encryptedData.byteLength >= 5) + version = encryptedData[4]; + else + throw new Error('Decryption error: invalid header version'); + if (version > CryptorHeader.MAX_VERSION) + throw new Error('Decryption error: Unknown cryptor error'); + let identifier; + let pos = 5 + CryptorHeader.IDENTIFIER_LENGTH; + if (encryptedData.byteLength >= pos) + identifier = encryptedData.slice(5, pos); + else + throw new Error('Decryption error: invalid crypto identifier'); + let metadataLength = null; + if (encryptedData.byteLength >= pos + 1) + metadataLength = encryptedData[pos]; + else + throw new Error('Decryption error: invalid metadata length'); + pos += 1; + if (metadataLength === 255 && encryptedData.byteLength >= pos + 2) { + metadataLength = new Uint16Array(encryptedData.slice(pos, pos + 2)).reduce((acc, val) => (acc << 8) + val, 0); + } + return new CryptorHeaderV1(this.decoder.decode(identifier), metadataLength); + } + } + CryptorHeader.SENTINEL = 'PNED'; + CryptorHeader.LEGACY_IDENTIFIER = ''; + CryptorHeader.IDENTIFIER_LENGTH = 4; + CryptorHeader.VERSION = 1; + CryptorHeader.MAX_VERSION = 1; + CryptorHeader.decoder = new TextDecoder(); + // v1 CryptorHeader + class CryptorHeaderV1 { + constructor(id, metadataLength) { + this._identifier = id; + this._metadataLength = metadataLength; + } + get identifier() { + return this._identifier; + } + set identifier(value) { + this._identifier = value; + } + get metadataLength() { + return this._metadataLength; + } + set metadataLength(value) { + this._metadataLength = value; + } + get version() { + return CryptorHeader.VERSION; + } + get length() { + return (CryptorHeader.SENTINEL.length + + 1 + + CryptorHeader.IDENTIFIER_LENGTH + + (this.metadataLength < 255 ? 1 : 3) + + this.metadataLength); + } + get data() { + let pos = 0; + const header = new Uint8Array(this.length); + const encoder = new TextEncoder(); + header.set(encoder.encode(CryptorHeader.SENTINEL)); + pos += CryptorHeader.SENTINEL.length; + header[pos] = this.version; + pos++; + if (this.identifier) + header.set(encoder.encode(this.identifier), pos); + const metadataLength = this.metadataLength; + pos += CryptorHeader.IDENTIFIER_LENGTH; + if (metadataLength < 255) + header[pos] = metadataLength; + else + header.set([255, metadataLength >> 8, metadataLength & 0xff], pos); + return header; + } + } + CryptorHeaderV1.IDENTIFIER_LENGTH = 4; + CryptorHeaderV1.SENTINEL = 'PNED'; + + /** + * REST API endpoint use error module. + * + * @internal + */ + /** + * PubNub REST API call error. + * + * @internal + */ + class PubNubAPIError extends Error { + /** + * Construct API from known error object or {@link PubNub} service error response. + * + * @param errorOrResponse - `Error` or service error response object from which error information + * should be extracted. + * @param [data] - Preprocessed service error response. + * + * @returns `PubNubAPIError` object with known error category and additional information (if + * available). + */ + static create(errorOrResponse, data) { + if (PubNubAPIError.isErrorObject(errorOrResponse)) + return PubNubAPIError.createFromError(errorOrResponse); + else + return PubNubAPIError.createFromServiceResponse(errorOrResponse, data); + } + /** + * Create API error instance from other error object. + * + * @param error - `Error` object provided by network provider (mostly) or other {@link PubNub} client components. + * + * @returns `PubNubAPIError` object with known error category and additional information (if + * available). + */ + static createFromError(error) { + let category = StatusCategory$1.PNUnknownCategory; + let message = 'Unknown error'; + let errorName = 'Error'; + if (!error) + return new PubNubAPIError(message, category, 0); + else if (error instanceof PubNubAPIError) + return error; + if (PubNubAPIError.isErrorObject(error)) { + message = error.message; + errorName = error.name; + } + if (errorName === 'AbortError' || message.indexOf('Aborted') !== -1) { + category = StatusCategory$1.PNCancelledCategory; + message = 'Request cancelled'; + } + else if (message.toLowerCase().indexOf('timeout') !== -1) { + category = StatusCategory$1.PNTimeoutCategory; + message = 'Request timeout'; + } + else if (message.toLowerCase().indexOf('network') !== -1) { + category = StatusCategory$1.PNNetworkIssuesCategory; + message = 'Network issues'; + } + else if (errorName === 'TypeError') { + if (message.indexOf('Load failed') !== -1 || message.indexOf('Failed to fetch') != -1) + category = StatusCategory$1.PNNetworkIssuesCategory; + else + category = StatusCategory$1.PNBadRequestCategory; + } + else if (errorName === 'FetchError') { + const errorCode = error.code; + if (['ECONNREFUSED', 'ENETUNREACH', 'ENOTFOUND', 'ECONNRESET', 'EAI_AGAIN'].includes(errorCode)) + category = StatusCategory$1.PNNetworkIssuesCategory; + if (errorCode === 'ECONNREFUSED') + message = 'Connection refused'; + else if (errorCode === 'ENETUNREACH') + message = 'Network not reachable'; + else if (errorCode === 'ENOTFOUND') + message = 'Server not found'; + else if (errorCode === 'ECONNRESET') + message = 'Connection reset by peer'; + else if (errorCode === 'EAI_AGAIN') + message = 'Name resolution error'; + else if (errorCode === 'ETIMEDOUT') { + category = StatusCategory$1.PNTimeoutCategory; + message = 'Request timeout'; + } + else + message = `Unknown system error: ${error}`; + } + else if (message === 'Request timeout') + category = StatusCategory$1.PNTimeoutCategory; + return new PubNubAPIError(message, category, 0, error); + } + /** + * Construct API from known {@link PubNub} service error response. + * + * @param response - Service error response object from which error information should be + * extracted. + * @param [data] - Preprocessed service error response. + * + * @returns `PubNubAPIError` object with known error category and additional information (if + * available). + */ + static createFromServiceResponse(response, data) { + let category = StatusCategory$1.PNUnknownCategory; + let errorData; + let message = 'Unknown error'; + let { status } = response; + data !== null && data !== void 0 ? data : (data = response.body); + if (status === 402) + message = 'Not available for used key set. Contact support@pubnub.com'; + else if (status === 404) + message = 'Resource not found'; + else if (status === 400) { + category = StatusCategory$1.PNBadRequestCategory; + message = 'Bad request'; + } + else if (status === 403) { + category = StatusCategory$1.PNAccessDeniedCategory; + message = 'Access denied'; + } + else if (status >= 500) { + category = StatusCategory$1.PNServerErrorCategory; + message = 'Internal server error'; + } + if (typeof response === 'object' && Object.keys(response).length === 0) { + category = StatusCategory$1.PNMalformedResponseCategory; + message = 'Malformed response (network issues)'; + status = 400; + } + // Try to get more information about error from service response. + if (data && data.byteLength > 0) { + const decoded = new TextDecoder().decode(data); + if (response.headers['content-type'].indexOf('text/javascript') !== -1 || + response.headers['content-type'].indexOf('application/json') !== -1) { + try { + const errorResponse = JSON.parse(decoded); + if (typeof errorResponse === 'object') { + if (!Array.isArray(errorResponse)) { + if ('error' in errorResponse && + (errorResponse.error === 1 || errorResponse.error === true) && + 'status' in errorResponse && + typeof errorResponse.status === 'number' && + 'message' in errorResponse && + 'service' in errorResponse) { + errorData = errorResponse; + status = errorResponse.status; + } + else + errorData = errorResponse; + if ('error' in errorResponse && errorResponse.error instanceof Error) + errorData = errorResponse.error; + } + else { + // Handling Publish API payload error. + if (typeof errorResponse[0] === 'number' && errorResponse[0] === 0) { + if (errorResponse.length > 1 && typeof errorResponse[1] === 'string') + errorData = errorResponse[1]; + } + } + } + } + catch (_) { + errorData = decoded; + } + } + else if (response.headers['content-type'].indexOf('xml') !== -1) { + const reason = /(.*)<\/Message>/gi.exec(decoded); + message = reason ? `Upload to bucket failed: ${reason[1]}` : 'Upload to bucket failed.'; + } + else { + errorData = decoded; + } + } + return new PubNubAPIError(message, category, status, errorData); + } + /** + * Construct PubNub endpoint error. + * + * @param message - Short API call error description. + * @param category - Error category. + * @param statusCode - Response HTTP status code. + * @param [errorData] - Error information. + */ + constructor(message, category, statusCode, errorData) { + super(message); + this.category = category; + this.statusCode = statusCode; + this.errorData = errorData; + this.name = 'PubNubAPIError'; + } + /** + * Convert API error object to API callback status object. + * + * @param operation - Request operation during which error happened. + * + * @returns Pre-formatted API callback status object. + */ + toStatus(operation) { + return { + error: true, + category: this.category, + operation, + statusCode: this.statusCode, + errorData: this.errorData, + // @ts-expect-error Inner helper for JSON.stringify. + toJSON: function () { + let normalizedErrorData; + const errorData = this.errorData; + if (errorData) { + try { + if (typeof errorData === 'object') { + const errorObject = Object.assign(Object.assign(Object.assign(Object.assign({}, ('name' in errorData ? { name: errorData.name } : {})), ('message' in errorData ? { message: errorData.message } : {})), ('stack' in errorData ? { stack: errorData.stack } : {})), errorData); + normalizedErrorData = JSON.parse(JSON.stringify(errorObject, PubNubAPIError.circularReplacer())); + } + else + normalizedErrorData = errorData; + } + catch (_) { + normalizedErrorData = { error: 'Could not serialize the error object' }; + } + } + // Make sure to exclude `toJSON` function from the final object. + const _a = this, status = __rest(_a, ["toJSON"]); + return JSON.stringify(Object.assign(Object.assign({}, status), { errorData: normalizedErrorData })); + }, + }; + } + /** + * Convert API error object to PubNub client error object. + * + * @param operation - Request operation during which error happened. + * @param [message] - Custom error message. + * + * @returns Client-facing pre-formatted endpoint call error. + */ + toPubNubError(operation, message) { + return new PubNubError(message !== null && message !== void 0 ? message : this.message, this.toStatus(operation)); + } + /** + * Function which handles circular references in serialized JSON. + * + * @returns Circular reference replacer function. + * + * @internal + */ + static circularReplacer() { + const visited = new WeakSet(); + return function (_, value) { + if (typeof value === 'object' && value !== null) { + if (visited.has(value)) + return '[Circular]'; + visited.add(value); + } + return value; + }; + } + /** + * Check whether provided `object` is an `Error` or not. + * + * This check is required because the error object may be tied to a different execution context (global + * environment) and won't pass `instanceof Error` from the main window. + * To protect against monkey-patching, the `fetch` function is taken from an invisible `iframe` and, as a result, + * it is bind to the separate execution context. Errors generated by `fetch` won't pass the simple + * `instanceof Error` test. + * + * @param object - Object which should be checked. + * + * @returns `true` if `object` looks like an `Error` object. + * + * @internal + */ + static isErrorObject(object) { + if (!object || typeof object !== 'object') + return false; + if (object instanceof Error) + return true; + if ('name' in object && + 'message' in object && + typeof object.name === 'string' && + typeof object.message === 'string') { + return true; + } + return Object.prototype.toString.call(object) === '[object Error]'; + } + } + + /** + * Endpoint API operation types. + */ + var RequestOperation; + (function (RequestOperation) { + // -------------------------------------------------------- + // ---------------------- Publish API --------------------- + // -------------------------------------------------------- + /** + * Data publish REST API operation. + */ + RequestOperation["PNPublishOperation"] = "PNPublishOperation"; + /** + * Signal sending REST API operation. + */ + RequestOperation["PNSignalOperation"] = "PNSignalOperation"; + // -------------------------------------------------------- + // --------------------- Subscribe API -------------------- + // -------------------------------------------------------- + /** + * Subscribe for real-time updates REST API operation. + * + * User's presence change on specified entities will trigger `join` event. + */ + RequestOperation["PNSubscribeOperation"] = "PNSubscribeOperation"; + /** + * Unsubscribe from real-time updates REST API operation. + * + * User's presence change on specified entities will trigger `leave` event. + */ + RequestOperation["PNUnsubscribeOperation"] = "PNUnsubscribeOperation"; + // -------------------------------------------------------- + // --------------------- Presence API --------------------- + // -------------------------------------------------------- + /** + * Fetch user's presence information REST API operation. + */ + RequestOperation["PNWhereNowOperation"] = "PNWhereNowOperation"; + /** + * Fetch channel's presence information REST API operation. + */ + RequestOperation["PNHereNowOperation"] = "PNHereNowOperation"; + /** + * Fetch global presence information REST API operation. + */ + RequestOperation["PNGlobalHereNowOperation"] = "PNGlobalHereNowOperation"; + /** + * Update user's information associated with specified channel REST API operation. + */ + RequestOperation["PNSetStateOperation"] = "PNSetStateOperation"; + /** + * Fetch user's information associated with the specified channel REST API operation. + */ + RequestOperation["PNGetStateOperation"] = "PNGetStateOperation"; + /** + * Announce presence on managed channels REST API operation. + */ + RequestOperation["PNHeartbeatOperation"] = "PNHeartbeatOperation"; + // -------------------------------------------------------- + // ----------------- Message Reaction API ----------------- + // -------------------------------------------------------- + /** + * Add a reaction to the specified message REST API operation. + */ + RequestOperation["PNAddMessageActionOperation"] = "PNAddActionOperation"; + /** + * Remove reaction from the specified message REST API operation. + */ + RequestOperation["PNRemoveMessageActionOperation"] = "PNRemoveMessageActionOperation"; + /** + * Fetch reactions for specific message REST API operation. + */ + RequestOperation["PNGetMessageActionsOperation"] = "PNGetMessageActionsOperation"; + RequestOperation["PNTimeOperation"] = "PNTimeOperation"; + // -------------------------------------------------------- + // ---------------------- Storage API --------------------- + // -------------------------------------------------------- + /** + * Channel history REST API operation. + */ + RequestOperation["PNHistoryOperation"] = "PNHistoryOperation"; + /** + * Delete messages from channel history REST API operation. + */ + RequestOperation["PNDeleteMessagesOperation"] = "PNDeleteMessagesOperation"; + /** + * History for channels REST API operation. + */ + RequestOperation["PNFetchMessagesOperation"] = "PNFetchMessagesOperation"; + /** + * Number of messages for channels in specified time frame REST API operation. + */ + RequestOperation["PNMessageCounts"] = "PNMessageCountsOperation"; + // -------------------------------------------------------- + // -------------------- App Context API ------------------- + // -------------------------------------------------------- + /** + * Fetch users metadata REST API operation. + */ + RequestOperation["PNGetAllUUIDMetadataOperation"] = "PNGetAllUUIDMetadataOperation"; + /** + * Fetch user metadata REST API operation. + */ + RequestOperation["PNGetUUIDMetadataOperation"] = "PNGetUUIDMetadataOperation"; + /** + * Set user metadata REST API operation. + */ + RequestOperation["PNSetUUIDMetadataOperation"] = "PNSetUUIDMetadataOperation"; + /** + * Remove user metadata REST API operation. + */ + RequestOperation["PNRemoveUUIDMetadataOperation"] = "PNRemoveUUIDMetadataOperation"; + /** + * Fetch channels metadata REST API operation. + */ + RequestOperation["PNGetAllChannelMetadataOperation"] = "PNGetAllChannelMetadataOperation"; + /** + * Fetch channel metadata REST API operation. + */ + RequestOperation["PNGetChannelMetadataOperation"] = "PNGetChannelMetadataOperation"; + /** + * Set channel metadata REST API operation. + */ + RequestOperation["PNSetChannelMetadataOperation"] = "PNSetChannelMetadataOperation"; + /** + * Remove channel metadata REST API operation. + */ + RequestOperation["PNRemoveChannelMetadataOperation"] = "PNRemoveChannelMetadataOperation"; + /** + * Fetch channel members REST API operation. + */ + RequestOperation["PNGetMembersOperation"] = "PNGetMembersOperation"; + /** + * Update channel members REST API operation. + */ + RequestOperation["PNSetMembersOperation"] = "PNSetMembersOperation"; + /** + * Fetch channel memberships REST API operation. + */ + RequestOperation["PNGetMembershipsOperation"] = "PNGetMembershipsOperation"; + /** + * Update channel memberships REST API operation. + */ + RequestOperation["PNSetMembershipsOperation"] = "PNSetMembershipsOperation"; + // -------------------------------------------------------- + // ------------------- DataSync API ---------------------- + // -------------------------------------------------------- + /** + * Create entity REST API operation. + */ + RequestOperation["PNCreateDataSyncEntityOperation"] = "PNCreateDataSyncEntityOperation"; + /** + * Get entity REST API operation. + */ + RequestOperation["PNGetDataSyncEntityOperation"] = "PNGetDataSyncEntityOperation"; + /** + * Get all entities REST API operation. + */ + RequestOperation["PNGetDataSyncEntitiesOperation"] = "PNGetDataSyncEntitiesOperation"; + /** + * Set entity REST API operation (full replacement via PUT). + */ + RequestOperation["PNSetDataSyncEntityOperation"] = "PNSetDataSyncEntityOperation"; + /** + * Update entity REST API operation (partial update via PATCH). + */ + RequestOperation["PNUpdateDataSyncEntityOperation"] = "PNUpdateDataSyncEntityOperation"; + /** + * Remove entity REST API operation. + */ + RequestOperation["PNRemoveDataSyncEntityOperation"] = "PNRemoveDataSyncEntityOperation"; + /** + * Create relationship REST API operation. + */ + RequestOperation["PNCreateDataSyncRelationshipOperation"] = "PNCreateDataSyncRelationshipOperation"; + /** + * Get relationship REST API operation. + */ + RequestOperation["PNGetDataSyncRelationshipOperation"] = "PNGetDataSyncRelationshipOperation"; + /** + * Get all relationships REST API operation. + */ + RequestOperation["PNGetDataSyncRelationshipsOperation"] = "PNGetDataSyncRelationshipsOperation"; + /** + * Set relationship REST API operation (full replacement via PUT). + */ + RequestOperation["PNSetDataSyncRelationshipOperation"] = "PNSetDataSyncRelationshipOperation"; + /** + * Update relationship REST API operation (partial update via PATCH). + */ + RequestOperation["PNUpdateDataSyncRelationshipOperation"] = "PNUpdateDataSyncRelationshipOperation"; + /** + * Remove relationship REST API operation. + */ + RequestOperation["PNRemoveDataSyncRelationshipOperation"] = "PNRemoveDataSyncRelationshipOperation"; + /** + * Create user REST API operation. + */ + RequestOperation["PNCreateDataSyncUserOperation"] = "PNCreateDataSyncUserOperation"; + /** + * Get user REST API operation. + */ + RequestOperation["PNGetDataSyncUserOperation"] = "PNGetDataSyncUserOperation"; + /** + * Get all users REST API operation. + */ + RequestOperation["PNGetDataSyncUsersOperation"] = "PNGetDataSyncUsersOperation"; + /** + * Set user REST API operation (full replacement via PUT). + */ + RequestOperation["PNSetDataSyncUserOperation"] = "PNSetDataSyncUserOperation"; + /** + * Update user REST API operation (partial update via PATCH). + */ + RequestOperation["PNUpdateDataSyncUserOperation"] = "PNUpdateDataSyncUserOperation"; + /** + * Remove user REST API operation. + */ + RequestOperation["PNRemoveDataSyncUserOperation"] = "PNRemoveDataSyncUserOperation"; + /** + * Create channel REST API operation. + */ + RequestOperation["PNCreateDataSyncChannelOperation"] = "PNCreateDataSyncChannelOperation"; + /** + * Get channel REST API operation. + */ + RequestOperation["PNGetDataSyncChannelOperation"] = "PNGetDataSyncChannelOperation"; + /** + * Get all channels REST API operation. + */ + RequestOperation["PNGetDataSyncChannelsOperation"] = "PNGetDataSyncChannelsOperation"; + /** + * Set channel REST API operation (full replacement via PUT). + */ + RequestOperation["PNSetDataSyncChannelOperation"] = "PNSetDataSyncChannelOperation"; + /** + * Update channel REST API operation (partial update via PATCH). + */ + RequestOperation["PNUpdateDataSyncChannelOperation"] = "PNUpdateDataSyncChannelOperation"; + /** + * Remove channel REST API operation. + */ + RequestOperation["PNRemoveDataSyncChannelOperation"] = "PNRemoveDataSyncChannelOperation"; + /** + * Create membership REST API operation. + */ + RequestOperation["PNCreateDataSyncMembershipOperation"] = "PNCreateDataSyncMembershipOperation"; + /** + * Get membership REST API operation. + */ + RequestOperation["PNGetDataSyncMembershipOperation"] = "PNGetDataSyncMembershipOperation"; + /** + * Get all memberships REST API operation. + */ + RequestOperation["PNGetDataSyncMembershipsOperation"] = "PNGetDataSyncMembershipsOperation"; + /** + * Set membership REST API operation (full replacement via PUT). + */ + RequestOperation["PNSetDataSyncMembershipOperation"] = "PNSetDataSyncMembershipOperation"; + /** + * Update membership REST API operation (partial update via PATCH). + */ + RequestOperation["PNUpdateDataSyncMembershipOperation"] = "PNUpdateDataSyncMembershipOperation"; + /** + * Remove membership REST API operation. + */ + RequestOperation["PNRemoveDataSyncMembershipOperation"] = "PNRemoveDataSyncMembershipOperation"; + // -------------------------------------------------------- + // -------------------- File Upload API ------------------- + // -------------------------------------------------------- + /** + * Fetch list of files sent to the channel REST API operation. + */ + RequestOperation["PNListFilesOperation"] = "PNListFilesOperation"; + /** + * Retrieve file upload URL REST API operation. + */ + RequestOperation["PNGenerateUploadUrlOperation"] = "PNGenerateUploadUrlOperation"; + /** + * Upload file to the channel REST API operation. + */ + RequestOperation["PNPublishFileOperation"] = "PNPublishFileOperation"; + /** + * Publish File Message to the channel REST API operation. + */ + RequestOperation["PNPublishFileMessageOperation"] = "PNPublishFileMessageOperation"; + /** + * Retrieve file download URL REST API operation. + */ + RequestOperation["PNGetFileUrlOperation"] = "PNGetFileUrlOperation"; + /** + * Download file from the channel REST API operation. + */ + RequestOperation["PNDownloadFileOperation"] = "PNDownloadFileOperation"; + /** + * Delete file sent to the channel REST API operation. + */ + RequestOperation["PNDeleteFileOperation"] = "PNDeleteFileOperation"; + // -------------------------------------------------------- + // -------------------- Mobile Push API ------------------- + // -------------------------------------------------------- + /** + * Register channels with device push notifications REST API operation. + */ + RequestOperation["PNAddPushNotificationEnabledChannelsOperation"] = "PNAddPushNotificationEnabledChannelsOperation"; + /** + * Unregister channels with device push notifications REST API operation. + */ + RequestOperation["PNRemovePushNotificationEnabledChannelsOperation"] = "PNRemovePushNotificationEnabledChannelsOperation"; + /** + * Fetch list of channels with enabled push notifications for device REST API operation. + */ + RequestOperation["PNPushNotificationEnabledChannelsOperation"] = "PNPushNotificationEnabledChannelsOperation"; + /** + * Disable push notifications for device REST API operation. + */ + RequestOperation["PNRemoveAllPushNotificationsOperation"] = "PNRemoveAllPushNotificationsOperation"; + // -------------------------------------------------------- + // ------------------ Channel Groups API ------------------ + // -------------------------------------------------------- + /** + * Fetch channels groups list REST API operation. + */ + RequestOperation["PNChannelGroupsOperation"] = "PNChannelGroupsOperation"; + /** + * Remove specified channel group REST API operation. + */ + RequestOperation["PNRemoveGroupOperation"] = "PNRemoveGroupOperation"; + /** + * Fetch list of channels for the specified channel group REST API operation. + */ + RequestOperation["PNChannelsForGroupOperation"] = "PNChannelsForGroupOperation"; + /** + * Add list of channels to the specified channel group REST API operation. + */ + RequestOperation["PNAddChannelsToGroupOperation"] = "PNAddChannelsToGroupOperation"; + /** + * Remove list of channels from the specified channel group REST API operation. + */ + RequestOperation["PNRemoveChannelsFromGroupOperation"] = "PNRemoveChannelsFromGroupOperation"; + // -------------------------------------------------------- + // ----------------------- PAM API ------------------------ + // -------------------------------------------------------- + /** + * Generate authorized token REST API operation. + */ + RequestOperation["PNAccessManagerGrant"] = "PNAccessManagerGrant"; + /** + * Generate authorized token REST API operation. + */ + RequestOperation["PNAccessManagerGrantToken"] = "PNAccessManagerGrantToken"; + RequestOperation["PNAccessManagerAudit"] = "PNAccessManagerAudit"; + /** + * Revoke authorized token REST API operation. + */ + RequestOperation["PNAccessManagerRevokeToken"] = "PNAccessManagerRevokeToken"; + // + // -------------------------------------------------------- + // ---------------- Subscription Utility ------------------ + // -------------------------------------------------------- + /** + * Initial event engine subscription handshake operation. + * + * @internal + */ + RequestOperation["PNHandshakeOperation"] = "PNHandshakeOperation"; + /** + * Event engine subscription loop operation. + * + * @internal + */ + RequestOperation["PNReceiveMessagesOperation"] = "PNReceiveMessagesOperation"; + })(RequestOperation || (RequestOperation = {})); + var RequestOperation$1 = RequestOperation; + + /** + * Subscription Worker transport middleware module. + * + * Middleware optimize subscription feature requests utilizing `Subscription Worker` if available and not disabled + * by user. + * + * @internal + */ + // endregion + /** + * Subscription Worker transport middleware. + */ + class SubscriptionWorkerMiddleware { + constructor(configuration) { + this.configuration = configuration; + /** + * Whether subscription worker has been initialized and ready to handle events. + */ + this.subscriptionWorkerReady = false; + /** + * Map of base64-encoded access tokens to their parsed representations. + */ + this.accessTokensMap = {}; + this.workerEventsQueue = []; + this.callbacks = new Map(); + this.setupSubscriptionWorker(); + } + /** + * Set status emitter from the PubNub client. + * + * @param emitter - Function which should be used to emit events. + */ + set emitStatus(emitter) { + this._emitStatus = emitter; + } + /** + * Update client's `userId`. + * + * @param userId - User ID which will be used by the PubNub client further. + */ + onUserIdChange(userId) { + this.configuration.userId = userId; + this.scheduleEventPost({ + type: 'client-update', + heartbeatInterval: this.configuration.heartbeatInterval, + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + userId: this.configuration.userId, + workerLogLevel: this.configuration.workerLogLevel, + }); + } + /** + * Update presence state associated with `userId`. + * + * @param state - Key-value pair of payloads (states) that should be associated with channels / groups specified as + * keys. + */ + onPresenceStateChange(state) { + this.scheduleEventPost({ + type: 'client-presence-state-update', + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + workerLogLevel: this.configuration.workerLogLevel, + state, + }); + } + /** + * Update client's heartbeat interval change. + * + * @param interval - Interval which should be used by timers for _backup_ heartbeat calls created in `SharedWorker`. + */ + onHeartbeatIntervalChange(interval) { + this.configuration.heartbeatInterval = interval; + this.scheduleEventPost({ + type: 'client-update', + heartbeatInterval: this.configuration.heartbeatInterval, + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + userId: this.configuration.userId, + workerLogLevel: this.configuration.workerLogLevel, + }); + } + /** + * Handle authorization key / token change. + * + * @param [token] - Authorization token which should be used. + */ + onTokenChange(token) { + const updateEvent = { + type: 'client-update', + heartbeatInterval: this.configuration.heartbeatInterval, + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + userId: this.configuration.userId, + workerLogLevel: this.configuration.workerLogLevel, + }; + // Trigger request processing by Service Worker. + this.parsedAccessToken(token) + .then((accessToken) => { + updateEvent.preProcessedToken = accessToken; + updateEvent.accessToken = token; + }) + .then(() => this.scheduleEventPost(updateEvent)); + } + /** + * Disconnect client and terminate ongoing long-poll requests (if needed). + */ + disconnect() { + this.scheduleEventPost({ + type: 'client-disconnect', + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + workerLogLevel: this.configuration.workerLogLevel, + }); + } + /** + * Terminate all ongoing long-poll requests. + */ + terminate() { + this.scheduleEventPost({ + type: 'client-unregister', + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + workerLogLevel: this.configuration.workerLogLevel, + }); + } + makeSendable(req) { + // Use default request flow for non-subscribe / presence leave requests. + if (!req.path.startsWith('/v2/subscribe') && !req.path.endsWith('/heartbeat') && !req.path.endsWith('/leave')) + return this.configuration.transport.makeSendable(req); + this.configuration.logger.debug('SubscriptionWorkerMiddleware', 'Process request with SharedWorker transport.'); + let controller; + const sendRequestEvent = { + type: 'send-request', + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + request: req, + workerLogLevel: this.configuration.workerLogLevel, + }; + if (req.cancellable) { + controller = { + abort: () => { + const cancelRequest = { + type: 'cancel-request', + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + identifier: req.identifier, + workerLogLevel: this.configuration.workerLogLevel, + }; + // Cancel active request with specified identifier. + this.scheduleEventPost(cancelRequest); + }, + }; + } + return [ + new Promise((resolve, reject) => { + // Associate Promise resolution / reject with a request identifier for future usage in + // the `onmessage ` handler block to return results. + this.callbacks.set(req.identifier, { resolve, reject }); + // Trigger request processing by Service Worker. + this.parsedAccessTokenForRequest(req) + .then((accessToken) => (sendRequestEvent.preProcessedToken = accessToken)) + .then(() => this.scheduleEventPost(sendRequestEvent)); + }), + controller, + ]; + } + request(req) { + return req; + } + /** + * Schedule {@link event} publish to the subscription worker. + * + * Subscription worker may not be ready for events processing and this method build queue for the time when worker + * will be ready. + * + * @param event - Event payload for the subscription worker. + * @param outOfOrder - Whether event should be processed first then enqueued queue. + */ + scheduleEventPost(event, outOfOrder = false) { + // Trigger request processing by a subscription worker. + const subscriptionWorker = this.sharedSubscriptionWorker; + if (subscriptionWorker) + subscriptionWorker.port.postMessage(event); + else { + if (outOfOrder) + this.workerEventsQueue.splice(0, 0, event); + else + this.workerEventsQueue.push(event); + } + } + /** + * Dequeue and post events from the queue to the subscription worker. + */ + flushScheduledEvents() { + // Trigger request processing by a subscription worker. + const subscriptionWorker = this.sharedSubscriptionWorker; + if (!subscriptionWorker || this.workerEventsQueue.length === 0) + return; + // Clean up from canceled events. + const outdatedEvents = []; + for (let i = 0; i < this.workerEventsQueue.length; i++) { + const event = this.workerEventsQueue[i]; + // Check whether found request cancel event to search for request send event it cancels. + if (event.type !== 'cancel-request' || i === 0) + continue; + for (let j = 0; j < i; j++) { + const otherEvent = this.workerEventsQueue[j]; + if (otherEvent.type !== 'send-request') + continue; + // Collect outdated events if identifiers match. + if (otherEvent.request.identifier === event.identifier) { + outdatedEvents.push(event, otherEvent); + break; + } + } + } + // Actualizing events queue. + this.workerEventsQueue = this.workerEventsQueue.filter((event) => !outdatedEvents.includes(event)); + this.workerEventsQueue.forEach((event) => subscriptionWorker.port.postMessage(event)); + this.workerEventsQueue = []; + } + /** + * Subscription worker. + * + * @returns Worker which has been registered by the PubNub SDK. + */ + get sharedSubscriptionWorker() { + return this.subscriptionWorkerReady ? this.subscriptionWorker : null; + } + setupSubscriptionWorker() { + if (typeof SharedWorker === 'undefined') + return; + try { + this.subscriptionWorker = new SharedWorker(this.configuration.workerUrl, `/pubnub-${this.configuration.sdkVersion}`); + } + catch (error) { + this.configuration.logger.error('SubscriptionWorkerMiddleware', () => ({ + messageType: 'error', + message: error, + })); + throw error; + } + this.subscriptionWorker.port.start(); + // Register PubNub client within subscription worker. + this.scheduleEventPost({ + type: 'client-register', + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + userId: this.configuration.userId, + heartbeatInterval: this.configuration.heartbeatInterval, + workerOfflineClientsCheckInterval: this.configuration.workerOfflineClientsCheckInterval, + workerUnsubscribeOfflineClients: this.configuration.workerUnsubscribeOfflineClients, + workerLogLevel: this.configuration.workerLogLevel, + }, true); + this.subscriptionWorker.port.onmessage = (event) => this.handleWorkerEvent(event); + if (this.shouldAnnounceNewerSharedWorkerVersionAvailability()) + localStorage.setItem('PNSubscriptionSharedWorkerVersion', this.configuration.sdkVersion); + window.addEventListener('storage', (event) => { + if (event.key !== 'PNSubscriptionSharedWorkerVersion' || !event.newValue) + return; + if (this._emitStatus && this.isNewerSharedWorkerVersion(event.newValue)) + this._emitStatus({ error: false, category: StatusCategory$1.PNSharedWorkerUpdatedCategory }); + }); + } + handleWorkerEvent(event) { + const { data } = event; + // Ignoring updates not related to this instance. + if (data.type !== 'shared-worker-ping' && + data.type !== 'shared-worker-connected' && + data.type !== 'shared-worker-console-log' && + data.type !== 'shared-worker-console-dir' && + data.clientIdentifier !== this.configuration.clientIdentifier) + return; + if (data.type === 'shared-worker-connected') { + this.configuration.logger.trace('SharedWorker', 'Ready for events processing.'); + this.subscriptionWorkerReady = true; + this.flushScheduledEvents(); + } + else if (data.type === 'shared-worker-console-log') { + this.configuration.logger.debug('SharedWorker', () => { + if (typeof data.message === 'string' || typeof data.message === 'number' || typeof data.message === 'boolean') { + return { + messageType: 'text', + message: data.message, + }; + } + return data.message; + }); + } + else if (data.type === 'shared-worker-console-dir') { + this.configuration.logger.debug('SharedWorker', () => { + return { + messageType: 'object', + message: data.data, + details: data.message ? data.message : undefined, + }; + }); + } + else if (data.type === 'shared-worker-ping') { + const { subscriptionKey, clientIdentifier } = this.configuration; + this.scheduleEventPost({ + type: 'client-pong', + subscriptionKey, + clientIdentifier, + workerLogLevel: this.configuration.workerLogLevel, + }); + } + else if (data.type === 'request-process-success' || data.type === 'request-process-error') { + if (this.callbacks.has(data.identifier)) { + const { resolve, reject } = this.callbacks.get(data.identifier); + this.callbacks.delete(data.identifier); + if (data.type === 'request-process-success') { + resolve({ + status: data.response.status, + url: data.url, + headers: data.response.headers, + body: data.response.body, + }); + } + else + reject(this.errorFromRequestSendingError(data)); + } + // Handling "backup" heartbeat which doesn't have registered callbacks. + else if (this._emitStatus && data.url.indexOf('/v2/presence') >= 0 && data.url.indexOf('/heartbeat') >= 0) { + if (data.type === 'request-process-success' && this.configuration.announceSuccessfulHeartbeats) { + this._emitStatus({ + statusCode: data.response.status, + error: false, + operation: RequestOperation$1.PNHeartbeatOperation, + category: StatusCategory$1.PNAcknowledgmentCategory, + }); + } + else if (data.type === 'request-process-error' && this.configuration.announceFailedHeartbeats) + this._emitStatus(this.errorFromRequestSendingError(data).toStatus(RequestOperation$1.PNHeartbeatOperation)); + } + } + } + /** + * Get parsed access token object from request. + * + * @param req - Transport request which may contain access token for processing. + * + * @returns Object with stringified access token information and expiration date information. + */ + parsedAccessTokenForRequest(req) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + return this.parsedAccessToken(req.queryParameters ? ((_a = req.queryParameters.auth) !== null && _a !== void 0 ? _a : '') : undefined); + }); + } + /** + * Get parsed access token object. + * + * @param accessToken - Access token for processing. + * + * @returns Object with stringified access token information and expiration date information. + */ + parsedAccessToken(accessToken) { + return __awaiter(this, void 0, void 0, function* () { + if (!accessToken) + return undefined; + else if (this.accessTokensMap[accessToken]) + return this.accessTokensMap[accessToken]; + return this.stringifyAccessToken(accessToken).then(([token, stringifiedToken]) => { + if (!token || !stringifiedToken) + return undefined; + return (this.accessTokensMap = { + [accessToken]: { token: stringifiedToken, expiration: token.timestamp + token.ttl * 60 }, + })[accessToken]; + }); + }); + } + /** + * Stringify access token content. + * + * Stringify information about resources with permissions. + * + * @param tokenString - Base64-encoded access token which should be parsed and stringified. + * + * @returns Tuple with parsed access token and its stringified content hash string. + */ + stringifyAccessToken(tokenString) { + return __awaiter(this, void 0, void 0, function* () { + if (!this.configuration.tokenManager) + return [undefined, undefined]; + const token = this.configuration.tokenManager.parseToken(tokenString); + if (!token) + return [undefined, undefined]; + // Translate permission to short string built from first chars of enabled permission. + const stringifyPermissions = (permission) => Object.entries(permission) + .filter(([_, v]) => v) + .map(([k]) => k[0]) + .sort() + .join(''); + const stringifyResources = (resource) => resource + ? Object.entries(resource) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([type, entries]) => Object.entries(entries || {}) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([name, perms]) => `${type}:${name}=${perms ? stringifyPermissions(perms) : ''}`) + .join(',')) + .join(';') + : ''; + let accessToken = [stringifyResources(token.resources), stringifyResources(token.patterns), token.authorized_uuid] + .filter(Boolean) + .join('|'); + if (typeof crypto !== 'undefined' && crypto.subtle) { + const hash = yield crypto.subtle.digest('SHA-256', new TextEncoder().encode(accessToken)); + accessToken = String.fromCharCode(...Array.from(new Uint8Array(hash))); + } + return [token, typeof btoa !== 'undefined' ? btoa(accessToken) : accessToken]; + }); + } + /** + * Create error from failure received from the `SharedWorker`. + * + * @param sendingError - Request sending error received from the `SharedWorker`. + * + * @returns `PubNubAPIError` instance with request processing failure information. + */ + errorFromRequestSendingError(sendingError) { + let category = StatusCategory$1.PNUnknownCategory; + let message = 'Unknown error'; + // Handle client-side issues (if any). + if (sendingError.error) { + if (sendingError.error.type === 'NETWORK_ISSUE') + category = StatusCategory$1.PNNetworkIssuesCategory; + else if (sendingError.error.type === 'TIMEOUT') + category = StatusCategory$1.PNTimeoutCategory; + else if (sendingError.error.type === 'ABORTED') + category = StatusCategory$1.PNCancelledCategory; + message = `${sendingError.error.message} (${sendingError.identifier})`; + } + // Handle service error response. + else if (sendingError.response) { + const { url, response } = sendingError; + return PubNubAPIError.create({ url, headers: response.headers, body: response.body, status: response.status }, response.body); + } + return new PubNubAPIError(message, category, 0, new Error(message)); + } + /** + * Check whether current subscription `SharedWorker` version should be announced or not. + * + * @returns `true` if local storage is empty (only newer version will add value) or stored version is smaller than + * current. + */ + shouldAnnounceNewerSharedWorkerVersionAvailability() { + const version = localStorage.getItem('PNSubscriptionSharedWorkerVersion'); + if (!version) + return true; + return !this.isNewerSharedWorkerVersion(version); + } + /** + * Check whether current subscription `SharedWorker` version should be announced or not. + * + * @param version - Stored (received on init or event) version of subscription shared worker. + * @returns `true` if provided `version` is newer than current client version. + */ + isNewerSharedWorkerVersion(version) { + const [currentMajor, currentMinor, currentPatch] = this.configuration.sdkVersion.split('.').map(Number); + const [storedMajor, storedMinor, storedPatch] = version.split('.').map(Number); + return storedMajor > currentMajor || storedMinor > currentMinor || storedPatch > currentPatch; + } + } + + /** + * CBOR support module. + * + * @internal + */ + /** + * Re-map CBOR object keys from potentially C buffer strings to actual strings. + * + * @param obj CBOR which should be remapped to stringified keys. + * @param nestingLevel PAM token structure nesting level. + * + * @returns Dictionary with stringified keys. + * + * @internal + */ + function stringifyBufferKeys(obj, nestingLevel = 0) { + const isObject = (value) => typeof value === 'object' && value !== null && value.constructor === Object; + const isString = (value) => typeof value === 'string' || value instanceof String; + const isNumber = (value) => typeof value === 'number' && isFinite(value); + if (!isObject(obj)) + return obj; + const normalizedObject = {}; + Object.keys(obj).forEach((key) => { + const keyIsString = isString(key); + let stringifiedKey = key; + const value = obj[key]; + if (nestingLevel < 2) { + if (keyIsString && key.indexOf(',') >= 0) { + const bytes = key.split(',').map(Number); + stringifiedKey = bytes.reduce((string, byte) => { + return string + String.fromCharCode(byte); + }, ''); + } + else if (isNumber(key) || (keyIsString && !isNaN(Number(key)))) { + stringifiedKey = String.fromCharCode(isNumber(key) ? key : parseInt(key, 10)); + } + } + normalizedObject[stringifiedKey] = isObject(value) ? stringifyBufferKeys(value, nestingLevel + 1) : value; + }); + return normalizedObject; + } + + /** + * {@link PubNub} client configuration module. + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether secured connection should be used by or not. + */ + const USE_SSL = true; + /** + * Whether PubNub client should catch up subscription after network issues. + */ + const RESTORE = true; + /** + * Whether network availability change should be announced with `PNNetworkDownCategory` and + * `PNNetworkUpCategory` state or not. + */ + const AUTO_NETWORK_DETECTION = false; + /** + * Whether messages should be de-duplicated before announcement or not. + */ + const DEDUPE_ON_SUBSCRIBE = false; + /** + * Maximum cache which should be used for message de-duplication functionality. + */ + const DEDUPE_CACHE_SIZE = 100; + /** + * Maximum number of file message publish retries. + */ + const FILE_PUBLISH_RETRY_LIMIT = 5; + /** + * Whether subscription event engine should be used or not. + */ + const ENABLE_EVENT_ENGINE = true; + /** + * Whether configured user presence state should be maintained by the PubNub client or not. + */ + const MAINTAIN_PRESENCE_STATE = true; + /** + * Whether heartbeat should be postponed on successful subscribe response or not. + */ + const USE_SMART_HEARTBEAT = false; + /** + * Whether PubNub client should try to utilize existing TCP connection for new requests or not. + */ + const KEEP_ALIVE$1 = false; + /** + * Whether leave events should be suppressed or not. + */ + const SUPPRESS_LEAVE_EVENTS = false; + /** + * Whether heartbeat request failure should be announced or not. + */ + const ANNOUNCE_HEARTBEAT_FAILURE = true; + /** + * Whether heartbeat request success should be announced or not. + */ + const ANNOUNCE_HEARTBEAT_SUCCESS = false; + /** + * Whether PubNub client instance id should be added to the requests or not. + */ + const USE_INSTANCE_ID = false; + /** + * Whether unique identifier should be added to the request or not. + */ + const USE_REQUEST_ID = true; + /** + * Transactional requests timeout. + */ + const TRANSACTIONAL_REQUEST_TIMEOUT = 15; + /** + * Subscription request timeout. + */ + const SUBSCRIBE_REQUEST_TIMEOUT = 310; + /** + * File upload / download request timeout. + */ + const FILE_REQUEST_TIMEOUT = 300; + /** + * Default user presence timeout. + */ + const PRESENCE_TIMEOUT = 300; + /** + * Maximum user presence timeout. + */ + const PRESENCE_TIMEOUT_MAXIMUM = 320; + /** + * Apply configuration default values. + * + * @param configuration - User-provided configuration. + * + * @internal + */ + const setDefaults$1 = (configuration) => { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; + // Copy configuration. + const configurationCopy = Object.assign({}, configuration); + (_a = configurationCopy.ssl) !== null && _a !== void 0 ? _a : (configurationCopy.ssl = USE_SSL); + (_b = configurationCopy.transactionalRequestTimeout) !== null && _b !== void 0 ? _b : (configurationCopy.transactionalRequestTimeout = TRANSACTIONAL_REQUEST_TIMEOUT); + (_c = configurationCopy.subscribeRequestTimeout) !== null && _c !== void 0 ? _c : (configurationCopy.subscribeRequestTimeout = SUBSCRIBE_REQUEST_TIMEOUT); + (_d = configurationCopy.fileRequestTimeout) !== null && _d !== void 0 ? _d : (configurationCopy.fileRequestTimeout = FILE_REQUEST_TIMEOUT); + (_e = configurationCopy.restore) !== null && _e !== void 0 ? _e : (configurationCopy.restore = RESTORE); + (_f = configurationCopy.useInstanceId) !== null && _f !== void 0 ? _f : (configurationCopy.useInstanceId = USE_INSTANCE_ID); + (_g = configurationCopy.suppressLeaveEvents) !== null && _g !== void 0 ? _g : (configurationCopy.suppressLeaveEvents = SUPPRESS_LEAVE_EVENTS); + (_h = configurationCopy.requestMessageCountThreshold) !== null && _h !== void 0 ? _h : (configurationCopy.requestMessageCountThreshold = DEDUPE_CACHE_SIZE); + (_j = configurationCopy.autoNetworkDetection) !== null && _j !== void 0 ? _j : (configurationCopy.autoNetworkDetection = AUTO_NETWORK_DETECTION); + (_k = configurationCopy.enableEventEngine) !== null && _k !== void 0 ? _k : (configurationCopy.enableEventEngine = ENABLE_EVENT_ENGINE); + (_l = configurationCopy.maintainPresenceState) !== null && _l !== void 0 ? _l : (configurationCopy.maintainPresenceState = MAINTAIN_PRESENCE_STATE); + (_m = configurationCopy.useSmartHeartbeat) !== null && _m !== void 0 ? _m : (configurationCopy.useSmartHeartbeat = USE_SMART_HEARTBEAT); + (_o = configurationCopy.keepAlive) !== null && _o !== void 0 ? _o : (configurationCopy.keepAlive = KEEP_ALIVE$1); + if (configurationCopy.userId && configurationCopy.uuid) + throw new PubNubError("PubNub client configuration error: use only 'userId'"); + (_p = configurationCopy.userId) !== null && _p !== void 0 ? _p : (configurationCopy.userId = configurationCopy.uuid); + if (!configurationCopy.userId) + throw new PubNubError("PubNub client configuration error: 'userId' not set"); + else if (((_q = configurationCopy.userId) === null || _q === void 0 ? void 0 : _q.trim().length) === 0) + throw new PubNubError("PubNub client configuration error: 'userId' is empty"); + // Generate default origin subdomains. + if (!configurationCopy.origin) + configurationCopy.origin = Array.from({ length: 20 }, (_, i) => `ps${i + 1}.pndsn.com`); + const keySet = { + subscribeKey: configurationCopy.subscribeKey, + publishKey: configurationCopy.publishKey, + secretKey: configurationCopy.secretKey, + }; + if (configurationCopy.presenceTimeout !== undefined) { + if (configurationCopy.presenceTimeout > PRESENCE_TIMEOUT_MAXIMUM) { + configurationCopy.presenceTimeout = PRESENCE_TIMEOUT_MAXIMUM; + // eslint-disable-next-line no-console + console.warn('WARNING: Presence timeout is larger than the maximum. Using maximum value: ', PRESENCE_TIMEOUT_MAXIMUM); + } + else if (configurationCopy.presenceTimeout <= 0) { + // eslint-disable-next-line no-console + console.warn('WARNING: Presence timeout should be larger than zero.'); + delete configurationCopy.presenceTimeout; + } + } + if (configurationCopy.presenceTimeout !== undefined) + configurationCopy.heartbeatInterval = configurationCopy.presenceTimeout / 2 - 1; + else + configurationCopy.presenceTimeout = PRESENCE_TIMEOUT; + // Apply extended configuration defaults. + let announceSuccessfulHeartbeats = ANNOUNCE_HEARTBEAT_SUCCESS; + let announceFailedHeartbeats = ANNOUNCE_HEARTBEAT_FAILURE; + let fileUploadPublishRetryLimit = FILE_PUBLISH_RETRY_LIMIT; + let dedupeOnSubscribe = DEDUPE_ON_SUBSCRIBE; + let maximumCacheSize = DEDUPE_CACHE_SIZE; + let useRequestId = USE_REQUEST_ID; + // @ts-expect-error Not documented legacy configuration options. + if (configurationCopy.dedupeOnSubscribe !== undefined && typeof configurationCopy.dedupeOnSubscribe === 'boolean') { + // @ts-expect-error Not documented legacy configuration options. + dedupeOnSubscribe = configurationCopy.dedupeOnSubscribe; + } + // @ts-expect-error Not documented legacy configuration options. + if (configurationCopy.maximumCacheSize !== undefined && typeof configurationCopy.maximumCacheSize === 'number') { + // @ts-expect-error Not documented legacy configuration options. + maximumCacheSize = configurationCopy.maximumCacheSize; + } + // @ts-expect-error Not documented legacy configuration options. + if (configurationCopy.useRequestId !== undefined && typeof configurationCopy.useRequestId === 'boolean') { + // @ts-expect-error Not documented legacy configuration options. + useRequestId = configurationCopy.useRequestId; + } + if ( + // @ts-expect-error Not documented legacy configuration options. + configurationCopy.announceSuccessfulHeartbeats !== undefined && + // @ts-expect-error Not documented legacy configuration options. + typeof configurationCopy.announceSuccessfulHeartbeats === 'boolean') { + // @ts-expect-error Not documented legacy configuration options. + announceSuccessfulHeartbeats = configurationCopy.announceSuccessfulHeartbeats; + } + if ( + // @ts-expect-error Not documented legacy configuration options. + configurationCopy.announceFailedHeartbeats !== undefined && + // @ts-expect-error Not documented legacy configuration options. + typeof configurationCopy.announceFailedHeartbeats === 'boolean') { + // @ts-expect-error Not documented legacy configuration options. + announceFailedHeartbeats = configurationCopy.announceFailedHeartbeats; + } + if ( + // @ts-expect-error Not documented legacy configuration options. + configurationCopy.fileUploadPublishRetryLimit !== undefined && + // @ts-expect-error Not documented legacy configuration options. + typeof configurationCopy.fileUploadPublishRetryLimit === 'number') { + // @ts-expect-error Not documented legacy configuration options. + fileUploadPublishRetryLimit = configurationCopy.fileUploadPublishRetryLimit; + } + return Object.assign(Object.assign({}, configurationCopy), { keySet, + dedupeOnSubscribe, + maximumCacheSize, + useRequestId, + announceSuccessfulHeartbeats, + announceFailedHeartbeats, + fileUploadPublishRetryLimit }); + }; + + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether PubNub client should update its state using browser's reachability events or not. + * + * If the browser fails to detect the network changes from Wi-Fi to LAN and vice versa, or you get + * reconnection issues, set the flag to `false`. This allows the SDK reconnection logic to take over. + */ + const LISTEN_TO_BROWSER_NETWORK_EVENTS = true; + /** + * Whether verbose logging should be enabled for `Subscription` worker to print debug messages or not. + */ + const SUBSCRIPTION_WORKER_LOG_VERBOSITY = false; + /** + * Interval at which Shared Worker should check whether PubNub instances which used it still active or not. + */ + const SUBSCRIPTION_WORKER_OFFLINE_CLIENTS_CHECK_INTERVAL = 10; + /** + * Whether `leave` request should be sent for _offline_ PubNub client or not. + */ + const SUBSCRIPTION_WORKER_UNSUBSCRIBE_OFFLINE_CLIENTS = false; + /** + * Use modern Web Fetch API for network requests by default. + */ + const TRANSPORT = 'fetch'; + /** + * Whether PubNub client should try to utilize existing TCP connection for new requests or not. + */ + const KEEP_ALIVE = true; + /** + * Apply configuration default values. + * + * @param configuration - User-provided configuration. + * + * @internal + */ + const setDefaults = (configuration) => { + var _a, _b, _c, _d, _e, _f; + // Force to disable service workers if the environment doesn't support them. + if (configuration.subscriptionWorkerUrl && typeof SharedWorker === 'undefined') { + configuration.subscriptionWorkerUrl = null; + } + return Object.assign(Object.assign({}, setDefaults$1(configuration)), { + // Set platform-specific options. + listenToBrowserNetworkEvents: (_a = configuration.listenToBrowserNetworkEvents) !== null && _a !== void 0 ? _a : LISTEN_TO_BROWSER_NETWORK_EVENTS, subscriptionWorkerUrl: configuration.subscriptionWorkerUrl, subscriptionWorkerOfflineClientsCheckInterval: (_b = configuration.subscriptionWorkerOfflineClientsCheckInterval) !== null && _b !== void 0 ? _b : SUBSCRIPTION_WORKER_OFFLINE_CLIENTS_CHECK_INTERVAL, subscriptionWorkerUnsubscribeOfflineClients: (_c = configuration.subscriptionWorkerUnsubscribeOfflineClients) !== null && _c !== void 0 ? _c : SUBSCRIPTION_WORKER_UNSUBSCRIBE_OFFLINE_CLIENTS, subscriptionWorkerLogVerbosity: (_d = configuration.subscriptionWorkerLogVerbosity) !== null && _d !== void 0 ? _d : SUBSCRIPTION_WORKER_LOG_VERBOSITY, transport: (_e = configuration.transport) !== null && _e !== void 0 ? _e : TRANSPORT, keepAlive: (_f = configuration.keepAlive) !== null && _f !== void 0 ? _f : KEEP_ALIVE }); + }; + + /** + * Enum with available log levels. + */ + var LogLevel; + (function (LogLevel) { + /** + * Used to notify about every last detail: + * - function calls, + * - full payloads, + * - internal variables, + * - state-machine hops. + */ + LogLevel[LogLevel["Trace"] = 0] = "Trace"; + /** + * Used to notify about broad strokes of your SDK’s logic: + * - inputs/outputs to public methods, + * - network request + * - network response + * - decision branches. + */ + LogLevel[LogLevel["Debug"] = 1] = "Debug"; + /** + * Used to notify summary of what the SDK is doing under the hood: + * - initialized, + * - connected, + * - entity created. + */ + LogLevel[LogLevel["Info"] = 2] = "Info"; + /** + * Used to notify about non-fatal events: + * - deprecations, + * - request retries. + */ + LogLevel[LogLevel["Warn"] = 3] = "Warn"; + /** + * Used to notify about: + * - exceptions, + * - HTTP failures, + * - invalid states. + */ + LogLevel[LogLevel["Error"] = 4] = "Error"; + /** + * Logging disabled. + */ + LogLevel[LogLevel["None"] = 5] = "None"; + })(LogLevel || (LogLevel = {})); + + /** + * Default console-based logger. + * + * **Important:** This logger is always added as part of {@link LoggerManager} instance configuration and can't be + * removed. + * + * @internal + */ + /** + * Custom {@link Logger} implementation to show a message in the native console. + */ + class ConsoleLogger { + /** + * Process a `debug` level message. + * + * @param message - Message which should be handled by custom logger implementation. + */ + debug(message) { + this.log(message); + } + /** + * Process a `error` level message. + * + * @param message - Message which should be handled by custom logger implementation. + */ + error(message) { + this.log(message); + } + /** + * Process an `info` level message. + * + * @param message - Message which should be handled by custom logger implementation. + */ + info(message) { + this.log(message); + } + /** + * Process a `trace` level message. + * + * @param message - Message which should be handled by custom logger implementation. + */ + trace(message) { + this.log(message); + } + /** + * Process an `warn` level message. + * + * @param message - Message which should be handled by custom logger implementation. + */ + warn(message) { + this.log(message); + } + /** + * Stringify logger object. + * + * @returns Serialized logger object. + */ + toString() { + return `ConsoleLogger {}`; + } + /** + * Process log message object. + * + * @param message - Object with information which can be used to identify level and prepare log entry payload. + */ + log(message) { + const logLevelString = LogLevel[message.level]; + const level = logLevelString.toLowerCase(); + console[level === 'trace' ? 'debug' : level](`${message.timestamp.toISOString()} PubNub-${message.pubNubId} ${logLevelString.padEnd(5, ' ')}${message.location ? ` ${message.location}` : ''} ${this.logMessage(message)}`); + } + /** + * Get a pre-formatted log message. + * + * @param message - Log message which should be stringified. + * + * @returns String formatted for log entry in console. + */ + logMessage(message) { + if (message.messageType === 'text') + return message.message; + else if (message.messageType === 'object') + return `${message.details ? `${message.details}\n` : ''}${this.formattedObject(message)}`; + else if (message.messageType === 'network-request') { + const showOnlyBasicInfo = !!message.canceled || !!message.failed; + const headersList = message.minimumLevel === LogLevel.Trace && !showOnlyBasicInfo ? this.formattedHeaders(message) : undefined; + const request = message.message; + const queryString = request.queryParameters && Object.keys(request.queryParameters).length > 0 + ? queryStringFromObject(request.queryParameters) + : undefined; + const url = `${request.origin}${request.path}${queryString ? `?${queryString}` : ''}`; + const formattedBody = !showOnlyBasicInfo ? this.formattedBody(message) : undefined; + let action = 'Sending'; + if (showOnlyBasicInfo) + action = `${!!message.canceled ? 'Canceled' : 'Failed'}${message.details ? ` (${message.details})` : ''}`; + const padding = ((formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.formData) ? 'FormData' : 'Method').length; + return `${action} HTTP request:\n ${this.paddedString('Method', padding)}: ${request.method}\n ${this.paddedString('URL', padding)}: ${url}${headersList ? `\n ${this.paddedString('Headers', padding)}:\n${headersList}` : ''}${(formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.formData) ? `\n ${this.paddedString('FormData', padding)}:\n${formattedBody.formData}` : ''}${(formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.body) ? `\n ${this.paddedString('Body', padding)}:\n${formattedBody.body}` : ''}`; + } + else if (message.messageType === 'network-response') { + const headersList = message.minimumLevel === LogLevel.Trace ? this.formattedHeaders(message) : undefined; + const formattedBody = this.formattedBody(message); + const padding = ((formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.formData) ? 'Headers' : 'Status').length; + const response = message.message; + return `Received HTTP response:\n ${this.paddedString('URL', padding)}: ${response.url}\n ${this.paddedString('Status', padding)}: ${response.status}${message.details ? `\n ${this.paddedString('Details', padding)}: ${message.details}` : ''}${headersList ? `\n ${this.paddedString('Headers', padding)}:\n${headersList}` : ''}${(formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.body) ? `\n ${this.paddedString('Body', padding)}:\n${formattedBody.body}` : ''}`; + } + else if (message.messageType === 'error') { + const formattedStatus = this.formattedErrorStatus(message); + const error = message.message; + return `${error.name}: ${error.message}${formattedStatus ? `\n${formattedStatus}` : ''}`; + } + return ''; + } + /** + * Get a pre-formatted object (dictionary / array). + * + * @param message - Log message which may contain an object for formatting. + * + * @returns String formatted for log entry in console or `undefined` if a log message doesn't have suitable data. + */ + formattedObject(message) { + const stringify = (obj, level = 1, skipIndentOnce = false) => { + const maxIndentReached = level === 10; + const targetIndent = ' '.repeat(level * 2); + const lines = []; + const isIgnored = (key, obj) => { + if (!message.ignoredKeys) + return false; + if (typeof message.ignoredKeys === 'function') + return message.ignoredKeys(key, obj); + return message.ignoredKeys.includes(key); + }; + if (typeof obj === 'string') + lines.push(`${targetIndent}- ${obj}`); + else if (typeof obj === 'number') + lines.push(`${targetIndent}- ${obj}`); + else if (typeof obj === 'boolean') + lines.push(`${targetIndent}- ${obj}`); + else if (obj === null) + lines.push(`${targetIndent}- null`); + else if (obj === undefined) + lines.push(`${targetIndent}- undefined`); + else if (typeof obj === 'function') + lines.push(`${targetIndent}- `); + else if (typeof obj === 'object') { + if (!Array.isArray(obj) && typeof obj.toString === 'function' && obj.toString().indexOf('[object') !== 0) { + lines.push(`${skipIndentOnce ? '' : targetIndent}${obj.toString()}`); + skipIndentOnce = false; + } + else if (Array.isArray(obj)) { + for (const element of obj) { + const indent = skipIndentOnce ? '' : targetIndent; + if (element === null) + lines.push(`${indent}- null`); + else if (element === undefined) + lines.push(`${indent}- undefined`); + else if (typeof element === 'function') + lines.push(`${indent}- `); + else if (typeof element === 'object') { + const isArray = Array.isArray(element); + const entry = maxIndentReached ? '...' : stringify(element, level + 1, !isArray); + lines.push(`${indent}-${isArray && !maxIndentReached ? '\n' : ' '}${entry}`); + } + else + lines.push(`${indent}- ${element}`); + skipIndentOnce = false; + } + } + else { + const object = obj; + const keys = Object.keys(object); + const maxKeyLen = keys.reduce((max, key) => Math.max(max, isIgnored(key, object) ? max : key.length), 0); + for (const key of keys) { + if (isIgnored(key, object)) + continue; + const indent = skipIndentOnce ? '' : targetIndent; + const raw = object[key]; + const paddedKey = key.padEnd(maxKeyLen, ' '); + if (raw === null) + lines.push(`${indent}${paddedKey}: null`); + else if (raw === undefined) + lines.push(`${indent}${paddedKey}: undefined`); + else if (typeof raw === 'function') + lines.push(`${indent}${paddedKey}: `); + else if (typeof raw === 'object') { + const isArray = Array.isArray(raw); + const isEmptyArray = isArray && raw.length === 0; + const isEmptyObject = !isArray && !(raw instanceof String) && Object.keys(raw).length === 0; + const hasToString = !isArray && typeof raw.toString === 'function' && raw.toString().indexOf('[object') !== 0; + const entry = maxIndentReached + ? '...' + : isEmptyArray + ? '[]' + : isEmptyObject + ? '{}' + : stringify(raw, level + 1, hasToString); + lines.push(`${indent}${paddedKey}:${maxIndentReached || hasToString || isEmptyArray || isEmptyObject ? ' ' : '\n'}${entry}`); + } + else + lines.push(`${indent}${paddedKey}: ${raw}`); + skipIndentOnce = false; + } + } + } + return lines.join('\n'); + }; + return stringify(message.message); + } + /** + * Get a pre-formatted headers list. + * + * @param message - Log message which may contain an object with headers to be used for formatting. + * + * @returns String formatted for log entry in console or `undefined` if a log message not related to the network data. + */ + formattedHeaders(message) { + if (!message.message.headers) + return undefined; + const headers = message.message.headers; + const maxHeaderLength = Object.keys(headers).reduce((max, key) => Math.max(max, key.length), 0); + return Object.keys(headers) + .map((key) => ` - ${key.toLowerCase().padEnd(maxHeaderLength, ' ')}: ${headers[key]}`) + .join('\n'); + } + /** + * Get a pre-formatted body. + * + * @param message - Log message which may contain an object with `body` (request or response). + * + * @returns Object with formatted string of form data and / or body for log entry in console or `undefined` if a log + * message not related to the network data. + */ + formattedBody(message) { + var _a; + if (!message.message.headers) + return undefined; + let stringifiedFormData; + let stringifiedBody; + const headers = message.message.headers; + const contentType = (_a = headers['content-type']) !== null && _a !== void 0 ? _a : headers['Content-Type']; + const formData = 'formData' in message.message ? message.message.formData : undefined; + const body = message.message.body; + // The presence of this object means that we are sending `multipart/form-data` (potentially uploading a file). + if (formData) { + const maxFieldLength = formData.reduce((max, { key }) => Math.max(max, key.length), 0); + stringifiedFormData = formData + .map(({ key, value }) => ` - ${key.padEnd(maxFieldLength, ' ')}: ${value}`) + .join('\n'); + } + if (!body) + return { formData: stringifiedFormData }; + if (typeof body === 'string') { + stringifiedBody = ` ${body}`; + } + else if (body instanceof ArrayBuffer || Object.prototype.toString.call(body) === '[object ArrayBuffer]') { + if (contentType && (contentType.indexOf('javascript') !== -1 || contentType.indexOf('json') !== -1)) + stringifiedBody = ` ${ConsoleLogger.decoder.decode(body)}`; + else + stringifiedBody = ` ArrayBuffer { byteLength: ${body.byteLength} }`; + } + else { + stringifiedBody = ` File { name: ${body.name}${body.contentLength ? `, contentLength: ${body.contentLength}` : ''}${body.mimeType ? `, mimeType: ${body.mimeType}` : ''} }`; + } + return { body: stringifiedBody, formData: stringifiedFormData }; + } + /** + * Get a pre-formatted status object. + * + * @param message - Log message which may contain a {@link Status} object. + * + * @returns String formatted for log entry in console or `undefined` if a log message doesn't have {@link Status} + * object. + */ + formattedErrorStatus(message) { + if (!message.message.status) + return undefined; + const status = message.message.status; + const errorData = status.errorData; + let stringifiedErrorData; + if (ConsoleLogger.isError(errorData)) { + stringifiedErrorData = ` ${errorData.name}: ${errorData.message}`; + if (errorData.stack) { + stringifiedErrorData += `\n${errorData.stack + .split('\n') + .map((line) => ` ${line}`) + .join('\n')}`; + } + } + else if (errorData) { + try { + stringifiedErrorData = ` ${JSON.stringify(errorData)}`; + } + catch (_) { + stringifiedErrorData = ` ${errorData}`; + } + } + return ` Category : ${status.category}\n Operation : ${status.operation}\n Status : ${status.statusCode}${stringifiedErrorData ? `\n Error data:\n${stringifiedErrorData}` : ''}`; + } + /** + * Append the required amount of space to provide proper padding. + * + * @param str - Source string which should be appended with necessary number of spaces. + * @param maxLength - Maximum length of the string to which source string should be padded. + * @returns End-padded string. + */ + paddedString(str, maxLength) { + return str.padEnd(maxLength - str.length, ' '); + } + /** + * Check whether passed object is {@link Error} instance. + * + * @param errorData - Object which should be checked. + * + * @returns `true` in case if an object actually {@link Error}. + */ + static isError(errorData) { + if (!errorData) + return false; + return errorData instanceof Error || Object.prototype.toString.call(errorData) === '[object Error]'; + } + } + /** + * Binary data decoder. + */ + ConsoleLogger.decoder = new TextDecoder(); + + /** + * HTTP status codes which represent definitive client-side outcomes and shouldn't be retried. + * + * @internal + */ + const NON_RETRIABLE_STATUS_CODES = [404, 409]; + // -------------------------------------------------------- + // ------------------------ Types ------------------------- + // -------------------------------------------------------- + // region Types + /** + * List of known endpoint groups (by context). + */ + var Endpoint; + (function (Endpoint) { + /** + * Unknown endpoint. + * + * @internal + */ + Endpoint["Unknown"] = "UnknownEndpoint"; + /** + * The endpoints to send messages. + * + * This is related to the following functionality: + * - `publish` + * - `signal` + * - `publish file` + * - `fire` + */ + Endpoint["MessageSend"] = "MessageSendEndpoint"; + /** + * The endpoint for real-time update retrieval. + * + * This is related to the following functionality: + * - `subscribe` + */ + Endpoint["Subscribe"] = "SubscribeEndpoint"; + /** + * The endpoint to access and manage `user_id` presence and fetch channel presence information. + * + * This is related to the following functionality: + * - `get presence state` + * - `set presence state` + * - `here now` + * - `where now` + * - `heartbeat` + */ + Endpoint["Presence"] = "PresenceEndpoint"; + /** + * The endpoint to access and manage files in channel-specific storage. + * + * This is related to the following functionality: + * - `send file` + * - `download file` + * - `list files` + * - `delete file` + */ + Endpoint["Files"] = "FilesEndpoint"; + /** + * The endpoint to access and manage messages for a specific channel(s) in the persistent storage. + * + * This is related to the following functionality: + * - `fetch messages / message actions` + * - `delete messages` + * - `messages count` + */ + Endpoint["MessageStorage"] = "MessageStorageEndpoint"; + /** + * The endpoint to access and manage channel groups. + * + * This is related to the following functionality: + * - `add channels to group` + * - `list channels in group` + * - `remove channels from group` + * - `list channel groups` + */ + Endpoint["ChannelGroups"] = "ChannelGroupsEndpoint"; + /** + * The endpoint to access and manage device registration for channel push notifications. + * + * This is related to the following functionality: + * - `enable channels for push notifications` + * - `list push notification enabled channels` + * - `disable push notifications for channels` + * - `disable push notifications for all channels` + */ + Endpoint["DevicePushNotifications"] = "DevicePushNotificationsEndpoint"; + /** + * The endpoint to access and manage App Context objects. + * + * This is related to the following functionality: + * - `set UUID metadata` + * - `get UUID metadata` + * - `remove UUID metadata` + * - `get all UUID metadata` + * - `set Channel metadata` + * - `get Channel metadata` + * - `remove Channel metadata` + * - `get all Channel metadata` + * - `manage members` + * - `list members` + * - `manage memberships` + * - `list memberships` + */ + Endpoint["AppContext"] = "AppContextEndpoint"; + /** + * The endpoint to access and manage reactions for a specific message. + * + * This is related to the following functionality: + * - `add message action` + * - `get message actions` + * - `remove message action` + */ + Endpoint["MessageReactions"] = "MessageReactionsEndpoint"; + })(Endpoint || (Endpoint = {})); + // endregion + /** + * Failed request retry policy. + */ + class RetryPolicy { + static None() { + return { + shouldRetry(_request, _response, _errorCategory, _attempt, _statusCode) { + return false; + }, + getDelay(_attempt, _response) { + return -1; + }, + validate() { + return true; + }, + }; + } + static LinearRetryPolicy(configuration) { + var _a; + return { + delay: configuration.delay, + maximumRetry: configuration.maximumRetry, + excluded: (_a = configuration.excluded) !== null && _a !== void 0 ? _a : [], + shouldRetry(request, response, error, attempt, statusCode) { + return isRetriableRequest(request, response, error, attempt !== null && attempt !== void 0 ? attempt : 0, this.maximumRetry, this.excluded, statusCode); + }, + getDelay(_, response) { + let delay = -1; + if (response && response.headers['retry-after'] !== undefined) + delay = parseInt(response.headers['retry-after'], 10); + if (delay === -1) + delay = this.delay; + return (delay + Math.random()) * 1000; + }, + validate() { + if (this.delay < 2) + throw new Error('Delay can not be set less than 2 seconds for retry'); + }, + }; + } + static ExponentialRetryPolicy(configuration) { + var _a; + return { + minimumDelay: configuration.minimumDelay, + maximumDelay: configuration.maximumDelay, + maximumRetry: configuration.maximumRetry, + excluded: (_a = configuration.excluded) !== null && _a !== void 0 ? _a : [], + shouldRetry(request, response, error, attempt, statusCode) { + return isRetriableRequest(request, response, error, attempt !== null && attempt !== void 0 ? attempt : 0, this.maximumRetry, this.excluded, statusCode); + }, + getDelay(attempt, response) { + let delay = -1; + if (response && response.headers['retry-after'] !== undefined) + delay = parseInt(response.headers['retry-after'], 10); + if (delay === -1) + delay = Math.min(this.minimumDelay * Math.pow(2, attempt), this.maximumDelay); + return (delay + Math.random()) * 1000; + }, + validate() { + if (this.minimumDelay < 2) + throw new Error('Minimum delay can not be set less than 2 seconds for retry'); + }, + }; + } + } + /** + * Check whether request can be retried or not. + * + * @param req - Request for which retry ability is checked. + * @param res - Service response which should be taken into consideration. + * @param errorCategory - Request processing error category. + * @param retryAttempt - Current retry attempt. + * @param maximumRetry - Maximum retry attempts count according to the retry policy. + * @param excluded - List of endpoints for which retry policy won't be applied. + * @param statusCode - Response HTTP status code (available when request failed with an error and hence there is no + * `res`). + * + * @return `true` if request can be retried. + * + * @internal + */ + const isRetriableRequest = (req, res, errorCategory, retryAttempt, maximumRetry, excluded, statusCode) => { + var _a; + if (errorCategory) { + if (errorCategory === StatusCategory$1.PNCancelledCategory || + errorCategory === StatusCategory$1.PNBadRequestCategory || + errorCategory === StatusCategory$1.PNAccessDeniedCategory) + return false; + } + if (isExcludedRequest(req, excluded)) + return false; + else if (retryAttempt > maximumRetry) + return false; + // Status code is reported separately from the `res` when the request failed with an error. + const status = (_a = res === null || res === void 0 ? void 0 : res.status) !== null && _a !== void 0 ? _a : statusCode; + if (status !== undefined && NON_RETRIABLE_STATUS_CODES.includes(status)) + return false; + return res ? res.status === 429 || res.status >= 500 : true; + }; + /** + * Check whether the provided request is in the list of endpoints for which retry is not allowed or not. + * + * @param req - Request which will be tested. + * @param excluded - List of excluded endpoints configured for retry policy. + * + * @returns `true` if request has been excluded and shouldn't be retried. + * + * @internal + */ + const isExcludedRequest = (req, excluded) => excluded && excluded.length > 0 ? excluded.includes(endpointFromRequest(req)) : false; + /** + * Identify API group from transport request. + * + * @param req - Request for which `path` will be analyzed to identify REST API group. + * + * @returns Endpoint group to which request belongs. + * + * @internal + */ + const endpointFromRequest = (req) => { + let endpoint = Endpoint.Unknown; + if (req.path.startsWith('/v2/subscribe')) + endpoint = Endpoint.Subscribe; + else if (req.path.startsWith('/publish/') || req.path.startsWith('/signal/')) + endpoint = Endpoint.MessageSend; + else if (req.path.startsWith('/v2/presence')) + endpoint = Endpoint.Presence; + else if (req.path.startsWith('/v2/history') || req.path.startsWith('/v3/history')) + endpoint = Endpoint.MessageStorage; + else if (req.path.startsWith('/v1/message-actions/')) + endpoint = Endpoint.MessageReactions; + else if (req.path.startsWith('/v1/channel-registration/')) + endpoint = Endpoint.ChannelGroups; + else if (req.path.startsWith('/v2/objects/')) + endpoint = Endpoint.ChannelGroups; + else if (req.path.startsWith('/v1/push/') || req.path.startsWith('/v2/push/')) + endpoint = Endpoint.DevicePushNotifications; + else if (req.path.startsWith('/v1/files/')) + endpoint = Endpoint.Files; + return endpoint; + }; + + /** + * Logging module manager. + * + * Manager responsible for log requests handling and forwarding to the registered {@link Logger logger} implementations. + */ + class LoggerManager { + /** + * Create and configure loggers' manager. + * + * @param pubNubId - Unique identifier of PubNub instance which will use this logger. + * @param minLogLevel - Minimum messages log level to be logged. + * @param loggers - List of additional loggers which should be used along with user-provided custom loggers. + * + * @internal + */ + constructor(pubNubId, minLogLevel, loggers) { + /** + * Keeping track of previous entry timestamp. + * + * This information will be used to make sure that multiple sequential entries doesn't have same timestamp. Adjustment + * on .001 will be done to make it possible to properly stort entries. + * + * @internal + */ + this.previousEntryTimestamp = 0; + this.pubNubId = pubNubId; + this.minLogLevel = minLogLevel; + this.loggers = loggers; + } + /** + * Get current log level. + * + * @returns Current log level. + * + * @internal + */ + get logLevel() { + return this.minLogLevel; + } + /** + * Process a `trace` level message. + * + * @param location - Call site from which a log message has been sent. + * @param messageFactory - Lazy message factory function or string for a text log message. + * + * @internal + */ + trace(location, messageFactory) { + this.log(LogLevel.Trace, location, messageFactory); + } + /** + * Process a `debug` level message. + * + * @param location - Call site from which a log message has been sent. + * @param messageFactory - Lazy message factory function or string for a text log message. + * + * @internal + */ + debug(location, messageFactory) { + this.log(LogLevel.Debug, location, messageFactory); + } + /** + * Process an `info` level message. + * + * @param location - Call site from which a log message has been sent. + * @param messageFactory - Lazy message factory function or string for a text log message. + * + * @internal + */ + info(location, messageFactory) { + this.log(LogLevel.Info, location, messageFactory); + } + /** + * Process a `warn` level message. + * + * @param location - Call site from which a log message has been sent. + * @param messageFactory - Lazy message factory function or string for a text log message. + * + * @internal + */ + warn(location, messageFactory) { + this.log(LogLevel.Warn, location, messageFactory); + } + /** + * Process an `error` level message. + * + * @param location - Call site from which a log message has been sent. + * @param messageFactory - Lazy message factory function or string for a text log message. + * + * @internal + */ + error(location, messageFactory) { + this.log(LogLevel.Error, location, messageFactory); + } + /** + * Process log message. + * + * @param logLevel - Logged message level. + * @param location - Call site from which a log message has been sent. + * @param messageFactory - Lazy message factory function or string for a text log message. + * + * @internal + */ + log(logLevel, location, messageFactory) { + // Check whether a log message should be handled at all or not. + if (logLevel < this.minLogLevel || this.loggers.length === 0) + return; + const date = new Date(); + if (date.getTime() <= this.previousEntryTimestamp) { + this.previousEntryTimestamp++; + date.setTime(this.previousEntryTimestamp); + } + else + this.previousEntryTimestamp = date.getTime(); + const level = LogLevel[logLevel].toLowerCase(); + const message = Object.assign({ timestamp: date, pubNubId: this.pubNubId, level: logLevel, minimumLevel: this.minLogLevel, location }, (typeof messageFactory === 'function' ? messageFactory() : { messageType: 'text', message: messageFactory })); + this.loggers.forEach((logger) => logger[level](message)); + } + } + + var uuid = {exports: {}}; + + /*! lil-uuid - v0.1 - MIT License - https://github.com/lil-js/uuid */ + uuid.exports; + + (function (module, exports) { + (function (root, factory) { + { + factory(exports); + if (module !== null) { + module.exports = exports.uuid; + } + } + }(commonjsGlobal, function (exports) { + var VERSION = '0.1.0'; + var uuidRegex = { + '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, + '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i + }; + + function uuid() { + var uuid = '', i, random; + for (i = 0; i < 32; i++) { + random = Math.random() * 16 | 0; + if (i === 8 || i === 12 || i === 16 || i === 20) uuid += '-'; + uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random)).toString(16); + } + return uuid + } + + function isUUID(str, version) { + var pattern = uuidRegex[version || 'all']; + return pattern && pattern.test(str) || false + } + + uuid.isUUID = isUUID; + uuid.VERSION = VERSION; + + exports.uuid = uuid; + exports.isUUID = isUUID; + })); + } (uuid, uuid.exports)); + + var uuidExports = uuid.exports; + var uuidGenerator$1 = /*@__PURE__*/getDefaultExportFromCjs(uuidExports); + + /** + * Random identifier generator helper module. + * + * @internal + */ + /** @internal */ + var uuidGenerator = { + createUUID() { + if (uuidGenerator$1.uuid) { + return uuidGenerator$1.uuid(); + } + // @ts-expect-error Depending on module type it may be callable. + return uuidGenerator$1(); + }, + }; + + /** + * {@link PubNub} client configuration module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether encryption (if set) should use random initialization vector or not. + * + * @internal + */ + const USE_RANDOM_INITIALIZATION_VECTOR = true; + /** + * Create {@link PubNub} client private configuration object. + * + * @param base - User- and platform-provided configuration. + * @param setupCryptoModule - Platform-provided {@link ICryptoModule} configuration block. + * + * @returns `PubNub` client private configuration. + * + * @internal + */ + const makeConfiguration = (base, setupCryptoModule) => { + var _a, _b, _c, _d; + // Set the default retry policy for subscribing (if new subscribe logic not used). + if (!base.retryConfiguration && base.enableEventEngine) { + base.retryConfiguration = RetryPolicy.ExponentialRetryPolicy({ + minimumDelay: 2, + maximumDelay: 150, + maximumRetry: 6, + excluded: [ + Endpoint.MessageSend, + Endpoint.Presence, + Endpoint.Files, + Endpoint.MessageStorage, + Endpoint.ChannelGroups, + Endpoint.DevicePushNotifications, + Endpoint.AppContext, + Endpoint.MessageReactions, + ], + }); + } + const instanceId = `pn-${uuidGenerator.createUUID()}`; + if (base.logVerbosity) + base.logLevel = LogLevel.Debug; + else if (base.logLevel === undefined) + base.logLevel = LogLevel.None; + // Prepare loggers manager. + const loggerManager = new LoggerManager(hashFromString(instanceId), base.logLevel, [ + ...((_a = base.loggers) !== null && _a !== void 0 ? _a : []), + new ConsoleLogger(), + ]); + if (base.logVerbosity !== undefined) + loggerManager.warn('Configuration', "'logVerbosity' is deprecated. Use 'logLevel' instead."); + // Ensure that retry policy has proper configuration (if has been set). + (_b = base.retryConfiguration) === null || _b === void 0 ? void 0 : _b.validate(); + const explicitUseRandomIVs = base.useRandomIVs; + (_c = base.useRandomIVs) !== null && _c !== void 0 ? _c : (base.useRandomIVs = USE_RANDOM_INITIALIZATION_VECTOR); + if (explicitUseRandomIVs !== undefined) { + loggerManager.warn('Configuration', "'useRandomIVs' is deprecated. Pass it to 'cryptoModule' instead."); + if (explicitUseRandomIVs === false) { + loggerManager.warn('Configuration', `Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients. + Do not disable random IVs in new applications.`); + } + } + // Override origin value. + base.origin = standardOrigin((_d = base.ssl) !== null && _d !== void 0 ? _d : false, base.origin); + const cryptoModule = base.cryptoModule; + if (cryptoModule) + delete base.cryptoModule; + const clientConfiguration = Object.assign(Object.assign({}, base), { _pnsdkSuffix: {}, _loggerManager: loggerManager, _instanceId: instanceId, _cryptoModule: undefined, _cipherKey: undefined, _setupCryptoModule: setupCryptoModule, get instanceId() { + if (base.useInstanceId) + return this._instanceId; + return undefined; + }, + getInstanceId() { + if (base.useInstanceId) + return this._instanceId; + return undefined; + }, + getUserId() { + return this.userId; + }, + setUserId(value) { + if (!value || typeof value !== 'string' || value.trim().length === 0) + throw new Error('Missing or invalid userId parameter. Provide a valid string userId'); + this.userId = value; + }, + logger() { + return this._loggerManager; + }, + getAuthKey() { + return this.authKey; + }, + setAuthKey(authKey) { + this.authKey = authKey; + }, + getFilterExpression() { + return this.filterExpression; + }, + setFilterExpression(expression) { + this.filterExpression = expression; + }, + getCipherKey() { + return this._cipherKey; + }, + setCipherKey(key) { + this._cipherKey = key; + if (!key && this._cryptoModule) { + this._cryptoModule = undefined; + return; + } + else if (!key || !this._setupCryptoModule) + return; + this._cryptoModule = this._setupCryptoModule({ + cipherKey: key, + useRandomIVs: base.useRandomIVs, + customEncrypt: this.getCustomEncrypt(), + customDecrypt: this.getCustomDecrypt(), + logger: this.logger(), + }); + }, + getCryptoModule() { + return this._cryptoModule; + }, + getUseRandomIVs() { + return base.useRandomIVs; + }, + isSharedWorkerEnabled() { + // @ts-expect-error: Access field from web-based SDK configuration. + return base.sdkFamily === 'Web' && base['subscriptionWorkerUrl']; + }, + getKeepPresenceChannelsInPresenceRequests() { + // @ts-expect-error: Access field from web-based SDK configuration. + return base.sdkFamily === 'Web' && base['subscriptionWorkerUrl']; + }, + setPresenceTimeout(value) { + this.heartbeatInterval = value / 2 - 1; + this.presenceTimeout = value; + }, + getPresenceTimeout() { + return this.presenceTimeout; + }, + getHeartbeatInterval() { + return this.heartbeatInterval; + }, + setHeartbeatInterval(interval) { + this.heartbeatInterval = interval; + }, + getTransactionTimeout() { + return this.transactionalRequestTimeout; + }, + getSubscribeTimeout() { + return this.subscribeRequestTimeout; + }, + getFileTimeout() { + return this.fileRequestTimeout; + }, + get PubNubFile() { + return base.PubNubFile; + }, + get version() { + return '13.1.2'; + }, + getVersion() { + return this.version; + }, + _addPnsdkSuffix(name, suffix) { + this._pnsdkSuffix[name] = `${suffix}`; + }, + _getPnsdkSuffix(separator) { + const sdk = Object.values(this._pnsdkSuffix).join(separator); + return sdk.length > 0 ? separator + sdk : ''; + }, + // -------------------------------------------------------- + // ---------------------- Deprecated ---------------------- + // -------------------------------------------------------- + // region Deprecated + getUUID() { + return this.getUserId(); + }, + setUUID(value) { + this.setUserId(value); + }, + getCustomEncrypt() { + return base.customEncrypt; + }, + getCustomDecrypt() { + return base.customDecrypt; + } }); + // Setup `CryptoModule` if possible. + if (base.cipherKey) { + loggerManager.warn('Configuration', "'cipherKey' is deprecated. Use 'cryptoModule' instead."); + clientConfiguration.setCipherKey(base.cipherKey); + } + else if (cryptoModule) + clientConfiguration._cryptoModule = cryptoModule; + return clientConfiguration; + }; + /** + * Decide {@lin PubNub} service REST API origin. + * + * @param secure - Whether preferred to use secured connection or not. + * @param origin - User-provided or default origin. + * + * @returns `PubNub` REST API endpoints origin. + */ + const standardOrigin = (secure, origin) => { + const protocol = secure ? 'https://' : 'http://'; + if (typeof origin === 'string') + return `${protocol}${origin}`; + return `${protocol}${origin[Math.floor(Math.random() * origin.length)]}`; + }; + /** + * Compute 32bit hash string from source value. + * + * @param value - String from which hash string should be computed. + * + * @returns Computed hash. + */ + const hashFromString = (value) => { + let basis = 0x811c9dc5; + for (let i = 0; i < value.length; i++) { + basis ^= value.charCodeAt(i); + basis = (basis + ((basis << 1) + (basis << 4) + (basis << 7) + (basis << 8) + (basis << 24))) >>> 0; + } + return basis.toString(16).padStart(8, '0'); + }; + + /** + * PubNub Access Token Manager module. + * + * @internal + */ + // endregion + /** + * REST API access token manager. + * + * Manager maintains active access token and let parse it to get information about permissions. + * + * @internal + */ + class TokenManager { + constructor(cbor) { + this.cbor = cbor; + } + /** + * Update REST API access token. + * + * **Note:** Token will be applied only for next requests and won't affect ongoing requests. + * + * @param [token] - Access token which should be used to access PubNub REST API. + */ + setToken(token) { + if (token && token.length > 0) + this.token = token; + else + this.token = undefined; + } + /** + * REST API access token. + * + * @returns Previously configured REST API access token. + */ + getToken() { + return this.token; + } + /** + * Parse Base64-encoded access token. + * + * @param tokenString - Base64-encoded access token. + * + * @returns Information about resources and permissions which has been granted for them. + */ + parseToken(tokenString) { + var _a, _b; + const parsed = this.cbor.decodeToken(tokenString); + if (parsed !== undefined) { + const uuidResourcePermissions = parsed.res.uuid ? Object.keys(parsed.res.uuid) : []; + const userResourcePermissions = parsed.res.usr ? Object.keys(parsed.res.usr) : []; + const channelResourcePermissions = Object.keys(parsed.res.chan); + const groupResourcePermissions = Object.keys(parsed.res.grp); + const uuidPatternPermissions = parsed.pat.uuid ? Object.keys(parsed.pat.uuid) : []; + const userPatternPermissions = parsed.pat.usr ? Object.keys(parsed.pat.usr) : []; + const channelPatternPermissions = Object.keys(parsed.pat.chan); + const groupPatternPermissions = Object.keys(parsed.pat.grp); + const result = { + version: parsed.v, + timestamp: parsed.t, + ttl: parsed.ttl, + authorized_uuid: parsed.uuid, + signature: parsed.sig, + }; + const uuidResources = uuidResourcePermissions.length > 0; + const userResources = userResourcePermissions.length > 0; + const channelResources = channelResourcePermissions.length > 0; + const groupResources = groupResourcePermissions.length > 0; + if (uuidResources || userResources || channelResources || groupResources) { + result.resources = {}; + if (uuidResources) { + const uuids = (result.resources.uuids = {}); + uuidResourcePermissions.forEach((id) => (uuids[id] = this.extractPermissions(parsed.res.uuid[id]))); + } + if (userResources) { + const users = (result.resources.users = {}); + userResourcePermissions.forEach((id) => (users[id] = this.extractCrudPermissions(parsed.res.usr[id]))); + } + if (channelResources) { + const channels = (result.resources.channels = {}); + channelResourcePermissions.forEach((id) => (channels[id] = this.extractPermissions(parsed.res.chan[id]))); + } + if (groupResources) { + const groups = (result.resources.groups = {}); + groupResourcePermissions.forEach((id) => (groups[id] = this.extractPermissions(parsed.res.grp[id]))); + } + } + const resourceDataSync = this.extractDataSyncScopes(parsed.res); + if (resourceDataSync) + ((_a = result.resources) !== null && _a !== void 0 ? _a : (result.resources = {})).dataSync = resourceDataSync; + const uuidPatterns = uuidPatternPermissions.length > 0; + const userPatterns = userPatternPermissions.length > 0; + const channelPatterns = channelPatternPermissions.length > 0; + const groupPatterns = groupPatternPermissions.length > 0; + if (uuidPatterns || userPatterns || channelPatterns || groupPatterns) { + result.patterns = {}; + if (uuidPatterns) { + const uuids = (result.patterns.uuids = {}); + uuidPatternPermissions.forEach((id) => (uuids[id] = this.extractPermissions(parsed.pat.uuid[id]))); + } + if (userPatterns) { + const users = (result.patterns.users = {}); + userPatternPermissions.forEach((id) => (users[id] = this.extractCrudPermissions(parsed.pat.usr[id]))); + } + if (channelPatterns) { + const channels = (result.patterns.channels = {}); + channelPatternPermissions.forEach((id) => (channels[id] = this.extractPermissions(parsed.pat.chan[id]))); + } + if (groupPatterns) { + const groups = (result.patterns.groups = {}); + groupPatternPermissions.forEach((id) => (groups[id] = this.extractPermissions(parsed.pat.grp[id]))); + } + } + const patternDataSync = this.extractDataSyncScopes(parsed.pat); + if (patternDataSync) + ((_b = result.patterns) !== null && _b !== void 0 ? _b : (result.patterns = {})).dataSync = patternDataSync; + const categories = this.extractCategories(parsed.cat); + if (categories) + result.categories = categories; + if (parsed.meta && Object.keys(parsed.meta).length > 0) + result.meta = parsed.meta; + return result; + } + return undefined; + } + /** + * Extract resource access permission information. + * + * @param permissions - Bit-encoded resource permissions. + * + * @returns Human-readable resource permissions. + */ + extractPermissions(permissions) { + const permissionsResult = { + read: false, + write: false, + manage: false, + delete: false, + get: false, + update: false, + join: false, + }; + if ((permissions & 128) === 128) + permissionsResult.join = true; + if ((permissions & 64) === 64) + permissionsResult.update = true; + if ((permissions & 32) === 32) + permissionsResult.get = true; + if ((permissions & 8) === 8) + permissionsResult.delete = true; + if ((permissions & 4) === 4) + permissionsResult.manage = true; + if ((permissions & 2) === 2) + permissionsResult.write = true; + if ((permissions & 1) === 1) + permissionsResult.read = true; + return permissionsResult; + } + /** + * Extract category-level permissions from the token `cat` section. + * + * `chan` maps to `channels` and `uuid` maps to `uuids`. `get` is set from the `32` bit. The + * section is omitted when `cat` is absent or empty. + * + * @param cat - Raw `cat` section decoded from the token. + * + * @returns Human-readable category permissions, or `undefined` when none are present. + */ + extractCategories(cat) { + if (!cat) + return undefined; + const result = {}; + if (typeof cat.chan === 'number') + result.channels = { get: (cat.chan & 32) === 32 }; + if (typeof cat.uuid === 'number') + result.uuids = { get: (cat.uuid & 32) === 32 }; + return Object.keys(result).length > 0 ? result : undefined; + } + /** + * Extract DataSync permission scopes from a token permissions section. + * + * The `datasync:*` wire keys are only present for tokens which granted DataSync permissions, so a + * result is returned only when at least one scope carries permissions. + * + * @param section - Raw `res` or `pat` permissions section decoded from the token. + * + * @returns Human-readable DataSync permission scopes, or `undefined` when none are granted. + */ + extractDataSyncScopes(section) { + const dataSyncScopes = [ + ['entities', 'datasync:entities'], + ['relationships', 'datasync:relationships'], + ['memberships', 'datasync:memberships'], + ]; + let result; + dataSyncScopes.forEach(([scope, wireKey]) => { + const permissions = section[wireKey]; + if (!permissions) + return; + const ids = Object.keys(permissions); + if (ids.length === 0) + return; + const scopeResult = ((result !== null && result !== void 0 ? result : (result = {}))[scope] = {}); + ids.forEach((id) => (scopeResult[id] = this.extractCrudPermissions(permissions[id]))); + }); + return result; + } + /** + * Extract CRUD-only access permission information. + * + * Shared by the `usr` wire key (which backs the `users` grant scope) and the `datasync:*` wire + * keys — both carry the same CRUD bit layout and none of the `read` / `write` / `manage` / `join` + * bits decoded by {@link extractPermissions}. + * + * @param permissions - Bit-encoded resource permissions. + * + * @returns Human-readable CRUD resource permissions. + */ + extractCrudPermissions(permissions) { + return { + create: (permissions & 16) === 16, + get: (permissions & 32) === 32, + update: (permissions & 64) === 64, + delete: (permissions & 8) === 8, + }; + } + } + + /** + * Enum representing possible transport methods for HTTP requests. + * + * @enum {number} + */ + var TransportMethod; + (function (TransportMethod) { + /** + * Request will be sent using `GET` method. + */ + TransportMethod["GET"] = "GET"; + /** + * Request will be sent using `POST` method. + */ + TransportMethod["POST"] = "POST"; + /** + * Request will be sent using `PATCH` method. + */ + TransportMethod["PATCH"] = "PATCH"; + /** + * Request will be sent using `PUT` method. + */ + TransportMethod["PUT"] = "PUT"; + /** + * Request will be sent using `DELETE` method. + */ + TransportMethod["DELETE"] = "DELETE"; + /** + * Local request. + * + * Request won't be sent to the service and probably used to compute URL. + */ + TransportMethod["LOCAL"] = "LOCAL"; + })(TransportMethod || (TransportMethod = {})); + + /** + * Common PubNub Network Provider middleware module. + * + * @internal + */ + /** + * Request signature generator. + * + * @internal + */ + class RequestSignature { + constructor(publishKey, secretKey, hasher, logger) { + this.publishKey = publishKey; + this.secretKey = secretKey; + this.hasher = hasher; + this.logger = logger; + } + /** + * Compute request signature. + * + * @param req - Request which will be used to compute signature. + * @returns {string} `v2` request signature. + */ + signature(req) { + const method = req.path.startsWith('/publish') ? TransportMethod.GET : req.method; + let signatureInput = `${method}\n${this.publishKey}\n${req.path}\n${this.queryParameters(req.queryParameters)}\n`; + if (method === TransportMethod.POST || method === TransportMethod.PATCH || method === TransportMethod.PUT) { + const body = req.body; + let payload; + if (body && body instanceof ArrayBuffer) { + payload = RequestSignature.textDecoder.decode(body); + } + else if (body && typeof body !== 'object') { + payload = body; + } + if (payload) + signatureInput += payload; + } + this.logger.trace('RequestSignature', () => ({ + messageType: 'text', + message: `Request signature input:\n${signatureInput}`, + })); + return `v2.${this.hasher(signatureInput, this.secretKey)}` + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/, ''); + } + /** + * Prepare request query parameters for signature. + * + * @param query - Key / value pair of the request query parameters. + * @private + */ + queryParameters(query) { + return Object.keys(query) + .sort() + .map((key) => { + const queryValue = query[key]; + if (!Array.isArray(queryValue)) + return `${key}=${encodeString(queryValue)}`; + return queryValue + .sort() + .map((value) => `${key}=${encodeString(value)}`) + .join('&'); + }) + .join('&'); + } + } + RequestSignature.textDecoder = new TextDecoder('utf-8'); + /** + * Common PubNub Network Provider middleware. + * + * @internal + */ + class PubNubMiddleware { + constructor(configuration) { + this.configuration = configuration; + const { clientConfiguration: { keySet }, shaHMAC, } = configuration; + { + if (keySet.secretKey && shaHMAC) + this.signatureGenerator = new RequestSignature(keySet.publishKey, keySet.secretKey, shaHMAC, this.logger); + } + } + /** + * Retrieve registered loggers' manager. + * + * @returns Registered loggers' manager. + */ + get logger() { + return this.configuration.clientConfiguration.logger(); + } + makeSendable(req) { + const retryPolicy = this.configuration.clientConfiguration.retryConfiguration; + const transport = this.configuration.transport; + // Make requests retryable. + if (retryPolicy !== undefined) { + let retryTimeout; + let activeCancellation; + let canceled = false; + let attempt = 0; + const cancellation = { + abort: (reason) => { + canceled = true; + if (retryTimeout) + clearTimeout(retryTimeout); + if (activeCancellation) + activeCancellation.abort(reason); + }, + }; + const retryableRequest = new Promise((resolve, reject) => { + const trySendRequest = () => { + // Check whether the request already has been canceled and there is no retry should proceed. + if (canceled) + return; + const [attemptPromise, attemptCancellation] = transport.makeSendable(this.request(req)); + activeCancellation = attemptCancellation; + const responseHandler = (res, error) => { + let delay = -1; + // Retry ability (error category, HTTP status code, excluded endpoints and attempts count) is entirely + // decided by the retry policy. + if (retryPolicy.shouldRetry(req, res, error === null || error === void 0 ? void 0 : error.category, attempt + 1, error === null || error === void 0 ? void 0 : error.statusCode)) + delay = retryPolicy.getDelay(attempt, res); + if (delay > 0) { + attempt++; + this.logger.warn('PubNubMiddleware', `HTTP request retry #${attempt} in ${delay}ms.`); + retryTimeout = setTimeout(() => trySendRequest(), delay); + } + else { + if (res) + resolve(res); + else if (error) + reject(error); + } + }; + attemptPromise + .then((res) => responseHandler(res)) + .catch((err) => responseHandler(undefined, err)); + }; + trySendRequest(); + }); + return [retryableRequest, activeCancellation ? cancellation : undefined]; + } + return transport.makeSendable(this.request(req)); + } + request(req) { + var _a; + const { clientConfiguration } = this.configuration; + // Get request patched by transport provider. + req = this.configuration.transport.request(req); + if (!req.queryParameters) + req.queryParameters = {}; + // Modify the request with required information. + if (clientConfiguration.useInstanceId) + req.queryParameters['instanceid'] = clientConfiguration.getInstanceId(); + if (!req.queryParameters['uuid']) + req.queryParameters['uuid'] = clientConfiguration.userId; + if (clientConfiguration.useRequestId) + req.queryParameters['requestid'] = req.identifier; + req.queryParameters['pnsdk'] = this.generatePNSDK(); + (_a = req.origin) !== null && _a !== void 0 ? _a : (req.origin = clientConfiguration.origin); + // Authenticate request if required. + this.authenticateRequest(req); + // Sign request if it is required. + this.signRequest(req); + return req; + } + authenticateRequest(req) { + var _a; + // Access management endpoints don't need authentication (signature required instead). + if (req.path.startsWith('/v2/auth/') || req.path.startsWith('/v3/pam/') || req.path.startsWith('/time')) + return; + const { clientConfiguration, tokenManager } = this.configuration; + const accessKey = (_a = (tokenManager && tokenManager.getToken())) !== null && _a !== void 0 ? _a : clientConfiguration.authKey; + if (accessKey) + req.queryParameters['auth'] = accessKey; + } + /** + * Compute and append request signature. + * + * @param req - Transport request with information which should be used to generate signature. + */ + signRequest(req) { + if (!this.signatureGenerator || req.path.startsWith('/time')) + return; + req.queryParameters['timestamp'] = String(Math.floor(new Date().getTime() / 1000)); + req.queryParameters['signature'] = this.signatureGenerator.signature(req); + } + /** + * Compose `pnsdk` query parameter. + * + * SDK provides ability to set custom name or append vendor information to the `pnsdk` query + * parameter. + * + * @returns Finalized `pnsdk` query parameter value. + */ + generatePNSDK() { + const { clientConfiguration } = this.configuration; + if (clientConfiguration.sdkName) + return clientConfiguration.sdkName; + let base = `PubNub-JS-${clientConfiguration.sdkFamily}`; + if (clientConfiguration.partnerId) + base += `-${clientConfiguration.partnerId}`; + base += `/${clientConfiguration.getVersion()}`; + const pnsdkSuffix = clientConfiguration._getPnsdkSuffix(' '); + if (pnsdkSuffix.length > 0) + base += pnsdkSuffix; + return base; + } + } + + /** + * Common browser and React Native Transport provider module. + * + * @internal + */ + /** + * Class representing a `fetch`-based browser and React Native transport provider. + * + * @internal + */ + class WebTransport { + /** + * Create and configure transport provider for Web and Rect environments. + * + * @param logger - Registered loggers' manager. + * @param [transport] - API, which should be used to make network requests. + * + * @internal + */ + constructor(logger, transport = 'fetch') { + this.logger = logger; + this.transport = transport; + logger.debug('WebTransport', `Create with configuration:\n - transport: ${transport}`); + // Check for `fetch` availability directly (works in DOM and DOM-less contexts such as service workers). + // because a bare `window` reference would throw in a service worker, and a partial `window = self` shim can + // define `window` without `fetch`, so probe the actual `fetch` global via `typeof`. + if (transport === 'fetch' && typeof fetch === 'undefined') { + logger.warn('WebTransport', `'${transport}' not supported in this browser. Fallback to the 'xhr' transport.`); + this.transport = 'xhr'; + } + if (this.transport !== 'fetch') + return; + // Storing reference on original `fetch` function implementation as protection against APM lib monkey patching. + // + // This is done unconditionally (not gated on `isFetchMonkeyPatched()`): APM libraries can defeat that + // detection by overriding stringification to report `[native code]` while still patching `fetch`, so we + // cannot rely on it to decide whether the workaround is needed. `getOriginalFetch()` itself decides how to + // obtain the reference based on the environment (iframe when a DOM is available, context `fetch` otherwise), + // which keeps construction safe in DOM-less contexts such as MV3 service workers. + WebTransport.originalFetch = WebTransport.getOriginalFetch(); + // Check whether `fetch` has been monkey patched or not. + if (this.isFetchMonkeyPatched()) + logger.warn('WebTransport', "Native Web Fetch API 'fetch' function monkey patched."); + } + makeSendable(req) { + const abortController = new AbortController(); + const cancellation = { + abortController, + abort: (reason) => { + if (!abortController.signal.aborted) { + this.logger.trace('WebTransport', `On-demand request aborting: ${reason}`); + abortController.abort(reason); + } + }, + }; + return [ + this.webTransportRequestFromTransportRequest(req).then((request) => { + this.logger.debug('WebTransport', () => ({ messageType: 'network-request', message: req })); + return this.sendRequest(request, cancellation) + .then((response) => response.arrayBuffer().then((arrayBuffer) => [response, arrayBuffer])) + .then((response) => { + const body = response[1].byteLength > 0 ? response[1] : undefined; + const { status, headers: requestHeaders } = response[0]; + const headers = {}; + // Copy Headers object content into plain Record. + requestHeaders.forEach((value, key) => (headers[key] = value.toLowerCase())); + const transportResponse = { status, url: request.url, headers, body }; + this.logger.debug('WebTransport', () => ({ + messageType: 'network-response', + message: transportResponse, + })); + if (status >= 400) + throw PubNubAPIError.create(transportResponse); + return transportResponse; + }) + .catch((error) => { + const errorMessage = (typeof error === 'string' ? error : error.message).toLowerCase(); + let fetchError = typeof error === 'string' ? new Error(error) : error; + if (errorMessage.includes('timeout')) { + this.logger.warn('WebTransport', () => ({ + messageType: 'network-request', + message: req, + details: 'Timeout', + canceled: true, + })); + } + else if (errorMessage.includes('cancel') || errorMessage.includes('abort')) { + this.logger.debug('WebTransport', () => ({ + messageType: 'network-request', + message: req, + details: 'Aborted', + canceled: true, + })); + fetchError = new Error('Aborted'); + fetchError.name = 'AbortError'; + } + else if (errorMessage.includes('network')) { + this.logger.warn('WebTransport', () => ({ + messageType: 'network-request', + message: req, + details: 'Network error', + failed: true, + })); + } + else { + this.logger.warn('WebTransport', () => ({ + messageType: 'network-request', + message: req, + details: PubNubAPIError.create(fetchError).message, + failed: true, + })); + } + throw PubNubAPIError.create(fetchError); + }); + }), + cancellation, + ]; + } + request(req) { + return req; + } + /** + * Send network request using preferred API. + * + * @param req - Transport API agnostic request object with prepared body and URL. + * @param controller - Request cancellation controller (for long-poll requests). + * + * @returns Promise which will be resolved or rejected at the end of network request processing. + * + * @internal + */ + sendRequest(req, controller) { + return __awaiter(this, void 0, void 0, function* () { + if (this.transport === 'fetch') + return this.sendFetchRequest(req, controller); + return this.sendXHRRequest(req, controller); + }); + } + /** + * Send network request using legacy XMLHttpRequest API. + * + * @param req - Transport API agnostic request object with prepared body and URL. + * @param controller - Request cancellation controller (for long-poll requests). + * + * @returns Promise which will be resolved or rejected at the end of network request processing. + * + * @internal + */ + sendFetchRequest(req, controller) { + return __awaiter(this, void 0, void 0, function* () { + let timeoutId; + const requestTimeout = new Promise((_, reject) => { + timeoutId = setTimeout(() => { + clearTimeout(timeoutId); + reject(new Error('Request timeout')); + controller.abort('Cancel because of timeout'); + }, req.timeout * 1000); + }); + const request = new Request(req.url, { + method: req.method, + headers: req.headers, + redirect: 'follow', + body: req.body, + }); + return Promise.race([ + WebTransport.originalFetch(request, { + signal: controller.abortController.signal, + credentials: 'omit', + cache: 'no-cache', + }).then((response) => { + if (timeoutId) + clearTimeout(timeoutId); + return response; + }), + requestTimeout, + ]); + }); + } + /** + * Send network request using legacy XMLHttpRequest API. + * + * @param req - Transport API agnostic request object with prepared body and URL. + * @param controller - Request cancellation controller (for long-poll requests). + * + * @returns Promise which will be resolved or rejected at the end of network request processing. + * + * @internal + */ + sendXHRRequest(req, controller) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + var _a; + const xhr = new XMLHttpRequest(); + xhr.open(req.method, req.url, true); + let aborted = false; + // Setup request + xhr.responseType = 'arraybuffer'; + xhr.timeout = req.timeout * 1000; + controller.abortController.signal.onabort = () => { + if (xhr.readyState == XMLHttpRequest.DONE || xhr.readyState == XMLHttpRequest.UNSENT) + return; + aborted = true; + xhr.abort(); + }; + Object.entries((_a = req.headers) !== null && _a !== void 0 ? _a : {}).forEach(([key, value]) => xhr.setRequestHeader(key, value)); + // Setup handlers to match `fetch` results handling. + xhr.onabort = () => { + reject(new Error('Aborted')); + }; + xhr.ontimeout = () => { + reject(new Error('Request timeout')); + }; + xhr.onerror = () => { + if (!aborted) { + const response = this.transportResponseFromXHR(req.url, xhr); + reject(new Error(PubNubAPIError.create(response).message)); + } + }; + xhr.onload = () => { + const headers = new Headers(); + xhr + .getAllResponseHeaders() + .split('\r\n') + .forEach((header) => { + const [key, value] = header.split(': '); + if (key.length > 1 && value.length > 1) + headers.append(key, value); + }); + resolve(new Response(xhr.response, { status: xhr.status, headers, statusText: xhr.statusText })); + }; + xhr.send(req.body); + }); + }); + } + /** + * Creates a Web Request object from a given {@link TransportRequest} object. + * + * @param req - The {@link TransportRequest} object containing request information. + * + * @returns Request object generated from the {@link TransportRequest} object. + * + * @internal + */ + webTransportRequestFromTransportRequest(req) { + return __awaiter(this, void 0, void 0, function* () { + let body; + let path = req.path; + // Create a multipart request body. + if (req.formData && req.formData.length > 0) { + // Reset query parameters to conform to signed URL + req.queryParameters = {}; + const file = req.body; + const formData = new FormData(); + for (const { key, value } of req.formData) + formData.append(key, value); + try { + const fileData = yield file.toArrayBuffer(); + formData.append('file', new Blob([fileData], { type: 'application/octet-stream' }), file.name); + } + catch (toBufferError) { + this.logger.warn('WebTransport', () => ({ messageType: 'error', message: toBufferError })); + try { + const fileData = yield file.toFileUri(); + // @ts-expect-error React Native File Uri support. + formData.append('file', fileData, file.name); + } + catch (toFileURLError) { + this.logger.error('WebTransport', () => ({ messageType: 'error', message: toFileURLError })); + } + } + body = formData; + } + // Handle regular body payload (if passed). + else if (req.body && (typeof req.body === 'string' || req.body instanceof ArrayBuffer)) { + // Compressing body if the browser has native support. + if (req.compressible && typeof CompressionStream !== 'undefined') { + const bodyArrayBuffer = typeof req.body === 'string' ? WebTransport.encoder.encode(req.body) : req.body; + const initialBodySize = bodyArrayBuffer.byteLength; + const bodyStream = new ReadableStream({ + start(controller) { + controller.enqueue(bodyArrayBuffer); + controller.close(); + }, + }); + body = yield new Response(bodyStream.pipeThrough(new CompressionStream('deflate'))).arrayBuffer(); + this.logger.trace('WebTransport', () => { + const compressedSize = body.byteLength; + const ratio = (compressedSize / initialBodySize).toFixed(2); + return { + messageType: 'text', + message: `Body of ${initialBodySize} bytes, compressed by ${ratio}x to ${compressedSize} bytes.`, + }; + }); + } + else + body = req.body; + } + if (req.queryParameters && Object.keys(req.queryParameters).length !== 0) + path = `${path}?${queryStringFromObject(req.queryParameters)}`; + return { + url: `${req.origin}${path}`, + method: req.method, + headers: req.headers, + timeout: req.timeout, + body, + }; + }); + } + /** + * Check whether the original ` fetch ` has been monkey patched or not. + * + * @returns `true` if original `fetch` has been patched. + */ + isFetchMonkeyPatched(oFetch) { + const fetchString = (oFetch !== null && oFetch !== void 0 ? oFetch : fetch).toString(); + return !fetchString.includes('[native code]') && fetch.name !== 'fetch'; + } + /** + * Create service response from {@link XMLHttpRequest} processing result. + * + * @param url - Used endpoint url. + * @param xhr - `HTTPClient`, which has been used to make a request. + * + * @returns Pre-processed transport response. + */ + transportResponseFromXHR(url, xhr) { + const allHeaders = xhr.getAllResponseHeaders().split('\n'); + const headers = {}; + for (const header of allHeaders) { + const [key, value] = header.trim().split(':'); + if (key && value) + headers[key.toLowerCase()] = value.trim(); + } + return { status: xhr.status, url, headers, body: xhr.response }; + } + /** + * Retrieve the original ` fetch ` implementation. + * + * Retrieve implementation which hasn't been patched by APM tools. + * + * @returns Reference to the `fetch` function. + */ + static getOriginalFetch() { + // The iframe-based APM workaround requires a DOM. In DOM-less contexts (e.g. MV3 service workers) there is + // no `document`, and `fetch` cannot be reached through a fresh browsing context — return the context `fetch` + // directly. This is safe there: without a DOM there is no APM page script to monkey patch `fetch` in the + // first place. This environment check is what keeps the unconditional call in the constructor safe. + // + // `fetch` must be bound to the global scope: native `fetch` requires its `this` to be the `Window` / + // `WorkerGlobalScope`, and it is later invoked detached (`WebTransport.originalFetch(...)`). Without the bind + // a service worker throws "Failed to execute 'fetch' on 'WorkerGlobalScope': Illegal invocation". + if (typeof document === 'undefined' || !document.body) + return fetch.bind(globalThis); + let iframe = document.querySelector('iframe[name="pubnub-context-unpatched-fetch"]'); + if (!iframe) { + iframe = document.createElement('iframe'); + iframe.style.display = 'none'; + iframe.name = 'pubnub-context-unpatched-fetch'; + iframe.src = 'about:blank'; + document.body.appendChild(iframe); + } + if (iframe.contentWindow) + return iframe.contentWindow.fetch.bind(iframe.contentWindow); + return fetch.bind(globalThis); + } + } + /** + * Request body decoder. + * + * @internal + */ + WebTransport.encoder = new TextEncoder(); + /** + * Service {@link ArrayBuffer} response decoder. + * + * @internal + */ + WebTransport.decoder = new TextDecoder(); + + /** + * Network request module. + * + * @internal + */ + /** + * Base REST API request class. + * + * @internal + */ + class AbstractRequest { + /** + * Construct base request. + * + * Constructed request by default won't be cancellable and performed using `GET` HTTP method. + * + * @param params - Request configuration parameters. + */ + constructor(params) { + this.params = params; + /** + * Unique request identifier. + */ + this.requestIdentifier = uuidGenerator.createUUID(); + this._cancellationController = null; + } + /** + * Retrieve configured cancellation controller. + * + * @returns Cancellation controller. + */ + get cancellationController() { + return this._cancellationController; + } + /** + * Update request cancellation controller. + * + * Controller itself provided by transport provider implementation and set only when request + * sending has been scheduled. + * + * @param controller - Cancellation controller or `null` to reset it. + */ + set cancellationController(controller) { + this._cancellationController = controller; + } + /** + * Abort request if possible. + * + * @param [reason] Information about why request has been cancelled. + */ + abort(reason) { + if (this && this.cancellationController) + this.cancellationController.abort(reason); + } + /** + * Target REST API endpoint operation type. + */ + operation() { + throw Error('Should be implemented by subclass.'); + } + /** + * Validate user-provided data before scheduling request. + * + * @returns Error message if request can't be sent without missing or malformed parameters. + */ + validate() { + return undefined; + } + /** + * Parse service response. + * + * @param response - Raw service response which should be parsed. + */ + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return this.deserializeResponse(response); + }); + } + /** + * Create platform-agnostic request object. + * + * @returns Request object which can be processed using platform-specific requirements. + */ + request() { + var _a, _b, _c, _d, _e, _f; + const request = { + method: (_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.method) !== null && _b !== void 0 ? _b : TransportMethod.GET, + path: this.path, + queryParameters: this.queryParameters, + cancellable: (_d = (_c = this.params) === null || _c === void 0 ? void 0 : _c.cancellable) !== null && _d !== void 0 ? _d : false, + compressible: (_f = (_e = this.params) === null || _e === void 0 ? void 0 : _e.compressible) !== null && _f !== void 0 ? _f : false, + timeout: 10, + identifier: this.requestIdentifier, + }; + // Attach headers (if required). + const headers = this.headers; + if (headers) + request.headers = headers; + // Attach body (if required). + if (request.method === TransportMethod.POST || + request.method === TransportMethod.PATCH || + request.method === TransportMethod.PUT) { + const [body, formData] = [this.body, this.formData]; + if (formData) + request.formData = formData; + if (body) + request.body = body; + } + return request; + } + /** + * Target REST API endpoint request headers getter. + * + * @returns Key/value headers which should be used with request. + */ + get headers() { + var _a, _b; + return Object.assign({ 'Accept-Encoding': 'gzip, deflate' }, (((_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.compressible) !== null && _b !== void 0 ? _b : false) ? { 'Content-Encoding': 'deflate' } : {})); + } + /** + * Target REST API endpoint request path getter. + * + * @returns REST API path. + */ + get path() { + throw Error('`path` getter should be implemented by subclass.'); + } + /** + * Target REST API endpoint request query parameters getter. + * + * @returns Key/value pairs which should be appended to the REST API path. + */ + get queryParameters() { + return {}; + } + get formData() { + return undefined; + } + /** + * Target REST API Request body payload getter. + * + * @returns Buffer of stringified data which should be sent with `POST` or `PATCH` request. + */ + get body() { + return undefined; + } + /** + * Deserialize service response. + * + * @param response - Transparent response object with headers and body information. + * + * @returns Deserialized service response data. + * + * @throws {Error} if received service response can't be processed (has unexpected content-type or can't be parsed as + * JSON). + */ + deserializeResponse(response) { + const responseText = AbstractRequest.decoder.decode(response.body); + const contentType = response.headers['content-type']; + let parsedJson; + if (!contentType || (contentType.indexOf('javascript') === -1 && contentType.indexOf('json') === -1)) + throw new PubNubError('Service response error, check status for details', createMalformedResponseError(responseText, response.status)); + try { + parsedJson = JSON.parse(responseText); + } + catch (error) { + console.error('Error parsing JSON response:', error); + throw new PubNubError('Service response error, check status for details', createMalformedResponseError(responseText, response.status)); + } + // Throw and exception in case of client / server error. + if ('status' in parsedJson && typeof parsedJson.status === 'number' && parsedJson.status >= 400) + throw PubNubAPIError.create(response); + return parsedJson; + } + } + /** + * Service `ArrayBuffer` response decoder. + */ + AbstractRequest.decoder = new TextDecoder(); + + /** + * Subscription REST API module. + */ + // -------------------------------------------------------- + // ---------------------- Defaults ------------------------ + // -------------------------------------------------------- + // region Defaults + /** + * Whether should subscribe to channels / groups presence announcements or not. + */ + const WITH_PRESENCE = false; + // endregion + // -------------------------------------------------------- + // ------------------------ Types ------------------------- + // -------------------------------------------------------- + // region Types + /** + * PubNub-defined event types by payload. + */ + var PubNubEventType; + (function (PubNubEventType) { + /** + * Presence change event. + */ + PubNubEventType[PubNubEventType["Presence"] = -2] = "Presence"; + /** + * Regular message event. + * + * **Note:** This is default type assigned for non-presence events if `e` field is missing. + */ + PubNubEventType[PubNubEventType["Message"] = -1] = "Message"; + /** + * Signal data event. + */ + PubNubEventType[PubNubEventType["Signal"] = 1] = "Signal"; + /** + * App Context object event. + */ + PubNubEventType[PubNubEventType["AppContext"] = 2] = "AppContext"; + /** + * Message reaction event. + */ + PubNubEventType[PubNubEventType["MessageAction"] = 3] = "MessageAction"; + /** + * Files event. + */ + PubNubEventType[PubNubEventType["Files"] = 4] = "Files"; + /** + * DataSync object change event. + * + * **Note:** Value must equal `5` to match the service wire value (`e: 5`). + */ + PubNubEventType[PubNubEventType["DataSync"] = 5] = "DataSync"; + })(PubNubEventType || (PubNubEventType = {})); + /** + * Event types which this SDK version knows how to parse. + * + * Events with any other `e` value are ignored: they most likely originate from a service release newer than + * the SDK + */ + const KNOWN_EVENT_TYPES = new Set([ + PubNubEventType.Presence, + PubNubEventType.Message, + PubNubEventType.Signal, + PubNubEventType.AppContext, + PubNubEventType.MessageAction, + PubNubEventType.Files, + PubNubEventType.DataSync, + ]); + /** + * Reserved DataSync system class names (lower-cased) → normalized object kind. + * + * Only consulted when the wire {@link DataSyncData.type} is the generic `entity` / `relationship` + * kind, and only for classes the service marks as `Global` (see {@link DataSyncClassLevel}) — so a + * developer-defined class which happens to share one of these names is not mistaken for a typed + * resource. Keys are compared case-insensitively. + * + * @internal + */ + const DATA_SYNC_RESERVED_CLASSES = { + user: 'user', + channel: 'channel', + membership: 'membership', + }; + // endregion + /** + * Base subscription request implementation. + * + * Subscription request used in small variations in two cases: + * - subscription manager + * - event engine + * + * @internal + */ + class BaseSubscribeRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c; + var _d, _e, _f; + super({ cancellable: true }); + this.parameters = parameters; + // Apply default request parameters. + (_a = (_d = this.parameters).withPresence) !== null && _a !== void 0 ? _a : (_d.withPresence = WITH_PRESENCE); + (_b = (_e = this.parameters).channelGroups) !== null && _b !== void 0 ? _b : (_e.channelGroups = []); + (_c = (_f = this.parameters).channels) !== null && _c !== void 0 ? _c : (_f.channels = []); + } + operation() { + return RequestOperation$1.PNSubscribeOperation; + } + validate() { + const { keySet: { subscribeKey }, channels, channelGroups, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channels && !channelGroups) + return '`channels` and `channelGroups` both should not be empty'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + let serviceResponse; + let responseText; + try { + responseText = AbstractRequest.decoder.decode(response.body); + const parsedJson = JSON.parse(responseText); + serviceResponse = parsedJson; + } + catch (error) { + console.error('Error parsing JSON response:', error); + } + if (!serviceResponse) { + throw new PubNubError('Service response error, check status for details', createMalformedResponseError(responseText, response.status)); + } + const events = serviceResponse.m + .filter((envelope) => { + const subscribable = envelope.b === undefined ? envelope.c : envelope.b; + return ((this.parameters.channels && this.parameters.channels.includes(subscribable)) || + (this.parameters.channelGroups && this.parameters.channelGroups.includes(subscribable))); + }) + .map((envelope) => { + let { e: eventType } = envelope; + // Events delivered on a presence channel are always presence events: the `-pnpres` suffix wins over + // the service-reported type. `envelope.c` is the actual channel (`envelope.b` is the channel group + // name), so this also covers presence delivered through a subscribed channel group. + if (envelope.c.endsWith('-pnpres')) + eventType = PubNubEventType.Presence; + // Resolve missing event type. + else + eventType !== null && eventType !== void 0 ? eventType : (eventType = PubNubEventType.Message); + // Ignore an event type this SDK version cannot parse rather than delivering an unexpected payload. + if (!KNOWN_EVENT_TYPES.has(eventType)) + return undefined; + const pn_mfp = messageFingerprint(envelope.d); + // Check whether payload is string (potentially encrypted data). + if (eventType != PubNubEventType.Presence && + eventType != PubNubEventType.Signal && + typeof envelope.d === 'string') { + if (eventType == PubNubEventType.Message) { + return { + type: PubNubEventType.Message, + data: this.messageFromEnvelope(envelope), + pn_mfp, + }; + } + return { + type: PubNubEventType.Files, + data: this.fileFromEnvelope(envelope), + pn_mfp, + }; + } + else if (eventType == PubNubEventType.Message) { + return { + type: PubNubEventType.Message, + data: this.messageFromEnvelope(envelope), + pn_mfp, + }; + } + else if (eventType === PubNubEventType.Presence) { + return { + type: PubNubEventType.Presence, + data: this.presenceEventFromEnvelope(envelope), + pn_mfp, + }; + } + else if (eventType == PubNubEventType.Signal) { + return { + type: PubNubEventType.Signal, + data: this.signalFromEnvelope(envelope), + pn_mfp, + }; + } + else if (eventType === PubNubEventType.AppContext) { + return { + type: PubNubEventType.AppContext, + data: this.appContextFromEnvelope(envelope), + pn_mfp, + }; + } + else if (eventType === PubNubEventType.MessageAction) { + return { + type: PubNubEventType.MessageAction, + data: this.messageActionFromEnvelope(envelope), + pn_mfp, + }; + } + else if (eventType === PubNubEventType.DataSync) { + const dataSync = this.dataSyncFromEnvelope(envelope); + // Guard: only treat as DataSync when the service marks it so; otherwise fall back to message. + if (dataSync) + return { type: PubNubEventType.DataSync, data: dataSync, pn_mfp }; + return { type: PubNubEventType.Message, data: this.messageFromEnvelope(envelope), pn_mfp }; + } + // The only known event type left is a file event. + return { + type: PubNubEventType.Files, + data: this.fileFromEnvelope(envelope), + pn_mfp, + }; + }) + .filter((event) => event !== undefined); + return { + cursor: { timetoken: serviceResponse.t.t, region: serviceResponse.t.r }, + messages: events, + }; + }); + } + get headers() { + var _a; + return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { accept: 'text/javascript' }); + } + // -------------------------------------------------------- + // ------------------ Envelope parsing -------------------- + // -------------------------------------------------------- + // region Envelope parsing + presenceEventFromEnvelope(envelope) { + var _a; + const { d: payload } = envelope; + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + // Clean up channel and subscription name from presence suffix. + const trimmedChannel = channel.replace('-pnpres', ''); + // Backward compatibility with deprecated properties. + const actualChannel = subscription !== null ? trimmedChannel : null; + const subscribedChannel = subscription !== null ? subscription : trimmedChannel; + // Presence payloads are objects. A string can only reach here when a non-presence payload has been published + // on a `-pnpres` channel: try to read it as JSON and never spread a string (which would add character-indexed + // keys to the event). + let presenceData; + if (typeof payload === 'string') { + try { + const parsed = JSON.parse(payload); + if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) + presenceData = parsed; + } + catch (_b) { + // Not JSON (encrypted or plain-text publish): payload contributes no presence fields. + } + } + else + presenceData = payload; + if (presenceData) { + if ('data' in presenceData) { + // @ts-expect-error This is `state-change` object which should have `state` field. + presenceData['state'] = presenceData.data; + delete presenceData.data; + } + else if ('action' in presenceData && presenceData.action === 'interval') { + presenceData.hereNowRefresh = (_a = presenceData.here_now_refresh) !== null && _a !== void 0 ? _a : false; + delete presenceData.here_now_refresh; + } + } + return Object.assign({ channel: trimmedChannel, subscription, + actualChannel, + subscribedChannel, timetoken: envelope.p.t }, (presenceData !== null && presenceData !== void 0 ? presenceData : {})); + } + messageFromEnvelope(envelope) { + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + const [message, decryptionError] = this.decryptedData(envelope.d); + // Backward compatibility with deprecated properties. + const actualChannel = subscription !== null ? channel : null; + const subscribedChannel = subscription !== null ? subscription : channel; + // Basic message event payload. + const event = { + channel, + subscription, + actualChannel, + subscribedChannel, + timetoken: envelope.p.t, + publisher: envelope.i, + message, + }; + if (envelope.u) + event.userMetadata = envelope.u; + if (envelope.cmt) + event.customMessageType = envelope.cmt; + if (decryptionError) + event.error = decryptionError; + return event; + } + signalFromEnvelope(envelope) { + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + const event = { + channel, + subscription, + timetoken: envelope.p.t, + publisher: envelope.i, + message: envelope.d, + }; + if (envelope.u) + event.userMetadata = envelope.u; + if (envelope.cmt) + event.customMessageType = envelope.cmt; + return event; + } + messageActionFromEnvelope(envelope) { + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + const action = envelope.d; + return { + channel, + subscription, + timetoken: envelope.p.t, + publisher: envelope.i, + event: action.event, + data: Object.assign(Object.assign({}, action.data), { uuid: envelope.i }), + }; + } + appContextFromEnvelope(envelope) { + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + const object = envelope.d; + return { + channel, + subscription, + timetoken: envelope.p.t, + message: object, + }; + } + dataSyncFromEnvelope(envelope) { + var _a; + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + const payload = envelope.d; + const metadata = payload === null || payload === void 0 ? void 0 : payload.metadata; + // Only treat the envelope as DataSync when the service marks it and carries the required fields. + if (!metadata || metadata.source !== 'data-sync' || !metadata.event || !metadata.type) + return undefined; + // Wire `className` is a bare class name (`User`, `Membership`, `Customer`); the `:`-splitting below + // is only there to keep tolerating the retired positional composite (`User::` / `::Customer`). + const classSegments = metadata.className ? metadata.className.split(':') : []; + const nonEmptySegments = classSegments.filter((segment) => segment.length > 0); + const className = nonEmptySegments.length > 0 ? nonEmptySegments[nonEmptySegments.length - 1] : undefined; + const classLevel = metadata.classLevel; + // `classLevel` authoritatively separates the built-in classes from developer-defined ones, so a + // developer class named `User` / `Channel` / `Membership` is not mistaken for a typed resource. + // When it is absent (service predating the field) fall back to the legacy positional heuristic, + // where the system class was the first segment. + const systemClass = classLevel === undefined ? classSegments[0] : classLevel === 'Global' ? className : undefined; + // The service reports the semantic kind directly; the class-name lookup only fills it in for a + // service which still sends the built-in classes under the generic `entity` / `relationship` kind. + const genericType = metadata.type === 'entity' || metadata.type === 'relationship'; + const objectType = genericType + ? (systemClass && DATA_SYNC_RESERVED_CLASSES[systemClass.toLowerCase()]) || metadata.type + : metadata.type; + const parsedVersion = metadata.classVersion !== undefined ? Number.parseInt(`${metadata.classVersion}`, 10) : NaN; + const classVersion = Number.isNaN(parsedVersion) ? undefined : parsedVersion; + const raw = ((_a = payload.data) !== null && _a !== void 0 ? _a : {}); + // Class identity is reported once, on the event, so it is shared by every event shape. + const common = { + version: payload.version, + source: metadata.source, + type: metadata.type, + className, + classLevel, + classVersion, + }; + // `data` mirrors the object as sent by the service, and its shape is tied to `event` / + // `objectType` — which is what makes `message` a discriminated union for the consumer. + let message; + if (metadata.event === 'delete' && objectType === 'membership') { + const data = { + id: raw.id, + deletedAt: raw.deletedAt, + }; + // Membership deletes name the endpoints they joined. Other fields stay trimmed. + if (typeof raw.channelId === 'string') + data.channelId = raw.channelId; + if (typeof raw.userId === 'string') + data.userId = raw.userId; + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data }); + } + else if (metadata.event === 'delete' && objectType === 'relationship') { + const data = { + id: raw.id, + deletedAt: raw.deletedAt, + }; + // Relationship deletes name the entities they linked. Other fields stay trimmed. + if (typeof raw.entityAId === 'string') + data.entityAId = raw.entityAId; + if (typeof raw.entityBId === 'string') + data.entityBId = raw.entityBId; + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data }); + } + else if (metadata.event === 'delete') + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: { id: raw.id, deletedAt: raw.deletedAt } }); + else if (objectType === 'membership') + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); + else if (objectType === 'relationship') + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); + else + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); + return { + channel, + subscription, + timetoken: envelope.p.t, + message, + }; + } + fileFromEnvelope(envelope) { + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + const [file, decryptionError] = this.decryptedData(envelope.d); + let errorMessage = decryptionError; + // Basic file event payload. + const event = { + channel, + subscription, + timetoken: envelope.p.t, + publisher: envelope.i, + }; + if (envelope.u) + event.userMetadata = envelope.u; + if (!file) + errorMessage !== null && errorMessage !== void 0 ? errorMessage : (errorMessage = `File information payload is missing.`); + else if (typeof file === 'string') + errorMessage !== null && errorMessage !== void 0 ? errorMessage : (errorMessage = `Unexpected file information payload data type.`); + else { + event.message = file.message; + if (file.file) { + event.file = { + id: file.file.id, + name: file.file.name, + url: this.parameters.getFileUrl({ id: file.file.id, name: file.file.name, channel }), + }; + } + } + if (envelope.cmt) + event.customMessageType = envelope.cmt; + if (errorMessage) + event.error = errorMessage; + return event; + } + // endregion + subscriptionChannelFromEnvelope(envelope) { + return [envelope.c, envelope.b === undefined ? envelope.c : envelope.b]; + } + /** + * Decrypt provided `data`. + * + * @param [data] - Message or file information which should be decrypted if possible. + * + * @returns Tuple with decrypted data and decryption error (if any). + */ + decryptedData(data) { + if (!this.parameters.crypto || typeof data !== 'string') + return [data, undefined]; + let payload; + let error; + try { + const decryptedData = this.parameters.crypto.decrypt(data); + payload = + decryptedData instanceof ArrayBuffer + ? JSON.parse(SubscribeRequest.decoder.decode(decryptedData)) + : decryptedData; + } + catch (err) { + payload = null; + error = `Error while decrypting message content: ${err.message}`; + } + return [(payload !== null && payload !== void 0 ? payload : data), error]; + } + } + /** + * Subscribe request. + * + * @internal + */ + class SubscribeRequest extends BaseSubscribeRequest { + get path() { + var _a; + const { keySet: { subscribeKey }, channels, } = this.parameters; + return `/v2/subscribe/${subscribeKey}/${encodeNames((_a = channels === null || channels === void 0 ? void 0 : channels.sort()) !== null && _a !== void 0 ? _a : [], ',')}/0`; + } + get queryParameters() { + const { channelGroups, filterExpression, heartbeat, state, timetoken, region, onDemand } = this.parameters; + const query = {}; + if (onDemand) + query['on-demand'] = 1; + if (channelGroups && channelGroups.length > 0) + query['channel-group'] = channelGroups.sort().join(','); + if (filterExpression && filterExpression.length > 0) + query['filter-expr'] = filterExpression; + if (heartbeat) + query.heartbeat = heartbeat; + if (state && Object.keys(state).length > 0) + query['state'] = JSON.stringify(state); + if (timetoken !== undefined && typeof timetoken === 'string') { + if (timetoken.length > 0 && timetoken !== '0') + query['tt'] = timetoken; + } + else if (timetoken !== undefined && timetoken > 0) + query['tt'] = timetoken; + if (region) + query['tr'] = region; + return query; + } + } + + /** + * Events dispatcher module. + */ + /** + * Real-time events dispatcher. + * + * Class responsible for listener management and invocation. + * + * @internal + */ + class EventDispatcher { + constructor() { + /** + * Whether listeners has been added or not. + */ + this.hasListeners = false; + /** + * List of registered event handlers. + * + * **Note:** the First element is reserved for type-based event handlers. + */ + this.listeners = [{ count: -1, listener: {} }]; + } + /** + * Set a connection status change event handler. + * + * @param listener - Listener function, which will be called each time when the connection status changes. + */ + set onStatus(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'status' }); + } + /** + * Set a new message handler. + * + * @param listener - Listener function, which will be called each time when a new message + * is received from the real-time network. + */ + set onMessage(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'message' }); + } + /** + * Set a new presence events handler. + * + * @param listener - Listener function, which will be called each time when a new + * presence event is received from the real-time network. + */ + set onPresence(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'presence' }); + } + /** + * Set a new signal handler. + * + * @param listener - Listener function, which will be called each time when a new signal + * is received from the real-time network. + */ + set onSignal(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'signal' }); + } + /** + * Set a new app context event handler. + * + * @param listener - Listener function, which will be called each time when a new + * app context event is received from the real-time network. + */ + set onObjects(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'objects' }); + } + /** + * Set a new message reaction event handler. + * + * @param listener - Listener function, which will be called each time when a + * new message reaction event is received from the real-time network. + */ + set onMessageAction(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'messageAction' }); + } + /** + * Set a new file handler. + * + * @param listener - Listener function, which will be called each time when a new file + * is received from the real-time network. + */ + set onFile(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'file' }); + } + /** + * Set a new DataSync event handler. + * + * @param listener - Listener function, which will be called each time when a new + * DataSync event is received from the real-time network. + */ + set onDataSync(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'dataSync' }); + } + /** + * Dispatch received a real-time update. + * + * @param event - A real-time event from multiplexed subscription. + */ + handleEvent(event) { + if (!this.hasListeners) + return; + if (event.type === PubNubEventType.Message) + this.announce('message', event.data); + else if (event.type === PubNubEventType.Signal) + this.announce('signal', event.data); + else if (event.type === PubNubEventType.Presence) + this.announce('presence', event.data); + else if (event.type === PubNubEventType.AppContext) { + const { data: objectEvent } = event; + const { message: object } = objectEvent; + this.announce('objects', objectEvent); + if (object.type === 'uuid') { + const { message, channel } = objectEvent, restEvent = __rest(objectEvent, ["message", "channel"]); + const { event, type } = object, restObject = __rest(object, ["event", "type"]); + const userEvent = Object.assign(Object.assign({}, restEvent), { spaceId: channel, message: Object.assign(Object.assign({}, restObject), { event: event === 'set' ? 'updated' : 'removed', type: 'user' }) }); + this.announce('user', userEvent); + } + else if (object.type === 'channel') { + const { message, channel } = objectEvent, restEvent = __rest(objectEvent, ["message", "channel"]); + const { event, type } = object, restObject = __rest(object, ["event", "type"]); + const spaceEvent = Object.assign(Object.assign({}, restEvent), { spaceId: channel, message: Object.assign(Object.assign({}, restObject), { event: event === 'set' ? 'updated' : 'removed', type: 'space' }) }); + this.announce('space', spaceEvent); + } + else if (object.type === 'membership') { + const { message, channel } = objectEvent, restEvent = __rest(objectEvent, ["message", "channel"]); + const { event, data } = object, restObject = __rest(object, ["event", "data"]); + const { uuid, channel: channelMeta } = data, restData = __rest(data, ["uuid", "channel"]); + const membershipEvent = Object.assign(Object.assign({}, restEvent), { spaceId: channel, message: Object.assign(Object.assign({}, restObject), { event: event === 'set' ? 'updated' : 'removed', data: Object.assign(Object.assign({}, restData), { user: uuid, space: channelMeta }) }) }); + this.announce('membership', membershipEvent); + } + } + else if (event.type === PubNubEventType.MessageAction) + this.announce('messageAction', event.data); + else if (event.type === PubNubEventType.Files) + this.announce('file', event.data); + else if (event.type === PubNubEventType.DataSync) + this.announce('dataSync', event.data); + } + /** + * Dispatch received connection status change. + * + * @param status - Status object which should be emitter for all status listeners. + */ + handleStatus(status) { + if (!this.hasListeners) + return; + this.announce('status', status); + } + /** + * Add events handler. + * + * @param listener - Events listener configuration object, which lets specify handlers for multiple types of events. + */ + addListener(listener) { + this.updateTypeOrObjectListener({ add: true, listener }); + } + removeListener(listener) { + this.updateTypeOrObjectListener({ add: false, listener }); + } + removeAllListeners() { + this.listeners = [{ count: -1, listener: {} }]; + this.hasListeners = false; + } + updateTypeOrObjectListener(parameters) { + if (parameters.type) { + if (typeof parameters.listener === 'function') + this.listeners[0].listener[parameters.type] = parameters.listener; + else + delete this.listeners[0].listener[parameters.type]; + } + else if (parameters.listener && typeof parameters.listener !== 'function') { + let listenerObject; + let listenerExists = false; + for (listenerObject of this.listeners) { + if (listenerObject.listener === parameters.listener) { + if (parameters.add) { + listenerObject.count++; + listenerExists = true; + } + else { + listenerObject.count--; + if (listenerObject.count === 0) + this.listeners.splice(this.listeners.indexOf(listenerObject), 1); + } + break; + } + } + if (parameters.add && !listenerExists) + this.listeners.push({ count: 1, listener: parameters.listener }); + } + this.hasListeners = this.listeners.length > 1 || Object.keys(this.listeners[0]).length > 0; + } + /** + * Announce a real-time event to all listeners. + * + * @param type - Type of event which should be announced. + * @param event - Announced real-time event payload. + */ + announce(type, event) { + this.listeners.forEach(({ listener }) => { + const typedListener = listener[type]; + // @ts-expect-error Dynamic events mapping. + if (typedListener) + typedListener(event); + }); + } + } + + /** + * Subscription reconnection-manager. + * + * **Note:** Reconnection manger rely on legacy time-based availability check. + * + * @internal + */ + /** + * Network "discovery" manager. + * + * Manager perform periodic `time` API calls to identify network availability. + * + * @internal + */ + class ReconnectionManager { + constructor(time) { + this.time = time; + } + /** + * Configure reconnection handler. + * + * @param callback - Successful availability check notify callback. + */ + onReconnect(callback) { + this.callback = callback; + } + /** + * Start periodic "availability" check. + */ + startPolling() { + this.timeTimer = setInterval(() => this.callTime(), 3000); + } + /** + * Stop periodic "availability" check. + */ + stopPolling() { + if (this.timeTimer) + clearInterval(this.timeTimer); + this.timeTimer = null; + } + callTime() { + this.time((status) => { + if (!status.error) { + this.stopPolling(); + if (this.callback) + this.callback(); + } + }); + } + } + + /** + * Messages de-duplication manager module. + * + * @internal + */ + /** + * Real-time events deduplication manager. + * + * @internal + */ + class DedupingManager { + /** + * Create and configure real-time events de-duplication manager. + * + * @param config - PubNub client configuration object. + */ + constructor(config) { + this.config = config; + config.logger().debug('DedupingManager', () => ({ + messageType: 'object', + message: { maximumCacheSize: config.maximumCacheSize }, + details: 'Create with configuration:', + })); + this.maximumCacheSize = config.maximumCacheSize; + this.hashHistory = []; + } + /** + * Compute unique real-time event payload key. + * + * @param message - Received real-time event payload for which unique key should be computed. + * @returns Unique real-time event payload key in messages cache. + */ + getKey(message) { + var _a; + return `${message.timetoken}-${this.hashCode(JSON.stringify((_a = message.message) !== null && _a !== void 0 ? _a : '')).toString()}`; + } + /** + * Check whether there is similar message already received or not. + * + * @param message - Received real-time event payload which should be checked for duplicates. + * @returns `true` in case if similar payload already has been received before. + */ + isDuplicate(message) { + return this.hashHistory.includes(this.getKey(message)); + } + /** + * Store received message to be used later for duplicate detection. + * + * @param message - Received real-time event payload. + */ + addEntry(message) { + if (this.hashHistory.length >= this.maximumCacheSize) { + this.hashHistory.shift(); + } + this.hashHistory.push(this.getKey(message)); + } + /** + * Clean up cached messages. + */ + clearHistory() { + this.hashHistory = []; + } + /** + * Compute message hash sum. + * + * @param payload - Received payload for which hash sum should be computed. + * @returns {number} - Resulting hash sum. + */ + hashCode(payload) { + let hash = 0; + if (payload.length === 0) + return hash; + for (let i = 0; i < payload.length; i += 1) { + const character = payload.charCodeAt(i); + hash = (hash << 5) - hash + character; // eslint-disable-line + hash = hash & hash; // eslint-disable-line + } + return hash; + } + } + + /** + * Subscription manager module. + * + * @internal + */ + /** + * Subscription loop manager. + * + * @internal + */ + class SubscriptionManager { + constructor(configuration, emitEvent, emitStatus, subscribeCall, heartbeatCall, leaveCall, time) { + this.configuration = configuration; + this.emitEvent = emitEvent; + this.emitStatus = emitStatus; + this.subscribeCall = subscribeCall; + this.heartbeatCall = heartbeatCall; + this.leaveCall = leaveCall; + /** + * Whether user code in event handlers requested disconnection or not. + * + * Won't continue subscription loop if user requested disconnection/unsubscribe from all in response to received + * event. + */ + this.disconnectedWhileHandledEvent = false; + configuration.logger().trace('SubscriptionManager', 'Create manager.'); + this.reconnectionManager = new ReconnectionManager(time); + this.dedupingManager = new DedupingManager(this.configuration); + this.heartbeatChannelGroups = {}; + this.heartbeatChannels = {}; + this.presenceChannelGroups = {}; + this.presenceChannels = {}; + this.heartbeatTimer = null; + this.presenceState = {}; + this.pendingChannelGroupSubscriptions = new Set(); + this.pendingChannelSubscriptions = new Set(); + this.channelGroups = {}; + this.channels = {}; + this.currentTimetoken = '0'; + this.lastTimetoken = '0'; + this.storedTimetoken = null; + this.referenceTimetoken = null; + this.subscriptionStatusAnnounced = false; + this.isOnline = true; + } + // region Information + /** + * Subscription-based current timetoken. + * + * @returns Timetoken based on current timetoken plus diff between current and loop start time. + */ + get subscriptionTimetoken() { + var _a; + return subscriptionTimetokenFromReference(this.currentTimetoken, (_a = this.referenceTimetoken) !== null && _a !== void 0 ? _a : '0'); + } + get subscribedChannels() { + return Object.keys(this.channels); + } + get subscribedChannelGroups() { + return Object.keys(this.channelGroups); + } + get abort() { + return this._subscribeAbort; + } + set abort(call) { + this._subscribeAbort = call; + } + // endregion + // region Subscription + disconnect() { + // Potentially called during received events handling. + // Mark to prevent subscription loop continuation in subscribe response handler. + this.disconnectedWhileHandledEvent = true; + this.stopSubscribeLoop(); + this.stopHeartbeatTimer(); + this.reconnectionManager.stopPolling(); + } + /** + * Restart subscription loop with current state. + * + * @param forUnsubscribe - Whether restarting subscription loop as part of channels list change on + * unsubscribe or not. + */ + reconnect(forUnsubscribe = false) { + this.startSubscribeLoop(forUnsubscribe); + // Starting heartbeat loop for provided channels and groups. + if (!forUnsubscribe && !this.configuration.useSmartHeartbeat) + this.startHeartbeatTimer(); + } + /** + * Update channels and groups used in subscription loop. + * + * @param parameters - Subscribe configuration parameters. + */ + subscribe(parameters) { + const { channels, channelGroups, timetoken, withPresence = false, withHeartbeats = false } = parameters; + if (timetoken) { + this.lastTimetoken = this.currentTimetoken; + this.currentTimetoken = `${timetoken}`; + } + if (this.currentTimetoken !== '0') { + this.storedTimetoken = this.currentTimetoken; + this.currentTimetoken = '0'; + } + channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => { + this.pendingChannelSubscriptions.add(channel); + this.channels[channel] = {}; + if (withPresence) + this.presenceChannels[channel] = {}; + if (withHeartbeats || this.configuration.getHeartbeatInterval()) + this.heartbeatChannels[channel] = {}; + }); + channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => { + this.pendingChannelGroupSubscriptions.add(group); + this.channelGroups[group] = {}; + if (withPresence) + this.presenceChannelGroups[group] = {}; + if (withHeartbeats || this.configuration.getHeartbeatInterval()) + this.heartbeatChannelGroups[group] = {}; + }); + this.subscriptionStatusAnnounced = false; + this.reconnect(); + } + unsubscribe(parameters, isOffline = false) { + let { channels, channelGroups } = parameters; + const actualChannelGroups = new Set(); + const actualChannels = new Set(); + channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => { + if (channel in this.channels) { + delete this.channels[channel]; + actualChannels.add(channel); + if (channel in this.heartbeatChannels) + delete this.heartbeatChannels[channel]; + } + if (channel in this.presenceState) + delete this.presenceState[channel]; + if (channel in this.presenceChannels) { + delete this.presenceChannels[channel]; + actualChannels.add(channel); + } + }); + channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => { + if (group in this.channelGroups) { + delete this.channelGroups[group]; + actualChannelGroups.add(group); + if (group in this.heartbeatChannelGroups) + delete this.heartbeatChannelGroups[group]; + } + if (group in this.presenceState) + delete this.presenceState[group]; + if (group in this.presenceChannelGroups) { + delete this.presenceChannelGroups[group]; + actualChannelGroups.add(group); + } + }); + // There is no need to unsubscribe to empty list of data sources. + if (actualChannels.size === 0 && actualChannelGroups.size === 0) + return; + const lastTimetoken = this.lastTimetoken; + const currentTimetoken = this.currentTimetoken; + if (Object.keys(this.channels).length === 0 && + Object.keys(this.presenceChannels).length === 0 && + Object.keys(this.channelGroups).length === 0 && + Object.keys(this.presenceChannelGroups).length === 0) { + this.lastTimetoken = '0'; + this.currentTimetoken = '0'; + this.referenceTimetoken = null; + this.storedTimetoken = null; + this.region = null; + this.reconnectionManager.stopPolling(); + } + this.reconnect(true); + // Send leave request after long-poll connection closed and loop restarted (the same way as it happens in new + // subscription flow). + if (this.configuration.suppressLeaveEvents === false && !isOffline) { + channelGroups = Array.from(actualChannelGroups); + channels = Array.from(actualChannels); + this.leaveCall({ channels, channelGroups }, (status) => { + const { error } = status, restOfStatus = __rest(status, ["error"]); + let errorMessage; + if (error) { + if (status.errorData && + typeof status.errorData === 'object' && + 'message' in status.errorData && + typeof status.errorData.message === 'string') + errorMessage = status.errorData.message; + else if ('message' in status && typeof status.message === 'string') + errorMessage = status.message; + } + this.emitStatus(Object.assign(Object.assign({}, restOfStatus), { error: errorMessage !== null && errorMessage !== void 0 ? errorMessage : false, affectedChannels: channels, affectedChannelGroups: channelGroups, currentTimetoken, + lastTimetoken })); + }); + } + } + unsubscribeAll(isOffline = false) { + this.disconnectedWhileHandledEvent = true; + this.unsubscribe({ + channels: this.subscribedChannels, + channelGroups: this.subscribedChannelGroups, + }, isOffline); + } + /** + * Start next subscription loop. + * + * @param restartOnUnsubscribe - Whether restarting subscription loop as part of channels list change on + * unsubscribe or not. + * + * @internal + */ + startSubscribeLoop(restartOnUnsubscribe = false) { + this.disconnectedWhileHandledEvent = false; + this.stopSubscribeLoop(); + const channelGroups = [...Object.keys(this.channelGroups)]; + const channels = [...Object.keys(this.channels)]; + Object.keys(this.presenceChannelGroups).forEach((group) => channelGroups.push(`${group}-pnpres`)); + Object.keys(this.presenceChannels).forEach((channel) => channels.push(`${channel}-pnpres`)); + // There is no need to start subscription loop for an empty list of data sources. + if (channels.length === 0 && channelGroups.length === 0) + return; + this.subscribeCall(Object.assign(Object.assign(Object.assign({ channels, + channelGroups, state: this.presenceState, heartbeat: this.configuration.getPresenceTimeout(), timetoken: this.currentTimetoken }, (this.region !== null ? { region: this.region } : {})), (this.configuration.filterExpression ? { filterExpression: this.configuration.filterExpression } : {})), { onDemand: !this.subscriptionStatusAnnounced || restartOnUnsubscribe }), (status, result) => { + this.processSubscribeResponse(status, result); + }); + if (!restartOnUnsubscribe && this.configuration.useSmartHeartbeat) + this.startHeartbeatTimer(); + } + stopSubscribeLoop() { + if (this._subscribeAbort) { + this._subscribeAbort(); + this._subscribeAbort = null; + } + } + /** + * Process subscribe REST API endpoint response. + */ + processSubscribeResponse(status, result) { + if (status.error) { + // Ignore aborted request. + if ((typeof status.errorData === 'object' && + 'name' in status.errorData && + status.errorData.name === 'AbortError') || + status.category === StatusCategory$1.PNCancelledCategory) + return; + if (status.category === StatusCategory$1.PNTimeoutCategory) { + this.startSubscribeLoop(); + } + else if (status.category === StatusCategory$1.PNNetworkIssuesCategory || + status.category === StatusCategory$1.PNMalformedResponseCategory) { + this.disconnect(); + if (status.error && this.configuration.autoNetworkDetection && this.isOnline) { + this.isOnline = false; + this.emitStatus({ category: StatusCategory$1.PNNetworkDownCategory }); + } + this.reconnectionManager.onReconnect(() => { + if (this.configuration.autoNetworkDetection && !this.isOnline) { + this.isOnline = true; + this.emitStatus({ category: StatusCategory$1.PNNetworkUpCategory }); + } + this.reconnect(); + this.subscriptionStatusAnnounced = true; + const reconnectedAnnounce = { + category: StatusCategory$1.PNReconnectedCategory, + operation: status.operation, + lastTimetoken: this.lastTimetoken, + currentTimetoken: this.currentTimetoken, + }; + this.emitStatus(reconnectedAnnounce); + }); + this.reconnectionManager.startPolling(); + this.emitStatus(Object.assign(Object.assign({}, status), { category: StatusCategory$1.PNNetworkIssuesCategory })); + } + else if (status.category === StatusCategory$1.PNBadRequestCategory) { + this.stopHeartbeatTimer(); + this.emitStatus(status); + } + else + this.emitStatus(status); + return; + } + this.referenceTimetoken = referenceSubscribeTimetoken(result.cursor.timetoken, this.storedTimetoken); + if (this.storedTimetoken) { + this.currentTimetoken = this.storedTimetoken; + this.storedTimetoken = null; + } + else { + this.lastTimetoken = this.currentTimetoken; + this.currentTimetoken = result.cursor.timetoken; + } + if (!this.subscriptionStatusAnnounced) { + const connected = { + category: StatusCategory$1.PNConnectedCategory, + operation: status.operation, + affectedChannels: Array.from(this.pendingChannelSubscriptions), + subscribedChannels: this.subscribedChannels, + affectedChannelGroups: Array.from(this.pendingChannelGroupSubscriptions), + lastTimetoken: this.lastTimetoken, + currentTimetoken: this.currentTimetoken, + }; + this.subscriptionStatusAnnounced = true; + this.emitStatus(connected); + // Clear pending channels and groups. + this.pendingChannelGroupSubscriptions.clear(); + this.pendingChannelSubscriptions.clear(); + } + const { messages } = result; + const { requestMessageCountThreshold, dedupeOnSubscribe } = this.configuration; + if (requestMessageCountThreshold && messages.length >= requestMessageCountThreshold) { + this.emitStatus({ + category: StatusCategory$1.PNRequestMessageCountExceededCategory, + operation: status.operation, + }); + } + try { + const cursor = { + timetoken: this.currentTimetoken, + region: this.region ? this.region : undefined, + }; + this.configuration.logger().debug('SubscriptionManager', () => { + const hashedEvents = messages.map((event) => ({ + type: event.type, + data: Object.assign(Object.assign({}, event.data), { pn_mfp: event.pn_mfp }), + })); + return { messageType: 'object', message: hashedEvents, details: 'Received events:' }; + }); + messages.forEach((message) => { + if (dedupeOnSubscribe && 'message' in message.data && 'timetoken' in message.data) { + if (this.dedupingManager.isDuplicate(message.data)) { + this.configuration.logger().warn('SubscriptionManager', () => ({ + messageType: 'object', + message: message.data, + details: 'Duplicate message detected (skipped):', + })); + return; + } + this.dedupingManager.addEntry(message.data); + } + this.emitEvent(cursor, message); + }); + } + catch (e) { + const errorStatus = { + error: true, + category: StatusCategory$1.PNUnknownCategory, + errorData: e, + statusCode: 0, + }; + this.emitStatus(errorStatus); + } + this.region = result.cursor.region; + if (!this.disconnectedWhileHandledEvent) + this.startSubscribeLoop(); + else + this.disconnectedWhileHandledEvent = false; + } + // endregion + // region Presence + /** + * Update `uuid` state which should be sent with subscribe request. + * + * @param parameters - Channels and groups with state which should be associated to `uuid`. + */ + setState(parameters) { + const { state, channels, channelGroups } = parameters; + channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => channel in this.channels && (this.presenceState[channel] = state)); + channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => group in this.channelGroups && (this.presenceState[group] = state)); + } + /** + * Manual presence management. + * + * @param parameters - Desired presence state for provided list of channels and groups. + */ + changePresence(parameters) { + const { connected, channels, channelGroups } = parameters; + if (connected) { + channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => (this.heartbeatChannels[channel] = {})); + channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => (this.heartbeatChannelGroups[group] = {})); + } + else { + channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => { + if (channel in this.heartbeatChannels) + delete this.heartbeatChannels[channel]; + }); + channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => { + if (group in this.heartbeatChannelGroups) + delete this.heartbeatChannelGroups[group]; + }); + if (this.configuration.suppressLeaveEvents === false) { + this.leaveCall({ channels, channelGroups }, (status) => this.emitStatus(status)); + } + } + this.reconnect(); + } + startHeartbeatTimer() { + this.stopHeartbeatTimer(); + const heartbeatInterval = this.configuration.getHeartbeatInterval(); + if (!heartbeatInterval || heartbeatInterval === 0) + return; + // Sending immediate heartbeat only if not working as a smart heartbeat. + if (!this.configuration.useSmartHeartbeat) + this.sendHeartbeat(); + this.heartbeatTimer = setInterval(() => this.sendHeartbeat(), heartbeatInterval * 1000); + } + /** + * Stop heartbeat. + * + * Stop timer which trigger {@link HeartbeatRequest} sending with configured presence intervals. + */ + stopHeartbeatTimer() { + if (!this.heartbeatTimer) + return; + clearInterval(this.heartbeatTimer); + this.heartbeatTimer = null; + } + /** + * Send heartbeat request. + */ + sendHeartbeat() { + const heartbeatChannelGroups = Object.keys(this.heartbeatChannelGroups); + const heartbeatChannels = Object.keys(this.heartbeatChannels); + // There is no need to start heartbeat loop if there is no channels and groups to use. + if (heartbeatChannels.length === 0 && heartbeatChannelGroups.length === 0) + return; + this.heartbeatCall({ + channels: heartbeatChannels, + channelGroups: heartbeatChannelGroups, + heartbeat: this.configuration.getPresenceTimeout(), + state: this.presenceState, + }, (status) => { + if (status.error && this.configuration.announceFailedHeartbeats) + this.emitStatus(status); + if (status.error && this.configuration.autoNetworkDetection && this.isOnline) { + this.isOnline = false; + this.disconnect(); + this.emitStatus({ category: StatusCategory$1.PNNetworkDownCategory }); + this.reconnect(); + } + if (!status.error && this.configuration.announceSuccessfulHeartbeats) + this.emitStatus(status); + }); + } + } + + // endregion + /** + * Base notification payload object. + */ + class BaseNotificationPayload { + /** + * Base notification provider payload object. + * + * @internal + * + * @param payload - Object which contains vendor-specific preformatted push notification payload. + * @param title - Notification main title. + * @param body - Notification body (main messages). + */ + constructor(payload, title, body) { + this._payload = payload; + this.setDefaultPayloadStructure(); + this.title = title; + this.body = body; + } + /** + * Retrieve resulting notification payload content for message. + * + * @returns Preformatted push notification payload data. + */ + get payload() { + return this._payload; + } + /** + * Update notification title. + * + * @param value - New notification title. + */ + set title(value) { + this._title = value; + } + /** + * Update notification subtitle. + * + * @param value - New second-line notification title. + */ + set subtitle(value) { + this._subtitle = value; + } + /** + * Update notification body. + * + * @param value - Update main notification message (shown when expanded). + */ + set body(value) { + this._body = value; + } + /** + * Update application badge number. + * + * @param value - Number which should be shown in application badge upon receiving notification. + */ + set badge(value) { + this._badge = value; + } + /** + * Update notification sound. + * + * @param value - Name of the sound file which should be played upon notification receive. + */ + set sound(value) { + this._sound = value; + } + /** + * Platform-specific structure initialization. + * + * @internal + */ + setDefaultPayloadStructure() { } + /** + * Translate data object into PubNub push notification payload object. + * + * @internal + * + * @returns Preformatted push notification payload. + */ + toObject() { + return {}; + } + } + /** + * Message payload for Apple Push Notification Service. + */ + class APNSNotificationPayload extends BaseNotificationPayload { + constructor() { + super(...arguments); + /** + * Type of push notification service for which payload will be created. + * + * @internal + */ + this._apnsPushType = 'apns'; + /** + * Whether resulting payload should trigger silent notification or not. + * + * @internal + */ + this._isSilent = false; + } + get payload() { + return this._payload; + } + /** + * Update notification receivers configuration. + * + * @param value - New APNS2 configurations. + */ + set configurations(value) { + if (!value || !value.length) + return; + this._configurations = value; + } + /** + * Notification payload. + * + * @returns Platform-specific part of PubNub notification payload. + */ + get notification() { + return this.payload.aps; + } + /** + * Notification title. + * + * @returns Main notification title. + */ + get title() { + return this._title; + } + /** + * Update notification title. + * + * @param value - New notification title. + */ + set title(value) { + if (!value || !value.length) + return; + this.payload.aps.alert.title = value; + this._title = value; + } + /** + * Notification subtitle. + * + * @returns Second-line notification title. + */ + get subtitle() { + return this._subtitle; + } + /** + * Update notification subtitle. + * + * @param value - New second-line notification title. + */ + set subtitle(value) { + if (!value || !value.length) + return; + this.payload.aps.alert.subtitle = value; + this._subtitle = value; + } + /** + * Notification body. + * + * @returns Main notification message (shown when expanded). + */ + get body() { + return this._body; + } + /** + * Update notification body. + * + * @param value - Update main notification message (shown when expanded). + */ + set body(value) { + if (!value || !value.length) + return; + this.payload.aps.alert.body = value; + this._body = value; + } + /** + * Retrieve unread notifications number. + * + * @returns Number of unread notifications which should be shown on application badge. + */ + get badge() { + return this._badge; + } + /** + * Update application badge number. + * + * @param value - Number which should be shown in application badge upon receiving notification. + */ + set badge(value) { + if (value === undefined || value === null) + return; + this.payload.aps.badge = value; + this._badge = value; + } + /** + * Retrieve notification sound file. + * + * @returns Notification sound file name from resource bundle. + */ + get sound() { + return this._sound; + } + /** + * Update notification sound. + * + * @param value - Name of the sound file which should be played upon notification receive. + */ + set sound(value) { + if (!value || !value.length) + return; + this.payload.aps.sound = value; + this._sound = value; + } + /** + * Set whether notification should be silent or not. + * + * `content-available` notification type will be used to deliver silent notification if set to `true`. + * + * @param value - Whether notification should be sent as silent or not. + */ + set silent(value) { + this._isSilent = value; + } + /** + * Setup push notification payload default content. + * + * @internal + */ + setDefaultPayloadStructure() { + this.payload.aps = { alert: {} }; + } + /** + * Translate data object into PubNub push notification payload object. + * + * @internal + * + * @returns Preformatted push notification payload. + */ + toObject() { + const payload = Object.assign({}, this.payload); + const { aps } = payload; + let { alert } = aps; + if (this._isSilent) + aps['content-available'] = 1; + if (this._apnsPushType === 'apns2') { + if (!this._configurations || !this._configurations.length) + throw new ReferenceError('APNS2 configuration is missing'); + const configurations = []; + this._configurations.forEach((configuration) => { + configurations.push(this.objectFromAPNS2Configuration(configuration)); + }); + if (configurations.length) + payload.pn_push = configurations; + } + if (!alert || !Object.keys(alert).length) + delete aps.alert; + if (this._isSilent) { + delete aps.alert; + delete aps.badge; + delete aps.sound; + alert = {}; + } + return this._isSilent || (alert && Object.keys(alert).length) ? payload : null; + } + /** + * Create PubNub push notification service APNS2 configuration information object. + * + * @internal + * + * @param configuration - Source user-provided APNS2 configuration. + * + * @returns Preformatted for PubNub service APNS2 configuration information. + */ + objectFromAPNS2Configuration(configuration) { + if (!configuration.targets || !configuration.targets.length) + throw new ReferenceError('At least one APNS2 target should be provided'); + const { collapseId, expirationDate } = configuration; + const objectifiedConfiguration = { + auth_method: 'token', + targets: configuration.targets.map((target) => this.objectFromAPNSTarget(target)), + version: 'v2', + }; + if (collapseId && collapseId.length) + objectifiedConfiguration.collapse_id = collapseId; + if (expirationDate) + objectifiedConfiguration.expiration = expirationDate.toISOString(); + return objectifiedConfiguration; + } + /** + * Create PubNub push notification service APNS2 target information object. + * + * @internal + * + * @param target - Source user-provided data. + * + * @returns Preformatted for PubNub service APNS2 target information. + */ + objectFromAPNSTarget(target) { + if (!target.topic || !target.topic.length) + throw new TypeError("Target 'topic' undefined."); + const { topic, environment = 'development', excludedDevices = [] } = target; + const objectifiedTarget = { topic, environment }; + if (excludedDevices.length) + objectifiedTarget.excluded_devices = excludedDevices; + return objectifiedTarget; + } + } + /** + * Message payload for Firebase Cloud Messaging service. + */ + class FCMNotificationPayload extends BaseNotificationPayload { + get payload() { + return this._payload; + } + /** + * Notification payload. + * + * @returns Platform-specific part of PubNub notification payload. + */ + get notification() { + return this.payload.notification; + } + /** + * Silent notification payload. + * + * @returns Silent notification payload (data notification). + */ + get data() { + return this.payload.data; + } + /** + * Retrieve Android notification payload and initialize required structure. + * + * @returns Android specific notification payload. + */ + get androidNotification() { + var _c; + return (_c = this.payload.android) === null || _c === void 0 ? void 0 : _c.notification; + } + /** + * Notification title. + * + * @returns Main notification title. + */ + get title() { + return this._title; + } + /** + * Update notification title. + * + * @param value - New notification title. + */ + set title(value) { + if (!value || !value.length) + return; + this.payload.notification.title = value; + this.androidNotification.title = value; + this._title = value; + } + /** + * Notification body. + * + * @returns Main notification message (shown when expanded). + */ + get body() { + return this._body; + } + /** + * Update notification body. + * + * @param value - Update main notification message (shown when expanded). + */ + set body(value) { + if (!value || !value.length) + return; + this.payload.notification.body = value; + this.androidNotification.body = value; + this._body = value; + } + /** + * Retrieve unread notifications number. + * + * @returns Number of unread notifications which should be shown on application badge. + */ + get badge() { + return this._badge; + } + /** + * Update application badge number. + * + * @param value - Number which should be shown in application badge upon receiving notification. + */ + set badge(value) { + if (value === undefined || value === null) + return; + this.androidNotification.notification_count = value; + this._badge = value; + } + /** + * Retrieve notification sound file. + * + * @returns Notification sound file name from resource bundle. + */ + get sound() { + return this._sound; + } + /** + * Update notification sound. + * + * @param value - Name of the sound file which should be played upon notification receive. + */ + set sound(value) { + if (!value || !value.length) + return; + this.androidNotification.sound = value; + this._sound = value; + } + /** + * Retrieve notification icon file. + * + * @returns Notification icon file name from resource bundle. + */ + get icon() { + return this._icon; + } + /** + * Update notification icon. + * + * @param value - Name of the icon file set for `android.notification.icon`. + */ + set icon(value) { + if (!value || !value.length) + return; + this.androidNotification.icon = value; + this._icon = value; + } + /** + * Retrieve notifications grouping tag. + * + * @returns Notifications grouping tag. + */ + get tag() { + return this._tag; + } + /** + * Update notifications grouping tag. + * + * @param value - String set for `android.notification.tag` to group similar notifications. + */ + set tag(value) { + if (!value || !value.length) + return; + this.androidNotification.tag = value; + this._tag = value; + } + /** + * Set whether notification should be silent or not. + * + * All notification data will be sent under `data` field if set to `true`. + * + * @param value - Whether notification should be sent as silent or not. + */ + set silent(value) { + this._isSilent = value; + } + /** + * Setup push notification payload default content. + * + * @internal + */ + setDefaultPayloadStructure() { + this.payload.notification = {}; + this.payload.data = {}; + this.payload.android = { notification: {} }; + } + /** + * Translate data object into PubNub push notification payload object. + * + * @internal + * + * @returns Preformatted push notification payload. + */ + toObject() { + var _c, _e; + const payload = {}; + const notification = Object.assign({}, this.payload.notification); + const android = Object.assign({}, this.payload.android); + const androidNotification = Object.assign({}, ((_c = android.notification) !== null && _c !== void 0 ? _c : {})); + // Strip title/body from android.notification — they belong in top-level notification (or data for silent). + const androidSpecificFields = __rest(androidNotification, ["title", "body"]); + if (this._isSilent) { + // For silent (data-only) notifications, strip all `notification` fields + // (both root and android) and move everything into the root `data` object. + const data = {}; + if (this._title) + data.title = this._title; + if (this._body) + data.body = this._body; + // Merge android-specific notification fields (sound, icon, tag, etc.) into data. + for (const [key, value] of Object.entries(androidSpecificFields)) { + if (value !== undefined && value !== null) + data[key] = String(value); + } + // Merge any existing user-provided custom data. + if (this.payload.data) + Object.assign(data, this.payload.data); + if (Object.keys(data).length) + payload.data = data; + // Exclude `notification` entirely from android — only keep non-notification android fields. + delete android.notification; + if (Object.keys(android).length) { + payload.android = android; + } + } + else { + if (Object.keys(notification).length) + payload.notification = notification; + // Include top-level data if present. + if (this.payload.data && Object.keys(this.payload.data).length) + payload.data = Object.assign({}, this.payload.data); + // android.notification should only contain android-specific fields (sound, icon, tag, etc.). + if (Object.keys(androidSpecificFields).length) { + const androidWithoutNotification = __rest(android, ["notification"]); + payload.android = Object.assign(Object.assign({}, androidWithoutNotification), { notification: androidSpecificFields }); + } + else { + const androidWithoutNotification = __rest(android, ["notification"]); + if (Object.keys(androidWithoutNotification).length) { + payload.android = androidWithoutNotification; + } + } + } + // Preserve other top-level FCM fields (apns, webpush, fcm_options, etc.). + const _f = this.payload, otherFields = __rest(_f, ["notification", "android", "data", "pn_exceptions"]); + Object.assign(payload, otherFields); + if ((_e = this.payload.pn_exceptions) === null || _e === void 0 ? void 0 : _e.length) + payload.pn_exceptions = this.payload.pn_exceptions; + return Object.keys(payload).length ? payload : null; + } + } + class NotificationsPayload { + /** + * Create push notification payload holder. + * + * @internal + * + * @param title - String which will be shown at the top of the notification (below app name). + * @param body - String with message which should be shown when user will check notification. + */ + constructor(title, body) { + this._payload = { apns: {}, fcm: {} }; + this._title = title; + this._body = body; + this.apns = new APNSNotificationPayload(this._payload.apns, title, body); + this.fcm = new FCMNotificationPayload(this._payload.fcm, title, body); + } + /** + * Enable or disable push notification debugging message. + * + * @param value - Whether debug message from push notification scheduler should be published to the specific + * channel or not. + */ + set debugging(value) { + this._debugging = value; + } + /** + * Notification title. + * + * @returns Main notification title. + */ + get title() { + return this._title; + } + /** + * Notification subtitle. + * + * @returns Second-line notification title. + */ + get subtitle() { + return this._subtitle; + } + /** + * Update notification subtitle. + * + * @param value - New second-line notification title. + */ + set subtitle(value) { + this._subtitle = value; + this.apns.subtitle = value; + this.fcm.subtitle = value; + } + /** + * Notification body. + * + * @returns Main notification message (shown when expanded). + */ + get body() { + return this._body; + } + /** + * Retrieve unread notifications number. + * + * @returns Number of unread notifications which should be shown on application badge. + */ + get badge() { + return this._badge; + } + /** + * Update application badge number. + * + * @param value - Number which should be shown in application badge upon receiving notification. + */ + set badge(value) { + this._badge = value; + this.apns.badge = value; + this.fcm.badge = value; + } + /** + * Retrieve notification sound file. + * + * @returns Notification sound file name from resource bundle. + */ + get sound() { + return this._sound; + } + /** + * Update notification sound. + * + * @param value - Name of the sound file which should be played upon notification receive. + */ + set sound(value) { + this._sound = value; + this.apns.sound = value; + this.fcm.sound = value; + } + /** + * Build notifications platform for requested platforms. + * + * @param platforms - List of platforms for which payload should be added to final dictionary. Supported values: + * fcm, apns, and apns2. + * + * @returns Object with data, which can be sent with publish method call and trigger remote notifications for + * specified platforms. + */ + buildPayload(platforms) { + const payload = {}; + if (platforms.includes('apns') || platforms.includes('apns2')) { + // @ts-expect-error Override APNS version. + this.apns._apnsPushType = platforms.includes('apns') ? 'apns' : 'apns2'; + const apnsPayload = this.apns.toObject(); + if (apnsPayload && Object.keys(apnsPayload).length) + payload.pn_apns = apnsPayload; + } + if (platforms.includes('fcm')) { + const fcmPayload = this.fcm.toObject(); + if (fcmPayload && Object.keys(fcmPayload).length) + payload.pn_fcm = fcmPayload; + } + if (Object.keys(payload).length && this._debugging) + payload.pn_debug = true; + return payload; + } + } + + /** + * Event Engine terminate signal listener module. + * + * @internal + */ + /** + * @internal + */ + class Subject { + constructor(sync = false) { + this.sync = sync; + this.listeners = new Set(); + } + subscribe(listener) { + this.listeners.add(listener); + return () => { + this.listeners.delete(listener); + }; + } + notify(event) { + const wrapper = () => { + this.listeners.forEach((listener) => { + listener(event); + }); + }; + if (this.sync) { + wrapper(); + } + else { + setTimeout(wrapper, 0); + } + } + } + + /** + * Event Engine Core state module. + * + * @internal + */ + /** + * Event engine current state object. + * + * State contains current context and list of invocations which should be performed by the Event Engine. + * + * @internal + */ + class State { + transition(context, event) { + var _a; + if (this.transitionMap.has(event.type)) { + return (_a = this.transitionMap.get(event.type)) === null || _a === void 0 ? void 0 : _a(context, event); + } + return undefined; + } + constructor(label) { + this.label = label; + this.transitionMap = new Map(); + this.enterEffects = []; + this.exitEffects = []; + } + on(eventType, transition) { + this.transitionMap.set(eventType, transition); + return this; + } + with(context, effects) { + return [this, context, effects !== null && effects !== void 0 ? effects : []]; + } + onEnter(effect) { + this.enterEffects.push(effect); + return this; + } + onExit(effect) { + this.exitEffects.push(effect); + return this; + } + } + + /** + * Event Engine Core module. + * + * @internal + */ + /** + * Generic event engine. + * + * @internal + */ + class Engine extends Subject { + constructor(logger) { + super(true); + this.logger = logger; + this._pendingEvents = []; + this._inTransition = false; + } + get currentState() { + return this._currentState; + } + get currentContext() { + return this._currentContext; + } + describe(label) { + return new State(label); + } + start(initialState, initialContext) { + this._currentState = initialState; + this._currentContext = initialContext; + this.notify({ + type: 'engineStarted', + state: initialState, + context: initialContext, + }); + return; + } + transition(event) { + if (!this._currentState) { + this.logger.error('Engine', 'Finite state machine is not started'); + throw new Error('Start the engine first'); + } + if (this._inTransition) { + this.logger.trace('Engine', () => ({ + messageType: 'object', + message: event, + details: 'Event engine in transition. Enqueue received event:', + })); + this._pendingEvents.push(event); + return; + } + else + this._inTransition = true; + this.logger.trace('Engine', () => ({ + messageType: 'object', + message: event, + details: 'Event engine received event:', + })); + this.notify({ + type: 'eventReceived', + event: event, + }); + const transition = this._currentState.transition(this._currentContext, event); + if (transition) { + const [newState, newContext, effects] = transition; + this.logger.trace('Engine', `Exiting state: ${this._currentState.label}`); + for (const effect of this._currentState.exitEffects) { + this.notify({ + type: 'invocationDispatched', + invocation: effect(this._currentContext), + }); + } + this.logger.trace('Engine', () => ({ + messageType: 'object', + details: `Entering '${newState.label}' state with context:`, + message: newContext, + })); + const oldState = this._currentState; + this._currentState = newState; + const oldContext = this._currentContext; + this._currentContext = newContext; + this.notify({ + type: 'transitionDone', + fromState: oldState, + fromContext: oldContext, + toState: newState, + toContext: newContext, + event: event, + }); + for (const effect of effects) { + this.notify({ + type: 'invocationDispatched', + invocation: effect, + }); + } + for (const effect of this._currentState.enterEffects) { + this.notify({ + type: 'invocationDispatched', + invocation: effect(this._currentContext), + }); + } + } + else + this.logger.warn('Engine', `No transition from '${this._currentState.label}' found for event: ${event.type}`); + this._inTransition = false; + // Check whether a pending task should be dequeued. + if (this._pendingEvents.length > 0) { + const nextEvent = this._pendingEvents.shift(); + if (nextEvent) { + this.logger.trace('Engine', () => ({ + messageType: 'object', + message: nextEvent, + details: 'De-queueing pending event:', + })); + this.transition(nextEvent); + } + } + } + } + + /** + * Event Engine Core Effects dispatcher module. + * + * @internal + */ + /** + * Event Engine effects dispatcher. + * + * Dispatcher responsible for invocation enqueue and dequeue for processing. + * + * @internal + */ + class Dispatcher { + constructor(dependencies, logger) { + this.dependencies = dependencies; + this.logger = logger; + this.instances = new Map(); + this.handlers = new Map(); + } + on(type, handlerCreator) { + this.handlers.set(type, handlerCreator); + } + dispatch(invocation) { + this.logger.trace('Dispatcher', `Process invocation: ${invocation.type}`); + if (invocation.type === 'CANCEL') { + if (this.instances.has(invocation.payload)) { + const instance = this.instances.get(invocation.payload); + instance === null || instance === void 0 ? void 0 : instance.cancel(); + this.instances.delete(invocation.payload); + } + return; + } + const handlerCreator = this.handlers.get(invocation.type); + if (!handlerCreator) { + this.logger.error('Dispatcher', `Unhandled invocation '${invocation.type}'`); + throw new Error(`Unhandled invocation '${invocation.type}'`); + } + const instance = handlerCreator(invocation.payload, this.dependencies); + this.logger.trace('Dispatcher', () => ({ + messageType: 'object', + details: 'Call invocation handler with parameters:', + message: invocation.payload, + ignoredKeys: ['abortSignal'], + })); + if (invocation.managed) { + this.instances.set(invocation.type, instance); + } + instance.start(); + } + dispose() { + for (const [key, instance] of this.instances.entries()) { + instance.cancel(); + this.instances.delete(key); + } + } + } + + /** + * Event Engine Core types module. + * + * @internal + */ + /** + * Create and configure event engine event. + * + * @internal + */ + function createEvent(type, fn) { + const creator = function (...args) { + return { + type, + payload: fn === null || fn === void 0 ? void 0 : fn(...args), + }; + }; + creator.type = type; + return creator; + } + /** + * Create and configure short-term effect invocation. + * + * @internal + */ + function createEffect(type, fn) { + const creator = (...args) => { + return { type, payload: fn(...args), managed: false }; + }; + creator.type = type; + return creator; + } + /** + * Create and configure long-running effect invocation. + * + * @internal + */ + function createManagedEffect(type, fn) { + const creator = (...args) => { + return { type, payload: fn(...args), managed: true }; + }; + creator.type = type; + creator.cancel = { type: 'CANCEL', payload: type, managed: false }; + return creator; + } + + /** + * Event Engine managed effects terminate signal module. + * + * @internal + */ + class AbortError extends Error { + constructor() { + super('The operation was aborted.'); + this.name = 'AbortError'; + Object.setPrototypeOf(this, new.target.prototype); + } + } + /** + * Event Engine stored effect processing cancellation signal. + * + * @internal + */ + class AbortSignal extends Subject { + constructor() { + super(...arguments); + this._aborted = false; + } + get aborted() { + return this._aborted; + } + throwIfAborted() { + if (this._aborted) { + throw new AbortError(); + } + } + abort() { + this._aborted = true; + this.notify(new AbortError()); + } + } + + /** + * Event Engine Core Effects handler module. + * + * @internal + */ + /** + * Synchronous (short-term) effect invocation handler. + * + * Handler manages effect execution on behalf of effect dispatcher. + * + * @internal + */ + class Handler { + constructor(payload, dependencies) { + this.payload = payload; + this.dependencies = dependencies; + } + } + /** + * Asynchronous (long-running) effect invocation handler. + * + * Handler manages effect execution on behalf of effect dispatcher. + * + * @internal + */ + class AsyncHandler extends Handler { + constructor(payload, dependencies, asyncFunction) { + super(payload, dependencies); + this.asyncFunction = asyncFunction; + this.abortSignal = new AbortSignal(); + } + start() { + this.asyncFunction(this.payload, this.abortSignal, this.dependencies).catch((error) => { + // swallow the error + }); + } + cancel() { + this.abortSignal.abort(); + } + } + /** + * Asynchronous effect invocation handler constructor. + * + * @param handlerFunction - Function which performs asynchronous action and should be called on `start`. + * + * @internal + */ + const asyncHandler = (handlerFunction) => (payload, dependencies) => new AsyncHandler(payload, dependencies, handlerFunction); + + /** + * Presence Event Engine effects module. + * + * @internal + */ + /** + * Presence heartbeat effect. + * + * Performs presence heartbeat REST API call. + * + * @internal + */ + const heartbeat = createManagedEffect('HEARTBEAT', (channels, groups) => ({ + channels, + groups, + })); + /** + * Presence leave effect. + * + * Performs presence leave REST API call. + * + * @internal + */ + const leave = createEffect('LEAVE', (channels, groups) => ({ + channels, + groups, + })); + /** + * Emit presence heartbeat REST API call result status effect. + * + * Notify status change event listeners. + * + * @internal + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ + const emitStatus$1 = createEffect('EMIT_STATUS', (status) => status); + /** + * Heartbeat delay effect. + * + * Delay of configured length (heartbeat interval) before another heartbeat REST API call will be done. + * + * @internal + */ + const wait = createManagedEffect('WAIT', () => ({})); + + /** + * Presence Event Engine events module. + * + * @internal + */ + /** + * Reconnect event. + * + * Event is sent each time when user restores real-time updates processing and notifies other present subscribers + * about joining back. + * + * @internal + */ + const reconnect$1 = createEvent('RECONNECT', () => ({})); + /** + * Disconnect event. + * + * Event is sent when user wants to temporarily stop real-time updates processing and notifies other present + * subscribers about leaving. + * + * @internal + */ + const disconnect$1 = createEvent('DISCONNECT', (isOffline = false) => ({ isOffline })); + /** + * Channel / group join event. + * + * Event is sent when user adds new channels / groups to the active channels / groups list and notifies other present + * subscribers about joining. + * + * @internal + */ + const joined = createEvent('JOINED', (channels, groups) => ({ + channels, + groups, + })); + /** + * Channel / group leave event. + * + * Event is sent when user removes channels / groups from the active channels / groups list and notifies other present + * subscribers about leaving. + * + * @internal + */ + const left = createEvent('LEFT', (channels, groups) => ({ + channels, + groups, + })); + /** + * Leave all event. + * + * Event is sent when user doesn't want to receive any real-time updates anymore and notifies other + * subscribers on previously active channels / groups about leaving. + * + * @internal + */ + const leftAll = createEvent('LEFT_ALL', (isOffline = false) => ({ isOffline })); + /** + * Presence heartbeat success event. + * + * Event is sent by corresponding effect handler if REST API call was successful. + * + * @internal + */ + const heartbeatSuccess = createEvent('HEARTBEAT_SUCCESS', (statusCode) => ({ statusCode })); + /** + * Presence heartbeat did fail event. + * + * Event is sent by corresponding effect handler if REST API call failed. + * + * @internal + */ + const heartbeatFailure = createEvent('HEARTBEAT_FAILURE', (error) => error); + /** + * Delayed presence heartbeat event. + * + * Event is sent by corresponding effect handler when delay timer between heartbeat calls fired. + * + * @internal + */ + const timesUp = createEvent('TIMES_UP', () => ({})); + + /** + * Presence Event Engine effects dispatcher. + * + * @internal + */ + /** + * Presence Event Engine dispatcher. + * + * Dispatcher responsible for presence events handling and corresponding effects execution. + * + * @internal + */ + class PresenceEventEngineDispatcher extends Dispatcher { + constructor(engine, dependencies) { + super(dependencies, dependencies.config.logger()); + this.on(heartbeat.type, asyncHandler((payload_1, abortSignal_1, _a) => __awaiter(this, [payload_1, abortSignal_1, _a], void 0, function* (payload, abortSignal, { heartbeat, presenceState, config }) { + abortSignal.throwIfAborted(); + try { + const result = yield heartbeat(Object.assign(Object.assign({ abortSignal: abortSignal, channels: payload.channels, channelGroups: payload.groups }, (config.maintainPresenceState && { state: presenceState })), { heartbeat: config.presenceTimeout })); + engine.transition(heartbeatSuccess(200)); + } + catch (e) { + if (e instanceof PubNubError) { + if (e.status && e.status.category == StatusCategory$1.PNCancelledCategory) + return; + engine.transition(heartbeatFailure(e)); + } + } + }))); + this.on(leave.type, asyncHandler((payload_1, _1, _a) => __awaiter(this, [payload_1, _1, _a], void 0, function* (payload, _, { leave, config }) { + if (!config.suppressLeaveEvents) { + try { + leave({ + channels: payload.channels, + channelGroups: payload.groups, + }); + } + catch (e) { } + } + }))); + this.on(wait.type, asyncHandler((_1, abortSignal_1, _a) => __awaiter(this, [_1, abortSignal_1, _a], void 0, function* (_, abortSignal, { heartbeatDelay }) { + const { cancelDelay, promise } = heartbeatDelay(); + abortSignal.throwIfAborted(); + const unsubscribeAbortListener = abortSignal.subscribe(() => cancelDelay()); + yield promise; + unsubscribeAbortListener(); + abortSignal.throwIfAborted(); + return engine.transition(timesUp()); + }))); + this.on(emitStatus$1.type, asyncHandler((payload_1, _1, _a) => __awaiter(this, [payload_1, _1, _a], void 0, function* (payload, _, { emitStatus, config }) { + if (config.announceFailedHeartbeats && (payload === null || payload === void 0 ? void 0 : payload.error) === true) { + emitStatus(Object.assign(Object.assign({}, payload), { operation: RequestOperation$1.PNHeartbeatOperation })); + } + else if (config.announceSuccessfulHeartbeats && payload.statusCode === 200) { + emitStatus(Object.assign(Object.assign({}, payload), { error: false, operation: RequestOperation$1.PNHeartbeatOperation, category: StatusCategory$1.PNAcknowledgmentCategory })); + } + }))); + } + } + + /** + * Presence Event Engine state instances. + * + * Isolated from transition handlers so state modules can import sibling states + * without creating circular dependencies. + * + * @internal + */ + /** @internal */ + const HeartbeatInactiveState = new State('HEARTBEAT_INACTIVE'); + /** @internal */ + const HeartbeatingState = new State('HEARTBEATING'); + /** @internal */ + const HeartbeatCooldownState = new State('HEARTBEAT_COOLDOWN'); + /** @internal */ + const HeartbeatStoppedState = new State('HEARTBEAT_STOPPED'); + /** @internal */ + const HeartbeatFailedState = new State('HEARTBEAT_FAILED'); + + /** + * Inactive heratbeating state module. + * + * @internal + */ + /** + * Inactive heratbeating state + * + * State in which Presence Event Engine doesn't process any heartbeat requests (initial state). + * + * @internal + */ + HeartbeatInactiveState.on(joined.type, (_, event) => HeartbeatingState.with({ + channels: event.payload.channels, + groups: event.payload.groups, + })); + + /** + * Heartbeating state module. + * + * @internal + */ + /** + * Heartbeating state module. + * + * State in which Presence Event Engine send heartbeat REST API call. + * + * @internal + */ + HeartbeatingState.onEnter((context) => heartbeat(context.channels, context.groups)); + HeartbeatingState.onExit(() => heartbeat.cancel); + HeartbeatingState.on(heartbeatSuccess.type, (context, event) => HeartbeatCooldownState.with({ channels: context.channels, groups: context.groups }, [ + emitStatus$1(Object.assign({}, event.payload)), + ])); + HeartbeatingState.on(joined.type, (context, event) => HeartbeatingState.with({ + channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], + groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], + })); + HeartbeatingState.on(left.type, (context, event) => { + return HeartbeatingState.with({ + channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), + groups: context.groups.filter((group) => !event.payload.groups.includes(group)), + }, [leave(event.payload.channels, event.payload.groups)]); + }); + HeartbeatingState.on(heartbeatFailure.type, (context, event) => HeartbeatFailedState.with(Object.assign({}, context), [ + ...(event.payload.status ? [emitStatus$1(Object.assign({}, event.payload.status))] : []), + ])); + HeartbeatingState.on(disconnect$1.type, (context, event) => HeartbeatStoppedState.with({ channels: context.channels, groups: context.groups }, [ + ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), + ])); + HeartbeatingState.on(leftAll.type, (context, event) => HeartbeatInactiveState.with(undefined, [ + ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), + ])); + + /** + * Waiting next heartbeat state module. + * + * @internal + */ + /** + * Waiting next heartbeat state. + * + * State in which Presence Event Engine is waiting when delay will run out and next heartbeat call should be done. + * + * @internal + */ + HeartbeatCooldownState.onEnter(() => wait()); + HeartbeatCooldownState.onExit(() => wait.cancel); + HeartbeatCooldownState.on(timesUp.type, (context, _) => HeartbeatingState.with({ + channels: context.channels, + groups: context.groups, + })); + HeartbeatCooldownState.on(joined.type, (context, event) => HeartbeatingState.with({ + channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], + groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], + })); + HeartbeatCooldownState.on(left.type, (context, event) => HeartbeatingState.with({ + channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), + groups: context.groups.filter((group) => !event.payload.groups.includes(group)), + }, [leave(event.payload.channels, event.payload.groups)])); + HeartbeatCooldownState.on(disconnect$1.type, (context, event) => HeartbeatStoppedState.with({ channels: context.channels, groups: context.groups }, [ + ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), + ])); + HeartbeatCooldownState.on(leftAll.type, (context, event) => HeartbeatInactiveState.with(undefined, [ + ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), + ])); + + /** + * Heartbeat stopped state module. + * + * @internal + */ + /** + * Heartbeat stopped state. + * + * State in which Presence Event Engine still has information about active channels / groups, but doesn't wait for + * delayed heartbeat request sending. + * + * @internal + */ + HeartbeatStoppedState.on(joined.type, (context, event) => HeartbeatStoppedState.with({ + channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], + groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], + })); + HeartbeatStoppedState.on(left.type, (context, event) => HeartbeatStoppedState.with({ + channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), + groups: context.groups.filter((group) => !event.payload.groups.includes(group)), + })); + HeartbeatStoppedState.on(reconnect$1.type, (context, _) => HeartbeatingState.with({ + channels: context.channels, + groups: context.groups, + })); + HeartbeatStoppedState.on(leftAll.type, (context, _) => HeartbeatInactiveState.with(undefined)); + + /** + * Failed to heartbeat state module. + * + * @internal + */ + /** + * Failed to heartbeat state. + * + * State in which Subscription Event Engine waits for user to try to reconnect after all retry attempts has been + * exhausted. + * + * @internal + */ + HeartbeatFailedState.on(joined.type, (context, event) => HeartbeatingState.with({ + channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], + groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], + })); + HeartbeatFailedState.on(left.type, (context, event) => HeartbeatingState.with({ + channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), + groups: context.groups.filter((group) => !event.payload.groups.includes(group)), + }, [leave(event.payload.channels, event.payload.groups)])); + HeartbeatFailedState.on(reconnect$1.type, (context, _) => HeartbeatingState.with({ + channels: context.channels, + groups: context.groups, + })); + HeartbeatFailedState.on(disconnect$1.type, (context, event) => HeartbeatStoppedState.with({ channels: context.channels, groups: context.groups }, [ + ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), + ])); + HeartbeatFailedState.on(leftAll.type, (context, event) => HeartbeatInactiveState.with(undefined, [ + ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), + ])); + + /** + * Presence Event Engine module. + * + * @internal + */ + /** + * Presence Event Engine Core. + * + * @internal + */ + class PresenceEventEngine { + get _engine() { + return this.engine; + } + constructor(dependencies) { + this.dependencies = dependencies; + this.channels = []; + this.groups = []; + this.engine = new Engine(dependencies.config.logger()); + this.dispatcher = new PresenceEventEngineDispatcher(this.engine, dependencies); + dependencies.config.logger().debug('PresenceEventEngine', 'Create presence event engine.'); + this._unsubscribeEngine = this.engine.subscribe((change) => { + if (change.type === 'invocationDispatched') { + this.dispatcher.dispatch(change.invocation); + } + }); + this.engine.start(HeartbeatInactiveState, undefined); + } + join({ channels, groups }) { + this.channels = [...this.channels, ...(channels !== null && channels !== void 0 ? channels : []).filter((channel) => !this.channels.includes(channel))]; + this.groups = [...this.groups, ...(groups !== null && groups !== void 0 ? groups : []).filter((group) => !this.groups.includes(group))]; + // Don't make any transitions if there is no channels and groups. + if (this.channels.length === 0 && this.groups.length === 0) + return; + this.engine.transition(joined(this.channels.slice(0), this.groups.slice(0))); + } + leave({ channels, groups }) { + // Update internal channel tracking to prevent stale heartbeat requests + if (channels) + this.channels = this.channels.filter((channel) => !channels.includes(channel)); + if (groups) + this.groups = this.groups.filter((group) => !groups.includes(group)); + if (this.dependencies.presenceState) { + channels === null || channels === void 0 ? void 0 : channels.forEach((c) => delete this.dependencies.presenceState[c]); + groups === null || groups === void 0 ? void 0 : groups.forEach((g) => delete this.dependencies.presenceState[g]); + } + this.engine.transition(left(channels !== null && channels !== void 0 ? channels : [], groups !== null && groups !== void 0 ? groups : [])); + } + leaveAll(isOffline = false) { + // Clear presence state for all current channels and groups + if (this.dependencies.presenceState) { + this.channels.forEach((c) => delete this.dependencies.presenceState[c]); + this.groups.forEach((g) => delete this.dependencies.presenceState[g]); + } + // Reset internal channel and group tracking + this.channels = []; + this.groups = []; + this.engine.transition(leftAll(isOffline)); + } + reconnect() { + this.engine.transition(reconnect$1()); + } + disconnect(isOffline = false) { + this.engine.transition(disconnect$1(isOffline)); + } + dispose() { + this.disconnect(true); + this._unsubscribeEngine(); + this.dispatcher.dispose(); + } + } + + /** + * Subscribe Event Engine events module. + * + * @internal + */ + /** + * Subscription list change event. + * + * Event is sent each time when the user would like to change a list of active channels / groups. + * + * @internal + */ + const subscriptionChange = createEvent('SUBSCRIPTION_CHANGED', (channels, groups, isOffline = false) => ({ + channels, + groups, + isOffline, + })); + /** + * Subscription loop restore. + * + * Event is sent when a user would like to try to catch up on missed updates by providing specific timetoken. + * + * @internal + */ + const restore = createEvent('SUBSCRIPTION_RESTORED', (channels, groups, timetoken, region) => ({ + channels, + groups, + cursor: { + timetoken: timetoken, + region: region !== null && region !== void 0 ? region : 0, + }, + })); + /** + * Initial subscription handshake success event. + * + * Event is sent by the corresponding effect handler if the REST API call was successful. + * + * @internal + */ + const handshakeSuccess = createEvent('HANDSHAKE_SUCCESS', (cursor) => cursor); + /** + * The initial subscription handshake did fail event. + * + * Event is sent by the corresponding effect handler if the REST API call failed. + * + * @internal + */ + const handshakeFailure = createEvent('HANDSHAKE_FAILURE', (error) => error); + /** + * Subscription successfully received real-time updates event. + * + * Event is sent by the corresponding effect handler if the REST API call was successful. + * + * @internal + */ + const receiveSuccess = createEvent('RECEIVE_SUCCESS', (cursor, events) => ({ + cursor, + events, + })); + /** + * Subscription did fail to receive real-time updates event. + * + * Event is sent by the corresponding effect handler if the REST API call failed. + * + * @internal + */ + const receiveFailure = createEvent('RECEIVE_FAILURE', (error) => error); + /** + * Client disconnect event. + * + * Event is sent when the user wants to temporarily stop real-time updates receive. + * + * @internal + */ + const disconnect = createEvent('DISCONNECT', (isOffline = false) => ({ isOffline })); + /** + * Client reconnect event. + * + * Event is sent when the user wants to restore real-time updates receive. + * + * @internal + */ + const reconnect = createEvent('RECONNECT', (timetoken, region) => ({ + cursor: { + timetoken: timetoken !== null && timetoken !== void 0 ? timetoken : '', + region: region !== null && region !== void 0 ? region : 0, + }, + })); + /** + * Completely stop real-time updates receive event. + * + * Event is sent when the user doesn't want to receive any real-time updates anymore. + * + * @internal + */ + const unsubscribeAll = createEvent('UNSUBSCRIBE_ALL', () => ({})); + + /** + * Subscribe Event Engine state instances. + * + * Isolated from transition handlers so state modules can import sibling states + * without creating circular dependencies. + * + * @internal + */ + /** @internal */ + const UnsubscribedState = new State('UNSUBSCRIBED'); + /** @internal */ + const HandshakingState = new State('HANDSHAKING'); + /** @internal */ + const HandshakeStoppedState = new State('HANDSHAKE_STOPPED'); + /** @internal */ + const HandshakeFailedState = new State('HANDSHAKE_FAILED'); + /** @internal */ + const ReceivingState = new State('RECEIVING'); + /** @internal */ + const ReceiveStoppedState = new State('RECEIVE_STOPPED'); + /** @internal */ + const ReceiveFailedState = new State('RECEIVE_FAILED'); + + /** + * Unsubscribed / disconnected state module. + * + * @internal + */ + /** + * Unsubscribed / disconnected state. + * + * State in which Subscription Event Engine doesn't process any real-time updates. + * + * @internal + */ + UnsubscribedState.on(subscriptionChange.type, (_, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ channels: payload.channels, groups: payload.groups, onDemand: true }); + }); + UnsubscribedState.on(restore.type, (_, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region }, + onDemand: true, + }); + }); + + /** + * Subscribe Event Engine effects module. + * + * @internal + */ + /** + * Initial subscription effect. + * + * Performs subscribe REST API call with `tt=0`. + * + * @internal + */ + const handshake = createManagedEffect('HANDSHAKE', (channels, groups, onDemand) => ({ + channels, + groups, + onDemand, + })); + /** + * Real-time updates receive effect. + * + * Performs sequential subscribe REST API call with `tt` set to the value received from the previous subscribe + * REST API call. + * + * @internal + */ + const receiveMessages = createManagedEffect('RECEIVE_MESSAGES', (channels, groups, cursor, onDemand) => ({ + channels, + groups, + cursor, + onDemand, + })); + /** + * Emit real-time updates effect. + * + * Notify event listeners about updates for which listener handlers has been provided. + * + * @internal + */ + const emitMessages = createEffect('EMIT_MESSAGES', (cursor, events) => ({ + cursor, + events, + })); + /** + * Emit subscription status change effect. + * + * Notify status change event listeners. + * + * @internal + */ + const emitStatus = createEffect('EMIT_STATUS', (status) => status); + + /** + * Initial subscription handshake (disconnected) state. + * + * @internal + */ + /** + * Initial subscription handshake (disconnected) state. + * + * State in which Subscription Event Engine tries to receive the subscription cursor for the next sequential + * subscribe REST API calls. + * + * @internal + */ + HandshakingState.onEnter((context) => { var _a; return handshake(context.channels, context.groups, (_a = context.onDemand) !== null && _a !== void 0 ? _a : false); }); + HandshakingState.onExit(() => handshake.cancel); + HandshakingState.on(subscriptionChange.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: context.cursor, + onDemand: true, + }); + }); + HandshakingState.on(handshakeSuccess.type, (context, { payload }) => { + var _a, _b, _c, _d, _e; + return ReceivingState.with({ + channels: context.channels, + groups: context.groups, + cursor: { + timetoken: !!((_a = context.cursor) === null || _a === void 0 ? void 0 : _a.timetoken) ? (_b = context.cursor) === null || _b === void 0 ? void 0 : _b.timetoken : payload.timetoken, + region: payload.region, + }, + referenceTimetoken: referenceSubscribeTimetoken(payload.timetoken, (_c = context.cursor) === null || _c === void 0 ? void 0 : _c.timetoken), + }, [ + emitStatus({ + category: StatusCategory$1.PNConnectedCategory, + affectedChannels: context.channels.slice(0), + affectedChannelGroups: context.groups.slice(0), + operation: RequestOperation$1.PNSubscribeOperation, + currentTimetoken: !!((_d = context.cursor) === null || _d === void 0 ? void 0 : _d.timetoken) ? (_e = context.cursor) === null || _e === void 0 ? void 0 : _e.timetoken : payload.timetoken, + }), + ]); + }); + HandshakingState.on(handshakeFailure.type, (context, event) => { + var _a; + return HandshakeFailedState.with(Object.assign(Object.assign({}, context), { reason: event.payload }), [ + emitStatus({ category: StatusCategory$1.PNConnectionErrorCategory, error: (_a = event.payload.status) === null || _a === void 0 ? void 0 : _a.category }), + ]); + }); + HandshakingState.on(disconnect.type, (context, event) => { + var _a; + if (!event.payload.isOffline) + return HandshakeStoppedState.with(Object.assign({}, context)); + else { + const errorReason = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation); + return HandshakeFailedState.with(Object.assign(Object.assign({}, context), { reason: errorReason }), [ + emitStatus({ + category: StatusCategory$1.PNConnectionErrorCategory, + error: (_a = errorReason.status) === null || _a === void 0 ? void 0 : _a.category, + }), + ]); + } + }); + HandshakingState.on(restore.type, (context, { payload }) => { + var _a; + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || ((_a = context === null || context === void 0 ? void 0 : context.cursor) === null || _a === void 0 ? void 0 : _a.region) || 0 }, + onDemand: true, + }); + }); + HandshakingState.on(unsubscribeAll.type, (_) => UnsubscribedState.with()); + + /** + * Stopped initial subscription handshake (disconnected) state. + * + * @internal + */ + /** + * Stopped initial subscription handshake (disconnected) state. + * + * State in which Subscription Event Engine still has information about subscription but doesn't have subscription + * cursor for next sequential subscribe REST API call. + * + * @internal + */ + HandshakeStoppedState.on(subscriptionChange.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakeStoppedState.with({ channels: payload.channels, groups: payload.groups, cursor: context.cursor }); + }); + HandshakeStoppedState.on(reconnect.type, (context, { payload }) => HandshakingState.with(Object.assign(Object.assign({}, context), { cursor: payload.cursor || context.cursor, onDemand: true }))); + HandshakeStoppedState.on(restore.type, (context, { payload }) => { + var _a; + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakeStoppedState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || ((_a = context.cursor) === null || _a === void 0 ? void 0 : _a.region) || 0 }, + }); + }); + HandshakeStoppedState.on(unsubscribeAll.type, (_) => UnsubscribedState.with()); + + /** + * Failed initial subscription handshake (disconnected) state. + * + * @internal + */ + /** + * Failed initial subscription handshake (disconnected) state. + * + * State in which Subscription Event Engine waits for user to try to reconnect after all retry attempts has been + * exhausted. + * + * @internal + */ + HandshakeFailedState.on(subscriptionChange.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: context.cursor, + onDemand: true, + }); + }); + HandshakeFailedState.on(reconnect.type, (context, { payload }) => HandshakingState.with(Object.assign(Object.assign({}, context), { cursor: payload.cursor || context.cursor, onDemand: true }))); + HandshakeFailedState.on(restore.type, (context, { payload }) => { + var _a, _b; + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { + timetoken: `${payload.cursor.timetoken}`, + region: payload.cursor.region ? payload.cursor.region : ((_b = (_a = context === null || context === void 0 ? void 0 : context.cursor) === null || _a === void 0 ? void 0 : _a.region) !== null && _b !== void 0 ? _b : 0), + }, + onDemand: true, + }); + }); + HandshakeFailedState.on(unsubscribeAll.type, (_) => UnsubscribedState.with()); + + /** + * Receiving real-time updates (connected) state module. + * + * @internal + */ + /** + * Receiving real-time updates (connected) state. + * + * State in which Subscription Event Engine processes any real-time updates. + * + * @internal + */ + ReceivingState.onEnter((context) => { var _a; return receiveMessages(context.channels, context.groups, context.cursor, (_a = context.onDemand) !== null && _a !== void 0 ? _a : false); }); + ReceivingState.onExit(() => receiveMessages.cancel); + ReceivingState.on(receiveSuccess.type, (context, { payload }) => ReceivingState.with({ + channels: context.channels, + groups: context.groups, + cursor: payload.cursor, + referenceTimetoken: referenceSubscribeTimetoken(payload.cursor.timetoken), + }, [emitMessages(context.cursor, payload.events)])); + ReceivingState.on(subscriptionChange.type, (context, { payload }) => { + var _a; + if (payload.channels.length === 0 && payload.groups.length === 0) { + let errorCategory; + if (payload.isOffline) + errorCategory = (_a = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation).status) === null || _a === void 0 ? void 0 : _a.category; + return UnsubscribedState.with(undefined, [ + emitStatus(Object.assign({ category: !payload.isOffline + ? StatusCategory$1.PNDisconnectedCategory + : StatusCategory$1.PNDisconnectedUnexpectedlyCategory, operation: RequestOperation$1.PNUnsubscribeOperation }, (errorCategory ? { error: errorCategory } : {}))), + ]); + } + return ReceivingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: context.cursor, + referenceTimetoken: context.referenceTimetoken, + onDemand: true, + }, [ + emitStatus({ + category: StatusCategory$1.PNSubscriptionChangedCategory, + affectedChannels: payload.channels.slice(0), + affectedChannelGroups: payload.groups.slice(0), + currentTimetoken: context.cursor.timetoken, + }), + ]); + }); + ReceivingState.on(restore.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined, [emitStatus({ category: StatusCategory$1.PNDisconnectedCategory })]); + return ReceivingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || context.cursor.region }, + referenceTimetoken: referenceSubscribeTimetoken(context.cursor.timetoken, `${payload.cursor.timetoken}`, context.referenceTimetoken), + onDemand: true, + }, [ + emitStatus({ + category: StatusCategory$1.PNSubscriptionChangedCategory, + affectedChannels: payload.channels.slice(0), + affectedChannelGroups: payload.groups.slice(0), + currentTimetoken: payload.cursor.timetoken, + }), + ]); + }); + ReceivingState.on(receiveFailure.type, (context, { payload }) => { + var _a; + return ReceiveFailedState.with(Object.assign(Object.assign({}, context), { reason: payload }), [ + emitStatus({ category: StatusCategory$1.PNDisconnectedUnexpectedlyCategory, error: (_a = payload.status) === null || _a === void 0 ? void 0 : _a.category }), + ]); + }); + ReceivingState.on(disconnect.type, (context, event) => { + var _a; + if (!event.payload.isOffline) { + return ReceiveStoppedState.with(Object.assign({}, context), [ + emitStatus({ + category: StatusCategory$1.PNDisconnectedCategory, + operation: RequestOperation$1.PNSubscribeOperation, + }), + ]); + } + else { + const errorReason = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation); + return ReceiveFailedState.with(Object.assign(Object.assign({}, context), { reason: errorReason }), [ + emitStatus({ + category: StatusCategory$1.PNDisconnectedUnexpectedlyCategory, + operation: RequestOperation$1.PNSubscribeOperation, + error: (_a = errorReason.status) === null || _a === void 0 ? void 0 : _a.category, + }), + ]); + } + }); + ReceivingState.on(unsubscribeAll.type, (_) => UnsubscribedState.with(undefined, [ + emitStatus({ + category: StatusCategory$1.PNDisconnectedCategory, + operation: RequestOperation$1.PNUnsubscribeOperation, + }), + ])); + + /** + * Stopped real-time updates (disconnected) state module. + * + * @internal + */ + /** + * Stopped real-time updates (disconnected) state. + * + * State in which Subscription Event Engine still has information about subscription but doesn't process real-time + * updates. + * + * @internal + */ + ReceiveStoppedState.on(subscriptionChange.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return ReceiveStoppedState.with({ channels: payload.channels, groups: payload.groups, cursor: context.cursor }); + }); + ReceiveStoppedState.on(restore.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return ReceiveStoppedState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || context.cursor.region }, + }); + }); + ReceiveStoppedState.on(reconnect.type, (context, { payload }) => { + var _a; + return HandshakingState.with({ + channels: context.channels, + groups: context.groups, + cursor: { + timetoken: !!payload.cursor.timetoken ? (_a = payload.cursor) === null || _a === void 0 ? void 0 : _a.timetoken : context.cursor.timetoken, + region: payload.cursor.region || context.cursor.region, + }, + onDemand: true, + }); + }); + ReceiveStoppedState.on(unsubscribeAll.type, () => UnsubscribedState.with(undefined)); + + /** + * Failed to receive real-time updates (disconnected) state. + * + * @internal + */ + /** + * Failed to receive real-time updates (disconnected) state. + * + * State in which Subscription Event Engine waits for user to try to reconnect after all retry attempts has been + * exhausted. + * + * @internal + */ + ReceiveFailedState.on(reconnect.type, (context, { payload }) => { + var _a; + return HandshakingState.with({ + channels: context.channels, + groups: context.groups, + cursor: { + timetoken: !!payload.cursor.timetoken ? (_a = payload.cursor) === null || _a === void 0 ? void 0 : _a.timetoken : context.cursor.timetoken, + region: payload.cursor.region || context.cursor.region, + }, + onDemand: true, + }); + }); + ReceiveFailedState.on(subscriptionChange.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: context.cursor, + onDemand: true, + }); + }); + ReceiveFailedState.on(restore.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || context.cursor.region }, + onDemand: true, + }); + }); + ReceiveFailedState.on(unsubscribeAll.type, (_) => UnsubscribedState.with(undefined)); + + /** + * Subscribe Event Engine effects dispatcher. + * + * @internal + */ + /** + * Subscribe Event Engine dispatcher. + * + * Dispatcher responsible for subscription events handling and corresponding effects execution. + * + * @internal + */ + class EventEngineDispatcher extends Dispatcher { + constructor(engine, dependencies) { + super(dependencies, dependencies.config.logger()); + this.on(handshake.type, asyncHandler((payload_1, abortSignal_1, _a) => __awaiter(this, [payload_1, abortSignal_1, _a], void 0, function* (payload, abortSignal, { handshake, presenceState, config }) { + abortSignal.throwIfAborted(); + try { + const result = yield handshake(Object.assign(Object.assign({ abortSignal: abortSignal, channels: payload.channels, channelGroups: payload.groups, filterExpression: config.filterExpression }, (config.maintainPresenceState && { state: presenceState })), { onDemand: payload.onDemand })); + return engine.transition(handshakeSuccess(result)); + } + catch (e) { + if (e instanceof PubNubError) { + if (e.status && e.status.category == StatusCategory$1.PNCancelledCategory) + return; + return engine.transition(handshakeFailure(e)); + } + } + }))); + this.on(receiveMessages.type, asyncHandler((payload_1, abortSignal_1, _a) => __awaiter(this, [payload_1, abortSignal_1, _a], void 0, function* (payload, abortSignal, { receiveMessages, config }) { + abortSignal.throwIfAborted(); + try { + const result = yield receiveMessages({ + abortSignal: abortSignal, + channels: payload.channels, + channelGroups: payload.groups, + timetoken: payload.cursor.timetoken, + region: payload.cursor.region, + filterExpression: config.filterExpression, + onDemand: payload.onDemand, + }); + engine.transition(receiveSuccess(result.cursor, result.messages)); + } + catch (error) { + if (error instanceof PubNubError) { + if (error.status && error.status.category == StatusCategory$1.PNCancelledCategory) + return; + if (!abortSignal.aborted) + return engine.transition(receiveFailure(error)); + } + } + }))); + this.on(emitMessages.type, asyncHandler((_a, _1, _b) => __awaiter(this, [_a, _1, _b], void 0, function* ({ cursor, events }, _, { emitMessages }) { + if (events.length > 0) + emitMessages(cursor, events); + }))); + this.on(emitStatus.type, asyncHandler((payload_1, _1, _a) => __awaiter(this, [payload_1, _1, _a], void 0, function* (payload, _, { emitStatus }) { return emitStatus(payload); }))); + } + } + + /** + * Subscribe Event Engine module. + * + * @internal + */ + /** + * Subscribe Event Engine Core. + * + * @internal + */ + class EventEngine { + get _engine() { + return this.engine; + } + constructor(dependencies) { + this.channels = []; + this.groups = []; + this.dependencies = dependencies; + this.engine = new Engine(dependencies.config.logger()); + this.dispatcher = new EventEngineDispatcher(this.engine, dependencies); + dependencies.config.logger().debug('EventEngine', 'Create subscribe event engine.'); + this._unsubscribeEngine = this.engine.subscribe((change) => { + if (change.type === 'invocationDispatched') { + this.dispatcher.dispatch(change.invocation); + } + }); + this.engine.start(UnsubscribedState, undefined); + } + /** + * Subscription-based current timetoken. + * + * @returns Timetoken based on current timetoken plus diff between current and loop start time. + */ + get subscriptionTimetoken() { + const currentState = this.engine.currentState; + if (!currentState) + return undefined; + let referenceTimetoken; + let currentTimetoken = '0'; + if (currentState.label === ReceivingState.label) { + const context = this.engine.currentContext; + currentTimetoken = context.cursor.timetoken; + referenceTimetoken = context.referenceTimetoken; + } + return subscriptionTimetokenFromReference(currentTimetoken, referenceTimetoken !== null && referenceTimetoken !== void 0 ? referenceTimetoken : '0'); + } + subscribe({ channels, channelGroups, timetoken, withPresence, }) { + var _a; + // check if the channels and groups are already subscribed + const hasNewChannels = channels === null || channels === void 0 ? void 0 : channels.some((channel) => !this.channels.includes(channel)); + const hasNewGroups = channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.some((group) => !this.groups.includes(group)); + const hasNewSubscriptions = hasNewChannels || hasNewGroups; + this.channels = [...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])]; + this.groups = [...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])]; + if (withPresence) { + this.channels.map((c) => this.channels.push(`${c}-pnpres`)); + this.groups.map((g) => this.groups.push(`${g}-pnpres`)); + } + if (timetoken) { + this.engine.transition(restore(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])])), timetoken)); + } + else { + if (hasNewSubscriptions) { + this.engine.transition(subscriptionChange(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])])))); + } + else { + this.dependencies.config + .logger() + .debug('EventEngine', 'Skipping state transition - all channels/groups already subscribed. Emitting SubscriptionChanged event.'); + // Get current timetoken from state context + const currentState = this.engine.currentState; + const currentContext = this.engine.currentContext; + let currentTimetoken = '0'; + if ((currentState === null || currentState === void 0 ? void 0 : currentState.label) === ReceivingState.label && currentContext) { + const receivingContext = currentContext; + currentTimetoken = (_a = receivingContext.cursor) === null || _a === void 0 ? void 0 : _a.timetoken; + } + // Manually emit SubscriptionChanged status event + this.dependencies.emitStatus({ + category: StatusCategory$1.PNSubscriptionChangedCategory, + affectedChannels: Array.from(new Set(this.channels)), + affectedChannelGroups: Array.from(new Set(this.groups)), + currentTimetoken, + }); + } + } + if (this.dependencies.join) { + this.dependencies.join({ + channels: Array.from(new Set(this.channels.filter((c) => !c.endsWith('-pnpres')))), + groups: Array.from(new Set(this.groups.filter((g) => !g.endsWith('-pnpres')))), + }); + } + } + unsubscribe({ channels = [], channelGroups = [] }) { + const filteredChannels = removeSingleOccurrence(this.channels, [ + ...channels, + ...channels.map((c) => `${c}-pnpres`), + ]); + const filteredGroups = removeSingleOccurrence(this.groups, [ + ...channelGroups, + ...channelGroups.map((c) => `${c}-pnpres`), + ]); + if (new Set(this.channels).size !== new Set(filteredChannels).size || + new Set(this.groups).size !== new Set(filteredGroups).size) { + const channelsToLeave = findUniqueCommonElements(this.channels, channels); + const groupsToLeave = findUniqueCommonElements(this.groups, channelGroups); + if (this.dependencies.presenceState) { + channelsToLeave === null || channelsToLeave === void 0 ? void 0 : channelsToLeave.forEach((c) => delete this.dependencies.presenceState[c]); + groupsToLeave === null || groupsToLeave === void 0 ? void 0 : groupsToLeave.forEach((g) => delete this.dependencies.presenceState[g]); + } + this.channels = filteredChannels; + this.groups = filteredGroups; + this.engine.transition(subscriptionChange(Array.from(new Set(this.channels.slice(0))), Array.from(new Set(this.groups.slice(0))))); + if (this.dependencies.leave) { + this.dependencies.leave({ + channels: channelsToLeave.slice(0), + groups: groupsToLeave.slice(0), + }); + } + } + } + unsubscribeAll(isOffline = false) { + const channelGroups = this.getSubscribedChannelGroups(); + const channels = this.getSubscribedChannels(); + this.channels = []; + this.groups = []; + if (this.dependencies.presenceState) { + Object.keys(this.dependencies.presenceState).forEach((objectName) => { + delete this.dependencies.presenceState[objectName]; + }); + } + this.engine.transition(subscriptionChange(this.channels.slice(0), this.groups.slice(0), isOffline)); + if (this.dependencies.leaveAll) + this.dependencies.leaveAll({ channels, groups: channelGroups, isOffline }); + } + reconnect({ timetoken, region }) { + const channelGroups = this.getSubscribedChannels(); + const channels = this.getSubscribedChannels(); + this.engine.transition(reconnect(timetoken, region)); + if (this.dependencies.presenceReconnect) + this.dependencies.presenceReconnect({ channels, groups: channelGroups }); + } + disconnect(isOffline = false) { + const channelGroups = this.getSubscribedChannels(); + const channels = this.getSubscribedChannels(); + this.engine.transition(disconnect(isOffline)); + if (this.dependencies.presenceDisconnect) + this.dependencies.presenceDisconnect({ channels, groups: channelGroups, isOffline }); + } + getSubscribedChannels() { + return Array.from(new Set(this.channels.slice(0))); + } + getSubscribedChannelGroups() { + return Array.from(new Set(this.groups.slice(0))); + } + dispose() { + this.disconnect(true); + this._unsubscribeEngine(); + this.dispatcher.dispose(); + } + } + + /** + * Publish REST API module. + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether data is published used `POST` body or not. + */ + const SEND_BY_POST = false; + // endregion + /** + * Data publish request. + * + * Request will normalize and encrypt (if required) provided data and push it to the specified + * channel. + * + * @internal + */ + class PublishRequest extends AbstractRequest { + /** + * Construct data publish request. + * + * @param parameters - Request configuration. + */ + constructor(parameters) { + var _a; + const sendByPost = (_a = parameters.sendByPost) !== null && _a !== void 0 ? _a : SEND_BY_POST; + super({ method: sendByPost ? TransportMethod.POST : TransportMethod.GET, compressible: sendByPost }); + this.parameters = parameters; + // Apply default request parameters. + this.parameters.sendByPost = sendByPost; + } + operation() { + return RequestOperation$1.PNPublishOperation; + } + validate() { + const { message, channel, keySet: { publishKey }, } = this.parameters; + if (!channel) + return "Missing 'channel'"; + if (!message) + return "Missing 'message'"; + if (!publishKey) + return "Missing 'publishKey'"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { timetoken: this.deserializeResponse(response)[2] }; + }); + } + get path() { + const { message, channel, keySet } = this.parameters; + const stringifiedPayload = this.prepareMessagePayload(message); + return `/publish/${keySet.publishKey}/${keySet.subscribeKey}/0/${encodeString(channel)}/0${!this.parameters.sendByPost ? `/${encodeString(stringifiedPayload)}` : ''}`; + } + get queryParameters() { + const { customMessageType, meta, replicate, storeInHistory, ttl } = this.parameters; + const query = {}; + if (customMessageType) + query.custom_message_type = customMessageType; + if (storeInHistory !== undefined) + query.store = storeInHistory ? '1' : '0'; + if (ttl !== undefined) + query.ttl = ttl; + if (replicate !== undefined && !replicate) + query.norep = 'true'; + if (meta && typeof meta === 'object') + query.meta = JSON.stringify(meta); + return query; + } + get headers() { + var _a; + if (!this.parameters.sendByPost) + return super.headers; + return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); + } + get body() { + return this.prepareMessagePayload(this.parameters.message); + } + /** + * Pre-process provided data. + * + * Data will be "normalized" and encrypted if `cryptoModule` has been provided. + * + * @param payload - User-provided data which should be pre-processed before use. + * + * @returns Payload which can be used as part of request URL or body. + * + * @throws {Error} in case if provided `payload` or results of `encryption` can't be stringified. + */ + prepareMessagePayload(payload) { + const { crypto } = this.parameters; + if (!crypto) + return JSON.stringify(payload) || ''; + const encrypted = crypto.encrypt(JSON.stringify(payload)); + return JSON.stringify(typeof encrypted === 'string' ? encrypted : encode(encrypted)); + } + } + + /** + * Signal REST API module. + */ + // endregion + /** + * Signal data (size-limited) publish request. + * + * @internal + */ + class SignalRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSignalOperation; + } + validate() { + const { message, channel, keySet: { publishKey }, } = this.parameters; + if (!channel) + return "Missing 'channel'"; + if (!message) + return "Missing 'message'"; + if (!publishKey) + return "Missing 'publishKey'"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { timetoken: this.deserializeResponse(response)[2] }; + }); + } + get path() { + const { keySet: { publishKey, subscribeKey }, channel, message, } = this.parameters; + const stringifiedPayload = JSON.stringify(message); + return `/signal/${publishKey}/${subscribeKey}/0/${encodeString(channel)}/0/${encodeString(stringifiedPayload)}`; + } + get queryParameters() { + const { customMessageType } = this.parameters; + const query = {}; + if (customMessageType) + query.custom_message_type = customMessageType; + return query; + } + } + + /** + * Receive messages subscribe REST API module. + * + * @internal + */ + /** + * Receive messages subscribe request. + * + * @internal + */ + class ReceiveMessagesSubscribeRequest extends BaseSubscribeRequest { + operation() { + return RequestOperation$1.PNReceiveMessagesOperation; + } + validate() { + const validationResult = super.validate(); + if (validationResult) + return validationResult; + if (!this.parameters.timetoken) + return 'timetoken can not be empty'; + if (!this.parameters.region) + return 'region can not be empty'; + } + get path() { + const { keySet: { subscribeKey }, channels = [], } = this.parameters; + return `/v2/subscribe/${subscribeKey}/${encodeNames(channels.sort(), ',')}/0`; + } + get queryParameters() { + const { channelGroups, filterExpression, timetoken, region, heartbeat, onDemand } = this + .parameters; + const query = { ee: '' }; + if (onDemand) + query['on-demand'] = 1; + if (channelGroups && channelGroups.length > 0) + query['channel-group'] = channelGroups.sort().join(','); + if (filterExpression && filterExpression.length > 0) + query['filter-expr'] = filterExpression; + if (typeof timetoken === 'string') { + if (timetoken && timetoken !== '0' && timetoken.length > 0) + query['tt'] = timetoken; + } + else if (timetoken && timetoken > 0) + query['tt'] = timetoken; + if (region) + query['tr'] = region; + if (heartbeat) + query.heartbeat = heartbeat; + return query; + } + } + + /** + * Handshake subscribe REST API module. + * + * @internal + */ + /** + * Handshake subscribe request. + * + * Separate subscribe request required by Event Engine. + * + * @internal + */ + class HandshakeSubscribeRequest extends BaseSubscribeRequest { + operation() { + return RequestOperation$1.PNHandshakeOperation; + } + get path() { + const { keySet: { subscribeKey }, channels = [], } = this.parameters; + return `/v2/subscribe/${subscribeKey}/${encodeNames(channels.sort(), ',')}/0`; + } + get queryParameters() { + const { channelGroups, heartbeat, filterExpression, state, onDemand } = this + .parameters; + const query = { ee: '' }; + if (onDemand) + query['on-demand'] = 1; + if (channelGroups && channelGroups.length > 0) + query['channel-group'] = channelGroups.sort().join(','); + if (filterExpression && filterExpression.length > 0) + query['filter-expr'] = filterExpression; + if (state && Object.keys(state).length > 0) + query['state'] = JSON.stringify(state); + if (heartbeat) + query.heartbeat = heartbeat; + return query; + } + } + + /** + * SubscriptionCapable entity type. + * + * @internal + */ + var SubscriptionType; + (function (SubscriptionType) { + /** + * Channel identifier, which is part of the URI path. + */ + SubscriptionType[SubscriptionType["Channel"] = 0] = "Channel"; + /** + * Channel group identifiers, which is part of the query parameters. + */ + SubscriptionType[SubscriptionType["ChannelGroup"] = 1] = "ChannelGroup"; + })(SubscriptionType || (SubscriptionType = {})); + + /** + * User-provided channels and groups for subscription. + * + * Object contains information about channels and groups for which real-time updates should be retrieved from the + * PubNub network. + * + * @internal + */ + class SubscriptionInput { + /** + * Create a subscription input object. + * + * @param channels - List of channels which will be used with subscribe REST API to receive real-time updates. + * @param channelGroups - List of channel groups which will be used with subscribe REST API to receive real-time + * updates. + */ + constructor({ channels, channelGroups }) { + /** + * Whether the user input is empty or not. + */ + this.isEmpty = true; + this._channelGroups = new Set((channelGroups !== null && channelGroups !== void 0 ? channelGroups : []).filter((value) => value.length > 0)); + this._channels = new Set((channels !== null && channels !== void 0 ? channels : []).filter((value) => value.length > 0)); + this.isEmpty = this._channels.size === 0 && this._channelGroups.size === 0; + } + /** + * Retrieve total length of subscription input. + * + * @returns Number of channels and groups in subscription input. + */ + get length() { + if (this.isEmpty) + return 0; + return this._channels.size + this._channelGroups.size; + } + /** + * Retrieve a list of user-provided channel names. + * + * @returns List of user-provided channel names. + */ + get channels() { + if (this.isEmpty) + return []; + return Array.from(this._channels); + } + /** + * Retrieve a list of user-provided channel group names. + * + * @returns List of user-provided channel group names. + */ + get channelGroups() { + if (this.isEmpty) + return []; + return Array.from(this._channelGroups); + } + /** + * Check if the given name is contained in the channel or channel group. + * + * @param name - Containing the name to be checked. + * + * @returns `true` if the name is found in the channel or channel group, `false` otherwise. + */ + contains(name) { + if (this.isEmpty) + return false; + return this._channels.has(name) || this._channelGroups.has(name); + } + /** + * Create a new subscription input which will contain all channels and channel groups from both inputs. + * + * @param input - Another subscription input that should be used to aggregate data in new instance. + * + * @returns New subscription input instance with combined channels and channel groups. + */ + with(input) { + return new SubscriptionInput({ + channels: [...this._channels, ...input._channels], + channelGroups: [...this._channelGroups, ...input._channelGroups], + }); + } + /** + * Create a new subscription input which will contain only channels and groups which not present in the input. + * + * @param input - Another subscription input which should be used to filter data in new instance. + * + * @returns New subscription input instance with filtered channels and channel groups. + */ + without(input) { + return new SubscriptionInput({ + channels: [...this._channels].filter((value) => !input._channels.has(value)), + channelGroups: [...this._channelGroups].filter((value) => !input._channelGroups.has(value)), + }); + } + /** + * Add data from another subscription input to the receiver. + * + * @param input - Another subscription input whose data should be added to the receiver. + * + * @returns Receiver instance with updated channels and channel groups. + */ + add(input) { + if (input._channelGroups.size > 0) + this._channelGroups = new Set([...this._channelGroups, ...input._channelGroups]); + if (input._channels.size > 0) + this._channels = new Set([...this._channels, ...input._channels]); + this.isEmpty = this._channels.size === 0 && this._channelGroups.size === 0; + return this; + } + /** + * Remove data from another subscription input from the receiver. + * + * @param input - Another subscription input whose data should be removed from the receiver. + * + * @returns Receiver instance with updated channels and channel groups. + */ + remove(input) { + if (input._channelGroups.size > 0) + this._channelGroups = new Set([...this._channelGroups].filter((value) => !input._channelGroups.has(value))); + if (input._channels.size > 0) + this._channels = new Set([...this._channels].filter((value) => !input._channels.has(value))); + return this; + } + /** + * Remove all data from subscription input. + * + * @returns Receiver instance with updated channels and channel groups. + */ + removeAll() { + this._channels.clear(); + this._channelGroups.clear(); + this.isEmpty = true; + return this; + } + /** + * Serialize a subscription input to string. + * + * @returns Printable string representation of a subscription input. + */ + toString() { + return `SubscriptionInput { channels: [${this.channels.join(', ')}], channelGroups: [${this.channelGroups.join(', ')}], is empty: ${this.isEmpty ? 'true' : 'false'}} }`; + } + } + // endregion + + /** + * Subscription state object. + * + * State object used across multiple subscription object clones. + * + * @internal + */ + class SubscriptionBaseState { + /** + * Create a base subscription state object. + * + * @param client - PubNub client which will work with a subscription object. + * @param subscriptionInput - User's input to be used with subscribe REST API. + * @param options - Subscription behavior options. + * @param referenceTimetoken - High-precision timetoken of the moment when subscription was created for entity. + */ + constructor(client, subscriptionInput, options, referenceTimetoken) { + /** + * Whether a subscribable object subscribed or not. + */ + this._isSubscribed = false; + /** + * The list of references to all {@link SubscriptionBase} clones created for this reference. + */ + this.clones = {}; + /** + * List of a parent subscription state objects list. + * + * List is used to track usage of a subscription object in other subscription object sets. + * + * **Important:** Tracking is required to prevent unexpected unsubscriptions if an object still has a parent. + */ + this.parents = []; + /** + * Unique subscription object identifier. + */ + this._id = uuidGenerator.createUUID(); + this.referenceTimetoken = referenceTimetoken; + this.subscriptionInput = subscriptionInput; + this.options = options; + this.client = client; + } + /** + * Get unique subscription object identifier. + * + * @returns Unique subscription object identifier. + */ + get id() { + return this._id; + } + /** + * Check whether a subscription object is the last clone or not. + * + * @returns `true` if a subscription object is the last clone. + */ + get isLastClone() { + return Object.keys(this.clones).length === 1; + } + /** + * Get whether a subscribable object subscribed or not. + * + * **Warning:** This method shouldn't be overridden by {@link SubscriptionSet}. + * + * @returns Whether a subscribable object subscribed or not. + */ + get isSubscribed() { + if (this._isSubscribed) + return true; + // Checking whether any of "parents" is subscribed. + return this.parents.length > 0 && this.parents.some((state) => state.isSubscribed); + } + /** + * Update active subscription state. + * + * @param value - New subscription state. + */ + set isSubscribed(value) { + if (this.isSubscribed === value) + return; + this._isSubscribed = value; + } + /** + * Add a parent subscription state object to mark the linkage. + * + * @param parent - Parent subscription state object. + * + * @internal + */ + addParentState(parent) { + if (!this.parents.includes(parent)) + this.parents.push(parent); + } + /** + * Remove a parent subscription state object. + * + * @param parent - Parent object for which linkage should be broken. + * + * @internal + */ + removeParentState(parent) { + const parentStateIndex = this.parents.indexOf(parent); + if (parentStateIndex !== -1) + this.parents.splice(parentStateIndex, 1); + } + /** + * Store a clone of a {@link SubscriptionBase} instance with a given instance ID. + * + * @param id - The instance ID to associate with clone. + * @param instance - Reference to the subscription instance to store as a clone. + */ + storeClone(id, instance) { + if (!this.clones[id]) + this.clones[id] = instance; + } + } + /** + * Base subscribe object. + * + * Implementation of base functionality used by {@link SubscriptionObject Subscription} and {@link SubscriptionSet}. + */ + class SubscriptionBase { + /** + * Create a subscription object from the state. + * + * @param state - Subscription state object. + * @param subscriptionType - Actual subscription object type. + * + * @internal + */ + constructor(state, subscriptionType = 'Subscription') { + this.subscriptionType = subscriptionType; + /** + * Unique subscription object identifier. + * + * @internal + */ + this.id = uuidGenerator.createUUID(); + /** + * Event emitter, which will notify listeners about updates received for channels / groups. + * + * @internal + */ + this.eventDispatcher = new EventDispatcher(); + this._state = state; + } + /** + * Subscription state. + * + * @returns Subscription state object. + * + * @internal + */ + get state() { + return this._state; + } + /** + * Get a list of channels which is used for subscription. + * + * @returns List of channel names. + */ + get channels() { + return this.state.subscriptionInput.channels.slice(0); + } + /** + * Get a list of channel groups which is used for subscription. + * + * @returns List of channel group names. + */ + get channelGroups() { + return this.state.subscriptionInput.channelGroups.slice(0); + } + // -------------------------------------------------------- + // -------------------- Event emitter --------------------- + // -------------------------------------------------------- + // region Event emitter + /** + * Set a new message handler. + * + * @param listener - Listener function, which will be called each time when a new message + * is received from the real-time network. + */ + set onMessage(listener) { + this.eventDispatcher.onMessage = listener; + } + /** + * Set a new presence events handler. + * + * @param listener - Listener function, which will be called each time when a new + * presence event is received from the real-time network. + */ + set onPresence(listener) { + this.eventDispatcher.onPresence = listener; + } + /** + * Set a new signal handler. + * + * @param listener - Listener function, which will be called each time when a new signal + * is received from the real-time network. + */ + set onSignal(listener) { + this.eventDispatcher.onSignal = listener; + } + /** + * Set a new app context event handler. + * + * @param listener - Listener function, which will be called each time when a new + * app context event is received from the real-time network. + */ + set onObjects(listener) { + this.eventDispatcher.onObjects = listener; + } + /** + * Set a new message reaction event handler. + * + * @param listener - Listener function, which will be called each time when a + * new message reaction event is received from the real-time network. + */ + set onMessageAction(listener) { + this.eventDispatcher.onMessageAction = listener; + } + /** + * Set a new file handler. + * + * @param listener - Listener function, which will be called each time when a new file + * is received from the real-time network. + */ + set onFile(listener) { + this.eventDispatcher.onFile = listener; + } + /** + * Set a new DataSync event handler. + * + * @param listener - Listener function, which will be called each time when a new + * DataSync event is received from the real-time network. + */ + set onDataSync(listener) { + this.eventDispatcher.onDataSync = listener; + } + /** + * Set events handler. + * + * @param listener - Events listener configuration object, which lets specify handlers for multiple + * types of events. + */ + addListener(listener) { + this.eventDispatcher.addListener(listener); + } + /** + * Remove events handler. + * + * @param listener - Event listener configuration, which should be removed from the list of notified + * listeners. **Important:** Should be the same object which has been passed to the {@link addListener}. + */ + removeListener(listener) { + this.eventDispatcher.removeListener(listener); + } + /** + * Remove all events listeners. + */ + removeAllListeners() { + this.eventDispatcher.removeAllListeners(); + } + /** + * Dispatch received a real-time update. + * + * @param cursor - A time cursor for the next portion of events. + * @param event - A real-time event from multiplexed subscription. + * + * @return `true` if receiver has consumed event. + * + * @internal + */ + handleEvent(cursor, event) { + var _a; + if (!this.state.cursor || cursor > this.state.cursor) + this.state.cursor = cursor; + // Check whether this is an old `old` event and it should be ignored or not. + if (this.state.referenceTimetoken && event.data.timetoken < this.state.referenceTimetoken) { + this.state.client.logger.trace(this.subscriptionType, () => ({ + messageType: 'text', + message: `Event timetoken (${event.data.timetoken}) is older than reference timetoken (${this.state.referenceTimetoken}) for ${this.id} subscription object. Ignoring event.`, + })); + return; + } + // Don't pass events which are filtered out by the user-provided function. + if (((_a = this.state.options) === null || _a === void 0 ? void 0 : _a.filter) && !this.state.options.filter(event)) { + this.state.client.logger.trace(this.subscriptionType, `Event filtered out by filter function for ${this.id} subscription object. Ignoring event.`); + return; + } + const clones = Object.values(this.state.clones); + if (clones.length > 0) { + this.state.client.logger.trace(this.subscriptionType, `Notify ${this.id} subscription object clones (count: ${clones.length}) about received event.`); + } + clones.forEach((subscription) => subscription.eventDispatcher.handleEvent(event)); + } + /** + * Graceful object destruction. + * + * This is an instance destructor, which will properly deinitialize it: + * - remove and unset all listeners, + * - try to unsubscribe (if subscribed and there are no more instances interested in the same data stream). + * + * **Important:** {@link SubscriptionBase#dispose dispose} won't have any effect if a subscription object is part of + * set. To gracefully dispose an object, it should be removed from the set using + * {@link SubscriptionSet#removeSubscription removeSubscription} (in this case call of + * {@link SubscriptionBase#dispose dispose} not required. + * + * **Note:** Disposed instance won't call the dispatcher to deliver updates to the listeners. + */ + dispose() { + const keys = Object.keys(this.state.clones); + if (keys.length > 1) { + this.state.client.logger.debug(this.subscriptionType, `Remove subscription object clone on dispose: ${this.id}`); + delete this.state.clones[this.id]; + } + else if (keys.length === 1 && this.state.clones[this.id]) { + this.state.client.logger.debug(this.subscriptionType, `Unsubscribe subscription object on dispose: ${this.id}`); + this.unsubscribe(); + } + } + /** + * Invalidate subscription object. + * + * Clean up resources used by a subscription object. + * + * **Note:** An invalidated instance won't call the dispatcher to deliver updates to the listeners. + * + * @param forDestroy - Whether subscription object invalidated as part of PubNub client destroy process or not. + * + * @internal + */ + invalidate(forDestroy = false) { + this.state._isSubscribed = false; + if (forDestroy) { + delete this.state.clones[this.id]; + if (Object.keys(this.state.clones).length === 0) { + this.state.client.logger.trace(this.subscriptionType, 'Last clone removed. Reset shared subscription state.'); + this.state.subscriptionInput.removeAll(); + this.state.parents = []; + } + } + } + /** + * Start receiving real-time updates. + * + * @param parameters - Additional subscription configuration options which should be used + * for request. + */ + subscribe(parameters) { + if (this.state.isSubscribed) { + this.state.client.logger.trace(this.subscriptionType, 'Already subscribed. Ignoring subscribe request.'); + return; + } + this.state.client.logger.debug(this.subscriptionType, () => { + if (!parameters) + return { messageType: 'text', message: 'Subscribe' }; + return { messageType: 'object', message: parameters, details: 'Subscribe with parameters:' }; + }); + this.state.isSubscribed = true; + this.updateSubscription({ subscribing: true, timetoken: parameters === null || parameters === void 0 ? void 0 : parameters.timetoken }); + } + /** + * Stop real-time events processing. + * + * **Important:** {@link SubscriptionBase#unsubscribe unsubscribe} won't have any effect if a subscription object + * is part of active (subscribed) set. To unsubscribe an object, it should be removed from the set using + * {@link SubscriptionSet#removeSubscription removeSubscription} (in this case call of + * {@link SubscriptionBase#unsubscribe unsubscribe} not required. + * + * **Note:** Unsubscribed instance won't call the dispatcher to deliver updates to the listeners. + */ + unsubscribe() { + // Check whether an instance-level subscription flag not set or parent has active subscription. + if (!this.state._isSubscribed || this.state.isSubscribed) { + // Warn if a user tries to unsubscribe using specific subscription which subscribed as part of a subscription set. + if (!this.state._isSubscribed && this.state.parents.length > 0 && this.state.isSubscribed) { + this.state.client.logger.warn(this.subscriptionType, () => ({ + messageType: 'object', + details: 'Subscription is subscribed as part of a subscription set. Remove from active sets to unsubscribe:', + message: this.state.parents.filter((subscriptionSet) => subscriptionSet.isSubscribed), + })); + return; + } + else if (!this.state._isSubscribed) { + this.state.client.logger.trace(this.subscriptionType, 'Not subscribed. Ignoring unsubscribe request.'); + return; + } + } + this.state.client.logger.debug(this.subscriptionType, 'Unsubscribe'); + this.state.isSubscribed = false; + delete this.state.cursor; + this.updateSubscription({ subscribing: false }); + } + /** + * Update channels and groups used by subscription loop. + * + * @param parameters - Subscription loop update parameters. + * @param parameters.subscribing - Whether subscription updates as part of subscription or unsubscription. + * @param [parameters.timetoken] - Subscription catch-up timetoken. + * @param [parameters.subscriptions] - List of subscriptions which should be used to modify a subscription loop + * object. + * + * @internal + */ + updateSubscription(parameters) { + var _a, _b; + if (parameters === null || parameters === void 0 ? void 0 : parameters.timetoken) { + if (((_a = this.state.cursor) === null || _a === void 0 ? void 0 : _a.timetoken) && ((_b = this.state.cursor) === null || _b === void 0 ? void 0 : _b.timetoken) !== '0') { + if (parameters.timetoken !== '0' && parameters.timetoken > this.state.cursor.timetoken) + this.state.cursor.timetoken = parameters.timetoken; + } + else + this.state.cursor = { timetoken: parameters.timetoken }; + } + const subscriptions = parameters.subscriptions && parameters.subscriptions.length > 0 ? parameters.subscriptions : undefined; + if (parameters.subscribing) { + this.register(Object.assign(Object.assign({}, (parameters.timetoken ? { cursor: this.state.cursor } : {})), (subscriptions ? { subscriptions } : {}))); + } + else + this.unregister(subscriptions); + } + } + + /** + * {@link SubscriptionSet} state object. + * + * State object used across multiple {@link SubscriptionSet} object clones. + * + * @internal + */ + class SubscriptionSetState extends SubscriptionBaseState { + /** + * Create a subscription state object. + * + * @param parameters - State configuration options + * @param parameters.client - PubNub client which will work with a subscription object. + * @param parameters.subscriptions - List of subscriptions managed by set. + * @param [parameters.options] - Subscription behavior options. + */ + constructor(parameters) { + const subscriptionInput = new SubscriptionInput({}); + parameters.subscriptions.forEach((subscription) => subscriptionInput.add(subscription.state.subscriptionInput)); + super(parameters.client, subscriptionInput, parameters.options, parameters.client.subscriptionTimetoken); + this.subscriptions = parameters.subscriptions; + } + /** + * Add a single subscription object to the set. + * + * @param subscription - Another entity's subscription object, which should be added. + */ + addSubscription(subscription) { + if (this.subscriptions.includes(subscription)) + return; + subscription.state.addParentState(this); + this.subscriptions.push(subscription); + // Update subscription input. + this.subscriptionInput.add(subscription.state.subscriptionInput); + } + /** + * Remove a single subscription object from the set. + * + * @param subscription - Another entity's subscription object, which should be removed. + * @param clone - Whether a target subscription is a clone. + */ + removeSubscription(subscription, clone) { + const index = this.subscriptions.indexOf(subscription); + if (index === -1) + return; + this.subscriptions.splice(index, 1); + if (!clone) + subscription.state.removeParentState(this); + // Update subscription input. + this.subscriptionInput.remove(subscription.state.subscriptionInput); + } + /** + * Remove any registered subscription object. + */ + removeAllSubscriptions() { + this.subscriptions.forEach((subscription) => subscription.state.removeParentState(this)); + this.subscriptions.splice(0, this.subscriptions.length); + this.subscriptionInput.removeAll(); + } + } + /** + * Multiple entities subscription set object which can be used to receive and handle real-time + * updates. + * + * Subscription set object represents a collection of per-entity subscription objects and allows + * processing them at once for subscription loop and events handling. + */ + class SubscriptionSet extends SubscriptionBase { + /** + * Create entities' subscription set object. + * + * Subscription set object represents a collection of per-entity subscription objects and allows + * processing them at once for subscription loop and events handling. + * + * @param parameters - Subscription set object configuration. + * + * @returns Ready to use entities' subscription set object. + * + * @internal + */ + constructor(parameters) { + let state; + if ('client' in parameters) { + let subscriptions = []; + if (!parameters.subscriptions && parameters.entities) { + parameters.entities.forEach((entity) => subscriptions.push(entity.subscription(parameters.options))); + } + else if (parameters.subscriptions) + subscriptions = parameters.subscriptions; + state = new SubscriptionSetState({ client: parameters.client, subscriptions, options: parameters.options }); + subscriptions.forEach((subscription) => subscription.state.addParentState(state)); + state.client.logger.debug('SubscriptionSet', () => ({ + messageType: 'object', + details: 'Create subscription set with parameters:', + message: Object.assign({ subscriptions: state.subscriptions }, (parameters.options ? parameters.options : {})), + })); + } + else { + state = parameters.state; + state.client.logger.debug('SubscriptionSet', 'Create subscription set clone'); + } + super(state, 'SubscriptionSet'); + this.state.storeClone(this.id, this); + // Update a parent sets list for original set subscriptions. + state.subscriptions.forEach((subscription) => subscription.addParentSet(this)); + } + /** + * Get a {@link SubscriptionSet} object state. + * + * @returns: {@link SubscriptionSet} object state. + * + * @internal + */ + get state() { + return super.state; + } + /** + * Get a list of entities' subscription objects registered in a subscription set. + * + * @returns Entities' subscription objects list. + */ + get subscriptions() { + return this.state.subscriptions.slice(0); + } + // -------------------------------------------------------- + // -------------------- Event handler --------------------- + // -------------------------------------------------------- + // region Event handler + /** + * Dispatch received a real-time update. + * + * @param cursor - A time cursor for the next portion of events. + * @param event - A real-time event from multiplexed subscription. + * + * @return `true` if receiver has consumed event. + * + * @internal + */ + handleEvent(cursor, event) { + var _a; + // Check whether an event is not designated for this subscription set. + if (!this.state.subscriptionInput.contains((_a = event.data.subscription) !== null && _a !== void 0 ? _a : event.data.channel)) + return; + // Check whether `event` can be processed or not. + if (!this.state._isSubscribed) { + this.state.client.logger.trace(this.subscriptionType, `Subscription set ${this.id} is not subscribed. Ignoring event.`); + return; + } + super.handleEvent(cursor, event); + if (this.state.subscriptions.length > 0) { + this.state.client.logger.trace(this.subscriptionType, `Notify ${this.id} subscription set subscriptions (count: ${this.state.subscriptions.length}) about received event.`); + } + this.state.subscriptions.forEach((subscription) => subscription.handleEvent(cursor, event)); + } + // endregion + /** + User-provided subscription input associated with this {@link SubscriptionSet} object. + * + * @param forUnsubscribe - Whether list subscription input created for unsubscription (means entity should be free). + * + * @returns Subscription input object. + * + * @internal + */ + subscriptionInput(forUnsubscribe = false) { + let subscriptionInput = this.state.subscriptionInput; + this.state.subscriptions.forEach((subscription) => { + if (forUnsubscribe && subscription.state.entity.subscriptionsCount > 0) + subscriptionInput = subscriptionInput.without(subscription.state.subscriptionInput); + }); + return subscriptionInput; + } + /** + * Make a bare copy of the {@link SubscriptionSet} object. + * + * Copy won't have any type-specific listeners or added listener objects but will have the same internal state as + * the source object. + * + * @returns Bare copy of a {@link SubscriptionSet} object. + */ + cloneEmpty() { + return new SubscriptionSet({ state: this.state }); + } + /** + * Graceful {@link SubscriptionSet} destruction. + * + * This is an instance destructor, which will properly deinitialize it: + * - remove and unset all listeners, + * - try to unsubscribe (if subscribed and there are no more instances interested in the same data stream). + * + * **Note:** Disposed instance won't call the dispatcher to deliver updates to the listeners. + */ + dispose() { + const isLastClone = this.state.isLastClone; + this.state.subscriptions.forEach((subscription) => { + subscription.removeParentSet(this); + if (isLastClone) + subscription.state.removeParentState(this.state); + }); + super.dispose(); + } + /** + * Invalidate {@link SubscriptionSet} object. + * + * Clean up resources used by a subscription object. All {@link SubscriptionObject subscription} objects will be + * removed. + * + * **Important:** This method is used only when a global subscription set is used (backward compatibility). + * + * **Note:** An invalidated instance won't call the dispatcher to deliver updates to the listeners. + * + * @param forDestroy - Whether subscription object invalidated as part of PubNub client destroy process or not. + * + * @internal + */ + invalidate(forDestroy = false) { + const subscriptions = forDestroy ? this.state.subscriptions.slice(0) : this.state.subscriptions; + subscriptions.forEach((subscription) => { + if (forDestroy) { + subscription.state.entity.decreaseSubscriptionCount(this.state.id); + subscription.removeParentSet(this); + } + subscription.invalidate(forDestroy); + }); + if (forDestroy) + this.state.removeAllSubscriptions(); + super.invalidate(); + } + /** + * Add an entity's subscription to the subscription set. + * + * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. + * + * @param subscription - Another entity's subscription object, which should be added. + */ + addSubscription(subscription) { + this.addSubscriptions([subscription]); + } + /** + * Add an entity's subscriptions to the subscription set. + * + * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. + * + * @param subscriptions - List of entity's subscription objects, which should be added. + */ + addSubscriptions(subscriptions) { + const inactiveSubscriptions = []; + const activeSubscriptions = []; + this.state.client.logger.debug(this.subscriptionType, () => { + const ignoredSubscriptions = []; + const subscriptionsToAdd = []; + subscriptions.forEach((subscription) => { + if (!this.state.subscriptions.includes(subscription)) + subscriptionsToAdd.push(subscription); + else + ignoredSubscriptions.push(subscription); + }); + return { + messageType: 'object', + details: `Add subscriptions to ${this.id} (subscriptions count: ${this.state.subscriptions.length + subscriptionsToAdd.length}):`, + message: { addedSubscriptions: subscriptionsToAdd, ignoredSubscriptions }, + }; + }); + subscriptions + .filter((subscription) => !this.state.subscriptions.includes(subscription)) + .forEach((subscription) => { + if (subscription.state.isSubscribed) + activeSubscriptions.push(subscription); + else + inactiveSubscriptions.push(subscription); + subscription.addParentSet(this); + this.state.addSubscription(subscription); + }); + // Check whether there are any subscriptions for which the subscription loop should be changed or not. + if ((activeSubscriptions.length === 0 && inactiveSubscriptions.length === 0) || !this.state.isSubscribed) + return; + activeSubscriptions.forEach(({ state }) => state.entity.increaseSubscriptionCount(this.state.id)); + if (inactiveSubscriptions.length > 0) + this.updateSubscription({ subscribing: true, subscriptions: inactiveSubscriptions }); + } + /** + * Remove an entity's subscription object from the set. + * + * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. + * + * @param subscription - Another entity's subscription object, which should be removed. + */ + removeSubscription(subscription) { + this.removeSubscriptions([subscription]); + } + /** + * Remove an entity's subscription objects from the set. + * + * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. + * + * @param subscriptions - List entity's subscription objects, which should be removed. + */ + removeSubscriptions(subscriptions) { + const activeSubscriptions = []; + this.state.client.logger.debug(this.subscriptionType, () => { + const ignoredSubscriptions = []; + const subscriptionsToRemove = []; + subscriptions.forEach((subscription) => { + if (this.state.subscriptions.includes(subscription)) + subscriptionsToRemove.push(subscription); + else + ignoredSubscriptions.push(subscription); + }); + return { + messageType: 'object', + details: `Remove subscriptions from ${this.id} (subscriptions count: ${this.state.subscriptions.length}):`, + message: { removedSubscriptions: subscriptionsToRemove, ignoredSubscriptions }, + }; + }); + subscriptions + .filter((subscription) => this.state.subscriptions.includes(subscription)) + .forEach((subscription) => { + if (subscription.state.isSubscribed) + activeSubscriptions.push(subscription); + subscription.removeParentSet(this); + this.state.removeSubscription(subscription, subscription.parentSetsCount > 1); + }); + // Check whether there are any subscriptions for which the subscription loop should be changed or not. + if (activeSubscriptions.length === 0 || !this.state.isSubscribed) + return; + this.updateSubscription({ subscribing: false, subscriptions: activeSubscriptions }); + } + /** + * Merge with another {@link SubscriptionSet} object. + * + * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. + * + * @param subscriptionSet - Other entities' subscription set, which should be joined. + */ + addSubscriptionSet(subscriptionSet) { + this.addSubscriptions(subscriptionSet.subscriptions); + } + /** + * Subtract another {@link SubscriptionSet} object. + * + * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. + * + * @param subscriptionSet - Other entities' subscription set, which should be subtracted. + */ + removeSubscriptionSet(subscriptionSet) { + this.removeSubscriptions(subscriptionSet.subscriptions); + } + /** + * Register {@link SubscriptionSet} object for real-time events' retrieval. + * + * @param parameters - Object registration parameters. + * @param [parameters.cursor] - Subscription real-time events catch-up cursor. + * @param [parameters.subscriptions] - List of subscription objects which should be registered (in case of partial + * modification). + * + * @internal + */ + register(parameters) { + var _a; + const subscriptions = ((_a = parameters.subscriptions) !== null && _a !== void 0 ? _a : this.state.subscriptions); + subscriptions.forEach(({ state }) => state.entity.increaseSubscriptionCount(this.state.id)); + this.state.client.logger.trace(this.subscriptionType, () => ({ + messageType: 'text', + message: `Register subscription for real-time events: ${this}`, + })); + this.state.client.registerEventHandleCapable(this, parameters.cursor, subscriptions); + } + /** + * Unregister {@link SubscriptionSet} object from real-time events' retrieval. + * + * @param [subscriptions] - List of subscription objects which should be unregistered (in case of partial + * modification). + * + * @internal + */ + unregister(subscriptions) { + const activeSubscriptions = (subscriptions !== null && subscriptions !== void 0 ? subscriptions : this.state.subscriptions); + activeSubscriptions.forEach(({ state }) => state.entity.decreaseSubscriptionCount(this.state.id)); + this.state.client.logger.trace(this.subscriptionType, () => { + if (!subscriptions) { + return { + messageType: 'text', + message: `Unregister subscription from real-time events: ${this}`, + }; + } + else { + return { + messageType: 'object', + message: { + subscription: this, + subscriptions, + }, + details: 'Unregister subscriptions of subscription set from real-time events:', + }; + } + }); + this.state.client.unregisterEventHandleCapable(this, activeSubscriptions); + } + /** + * Stringify subscription object. + * + * @returns Serialized subscription object. + */ + toString() { + const state = this.state; + return `${this.subscriptionType} { id: ${this.id}, stateId: ${state.id}, clonesCount: ${Object.keys(this.state.clones).length}, isSubscribed: ${state.isSubscribed}, subscriptions: [${state.subscriptions + .map((sub) => sub.toString()) + .join(', ')}] }`; + } + } + + /** + * {@link Subscription} state object. + * + * State object used across multiple {@link Subscription} object clones. + * + * @internal + */ + class SubscriptionState extends SubscriptionBaseState { + /** + * Create a subscription state object. + * + * @param parameters - State configuration options + * @param parameters.client - PubNub client which will work with a subscription object. + * @param parameters.entity - Entity for which a subscription object has been created. + * @param [parameters.options] - Subscription behavior options. + */ + constructor(parameters) { + var _a, _b; + const names = parameters.entity.subscriptionNames((_b = (_a = parameters.options) === null || _a === void 0 ? void 0 : _a.receivePresenceEvents) !== null && _b !== void 0 ? _b : false); + const subscriptionInput = new SubscriptionInput({ + [parameters.entity.subscriptionType == SubscriptionType.Channel ? 'channels' : 'channelGroups']: names, + }); + super(parameters.client, subscriptionInput, parameters.options, parameters.client.subscriptionTimetoken); + this.entity = parameters.entity; + } + } + /** + * Single-entity subscription object which can be used to receive and handle real-time updates. + */ + class Subscription extends SubscriptionBase { + /** + * Create a subscribing capable object for entity. + * + * @param parameters - Subscription object configuration. + * + * @internal + */ + constructor(parameters) { + if ('client' in parameters) { + parameters.client.logger.debug('Subscription', () => ({ + messageType: 'object', + details: 'Create subscription with parameters:', + message: Object.assign({ entity: parameters.entity }, (parameters.options ? parameters.options : {})), + })); + } + else + parameters.state.client.logger.debug('Subscription', 'Create subscription clone'); + super('state' in parameters ? parameters.state : new SubscriptionState(parameters)); + /** + * List of subscription {@link SubscriptionSet sets} which contains {@link Subscription subscription}. + * + * List if used to track usage of a specific {@link Subscription subscription} in other subscription + * {@link SubscriptionSet sets}. + * + * **Important:** Tracking is required to prevent cloned instance dispose if there are sets that still use it. + * + * @internal + */ + this.parents = []; + /** + * List of fingerprints from updates which has been handled already. + * + * **Important:** Tracking is required to avoid repetitive call of the subscription object's listener when the object + * is part of multiple subscribed sets. Handler will be called once, and then the fingerprint will be stored in this + * list to avoid another listener call for it. + * + * @internal + */ + this.handledUpdates = []; + this.state.storeClone(this.id, this); + } + /** + * Get a {@link Subscription} object state. + * + * @returns: {@link Subscription} object state. + * + * @internal + */ + get state() { + return super.state; + } + /** + * Get number of {@link SubscriptionSet} which use this subscription object. + * + * @returns Number of {@link SubscriptionSet} which use this subscription object. + * + * @internal + */ + get parentSetsCount() { + return this.parents.length; + } + // -------------------------------------------------------- + // -------------------- Event handler --------------------- + // -------------------------------------------------------- + // region Event handler + /** + * Dispatch received a real-time update. + * + * @param cursor - A time cursor for the next portion of events. + * @param event - A real-time event from multiplexed subscription. + * + * @return `true` if receiver has consumed event. + * + * @internal + */ + handleEvent(cursor, event) { + var _a, _b; + if (!this.state.isSubscribed || + !this.state.subscriptionInput.contains((_a = event.data.subscription) !== null && _a !== void 0 ? _a : event.data.channel)) + return; + if (this.parentSetsCount > 0) { + // Creating from whole payload (not only for published messages). + const fingerprint = messageFingerprint(event.data); + if (this.handledUpdates.includes(fingerprint)) { + this.state.client.logger.trace(this.subscriptionType, `Event (${fingerprint}) already handled by ${this.id}. Ignoring.`); + return; + } + // Update a list of tracked messages and shrink it if too big. + this.handledUpdates.push(fingerprint); + if (this.handledUpdates.length > 10) + this.handledUpdates.shift(); + } + // Check whether an event is not designated for this subscription set. + if (!this.state.subscriptionInput.contains((_b = event.data.subscription) !== null && _b !== void 0 ? _b : event.data.channel)) + return; + super.handleEvent(cursor, event); + } + // endregion + /** + * User-provided subscription input associated with this {@link Subscription} object. + * + * @param forUnsubscribe - Whether list subscription input created for unsubscription (means entity should be free). + * + * @returns Subscription input object. + * + * @internal + */ + subscriptionInput(forUnsubscribe = false) { + if (forUnsubscribe && this.state.entity.subscriptionsCount > 0) + return new SubscriptionInput({}); + return this.state.subscriptionInput; + } + /** + * Make a bare copy of the {@link Subscription} object. + * + * Copy won't have any type-specific listeners or added listener objects but will have the same internal state as + * the source object. + * + * @returns Bare copy of a {@link Subscription} object. + */ + cloneEmpty() { + return new Subscription({ state: this.state }); + } + /** + * Graceful {@link Subscription} object destruction. + * + * This is an instance destructor, which will properly deinitialize it: + * - remove and unset all listeners, + * - try to unsubscribe (if subscribed and there are no more instances interested in the same data stream). + * + * **Important:** {@link Subscription#dispose dispose} won't have any effect if a subscription object is part of + * {@link SubscriptionSet set}. To gracefully dispose an object, it should be removed from the set using + * {@link SubscriptionSet#removeSubscription removeSubscription} (in this case call of + * {@link Subscription#dispose dispose} not required). + * + * **Note:** Disposed instance won't call the dispatcher to deliver updates to the listeners. + */ + dispose() { + if (this.parentSetsCount > 0) { + this.state.client.logger.debug(this.subscriptionType, () => ({ + messageType: 'text', + message: `'${this.state.entity.subscriptionNames()}' subscription still in use. Ignore dispose request.`, + })); + return; + } + this.handledUpdates.splice(0, this.handledUpdates.length); + super.dispose(); + } + /** + * Invalidate subscription object. + * + * Clean up resources used by a subscription object. + * + * **Note:** An invalidated instance won't call the dispatcher to deliver updates to the listeners. + * + * @param forDestroy - Whether subscription object invalidated as part of PubNub client destroy process or not. + * + * @internal + */ + invalidate(forDestroy = false) { + if (forDestroy) + this.state.entity.decreaseSubscriptionCount(this.state.id); + this.handledUpdates.splice(0, this.handledUpdates.length); + super.invalidate(forDestroy); + } + /** + * Add another {@link SubscriptionSet} into which subscription has been added. + * + * @param parent - {@link SubscriptionSet} which has been modified. + * + * @internal + */ + addParentSet(parent) { + if (!this.parents.includes(parent)) { + this.parents.push(parent); + this.state.client.logger.trace(this.subscriptionType, `Add parent subscription set for ${this.id}: ${parent.id}. Parent subscription set count: ${this.parentSetsCount}`); + } + } + /** + * Remove {@link SubscriptionSet} upon subscription removal from it. + * + * @param parent - {@link SubscriptionSet} which has been modified. + * + * @internal + */ + removeParentSet(parent) { + const parentIndex = this.parents.indexOf(parent); + if (parentIndex !== -1) { + this.parents.splice(parentIndex, 1); + this.state.client.logger.trace(this.subscriptionType, `Remove parent subscription set from ${this.id}: ${parent.id}. Parent subscription set count: ${this.parentSetsCount}`); + } + if (this.parentSetsCount === 0) + this.handledUpdates.splice(0, this.handledUpdates.length); + } + /** + * Merge entities' subscription objects into {@link SubscriptionSet}. + * + * @param subscription - Another entity's subscription object to be merged with receiver. + * + * @return {@link SubscriptionSet} which contains both receiver and other entities' subscription objects. + */ + addSubscription(subscription) { + this.state.client.logger.debug(this.subscriptionType, () => ({ + messageType: 'text', + message: `Create set with subscription: ${subscription}`, + })); + const subscriptionSet = new SubscriptionSet({ + client: this.state.client, + subscriptions: [this, subscription], + options: this.state.options, + }); + // Check whether a source subscription is already subscribed or not. + if (!this.state.isSubscribed && !subscription.state.isSubscribed) + return subscriptionSet; + this.state.client.logger.trace(this.subscriptionType, 'Subscribe resulting set because the receiver is already subscribed.'); + // Subscribing resulting subscription set because source subscription was subscribed. + subscriptionSet.subscribe(); + return subscriptionSet; + } + /** + * Register {@link Subscription} object for real-time events' retrieval. + * + * **Note:** Superclass calls this method only in response to a {@link Subscription.subscribe subscribe} method call. + * + * @param parameters - Object registration parameters. + * @param [parameters.cursor] - Subscription real-time events catch-up cursor. + * @param [parameters.subscriptions] - List of subscription objects which should be registered (in case of partial + * modification). + * + * @internal + */ + register(parameters) { + this.state.entity.increaseSubscriptionCount(this.state.id); + this.state.client.logger.trace(this.subscriptionType, () => ({ + messageType: 'text', + message: `Register subscription for real-time events: ${this}`, + })); + this.state.client.registerEventHandleCapable(this, parameters.cursor); + } + /** + * Unregister {@link Subscription} object from real-time events' retrieval. + * + * **Note:** Superclass calls this method only in response to a {@link Subscription.unsubscribe unsubscribe} method + * call. + * + * @param [_subscriptions] - List of subscription objects which should be unregistered (in case of partial + * modification). + * + * @internal + */ + unregister(_subscriptions) { + this.state.entity.decreaseSubscriptionCount(this.state.id); + this.state.client.logger.trace(this.subscriptionType, () => ({ + messageType: 'text', + message: `Unregister subscription from real-time events: ${this}`, + })); + this.handledUpdates.splice(0, this.handledUpdates.length); + this.state.client.unregisterEventHandleCapable(this); + } + /** + * Stringify subscription object. + * + * @returns Serialized subscription object. + */ + toString() { + const state = this.state; + return `${this.subscriptionType} { id: ${this.id}, stateId: ${state.id}, entity: ${state.entity + .subscriptionNames(false) + .pop()}, clonesCount: ${Object.keys(state.clones).length}, isSubscribed: ${state.isSubscribed}, parentSetsCount: ${this.parentSetsCount}, cursor: ${state.cursor ? state.cursor.timetoken : 'not set'}, referenceTimetoken: ${state.referenceTimetoken ? state.referenceTimetoken : 'not set'} }`; + } + } + + /** + * Get Presence State REST API module. + * + * @internal + */ + // endregion + /** + * Get `uuid` presence state request. + * + * @internal + */ + class GetPresenceStateRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b; + var _c, _d; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = (_c = this.parameters).channels) !== null && _a !== void 0 ? _a : (_c.channels = []); + (_b = (_d = this.parameters).channelGroups) !== null && _b !== void 0 ? _b : (_d.channelGroups = []); + } + operation() { + return RequestOperation$1.PNGetStateOperation; + } + validate() { + const { keySet: { subscribeKey }, channels, channelGroups, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + const serviceResponse = this.deserializeResponse(response); + const { channels = [], channelGroups = [] } = this.parameters; + const state = { channels: {} }; + if (channels.length === 1 && channelGroups.length === 0) + state.channels[channels[0]] = serviceResponse.payload; + else + state.channels = serviceResponse.payload; + return state; + }); + } + get path() { + const { keySet: { subscribeKey }, uuid, channels, } = this.parameters; + return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}/uuid/${encodeString(uuid !== null && uuid !== void 0 ? uuid : '')}`; + } + get queryParameters() { + const { channelGroups } = this.parameters; + if (!channelGroups || channelGroups.length === 0) + return {}; + return { 'channel-group': channelGroups.join(',') }; + } + } + + /** + * Set Presence State REST API module. + * + * @internal + */ + // endregion + /** + * Set `uuid` presence state request. + * + * @internal + */ + class SetPresenceStateRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSetStateOperation; + } + validate() { + const { keySet: { subscribeKey }, state, channels = [], channelGroups = [], } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (state === undefined) + return 'Missing State'; + if ((channels === null || channels === void 0 ? void 0 : channels.length) === 0 && (channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.length) === 0) + return 'Please provide a list of channels and/or channel-groups'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { state: this.deserializeResponse(response).payload }; + }); + } + get path() { + const { keySet: { subscribeKey }, uuid, channels, } = this.parameters; + return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}/uuid/${encodeString(uuid)}/data`; + } + get queryParameters() { + const { channelGroups, state } = this.parameters; + const query = { state: JSON.stringify(state) }; + if (channelGroups && channelGroups.length !== 0) + query['channel-group'] = channelGroups.join(','); + return query; + } + } + + /** + * Announce heartbeat REST API module. + * + * @internal + */ + // endregion + /** + * Announce `uuid` presence request. + * + * @internal + */ + class HeartbeatRequest extends AbstractRequest { + constructor(parameters) { + super({ cancellable: true }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNHeartbeatOperation; + } + validate() { + const { keySet: { subscribeKey }, channels = [], channelGroups = [], } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (channels.length === 0 && channelGroups.length === 0) + return 'Please provide a list of channels and/or channel-groups'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + get path() { + const { keySet: { subscribeKey }, channels, } = this.parameters; + return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}/heartbeat`; + } + get queryParameters() { + const { channelGroups, state, heartbeat } = this.parameters; + const query = { heartbeat: `${heartbeat}` }; + if (channelGroups && channelGroups.length !== 0) + query['channel-group'] = channelGroups.join(','); + if (state !== undefined) + query.state = JSON.stringify(state); + return query; + } + } + + /** + * Announce leave REST API module. + * + * @internal + */ + // endregion + /** + * Announce user leave request. + * + * @internal + */ + class PresenceLeaveRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + if (this.parameters.channelGroups) + this.parameters.channelGroups = Array.from(new Set(this.parameters.channelGroups)); + if (this.parameters.channels) + this.parameters.channels = Array.from(new Set(this.parameters.channels)); + } + operation() { + return RequestOperation$1.PNUnsubscribeOperation; + } + validate() { + const { keySet: { subscribeKey }, channels = [], channelGroups = [], } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (channels.length === 0 && channelGroups.length === 0) + return 'At least one `channel` or `channel group` should be provided.'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + get path() { + var _a; + const { keySet: { subscribeKey }, channels, } = this.parameters; + return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames((_a = channels === null || channels === void 0 ? void 0 : channels.sort()) !== null && _a !== void 0 ? _a : [], ',')}/leave`; + } + get queryParameters() { + const { channelGroups } = this.parameters; + if (!channelGroups || channelGroups.length === 0) + return {}; + return { 'channel-group': channelGroups.sort().join(',') }; + } + } + + /** + * `uuid` presence REST API module. + * + * @internal + */ + // endregion + /** + * Get `uuid` presence request. + * + * @internal + */ + class WhereNowRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNWhereNowOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + const serviceResponse = this.deserializeResponse(response); + if (!serviceResponse.payload) + return { channels: [] }; + return { channels: serviceResponse.payload.channels }; + }); + } + get path() { + const { keySet: { subscribeKey }, uuid, } = this.parameters; + return `/v2/presence/sub-key/${subscribeKey}/uuid/${encodeString(uuid)}`; + } + } + + /** + * Channels / channel groups presence REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `uuid` should be included in response or not. + */ + const INCLUDE_UUID$1 = true; + /** + * Whether state associated with `uuid` should be included in response or not. + */ + const INCLUDE_STATE = false; + /** + * Maximum number of participants which can be returned with single response. + */ + const MAXIMUM_COUNT = 1000; + // endregion + /** + * Channel presence request. + * + * @internal + */ + class HereNowRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d; + var _e, _f, _g, _h; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = (_e = this.parameters).queryParameters) !== null && _a !== void 0 ? _a : (_e.queryParameters = {}); + (_b = (_f = this.parameters).includeUUIDs) !== null && _b !== void 0 ? _b : (_f.includeUUIDs = INCLUDE_UUID$1); + (_c = (_g = this.parameters).includeState) !== null && _c !== void 0 ? _c : (_g.includeState = INCLUDE_STATE); + (_d = (_h = this.parameters).limit) !== null && _d !== void 0 ? _d : (_h.limit = MAXIMUM_COUNT); + } + operation() { + const { channels = [], channelGroups = [] } = this.parameters; + return channels.length === 0 && channelGroups.length === 0 + ? RequestOperation$1.PNGlobalHereNowOperation + : RequestOperation$1.PNHereNowOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b; + const serviceResponse = this.deserializeResponse(response); + // Extract general presence information. + const totalChannels = 'occupancy' in serviceResponse ? 1 : serviceResponse.payload.total_channels; + const totalOccupancy = 'occupancy' in serviceResponse ? serviceResponse.occupancy : serviceResponse.payload.total_occupancy; + const channelsPresence = {}; + let channels = {}; + const limit = this.parameters.limit; + let occupancyMatchLimit = false; + // Remap single channel presence to multiple channels presence response. + if ('occupancy' in serviceResponse) { + const channel = this.parameters.channels[0]; + channels[channel] = { uuids: (_a = serviceResponse.uuids) !== null && _a !== void 0 ? _a : [], occupancy: totalOccupancy }; + } + else + channels = (_b = serviceResponse.payload.channels) !== null && _b !== void 0 ? _b : {}; + Object.keys(channels).forEach((channel) => { + const channelEntry = channels[channel]; + channelsPresence[channel] = { + occupants: this.parameters.includeUUIDs + ? channelEntry.uuids.map((uuid) => { + if (typeof uuid === 'string') + return { uuid, state: null }; + return uuid; + }) + : [], + name: channel, + occupancy: channelEntry.occupancy, + }; + if (!occupancyMatchLimit && channelEntry.occupancy === limit) + occupancyMatchLimit = true; + }); + return { + totalChannels, + totalOccupancy, + channels: channelsPresence, + }; + }); + } + get path() { + const { keySet: { subscribeKey }, channels, channelGroups, } = this.parameters; + let path = `/v2/presence/sub-key/${subscribeKey}`; + if ((channels && channels.length > 0) || (channelGroups && channelGroups.length > 0)) + path += `/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}`; + return path; + } + get queryParameters() { + const { channelGroups, includeUUIDs, includeState, limit, offset, queryParameters } = this.parameters; + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (this.operation() === RequestOperation$1.PNHereNowOperation ? { limit } : {})), (this.operation() === RequestOperation$1.PNHereNowOperation && (offset !== null && offset !== void 0 ? offset : 0 > 0) ? { offset } : {})), (!includeUUIDs ? { disable_uuids: '1' } : {})), ((includeState !== null && includeState !== void 0 ? includeState : false) ? { state: '1' } : {})), (channelGroups && channelGroups.length > 0 ? { 'channel-group': channelGroups.join(',') } : {})), queryParameters); + } + } + + /** + * Delete messages REST API module. + * + * @internal + */ + // endregion + /** + * Delete messages from channel history. + * + * @internal + */ + class DeleteMessageRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNDeleteMessagesOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + if (!this.parameters.channel) + return 'Missing channel'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v3/history/sub-key/${subscribeKey}/channel/${encodeString(channel)}`; + } + get queryParameters() { + const { start, end } = this.parameters; + return Object.assign(Object.assign({}, (start ? { start } : {})), (end ? { end } : {})); + } + } + + /** + * Messages count REST API module. + * + * @internal + */ + // endregion + /** + * Count messages request. + * + * @internal + */ + class MessageCountRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNMessageCounts; + } + validate() { + const { keySet: { subscribeKey }, channels, timetoken, channelTimetokens, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channels) + return 'Missing channels'; + if (timetoken && channelTimetokens) + return '`timetoken` and `channelTimetokens` are incompatible together'; + if (!timetoken && !channelTimetokens) + return '`timetoken` or `channelTimetokens` need to be set'; + if (channelTimetokens && channelTimetokens.length > 1 && channelTimetokens.length !== channels.length) + return 'Length of `channelTimetokens` and `channels` do not match'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { channels: this.deserializeResponse(response).channels }; + }); + } + get path() { + return `/v3/history/sub-key/${this.parameters.keySet.subscribeKey}/message-counts/${encodeNames(this.parameters.channels)}`; + } + get queryParameters() { + let { channelTimetokens } = this.parameters; + if (this.parameters.timetoken) + channelTimetokens = [this.parameters.timetoken]; + return Object.assign(Object.assign({}, (channelTimetokens.length === 1 ? { timetoken: channelTimetokens[0] } : {})), (channelTimetokens.length > 1 ? { channelsTimetoken: channelTimetokens.join(',') } : {})); + } + } + + /** + * Get history REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ---------------------- Defaults ------------------------ + // -------------------------------------------------------- + // region Defaults + /** + * Whether verbose logging enabled or not. + */ + const LOG_VERBOSITY$1 = false; + /** + * Whether associated message metadata should be returned or not. + */ + const INCLUDE_METADATA = false; + /** + * Whether timetokens should be returned as strings by default or not. + */ + const STRINGIFY_TIMETOKENS$1 = false; + /** + * Default and maximum number of messages which should be returned. + */ + const MESSAGES_COUNT = 100; + // endregion + /** + * Get single channel messages request. + * + * @internal + */ + class GetHistoryRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c; + super(); + this.parameters = parameters; + // Apply defaults. + if (parameters.count) + parameters.count = Math.min(parameters.count, MESSAGES_COUNT); + else + parameters.count = MESSAGES_COUNT; + (_a = parameters.stringifiedTimeToken) !== null && _a !== void 0 ? _a : (parameters.stringifiedTimeToken = STRINGIFY_TIMETOKENS$1); + (_b = parameters.includeMeta) !== null && _b !== void 0 ? _b : (parameters.includeMeta = INCLUDE_METADATA); + (_c = parameters.logVerbosity) !== null && _c !== void 0 ? _c : (parameters.logVerbosity = LOG_VERBOSITY$1); + } + operation() { + return RequestOperation$1.PNHistoryOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + if (!this.parameters.channel) + return 'Missing channel'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + const serviceResponse = this.deserializeResponse(response); + const messages = serviceResponse[0]; + const startTimeToken = serviceResponse[1]; + const endTimeToken = serviceResponse[2]; + // Handle malformed get history response. + if (!Array.isArray(messages)) + return { messages: [], startTimeToken, endTimeToken }; + return { + messages: messages.map((payload) => { + const processedPayload = this.processPayload(payload.message); + const item = { + entry: processedPayload.payload, + timetoken: payload.timetoken, + }; + if (processedPayload.error) + item.error = processedPayload.error; + if (payload.meta) + item.meta = payload.meta; + return item; + }), + startTimeToken, + endTimeToken, + }; + }); + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v2/history/sub-key/${subscribeKey}/channel/${encodeString(channel)}`; + } + get queryParameters() { + const { start, end, reverse, count, stringifiedTimeToken, includeMeta } = this.parameters; + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: count, include_token: 'true' }, (start ? { start } : {})), (end ? { end } : {})), (stringifiedTimeToken ? { string_message_token: 'true' } : {})), (reverse !== undefined && reverse !== null ? { reverse: reverse.toString() } : {})), (includeMeta ? { include_meta: 'true' } : {})); + } + processPayload(payload) { + const { crypto, logVerbosity } = this.parameters; + if (!crypto || typeof payload !== 'string') + return { payload }; + let decryptedPayload; + let error; + try { + const decryptedData = crypto.decrypt(payload); + decryptedPayload = + decryptedData instanceof ArrayBuffer + ? JSON.parse(GetHistoryRequest.decoder.decode(decryptedData)) + : decryptedData; + } + catch (err) { + if (logVerbosity) + console.log(`decryption error`, err.message); + decryptedPayload = payload; + error = `Error while decrypting message content: ${err.message}`; + } + return { + payload: decryptedPayload, + error, + }; + } + } + + // endregion + // -------------------------------------------------------- + // -------------------- Fetch Messages -------------------- + // -------------------------------------------------------- + // region Fetch Messages + /** + * PubNub-defined message type. + * + * Types of messages which can be retrieved with fetch messages REST API. + */ + var PubNubMessageType; + (function (PubNubMessageType) { + /** + * Regular message. + */ + PubNubMessageType[PubNubMessageType["Message"] = -1] = "Message"; + /** + * File message. + */ + PubNubMessageType[PubNubMessageType["Files"] = 4] = "Files"; + })(PubNubMessageType || (PubNubMessageType = {})); + // endregion + + /** + * Fetch messages REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ---------------------- Defaults ------------------------ + // -------------------------------------------------------- + // region Defaults + /** + * Whether verbose logging enabled or not. + */ + const LOG_VERBOSITY = false; + /** + * Whether message type should be returned or not. + */ + const INCLUDE_MESSAGE_TYPE = true; + /** + * Whether timetokens should be returned as strings by default or not. + */ + const STRINGIFY_TIMETOKENS = false; + /** + * Whether message publisher `uuid` should be returned or not. + */ + const INCLUDE_UUID = true; + /** + * Default number of messages which can be returned for single channel, and it is maximum as well. + */ + const SINGLE_CHANNEL_MESSAGES_COUNT = 100; + /** + * Default number of messages which can be returned for multiple channels or when fetched + * message actions. + */ + const MULTIPLE_CHANNELS_MESSAGES_COUNT = 25; + // endregion + /** + * Fetch messages from channels request. + * + * @internal + */ + class FetchMessagesRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d, _e; + super(); + this.parameters = parameters; + // Apply defaults. + const includeMessageActions = (_a = parameters.includeMessageActions) !== null && _a !== void 0 ? _a : false; + const defaultCount = parameters.channels.length > 1 || includeMessageActions + ? MULTIPLE_CHANNELS_MESSAGES_COUNT + : SINGLE_CHANNEL_MESSAGES_COUNT; + if (!parameters.count) + parameters.count = defaultCount; + else + parameters.count = Math.min(parameters.count, defaultCount); + if (parameters.includeUuid) + parameters.includeUUID = parameters.includeUuid; + else + (_b = parameters.includeUUID) !== null && _b !== void 0 ? _b : (parameters.includeUUID = INCLUDE_UUID); + (_c = parameters.stringifiedTimeToken) !== null && _c !== void 0 ? _c : (parameters.stringifiedTimeToken = STRINGIFY_TIMETOKENS); + (_d = parameters.includeMessageType) !== null && _d !== void 0 ? _d : (parameters.includeMessageType = INCLUDE_MESSAGE_TYPE); + (_e = parameters.logVerbosity) !== null && _e !== void 0 ? _e : (parameters.logVerbosity = LOG_VERBOSITY); + } + operation() { + return RequestOperation$1.PNFetchMessagesOperation; + } + validate() { + const { keySet: { subscribeKey }, channels, includeMessageActions, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channels) + return 'Missing channels'; + if (includeMessageActions !== undefined && includeMessageActions && channels.length > 1) + return ('History can return actions data for a single channel only. Either pass a single channel ' + + 'or disable the includeMessageActions flag.'); + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + const serviceResponse = this.deserializeResponse(response); + const responseChannels = (_a = serviceResponse.channels) !== null && _a !== void 0 ? _a : {}; + const channels = {}; + Object.keys(responseChannels).forEach((channel) => { + // Map service response to expected data object type structure. + channels[channel] = responseChannels[channel].map((payload) => { + // `null` message type means regular message. + if (payload.message_type === null) + payload.message_type = PubNubMessageType.Message; + const processedPayload = this.processPayload(channel, payload); + const item = Object.assign(Object.assign({ channel, timetoken: payload.timetoken, message: processedPayload.payload, messageType: payload.message_type }, (payload.custom_message_type ? { customMessageType: payload.custom_message_type } : {})), { uuid: payload.uuid }); + if (payload.actions) { + const itemWithActions = item; + itemWithActions.actions = payload.actions; + // Backward compatibility for existing users. + // TODO: Remove in next release. + itemWithActions.data = payload.actions; + } + if (payload.meta) + item.meta = payload.meta; + if (processedPayload.error) + item.error = processedPayload.error; + return item; + }); + }); + if (serviceResponse.more) + return { channels, more: serviceResponse.more }; + return { channels }; + }); + } + get path() { + const { keySet: { subscribeKey }, channels, includeMessageActions, } = this.parameters; + const endpoint = !includeMessageActions ? 'history' : 'history-with-actions'; + return `/v3/${endpoint}/sub-key/${subscribeKey}/channel/${encodeNames(channels)}`; + } + get queryParameters() { + const { start, end, count, includeCustomMessageType, includeMessageType, includeMeta, includeUUID, stringifiedTimeToken, } = this.parameters; + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ max: count }, (start ? { start } : {})), (end ? { end } : {})), (stringifiedTimeToken ? { string_message_token: 'true' } : {})), (includeMeta !== undefined && includeMeta ? { include_meta: 'true' } : {})), (includeUUID ? { include_uuid: 'true' } : {})), (includeCustomMessageType !== undefined && includeCustomMessageType !== null + ? { include_custom_message_type: includeCustomMessageType ? 'true' : 'false' } + : {})), (includeMessageType ? { include_message_type: 'true' } : {})); + } + /** + * Parse single channel data entry. + * + * @param channel - Channel for which {@link payload} should be processed. + * @param payload - Source payload which should be processed and parsed to expected type. + * + * @returns + */ + processPayload(channel, payload) { + const { crypto, logVerbosity } = this.parameters; + if (!crypto || typeof payload.message !== 'string') + return { payload: payload.message }; + let decryptedPayload; + let error; + try { + const decryptedData = crypto.decrypt(payload.message); + decryptedPayload = + decryptedData instanceof ArrayBuffer + ? JSON.parse(FetchMessagesRequest.decoder.decode(decryptedData)) + : decryptedData; + } + catch (err) { + if (logVerbosity) + console.log(`decryption error`, err.message); + decryptedPayload = payload.message; + error = `Error while decrypting message content: ${err.message}`; + } + if (!error && + decryptedPayload && + payload.message_type == PubNubMessageType.Files && + typeof decryptedPayload === 'object' && + this.isFileMessage(decryptedPayload)) { + const fileMessage = decryptedPayload; + return { + payload: { + message: fileMessage.message, + file: Object.assign(Object.assign({}, fileMessage.file), { url: this.parameters.getFileUrl({ channel, id: fileMessage.file.id, name: fileMessage.file.name }) }), + }, + error, + }; + } + return { payload: decryptedPayload, error }; + } + /** + * Check whether `payload` potentially represents file message. + * + * @param payload - Fetched message payload. + * + * @returns `true` if payload can be {@link History#FileMessage|FileMessage}. + */ + isFileMessage(payload) { + return payload.file !== undefined; + } + } + + /** + * Get Message Actions REST API module. + * + * @internal + */ + // endregion + /** + * Fetch channel message actions request. + * + * @internal + */ + class GetMessageActionsRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetMessageActionsOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + if (!this.parameters.channel) + return 'Missing message channel'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + const serviceResponse = this.deserializeResponse(response); + let start = null; + let end = null; + if (serviceResponse.data.length > 0) { + start = serviceResponse.data[0].actionTimetoken; + end = serviceResponse.data[serviceResponse.data.length - 1].actionTimetoken; + } + return { + data: serviceResponse.data, + more: serviceResponse.more, + start, + end, + }; + }); + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v1/message-actions/${subscribeKey}/channel/${encodeString(channel)}`; + } + get queryParameters() { + const { limit, start, end } = this.parameters; + return Object.assign(Object.assign(Object.assign({}, (start ? { start } : {})), (end ? { end } : {})), (limit ? { limit } : {})); + } + } + + /** + * Add Message Action REST API module. + * + * @internal + */ + // endregion + /** + * Add Message Reaction request. + * + * @internal + */ + class AddMessageActionRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNAddMessageActionOperation; + } + validate() { + const { keySet: { subscribeKey }, action, channel, messageTimetoken, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channel) + return 'Missing message channel'; + if (!messageTimetoken) + return 'Missing message timetoken'; + if (!action) + return 'Missing Action'; + if (!action.value) + return 'Missing Action.value'; + if (!action.type) + return 'Missing Action.type'; + if (action.type.length > 15) + return 'Action.type value exceed maximum length of 15'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then(({ data }) => ({ data })); + }); + } + get path() { + const { keySet: { subscribeKey }, channel, messageTimetoken, } = this.parameters; + return `/v1/message-actions/${subscribeKey}/channel/${encodeString(channel)}/message/${messageTimetoken}`; + } + get headers() { + var _a; + return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); + } + get body() { + return JSON.stringify(this.parameters.action); + } + } + + /** + * Remove Message Action REST API module. + * + * @internal + */ + // endregion + /** + * Remove specific message action request. + * + * @internal + */ + class RemoveMessageAction extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveMessageActionOperation; + } + validate() { + const { keySet: { subscribeKey }, channel, messageTimetoken, actionTimetoken, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channel) + return 'Missing message action channel'; + if (!messageTimetoken) + return 'Missing message timetoken'; + if (!actionTimetoken) + return 'Missing action timetoken'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then(({ data }) => ({ data })); + }); + } + get path() { + const { keySet: { subscribeKey }, channel, actionTimetoken, messageTimetoken, } = this.parameters; + return `/v1/message-actions/${subscribeKey}/channel/${encodeString(channel)}/message/${messageTimetoken}/action/${actionTimetoken}`; + } + } + + /** + * Publish File Message REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether published file messages should be stored in the channel's history. + */ + const STORE_IN_HISTORY = true; + // endregion + /** + * Publish shared file information request. + * + * @internal + */ + class PublishFileMessageRequest extends AbstractRequest { + constructor(parameters) { + var _a; + var _b; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = (_b = this.parameters).storeInHistory) !== null && _a !== void 0 ? _a : (_b.storeInHistory = STORE_IN_HISTORY); + } + operation() { + return RequestOperation$1.PNPublishFileMessageOperation; + } + validate() { + const { channel, fileId, fileName } = this.parameters; + if (!channel) + return "channel can't be empty"; + if (!fileId) + return "file id can't be empty"; + if (!fileName) + return "file name can't be empty"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { timetoken: this.deserializeResponse(response)[2] }; + }); + } + get path() { + const { message, channel, keySet: { publishKey, subscribeKey }, fileId, fileName, } = this.parameters; + const fileMessage = Object.assign({ file: { + name: fileName, + id: fileId, + } }, (message ? { message } : {})); + return `/v1/files/publish-file/${publishKey}/${subscribeKey}/0/${encodeString(channel)}/0/${encodeString(this.prepareMessagePayload(fileMessage))}`; + } + get queryParameters() { + const { customMessageType, storeInHistory, ttl, meta } = this.parameters; + return Object.assign(Object.assign(Object.assign({ store: storeInHistory ? '1' : '0' }, (customMessageType ? { custom_message_type: customMessageType } : {})), (ttl ? { ttl } : {})), (meta && typeof meta === 'object' ? { meta: JSON.stringify(meta) } : {})); + } + /** + * Pre-process provided data. + * + * Data will be "normalized" and encrypted if `cryptoModule` has been provided. + * + * @param payload - User-provided data which should be pre-processed before use. + * + * @returns Payload which can be used as part of request URL or body. + * + * @throws {Error} in case if provided `payload` or results of `encryption` can't be stringified. + */ + prepareMessagePayload(payload) { + const { crypto } = this.parameters; + if (!crypto) + return JSON.stringify(payload) || ''; + const encrypted = crypto.encrypt(JSON.stringify(payload)); + return JSON.stringify(typeof encrypted === 'string' ? encrypted : encode(encrypted)); + } + } + + /** + * File sharing REST API module. + * + * @internal + */ + // endregion + /** + * File download Url generation request. + * + * Local request which generates Url to download shared file from the specific channel. + * + * @internal + */ + class GetFileDownloadUrlRequest extends AbstractRequest { + /** + * Construct file download Url generation request. + * + * @param parameters - Request configuration. + */ + constructor(parameters) { + super({ method: TransportMethod.LOCAL }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetFileUrlOperation; + } + validate() { + const { channel, id, name } = this.parameters; + if (!channel) + return "channel can't be empty"; + if (!id) + return "file id can't be empty"; + if (!name) + return "file name can't be empty"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return response.url; + }); + } + get path() { + const { channel, id, name, keySet: { subscribeKey }, } = this.parameters; + return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files/${encodeString(id)}/${encodeString(name)}`; + } + } + + /** + * Delete file REST API module. + * + * @internal + */ + // endregion + /** + * Delete File request. + * + * @internal + */ + class DeleteFileRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNDeleteFileOperation; + } + validate() { + const { channel, id, name } = this.parameters; + if (!channel) + return "channel can't be empty"; + if (!id) + return "file id can't be empty"; + if (!name) + return "file name can't be empty"; + } + get path() { + const { keySet: { subscribeKey }, id, channel, name, } = this.parameters; + return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files/${encodeString(id)}/${encodeString(name)}`; + } + } + + /** + * List Files REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Number of files to return in response. + */ + const LIMIT$6 = 100; + // endregion + /** + * Files List request. + * + * @internal + */ + class FilesListRequest extends AbstractRequest { + constructor(parameters) { + var _a; + var _b; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = (_b = this.parameters).limit) !== null && _a !== void 0 ? _a : (_b.limit = LIMIT$6); + } + operation() { + return RequestOperation$1.PNListFilesOperation; + } + validate() { + if (!this.parameters.channel) + return "channel can't be empty"; + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files`; + } + get queryParameters() { + const { limit, next } = this.parameters; + return Object.assign({ limit: limit }, (next ? { next } : {})); + } + } + + /** + * Generate file upload URL REST API request. + * + * @internal + */ + // endregion + /** + * Generate File Upload Url request. + * + * @internal + */ + class GenerateFileUploadUrlRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGenerateUploadUrlOperation; + } + validate() { + if (!this.parameters.channel) + return "channel can't be empty"; + if (!this.parameters.name) + return "'name' can't be empty"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + const serviceResponse = this.deserializeResponse(response); + return { + id: serviceResponse.data.id, + name: serviceResponse.data.name, + url: serviceResponse.file_upload_request.url, + formFields: serviceResponse.file_upload_request.form_fields, + }; + }); + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/generate-upload-url`; + } + get headers() { + var _a; + return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); + } + get body() { + return JSON.stringify({ name: this.parameters.name }); + } + } + + /** + * Upload file REST API request. + * + * @internal + */ + /** + * File Upload request. + * + * @internal + */ + class UploadFileRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + // Use file's actual mime type if available. + const mimeType = parameters.file.mimeType; + if (mimeType) { + parameters.formFields = parameters.formFields.map((entry) => { + if (entry.name === 'Content-Type') + return { name: entry.name, value: mimeType }; + return entry; + }); + } + } + operation() { + return RequestOperation$1.PNPublishFileOperation; + } + validate() { + const { fileId, fileName, file, uploadUrl } = this.parameters; + if (!fileId) + return "Validation failed: file 'id' can't be empty"; + if (!fileName) + return "Validation failed: file 'name' can't be empty"; + if (!file) + return "Validation failed: 'file' can't be empty"; + if (!uploadUrl) + return "Validation failed: file upload 'url' can't be empty"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { + status: response.status, + message: response.body ? UploadFileRequest.decoder.decode(response.body) : 'OK', + }; + }); + } + request() { + return Object.assign(Object.assign({}, super.request()), { origin: new URL(this.parameters.uploadUrl).origin, timeout: 300 }); + } + get path() { + const { pathname, search } = new URL(this.parameters.uploadUrl); + return `${pathname}${search}`; + } + get body() { + return this.parameters.file; + } + get formData() { + return this.parameters.formFields; + } + } + + /** + * Share File API module. + * + * @internal + */ + // endregion + /** + * Send file composed request. + * + * @internal + */ + class SendFileRequest { + constructor(parameters) { + var _a; + this.parameters = parameters; + this.file = (_a = this.parameters.PubNubFile) === null || _a === void 0 ? void 0 : _a.create(parameters.file); + if (!this.file) + throw new Error('File upload error: unable to create File object.'); + } + /** + * Process user-input and upload file. + * + * @returns File upload request response. + */ + process() { + return __awaiter(this, void 0, void 0, function* () { + let fileName; + let fileId; + return this.generateFileUploadUrl() + .then((result) => { + fileName = result.name; + fileId = result.id; + return this.uploadFile(result); + }) + .then((result) => { + if (result.status !== 204) { + throw new PubNubError('Upload to bucket was unsuccessful', { + error: true, + statusCode: result.status, + category: StatusCategory$1.PNUnknownCategory, + operation: RequestOperation$1.PNPublishFileOperation, + errorData: { message: result.message }, + }); + } + }) + .then(() => this.publishFileMessage(fileId, fileName)) + .catch((error) => { + if (error instanceof PubNubError) + throw error; + const apiError = !(error instanceof PubNubAPIError) ? PubNubAPIError.create(error) : error; + throw new PubNubError('File upload error.', apiError.toStatus(RequestOperation$1.PNPublishFileOperation)); + }); + }); + } + /** + * Generate pre-signed file upload Url. + * + * @returns File upload credentials. + */ + generateFileUploadUrl() { + return __awaiter(this, void 0, void 0, function* () { + const request = new GenerateFileUploadUrlRequest(Object.assign(Object.assign({}, this.parameters), { name: this.file.name, keySet: this.parameters.keySet })); + return this.parameters.sendRequest(request); + }); + } + /** + * Prepare and upload {@link PubNub} File object to remote storage. + * + * @param uploadParameters - File upload request parameters. + * + * @returns + */ + uploadFile(uploadParameters) { + return __awaiter(this, void 0, void 0, function* () { + const { cipherKey, PubNubFile, crypto, cryptography } = this.parameters; + const { id, name, url, formFields } = uploadParameters; + // Encrypt file if possible. + if (this.parameters.PubNubFile.supportsEncryptFile) { + if (!cipherKey && crypto) + this.file = (yield crypto.encryptFile(this.file, PubNubFile)); + else if (cipherKey && cryptography) + this.file = (yield cryptography.encryptFile(cipherKey, this.file, PubNubFile)); + } + return this.parameters.sendRequest(new UploadFileRequest({ + fileId: id, + fileName: name, + file: this.file, + uploadUrl: url, + formFields, + })); + }); + } + publishFileMessage(fileId, fileName) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b, _c, _d; + let result = { timetoken: '0' }; + let retries = this.parameters.fileUploadPublishRetryLimit; + let publishError; + let wasSuccessful = false; + do { + try { + result = yield this.parameters.publishFile(Object.assign(Object.assign({}, this.parameters), { fileId, fileName })); + wasSuccessful = true; + } + catch (error) { + if (error instanceof PubNubError) + publishError = error; + retries -= 1; + } + } while (!wasSuccessful && retries > 0); + if (!wasSuccessful) { + throw new PubNubError('Publish failed. You may want to execute that operation manually using pubnub.publishFile', { + error: true, + category: (_b = (_a = publishError.status) === null || _a === void 0 ? void 0 : _a.category) !== null && _b !== void 0 ? _b : StatusCategory$1.PNUnknownCategory, + statusCode: (_d = (_c = publishError.status) === null || _c === void 0 ? void 0 : _c.statusCode) !== null && _d !== void 0 ? _d : 0, + channel: this.parameters.channel, + id: fileId, + name: fileName, + }); + } + else + return { status: 200, timetoken: result.timetoken, id: fileId, name: fileName }; + }); + } + } + + /** + * Common entity interface. + */ + class Entity { + /** + * Create an entity instance. + * + * @param nameOrId - Identifier which will be used with subscription loop. + * @param client - PubNub instance which has been used to create this entity. + * + * @internal + */ + constructor(nameOrId, client) { + /** + * List of subscription state object IDs which are using this entity. + * + * @internal + */ + this.subscriptionStateIds = []; + this.client = client; + this._nameOrId = nameOrId; + } + /** + * Retrieve entity type. + * + * @return One of known {@link EntityType entity types}. + * + * @internal + */ + get entityType() { + return 'Channel'; + } + /** + * Type of subscription entity. + * + * Type defines where it will be used with multiplexed subscribe REST API calls. + * + * @retuerns One of {@link SubscriptionType} enum fields. + * + * @internal + */ + get subscriptionType() { + return SubscriptionType.Channel; + } + /** + * Names for an object to be used in subscription. + * + * Provided strings will be used with multiplexed subscribe REST API calls. + * + * @param receivePresenceEvents - Whether presence events should be observed or not. + * + * @returns List of names with multiplexed subscribe REST API calls (may include additional names to receive presence + * updates). + * + * @internal + */ + subscriptionNames(receivePresenceEvents) { + { + return [ + this._nameOrId, + ...(receivePresenceEvents && !this._nameOrId.endsWith('-pnpres') ? [`${this._nameOrId}-pnpres`] : []), + ]; + } + } + /** + * Create a subscribable's subscription object for real-time updates. + * + * Create a subscription object which can be used to subscribe to the real-time updates sent to the specific data + * stream. + * + * @param [subscriptionOptions] - Subscription object behavior customization options. + * + * @returns Configured and ready to use subscribable's subscription object. + */ + subscription(subscriptionOptions) { + { + return new Subscription({ + client: this.client, + entity: this, + options: subscriptionOptions, + }); + } + } + /** + * How many active subscriptions use this entity. + * + * @internal + */ + get subscriptionsCount() { + return this.subscriptionStateIds.length; + } + /** + * Increase the number of active subscriptions. + * + * @param subscriptionStateId - Unique identifier of the subscription state object which doesn't use entity anymore. + * + * @internal + */ + increaseSubscriptionCount(subscriptionStateId) { + { + if (!this.subscriptionStateIds.includes(subscriptionStateId)) + this.subscriptionStateIds.push(subscriptionStateId); + } + } + /** + * Decrease the number of active subscriptions. + * + * **Note:** As long as the entity is used by at least one subscription, it can't be removed from the subscription. + * + * @param subscriptionStateId - Unique identifier of the subscription state object which doesn't use entity anymore. + * + * @internal + */ + decreaseSubscriptionCount(subscriptionStateId) { + { + const index = this.subscriptionStateIds.indexOf(subscriptionStateId); + if (index >= 0) + this.subscriptionStateIds.splice(index, 1); + } + } + /** + * Stringify entity object. + * + * @returns Serialized entity object. + */ + toString() { + return `${this.entityType} { nameOrId: ${this._nameOrId}, subscriptionsCount: ${this.subscriptionsCount} }`; + } + } + + /** + * Projection names which are observed on the object's base (un-prefixed) data channel. + * + * @internal + */ + const BASE_PROJECTIONS = ['default', '__default__']; + /** + * Key under which the base (un-prefixed) projection is stored in the variants registry. + * + * @internal + */ + const BASE_PROJECTION_KEY = ''; + /** + * Normalize a user-provided DataSync projection name. + * + * **Note:** Only the projection name is normalized. A DataSync object identifier is always used + * verbatim (so wildcard identifiers keep working by construction). + * + * @param [projection] - Projection name as provided by the user. + * + * @returns Trimmed projection name or `undefined` when the base projection is requested. + * + * @internal + */ + const normalizedProjection = (projection) => { + if (!projection) + return undefined; + const trimmed = projection.trim(); + if (trimmed.length === 0 || BASE_PROJECTIONS.includes(trimmed.toLowerCase())) + return undefined; + return trimmed; + }; + /** + * Base class for DataSync objects which can be observed with the subscribe REST API. + * + * A DataSync object is observed on a data channel named after its identifier, optionally prefixed + * with the name of an observed projection: `__{projection}__{id}`. + * + * **Note:** The identifier is used verbatim, so an identifier which already looks prefixed + * (`__admin__u1`) will be prefixed again when a projection is requested (`__admin____admin__u1`). + */ + class DataSyncSubscribable extends Entity { + /** + * Create a DataSync object entity. + * + * @param nameOrId - Unique DataSync object identifier (used verbatim). + * @param client - PubNub instance which has been used to create this entity. + * @param [projection] - Name of the projection which should be observed by this entity. + * + * @internal + */ + constructor(nameOrId, client, projection) { + super(nameOrId, client); + this._projection = normalizedProjection(projection); + } + /** + * Get unique DataSync object identifier. + * + * @returns DataSync object identifier. + */ + get id() { + return this._nameOrId; + } + /** + * Get the name of the projection which is observed by this entity. + * + * **Note:** A projection is chosen per subscription + * ({@link DataSyncSubscriptionOptions#projection}), so an entity created by the PubNub client + * always reports `undefined` here: it is the base-projection entity, and the entities bound to + * other projections are internal to it. + * + * @returns Observed projection name or `undefined` when the object is observed through its base + * projection. + */ + get projection() { + return this._projection; + } + /** + * Name of the data channel which is used with multiplexed subscribe REST API calls. + * + * @returns Name of the observed data channel. + * + * @internal + */ + get subscriptionChannel() { + return this._projection ? `__${this._projection}__${this._nameOrId}` : this._nameOrId; + } + /** + * Names for an object to be used in subscription. + * + * **Note:** A DataSync object is observed on a single data channel; presence events are not + * supported for it and `_receivePresenceEvents` is ignored. + * + * @param _receivePresenceEvents - Whether presence events should be observed or not. + * + * @returns List of names with multiplexed subscribe REST API calls. + * + * @internal + */ + subscriptionNames(_receivePresenceEvents) { + return [this.subscriptionChannel]; + } + /** + * Create a DataSync object's subscription object for real-time updates. + * + * @param [subscriptionOptions] - Subscription object behavior customization options. + * + * @returns Configured and ready to use DataSync object's subscription object. + * + * @example + * ```typescript + * // Observe the object itself. + * pubnub.dataSyncUser('u1').subscription().subscribe(); + * + * // Observe the `admin` projection of the object (the `__admin__u1` data channel). + * pubnub.dataSyncUser('u1').subscription({ projection: 'admin' }).subscribe(); + * ``` + */ + subscription(subscriptionOptions) { + { + const entity = this.entityForProjection(normalizedProjection(subscriptionOptions === null || subscriptionOptions === void 0 ? void 0 : subscriptionOptions.projection)); + // Each projection is observed on its own data channel, so it must be represented by its own + // entity instance (see `variants`). Let the entity which owns the requested projection create + // the subscription object for itself: it resolves that same projection to itself, so this + // delegation is always a single hop. + if (entity !== this) + return entity.subscription(subscriptionOptions); + return super.subscription(subscriptionOptions); + } + } + /** + * Resolve the entity which observes the same DataSync object through `projection`. + * + * @param [projection] - Normalized name of the projection to observe. + * + * @returns Receiver itself, or the memoized sibling entity bound to `projection`. + * + * @internal + */ + entityForProjection(projection) { + var _a, _b, _c; + var _d; + if (projection === this._projection) + return this; + // Register the receiver in the shared registry, so that it can be resolved back from siblings. + // + // Note: the receiver is added with an element assignment and never as part of an object literal + // which is assigned to `variants`. Declaration files for this module are inferred from the + // compiled JavaScript (`allowJs`), where a `this.variants = { ...: this }` statement would make + // the inferred member type reference the inaccessible polymorphic `this` type (TS2527). + const variants = ((_a = this.variants) !== null && _a !== void 0 ? _a : (this.variants = {})); + (_c = variants[_d = (_b = this._projection) !== null && _b !== void 0 ? _b : BASE_PROJECTION_KEY]) !== null && _c !== void 0 ? _c : (variants[_d] = this); + const key = projection !== null && projection !== void 0 ? projection : BASE_PROJECTION_KEY; + let entity = variants[key]; + if (!entity) { + entity = variants[key] = this.withProjection(projection); + entity.variants = variants; + } + return entity; + } + /** + * Stringify entity object. + * + * @returns Serialized entity object. + */ + toString() { + var _a; + return (`${this.entityType} { id: ${this._nameOrId}, projection: ${(_a = this._projection) !== null && _a !== void 0 ? _a : 'none'}, ` + + `channel: ${this.subscriptionChannel}, subscriptionsCount: ${this.subscriptionsCount} }`); + } + } + + /** + * First-class object which provides access to the real-time updates of a DataSync `Relationship` + * object. + * + * **Important:** The service delivers relationship changes on the data channels of **both linked + * entities** (`entityAId` and `entityBId`), and never on the relationship's own identifier. Observe + * `pubnub.dataSyncEntity(...)` for the linked entities to receive relationship updates; this entity + * is only useful if a key set is configured to publish relationship changes on the relationship + * identifier itself. + */ + class DataSyncRelationship extends DataSyncSubscribable { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'DataSyncRelationship'; + } + /** + * Create a copy of the receiver which observes `projection` of the same DataSync `Relationship` + * object. + * + * @param [projection] - Normalized name of the projection to observe. + * + * @returns `DataSyncRelationship` entity bound to `projection`. + * + * @internal + */ + withProjection(projection) { + return new DataSyncRelationship(this._nameOrId, this.client, projection); + } + } + + /** + * First-class object which provides access to the real-time updates of a DataSync `Membership` + * object. + * + * **Note:** A membership identifier is composite (`{userId}:{channelId}`) and is used verbatim as + * the name of the observed data channel. + * + * **Important:** The service delivers membership changes on the data channels of **both linked + * entities** (the user identifier and the channel identifier), and never on the membership's own + * identifier. Observe `pubnub.dataSyncUser(...)` and/or `pubnub.dataSyncChannel(...)` to receive + * membership updates; this entity is only useful if a key set is configured to publish membership + * changes on the membership identifier itself. + */ + class DataSyncMembership extends DataSyncSubscribable { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'DataSyncMembership'; + } + /** + * Create a copy of the receiver which observes `projection` of the same DataSync `Membership` + * object. + * + * @param [projection] - Normalized name of the projection to observe. + * + * @returns `DataSyncMembership` entity bound to `projection`. + * + * @internal + */ + withProjection(projection) { + return new DataSyncMembership(this._nameOrId, this.client, projection); + } + } + + /** + * First-class object which provides access to the real-time updates of a DataSync `Channel` object. + */ + class DataSyncChannel extends DataSyncSubscribable { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'DataSyncChannel'; + } + /** + * Create a copy of the receiver which observes `projection` of the same DataSync `Channel` object. + * + * @param [projection] - Normalized name of the projection to observe. + * + * @returns `DataSyncChannel` entity bound to `projection`. + * + * @internal + */ + withProjection(projection) { + return new DataSyncChannel(this._nameOrId, this.client, projection); + } + } + + /** + * First-class object which provides access to the real-time updates of a DataSync `Entity` object. + */ + class DataSyncEntity extends DataSyncSubscribable { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'DataSyncEntity'; + } + /** + * Create a copy of the receiver which observes `projection` of the same DataSync `Entity` object. + * + * @param [projection] - Normalized name of the projection to observe. + * + * @returns `DataSyncEntity` entity bound to `projection`. + * + * @internal + */ + withProjection(projection) { + return new DataSyncEntity(this._nameOrId, this.client, projection); + } + } + + /** + * First-class objects which provides access to the channel app context object-specific APIs. + */ + class ChannelMetadata extends Entity { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'ChannelMetadata'; + } + /** + * Get unique channel metadata object identifier. + * + * @returns Channel metadata identifier. + */ + get id() { + return this._nameOrId; + } + /** + * Names for an object to be used in subscription. + * + * Provided strings will be used with multiplexed subscribe REST API calls. + * + * @param _receivePresenceEvents - Whether presence events should be observed or not. + * + * @returns List of names with multiplexed subscribe REST API calls (may include additional names to receive presence + * updates). + * + * @internal + */ + subscriptionNames(_receivePresenceEvents) { + return [this.id]; + } + } + + /** + * First-class object which provides access to the real-time updates of a DataSync `User` object. + */ + class DataSyncUser extends DataSyncSubscribable { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'DataSyncUser'; + } + /** + * Create a copy of the receiver which observes `projection` of the same DataSync `User` object. + * + * @param [projection] - Normalized name of the projection to observe. + * + * @returns `DataSyncUser` entity bound to `projection`. + * + * @internal + */ + withProjection(projection) { + return new DataSyncUser(this._nameOrId, this.client, projection); + } + } + + /** + * First-class objects which provides access to the channel group-specific APIs. + */ + class ChannelGroup extends Entity { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'ChannelGroups'; + } + /** + * Get a unique channel group name. + * + * @returns Channel group name. + */ + get name() { + return this._nameOrId; + } + /** + * Type of subscription entity. + * + * Type defines where it will be used with multiplexed subscribe REST API calls. + * + * @retuerns One of {@link SubscriptionType} enum fields. + * + * @internal + */ + get subscriptionType() { + return SubscriptionType.ChannelGroup; + } + } + + /** + * First-class objects which provides access to the user app context object-specific APIs. + */ + class UserMetadata extends Entity { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'UserMetadata'; + } + /** + * Get unique user metadata object identifier. + * + * @returns User metadata identifier. + */ + get id() { + return this._nameOrId; + } + /** + * Names for an object to be used in subscription. + * + * Provided strings will be used with multiplexed subscribe REST API calls. + * + * @param _receivePresenceEvents - Whether presence events should be observed or not. + * + * @returns List of names with multiplexed subscribe REST API calls (may include additional names to receive presence + * updates). + * + * @internal + */ + subscriptionNames(_receivePresenceEvents) { + return [this.id]; + } + } + + /** + * First-class objects which provides access to the channel-specific APIs. + */ + class Channel extends Entity { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'Channel'; + } + /** + * Get a unique channel name. + * + * @returns Channel name. + */ + get name() { + return this._nameOrId; + } + } + + /** + * Remove channel group channels REST API module. + * + * @internal + */ + // endregion + /** + * Remove channel group channels request. + * + * @internal + */ + // prettier-ignore + class RemoveChannelGroupChannelsRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveChannelsFromGroupOperation; + } + validate() { + const { keySet: { subscribeKey }, channels, channelGroup, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channelGroup) + return 'Missing Channel Group'; + if (!channels) + return 'Missing channels'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + get path() { + const { keySet: { subscribeKey }, channelGroup, } = this.parameters; + return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}`; + } + get queryParameters() { + return { remove: this.parameters.channels.join(',') }; + } + } + + /** + * Add channel group channels REST API module. + * + * @internal + */ + // endregion + /** + * Add channel group channels request. + * + * @internal + */ + class AddChannelGroupChannelsRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNAddChannelsToGroupOperation; + } + validate() { + const { keySet: { subscribeKey }, channels, channelGroup, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channelGroup) + return 'Missing Channel Group'; + if (!channels) + return 'Missing channels'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + get path() { + const { keySet: { subscribeKey }, channelGroup, } = this.parameters; + return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}`; + } + get queryParameters() { + return { add: this.parameters.channels.join(',') }; + } + } + + /** + * List channel group channels REST API module. + * + * @internal + */ + // endregion + /** + * List Channel Group Channels request. + * + * @internal + */ + class ListChannelGroupChannels extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNChannelsForGroupOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + if (!this.parameters.channelGroup) + return 'Missing Channel Group'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { channels: this.deserializeResponse(response).payload.channels }; + }); + } + get path() { + const { keySet: { subscribeKey }, channelGroup, } = this.parameters; + return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}`; + } + } + + /** + * Delete channel group REST API module. + * + * @internal + */ + // endregion + /** + * Channel group delete request. + * + * @internal + */ + class DeleteChannelGroupRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveGroupOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + if (!this.parameters.channelGroup) + return 'Missing Channel Group'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + get path() { + const { keySet: { subscribeKey }, channelGroup, } = this.parameters; + return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}/remove`; + } + } + + /** + * List All Channel Groups REST API module. + * + * @internal + */ + // endregion + /** + * List all channel groups request. + * + * @internal + */ + class ListChannelGroupsRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNChannelGroupsOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { groups: this.deserializeResponse(response).payload.groups }; + }); + } + get path() { + return `/v1/channel-registration/sub-key/${this.parameters.keySet.subscribeKey}/channel-group`; + } + } + + /** + * PubNub Channel Groups API module. + */ + /** + * PubNub Stream / Channel group API interface. + */ + class PubNubChannelGroups { + /** + * Create stream / channel group API access object. + * + * @param logger - Registered loggers' manager. + * @param keySet - PubNub account keys set which should be used for REST API calls. + * @param sendRequest - Function which should be used to send REST API calls. + * + * @internal + */ + constructor(logger, keySet, + /* eslint-disable @typescript-eslint/no-explicit-any */ + sendRequest) { + this.sendRequest = sendRequest; + this.logger = logger; + this.keySet = keySet; + } + /** + * Fetch channel group channels. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get channel group channels response or `void` in case if `callback` + * provided. + */ + listChannels(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'List channel group channels with parameters:', + })); + const request = new ListChannelGroupChannels(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `List channel group channels success. Received ${response.channels.length} channels.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Fetch all channel groups. + * + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all channel groups response or `void` in case if `callback` provided. + * + * @deprecated + */ + listGroups(callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', 'List all channel groups.'); + const request = new ListChannelGroupsRequest({ keySet: this.keySet }); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `List all channel groups success. Received ${response.groups.length} groups.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Add channels to the channel group. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous add channels to the channel group response or `void` in case if + * `callback` provided. + */ + addChannels(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Add channels to the channel group with parameters:', + })); + const request = new AddChannelGroupChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = () => { + this.logger.debug('PubNub', `Add channels to the channel group success.`); + }; + if (callback) + return this.sendRequest(request, (status) => { + if (!status.error) + logResponse(); + callback(status); + }); + return this.sendRequest(request).then((response) => { + logResponse(); + return response; + }); + }); + } + /** + * Remove channels from the channel group. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove channels from the channel group response or `void` in + * case if `callback` provided. + */ + removeChannels(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove channels from the channel group with parameters:', + })); + const request = new RemoveChannelGroupChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = () => { + this.logger.debug('PubNub', `Remove channels from the channel group success.`); + }; + if (callback) + return this.sendRequest(request, (status) => { + if (!status.error) + logResponse(); + callback(status); + }); + return this.sendRequest(request).then((response) => { + logResponse(); + return response; + }); + }); + } + /** + * Remove a channel group. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove channel group response or `void` in case if `callback` provided. + */ + deleteGroup(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove a channel group with parameters:', + })); + const request = new DeleteChannelGroupRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = () => { + this.logger.debug('PubNub', `Remove a channel group success. Removed '${parameters.channelGroup}' channel group.'`); + }; + if (callback) + return this.sendRequest(request, (status) => { + if (!status.error) + logResponse(); + callback(status); + }); + return this.sendRequest(request).then((response) => { + logResponse(); + return response; + }); + }); + } + } + + /** + * Manage channels enabled for device push REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Environment for which APNS2 notifications + */ + const ENVIRONMENT = 'development'; + /** + * Maximum number of channels in `list` response. + */ + const MAX_COUNT = 1000; + // endregion + /** + * Base push notification request. + * + * @internal + */ + class BasePushNotificationChannelsRequest extends AbstractRequest { + constructor(parameters) { + var _a; + var _b; + super(); + this.parameters = parameters; + // Apply request defaults + if (this.parameters.pushGateway === 'apns2') + (_a = (_b = this.parameters).environment) !== null && _a !== void 0 ? _a : (_b.environment = ENVIRONMENT); + if (this.parameters.count && this.parameters.count > MAX_COUNT) + this.parameters.count = MAX_COUNT; + } + operation() { + throw Error('Should be implemented in subclass.'); + } + validate() { + const { keySet: { subscribeKey }, action, device, pushGateway, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!device) + return 'Missing Device ID (device)'; + if ((action === 'add' || action === 'remove') && + (!('channels' in this.parameters) || this.parameters.channels.length === 0)) + return 'Missing Channels'; + if (!pushGateway) + return 'Missing GW Type (pushGateway: fcm or apns2)'; + if (this.parameters.pushGateway === 'apns2' && !this.parameters.topic) + return 'Missing APNS2 topic'; + } + get path() { + const { keySet: { subscribeKey }, action, device, pushGateway, } = this.parameters; + let path = pushGateway === 'apns2' + ? `/v2/push/sub-key/${subscribeKey}/devices-apns2/${device}` + : `/v1/push/sub-key/${subscribeKey}/devices/${device}`; + if (action === 'remove-device') + path = `${path}/remove`; + return path; + } + get queryParameters() { + const { start, count } = this.parameters; + let query = Object.assign(Object.assign({ type: this.parameters.pushGateway }, (start ? { start } : {})), (count && count > 0 ? { count } : {})); + if ('channels' in this.parameters) + query[this.parameters.action] = this.parameters.channels.join(','); + if (this.parameters.pushGateway === 'apns2') { + const { environment, topic } = this.parameters; + query = Object.assign(Object.assign({}, query), { environment: environment, topic }); + } + return query; + } + } + + /** + * Unregister Channels from Device push REST API module. + * + * @internal + */ + // endregion + /** + * Unregister channels from device push request. + * + * @internal + */ + // prettier-ignore + class RemoveDevicePushNotificationChannelsRequest extends BasePushNotificationChannelsRequest { + constructor(parameters) { + super(Object.assign(Object.assign({}, parameters), { action: 'remove' })); + } + operation() { + return RequestOperation$1.PNRemovePushNotificationEnabledChannelsOperation; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + } + + /** + * List Device push enabled channels REST API module. + * + * @internal + */ + // endregion + /** + * List device push enabled channels request. + * + * @internal + */ + // prettier-ignore + class ListDevicePushNotificationChannelsRequest extends BasePushNotificationChannelsRequest { + constructor(parameters) { + super(Object.assign(Object.assign({}, parameters), { action: 'list' })); + } + operation() { + return RequestOperation$1.PNPushNotificationEnabledChannelsOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { channels: this.deserializeResponse(response) }; + }); + } + } + + /** + * Register Channels with Device push REST API module. + * + * @internal + */ + // endregion + /** + * Register channels with device push request. + * + * @internal + */ + // prettier-ignore + class AddDevicePushNotificationChannelsRequest extends BasePushNotificationChannelsRequest { + constructor(parameters) { + super(Object.assign(Object.assign({}, parameters), { action: 'add' })); + } + operation() { + return RequestOperation$1.PNAddPushNotificationEnabledChannelsOperation; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + } + + /** + * Unregister Device push REST API module. + * + * @internal + */ + // endregion + /** + * Unregister device push notifications request. + * + * @internal + */ + // prettier-ignore + class RemoveDevicePushNotificationRequest extends BasePushNotificationChannelsRequest { + constructor(parameters) { + super(Object.assign(Object.assign({}, parameters), { action: 'remove-device' })); + } + operation() { + return RequestOperation$1.PNRemoveAllPushNotificationsOperation; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + } + + /** + * PubNub Push Notifications API module. + */ + /** + * PubNub Push Notifications API interface. + */ + class PubNubPushNotifications { + /** + * Create mobile push notifications API access object. + * + * @param logger - Registered loggers' manager. + * @param keySet - PubNub account keys set which should be used for REST API calls. + * @param sendRequest - Function which should be used to send REST API calls. + * + * @internal + */ + constructor(logger, keySet, + /* eslint-disable @typescript-eslint/no-explicit-any */ + sendRequest) { + this.sendRequest = sendRequest; + this.logger = logger; + this.keySet = keySet; + } + /** + * Fetch device's push notification enabled channels. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get device channels response or `void` in case if `callback` provided. + */ + listChannels(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `List push-enabled channels with parameters:`, + })); + const request = new ListDevicePushNotificationChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `List push-enabled channels success. Received ${response.channels.length} channels.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Enable push notifications on channels for device. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + */ + addChannels(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Add push-enabled channels with parameters:`, + })); + const request = new AddDevicePushNotificationChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = () => { + this.logger.debug('PubNub', `Add push-enabled channels success.`); + }; + if (callback) + return this.sendRequest(request, (status) => { + if (!status.error) + logResponse(); + callback(status); + }); + return this.sendRequest(request).then((response) => { + logResponse(); + return response; + }); + }); + } + /** + * Disable push notifications on channels for device. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + */ + removeChannels(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove push-enabled channels with parameters:`, + })); + const request = new RemoveDevicePushNotificationChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = () => { + this.logger.debug('PubNub', `Remove push-enabled channels success.`); + }; + if (callback) + return this.sendRequest(request, (status) => { + if (!status.error) + logResponse(); + callback(status); + }); + return this.sendRequest(request).then((response) => { + logResponse(); + return response; + }); + }); + } + /** + * Disable push notifications for device. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + */ + deleteDevice(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove push notifications for device with parameters:`, + })); + const request = new RemoveDevicePushNotificationRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = () => { + this.logger.debug('PubNub', `Remove push notifications for device success.`); + }; + if (callback) + return this.sendRequest(request, (status) => { + if (!status.error) + logResponse(); + callback(status); + }); + return this.sendRequest(request).then((response) => { + logResponse(); + return response; + }); + }); + } + } + + /** + * Get All Channel Metadata REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Channel` custom fields should be included in response or not. + */ + const INCLUDE_CUSTOM_FIELDS$9 = false; + /** + * Whether total number of channels should be included in response or not. + */ + const INCLUDE_TOTAL_COUNT$4 = false; + /** + * Number of objects to return in response. + */ + const LIMIT$5 = 100; + // endregion + /** + * Get All Channels Metadata request. + * + * @internal + */ + class GetAllChannelsMetadataRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d; + var _e, _f; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_e = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_e.customFields = INCLUDE_CUSTOM_FIELDS$9); + (_c = (_f = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_f.totalCount = INCLUDE_TOTAL_COUNT$4); + (_d = parameters.limit) !== null && _d !== void 0 ? _d : (parameters.limit = LIMIT$5); + } + operation() { + return RequestOperation$1.PNGetAllChannelMetadataOperation; + } + get path() { + return `/v2/objects/${this.parameters.keySet.subscribeKey}/channels`; + } + get queryParameters() { + const { include, page, filter, sort, limit } = this.parameters; + let sorting = ''; + if (typeof sort === 'string') + sorting = sort; + else + sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ include: ['status', 'type', ...(include.customFields ? ['custom'] : [])].join(','), count: `${include.totalCount}` }, (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Remove Channel Metadata REST API module. + * + * @internal + */ + // endregion + /** + * Remove Channel Metadata request. + * + * @internal + */ + class RemoveChannelMetadataRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveChannelMetadataOperation; + } + validate() { + if (!this.parameters.channel) + return 'Channel cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}`; + } + } + + /** + * Get UUID Memberships REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Membership` custom field should be included in response or not. + */ + const INCLUDE_CUSTOM_FIELDS$8 = false; + /** + * Whether membership's `status` field should be included in response or not. + */ + const INCLUDE_STATUS$3 = false; + /** + * Whether membership's `type` field should be included in response or not. + */ + const INCLUDE_TYPE$3 = false; + /** + * Whether total number of memberships should be included in response or not. + */ + const INCLUDE_TOTAL_COUNT$3 = false; + /** + * Whether `Channel` fields should be included in response or not. + */ + const INCLUDE_CHANNEL_FIELDS$1 = false; + /** + * Whether `Channel` status field should be included in response or not. + */ + const INCLUDE_CHANNEL_STATUS_FIELD$1 = false; + /** + * Whether `Channel` type field should be included in response or not. + */ + const INCLUDE_CHANNEL_TYPE_FIELD$1 = false; + /** + * Whether `Channel` custom field should be included in response or not. + */ + const INCLUDE_CHANNEL_CUSTOM_FIELDS$1 = false; + /** + * Number of objects to return in response. + */ + const LIMIT$4 = 100; + // endregion + /** + * Get UUID Memberships request. + * + * @internal + */ + class GetUUIDMembershipsRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + var _l, _m, _o, _p, _q, _r, _s, _t; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$8); + (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT$3); + (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS$3); + (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE$3); + (_f = (_q = parameters.include).channelFields) !== null && _f !== void 0 ? _f : (_q.channelFields = INCLUDE_CHANNEL_FIELDS$1); + (_g = (_r = parameters.include).customChannelFields) !== null && _g !== void 0 ? _g : (_r.customChannelFields = INCLUDE_CHANNEL_CUSTOM_FIELDS$1); + (_h = (_s = parameters.include).channelStatusField) !== null && _h !== void 0 ? _h : (_s.channelStatusField = INCLUDE_CHANNEL_STATUS_FIELD$1); + (_j = (_t = parameters.include).channelTypeField) !== null && _j !== void 0 ? _j : (_t.channelTypeField = INCLUDE_CHANNEL_TYPE_FIELD$1); + (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT$4); + // Remap for backward compatibility. + if (this.parameters.userId) + this.parameters.uuid = this.parameters.userId; + } + operation() { + return RequestOperation$1.PNGetMembershipsOperation; + } + validate() { + if (!this.parameters.uuid) + return "'uuid' cannot be empty"; + } + get path() { + const { keySet: { subscribeKey }, uuid, } = this.parameters; + return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}/channels`; + } + get queryParameters() { + const { include, page, filter, sort, limit } = this.parameters; + let sorting = ''; + if (typeof sort === 'string') + sorting = sort; + else + sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + const includeFlags = []; + if (include.statusField) + includeFlags.push('status'); + if (include.typeField) + includeFlags.push('type'); + if (include.customFields) + includeFlags.push('custom'); + if (include.channelFields) + includeFlags.push('channel'); + if (include.channelStatusField) + includeFlags.push('channel.status'); + if (include.channelTypeField) + includeFlags.push('channel.type'); + if (include.customChannelFields) + includeFlags.push('channel.custom'); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set UUID Memberships REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Membership` custom field should be included in response or not. + */ + const INCLUDE_CUSTOM_FIELDS$7 = false; + /** + * Whether membership's `status` field should be included in response or not. + */ + const INCLUDE_STATUS$2 = false; + /** + * Whether membership's `type` field should be included in response or not. + */ + const INCLUDE_TYPE$2 = false; + /** + * Whether total number of memberships should be included in response or not. + */ + const INCLUDE_TOTAL_COUNT$2 = false; + /** + * Whether `Channel` fields should be included in response or not. + */ + const INCLUDE_CHANNEL_FIELDS = false; + /** + * Whether `Channel` status field should be included in response or not. + */ + const INCLUDE_CHANNEL_STATUS_FIELD = false; + /** + * Whether `Channel` type field should be included in response or not. + */ + const INCLUDE_CHANNEL_TYPE_FIELD = false; + /** + * Whether `Channel` custom field should be included in response or not. + */ + const INCLUDE_CHANNEL_CUSTOM_FIELDS = false; + /** + * Number of objects to return in response. + */ + const LIMIT$3 = 100; + // endregion + /** + * Set UUID Memberships request. + * + * @internal + */ + class SetUUIDMembershipsRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + var _l, _m, _o, _p, _q, _r, _s, _t; + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$7); + (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT$2); + (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS$2); + (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE$2); + (_f = (_q = parameters.include).channelFields) !== null && _f !== void 0 ? _f : (_q.channelFields = INCLUDE_CHANNEL_FIELDS); + (_g = (_r = parameters.include).customChannelFields) !== null && _g !== void 0 ? _g : (_r.customChannelFields = INCLUDE_CHANNEL_CUSTOM_FIELDS); + (_h = (_s = parameters.include).channelStatusField) !== null && _h !== void 0 ? _h : (_s.channelStatusField = INCLUDE_CHANNEL_STATUS_FIELD); + (_j = (_t = parameters.include).channelTypeField) !== null && _j !== void 0 ? _j : (_t.channelTypeField = INCLUDE_CHANNEL_TYPE_FIELD); + (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT$3); + // Remap for backward compatibility. + if (this.parameters.userId) + this.parameters.uuid = this.parameters.userId; + } + operation() { + return RequestOperation$1.PNSetMembershipsOperation; + } + validate() { + const { uuid, channels } = this.parameters; + if (!uuid) + return "'uuid' cannot be empty"; + if (!channels || channels.length === 0) + return 'Channels cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, uuid, } = this.parameters; + return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}/channels`; + } + get queryParameters() { + const { include, page, filter, sort, limit } = this.parameters; + let sorting = ''; + if (typeof sort === 'string') + sorting = sort; + else + sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + const includeFlags = ['channel.status', 'channel.type', 'status']; + if (include.statusField) + includeFlags.push('status'); + if (include.typeField) + includeFlags.push('type'); + if (include.customFields) + includeFlags.push('custom'); + if (include.channelFields) + includeFlags.push('channel'); + if (include.channelStatusField) + includeFlags.push('channel.status'); + if (include.channelTypeField) + includeFlags.push('channel.type'); + if (include.customChannelFields) + includeFlags.push('channel.custom'); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); + } + get headers() { + var _a; + return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); + } + get body() { + const { channels, type } = this.parameters; + return JSON.stringify({ + [`${type}`]: channels.map((channel) => { + if (typeof channel === 'string') { + return { channel: { id: channel } }; + } + else { + return { channel: { id: channel.id }, status: channel.status, type: channel.type, custom: channel.custom }; + } + }), + }); + } + } + + /** + * Get All UUID Metadata REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Channel` custom field should be included by default or not. + */ + const INCLUDE_CUSTOM_FIELDS$6 = false; + /** + * Number of objects to return in response. + */ + const LIMIT$2 = 100; + // endregion + /** + * Get All UUIDs Metadata request. + * + * @internal + */ + class GetAllUUIDMetadataRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c; + var _d; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_d = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_d.customFields = INCLUDE_CUSTOM_FIELDS$6); + (_c = parameters.limit) !== null && _c !== void 0 ? _c : (parameters.limit = LIMIT$2); + } + operation() { + return RequestOperation$1.PNGetAllUUIDMetadataOperation; + } + get path() { + return `/v2/objects/${this.parameters.keySet.subscribeKey}/uuids`; + } + get queryParameters() { + const { include, page, filter, sort, limit } = this.parameters; + let sorting = ''; + if (typeof sort === 'string') + sorting = sort; + else + sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ include: ['status', 'type', ...(include.customFields ? ['custom'] : [])].join(',') }, (include.totalCount !== undefined ? { count: `${include.totalCount}` } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Get Channel Metadata REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Channel` custom field should be included by default or not. + */ + const INCLUDE_CUSTOM_FIELDS$5 = true; + // endregion + /** + * Get Channel Metadata request. + * + * @internal + */ + class GetChannelMetadataRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b; + var _c; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS$5); + } + operation() { + return RequestOperation$1.PNGetChannelMetadataOperation; + } + validate() { + if (!this.parameters.channel) + return 'Channel cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}`; + } + get queryParameters() { + return { + include: ['status', 'type', ...(this.parameters.include.customFields ? ['custom'] : [])].join(','), + }; + } + } + + /** + * Set Channel Metadata REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Channel` custom field should be included by default or not. + */ + const INCLUDE_CUSTOM_FIELDS$4 = true; + // endregion + /** + * Set Channel Metadata request. + * + * @internal + */ + class SetChannelMetadataRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b; + var _c; + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS$4); + } + operation() { + return RequestOperation$1.PNSetChannelMetadataOperation; + } + validate() { + if (!this.parameters.channel) + return 'Channel cannot be empty'; + if (!this.parameters.data) + return 'Data cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json' }); + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}`; + } + get queryParameters() { + return { + include: ['status', 'type', ...(this.parameters.include.customFields ? ['custom'] : [])].join(','), + }; + } + get body() { + return JSON.stringify(this.parameters.data); + } + } + + /** + * Remove UUID Metadata REST API module. + * + * @internal + */ + // endregion + /** + * Remove UUID Metadata request. + * + * @internal + */ + class RemoveUUIDMetadataRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + // Remap for backward compatibility. + if (this.parameters.userId) + this.parameters.uuid = this.parameters.userId; + } + operation() { + return RequestOperation$1.PNRemoveUUIDMetadataOperation; + } + validate() { + if (!this.parameters.uuid) + return "'uuid' cannot be empty"; + } + get path() { + const { keySet: { subscribeKey }, uuid, } = this.parameters; + return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}`; + } + } + + /** + * Get Channel Members REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Member` custom field should be included in response or not. + */ + const INCLUDE_CUSTOM_FIELDS$3 = false; + /** + * Whether member's `status` field should be included in response or not. + */ + const INCLUDE_STATUS$1 = false; + /** + * Whether member's `type` field should be included in response or not. + */ + const INCLUDE_TYPE$1 = false; + /** + * Whether total number of members should be included in response or not. + */ + const INCLUDE_TOTAL_COUNT$1 = false; + /** + * Whether `UUID` fields should be included in response or not. + */ + const INCLUDE_UUID_FIELDS$1 = false; + /** + * Whether `UUID` status field should be included in response or not. + */ + const INCLUDE_UUID_STATUS_FIELD$1 = false; + /** + * Whether `UUID` type field should be included in response or not. + */ + const INCLUDE_UUID_TYPE_FIELD$1 = false; + /** + * Whether `UUID` custom field should be included in response or not. + */ + const INCLUDE_UUID_CUSTOM_FIELDS$1 = false; + /** + * Number of objects to return in response. + */ + const LIMIT$1 = 100; + // endregion + /** + * Get Channel Members request. + * + * @internal + */ + class GetChannelMembersRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + var _l, _m, _o, _p, _q, _r, _s, _t; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$3); + (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT$1); + (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS$1); + (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE$1); + (_f = (_q = parameters.include).UUIDFields) !== null && _f !== void 0 ? _f : (_q.UUIDFields = INCLUDE_UUID_FIELDS$1); + (_g = (_r = parameters.include).customUUIDFields) !== null && _g !== void 0 ? _g : (_r.customUUIDFields = INCLUDE_UUID_CUSTOM_FIELDS$1); + (_h = (_s = parameters.include).UUIDStatusField) !== null && _h !== void 0 ? _h : (_s.UUIDStatusField = INCLUDE_UUID_STATUS_FIELD$1); + (_j = (_t = parameters.include).UUIDTypeField) !== null && _j !== void 0 ? _j : (_t.UUIDTypeField = INCLUDE_UUID_TYPE_FIELD$1); + (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT$1); + } + operation() { + return RequestOperation$1.PNSetMembersOperation; + } + validate() { + if (!this.parameters.channel) + return 'Channel cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}/uuids`; + } + get queryParameters() { + const { include, page, filter, sort, limit } = this.parameters; + let sorting = ''; + if (typeof sort === 'string') + sorting = sort; + else + sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + const includeFlags = []; + if (include.statusField) + includeFlags.push('status'); + if (include.typeField) + includeFlags.push('type'); + if (include.customFields) + includeFlags.push('custom'); + if (include.UUIDFields) + includeFlags.push('uuid'); + if (include.UUIDStatusField) + includeFlags.push('uuid.status'); + if (include.UUIDTypeField) + includeFlags.push('uuid.type'); + if (include.customUUIDFields) + includeFlags.push('uuid.custom'); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set Channel Members REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Member` custom field should be included in response or not. + */ + const INCLUDE_CUSTOM_FIELDS$2 = false; + /** + * Whether member's `status` field should be included in response or not. + */ + const INCLUDE_STATUS = false; + /** + * Whether member's `type` field should be included in response or not. + */ + const INCLUDE_TYPE = false; + /** + * Whether total number of members should be included in response or not. + */ + const INCLUDE_TOTAL_COUNT = false; + /** + * Whether `UUID` fields should be included in response or not. + */ + const INCLUDE_UUID_FIELDS = false; + /** + * Whether `UUID` status field should be included in response or not. + */ + const INCLUDE_UUID_STATUS_FIELD = false; + /** + * Whether `UUID` type field should be included in response or not. + */ + const INCLUDE_UUID_TYPE_FIELD = false; + /** + * Whether `UUID` custom field should be included in response or not. + */ + const INCLUDE_UUID_CUSTOM_FIELDS = false; + /** + * Number of objects to return in response. + */ + const LIMIT = 100; + // endregion + /** + * Set Channel Members request. + * + * @internal + */ + class SetChannelMembersRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + var _l, _m, _o, _p, _q, _r, _s, _t; + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$2); + (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT); + (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS); + (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE); + (_f = (_q = parameters.include).UUIDFields) !== null && _f !== void 0 ? _f : (_q.UUIDFields = INCLUDE_UUID_FIELDS); + (_g = (_r = parameters.include).customUUIDFields) !== null && _g !== void 0 ? _g : (_r.customUUIDFields = INCLUDE_UUID_CUSTOM_FIELDS); + (_h = (_s = parameters.include).UUIDStatusField) !== null && _h !== void 0 ? _h : (_s.UUIDStatusField = INCLUDE_UUID_STATUS_FIELD); + (_j = (_t = parameters.include).UUIDTypeField) !== null && _j !== void 0 ? _j : (_t.UUIDTypeField = INCLUDE_UUID_TYPE_FIELD); + (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT); + } + operation() { + return RequestOperation$1.PNSetMembersOperation; + } + validate() { + const { channel, uuids } = this.parameters; + if (!channel) + return 'Channel cannot be empty'; + if (!uuids || uuids.length === 0) + return 'UUIDs cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}/uuids`; + } + get queryParameters() { + const { include, page, filter, sort, limit } = this.parameters; + let sorting = ''; + if (typeof sort === 'string') + sorting = sort; + else + sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + const includeFlags = ['uuid.status', 'uuid.type', 'type']; + if (include.statusField) + includeFlags.push('status'); + if (include.typeField) + includeFlags.push('type'); + if (include.customFields) + includeFlags.push('custom'); + if (include.UUIDFields) + includeFlags.push('uuid'); + if (include.UUIDStatusField) + includeFlags.push('uuid.status'); + if (include.UUIDTypeField) + includeFlags.push('uuid.type'); + if (include.customUUIDFields) + includeFlags.push('uuid.custom'); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); + } + get headers() { + var _a; + return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); + } + get body() { + const { uuids, type } = this.parameters; + return JSON.stringify({ + [`${type}`]: uuids.map((uuid) => { + if (typeof uuid === 'string') { + return { uuid: { id: uuid } }; + } + else { + return { uuid: { id: uuid.id }, status: uuid.status, type: uuid.type, custom: uuid.custom }; + } + }), + }); + } + } + + /** + * Get UUID Metadata REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether UUID custom field should be included by default or not. + */ + const INCLUDE_CUSTOM_FIELDS$1 = true; + // endregion + /** + * Get UUID Metadata request. + * + * @internal + */ + class GetUUIDMetadataRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b; + var _c; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS$1); + // Remap for backward compatibility. + if (this.parameters.userId) + this.parameters.uuid = this.parameters.userId; + } + operation() { + return RequestOperation$1.PNGetUUIDMetadataOperation; + } + validate() { + if (!this.parameters.uuid) + return "'uuid' cannot be empty"; + } + get path() { + const { keySet: { subscribeKey }, uuid, } = this.parameters; + return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}`; + } + get queryParameters() { + const { include } = this.parameters; + return { include: ['status', 'type', ...(include.customFields ? ['custom'] : [])].join(',') }; + } + } + + /** + * Set UUID Metadata REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Channel` custom field should be included by default or not. + */ + const INCLUDE_CUSTOM_FIELDS = true; + // endregion + /** + * Set UUID Metadata request. + * + * @internal + */ + class SetUUIDMetadataRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b; + var _c; + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS); + // Remap for backward compatibility. + if (this.parameters.userId) + this.parameters.uuid = this.parameters.userId; + } + operation() { + return RequestOperation$1.PNSetUUIDMetadataOperation; + } + validate() { + if (!this.parameters.uuid) + return "'uuid' cannot be empty"; + if (!this.parameters.data) + return 'Data cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json' }); + } + get path() { + const { keySet: { subscribeKey }, uuid, } = this.parameters; + return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}`; + } + get queryParameters() { + return { + include: ['status', 'type', ...(this.parameters.include.customFields ? ['custom'] : [])].join(','), + }; + } + get body() { + return JSON.stringify(this.parameters.data); + } + } + + /** + * PubNub Objects API module. + */ + /** + * PubNub App Context API interface. + */ + class PubNubObjects { + /** + * Create app context API access object. + * + * @param configuration - Extended PubNub client configuration object. + * @param sendRequest - Function which should be used to send REST API calls. + * + * @internal + */ + constructor(configuration, + /* eslint-disable @typescript-eslint/no-explicit-any */ + sendRequest) { + this.keySet = configuration.keySet; + this.configuration = configuration; + this.sendRequest = sendRequest; + } + /** + * Get registered loggers' manager. + * + * @returns Registered loggers' manager. + * + * @internal + */ + get logger() { + return this.configuration.logger(); + } + /** + * Fetch a paginated list of UUID Metadata objects. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all UUID metadata response or `void` in case if `callback` provided. + */ + getAllUUIDMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, + details: `Get all UUID metadata objects with parameters:`, + })); + return this._getAllUUIDMetadata(parametersOrCallback, callback); + }); + } + /** + * Fetch a paginated list of UUID Metadata objects. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all UUID metadata response or `void` in case if `callback` provided. + * + * @internal + */ + _getAllUUIDMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + // Get user request parameters. + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + const request = new GetAllUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get all UUID metadata success. Received ${response.totalCount} UUID metadata objects.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Fetch a specific UUID Metadata object. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get UUID metadata response or `void` in case if `callback` provided. + */ + getUUIDMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' + ? { uuid: this.configuration.userId } + : parametersOrCallback, + details: `Get ${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} UUID metadata object with parameters:`, + })); + return this._getUUIDMetadata(parametersOrCallback, callback); + }); + } + /** + * Fetch a specific UUID Metadata object. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get UUID metadata response or `void` in case if `callback` provided. + * + * @internal + */ + _getUUIDMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + // Get user request parameters. + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + if (parameters.userId) { + this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); + parameters.uuid = parameters.userId; + } + (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); + const request = new GetUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get UUID metadata object success. Received '${parameters.uuid}' UUID metadata object.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Update a specific UUID Metadata object. + * + * @param parameters - Request configuration parameters. Will set UUID metadata for currently + * configured PubNub client `uuid` if not set. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set UUID metadata response or `void` in case if `callback` provided. + */ + setUUIDMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Set UUID metadata object with parameters:`, + })); + return this._setUUIDMetadata(parameters, callback); + }); + } + /** + * Update a specific UUID Metadata object. + * + * @internal + * + * @param parameters - Request configuration parameters. Will set UUID metadata for currently + * configured PubNub client `uuid` if not set. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set UUID metadata response or `void` in case if `callback` provided. + */ + _setUUIDMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + if (parameters.userId) { + this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); + parameters.uuid = parameters.userId; + } + (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); + const request = new SetUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Set UUID metadata object success. Updated '${parameters.uuid}' UUID metadata object.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Remove a specific UUID Metadata object. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous UUID metadata remove response or `void` in case if `callback` provided. + */ + removeUUIDMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' + ? { uuid: this.configuration.userId } + : parametersOrCallback, + details: `Remove${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} UUID metadata object with parameters:`, + })); + return this._removeUUIDMetadata(parametersOrCallback, callback); + }); + } + /** + * Remove a specific UUID Metadata object. + * + * @internal + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous UUID metadata remove response or `void` in case if `callback` provided. + */ + _removeUUIDMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + // Get user request parameters. + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + if (parameters.userId) { + this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); + parameters.uuid = parameters.userId; + } + (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); + const request = new RemoveUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Remove UUID metadata object success. Removed '${parameters.uuid}' UUID metadata object.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Fetch a paginated list of Channel Metadata objects. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all Channel metadata response or `void` in case if `callback` + * provided. + */ + getAllChannelMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, + details: `Get all Channel metadata objects with parameters:`, + })); + return this._getAllChannelMetadata(parametersOrCallback, callback); + }); + } + /** + * Fetch a paginated list of Channel Metadata objects. + * + * @internal + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all Channel metadata response or `void` in case if `callback` + * provided. + */ + _getAllChannelMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + // Get user request parameters. + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + const request = new GetAllChannelsMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get all Channel metadata objects success. Received ${response.totalCount} Channel metadata objects.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Fetch Channel Metadata object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get Channel metadata response or `void` in case if `callback` provided. + */ + getChannelMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Get Channel metadata object with parameters:`, + })); + return this._getChannelMetadata(parameters, callback); + }); + } + /** + * Fetch Channel Metadata object. + * + * @internal + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get Channel metadata response or `void` in case if `callback` provided. + */ + _getChannelMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + const request = new GetChannelMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get Channel metadata object success. Received '${parameters.channel}' Channel metadata object.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Update specific Channel Metadata object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set Channel metadata response or `void` in case if `callback` provided. + */ + setChannelMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Set Channel metadata object with parameters:`, + })); + return this._setChannelMetadata(parameters, callback); + }); + } + /** + * Update specific Channel Metadata object. + * + * @internal + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set Channel metadata response or `void` in case if `callback` provided. + */ + _setChannelMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + const request = new SetChannelMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Set Channel metadata object success. Updated '${parameters.channel}' Channel metadata object.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Remove a specific Channel Metadata object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous Channel metadata remove response or `void` in case if `callback` + * provided. + */ + removeChannelMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove Channel metadata object with parameters:`, + })); + return this._removeChannelMetadata(parameters, callback); + }); + } + /** + * Remove a specific Channel Metadata object. + * + * @internal + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous Channel metadata remove response or `void` in case if `callback` + * provided. + */ + _removeChannelMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + const request = new RemoveChannelMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Remove Channel metadata object success. Removed '${parameters.channel}' Channel metadata object.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Fetch a paginated list of Channel Member objects. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get Channel Members response or `void` in case if `callback` provided. + */ + getChannelMembers(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Get channel members with parameters:`, + })); + const request = new GetChannelMembersRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get channel members success. Received ${response.totalCount} channel members.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Update specific Channel Members list. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update Channel members list response or `void` in case if `callback` + * provided. + */ + setChannelMembers(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Set channel members with parameters:`, + })); + const request = new SetChannelMembersRequest(Object.assign(Object.assign({}, parameters), { type: 'set', keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Set channel members success. There are ${response.totalCount} channel members now.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Remove Members from the Channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous Channel Members remove response or `void` in case if `callback` provided. + */ + removeChannelMembers(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove channel members with parameters:`, + })); + const request = new SetChannelMembersRequest(Object.assign(Object.assign({}, parameters), { type: 'delete', keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Remove channel members success. There are ${response.totalCount} channel members now.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Fetch a specific UUID Memberships list. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get UUID Memberships response or `void` in case if `callback` provided. + */ + getMemberships(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + // Get user request parameters. + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + if (parameters.userId) { + this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); + parameters.uuid = parameters.userId; + } + (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Get memberships with parameters:`, + })); + const request = new GetUUIDMembershipsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get memberships success. Received ${response.totalCount} memberships.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Update specific UUID Memberships list. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update UUID Memberships list response or `void` in case if `callback` + * provided. + */ + setMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + if (parameters.userId) { + this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); + parameters.uuid = parameters.userId; + } + (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Set memberships with parameters:`, + })); + const request = new SetUUIDMembershipsRequest(Object.assign(Object.assign({}, parameters), { type: 'set', keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Set memberships success. There are ${response.totalCount} memberships now.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Remove a specific UUID Memberships. + * + * @param parameters - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous UUID Memberships remove response or `void` in case if `callback` + * provided. + */ + removeMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + if (parameters.userId) { + this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); + parameters.uuid = parameters.userId; + } + (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove memberships with parameters:`, + })); + const request = new SetUUIDMembershipsRequest(Object.assign(Object.assign({}, parameters), { type: 'delete', keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Remove memberships success. There are ${response.totalCount} memberships now.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + // endregion + // endregion + // -------------------------------------------------------- + // --------------------- Deprecated API ------------------- + // -------------------------------------------------------- + // region Deprecated + /** + * Fetch paginated list of specific Space members or specific User memberships. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get specific Space members or specific User memberships response. + * + * @deprecated Use {@link PubNubObjects#getChannelMembers getChannelMembers} or + * {@link PubNubObjects#getMemberships getMemberships} methods instead. + */ + fetchMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b; + this.logger.warn('PubNub', "'fetchMemberships' is deprecated. Use 'pubnub.objects.getChannelMembers' or 'pubnub.objects.getMemberships'" + + ' instead.'); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Fetch memberships with parameters:`, + })); + if ('spaceId' in parameters) { + const spaceParameters = parameters; + const mappedParameters = { + channel: (_a = spaceParameters.spaceId) !== null && _a !== void 0 ? _a : spaceParameters.channel, + filter: spaceParameters.filter, + limit: spaceParameters.limit, + page: spaceParameters.page, + include: Object.assign({}, spaceParameters.include), + sort: spaceParameters.sort + ? Object.fromEntries(Object.entries(spaceParameters.sort).map(([key, value]) => [key.replace('user', 'uuid'), value])) + : undefined, + }; + // Map Members object to the older version. + const mapMembers = (response) => ({ + status: response.status, + data: response.data.map((members) => ({ + user: members.uuid, + custom: members.custom, + updated: members.updated, + eTag: members.eTag, + })), + totalCount: response.totalCount, + next: response.next, + prev: response.prev, + }); + if (callback) + return this.getChannelMembers(mappedParameters, (status, result) => { + callback(status, result ? mapMembers(result) : result); + }); + return this.getChannelMembers(mappedParameters).then(mapMembers); + } + const userParameters = parameters; + const mappedParameters = { + uuid: (_b = userParameters.userId) !== null && _b !== void 0 ? _b : userParameters.uuid, + filter: userParameters.filter, + limit: userParameters.limit, + page: userParameters.page, + include: Object.assign({}, userParameters.include), + sort: userParameters.sort + ? Object.fromEntries(Object.entries(userParameters.sort).map(([key, value]) => [key.replace('space', 'channel'), value])) + : undefined, + }; + // Map Memberships object to the older version. + const mapMemberships = (response) => ({ + status: response.status, + data: response.data.map((membership) => ({ + space: membership.channel, + custom: membership.custom, + updated: membership.updated, + eTag: membership.eTag, + })), + totalCount: response.totalCount, + next: response.next, + prev: response.prev, + }); + if (callback) + return this.getMemberships(mappedParameters, (status, result) => { + callback(status, result ? mapMemberships(result) : result); + }); + return this.getMemberships(mappedParameters).then(mapMemberships); + }); + } + /** + * Add members to specific Space or memberships specific User. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous add members to specific Space or memberships specific User response or + * `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubObjects#setChannelMembers setChannelMembers} or + * {@link PubNubObjects#setMemberships setMemberships} methods instead. + */ + addMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b, _c, _d, _e, _f; + this.logger.warn('PubNub', "'addMemberships' is deprecated. Use 'pubnub.objects.setChannelMembers' or 'pubnub.objects.setMemberships'" + + ' instead.'); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Add memberships with parameters:`, + })); + if ('spaceId' in parameters) { + const spaceParameters = parameters; + const mappedParameters = { + channel: (_a = spaceParameters.spaceId) !== null && _a !== void 0 ? _a : spaceParameters.channel, + uuids: (_c = (_b = spaceParameters.users) === null || _b === void 0 ? void 0 : _b.map((user) => { + if (typeof user === 'string') + return user; + return { id: user.userId, custom: user.custom }; + })) !== null && _c !== void 0 ? _c : spaceParameters.uuids, + limit: 0, + }; + if (callback) + return this.setChannelMembers(mappedParameters, callback); + return this.setChannelMembers(mappedParameters); + } + const userParameters = parameters; + const mappedParameters = { + uuid: (_d = userParameters.userId) !== null && _d !== void 0 ? _d : userParameters.uuid, + channels: (_f = (_e = userParameters.spaces) === null || _e === void 0 ? void 0 : _e.map((space) => { + if (typeof space === 'string') + return space; + return { + id: space.spaceId, + custom: space.custom, + }; + })) !== null && _f !== void 0 ? _f : userParameters.channels, + limit: 0, + }; + if (callback) + return this.setMemberships(mappedParameters, callback); + return this.setMemberships(mappedParameters); + }); + } + } + + /** + * Create User REST API module. + * + * @internal + */ + // endregion + /** + * Create User request. + * + * @internal + */ + class CreateUserRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNCreateDataSyncUserOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.data) + return 'User data cannot be empty'; + if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) + return 'Entity class version cannot be empty'; + } + get headers() { + var _a; + const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.user+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/users`; + } + get body() { + const { id, class: entityClass, classLevel, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), (entityClass !== undefined ? { entityClass } : {})), { entityClassVersion: data.classVersion }), (classLevel !== undefined ? { entityClassLevel: classLevel } : {})), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * PubNub DataSync API type definitions. + * + * Types for Entity Class CRUD operations. + */ + /** + * Serialize a {@link DataSyncSort} into the query value the service expects. + * + * A raw string is passed through unchanged. An object is turned into a list of `field:order` + * entries (a `null` direction emits the bare field name, letting the service apply its default + * ascending order). Mirrors the App Context `getAllChannelMetadata` sort handling. + * + * @internal + */ + function serializeDataSyncSort(sort) { + if (typeof sort === 'string') + return sort; + return Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + } + /** + * Convert user-friendly patch input to JSON Patch operations (request format). + * + * `path`/`from` are passed through verbatim — callers supply the exact RFC 6901 pointer. Do not + * reintroduce dot-notation translation here: splitting on `.` makes stored field names that + * contain a `.` unaddressable. + * + * - Each key in `add` becomes an "add" operation. + * - Each key in `replace` becomes a "replace" operation. + * - Each entry in `remove` becomes a "remove" operation. + * - Each `{ from, path }` pair in `move` becomes a "move" operation. + * - Each `{ from, path }` pair in `copy` becomes a "copy" operation. + * - Each key in `test` becomes a "test" operation. + * + * @internal + */ + function toJsonPatchOperations(input) { + const { add, replace, remove, move, copy, test } = input; + const ops = []; + if (add) { + for (const [path, value] of Object.entries(add)) { + ops.push({ op: 'add', path, value }); + } + } + if (replace) { + for (const [path, value] of Object.entries(replace)) { + ops.push({ op: 'replace', path, value }); + } + } + if (remove) { + for (const path of remove) { + ops.push({ op: 'remove', path }); + } + } + if (move) { + for (const { from, path } of move) { + ops.push({ op: 'move', from, path }); + } + } + if (copy) { + for (const { from, path } of copy) { + ops.push({ op: 'copy', from, path }); + } + } + if (test) { + for (const [path, value] of Object.entries(test)) { + ops.push({ op: 'test', path, value }); + } + } + return ops; + } + + /** + * Get Users REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Default number of items per page. + */ + const DEFAULT_LIMIT$4 = 20; + // endregion + /** + * Get Users request. + * + * @internal + */ + class GetUsersRequest extends AbstractRequest { + constructor(parameters) { + var _a; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$4); + } + operation() { + return RequestOperation$1.PNGetDataSyncUsersOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + get path() { + return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/users`; + } + get queryParameters() { + const { class: entityClass, classVersion, classLevel, cursor, limit, filter, filterFast, sort } = this.parameters; + const sorting = serializeDataSyncSort(sort); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (entityClass ? { entity_class: entityClass } : {})), (classVersion !== undefined ? { entity_class_version: `${classVersion}` } : {})), (classLevel ? { entity_class_level: classLevel } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set User REST API module. + * + * Full resource replacement via PUT. + * + * @internal + */ + // endregion + /** + * Set User request. + * + * @internal + */ + class SetUserRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PUT }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSetDataSyncUserOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'User id cannot be empty'; + if (!this.parameters.data) + return 'User data cannot be empty'; + if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) + return 'Entity class version cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.user+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; + } + get body() { + const { data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign({ entityClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Remove User REST API module. + * + * @internal + */ + // endregion + /** + * Remove User request. + * + * @internal + */ + class RemoveUserRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveDataSyncUserOperation; + } + validate() { + if (!this.parameters.id) + return 'User id cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.keys(headers).length > 0 ? headers : undefined; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { status: response.status }; + }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; + } + } + + /** + * Update User REST API module. + * + * Partial update via JSON Patch (RFC 6902). + * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` + * (JSON Pointer paths), and `move`/`copy` (JSON Pointer `{ from, path }` pairs) + * and converts them to JSON Patch operations. Paths are sent verbatim. + * + * @internal + */ + // endregion + /** + * Update User request. + * + * @internal + */ + class UpdateUserRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNUpdateDataSyncUserOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'User id cannot be empty'; + const { add, replace, remove, move, copy, test } = this.parameters; + const hasAdd = add && Object.keys(add).length > 0; + const hasReplace = replace && Object.keys(replace).length > 0; + const hasRemove = remove && remove.length > 0; + const hasMove = move && move.length > 0; + const hasCopy = copy && copy.length > 0; + const hasTest = test && Object.keys(test).length > 0; + if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) + return 'At least one of add, replace, remove, move, copy, or test must be provided'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; + } + get body() { + const { add, replace, remove, move, copy, test } = this.parameters; + const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); + return JSON.stringify(jsonPatchOps); + } + } + + /** + * Get User REST API module. + * + * @internal + */ + // endregion + /** + * Get User request. + * + * @internal + */ + class GetUserRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetDataSyncUserOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'User id cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; + } + } + + /** + * Create Channel REST API module. + * + * @internal + */ + // endregion + /** + * Create Channel request. + * + * @internal + */ + class CreateChannelRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNCreateDataSyncChannelOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.data) + return 'Channel data cannot be empty'; + if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) + return 'Entity class version cannot be empty'; + } + get headers() { + var _a; + const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.channel+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/channels`; + } + get body() { + const { id, class: entityClass, classLevel, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), (entityClass !== undefined ? { entityClass } : {})), { entityClassVersion: data.classVersion }), (classLevel !== undefined ? { entityClassLevel: classLevel } : {})), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Get Channels REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Default number of items per page. + */ + const DEFAULT_LIMIT$3 = 20; + // endregion + /** + * Get Channels request. + * + * @internal + */ + class GetChannelsRequest extends AbstractRequest { + constructor(parameters) { + var _a; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$3); + } + operation() { + return RequestOperation$1.PNGetDataSyncChannelsOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + get path() { + return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/channels`; + } + get queryParameters() { + const { class: entityClass, classVersion, classLevel, cursor, limit, filter, filterFast, sort } = this.parameters; + const sorting = serializeDataSyncSort(sort); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (entityClass ? { entity_class: entityClass } : {})), (classVersion !== undefined ? { entity_class_version: `${classVersion}` } : {})), (classLevel ? { entity_class_level: classLevel } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set Channel REST API module. + * + * Full resource replacement via PUT. + * + * @internal + */ + // endregion + /** + * Set Channel request. + * + * @internal + */ + class SetChannelRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PUT }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSetDataSyncChannelOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Channel id cannot be empty'; + if (!this.parameters.data) + return 'Channel data cannot be empty'; + if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) + return 'Entity class version cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.channel+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; + } + get body() { + const { data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign({ entityClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Remove Channel REST API module. + * + * @internal + */ + // endregion + /** + * Remove Channel request. + * + * @internal + */ + class RemoveChannelRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveDataSyncChannelOperation; + } + validate() { + if (!this.parameters.id) + return 'Channel id cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.keys(headers).length > 0 ? headers : undefined; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { status: response.status }; + }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; + } + } + + /** + * Update Channel REST API module. + * + * Partial update via JSON Patch (RFC 6902). + * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` + * (JSON Pointer paths), and `move`/`copy` (JSON Pointer from → path pairs), + * converting them to JSON Patch operations. Paths are sent verbatim. + * + * @internal + */ + // endregion + /** + * Update Channel request. + * + * @internal + */ + class UpdateChannelRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNUpdateDataSyncChannelOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Channel id cannot be empty'; + const { add, replace, remove, move, copy, test } = this.parameters; + const hasAdd = add && Object.keys(add).length > 0; + const hasReplace = replace && Object.keys(replace).length > 0; + const hasRemove = remove && remove.length > 0; + const hasMove = move && move.length > 0; + const hasCopy = copy && copy.length > 0; + const hasTest = test && Object.keys(test).length > 0; + if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) + return 'At least one of add, replace, remove, move, copy, or test must be provided'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; + } + get body() { + const { add, replace, remove, move, copy, test } = this.parameters; + const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); + return JSON.stringify(jsonPatchOps); + } + } + + /** + * Get Channel REST API module. + * + * @internal + */ + // endregion + /** + * Get Channel request. + * + * @internal + */ + class GetChannelRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetDataSyncChannelOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Channel id cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; + } + } + + /** + * Create Membership REST API module. + * + * @internal + */ + // endregion + /** + * Create Membership request. + * + * @internal + */ + class CreateMembershipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNCreateDataSyncMembershipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.userId) + return 'User id cannot be empty'; + if (!this.parameters.channelId) + return 'Channel id cannot be empty'; + if (!this.parameters.data) + return 'Membership data cannot be empty'; + if (!this.parameters.data.classVersion) + return 'Membership class version cannot be empty'; + } + get headers() { + var _a; + const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.membership+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/memberships`; + } + get body() { + const { id, userId, channelId, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), { userId, + channelId, relationshipClassVersion: data.classVersion }), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Get Memberships REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Default number of items per page. + */ + const DEFAULT_LIMIT$2 = 20; + // endregion + /** + * Get Memberships request. + * + * @internal + */ + class GetMembershipsRequest extends AbstractRequest { + constructor(parameters) { + var _a; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$2); + } + operation() { + return RequestOperation$1.PNGetDataSyncMembershipsOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + get path() { + return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/memberships`; + } + get queryParameters() { + const { userId, channelId, classVersion, cursor, limit, filter, filterFast, sort } = this.parameters; + const sorting = serializeDataSyncSort(sort); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (userId ? { user_id: userId } : {})), (channelId ? { channel_id: channelId } : {})), (classVersion !== undefined ? { relationship_class_version: `${classVersion}` } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set Membership REST API module. + * + * Full resource replacement via PUT. + * + * @internal + */ + // endregion + /** + * Set Membership request. + * + * @internal + */ + class SetMembershipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PUT }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSetDataSyncMembershipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Membership id cannot be empty'; + if (!this.parameters.userId) + return 'User id cannot be empty'; + if (!this.parameters.channelId) + return 'Channel id cannot be empty'; + if (!this.parameters.data) + return 'Membership data cannot be empty'; + if (!this.parameters.data.classVersion) + return 'Membership class version cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.membership+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; + } + get body() { + const { userId, channelId, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign({ userId, + channelId, relationshipClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Remove Membership REST API module. + * + * @internal + */ + // endregion + /** + * Remove Membership request. + * + * @internal + */ + class RemoveMembershipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveDataSyncMembershipOperation; + } + validate() { + if (!this.parameters.id) + return 'Membership id cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.keys(headers).length > 0 ? headers : undefined; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { status: response.status }; + }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; + } + } + + /** + * Update Membership REST API module. + * + * Partial update via JSON Patch (RFC 6902). + * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` + * (JSON Pointer paths), and `move`/`copy` (JSON Pointer `{ from, path }` pairs) + * and converts them to JSON Patch operations. Paths are sent verbatim. + * + * @internal + */ + // endregion + /** + * Update Membership request. + * + * @internal + */ + class UpdateMembershipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNUpdateDataSyncMembershipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Membership id cannot be empty'; + const { add, replace, remove, move, copy, test } = this.parameters; + const hasAdd = add && Object.keys(add).length > 0; + const hasReplace = replace && Object.keys(replace).length > 0; + const hasRemove = remove && remove.length > 0; + const hasMove = move && move.length > 0; + const hasCopy = copy && copy.length > 0; + const hasTest = test && Object.keys(test).length > 0; + if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) + return 'At least one of add, replace, remove, move, copy, or test must be provided'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; + } + get body() { + const { add, replace, remove, move, copy, test } = this.parameters; + const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); + return JSON.stringify(jsonPatchOps); + } + } + + /** + * Get Membership REST API module. + * + * @internal + */ + // endregion + /** + * Get Membership request. + * + * @internal + */ + class GetMembershipRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetDataSyncMembershipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Membership id cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; + } + } + + /** + * Create Relationship REST API module. + * + * @internal + */ + // endregion + /** + * Create Relationship request. + * + * @internal + */ + class CreateRelationshipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNCreateDataSyncRelationshipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.entityAId) + return 'Entity A id cannot be empty'; + if (!this.parameters.entityBId) + return 'Entity B id cannot be empty'; + if (!this.parameters.class) + return 'Relationship class cannot be empty'; + if (!this.parameters.data) + return 'Relationship data cannot be empty'; + if (!this.parameters.data.classVersion) + return 'Relationship class version cannot be empty'; + } + get headers() { + var _a; + const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.relationship+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/relationships`; + } + get body() { + const { id, class: relationshipClass, entityAId, entityBId, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), { entityAId, + entityBId, + relationshipClass, relationshipClassVersion: data.classVersion }), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Get Relationships REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Default number of items per page. + */ + const DEFAULT_LIMIT$1 = 20; + // endregion + /** + * Get Relationships request. + * + * @internal + */ + class GetRelationshipsRequest extends AbstractRequest { + constructor(parameters) { + var _a; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$1); + } + operation() { + return RequestOperation$1.PNGetDataSyncRelationshipsOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.class) + return 'Relationship class cannot be empty'; + } + get path() { + return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/relationships`; + } + get queryParameters() { + const { class: relationshipClass, classVersion, entityAId, entityBId, cursor, limit, filter, filterFast, sort, } = this.parameters; + const sorting = serializeDataSyncSort(sort); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ relationship_class: relationshipClass }, (classVersion !== undefined ? { relationship_class_version: `${classVersion}` } : {})), (entityAId ? { entity_a_id: entityAId } : {})), (entityBId ? { entity_b_id: entityBId } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set Relationship REST API module. + * + * Full resource replacement via PUT. + * + * @internal + */ + // endregion + /** + * Set Relationship request. + * + * @internal + */ + class SetRelationshipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PUT }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSetDataSyncRelationshipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Relationship id cannot be empty'; + if (!this.parameters.entityAId) + return 'Entity A id cannot be empty'; + if (!this.parameters.entityBId) + return 'Entity B id cannot be empty'; + if (!this.parameters.data) + return 'Relationship data cannot be empty'; + if (!this.parameters.data.classVersion) + return 'Relationship class version cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.relationship+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; + } + get body() { + const { entityAId, entityBId, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign({ entityAId, + entityBId, relationshipClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Remove Relationship REST API module. + * + * @internal + */ + // endregion + /** + * Remove Relationship request. + * + * @internal + */ + class RemoveRelationshipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveDataSyncRelationshipOperation; + } + validate() { + if (!this.parameters.id) + return 'Relationship id cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.keys(headers).length > 0 ? headers : undefined; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { status: response.status }; + }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; + } + } + + /** + * Update Relationship REST API module. + * + * Partial update via JSON Patch (RFC 6902). + * Accepts `add` and `replace` (JSON Pointer key-value pairs), `remove` + * (JSON Pointer paths), `move` and `copy` (`{ from, path }` JSON Pointer pairs), + * and `test` (JSON Pointer key-value pairs) and converts them to JSON Patch + * operations. Paths are sent verbatim. + * + * @internal + */ + // endregion + /** + * Update Relationship request. + * + * @internal + */ + class UpdateRelationshipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNUpdateDataSyncRelationshipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Relationship id cannot be empty'; + const { add, replace, remove, move, copy, test } = this.parameters; + const hasAdd = add && Object.keys(add).length > 0; + const hasReplace = replace && Object.keys(replace).length > 0; + const hasRemove = remove && remove.length > 0; + const hasMove = move && move.length > 0; + const hasCopy = copy && copy.length > 0; + const hasTest = test && Object.keys(test).length > 0; + if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) + return 'At least one of add, replace, remove, move, copy, or test must be provided'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; + } + get body() { + const { add, replace, remove, move, copy, test } = this.parameters; + const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); + return JSON.stringify(jsonPatchOps); + } + } + + /** + * Get Relationship REST API module. + * + * @internal + */ + // endregion + /** + * Get Relationship request. + * + * @internal + */ + class GetRelationshipRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetDataSyncRelationshipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Relationship id cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; + } + } + + /** + * Create Entity REST API module. + * + * @internal + */ + // endregion + /** + * Create Entity request. + * + * @internal + */ + class CreateEntityRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNCreateDataSyncEntityOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.class) + return 'Entity class cannot be empty'; + if (!this.parameters.data) + return 'Entity data cannot be empty'; + if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) + return 'Entity class version cannot be empty'; + } + get headers() { + var _a; + const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.entity+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/entities`; + } + get body() { + const { id, class: entityClass, classLevel, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), { entityClass, entityClassVersion: data.classVersion }), (classLevel !== undefined ? { entityClassLevel: classLevel } : {})), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Get Entities REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Default number of items per page. + */ + const DEFAULT_LIMIT = 20; + // endregion + /** + * Get Entities request. + * + * @internal + */ + class GetEntitiesRequest extends AbstractRequest { + constructor(parameters) { + var _a; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT); + } + operation() { + return RequestOperation$1.PNGetDataSyncEntitiesOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.class) + return 'Entity class cannot be empty'; + } + get path() { + return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/entities`; + } + get queryParameters() { + const { class: entityClass, classVersion, classLevel, cursor, limit, filter, filterFast, sort } = this.parameters; + const sorting = serializeDataSyncSort(sort); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ entity_class: entityClass }, (classVersion !== undefined ? { entity_class_version: `${classVersion}` } : {})), (classLevel ? { entity_class_level: classLevel } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set Entity REST API module. + * + * Full resource replacement via PUT. + * Note: `entityClass` is immutable and cannot be changed via update. + * + * @internal + */ + // endregion + /** + * Set Entity request. + * + * @internal + */ + class SetEntityRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PUT }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSetDataSyncEntityOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Entity id cannot be empty'; + if (!this.parameters.data) + return 'Entity data cannot be empty'; + if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) + return 'Entity class version cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.entity+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; + } + get body() { + const { data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign({ entityClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Remove Entity REST API module. + * + * @internal + */ + // endregion + /** + * Remove Entity request. + * + * @internal + */ + class RemoveEntityRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveDataSyncEntityOperation; + } + validate() { + if (!this.parameters.id) + return 'Entity id cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.keys(headers).length > 0 ? headers : undefined; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { status: response.status }; + }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; + } + } + + /** + * Update Entity REST API module. + * + * Partial update via JSON Patch (RFC 6902). + * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` + * (JSON Pointer paths), and `move`/`copy` (JSON Pointer from/path pairs), and + * converts them to JSON Patch operations. Paths are sent verbatim. + * + * @internal + */ + // endregion + /** + * Update Entity request. + * + * @internal + */ + class UpdateEntityRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNUpdateDataSyncEntityOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Entity id cannot be empty'; + const { add, replace, remove, move, copy, test } = this.parameters; + const hasAdd = add && Object.keys(add).length > 0; + const hasReplace = replace && Object.keys(replace).length > 0; + const hasRemove = remove && remove.length > 0; + const hasMove = move && move.length > 0; + const hasCopy = copy && copy.length > 0; + const hasTest = test && Object.keys(test).length > 0; + if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) + return 'At least one of add, replace, remove, move, copy, or test must be provided'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; + } + get body() { + const { add, replace, remove, move, copy, test } = this.parameters; + const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); + return JSON.stringify(jsonPatchOps); + } + } + + /** + * Get Entity REST API module. + * + * @internal + */ + // endregion + /** + * Get Entity request. + * + * @internal + */ + class GetEntityRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetDataSyncEntityOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Entity id cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; + } + } + + /** + * PubNub DataSync API module. + */ + /** + * PubNub DataSync API interface. + */ + class PubNubDataSync { + /** + * Create DataSync API access object. + * + * @param configuration - Extended PubNub client configuration object. + * @param sendRequest - Function which should be used to send REST API calls. + * + * @internal + */ + constructor(configuration, + /* eslint-disable @typescript-eslint/no-explicit-any */ + sendRequest) { + this.keySet = configuration.keySet; + this.configuration = configuration; + this.sendRequest = sendRequest; + } + /** + * Get registered loggers' manager. + * + * @returns Registered loggers' manager. + * + * @internal + */ + get logger() { + return this.configuration.logger(); + } + /** + * Create a new Entity. + * + * To change a field later with `updateEntity`, address it by its JSON Pointer: `classVersion` is + * patched as `/entityClassVersion`, `status` as `/status`, and payload fields as + * `/payload/`. `class` and `classLevel` are immutable and cannot be patched. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create entity response or `void` in case if `callback` provided. + */ + createEntity(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Create Entity with parameters:', + })); + const request = new CreateEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a specific Entity. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get entity response or `void` in case if `callback` provided. + */ + getEntity(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Entity with parameters:', + })); + const request = new GetEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a paginated list of Entities for a given Entity Class. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get entities response or `void` in case if `callback` provided. + */ + getEntities(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Entities with parameters:', + })); + const request = new GetEntitiesRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Set an Entity (full replacement via PUT). + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set entity response or `void` in case if `callback` provided. + */ + setEntity(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Set Entity with parameters:', + })); + const request = new SetEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Update an Entity (partial update via JSON Patch RFC 6902). + * + * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which + * is the name an entity carries in responses and real-time events: + * + * - `classVersion` → `/entityClassVersion` + * - `status` → `/status` + * - a payload field → `/payload/`; nest deeper with more segments, e.g. + * `/payload/address/city`. A field name that contains a `.` is written as-is + * (`/payload/user.name`). + * + * `entityClass` and `entityClassLevel` are immutable and cannot be patched. + * + * @example + * ```typescript + * await pubnub.dataSync.updateEntity({ + * id, + * replace: { '/status': 'inactive', '/payload/creditScore': 810 }, + * remove: ['/payload/legacyField'], + * }); + * ``` + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update entity response or `void` in case if `callback` provided. + */ + updateEntity(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Update Entity with parameters:', + })); + const request = new UpdateEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Remove an Entity. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove entity response or `void` in case if `callback` provided. + */ + removeEntity(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove Entity with parameters:', + })); + const request = new RemoveEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Create a new Relationship. + * + * To change a field later with `updateRelationship`, address it by its JSON Pointer: + * `classVersion` is patched as `/relationshipClassVersion`, `status` as `/status`, and payload + * fields as `/payload/`. `class`, `entityAId`, and `entityBId` are immutable and + * cannot be patched. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create relationship response or `void` in case if `callback` provided. + */ + createRelationship(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Create Relationship with parameters:', + })); + const request = new CreateRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a specific Relationship. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get relationship response or `void` in case if `callback` provided. + */ + getRelationship(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Relationship with parameters:', + })); + const request = new GetRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a paginated list of Relationships. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get relationships response or `void` in case if `callback` provided. + */ + getRelationships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Relationships with parameters:', + })); + const request = new GetRelationshipsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Set a Relationship (full replacement via PUT). + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set relationship response or `void` in case if `callback` provided. + */ + setRelationship(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Set Relationship with parameters:', + })); + const request = new SetRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Update a Relationship (partial update via JSON Patch RFC 6902). + * + * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which + * is the name a relationship carries in responses and real-time events: + * + * - `classVersion` → `/relationshipClassVersion` + * - `status` → `/status` + * - a payload field → `/payload/`; nest deeper with more segments, e.g. + * `/payload/address/city`. A field name that contains a `.` is written as-is + * (`/payload/user.name`). + * + * `relationshipClass`, `entityAId`, and `entityBId` are immutable and cannot be patched. + * + * @example + * ```typescript + * await pubnub.dataSync.updateRelationship({ + * id, + * replace: { '/status': 'inactive', '/payload/label': 'primary' }, + * remove: ['/payload/legacyField'], + * }); + * ``` + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update relationship response or `void` in case if `callback` provided. + */ + updateRelationship(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Update Relationship with parameters:', + })); + const request = new UpdateRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Remove a Relationship. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove relationship response or `void` in case if `callback` provided. + */ + removeRelationship(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove Relationship with parameters:', + })); + const request = new RemoveRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Create a new User. + * + * To change a field later with `updateUser`, address it by its JSON Pointer: `classVersion` is + * patched as `/entityClassVersion`, `status` as `/status`, and payload fields as + * `/payload/`. `class` and `classLevel` are immutable and cannot be patched. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create user response or `void` in case if `callback` provided. + */ + createUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Create User with parameters:', + })); + const request = new CreateUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a specific User. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get user response or `void` in case if `callback` provided. + */ + getUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get User with parameters:', + })); + const request = new GetUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a paginated list of Users. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get users response or `void` in case if `callback` provided. + */ + getUsers(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Users with parameters:', + })); + const request = new GetUsersRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Set a User (full replacement via PUT). + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set user response or `void` in case if `callback` provided. + */ + setUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Set User with parameters:', + })); + const request = new SetUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Update a User (partial update via JSON Patch RFC 6902). + * + * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which + * is the name a user carries in responses and real-time events: + * + * - `classVersion` → `/entityClassVersion` + * - `status` → `/status` + * - a payload field → `/payload/`; nest deeper with more segments, e.g. + * `/payload/address/city`. A field name that contains a `.` is written as-is + * (`/payload/user.name`). + * + * `entityClass` and `entityClassLevel` are immutable and cannot be patched. + * + * @example + * ```typescript + * await pubnub.dataSync.updateUser({ + * id, + * replace: { '/status': 'inactive', '/payload/email': 'alice.v@acme.test' }, + * remove: ['/payload/legacyField'], + * }); + * ``` + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update user response or `void` in case if `callback` provided. + */ + updateUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Update User with parameters:', + })); + const request = new UpdateUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Remove a User. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove user response or `void` in case if `callback` provided. + */ + removeUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove User with parameters:', + })); + const request = new RemoveUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Create a new Channel. + * + * To change a field later with `updateChannel`, address it by its JSON Pointer: `classVersion` + * is patched as `/entityClassVersion`, `status` as `/status`, and payload fields as + * `/payload/`. `class` and `classLevel` are immutable and cannot be patched. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create channel response or `void` in case if `callback` provided. + */ + createChannel(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Create Channel with parameters:', + })); + const request = new CreateChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a specific Channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get channel response or `void` in case if `callback` provided. + */ + getChannel(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Channel with parameters:', + })); + const request = new GetChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a paginated list of Channels. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get channels response or `void` in case if `callback` provided. + */ + getChannels(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Channels with parameters:', + })); + const request = new GetChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Set a Channel (full replacement via PUT). + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set channel response or `void` in case if `callback` provided. + */ + setChannel(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Set Channel with parameters:', + })); + const request = new SetChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Update a Channel (partial update via JSON Patch RFC 6902). + * + * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which + * is the name a channel carries in responses and real-time events: + * + * - `classVersion` → `/entityClassVersion` + * - `status` → `/status` + * - a payload field → `/payload/`; nest deeper with more segments, e.g. + * `/payload/address/city`. A field name that contains a `.` is written as-is + * (`/payload/user.name`). + * + * `entityClass` and `entityClassLevel` are immutable and cannot be patched. + * + * @example + * ```typescript + * await pubnub.dataSync.updateChannel({ + * id, + * replace: { '/status': 'inactive', '/payload/memberCount': 42 }, + * remove: ['/payload/legacyField'], + * }); + * ``` + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update channel response or `void` in case if `callback` provided. + */ + updateChannel(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Update Channel with parameters:', + })); + const request = new UpdateChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Remove a Channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove channel response or `void` in case if `callback` provided. + */ + removeChannel(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove Channel with parameters:', + })); + const request = new RemoveChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Create a new Membership (associates a User with a Channel). + * + * To change a field later with `updateMembership`, address it by its JSON Pointer: + * `classVersion` is patched as `/relationshipClassVersion`, `status` as `/status`, and payload + * fields as `/payload/`. `userId` and `channelId` are immutable and cannot be patched. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create membership response or `void` in case if `callback` provided. + */ + createMembership(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Create Membership with parameters:', + })); + const request = new CreateMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a specific Membership. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get membership response or `void` in case if `callback` provided. + */ + getMembership(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Membership with parameters:', + })); + const request = new GetMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a paginated list of Memberships. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get memberships response or `void` in case if `callback` provided. + */ + getMemberships(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Memberships with parameters:', + })); + const request = new GetMembershipsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Set a Membership (full replacement via PUT). + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set membership response or `void` in case if `callback` provided. + */ + setMembership(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Set Membership with parameters:', + })); + const request = new SetMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Update a Membership (partial update via JSON Patch RFC 6902). + * + * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which + * is the name a membership carries in responses and real-time events: + * + * - `classVersion` → `/relationshipClassVersion` + * - `status` → `/status` + * - a payload field → `/payload/`; nest deeper with more segments, e.g. + * `/payload/address/city`. A field name that contains a `.` is written as-is + * (`/payload/user.name`). + * + * `userId` and `channelId` are immutable and cannot be patched. + * + * @example + * ```typescript + * await pubnub.dataSync.updateMembership({ + * id, + * replace: { '/status': 'inactive', '/payload/role': 'moderator' }, + * remove: ['/payload/legacyField'], + * }); + * ``` + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update membership response or `void` in case if `callback` provided. + */ + updateMembership(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Update Membership with parameters:', + })); + const request = new UpdateMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Remove a Membership. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove membership response or `void` in case if `callback` provided. + */ + removeMembership(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove Membership with parameters:', + })); + const request = new RemoveMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + } + + /** + * Time REST API module. + */ + // endregion + /** + * Get current PubNub high-precision time request. + * + * @internal + */ + class TimeRequest extends AbstractRequest { + constructor() { + super(); + } + operation() { + return RequestOperation$1.PNTimeOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { timetoken: this.deserializeResponse(response)[0] }; + }); + } + get path() { + return '/time/0'; + } + } + + /** + * Download File REST API module. + * + * @internal + */ + // endregion + /** + * Download File request. + * + * @internal + */ + class DownloadFileRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNDownloadFileOperation; + } + validate() { + const { channel, id, name } = this.parameters; + if (!channel) + return "channel can't be empty"; + if (!id) + return "file id can't be empty"; + if (!name) + return "file name can't be empty"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + const { cipherKey, crypto, cryptography, name, PubNubFile } = this.parameters; + const mimeType = response.headers['content-type']; + let decryptedFile; + let body = response.body; + if (PubNubFile.supportsEncryptFile && (cipherKey || crypto)) { + if (cipherKey && cryptography) + body = yield cryptography.decrypt(cipherKey, body); + else if (!cipherKey && crypto) + decryptedFile = yield crypto.decryptFile(PubNubFile.create({ data: body, name: name, mimeType }), PubNubFile); + } + return (decryptedFile + ? decryptedFile + : PubNubFile.create({ + data: body, + name, + mimeType, + })); + }); + } + get path() { + const { keySet: { subscribeKey }, channel, id, name, } = this.parameters; + return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files/${encodeString(id)}/${encodeString(name)}`; + } + } + + /** + * Core PubNub API module. + */ + // endregion + /** + * Platform-agnostic PubNub client core. + */ + class PubNubCore { + /** + * Construct notification payload which will trigger push notification. + * + * @param title - Title which will be shown on notification. + * @param body - Payload which will be sent as part of notification. + * + * @returns Pre-formatted message payload which will trigger push notification. + */ + static notificationPayload(title, body) { + { + return new NotificationsPayload(title, body); + } + } + /** + * Generate unique identifier. + * + * @returns Unique identifier. + */ + static generateUUID() { + return uuidGenerator.createUUID(); + } + // endregion + /** + * Create and configure PubNub client core. + * + * @param configuration - PubNub client core configuration. + * @returns Configured and ready to use PubNub client. + * + * @internal + */ + constructor(configuration) { + /** + * List of subscribe capable objects with active subscriptions. + * + * Track list of {@link Subscription} and {@link SubscriptionSet} objects with active + * subscription. + * + * @internal + */ + this.eventHandleCapable = {}; + /** + * Created entities. + * + * Map of entities which have been created to access. + * + * @internal + */ + this.entities = {}; + this._configuration = configuration.configuration; + this.cryptography = configuration.cryptography; + this.tokenManager = configuration.tokenManager; + this.transport = configuration.transport; + this.crypto = configuration.crypto; + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: configuration.configuration, + details: 'Create with configuration:', + ignoredKeys(key, obj) { + return typeof obj[key] === 'function' || key.startsWith('_') || key === 'keySet' || isSensitiveLogKey(key); + }, + })); + // API group entry points initialization. + this._objects = new PubNubObjects(this._configuration, this.sendRequest.bind(this)); + this._dataSync = new PubNubDataSync(this._configuration, this.sendRequest.bind(this)); + this._channelGroups = new PubNubChannelGroups(this._configuration.logger(), this._configuration.keySet, this.sendRequest.bind(this)); + this._push = new PubNubPushNotifications(this._configuration.logger(), this._configuration.keySet, this.sendRequest.bind(this)); + { + // Prepare for a real-time events announcement. + this.eventDispatcher = new EventDispatcher(); + if (this._configuration.enableEventEngine) { + { + this.logger.debug('PubNub', 'Using new subscription loop management.'); + let heartbeatInterval = this._configuration.getHeartbeatInterval(); + this.presenceState = {}; + { + if (heartbeatInterval) { + this.presenceEventEngine = new PresenceEventEngine({ + heartbeat: (parameters, callback) => { + this.logger.trace('PresenceEventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Heartbeat with parameters:', + })); + return this.heartbeat(parameters, callback); + }, + leave: (parameters) => { + this.logger.trace('PresenceEventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Leave with parameters:', + })); + this.makeUnsubscribe(parameters, () => { }); + }, + heartbeatDelay: () => { + let cancelDelay = () => { }; + const promise = new Promise((resolve, reject) => { + heartbeatInterval = this._configuration.getHeartbeatInterval(); + if (!heartbeatInterval) + reject(new PubNubError('Heartbeat interval has been reset.')); + else { + const timeoutId = setTimeout(() => { + resolve(); + }, heartbeatInterval * 1000); + cancelDelay = () => { + clearTimeout(timeoutId); + reject(new PubNubError('Heartbeat interval has been cancelled.')); + }; + } + }); + return { cancelDelay, promise }; + }, + emitStatus: (status) => this.emitStatus(status), + config: this._configuration, + presenceState: this.presenceState, + }); + } + } + this.eventEngine = new EventEngine({ + handshake: (parameters) => { + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Handshake with parameters:', + ignoredKeys: ['abortSignal', 'crypto', 'timeout', 'keySet', 'getFileUrl'], + })); + return this.subscribeHandshake(parameters); + }, + receiveMessages: (parameters) => { + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Receive messages with parameters:', + ignoredKeys: ['abortSignal', 'crypto', 'timeout', 'keySet', 'getFileUrl'], + })); + return this.subscribeReceiveMessages(parameters); + }, + join: (parameters) => { + var _a, _b; + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Join with parameters:', + })); + if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { + this.logger.trace('EventEngine', "Ignoring 'join' announcement request."); + return; + } + this.join(parameters); + }, + leave: (parameters) => { + var _a, _b; + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Leave with parameters:', + })); + if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { + this.logger.trace('EventEngine', "Ignoring 'leave' announcement request."); + return; + } + this.leave(parameters); + }, + leaveAll: (parameters) => { + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Leave all with parameters:', + })); + this.leaveAll(parameters); + }, + presenceReconnect: (parameters) => { + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Reconnect with parameters:', + })); + this.presenceReconnect(parameters); + }, + presenceDisconnect: (parameters) => { + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Disconnect with parameters:', + })); + this.presenceDisconnect(parameters); + }, + presenceState: this.presenceState, + config: this._configuration, + emitMessages: (cursor, events) => { + try { + this.logger.debug('EventEngine', () => { + const hashedEvents = events.map((event) => { + const pn_mfp = event.type === PubNubEventType.Message || event.type === PubNubEventType.Signal + ? messageFingerprint(event.data.message) + : undefined; + return pn_mfp ? { type: event.type, data: Object.assign(Object.assign({}, event.data), { pn_mfp }) } : event; + }); + return { messageType: 'object', message: hashedEvents, details: 'Received events:' }; + }); + events.forEach((event) => this.emitEvent(cursor, event)); + } + catch (e) { + const errorStatus = { + error: true, + category: StatusCategory$1.PNUnknownCategory, + errorData: e, + statusCode: 0, + }; + this.emitStatus(errorStatus); + } + }, + emitStatus: (status) => this.emitStatus(status), + }); + } + } + else { + { + this.logger.debug('PubNub', 'Using legacy subscription loop management.'); + this.subscriptionManager = new SubscriptionManager(this._configuration, (cursor, event) => { + try { + this.emitEvent(cursor, event); + } + catch (e) { + const errorStatus = { + error: true, + category: StatusCategory$1.PNUnknownCategory, + errorData: e, + statusCode: 0, + }; + this.emitStatus(errorStatus); + } + }, this.emitStatus.bind(this), (parameters, callback) => { + this.logger.trace('SubscriptionManager', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Subscribe with parameters:', + ignoredKeys: ['crypto', 'timeout', 'keySet', 'getFileUrl'], + })); + this.makeSubscribe(parameters, callback); + }, (parameters, callback) => { + this.logger.trace('SubscriptionManager', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Heartbeat with parameters:', + ignoredKeys: ['crypto', 'timeout', 'keySet', 'getFileUrl'], + })); + return this.heartbeat(parameters, callback); + }, (parameters, callback) => { + this.logger.trace('SubscriptionManager', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Leave with parameters:', + })); + this.makeUnsubscribe(parameters, callback); + }, this.time.bind(this)); + } + } + } + } + // -------------------------------------------------------- + // -------------------- Configuration ---------------------- + // -------------------------------------------------------- + // region Configuration + /** + * PubNub client configuration. + * + * @returns Currently user PubNub client configuration. + */ + get configuration() { + return this._configuration; + } + /** + * Current PubNub client configuration. + * + * @returns Currently user PubNub client configuration. + * + * @deprecated Use {@link configuration} getter instead. + */ + get _config() { + return this.configuration; + } + /** + * REST API endpoint access authorization key. + * + * It is required to have `authorization key` with required permissions to access REST API + * endpoints when `PAM` enabled for user key set. + */ + get authKey() { + var _a; + return (_a = this._configuration.authKey) !== null && _a !== void 0 ? _a : undefined; + } + /** + * REST API endpoint access authorization key. + * + * It is required to have `authorization key` with required permissions to access REST API + * endpoints when `PAM` enabled for user key set. + */ + getAuthKey() { + return this.authKey; + } + /** + * Change REST API endpoint access authorization key. + * + * @param authKey - New authorization key which should be used with new requests. + */ + setAuthKey(authKey) { + this.logger.debug('PubNub', 'Auth key updated.'); + this._configuration.setAuthKey(authKey); + if (this.onAuthenticationChange) + this.onAuthenticationChange(authKey); + } + /** + * Get a PubNub client user identifier. + * + * @returns Current PubNub client user identifier. + */ + get userId() { + return this._configuration.userId; + } + /** + * Change the current PubNub client user identifier. + * + * **Important:** Change won't affect ongoing REST API calls. + * **Warning:** Because ongoing REST API calls won't be canceled there could happen unexpected events like implicit + * `join` event for the previous `userId` after a long-poll subscribe request will receive a response. To avoid this + * it is advised to unsubscribe from all/disconnect before changing `userId`. + * + * @param value - New PubNub client user identifier. + * + * @throws Error empty user identifier has been provided. + */ + set userId(value) { + if (!value || typeof value !== 'string' || value.trim().length === 0) { + const error = new Error('Missing or invalid userId parameter. Provide a valid string userId'); + this.logger.error('PubNub', () => ({ messageType: 'error', message: error })); + throw error; + } + this.logger.debug('PubNub', `Set user ID: ${value}`); + this._configuration.userId = value; + if (this.onUserIdChange) + this.onUserIdChange(this._configuration.userId); + } + /** + * Get a PubNub client user identifier. + * + * @returns Current PubNub client user identifier. + */ + getUserId() { + return this._configuration.userId; + } + /** + * Change the current PubNub client user identifier. + * + * **Important:** Change won't affect ongoing REST API calls. + * + * @param value - New PubNub client user identifier. + * + * @throws Error empty user identifier has been provided. + */ + setUserId(value) { + this.userId = value; + } + /** + * Real-time updates filtering expression. + * + * @returns Filtering expression. + */ + get filterExpression() { + var _a; + return (_a = this._configuration.getFilterExpression()) !== null && _a !== void 0 ? _a : undefined; + } + /** + * Real-time updates filtering expression. + * + * @returns Filtering expression. + */ + getFilterExpression() { + return this.filterExpression; + } + /** + * Update real-time updates filtering expression. + * + * @param expression - New expression which should be used or `undefined` to disable filtering. + */ + set filterExpression(expression) { + this.logger.debug('PubNub', `Set filter expression: ${expression}`); + this._configuration.setFilterExpression(expression); + } + /** + * Update real-time updates filtering expression. + * + * @param expression - New expression which should be used or `undefined` to disable filtering. + */ + setFilterExpression(expression) { + this.logger.debug('PubNub', `Set filter expression: ${expression}`); + this.filterExpression = expression; + } + /** + * Dta encryption / decryption key. + * + * @returns Currently used key for data encryption / decryption. + */ + get cipherKey() { + return this._configuration.getCipherKey(); + } + /** + * Change data encryption / decryption key. + * + * @param key - New key which should be used for data encryption / decryption. + */ + set cipherKey(key) { + this._configuration.setCipherKey(key); + } + /** + * Change data encryption / decryption key. + * + * @param key - New key which should be used for data encryption / decryption. + */ + setCipherKey(key) { + this.logger.debug('PubNub', 'Cipher key updated.'); + this.cipherKey = key; + } + /** + * Change a heartbeat requests interval. + * + * @param interval - New presence request heartbeat intervals. + */ + set heartbeatInterval(interval) { + var _a; + this.logger.debug('PubNub', `Set heartbeat interval: ${interval}`); + this._configuration.setHeartbeatInterval(interval); + if (this.onHeartbeatIntervalChange) + this.onHeartbeatIntervalChange((_a = this._configuration.getHeartbeatInterval()) !== null && _a !== void 0 ? _a : 0); + } + /** + * Change a heartbeat requests interval. + * + * @param interval - New presence request heartbeat intervals. + */ + setHeartbeatInterval(interval) { + this.heartbeatInterval = interval; + } + /** + * Get registered loggers' manager. + * + * @returns Registered loggers' manager. + */ + get logger() { + return this._configuration.logger(); + } + /** + * Get PubNub SDK version. + * + * @returns Current SDK version. + */ + getVersion() { + return this._configuration.getVersion(); + } + /** + * Add framework's prefix. + * + * @param name - Name of the framework which would want to add own data into `pnsdk` suffix. + * @param suffix - Suffix with information about a framework. + */ + _addPnsdkSuffix(name, suffix) { + this.logger.debug('PubNub', `Add '${name}' 'pnsdk' suffix: ${suffix}`); + this._configuration._addPnsdkSuffix(name, suffix); + } + // -------------------------------------------------------- + // ---------------------- Deprecated ---------------------- + // -------------------------------------------------------- + // region Deprecated + /** + * Get a PubNub client user identifier. + * + * @returns Current PubNub client user identifier. + * + * @deprecated Use the {@link getUserId} or {@link userId} getter instead. + */ + getUUID() { + return this.userId; + } + /** + * Change the current PubNub client user identifier. + * + * **Important:** Change won't affect ongoing REST API calls. + * + * @param value - New PubNub client user identifier. + * + * @throws Error empty user identifier has been provided. + * + * @deprecated Use the {@link PubNubCore#setUserId setUserId} or {@link PubNubCore#userId userId} setter instead. + */ + setUUID(value) { + this.logger.warn('PubNub', "'setUserId` is deprecated, please use 'setUserId' or 'userId' setter instead."); + this.logger.debug('PubNub', `Set UUID: ${value}`); + this.userId = value; + } + /** + * Custom data encryption method. + * + * @deprecated Instead use {@link cryptoModule} for data encryption. + */ + get customEncrypt() { + return this._configuration.getCustomEncrypt(); + } + /** + * Custom data decryption method. + * + * @deprecated Instead use {@link cryptoModule} for data decryption. + */ + get customDecrypt() { + return this._configuration.getCustomDecrypt(); + } + // endregion + // endregion + // -------------------------------------------------------- + // ---------------------- Entities ------------------------ + // -------------------------------------------------------- + // region Entities + /** + * Create a `Channel` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param name - Unique channel name. + * @returns `Channel` entity. + */ + channel(name) { + let channel = this.entities[`${name}_ch`]; + if (!channel) + channel = this.entities[`${name}_ch`] = new Channel(name, this); + return channel; + } + /** + * Create a `ChannelGroup` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param name - Unique channel group name. + * @returns `ChannelGroup` entity. + */ + channelGroup(name) { + let channelGroup = this.entities[`${name}_chg`]; + if (!channelGroup) + channelGroup = this.entities[`${name}_chg`] = new ChannelGroup(name, this); + return channelGroup; + } + /** + * Create a `ChannelMetadata` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param id - Unique channel metadata object identifier. + * @returns `ChannelMetadata` entity. + */ + channelMetadata(id) { + let metadata = this.entities[`${id}_chm`]; + if (!metadata) + metadata = this.entities[`${id}_chm`] = new ChannelMetadata(id, this); + return metadata; + } + /** + * Create a `UserMetadata` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param id - Unique user metadata object identifier. + * @returns `UserMetadata` entity. + */ + userMetadata(id) { + let metadata = this.entities[`${id}_um`]; + if (!metadata) + metadata = this.entities[`${id}_um`] = new UserMetadata(id, this); + return metadata; + } + /** + * Create a `DataSyncUser` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param id - Unique DataSync `User` object identifier (used verbatim, so wildcard identifiers + * like `user.*` are supported). + * @returns `DataSyncUser` entity. + */ + dataSyncUser(id) { + let entity = this.entities[`${id}_dsu`]; + if (!entity) + entity = this.entities[`${id}_dsu`] = new DataSyncUser(id, this); + return entity; + } + /** + * Create a `DataSyncChannel` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param id - Unique DataSync `Channel` object identifier (used verbatim, so wildcard identifiers + * like `channel.*` are supported). + * @returns `DataSyncChannel` entity. + */ + dataSyncChannel(id) { + let entity = this.entities[`${id}_dsc`]; + if (!entity) + entity = this.entities[`${id}_dsc`] = new DataSyncChannel(id, this); + return entity; + } + /** + * Create a `DataSyncMembership` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * **Important:** Membership changes are delivered on the data channels of both linked entities + * (the user and the channel identifier), not on the membership identifier — use + * {@link PubNubCore#dataSyncUser dataSyncUser} / {@link PubNubCore#dataSyncChannel + * dataSyncChannel} to observe them. + * + * @param id - Unique DataSync `Membership` object identifier (`{userId}:{channelId}`, used + * verbatim, so wildcard identifiers like `user-123:*` are supported). + * @returns `DataSyncMembership` entity. + */ + dataSyncMembership(id) { + let entity = this.entities[`${id}_dsm`]; + if (!entity) + entity = this.entities[`${id}_dsm`] = new DataSyncMembership(id, this); + return entity; + } + /** + * Create a `DataSyncEntity` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param id - Unique DataSync `Entity` object identifier (used verbatim, so wildcard identifiers + * like `customer.*` are supported). + * @returns `DataSyncEntity` entity. + */ + dataSyncEntity(id) { + let entity = this.entities[`${id}_dse`]; + if (!entity) + entity = this.entities[`${id}_dse`] = new DataSyncEntity(id, this); + return entity; + } + /** + * Create a `DataSyncRelationship` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * **Important:** Relationship changes are delivered on the data channels of both linked entities + * (`entityAId` and `entityBId`), not on the relationship identifier — use + * {@link PubNubCore#dataSyncEntity dataSyncEntity} to observe them. + * + * @param id - Unique DataSync `Relationship` object identifier (used verbatim, so wildcard + * identifiers like `owns.*` are supported). + * @returns `DataSyncRelationship` entity. + */ + dataSyncRelationship(id) { + let entity = this.entities[`${id}_dsr`]; + if (!entity) + entity = this.entities[`${id}_dsr`] = new DataSyncRelationship(id, this); + return entity; + } + /** + * Create subscriptions set object. + * + * @param parameters - Subscriptions set configuration parameters. + */ + subscriptionSet(parameters) { + var _a, _b; + { + // Prepare a list of entities for a set. + const entities = []; + (_a = parameters.channels) === null || _a === void 0 ? void 0 : _a.forEach((name) => entities.push(this.channel(name))); + (_b = parameters.channelGroups) === null || _b === void 0 ? void 0 : _b.forEach((name) => entities.push(this.channelGroup(name))); + return new SubscriptionSet({ client: this, entities, options: parameters.subscriptionOptions }); + } + } + /** + * Schedule request execution. + * + * @internal + * + * @param request - REST API request. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous request execution and response parsing result or `void` in case if + * `callback` provided. + * + * @throws PubNubError in case of request processing error. + */ + sendRequest(request, callback) { + return __awaiter(this, void 0, void 0, function* () { + // Validate user-input. + const validationResult = request.validate(); + if (validationResult) { + const validationError = createValidationError(validationResult); + this.logger.error('PubNub', () => ({ messageType: 'error', message: validationError })); + if (callback) + return callback(validationError, null); + throw new PubNubError('Validation failed, check status for details', validationError); + } + // Complete request configuration. + const transportRequest = request.request(); + const operation = request.operation(); + if ((transportRequest.formData && transportRequest.formData.length > 0) || + operation === RequestOperation$1.PNDownloadFileOperation) { + // Set file upload / download request delay. + transportRequest.timeout = this._configuration.getFileTimeout(); + } + else { + if (operation === RequestOperation$1.PNSubscribeOperation || + operation === RequestOperation$1.PNReceiveMessagesOperation) + transportRequest.timeout = this._configuration.getSubscribeTimeout(); + else + transportRequest.timeout = this._configuration.getTransactionTimeout(); + } + // API request processing status. + const status = { + error: false, + operation, + category: StatusCategory$1.PNAcknowledgmentCategory, + statusCode: 0, + }; + const [sendableRequest, cancellationController] = this.transport.makeSendable(transportRequest); + /** + * **Important:** Because of multiple environments where JS SDK can be used, control over + * cancellation had to be inverted to let the transport provider solve a request cancellation task + * more efficiently. As a result, cancellation controller can be retrieved and used only after + * the request will be scheduled by the transport provider. + */ + request.cancellationController = cancellationController ? cancellationController : null; + return sendableRequest + .then((response) => { + status.statusCode = response.status; + // Handle a special case when request completed but not fully processed by PubNub service. + if (response.status !== 200 && response.status !== 204) { + const responseText = PubNubCore.decoder.decode(response.body); + const contentType = response.headers['content-type']; + if (contentType || contentType.indexOf('javascript') !== -1 || contentType.indexOf('json') !== -1) { + const json = JSON.parse(responseText); + if (typeof json === 'object' && 'error' in json && json.error && typeof json.error === 'object') + status.errorData = json.error; + } + else + status.responseText = responseText; + } + return request.parse(response); + }) + .then((parsed) => { + // Notify callback (if possible). + if (callback) + return callback(status, parsed); + return parsed; + }) + .catch((error) => { + const apiError = !(error instanceof PubNubAPIError) ? PubNubAPIError.create(error) : error; + // Notify callback (if possible). + if (callback) { + if (apiError.category !== StatusCategory$1.PNCancelledCategory) { + this.logger.error('PubNub', () => ({ + messageType: 'error', + message: apiError.toPubNubError(operation, 'REST API request processing error, check status for details'), + })); + } + return callback(apiError.toStatus(operation), null); + } + const pubNubError = apiError.toPubNubError(operation, 'REST API request processing error, check status for details'); + if (apiError.category !== StatusCategory$1.PNCancelledCategory) + this.logger.error('PubNub', () => ({ messageType: 'error', message: pubNubError })); + throw pubNubError; + }); + }); + } + /** + * Unsubscribe from all channels and groups. + * + * @param [isOffline] - Whether `offline` presence should be notified or not. + */ + destroy(isOffline = false) { + this.logger.info('PubNub', 'Destroying PubNub client.'); + { + if (this._globalSubscriptionSet) { + this._globalSubscriptionSet.invalidate(true); + this._globalSubscriptionSet = undefined; + } + Object.values(this.eventHandleCapable).forEach((subscription) => subscription.invalidate(true)); + this.eventHandleCapable = {}; + if (this.subscriptionManager) { + this.subscriptionManager.unsubscribeAll(isOffline); + this.subscriptionManager.disconnect(); + } + else if (this.eventEngine) + this.eventEngine.unsubscribeAll(isOffline); + } + { + if (this.presenceEventEngine) + this.presenceEventEngine.leaveAll(isOffline); + } + } + /** + * Unsubscribe from all channels and groups. + * + * @deprecated Use {@link destroy} method instead. + */ + stop() { + this.logger.warn('PubNub', "'stop' is deprecated, please use 'destroy' instead."); + this.destroy(); + } + /** + * Publish data to a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous publish data response or `void` in case if `callback` provided. + */ + publish(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Publish with parameters:', + })); + const isFireRequest = parameters.replicate === false && parameters.storeInHistory === false; + const request = new PublishRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule() })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `${isFireRequest ? 'Fire' : 'Publish'} success with timetoken: ${response.timetoken}`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Signal data to a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous signal data response or `void` in case if `callback` provided. + */ + signal(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Signal with parameters:', + })); + const request = new SignalRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Publish success with timetoken: ${response.timetoken}`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * `Fire` a data to a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous signal data response or `void` in case if `callback` provided. + * + * @deprecated Use {@link publish} method instead. + */ + fire(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Fire with parameters:', + })); + callback !== null && callback !== void 0 ? callback : (callback = () => { }); + return this.publish(Object.assign(Object.assign({}, parameters), { replicate: false, storeInHistory: false }), callback); + }); + } + // endregion + // -------------------------------------------------------- + // -------------------- Subscribe API --------------------- + // -------------------------------------------------------- + // region Subscribe API + /** + * Global subscription set which supports legacy subscription interface. + * + * @returns Global subscription set. + * + * @internal + */ + get globalSubscriptionSet() { + if (!this._globalSubscriptionSet) + this._globalSubscriptionSet = this.subscriptionSet({}); + return this._globalSubscriptionSet; + } + /** + * Subscription-based current timetoken. + * + * @returns Timetoken based on current timetoken plus diff between current and loop start time. + * + * @internal + */ + get subscriptionTimetoken() { + { + if (this.subscriptionManager) + return this.subscriptionManager.subscriptionTimetoken; + else if (this.eventEngine) + return this.eventEngine.subscriptionTimetoken; + } + return undefined; + } + /** + * Get list of channels on which PubNub client currently subscribed. + * + * @returns List of active channels. + */ + getSubscribedChannels() { + { + if (this.subscriptionManager) + return this.subscriptionManager.subscribedChannels; + else if (this.eventEngine) + return this.eventEngine.getSubscribedChannels(); + } + return []; + } + /** + * Get list of channel groups on which PubNub client currently subscribed. + * + * @returns List of active channel groups. + */ + getSubscribedChannelGroups() { + { + if (this.subscriptionManager) + return this.subscriptionManager.subscribedChannelGroups; + else if (this.eventEngine) + return this.eventEngine.getSubscribedChannelGroups(); + } + return []; + } + /** + * Register an events handler object ({@link Subscription} or {@link SubscriptionSet}) with an active subscription. + * + * @param subscription - {@link Subscription} or {@link SubscriptionSet} object. + * @param [cursor] - Subscription catchup timetoken. + * @param [subscriptions] - List of subscriptions for partial subscription loop update. + * + * @internal + */ + registerEventHandleCapable(subscription, cursor, subscriptions) { + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign(Object.assign({ subscription: subscription }, (cursor ? { cursor } : [])), (subscriptions ? { subscriptions } : {})), + details: `Register event handle capable:`, + })); + if (!this.eventHandleCapable[subscription.state.id]) + this.eventHandleCapable[subscription.state.id] = subscription; + let subscriptionInput; + if (!subscriptions || subscriptions.length === 0) + subscriptionInput = subscription.subscriptionInput(false); + else { + subscriptionInput = new SubscriptionInput({}); + subscriptions.forEach((subscription) => subscriptionInput.add(subscription.subscriptionInput(false))); + } + const parameters = {}; + parameters.channels = subscriptionInput.channels; + parameters.channelGroups = subscriptionInput.channelGroups; + if (cursor) + parameters.timetoken = cursor.timetoken; + if (this.subscriptionManager) + this.subscriptionManager.subscribe(parameters); + else if (this.eventEngine) + this.eventEngine.subscribe(parameters); + } + } + /** + * Unregister an events handler object ({@link Subscription} or {@link SubscriptionSet}) with inactive subscription. + * + * @param subscription - {@link Subscription} or {@link SubscriptionSet} object. + * @param [subscriptions] - List of subscriptions for partial subscription loop update. + * + * @internal + */ + unregisterEventHandleCapable(subscription, subscriptions) { + { + if (!this.eventHandleCapable[subscription.state.id]) + return; + const inUseSubscriptions = []; + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: { subscription: subscription, subscriptions }, + details: `Unregister event handle capable:`, + })); + // Check whether only subscription object has been passed to be unregistered. + let shouldDeleteEventHandler = !subscriptions || subscriptions.length === 0; + // Check whether subscription set is unregistering with all managed Subscription objects, + if (!shouldDeleteEventHandler && + subscription instanceof SubscriptionSet && + subscription.subscriptions.length === (subscriptions === null || subscriptions === void 0 ? void 0 : subscriptions.length)) + shouldDeleteEventHandler = subscription.subscriptions.every((sub) => subscriptions.includes(sub)); + if (shouldDeleteEventHandler) + delete this.eventHandleCapable[subscription.state.id]; + let subscriptionInput; + if (!subscriptions || subscriptions.length === 0) { + subscriptionInput = subscription.subscriptionInput(true); + if (subscriptionInput.isEmpty) + inUseSubscriptions.push(subscription); + } + else { + subscriptionInput = new SubscriptionInput({}); + subscriptions.forEach((subscription) => { + const input = subscription.subscriptionInput(true); + if (input.isEmpty) + inUseSubscriptions.push(subscription); + else + subscriptionInput.add(input); + }); + } + if (inUseSubscriptions.length > 0) { + this.logger.trace('PubNub', () => { + const entities = []; + if (inUseSubscriptions[0] instanceof SubscriptionSet) { + inUseSubscriptions[0].subscriptions.forEach((subscription) => entities.push(subscription.state.entity)); + } + else + inUseSubscriptions.forEach((subscription) => entities.push(subscription.state.entity)); + return { + messageType: 'object', + message: { entities }, + details: `Can't unregister event handle capable because entities still in use:`, + }; + }); + } + if (subscriptionInput.isEmpty) + return; + else { + const _channelGroupsInUse = []; + const _channelsInUse = []; + Object.values(this.eventHandleCapable).forEach((_subscription) => { + const _subscriptionInput = _subscription.subscriptionInput(false); + const _subscriptionChannelGroups = _subscriptionInput.channelGroups; + const _subscriptionChannels = _subscriptionInput.channels; + _channelGroupsInUse.push(...subscriptionInput.channelGroups.filter((channel) => _subscriptionChannelGroups.includes(channel))); + _channelsInUse.push(...subscriptionInput.channels.filter((channel) => _subscriptionChannels.includes(channel))); + }); + if (_channelsInUse.length > 0 || _channelGroupsInUse.length > 0) { + this.logger.trace('PubNub', () => { + const _entitiesInUse = []; + const addEntityIfInUse = (entity) => { + const namesOrIds = entity.subscriptionNames(true); + const checkList = entity.subscriptionType === SubscriptionType.Channel ? _channelsInUse : _channelGroupsInUse; + if (namesOrIds.some((id) => checkList.includes(id))) + _entitiesInUse.push(entity); + }; + Object.values(this.eventHandleCapable).forEach((_subscription) => { + if (_subscription instanceof SubscriptionSet) { + _subscription.subscriptions.forEach((_subscriptionInSet) => { + addEntityIfInUse(_subscriptionInSet.state.entity); + }); + } + else if (_subscription instanceof Subscription) + addEntityIfInUse(_subscription.state.entity); + }); + let details = 'Some entities still in use:'; + if (_channelsInUse.length + _channelGroupsInUse.length === subscriptionInput.length) + details = "Can't unregister event handle capable because entities still in use:"; + return { messageType: 'object', message: { entities: _entitiesInUse }, details }; + }); + subscriptionInput.remove(new SubscriptionInput({ channels: _channelsInUse, channelGroups: _channelGroupsInUse })); + if (subscriptionInput.isEmpty) + return; + } + } + const parameters = {}; + parameters.channels = subscriptionInput.channels; + parameters.channelGroups = subscriptionInput.channelGroups; + if (this.subscriptionManager) + this.subscriptionManager.unsubscribe(parameters); + else if (this.eventEngine) + this.eventEngine.unsubscribe(parameters); + } + } + /** + * Subscribe to specified channels and groups real-time events. + * + * @param parameters - Request configuration parameters. + */ + subscribe(parameters) { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Subscribe with parameters:', + })); + // The addition of a new subscription set into the subscribed global subscription set will update the active + // subscription loop with new channels and groups. + const subscriptionSet = this.subscriptionSet(Object.assign(Object.assign({}, parameters), { subscriptionOptions: { receivePresenceEvents: parameters.withPresence } })); + this.globalSubscriptionSet.addSubscriptionSet(subscriptionSet); + subscriptionSet.dispose(); + const timetoken = typeof parameters.timetoken === 'number' ? `${parameters.timetoken}` : parameters.timetoken; + this.globalSubscriptionSet.subscribe({ timetoken }); + } + } + /** + * Perform subscribe request. + * + * **Note:** Method passed into managers to let them use it when required. + * + * @internal + * + * @param parameters - Request configuration parameters. + * @param callback - Request completion handler callback. + */ + makeSubscribe(parameters, callback) { + { + // `on-demand` query parameter not required for non-SharedWorker environment. + if (!this._configuration.isSharedWorkerEnabled()) + parameters.onDemand = false; + const request = new SubscribeRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); + this.sendRequest(request, (status, result) => { + var _a; + if (this.subscriptionManager && ((_a = this.subscriptionManager.abort) === null || _a === void 0 ? void 0 : _a.identifier) === request.requestIdentifier) + this.subscriptionManager.abort = null; + callback(status, result); + }); + /** + * Allow subscription cancellation. + * + * **Note:** Had to be done after scheduling because the transport provider returns the cancellation + * controller only when schedule new request. + */ + if (this.subscriptionManager) { + // Creating an identifiable abort caller. + const callableAbort = () => request.abort('Cancel long-poll subscribe request'); + callableAbort.identifier = request.requestIdentifier; + this.subscriptionManager.abort = callableAbort; + } + } + } + /** + * Unsubscribe from specified channels and groups real-time events. + * + * @param parameters - Request configuration parameters. + */ + unsubscribe(parameters) { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Unsubscribe with parameters:', + })); + if (!this._globalSubscriptionSet) { + this.logger.debug('PubNub', 'There are no active subscriptions. Ignore.'); + return; + } + const subscriptions = this.globalSubscriptionSet.subscriptions.filter((subscription) => { + var _a, _b; + const subscriptionInput = subscription.subscriptionInput(false); + if (subscriptionInput.isEmpty) + return false; + for (const channel of (_a = parameters.channels) !== null && _a !== void 0 ? _a : []) + if (subscriptionInput.contains(channel)) + return true; + for (const group of (_b = parameters.channelGroups) !== null && _b !== void 0 ? _b : []) + if (subscriptionInput.contains(group)) + return true; + }); + // Removal from the active subscription also will cause `unsubscribe`. + if (subscriptions.length > 0) + this.globalSubscriptionSet.removeSubscriptions(subscriptions); + } + } + /** + * Perform unsubscribe request. + * + * **Note:** Method passed into managers to let them use it when required. + * + * @internal + * + * @param parameters - Request configuration parameters. + * @param callback - Request completion handler callback. + */ + makeUnsubscribe(parameters, callback) { + { + // Filtering out presence channels and groups. + let { channels, channelGroups } = parameters; + // Remove `-pnpres` channels / groups if they not acceptable in the current PubNub client configuration. + if (!this._configuration.getKeepPresenceChannelsInPresenceRequests()) { + if (channelGroups) + channelGroups = channelGroups.filter((channelGroup) => !channelGroup.endsWith('-pnpres')); + if (channels) + channels = channels.filter((channel) => !channel.endsWith('-pnpres')); + } + // Complete immediately request only for presence channels. + if ((channelGroups !== null && channelGroups !== void 0 ? channelGroups : []).length === 0 && (channels !== null && channels !== void 0 ? channels : []).length === 0) { + return callback({ + error: false, + operation: RequestOperation$1.PNUnsubscribeOperation, + category: StatusCategory$1.PNAcknowledgmentCategory, + statusCode: 200, + }); + } + this.sendRequest(new PresenceLeaveRequest({ channels, channelGroups, keySet: this._configuration.keySet }), callback); + } + } + /** + * Unsubscribe from all channels and groups. + */ + unsubscribeAll() { + { + this.logger.debug('PubNub', 'Unsubscribe all channels and groups'); + // Keeping a subscription set instance after invalidation so to make it possible to deliver the expected + // disconnection status. + if (this._globalSubscriptionSet) + this._globalSubscriptionSet.invalidate(false); + Object.values(this.eventHandleCapable).forEach((subscription) => subscription.invalidate(false)); + this.eventHandleCapable = {}; + if (this.subscriptionManager) + this.subscriptionManager.unsubscribeAll(); + else if (this.eventEngine) + this.eventEngine.unsubscribeAll(); + } + } + /** + * Temporarily disconnect from the real-time events stream. + * + * **Note:** `isOffline` is set to `true` only when a client experiences network issues. + * + * @param [isOffline] - Whether `offline` presence should be notified or not. + */ + disconnect(isOffline = false) { + { + this.logger.debug('PubNub', `Disconnect (while offline? ${!!isOffline ? 'yes' : 'no'})`); + if (this.subscriptionManager) + this.subscriptionManager.disconnect(); + else if (this.eventEngine) + this.eventEngine.disconnect(isOffline); + } + } + /** + * Restore connection to the real-time events stream. + * + * @param parameters - Reconnection catch-up configuration. **Note:** available only with the enabled event engine. + */ + reconnect(parameters) { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Reconnect with parameters:', + })); + if (this.subscriptionManager) + this.subscriptionManager.reconnect(); + else if (this.eventEngine) + this.eventEngine.reconnect(parameters !== null && parameters !== void 0 ? parameters : {}); + } + } + /** + * Event engine handshake subscribe. + * + * @internal + * + * @param parameters - Request configuration parameters. + */ + subscribeHandshake(parameters) { + return __awaiter(this, void 0, void 0, function* () { + { + // `on-demand` query parameter not required for non-SharedWorker environment. + if (!this._configuration.isSharedWorkerEnabled()) + parameters.onDemand = false; + if (!parameters.heartbeat) + parameters.heartbeat = this._configuration.getPresenceTimeout(); + const request = new HandshakeSubscribeRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); + const abortUnsubscribe = parameters.abortSignal.subscribe((err) => { + request.abort('Cancel subscribe handshake request'); + }); + /** + * Allow subscription cancellation. + * + * **Note:** Had to be done after scheduling because the transport provider returns the cancellation + * controller only when schedule new request. + */ + const handshakeResponse = this.sendRequest(request); + return handshakeResponse.then((response) => { + abortUnsubscribe(); + return response.cursor; + }); + } + }); + } + /** + * Event engine receive messages subscribe. + * + * @internal + * + * @param parameters - Request configuration parameters. + */ + subscribeReceiveMessages(parameters) { + return __awaiter(this, void 0, void 0, function* () { + { + // `on-demand` query parameter not required for non-SharedWorker environment. + if (!this._configuration.isSharedWorkerEnabled()) + parameters.onDemand = false; + if (!parameters.heartbeat) + parameters.heartbeat = this._configuration.getPresenceTimeout(); + const request = new ReceiveMessagesSubscribeRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); + const abortUnsubscribe = parameters.abortSignal.subscribe((err) => { + request.abort('Cancel long-poll subscribe request'); + }); + /** + * Allow subscription cancellation. + * + * **Note:** Had to be done after scheduling because the transport provider returns the cancellation + * controller only when schedule new request. + */ + const receiveResponse = this.sendRequest(request); + return receiveResponse.then((response) => { + abortUnsubscribe(); + return response; + }); + } + }); + } + /** + * Get reactions to a specific message. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get reactions response or `void` in case if `callback` provided. + */ + getMessageActions(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get message actions with parameters:', + })); + const request = new GetMessageActionsRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get message actions success. Received ${response.data.length} message actions.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Add a reaction to a specific message. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous add a reaction response or `void` in case if `callback` provided. + */ + addMessageAction(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Add message action with parameters:', + })); + const request = new AddMessageActionRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Message action add success. Message action added with timetoken: ${response.data.actionTimetoken}`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Remove a reaction from a specific message. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove a reaction response or `void` in case if `callback` provided. + */ + removeMessageAction(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove message action with parameters:', + })); + const request = new RemoveMessageAction(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Message action remove success. Removed message action with ${parameters.actionTimetoken} timetoken.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Fetch messages history for channels. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous fetch messages response or `void` in case if `callback` provided. + */ + fetchMessages(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Fetch messages with parameters:', + })); + const request = new FetchMessagesRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); + const logResponse = (response) => { + if (!response) + return; + const messagesCount = Object.values(response.channels).reduce((acc, message) => acc + message.length, 0); + this.logger.debug('PubNub', `Fetch messages success. Received ${messagesCount} messages.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Delete messages from the channel history. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous delete messages response or `void` in case if `callback` provided. + * + */ + deleteMessages(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Delete messages with parameters:', + })); + const request = new DeleteMessageRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Delete messages success.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Count messages from the channels' history. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous count messages response or `void` in case if `callback` provided. + */ + messageCounts(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get messages count with parameters:', + })); + const request = new MessageCountRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + const messagesCount = Object.values(response.channels).reduce((acc, messagesCount) => acc + messagesCount, 0); + this.logger.debug('PubNub', `Get messages count success. There are ${messagesCount} messages since provided reference timetoken${parameters.channelTimetokens ? parameters.channelTimetokens.join(',') : ''.length > 1 ? 's' : ''}.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Fetch single channel history. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous fetch channel history response or `void` in case if `callback` provided. + * + * @deprecated + */ + history(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Fetch history with parameters:', + })); + const request = new GetHistoryRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule() })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Fetch history success. Received ${response.messages.length} messages.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Get channel's presence information. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get channel's presence response or `void` in case if `callback` provided. + */ + hereNow(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Here now with parameters:', + })); + const request = new HereNowRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Here now success. There are ${response.totalOccupancy} participants in ${response.totalChannels} channels.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Get user's presence information. + * + * Get list of channels to which `uuid` currently subscribed. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get user's presence response or `void` in case if `callback` provided. + */ + whereNow(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Where now with parameters:', + })); + const request = new WhereNowRequest({ + uuid: (_a = parameters.uuid) !== null && _a !== void 0 ? _a : this._configuration.userId, + keySet: this._configuration.keySet, + }); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Where now success. Currently present in ${response.channels.length} channels.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Get associated user's data for channels and groups. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get user's data response or `void` in case if `callback` provided. + */ + getState(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get presence state with parameters:', + })); + const request = new GetPresenceStateRequest(Object.assign(Object.assign({}, parameters), { uuid: (_a = parameters.uuid) !== null && _a !== void 0 ? _a : this._configuration.userId, keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get presence state success. Received presence state for ${Object.keys(response.channels).length} channels.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Set associated user's data for channels and groups. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set user's data response or `void` in case if `callback` provided. + */ + setState(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b; + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Set presence state with parameters:', + })); + const { keySet, userId: userId } = this._configuration; + const heartbeat = this._configuration.getPresenceTimeout(); + let request; + // Maintain presence information (if required). + if (this._configuration.enableEventEngine && this.presenceState) { + const presenceState = this.presenceState; + (_a = parameters.channels) === null || _a === void 0 ? void 0 : _a.forEach((channel) => (presenceState[channel] = parameters.state)); + if ('channelGroups' in parameters) { + (_b = parameters.channelGroups) === null || _b === void 0 ? void 0 : _b.forEach((group) => (presenceState[group] = parameters.state)); + } + if (this.onPresenceStateChange) + this.onPresenceStateChange(this.presenceState); + } + // Check whether the state should be set with heartbeat or not. + if ('withHeartbeat' in parameters && parameters.withHeartbeat) { + request = new HeartbeatRequest(Object.assign(Object.assign({}, parameters), { keySet, heartbeat })); + } + else { + request = new SetPresenceStateRequest(Object.assign(Object.assign({}, parameters), { keySet, uuid: userId })); + } + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Set presence state success.${request instanceof HeartbeatRequest ? ' Presence state has been set using heartbeat endpoint.' : ''}`); + }; + // Update state used by subscription manager. + if (this.subscriptionManager) { + this.subscriptionManager.setState(parameters); + if (this.onPresenceStateChange) + this.onPresenceStateChange(this.subscriptionManager.presenceState); + } + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + // endregion + // region Change presence state + /** + * Manual presence management. + * + * @param parameters - Desired presence state for a provided list of channels and groups. + */ + presence(parameters) { + var _a; + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Change presence with parameters:', + })); + (_a = this.subscriptionManager) === null || _a === void 0 ? void 0 : _a.changePresence(parameters); + } + } + // endregion + // region Heartbeat + /** + * Announce user presence + * + * @internal + * + * @param parameters - Desired presence state for provided list of channels and groups. + * @param callback - Request completion handler callback. + */ + heartbeat(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Heartbeat with parameters:', + })); + // Filtering out presence channels and groups. + let { channels, channelGroups } = parameters; + // Remove `-pnpres` channels / groups if they not acceptable in the current PubNub client configuration. + if (channelGroups) + channelGroups = channelGroups.filter((channelGroup) => !channelGroup.endsWith('-pnpres')); + if (channels) + channels = channels.filter((channel) => !channel.endsWith('-pnpres')); + // Complete immediately request only for presence channels. + if ((channelGroups !== null && channelGroups !== void 0 ? channelGroups : []).length === 0 && (channels !== null && channels !== void 0 ? channels : []).length === 0) { + const responseStatus = { + error: false, + operation: RequestOperation$1.PNHeartbeatOperation, + category: StatusCategory$1.PNAcknowledgmentCategory, + statusCode: 200, + }; + this.logger.trace('PubNub', 'There are no active subscriptions. Ignore.'); + if (callback) + return callback(responseStatus, {}); + return Promise.resolve(responseStatus); + } + const request = new HeartbeatRequest(Object.assign(Object.assign({}, parameters), { channels: [...new Set(channels)], channelGroups: [...new Set(channelGroups)], keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.trace('PubNub', 'Heartbeat success.'); + }; + const abortUnsubscribe = (_a = parameters.abortSignal) === null || _a === void 0 ? void 0 : _a.subscribe((err) => { + request.abort('Cancel long-poll subscribe request'); + }); + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + if (abortUnsubscribe) + abortUnsubscribe(); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + if (abortUnsubscribe) + abortUnsubscribe(); + return response; + }); + } + }); + } + // endregion + // region Join + /** + * Announce user `join` on specified list of channels and groups. + * + * @internal + * + * @param parameters - List of channels and groups where `join` event should be sent. + */ + join(parameters) { + var _a, _b; + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Join with parameters:', + })); + if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { + this.logger.trace('PubNub', "Ignoring 'join' announcement request."); + return; + } + if (this.presenceEventEngine) + this.presenceEventEngine.join(parameters); + else { + this.heartbeat(Object.assign(Object.assign({ channels: parameters.channels, channelGroups: parameters.groups }, (this._configuration.maintainPresenceState && + this.presenceState && + Object.keys(this.presenceState).length > 0 && { state: this.presenceState })), { heartbeat: this._configuration.getPresenceTimeout() }), () => { }); + } + } + } + /** + * Reconnect presence event engine after network issues. + * + * @param parameters - List of channels and groups where `join` event should be sent. + * + * @internal + */ + presenceReconnect(parameters) { + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Presence reconnect with parameters:', + })); + if (this.presenceEventEngine) + this.presenceEventEngine.reconnect(); + else { + this.heartbeat(Object.assign(Object.assign({ channels: parameters.channels, channelGroups: parameters.groups }, (this._configuration.maintainPresenceState && { state: this.presenceState })), { heartbeat: this._configuration.getPresenceTimeout() }), () => { }); + } + } + } + // endregion + // region Leave + /** + * Announce user `leave` on specified list of channels and groups. + * + * @internal + * + * @param parameters - List of channels and groups where `leave` event should be sent. + */ + leave(parameters) { + var _a, _b, _c; + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Leave with parameters:', + })); + if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { + this.logger.trace('PubNub', "Ignoring 'leave' announcement request."); + return; + } + if (this.presenceEventEngine) + (_c = this.presenceEventEngine) === null || _c === void 0 ? void 0 : _c.leave(parameters); + else + this.makeUnsubscribe({ channels: parameters.channels, channelGroups: parameters.groups }, () => { }); + } + } + /** + * Announce user `leave` on all subscribed channels. + * + * @internal + * + * @param parameters - List of channels and groups where `leave` event should be sent. + */ + leaveAll(parameters = {}) { + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Leave all with parameters:', + })); + if (this.presenceEventEngine) + this.presenceEventEngine.leaveAll(!!parameters.isOffline); + else if (!parameters.isOffline) + this.makeUnsubscribe({ channels: parameters.channels, channelGroups: parameters.groups }, () => { }); + } + } + /** + * Announce user `leave` on disconnection. + * + * @internal + * + * @param parameters - List of channels and groups where `leave` event should be sent. + */ + presenceDisconnect(parameters) { + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Presence disconnect parameters:', + })); + if (this.presenceEventEngine) + this.presenceEventEngine.disconnect(!!parameters.isOffline); + else if (!parameters.isOffline) + this.makeUnsubscribe({ channels: parameters.channels, channelGroups: parameters.groups }, () => { }); + } + } + /** + * Grant token permission. + * + * Generate an access token with requested permissions. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous grant token response or `void` in case if `callback` provided. + */ + grantToken(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('Grant Token error: PAM module disabled'); + }); + } + /** + * Revoke token permission. + * + * @param token - Access token for which permissions should be revoked. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous revoke token response or `void` in case if `callback` provided. + */ + revokeToken(token, callback) { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('Revoke Token error: PAM module disabled'); + }); + } + // endregion + // region Token Manipulation + /** + * Get a current access token. + * + * @returns Previously configured access token using {@link setToken} method. + */ + get token() { + return this.tokenManager && this.tokenManager.getToken(); + } + /** + * Get a current access token. + * + * @returns Previously configured access token using {@link setToken} method. + */ + getToken() { + return this.token; + } + /** + * Set current access token. + * + * @param token - New access token which should be used with next REST API endpoint calls. + */ + set token(token) { + if (this.tokenManager) + this.tokenManager.setToken(token); + if (this.onAuthenticationChange) + this.onAuthenticationChange(token); + } + /** + * Set current access token. + * + * @param token - New access token which should be used with next REST API endpoint calls. + */ + setToken(token) { + this.logger.debug('PubNub', 'Access token updated.'); + this.token = token; + } + /** + * Parse access token. + * + * Parse token to see what permissions token owner has. + * + * @param token - Token which should be parsed. + * + * @returns Token's permissions information for the resources. + */ + parseToken(token) { + this.logger.debug('PubNub', 'Parse access token.'); + return this.tokenManager && this.tokenManager.parseToken(token); + } + /** + * Grant auth key(s) permission. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous grant auth key(s) permissions or `void` in case if `callback` provided. + * + * @deprecated Use {@link grantToken} and {@link setToken} methods instead. + */ + grant(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('Grant error: PAM module disabled'); + }); + } + /** + * Audit auth key(s) permission. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @deprecated + * + * @deprecated Use {@link grantToken} and {@link setToken} methods instead. + */ + audit(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('Grant Permissions error: PAM module disabled'); + }); + } + // endregion + // endregion + // endregion + // -------------------------------------------------------- + // ------------------- App Context API -------------------- + // -------------------------------------------------------- + // region App Context API + /** + * PubNub App Context API group. + */ + get objects() { + return this._objects; + } + // -------------------------------------------------------- + // -------------------- DataSync API --------------------- + // -------------------------------------------------------- + // region DataSync API + /** + * PubNub DataSync API group. + */ + get dataSync() { + return this._dataSync; + } + /** + Fetch a paginated list of User objects. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all User objects response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.getAllUUIDMetadata getAllUUIDMetadata} method instead. + */ + fetchUsers(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'fetchUsers' is deprecated. Use 'pubnub.objects.getAllUUIDMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, + details: `Fetch all User objects with parameters:`, + })); + return this.objects._getAllUUIDMetadata(parametersOrCallback, callback); + } + }); + } + /** + * Fetch User object for a currently configured PubNub client `uuid`. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get User object response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.getUUIDMetadata getUUIDMetadata} method instead. + */ + fetchUser(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'fetchUser' is deprecated. Use 'pubnub.objects.getUUIDMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' + ? { uuid: this.userId } + : parametersOrCallback, + details: `Fetch${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} User object with parameters:`, + })); + return this.objects._getUUIDMetadata(parametersOrCallback, callback); + } + }); + } + /** + * Create a User object. + * + * @param parameters - Request configuration parameters. Will create a User object for a currently + * configured PubNub client `uuid` if not set. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create User object response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.setUUIDMetadata setUUIDMetadata} method instead. + */ + createUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'createUser' is deprecated. Use 'pubnub.objects.setUUIDMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Create User object with parameters:`, + })); + return this.objects._setUUIDMetadata(parameters, callback); + } + }); + } + /** + * Update a User object. + * + * @param parameters - Request configuration parameters. Will update a User object for a currently + * configured PubNub client `uuid` if not set. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update User object response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.setUUIDMetadata setUUIDMetadata} method instead. + */ + updateUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.warn('PubNub', "'updateUser' is deprecated. Use 'pubnub.objects.setUUIDMetadata' instead."); + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Update User object with parameters:`, + })); + return this.objects._setUUIDMetadata(parameters, callback); + } + }); + } + /** + * Remove a specific User object. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous User object removes response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.removeUUIDMetadata removeUUIDMetadata} method instead. + */ + removeUser(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'removeUser' is deprecated. Use 'pubnub.objects.removeUUIDMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' + ? { uuid: this.userId } + : parametersOrCallback, + details: `Remove${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} User object with parameters:`, + })); + return this.objects._removeUUIDMetadata(parametersOrCallback, callback); + } + }); + } + /** + * Fetch a paginated list of Space objects. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all Space objects response or `void` in case if `callback` + * provided. + * + * @deprecated Use {@link PubNubCore#objects.getAllChannelMetadata getAllChannelMetadata} method instead. + */ + fetchSpaces(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'fetchSpaces' is deprecated. Use 'pubnub.objects.getAllChannelMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, + details: `Fetch all Space objects with parameters:`, + })); + return this.objects._getAllChannelMetadata(parametersOrCallback, callback); + } + }); + } + /** + * Fetch a specific Space object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get Space object response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.getChannelMetadata getChannelMetadata} method instead. + */ + fetchSpace(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'fetchSpace' is deprecated. Use 'pubnub.objects.getChannelMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Fetch Space object with parameters:`, + })); + return this.objects._getChannelMetadata(parameters, callback); + } + }); + } + /** + * Create specific Space object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create Space object response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.setChannelMetadata setChannelMetadata} method instead. + */ + createSpace(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'createSpace' is deprecated. Use 'pubnub.objects.setChannelMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Create Space object with parameters:`, + })); + return this.objects._setChannelMetadata(parameters, callback); + } + }); + } + /** + * Update specific Space object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update Space object response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.setChannelMetadata setChannelMetadata} method instead. + */ + updateSpace(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'updateSpace' is deprecated. Use 'pubnub.objects.setChannelMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Update Space object with parameters:`, + })); + return this.objects._setChannelMetadata(parameters, callback); + } + }); + } + /** + * Remove a specific Space object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous Space object remove response or `void` in case if `callback` + * provided. + * + * @deprecated Use {@link PubNubCore#objects.removeChannelMetadata removeChannelMetadata} method instead. + */ + removeSpace(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'removeSpace' is deprecated. Use 'pubnub.objects.removeChannelMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove Space object with parameters:`, + })); + return this.objects._removeChannelMetadata(parameters, callback); + } + }); + } + /** + * Fetch a paginated list of specific Space members or specific User memberships. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get specific Space members or specific User memberships response or + * `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.getChannelMembers getChannelMembers} or + * {@link PubNubCore#objects.getMemberships getMemberships} methods instead. + */ + fetchMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + return this.objects.fetchMemberships(parameters, callback); + }); + } + /** + * Add members to specific Space or memberships specific User. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous add members to specific Space or memberships specific User response or + * `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.setChannelMembers setChannelMembers} or + * {@link PubNubCore#objects.setMemberships setMemberships} methods instead. + */ + addMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + return this.objects.addMemberships(parameters, callback); + }); + } + /** + * Update specific Space members or User memberships. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update Space members or User memberships response or `void` in case + * if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.setChannelMembers setChannelMembers} or + * {@link PubNubCore#objects.setMemberships setMemberships} methods instead. + */ + updateMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'addMemberships' is deprecated. Use 'pubnub.objects.setChannelMembers' or 'pubnub.objects.setMemberships'" + + ' instead.'); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Update memberships with parameters:`, + })); + return this.objects.addMemberships(parameters, callback); + } + }); + } + /** + * Remove User membership. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous memberships modification response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.removeMemberships removeMemberships} or + * {@link PubNubCore#objects.removeChannelMembers removeChannelMembers} methods instead from `objects` API group. + */ + removeMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b, _c; + { + this.logger.warn('PubNub', "'removeMemberships' is deprecated. Use 'pubnub.objects.removeMemberships' or" + + " 'pubnub.objects.removeChannelMembers' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove memberships with parameters:`, + })); + if ('spaceId' in parameters) { + const spaceParameters = parameters; + const requestParameters = { + channel: (_a = spaceParameters.spaceId) !== null && _a !== void 0 ? _a : spaceParameters.channel, + uuids: (_b = spaceParameters.userIds) !== null && _b !== void 0 ? _b : spaceParameters.uuids, + limit: 0, + }; + if (callback) + return this.objects.removeChannelMembers(requestParameters, callback); + return this.objects.removeChannelMembers(requestParameters); + } + const userParameters = parameters; + const requestParameters = { + uuid: userParameters.userId, + channels: (_c = userParameters.spaceIds) !== null && _c !== void 0 ? _c : userParameters.channels, + limit: 0, + }; + if (callback) + return this.objects.removeMemberships(requestParameters, callback); + return this.objects.removeMemberships(requestParameters); + } + }); + } + // endregion + // endregion + // -------------------------------------------------------- + // ----------------- Channel Groups API ------------------- + // -------------------------------------------------------- + // region Channel Groups API + /** + * PubNub Channel Groups API group. + */ + get channelGroups() { + return this._channelGroups; + } + // endregion + // -------------------------------------------------------- + // ---------------- Push Notifications API ----------------- + // -------------------------------------------------------- + // region Push Notifications API + /** + * PubNub Push Notifications API group. + */ + get push() { + return this._push; + } + /** + * Share file to a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous file sharing response or `void` in case if `callback` provided. + */ + sendFile(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + if (!this._configuration.PubNubFile) + throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Send file with parameters:`, + })); + const sendFileRequest = new SendFileRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, PubNubFile: this._configuration.PubNubFile, fileUploadPublishRetryLimit: this._configuration.fileUploadPublishRetryLimit, file: parameters.file, sendRequest: this.sendRequest.bind(this), publishFile: this.publishFile.bind(this), crypto: this._configuration.getCryptoModule(), cryptography: this.cryptography ? this.cryptography : undefined })); + const status = { + error: false, + operation: RequestOperation$1.PNPublishFileOperation, + category: StatusCategory$1.PNAcknowledgmentCategory, + statusCode: 0, + }; + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Send file success. File shared with ${response.id} ID.`); + }; + return sendFileRequest + .process() + .then((response) => { + status.statusCode = response.status; + logResponse(response); + if (callback) + return callback(status, response); + return response; + }) + .catch((error) => { + let errorStatus; + if (error instanceof PubNubError) + errorStatus = error.status; + else if (error instanceof PubNubAPIError) + errorStatus = error.toStatus(status.operation); + this.logger.error('PubNub', () => ({ + messageType: 'error', + message: new PubNubError('File sending error. Check status for details', errorStatus), + })); + // Notify callback (if possible). + if (callback && errorStatus) + callback(errorStatus, null); + throw new PubNubError('REST API request processing error. Check status for details', errorStatus); + }); + } + }); + } + /** + * Publish file message to a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous publish file message response or `void` in case if `callback` provided. + */ + publishFile(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + if (!this._configuration.PubNubFile) + throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Publish file message with parameters:`, + })); + const request = new PublishFileMessageRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule() })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Publish file message success. File message published with timetoken: ${response.timetoken}`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Retrieve list of shared files in specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous shared files list response or `void` in case if `callback` provided. + */ + listFiles(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `List files with parameters:`, + })); + const request = new FilesListRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `List files success. There are ${response.count} uploaded files.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + // endregion + // region Get Download Url + /** + * Get file download Url. + * + * @param parameters - Request configuration parameters. + * + * @returns File download Url. + */ + getFileUrl(parameters) { + var _a; + { + const request = this.transport.request(new GetFileDownloadUrlRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })).request()); + const query = (_a = request.queryParameters) !== null && _a !== void 0 ? _a : {}; + const queryString = Object.keys(query) + .map((key) => { + const queryValue = query[key]; + if (!Array.isArray(queryValue)) + return `${key}=${encodeString(queryValue)}`; + return queryValue.map((value) => `${key}=${encodeString(value)}`).join('&'); + }) + .join('&'); + return `${request.origin}${request.path}?${queryString}`; + } + } + /** + * Download a shared file from a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous download shared file response or `void` in case if `callback` provided. + */ + downloadFile(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + if (!this._configuration.PubNubFile) + throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Download file with parameters:`, + })); + const request = new DownloadFileRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, PubNubFile: this._configuration.PubNubFile, cryptography: this.cryptography ? this.cryptography : undefined, crypto: this._configuration.getCryptoModule() })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Download file success.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return (yield this.sendRequest(request).then((response) => { + logResponse(response); + return response; + })); + } + }); + } + /** + * Delete a shared file from a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous delete shared file response or `void` in case if `callback` provided. + */ + deleteFile(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Delete file with parameters:`, + })); + const request = new DeleteFileRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Delete file success. Deleted file with ${parameters.id} ID.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + Get current high-precision timetoken. + * + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get current timetoken response or `void` in case if `callback` provided. + */ + time(callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', 'Get service time.'); + const request = new TimeRequest(); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get service time success. Current timetoken: ${response.timetoken}`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + // endregion + // -------------------------------------------------------- + // -------------------- Event emitter --------------------- + // -------------------------------------------------------- + // region Event emitter + /** + * Emit received a status update. + * + * Use global and local event dispatchers to deliver a status object. + * + * @param status - Status object which should be emitted through the listeners. + * + * @internal + */ + emitStatus(status) { + var _a; + (_a = this.eventDispatcher) === null || _a === void 0 ? void 0 : _a.handleStatus(status); + } + /** + * Emit receiver real-time event. + * + * Use global and local event dispatchers to deliver an event object. + * + * @param cursor - Next subscription loop timetoken. + * @param event - Event object which should be emitted through the listeners. + * + * @internal + */ + emitEvent(cursor, event) { + var _a; + { + if (this._globalSubscriptionSet) + this._globalSubscriptionSet.handleEvent(cursor, event); + (_a = this.eventDispatcher) === null || _a === void 0 ? void 0 : _a.handleEvent(event); + Object.values(this.eventHandleCapable).forEach((eventHandleCapable) => { + if (eventHandleCapable !== this._globalSubscriptionSet) + eventHandleCapable.handleEvent(cursor, event); + }); + } + } + /** + * Set a connection status change event handler. + * + * @param listener - Listener function, which will be called each time when the connection status changes. + */ + set onStatus(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onStatus = listener; + } + } + /** + * Set a new message handler. + * + * @param listener - Listener function, which will be called each time when a new message + * is received from the real-time network. + */ + set onMessage(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onMessage = listener; + } + } + /** + * Set a new presence events handler. + * + * @param listener - Listener function, which will be called each time when a new + * presence event is received from the real-time network. + */ + set onPresence(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onPresence = listener; + } + } + /** + * Set a new signal handler. + * + * @param listener - Listener function, which will be called each time when a new signal + * is received from the real-time network. + */ + set onSignal(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onSignal = listener; + } + } + /** + * Set a new app context event handler. + * + * @param listener - Listener function, which will be called each time when a new + * app context event is received from the real-time network. + */ + set onObjects(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onObjects = listener; + } + } + /** + * Set a new message reaction event handler. + * + * @param listener - Listener function, which will be called each time when a + * new message reaction event is received from the real-time network. + */ + set onMessageAction(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onMessageAction = listener; + } + } + /** + * Set a new file handler. + * + * @param listener - Listener function, which will be called each time when a new file + * is received from the real-time network. + */ + set onFile(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onFile = listener; + } + } + /** + * Set a new DataSync event handler. + * + * @param listener - Listener function, which will be called each time when a new + * DataSync event is received from the real-time network. + */ + set onDataSync(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onDataSync = listener; + } + } + /** + * Set events handler. + * + * @param listener - Events listener configuration object, which lets specify handlers for multiple + * types of events. + */ + addListener(listener) { + { + if (this.eventDispatcher) { + this.eventDispatcher.addListener(listener); + } + } + } + /** + * Remove real-time event listener. + * + * @param listener - Event listener configuration, which should be removed from the list of notified + * listeners. **Important:** Should be the same object which has been passed to the + * {@link addListener}. + */ + removeListener(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.removeListener(listener); + } + } + /** + * Clear all real-time event listeners. + */ + removeAllListeners() { + { + if (this.eventDispatcher) + this.eventDispatcher.removeAllListeners(); + } + } + // endregion + // -------------------------------------------------------- + // ------------------ Cryptography API -------------------- + // -------------------------------------------------------- + // region Cryptography + // region Common + /** + * Encrypt data. + * + * @param data - Stringified data which should be encrypted using `CryptoModule`. + * @param [customCipherKey] - Cipher key which should be used to encrypt data. **Deprecated:** + * use {@link Configuration#cryptoModule|cryptoModule} instead. + * + * @returns Data encryption result as a string. + * + * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. + */ + encrypt(data, customCipherKey) { + this.logger.warn('PubNub', "'encrypt' is deprecated. Use cryptoModule instead."); + const cryptoModule = this._configuration.getCryptoModule(); + if (!customCipherKey && cryptoModule && typeof data === 'string') { + const encrypted = cryptoModule.encrypt(data); + return typeof encrypted === 'string' ? encrypted : encode(encrypted); + } + if (!this.crypto) + throw new Error('Encryption error: cypher key not set'); + { + return this.crypto.encrypt(data, customCipherKey); + } + } + /** + * Decrypt data. + * + * @param data - Stringified data which should be encrypted using `CryptoModule`. + * @param [customCipherKey] - Cipher key which should be used to decrypt data. **Deprecated:** + * use {@link Configuration#cryptoModule|cryptoModule} instead. + * + * @returns Data decryption result as an object. + * + * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. + */ + decrypt(data, customCipherKey) { + this.logger.warn('PubNub', "'decrypt' is deprecated. Use cryptoModule instead."); + const cryptoModule = this._configuration.getCryptoModule(); + if (!customCipherKey && cryptoModule) { + const decrypted = cryptoModule.decrypt(data); + return decrypted instanceof ArrayBuffer ? JSON.parse(new TextDecoder().decode(decrypted)) : decrypted; + } + if (!this.crypto) + throw new Error('Decryption error: cypher key not set'); + { + return this.crypto.decrypt(data, customCipherKey); + } + } + /** + * Encrypt file content. + * + * @param keyOrFile - Cipher key which should be used to encrypt data or file which should be + * encrypted using `CryptoModule`. + * @param [file] - File which should be encrypted using legacy cryptography. + * + * @returns Asynchronous file encryption result. + * + * @throws Error if a source file isn't provided. + * @throws File constructor not provided. + * @throws Crypto module is missing (if non-legacy flow used). + * + * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. + */ + encryptFile(keyOrFile, file) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + if (typeof keyOrFile !== 'string') + file = keyOrFile; + if (!file) + throw new Error('File encryption error. Source file is missing.'); + if (!this._configuration.PubNubFile) + throw new Error('File encryption error. File constructor not configured.'); + if (typeof keyOrFile !== 'string' && !this._configuration.getCryptoModule()) + throw new Error('File encryption error. Crypto module not configured.'); + if (typeof keyOrFile === 'string') { + if (!this.cryptography) + throw new Error('File encryption error. File encryption not available'); + return this.cryptography.encryptFile(keyOrFile, file, this._configuration.PubNubFile); + } + return (_a = this._configuration.getCryptoModule()) === null || _a === void 0 ? void 0 : _a.encryptFile(file, this._configuration.PubNubFile); + }); + } + /** + * Decrypt file content. + * + * @param keyOrFile - Cipher key which should be used to decrypt data or file which should be + * decrypted using `CryptoModule`. + * @param [file] - File which should be decrypted using legacy cryptography. + * + * @returns Asynchronous file decryption result. + * + * @throws Error if source file isn't provided. + * @throws File constructor not provided. + * @throws Crypto module is missing (if non-legacy flow used). + * + * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. + */ + decryptFile(keyOrFile, file) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + if (typeof keyOrFile !== 'string') + file = keyOrFile; + if (!file) + throw new Error('File encryption error. Source file is missing.'); + if (!this._configuration.PubNubFile) + throw new Error('File decryption error. File constructor' + ' not configured.'); + if (typeof keyOrFile === 'string' && !this._configuration.getCryptoModule()) + throw new Error('File decryption error. Crypto module not configured.'); + if (typeof keyOrFile === 'string') { + if (!this.cryptography) + throw new Error('File decryption error. File decryption not available'); + return this.cryptography.decryptFile(keyOrFile, file, this._configuration.PubNubFile); + } + return (_a = this._configuration.getCryptoModule()) === null || _a === void 0 ? void 0 : _a.decryptFile(file, this._configuration.PubNubFile); + }); + } + } + /** + * {@link ArrayBuffer} to {@link string} decoder. + * + * @internal + */ + PubNubCore.decoder = new TextDecoder(); + // -------------------------------------------------------- + // ----------------------- Static ------------------------- + // -------------------------------------------------------- + // region Static + /** + * Type of REST API endpoint which reported status. + */ + PubNubCore.OPERATIONS = RequestOperation$1; + /** + * API call status category. + */ + PubNubCore.CATEGORIES = StatusCategory$1; + /** + * Enum with API endpoint groups which can be used with retry policy to set up exclusions (which shouldn't be + * retried). + */ + PubNubCore.Endpoint = Endpoint; + /** + * Exponential retry policy constructor. + */ + PubNubCore.ExponentialRetryPolicy = RetryPolicy.ExponentialRetryPolicy; + /** + * Linear retry policy constructor. + */ + PubNubCore.LinearRetryPolicy = RetryPolicy.LinearRetryPolicy; + /** + * Disabled / inactive retry policy. + * + * **Note:** By default `ExponentialRetryPolicy` is set for subscribe requests and this one can be used to disable + * retry policy for all requests (setting `undefined` for retry configuration will set default policy). + */ + PubNubCore.NoneRetryPolicy = RetryPolicy.None; + /** + * Available minimum log levels. + */ + PubNubCore.LogLevel = LogLevel; + + /** + * Cbor decoder module. + * + * @internal + */ + /** + * CBOR data decoder. + * + * @internal + */ + class Cbor { + constructor(decode, base64ToBinary) { + this.decode = decode; + this.base64ToBinary = base64ToBinary; + } + /** + * Decode CBOR base64-encoded object. + * + * @param tokenString - Base64-encoded token. + * + * @returns Token object decoded from CBOR. + */ + decodeToken(tokenString) { + let padding = ''; + if (tokenString.length % 4 === 3) + padding = '='; + else if (tokenString.length % 4 === 2) + padding = '=='; + const cleaned = tokenString.replace(/-/gi, '+').replace(/_/gi, '/') + padding; + const result = this.decode(this.base64ToBinary(cleaned)); + return typeof result === 'object' ? result : undefined; + } + } + + /* eslint no-bitwise: ["error", { "allow": ["~", "&", ">>"] }] */ + /* global navigator */ + /** + * PubNub client for browser platform. + */ + class PubNub extends PubNubCore { + /** + * Create and configure the PubNub client core. + * + * @param configuration - User-provided PubNub client configuration. + * + * @returns Configured and ready to use PubNub client. + */ + constructor(configuration) { + var _a; + const sharedWorkerRequested = configuration.subscriptionWorkerUrl !== undefined; + const configurationCopy = setDefaults(configuration); + const platformConfiguration = Object.assign(Object.assign({}, configurationCopy), { sdkFamily: 'Web' }); + platformConfiguration.PubNubFile = PubNubFile; + // Prepare full client configuration. + const clientConfiguration = makeConfiguration(platformConfiguration, (cryptoConfiguration) => { + if (!cryptoConfiguration.cipherKey) + return undefined; + { + const cryptoModule = new WebCryptoModule({ + default: new LegacyCryptor(Object.assign(Object.assign({}, cryptoConfiguration), (!cryptoConfiguration.logger ? { logger: clientConfiguration.logger() } : {}))), + cryptors: [new AesCbcCryptor({ cipherKey: cryptoConfiguration.cipherKey })], + }); + return cryptoModule; + } + }); + if (configuration.subscriptionWorkerLogVerbosity) + configuration.subscriptionWorkerLogLevel = LogLevel.Debug; + else if (configuration.subscriptionWorkerLogLevel === undefined) + configuration.subscriptionWorkerLogLevel = LogLevel.None; + if (configuration.subscriptionWorkerLogVerbosity !== undefined) { + clientConfiguration + .logger() + .warn('Configuration', "'subscriptionWorkerLogVerbosity' is deprecated. Use 'subscriptionWorkerLogLevel' instead."); + } + { + // Ensure that the logger has been passed to the user-provided crypto module. + if (clientConfiguration.getCryptoModule()) + clientConfiguration.getCryptoModule().logger = clientConfiguration.logger(); + } + // Prepare Token manager. + let tokenManager; + { + tokenManager = new TokenManager(new Cbor((arrayBuffer) => stringifyBufferKeys(CborReader.decode(arrayBuffer)), decode)); + } + // Legacy crypto (legacy data encryption / decryption and request signature support). + let crypto; + { + if (clientConfiguration.getCipherKey() || clientConfiguration.secretKey) { + crypto = new Crypto({ + secretKey: clientConfiguration.secretKey, + cipherKey: clientConfiguration.getCipherKey(), + useRandomIVs: clientConfiguration.getUseRandomIVs(), + customEncrypt: clientConfiguration.getCustomEncrypt(), + customDecrypt: clientConfiguration.getCustomDecrypt(), + logger: clientConfiguration.logger(), + }); + } + } + // Settings change handlers + let heartbeatIntervalChangeHandler = () => { }; + let presenceStateChangeHandler = () => { }; + let authenticationChangeHandler = () => { }; + let userIdChangeHandler = () => { }; + let cryptography; + cryptography = new WebCryptography(); + // Setup transport provider. + let transport = new WebTransport(clientConfiguration.logger(), platformConfiguration.transport); + { + if (configurationCopy.subscriptionWorkerUrl) { + try { + // Inject subscription worker into the transport provider stack. + const middleware = new SubscriptionWorkerMiddleware({ + clientIdentifier: clientConfiguration._instanceId, + subscriptionKey: clientConfiguration.subscribeKey, + userId: clientConfiguration.getUserId(), + workerUrl: configurationCopy.subscriptionWorkerUrl, + sdkVersion: clientConfiguration.getVersion(), + heartbeatInterval: clientConfiguration.getHeartbeatInterval(), + announceSuccessfulHeartbeats: clientConfiguration.announceSuccessfulHeartbeats, + announceFailedHeartbeats: clientConfiguration.announceFailedHeartbeats, + workerOfflineClientsCheckInterval: platformConfiguration.subscriptionWorkerOfflineClientsCheckInterval, + workerUnsubscribeOfflineClients: platformConfiguration.subscriptionWorkerUnsubscribeOfflineClients, + workerLogLevel: platformConfiguration.subscriptionWorkerLogLevel, + tokenManager, + transport, + logger: clientConfiguration.logger(), + }); + presenceStateChangeHandler = (state) => middleware.onPresenceStateChange(state); + heartbeatIntervalChangeHandler = (interval) => middleware.onHeartbeatIntervalChange(interval); + authenticationChangeHandler = (auth) => middleware.onTokenChange(auth); + userIdChangeHandler = (userId) => middleware.onUserIdChange(userId); + transport = middleware; + if (configurationCopy.subscriptionWorkerUnsubscribeOfflineClients && + typeof window !== 'undefined' && + window.addEventListener) { + window.addEventListener('pagehide', (event) => { + if (!event.persisted) + middleware.terminate(); + }, { once: true }); + } + } + catch (e) { + clientConfiguration.logger().error('PubNub', () => ({ + messageType: 'error', + message: e, + })); + } + } + else if (sharedWorkerRequested) { + clientConfiguration + .logger() + .warn('PubNub', 'SharedWorker not supported in this browser. Fallback to the original transport.'); + } + } + const transportMiddleware = new PubNubMiddleware({ + clientConfiguration, + tokenManager, + transport, + }); + super({ + configuration: clientConfiguration, + transport: transportMiddleware, + cryptography, + tokenManager, + crypto, + }); + /** + * PubNub File constructor. + */ + this.File = PubNubFile; + this.onHeartbeatIntervalChange = heartbeatIntervalChangeHandler; + this.onAuthenticationChange = authenticationChangeHandler; + this.onPresenceStateChange = presenceStateChangeHandler; + this.onUserIdChange = userIdChangeHandler; + { + if (transport instanceof SubscriptionWorkerMiddleware) { + transport.emitStatus = this.emitStatus.bind(this); + const disconnect = this.disconnect.bind(this); + this.disconnect = (isOffline) => { + transport.disconnect(); + disconnect(); + }; + } + } + // `window` is unavailable in DOM-less contexts (e.g. MV3 service workers); only attach network + // listeners when a `window` with event support actually exists. + if (((_a = configuration.listenToBrowserNetworkEvents) !== null && _a !== void 0 ? _a : true) && + typeof window !== 'undefined' && + window.addEventListener) { + window.addEventListener('offline', () => { + this.networkDownDetected(); + }); + window.addEventListener('online', () => { + this.networkUpDetected(); + }); + } + } + networkDownDetected() { + this.logger.debug('PubNub', 'Network down detected'); + this.emitStatus({ category: PubNub.CATEGORIES.PNNetworkDownCategory }); + if (this._configuration.restore) + this.disconnect(true); + else + this.destroy(true); + } + networkUpDetected() { + this.logger.debug('PubNub', 'Network up detected'); + this.emitStatus({ category: PubNub.CATEGORIES.PNNetworkUpCategory }); + this.reconnect(); + } + } + /** + * Data encryption / decryption module constructor. + */ + PubNub.CryptoModule = WebCryptoModule ; + + return PubNub; + +})); diff --git a/lib/core/endpoints/subscribe.js b/lib/core/endpoints/subscribe.js index bc7a3a212..7666d6fab 100644 --- a/lib/core/endpoints/subscribe.js +++ b/lib/core/endpoints/subscribe.js @@ -389,7 +389,31 @@ class BaseSubscribeRequest extends request_1.AbstractRequest { // `data` mirrors the object as sent by the service, and its shape is tied to `event` / // `objectType` — which is what makes `message` a discriminated union for the consumer. let message; - if (metadata.event === 'delete') + if (metadata.event === 'delete' && objectType === 'membership') { + const data = { + id: raw.id, + deletedAt: raw.deletedAt, + }; + // Membership deletes name the endpoints they joined. Other fields stay trimmed. + if (typeof raw.channelId === 'string') + data.channelId = raw.channelId; + if (typeof raw.userId === 'string') + data.userId = raw.userId; + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data }); + } + else if (metadata.event === 'delete' && objectType === 'relationship') { + const data = { + id: raw.id, + deletedAt: raw.deletedAt, + }; + // Relationship deletes name the entities they linked. Other fields stay trimmed. + if (typeof raw.entityAId === 'string') + data.entityAId = raw.entityAId; + if (typeof raw.entityBId === 'string') + data.entityBId = raw.entityBId; + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data }); + } + else if (metadata.event === 'delete') message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: { id: raw.id, deletedAt: raw.deletedAt } }); else if (objectType === 'membership') message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); diff --git a/lib/types/index.d.ts b/lib/types/index.d.ts index c8613331e..57a983989 100644 --- a/lib/types/index.d.ts +++ b/lib/types/index.d.ts @@ -4224,6 +4224,38 @@ declare namespace PubNub { */ deletedAt?: string; }; + /** + * DataSync membership delete payload. + * + * A removed membership still names the channel and user it joined, so a subscriber on either + * endpoint can tell which membership went away. The rest of the membership body is omitted. + */ + export type DataSyncMembershipDeleteData = DataSyncDeleteData & { + /** + * Id of the channel the removed membership joined. + */ + channelId?: string; + /** + * Id of the user the removed membership joined. + */ + userId?: string; + }; + /** + * DataSync relationship delete payload. + * + * A removed relationship still names the two entities it linked, so a subscriber on either + * endpoint can tell which relationship went away. The rest of the relationship body is omitted. + */ + export type DataSyncRelationshipDeleteData = DataSyncDeleteData & { + /** + * First entity id in the removed relationship. + */ + entityAId?: string; + /** + * Second entity id in the removed relationship. + */ + entityBId?: string; + }; /** * Parsed DataSync change event for a single `event` / `objectType` combination. @@ -4279,7 +4311,8 @@ declare namespace PubNub { /** * Changed object information. * - * For `delete` events only `{ id, deletedAt }` is populated. + * For `delete` events the body is `{ id, deletedAt }`. A membership delete also includes + * `channelId` and `userId`. A relationship delete also includes `entityAId` and `entityBId`. */ data: Data; }; @@ -4289,15 +4322,18 @@ declare namespace PubNub { * * Discriminated by {@link DataSyncChangeEvent.event | event} and * {@link DataSyncChangeEvent.objectType | objectType}, so narrowing on either tells the compiler the - * exact shape of `data`: a `delete` carries only `{ id, deletedAt }`, a `membership` names its - * endpoints `channelId` / `userId`, and a developer-defined `relationship` names them - * `entityAId` / `entityBId`. + * exact shape of `data`: a `delete` carries `{ id, deletedAt }`, plus the linked ids for a + * membership (`channelId` / `userId`) or a relationship (`entityAId` / `entityBId`). A membership + * create or update names its endpoints `channelId` / `userId`, and a developer-defined + * relationship names them `entityAId` / `entityBId`. */ export type DataSyncData = | DataSyncChangeEvent<'create' | 'update', 'user' | 'channel' | 'entity', DataSyncEntityData> | DataSyncChangeEvent<'create' | 'update', 'relationship', DataSyncRelationshipData> | DataSyncChangeEvent<'create' | 'update', 'membership', DataSyncMembershipData> - | DataSyncChangeEvent<'delete', DataSyncObjectType, DataSyncDeleteData>; + | DataSyncChangeEvent<'delete', 'membership', DataSyncMembershipDeleteData> + | DataSyncChangeEvent<'delete', 'relationship', DataSyncRelationshipDeleteData> + | DataSyncChangeEvent<'delete', 'user' | 'channel' | 'entity', DataSyncDeleteData>; /** * File service response. diff --git a/src/core/endpoints/subscribe.ts b/src/core/endpoints/subscribe.ts index beca432d2..7aea8edd0 100644 --- a/src/core/endpoints/subscribe.ts +++ b/src/core/endpoints/subscribe.ts @@ -580,6 +580,42 @@ export type DataSyncDeleteData = { deletedAt?: string; }; +/** + * DataSync membership delete payload. + * + * A removed membership still names the channel and user it joined, so a subscriber on either + * endpoint can tell which membership went away. The rest of the membership body is omitted. + */ +export type DataSyncMembershipDeleteData = DataSyncDeleteData & { + /** + * Id of the channel the removed membership joined. + */ + channelId?: string; + + /** + * Id of the user the removed membership joined. + */ + userId?: string; +}; + +/** + * DataSync relationship delete payload. + * + * A removed relationship still names the two entities it linked, so a subscriber on either + * endpoint can tell which relationship went away. The rest of the relationship body is omitted. + */ +export type DataSyncRelationshipDeleteData = DataSyncDeleteData & { + /** + * First entity id in the removed relationship. + */ + entityAId?: string; + + /** + * Second entity id in the removed relationship. + */ + entityBId?: string; +}; + /** * Parsed DataSync change event for a single `event` / `objectType` combination. * @@ -642,7 +678,8 @@ type DataSyncChangeEvent< /** * Changed object information. * - * For `delete` events only `{ id, deletedAt }` is populated. + * For `delete` events the body is `{ id, deletedAt }`. A membership delete also includes + * `channelId` and `userId`. A relationship delete also includes `entityAId` and `entityBId`. */ data: Data; }; @@ -652,15 +689,18 @@ type DataSyncChangeEvent< * * Discriminated by {@link DataSyncChangeEvent.event | event} and * {@link DataSyncChangeEvent.objectType | objectType}, so narrowing on either tells the compiler the - * exact shape of `data`: a `delete` carries only `{ id, deletedAt }`, a `membership` names its - * endpoints `channelId` / `userId`, and a developer-defined `relationship` names them - * `entityAId` / `entityBId`. + * exact shape of `data`: a `delete` carries `{ id, deletedAt }`, plus the linked ids for a + * membership (`channelId` / `userId`) or a relationship (`entityAId` / `entityBId`). A membership + * create or update names its endpoints `channelId` / `userId`, and a developer-defined + * relationship names them `entityAId` / `entityBId`. */ export type DataSyncData = | DataSyncChangeEvent<'create' | 'update', 'user' | 'channel' | 'entity', DataSyncEntityData> | DataSyncChangeEvent<'create' | 'update', 'relationship', DataSyncRelationshipData> | DataSyncChangeEvent<'create' | 'update', 'membership', DataSyncMembershipData> - | DataSyncChangeEvent<'delete', DataSyncObjectType, DataSyncDeleteData>; + | DataSyncChangeEvent<'delete', 'membership', DataSyncMembershipDeleteData> + | DataSyncChangeEvent<'delete', 'relationship', DataSyncRelationshipDeleteData> + | DataSyncChangeEvent<'delete', 'user' | 'channel' | 'entity', DataSyncDeleteData>; /** * Raw DataSync envelope payload (before parsing). @@ -1184,7 +1224,25 @@ export class BaseSubscribeRequest extends AbstractRequest { + it('membership delete → "delete" event with {id, deletedAt, channelId, userId}', async () => { const { userId, channelId } = await seedEndpoints(); const id = freshId('membership'); await createMembership(id, userId, channelId); @@ -195,7 +195,7 @@ describe('DataSync events — Membership', function () { className: 'Membership', classLevel: 'Global', }); - assertEventDeleteData(event.message.data as Subscription.DataSyncDeleteData, id); + assertEventDeleteData(event.message.data as Subscription.DataSyncDeleteData, id, { channelId, userId }); }); it('routing proof — a subscriber to the membership id receives nothing', async () => { diff --git a/test/integration/endpoints/data_sync/events.relationship.test.ts b/test/integration/endpoints/data_sync/events.relationship.test.ts index 37ba33c6e..744a1c750 100644 --- a/test/integration/endpoints/data_sync/events.relationship.test.ts +++ b/test/integration/endpoints/data_sync/events.relationship.test.ts @@ -4,6 +4,7 @@ * ROUTING RULE: relationship-type events are delivered on the TWO endpoint-entity id channels * (`entityAId` AND `entityBId`), NEVER on the relationship's own id. We therefore subscribe to both * endpoint ids and assert `channel ∈ {customerId, loanQuoteId}`; `data.id` still equals the rel id. + * A delete keeps those endpoint ids on the body along with `id` and `deletedAt`. * */ @@ -199,7 +200,7 @@ describe('DataSync events Relationship REQUESTED_BY', function () { } }); - it('relationship delete delete event with only {id, deletedAt}', async () => { + it('relationship delete event with {id, deletedAt, entityAId, entityBId}', async () => { const { customerId, loanQuoteId } = await seedEndpoints(); const relId = freshId('requested-by'); await createRel(relId, customerId, loanQuoteId); @@ -220,7 +221,10 @@ describe('DataSync events Relationship REQUESTED_BY', function () { className: RELATIONSHIP_CLASS_REQUESTED_BY, classLevel: 'SubKey', }); - assertEventDeleteData(event.message.data as Subscription.DataSyncDeleteData, relId); + assertEventDeleteData(event.message.data as Subscription.DataSyncDeleteData, relId, { + entityAId: customerId, + entityBId: loanQuoteId, + }); }); it('routing proof — a subscriber to the relationship id receives nothing', async () => { diff --git a/test/integration/endpoints/data_sync/helpers.ts b/test/integration/endpoints/data_sync/helpers.ts index d2b4cc08e..bad840b33 100644 --- a/test/integration/endpoints/data_sync/helpers.ts +++ b/test/integration/endpoints/data_sync/helpers.ts @@ -484,16 +484,41 @@ export function assertEventMembershipData( if (exp.payload) assertPayloadContains(data.payload as Record, exp.payload); } -/** Delete body is trimmed to `{ id, deletedAt? }` only. */ -export function assertEventDeleteData(data: Subscription.DataSyncDeleteData, id: string): void { +/** + * Delete body is trimmed to `{ id, deletedAt? }`, plus the linked ids for a membership + * (`channelId` / `userId`) or a relationship (`entityAId` / `entityBId`). Pass `links` to require + * those ids; otherwise every link key must be absent. + */ +export function assertEventDeleteData( + data: Subscription.DataSyncDeleteData & { + channelId?: string; + userId?: string; + entityAId?: string; + entityBId?: string; + }, + id: string, + links?: { channelId: string; userId: string } | { entityAId: string; entityBId: string }, +): void { assert.strictEqual(data.id, id, 'delete data.id'); assert.ok(!('payload' in data), 'no payload on delete'); assert.ok(!('status' in data), 'no status on delete'); - assert.ok(!('entityAId' in data), 'no entityAId on delete'); - assert.ok(!('entityBId' in data), 'no entityBId on delete'); - assert.ok(!('channelId' in data), 'no channelId on delete'); - assert.ok(!('userId' in data), 'no userId on delete'); assert.ok(!('eTag' in data), 'no eTag on delete'); + if (links && 'channelId' in links) { + assert.strictEqual(data.channelId, links.channelId, 'channelId'); + assert.strictEqual(data.userId, links.userId, 'userId'); + assert.ok(!('entityAId' in data), 'no entityAId on membership delete'); + assert.ok(!('entityBId' in data), 'no entityBId on membership delete'); + } else if (links && 'entityAId' in links) { + assert.strictEqual(data.entityAId, links.entityAId, 'entityAId'); + assert.strictEqual(data.entityBId, links.entityBId, 'entityBId'); + assert.ok(!('channelId' in data), 'no channelId on relationship delete'); + assert.ok(!('userId' in data), 'no userId on relationship delete'); + } else { + assert.ok(!('channelId' in data), 'no channelId on delete'); + assert.ok(!('userId' in data), 'no userId on delete'); + assert.ok(!('entityAId' in data), 'no entityAId on delete'); + assert.ok(!('entityBId' in data), 'no entityBId on delete'); + } if (data.deletedAt !== undefined) { assert.strictEqual(typeof data.deletedAt, 'string', 'deletedAt is ISO string'); assert.ok(!Number.isNaN(Date.parse(data.deletedAt)), 'deletedAt parses'); diff --git a/test/unit/data_sync/subscribe-event-parsing.test.ts b/test/unit/data_sync/subscribe-event-parsing.test.ts index d891f1ce5..80c8985d6 100644 --- a/test/unit/data_sync/subscribe-event-parsing.test.ts +++ b/test/unit/data_sync/subscribe-event-parsing.test.ts @@ -227,7 +227,40 @@ const TYPED_MEMBERSHIP_DELETE: WireEnvelope = { classLevel: 'Global', classVersion: 1, }, - data: { id: 'm.mem914058452', deletedAt: '2026-08-13T03:46:14.418911Z' }, + data: { + id: 'm.mem914058452', + deletedAt: '2026-08-13T03:46:14.418911Z', + channelId: 'c.mem914058452', + userId: 'u.mem914058452', + status: 'active', + payload: { role: 'member' }, + }, + }, +}; + +const TYPED_RELATIONSHIP_DELETE: WireEnvelope = { + e: 5, + p: { t: '17865927752415830', r: 21 }, + c: 'cust-70b1d0f54f', + b: 'cust-70b1d0f54f', + d: { + version: '1.0', + metadata: { + event: 'delete', + source: 'data-sync', + type: 'relationship', + className: 'REQUESTED_BY', + classLevel: 'SubKey', + classVersion: 1, + }, + data: { + id: 'rel-c129c5a237', + deletedAt: '2026-08-13T03:46:14.418911Z', + entityAId: 'cust-70b1d0f54f', + entityBId: 'lq-871f0a90f3', + status: 'active', + payload: { linkedAt: '2026-07-06T10:00:00.000Z' }, + }, }, }; @@ -340,7 +373,7 @@ describe('DataSync subscribe event parsing', () => { }); describe('delete events', () => { - it('trims the delete body to { id, deletedAt }', async () => { + it('keeps channelId and userId on a membership delete and drops the rest', async () => { const message = await parseDataSyncMessage(TYPED_MEMBERSHIP_DELETE); assert.strictEqual(message.event, 'delete', 'event'); @@ -349,6 +382,21 @@ describe('DataSync subscribe event parsing', () => { assert.deepStrictEqual(message.data, { id: 'm.mem914058452', deletedAt: '2026-08-13T03:46:14.418911Z', + channelId: 'c.mem914058452', + userId: 'u.mem914058452', + }); + }); + + it('keeps entityAId and entityBId on a relationship delete and drops the rest', async () => { + const message = await parseDataSyncMessage(TYPED_RELATIONSHIP_DELETE); + + assert.strictEqual(message.event, 'delete', 'event'); + assert.strictEqual(message.objectType, 'relationship', 'objectType'); + assert.deepStrictEqual(message.data, { + id: 'rel-c129c5a237', + deletedAt: '2026-08-13T03:46:14.418911Z', + entityAId: 'cust-70b1d0f54f', + entityBId: 'lq-871f0a90f3', }); }); }); @@ -383,13 +431,27 @@ describe('DataSync subscribe event parsing', () => { assert.strictEqual(message.data.entityBId, 'lq-871f0a90f3', 'entityBId'); }); - it('narrows a delete body to { id, deletedAt }', async () => { + it('narrows a membership delete body to { id, deletedAt, channelId, userId }', async () => { const message = await parseDataSyncMessage(TYPED_MEMBERSHIP_DELETE); - if (message.event !== 'delete') throw new Error('expected a delete event'); + if (message.event !== 'delete' || message.objectType !== 'membership') + throw new Error('expected a membership delete event'); assert.strictEqual(message.data.id, 'm.mem914058452', 'id'); assert.strictEqual(message.data.deletedAt, '2026-08-13T03:46:14.418911Z', 'deletedAt'); - // @ts-expect-error A delete body carries no object fields. + assert.strictEqual(message.data.channelId, 'c.mem914058452', 'channelId'); + assert.strictEqual(message.data.userId, 'u.mem914058452', 'userId'); + // @ts-expect-error A delete body carries no payload. + assert.strictEqual(message.data.payload, undefined, 'no payload on a delete body'); + }); + + it('narrows a relationship delete body to { id, deletedAt, entityAId, entityBId }', async () => { + const message = await parseDataSyncMessage(TYPED_RELATIONSHIP_DELETE); + if (message.event !== 'delete' || message.objectType !== 'relationship') + throw new Error('expected a relationship delete event'); + + assert.strictEqual(message.data.entityAId, 'cust-70b1d0f54f', 'entityAId'); + assert.strictEqual(message.data.entityBId, 'lq-871f0a90f3', 'entityBId'); + // @ts-expect-error A delete body carries no payload. assert.strictEqual(message.data.payload, undefined, 'no payload on a delete body'); }); }); From 1aee35902d7f9ffd0283c54a00f78267eff26205 Mon Sep 17 00:00:00 2001 From: "mohit.tejani" Date: Thu, 22 Oct 2026 17:38:17 +0530 Subject: [PATCH 8/9] README update as per review comment --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4244eeb86..584e91be5 100644 --- a/README.md +++ b/README.md @@ -38,11 +38,11 @@ This example runs in Node.js 22 or later. It subscribes to hello_world, publishe ### Get your keys -Open the [PubNub Admin Portal](https://admin.pubnub.com/). +1. Open the [PubNub Admin Portal](https://admin.pubnub.com/). -Create an app and a keyset for development, or select an existing development keyset. +2. Create an app and a keyset for development, or select an existing development keyset. -Copy its publish key and subscribe key. +3. Copy its publish key and subscribe key. If Access Manager is enabled, obtain a token from your trusted backend and call `pubnub.setToken(token)` before accessing protected resources. Keep the secret key and token-granting logic on the backend. @@ -74,7 +74,7 @@ subscription.onMessage = (event) => { pubnub.addListener({ status: async (status) => { - if (status.category === "PNConnectedCategory" && !published) { + if (status.category === PubNub.CATEGORIES.PNConnectedCategory && !published) { published = true; await pubnub.publish({ From 57af37787a5978d23de7e964eaef26897a866e2b Mon Sep 17 00:00:00 2001 From: PubNub Release Bot <120067856+pubnub-release-bot@users.noreply.github.com> Date: Thu, 22 Oct 2026 14:08:39 +0000 Subject: [PATCH 9/9] PubNub SDK v13.1.3 release. --- .pubnub.yml | 15 +- CHANGELOG.md | 8 + README.md | 4 +- dist/web/pubnub.js | 42730 ++++++++++++------------- dist/web/pubnub.min.js | 2 +- lib/core/components/configuration.js | 2 +- lib/types/index.d.ts | 2 + package.json | 2 +- src/core/components/configuration.ts | 2 +- 9 files changed, 21393 insertions(+), 21374 deletions(-) diff --git a/.pubnub.yml b/.pubnub.yml index 480f1a8dd..84aa16daf 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -1,5 +1,14 @@ --- changelog: + - date: 2026-10-22 + version: v13.1.3 + changes: + - type: improvement + text: "Upgrade fflate, undici dependency version suggested by Synk." + - type: improvement + text: "Update dataSync event types for delete membership and relationship events." + - type: improvement + text: "Updated README to reflect SDK support for TypeScript and various environments, added installation instructions, and improved clarity on usage examples." - date: 2026-10-14 version: v13.1.2 changes: @@ -1522,7 +1531,7 @@ supported-platforms: - 'Ubuntu 14.04 and up' - 'Windows 7 and up' version: 'Pubnub Javascript for Node' -version: '13.1.2' +version: '13.1.3' sdks: - full-name: PubNub Javascript SDK short-name: Javascript @@ -1538,7 +1547,7 @@ sdks: - distribution-type: source distribution-repository: GitHub release package-name: pubnub.js - location: https://github.com/pubnub/javascript/archive/refs/tags/v13.1.2.zip + location: https://github.com/pubnub/javascript/archive/refs/tags/v13.1.3.zip requires: - name: 'agentkeepalive' min-version: '3.5.2' @@ -2209,7 +2218,7 @@ sdks: - distribution-type: library distribution-repository: GitHub release package-name: pubnub.js - location: https://github.com/pubnub/javascript/releases/download/v13.1.2/pubnub.13.1.2.js + location: https://github.com/pubnub/javascript/releases/download/v13.1.3/pubnub.13.1.3.js requires: - name: 'agentkeepalive' min-version: '3.5.2' diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f0568bd6..5ff566410 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## v13.1.3 +October 22 2026 + +#### Modified +- Upgrade fflate, undici dependency version suggested by Synk. Fixed the following issues reported by [@pubnub-snyk-universal-prd[bot]](https://github.com/pubnub-snyk-universal-prd[bot]) and [@pubnub-snyk-universal-prd[bot]](https://github.com/pubnub-snyk-universal-prd[bot]): [#528](https://github.com/pubnub/javascript/issues/528) and [#530](https://github.com/pubnub/javascript/issues/530). +- Update dataSync event types for delete membership and relationship events. +- Updated README to reflect SDK support for TypeScript and various environments, added installation instructions, and improved clarity on usage examples. + ## v13.1.2 October 14 2026 diff --git a/README.md b/README.md index 584e91be5..f0822abe0 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ npm install pubnub Or download one of our builds from our CDN: -- https://cdn.pubnub.com/sdk/javascript/pubnub.13.1.2.js -- https://cdn.pubnub.com/sdk/javascript/pubnub.13.1.2.min.js +- https://cdn.pubnub.com/sdk/javascript/pubnub.13.1.3.js +- https://cdn.pubnub.com/sdk/javascript/pubnub.13.1.3.min.js For other installation methods, see [environment setup](https://www.pubnub.com/docs/sdks/javascript/environment-setup). diff --git a/dist/web/pubnub.js b/dist/web/pubnub.js index 41a71dd0e..b2f732a97 100644 --- a/dist/web/pubnub.js +++ b/dist/web/pubnub.js @@ -1,17 +1,17 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.PubNub = factory()); -})(this, (function () { 'use strict'; - - var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - function getDefaultExportFromCjs (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; - } - - var cbor = {exports: {}}; - +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.PubNub = factory()); +})(this, (function () { 'use strict'; + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + } + + var cbor = {exports: {}}; + /* * The MIT License (MIT) * @@ -34,9 +34,9 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. - */ - - (function (module) { + */ + + (function (module) { (function(global, undefined$1) { var POW_2_24 = Math.pow(2, -24), POW_2_32 = Math.pow(2, 32), POW_2_53 = Math.pow(2, 53); @@ -415,12 +415,12 @@ else if (!global.CBOR) global.CBOR = obj; - })(commonjsGlobal); - } (cbor)); - - var cborExports = cbor.exports; - var CborReader = /*@__PURE__*/getDefaultExportFromCjs(cborExports); - + })(commonjsGlobal); + } (cbor)); + + var cborExports = cbor.exports; + var CborReader = /*@__PURE__*/getDefaultExportFromCjs(cborExports); + /****************************************************************************** Copyright (c) Microsoft Corporation. @@ -463,21345 +463,21345 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; - }; - - /** - * Crypto module. - */ - class AbstractCryptoModule { - // -------------------------------------------------------- - // --------------- Convenience functions ------------------ - // -------------------------------------------------------- - // region Convenience functions - /** - * Construct crypto module with legacy cryptor for encryption and both legacy and AES-CBC - * cryptors for decryption. - * - * @param config Cryptors configuration options. - * - * @returns Crypto module which encrypts data using legacy cryptor. - * - * @throws Error if `config.cipherKey` not set. - * - * @deprecated Use {@link aesCbcCryptoModule} for new applications. - */ - static legacyCryptoModule(config) { - throw new Error('Should be implemented by concrete crypto module implementation.'); - } - /** - * Construct crypto module with AES-CBC cryptor for encryption and both AES-CBC and legacy - * cryptors for decryption. - * - * @param config Cryptors configuration options. - * - * @returns Crypto module which encrypts data using AES-CBC cryptor. - * - * @throws Error if `config.cipherKey` not set. - */ - static aesCbcCryptoModule(config) { - throw new Error('Should be implemented by concrete crypto module implementation.'); - } - // endregion - constructor(configuration) { - var _a; - this.defaultCryptor = configuration.default; - this.cryptors = (_a = configuration.cryptors) !== null && _a !== void 0 ? _a : []; - } - /** - * Assign registered loggers' manager. - * - * @param _logger - Registered loggers' manager. - * - * @internal - */ - set logger(_logger) { - throw new Error('Method not implemented.'); - } - // endregion - // -------------------------------------------------------- - // ----------------------- Helpers ------------------------ - // -------------------------------------------------------- - // region Helpers - /** - * Retrieve list of module's cryptors. - * - * @internal - */ - getAllCryptors() { - return [this.defaultCryptor, ...this.cryptors]; - } - // endregion - /** - * Serialize crypto module information to string. - * - * @returns Serialized crypto module information. - */ - toString() { - return `AbstractCryptoModule { default: ${this.defaultCryptor.toString()}, cryptors: [${this.cryptors.map((c) => c.toString()).join(', ')}]}`; - } - } - /** - * `String` to {@link ArrayBuffer} response decoder. - * - * @internal - */ - AbstractCryptoModule.encoder = new TextEncoder(); - /** - * {@link ArrayBuffer} to {@link string} decoder. - * - * @internal - */ - AbstractCryptoModule.decoder = new TextDecoder(); - - /* global File, FileReader */ - /** - * Browser {@link PubNub} File object module. - */ - // endregion - /** - * Web implementation for {@link PubNub} File object. - * - * **Important:** Class should implement constructor and class fields from {@link PubNubFileConstructor}. - */ - class PubNubFile { - // endregion - static create(file) { - return new PubNubFile(file); - } - constructor(file) { - let contentLength; - let fileMimeType; - let fileName; - let fileData; - if (file instanceof File) { - fileData = file; - fileName = file.name; - fileMimeType = file.type; - contentLength = file.size; - } - else if ('data' in file) { - const contents = file.data; - fileMimeType = file.mimeType; - fileName = file.name; - fileData = new File([contents], fileName, { type: fileMimeType }); - contentLength = fileData.size; - } - if (fileData === undefined) - throw new Error("Couldn't construct a file out of supplied options."); - if (fileName === undefined) - throw new Error("Couldn't guess filename out of the options. Please provide one."); - if (contentLength) - this.contentLength = contentLength; - this.mimeType = fileMimeType; - this.data = fileData; - this.name = fileName; - } - /** - * Convert {@link PubNub} File object content to {@link Buffer}. - * - * @throws Error because {@link Buffer} not available in browser environment. - */ - toBuffer() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('This feature is only supported in Node.js environments.'); - }); - } - /** - * Convert {@link PubNub} File object content to {@link ArrayBuffer}. - * - * @returns Asynchronous results of conversion to the {@link ArrayBuffer}. - */ - toArrayBuffer() { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.addEventListener('load', () => { - if (reader.result instanceof ArrayBuffer) - return resolve(reader.result); - }); - reader.addEventListener('error', () => reject(reader.error)); - reader.readAsArrayBuffer(this.data); - }); - }); - } - /** - * Convert {@link PubNub} File object content to {@link string}. - * - * @returns Asynchronous results of conversion to the {@link string}. - */ - toString() { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.addEventListener('load', () => { - if (typeof reader.result === 'string') { - return resolve(reader.result); - } - }); - reader.addEventListener('error', () => { - reject(reader.error); - }); - reader.readAsBinaryString(this.data); - }); - }); - } - /** - * Convert {@link PubNub} File object content to {@link Readable} stream. - * - * @throws Error because {@link Readable} stream not available in browser environment. - */ - toStream() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('This feature is only supported in Node.js environments.'); - }); - } - /** - * Convert {@link PubNub} File object content to {@link File}. - * - * @returns Asynchronous results of conversion to the {@link File}. - */ - toFile() { - return __awaiter(this, void 0, void 0, function* () { - return this.data; - }); - } - /** - * Convert {@link PubNub} File object content to file `Uri`. - * - * @throws Error because file `Uri` not available in browser environment. - */ - toFileUri() { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('This feature is only supported in React Native environments.'); - }); - } - /** - * Convert {@link PubNub} File object content to {@link Blob}. - * - * @returns Asynchronous results of conversion to the {@link Blob}. - */ - toBlob() { - return __awaiter(this, void 0, void 0, function* () { - return this.data; - }); - } - } - // region Class properties - /** - * Whether {@link Blob} data supported by platform or not. - */ - PubNubFile.supportsBlob = typeof Blob !== 'undefined'; - /** - * Whether {@link File} data supported by platform or not. - */ - PubNubFile.supportsFile = typeof File !== 'undefined'; - /** - * Whether {@link Buffer} data supported by platform or not. - */ - PubNubFile.supportsBuffer = false; - /** - * Whether {@link Stream} data supported by platform or not. - */ - PubNubFile.supportsStream = false; - /** - * Whether {@link String} data supported by platform or not. - */ - PubNubFile.supportsString = true; - /** - * Whether {@link ArrayBuffer} supported by platform or not. - */ - PubNubFile.supportsArrayBuffer = true; - /** - * Whether {@link PubNub} File object encryption supported or not. - */ - PubNubFile.supportsEncryptFile = true; - /** - * Whether `File Uri` data supported by platform or not. - */ - PubNubFile.supportsFileUri = false; - - /** - * Base64 support module. - * - * @internal - */ - const BASE64_CHARMAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - /** - * Decode a Base64 encoded string. - * - * @param paddedInput Base64 string with padding - * @returns ArrayBuffer with decoded data - * - * @internal - */ - function decode(paddedInput) { - // Remove up to last two equal signs. - const input = paddedInput.replace(/==?$/, ''); - const outputLength = Math.floor((input.length / 4) * 3); - // Prepare output buffer. - const data = new ArrayBuffer(outputLength); - const view = new Uint8Array(data); - let cursor = 0; - /** - * Returns the next integer representation of a sixtet of bytes from the input - * @returns sixtet of bytes - */ - function nextSixtet() { - const char = input.charAt(cursor++); - const index = BASE64_CHARMAP.indexOf(char); - if (index === -1) { - throw new Error(`Illegal character at ${cursor}: ${input.charAt(cursor - 1)}`); - } - return index; - } - for (let i = 0; i < outputLength; i += 3) { - // Obtain four sixtets - const sx1 = nextSixtet(); - const sx2 = nextSixtet(); - const sx3 = nextSixtet(); - const sx4 = nextSixtet(); - // Encode them as three octets - const oc1 = ((sx1 & 0b00111111) << 2) | (sx2 >> 4); - const oc2 = ((sx2 & 0b00001111) << 4) | (sx3 >> 2); - const oc3 = ((sx3 & 0b00000011) << 6) | (sx4 >> 0); - view[i] = oc1; - // Skip padding bytes. - if (sx3 != 64) - view[i + 1] = oc2; - if (sx4 != 64) - view[i + 2] = oc3; - } - return data; - } - /** - * Encode `ArrayBuffer` as a Base64 encoded string. - * - * @param input ArrayBuffer with source data. - * @returns Base64 string with padding. - * - * @internal - */ - function encode(input) { - let base64 = ''; - const encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - const bytes = new Uint8Array(input); - const byteLength = bytes.byteLength; - const byteRemainder = byteLength % 3; - const mainLength = byteLength - byteRemainder; - let a, b, c, d; - let chunk; - // Main loop deals with bytes in chunks of 3 - for (let i = 0; i < mainLength; i = i + 3) { - // Combine the three bytes into a single integer - chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; - // Use bitmasks to extract 6-bit segments from the triplet - a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18 - b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12 - c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6 - d = chunk & 63; // 63 = 2^6 - 1 - // Convert the raw binary segments to the appropriate ASCII encoding - base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]; - } - // Deal with the remaining bytes and padding - if (byteRemainder == 1) { - chunk = bytes[mainLength]; - a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2 - // Set the 4 least significant bits to zero - b = (chunk & 3) << 4; // 3 = 2^2 - 1 - base64 += encodings[a] + encodings[b] + '=='; - } - else if (byteRemainder == 2) { - chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]; - a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10 - b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4 - // Set the 2 least significant bits to zero - c = (chunk & 15) << 2; // 15 = 2^4 - 1 - base64 += encodings[a] + encodings[b] + encodings[c] + '='; - } - return base64; - } - - /** - * Request processing status categories. - */ - var StatusCategory; - (function (StatusCategory) { - /** - * Call failed when network was unable to complete the call. - */ - StatusCategory["PNNetworkIssuesCategory"] = "PNNetworkIssuesCategory"; - /** - * Network call timed out. - */ - StatusCategory["PNTimeoutCategory"] = "PNTimeoutCategory"; - /** - * Request has been cancelled. - */ - StatusCategory["PNCancelledCategory"] = "PNCancelledCategory"; - /** - * Server responded with bad response. - */ - StatusCategory["PNBadRequestCategory"] = "PNBadRequestCategory"; - /** - * Server responded with access denied. - */ - StatusCategory["PNAccessDeniedCategory"] = "PNAccessDeniedCategory"; - /** - * Incomplete parameters provided for used endpoint. - */ - StatusCategory["PNValidationErrorCategory"] = "PNValidationErrorCategory"; - /** - * PubNub request acknowledgment status. - * - * Some API endpoints respond with request processing status w/o useful data. - */ - StatusCategory["PNAcknowledgmentCategory"] = "PNAcknowledgmentCategory"; - /** - * PubNub service or intermediate "actor" returned unexpected response. - * - * There can be few sources of unexpected return with success code: - * - proxy server / VPN; - * - Wi-Fi hotspot authorization page. - */ - StatusCategory["PNMalformedResponseCategory"] = "PNMalformedResponseCategory"; - /** - * Server can't process request. - * - * There can be few sources of unexpected return with success code: - * - potentially an ongoing incident; - * - proxy server / VPN. - */ - StatusCategory["PNServerErrorCategory"] = "PNServerErrorCategory"; - /** - * Something strange happened; please check the logs. - */ - StatusCategory["PNUnknownCategory"] = "PNUnknownCategory"; - // -------------------------------------------------------- - // --------------------- Network status ------------------- - // -------------------------------------------------------- - /** - * SDK will announce when the network appears to be connected again. - */ - StatusCategory["PNNetworkUpCategory"] = "PNNetworkUpCategory"; - /** - * SDK will announce when the network appears to down. - */ - StatusCategory["PNNetworkDownCategory"] = "PNNetworkDownCategory"; - // -------------------------------------------------------- - // -------------------- Real-time events ------------------ - // -------------------------------------------------------- - /** - * PubNub client reconnected to the real-time updates stream. - */ - StatusCategory["PNReconnectedCategory"] = "PNReconnectedCategory"; - /** - * PubNub client connected to the real-time updates stream. - */ - StatusCategory["PNConnectedCategory"] = "PNConnectedCategory"; - /** - * Set of active channels and groups has been changed. - */ - StatusCategory["PNSubscriptionChangedCategory"] = "PNSubscriptionChangedCategory"; - /** - * Received real-time updates exceed specified threshold. - * - * After temporary disconnection and catchup, this category means that potentially some - * real-time updates have been pushed into `storage` and need to be requested separately. - */ - StatusCategory["PNRequestMessageCountExceededCategory"] = "PNRequestMessageCountExceededCategory"; - /** - * PubNub client disconnected from the real-time updates streams. - */ - StatusCategory["PNDisconnectedCategory"] = "PNDisconnectedCategory"; - /** - * PubNub client wasn't able to connect to the real-time updates streams. - */ - StatusCategory["PNConnectionErrorCategory"] = "PNConnectionErrorCategory"; - /** - * PubNub client unexpectedly disconnected from the real-time updates streams. - */ - StatusCategory["PNDisconnectedUnexpectedlyCategory"] = "PNDisconnectedUnexpectedlyCategory"; - // -------------------------------------------------------- - // ------------------ Shared worker events ---------------- - // -------------------------------------------------------- - /** - * SDK will announce when newer shared worker will be 'noticed'. - */ - StatusCategory["PNSharedWorkerUpdatedCategory"] = "PNSharedWorkerUpdatedCategory"; - })(StatusCategory || (StatusCategory = {})); - var StatusCategory$1 = StatusCategory; - - /** - * PubNub operation error module. - */ - /** - * PubNub operation error. - * - * When an operation can't be performed or there is an error from the server, this object will be returned. - */ - class PubNubError extends Error { - /** - * Create PubNub operation error. - * - * @param message - Message with details about why operation failed. - * @param [status] - Additional information about performed operation. - * - * @returns Configured and ready to use PubNub operation error. - * - * @internal - */ - constructor(message, status) { - super(message); - this.status = status; - this.name = 'PubNubError'; - this.message = message; - Object.setPrototypeOf(this, new.target.prototype); - } - } - /** - * Create error status object. - * - * @param errorPayload - Additional information which should be attached to the error status object. - * @param category - Occurred error category. - * - * @returns Error status object. - * - * @internal - */ - function createError(errorPayload, category) { - var _a; - (_a = errorPayload.statusCode) !== null && _a !== void 0 ? _a : (errorPayload.statusCode = 0); - return Object.assign(Object.assign({}, errorPayload), { statusCode: errorPayload.statusCode, category, error: true }); - } - /** - * Create operation arguments validation error status object. - * - * @param message - Information about failed validation requirement. - * @param [statusCode] - Operation HTTP status code. - * - * @returns Operation validation error status object. - * - * @internal - */ - function createValidationError(message, statusCode) { - return createError(Object.assign({ message }, ({})), StatusCategory$1.PNValidationErrorCategory); - } - /** - * Create malformed service response error status object. - * - * @param [responseText] - Stringified original service response. - * @param [statusCode] - Operation HTTP status code. - */ - function createMalformedResponseError(responseText, statusCode) { - return createError(Object.assign(Object.assign({ message: 'Unable to deserialize service response' }, (responseText !== undefined ? { responseText } : {})), (statusCode !== undefined ? { statusCode } : {})), StatusCategory$1.PNMalformedResponseCategory); - } - - /** - * CryptoJS implementation. - * - * @internal - */ - - /*eslint-disable */ - - /* - CryptoJS v3.1.2 - code.google.com/p/crypto-js - (c) 2009-2013 by Jeff Mott. All rights reserved. - code.google.com/p/crypto-js/wiki/License - */ - var CryptoJS = - CryptoJS || - (function (h, s) { - var f = {}, - g = (f.lib = {}), - q = function () {}, - m = (g.Base = { - extend: function (a) { - q.prototype = this; - var c = new q(); - a && c.mixIn(a); - c.hasOwnProperty('init') || - (c.init = function () { - c.$super.init.apply(this, arguments); - }); - c.init.prototype = c; - c.$super = this; - return c; - }, - create: function () { - var a = this.extend(); - a.init.apply(a, arguments); - return a; - }, - init: function () {}, - mixIn: function (a) { - for (var c in a) a.hasOwnProperty(c) && (this[c] = a[c]); - a.hasOwnProperty('toString') && (this.toString = a.toString); - }, - clone: function () { - return this.init.prototype.extend(this); - }, - }), - r = (g.WordArray = m.extend({ - init: function (a, c) { - a = this.words = a || []; - this.sigBytes = c != s ? c : 4 * a.length; - }, - toString: function (a) { - return (a || k).stringify(this); - }, - concat: function (a) { - var c = this.words, - d = a.words, - b = this.sigBytes; - a = a.sigBytes; - this.clamp(); - if (b % 4) - for (var e = 0; e < a; e++) - c[(b + e) >>> 2] |= ((d[e >>> 2] >>> (24 - 8 * (e % 4))) & 255) << (24 - 8 * ((b + e) % 4)); - else if (65535 < d.length) for (e = 0; e < a; e += 4) c[(b + e) >>> 2] = d[e >>> 2]; - else c.push.apply(c, d); - this.sigBytes += a; - return this; - }, - clamp: function () { - var a = this.words, - c = this.sigBytes; - a[c >>> 2] &= 4294967295 << (32 - 8 * (c % 4)); - a.length = h.ceil(c / 4); - }, - clone: function () { - var a = m.clone.call(this); - a.words = this.words.slice(0); - return a; - }, - random: function (a) { - for (var c = [], d = 0; d < a; d += 4) c.push((4294967296 * h.random()) | 0); - return new r.init(c, a); - }, - })), - l = (f.enc = {}), - k = (l.Hex = { - stringify: function (a) { - var c = a.words; - a = a.sigBytes; - for (var d = [], b = 0; b < a; b++) { - var e = (c[b >>> 2] >>> (24 - 8 * (b % 4))) & 255; - d.push((e >>> 4).toString(16)); - d.push((e & 15).toString(16)); - } - return d.join(''); - }, - parse: function (a) { - for (var c = a.length, d = [], b = 0; b < c; b += 2) - d[b >>> 3] |= parseInt(a.substr(b, 2), 16) << (24 - 4 * (b % 8)); - return new r.init(d, c / 2); - }, - }), - n = (l.Latin1 = { - stringify: function (a) { - var c = a.words; - a = a.sigBytes; - for (var d = [], b = 0; b < a; b++) d.push(String.fromCharCode((c[b >>> 2] >>> (24 - 8 * (b % 4))) & 255)); - return d.join(''); - }, - parse: function (a) { - for (var c = a.length, d = [], b = 0; b < c; b++) d[b >>> 2] |= (a.charCodeAt(b) & 255) << (24 - 8 * (b % 4)); - return new r.init(d, c); - }, - }), - j = (l.Utf8 = { - stringify: function (a) { - try { - return decodeURIComponent(escape(n.stringify(a))); - } catch (c) { - throw Error('Malformed UTF-8 data'); - } - }, - parse: function (a) { - return n.parse(unescape(encodeURIComponent(a))); - }, - }), - u = (g.BufferedBlockAlgorithm = m.extend({ - reset: function () { - this._data = new r.init(); - this._nDataBytes = 0; - }, - _append: function (a) { - 'string' == typeof a && (a = j.parse(a)); - this._data.concat(a); - this._nDataBytes += a.sigBytes; - }, - _process: function (a) { - var c = this._data, - d = c.words, - b = c.sigBytes, - e = this.blockSize, - f = b / (4 * e), - f = a ? h.ceil(f) : h.max((f | 0) - this._minBufferSize, 0); - a = f * e; - b = h.min(4 * a, b); - if (a) { - for (var g = 0; g < a; g += e) this._doProcessBlock(d, g); - g = d.splice(0, a); - c.sigBytes -= b; - } - return new r.init(g, b); - }, - clone: function () { - var a = m.clone.call(this); - a._data = this._data.clone(); - return a; - }, - _minBufferSize: 0, - })); - g.Hasher = u.extend({ - cfg: m.extend(), - init: function (a) { - this.cfg = this.cfg.extend(a); - this.reset(); - }, - reset: function () { - u.reset.call(this); - this._doReset(); - }, - update: function (a) { - this._append(a); - this._process(); - return this; - }, - finalize: function (a) { - a && this._append(a); - return this._doFinalize(); - }, - blockSize: 16, - _createHelper: function (a) { - return function (c, d) { - return new a.init(d).finalize(c); - }; - }, - _createHmacHelper: function (a) { - return function (c, d) { - return new t.HMAC.init(a, d).finalize(c); - }; - }, - }); - var t = (f.algo = {}); - return f; - })(Math); - - // SHA256 - (function (h) { - for ( - var s = CryptoJS, - f = s.lib, - g = f.WordArray, - q = f.Hasher, - f = s.algo, - m = [], - r = [], - l = function (a) { - return (4294967296 * (a - (a | 0))) | 0; - }, - k = 2, - n = 0; - 64 > n; - - ) { - var j; - a: { - j = k; - for (var u = h.sqrt(j), t = 2; t <= u; t++) - if (!(j % t)) { - j = !1; - break a; - } - j = !0; - } - j && (8 > n && (m[n] = l(h.pow(k, 0.5))), (r[n] = l(h.pow(k, 1 / 3))), n++); - k++; - } - var a = [], - f = (f.SHA256 = q.extend({ - _doReset: function () { - this._hash = new g.init(m.slice(0)); - }, - _doProcessBlock: function (c, d) { - for ( - var b = this._hash.words, - e = b[0], - f = b[1], - g = b[2], - j = b[3], - h = b[4], - m = b[5], - n = b[6], - q = b[7], - p = 0; - 64 > p; - p++ - ) { - if (16 > p) a[p] = c[d + p] | 0; - else { - var k = a[p - 15], - l = a[p - 2]; - a[p] = - (((k << 25) | (k >>> 7)) ^ ((k << 14) | (k >>> 18)) ^ (k >>> 3)) + - a[p - 7] + - (((l << 15) | (l >>> 17)) ^ ((l << 13) | (l >>> 19)) ^ (l >>> 10)) + - a[p - 16]; - } - k = - q + - (((h << 26) | (h >>> 6)) ^ ((h << 21) | (h >>> 11)) ^ ((h << 7) | (h >>> 25))) + - ((h & m) ^ (~h & n)) + - r[p] + - a[p]; - l = - (((e << 30) | (e >>> 2)) ^ ((e << 19) | (e >>> 13)) ^ ((e << 10) | (e >>> 22))) + - ((e & f) ^ (e & g) ^ (f & g)); - q = n; - n = m; - m = h; - h = (j + k) | 0; - j = g; - g = f; - f = e; - e = (k + l) | 0; - } - b[0] = (b[0] + e) | 0; - b[1] = (b[1] + f) | 0; - b[2] = (b[2] + g) | 0; - b[3] = (b[3] + j) | 0; - b[4] = (b[4] + h) | 0; - b[5] = (b[5] + m) | 0; - b[6] = (b[6] + n) | 0; - b[7] = (b[7] + q) | 0; - }, - _doFinalize: function () { - var a = this._data, - d = a.words, - b = 8 * this._nDataBytes, - e = 8 * a.sigBytes; - d[e >>> 5] |= 128 << (24 - (e % 32)); - d[(((e + 64) >>> 9) << 4) + 14] = h.floor(b / 4294967296); - d[(((e + 64) >>> 9) << 4) + 15] = b; - a.sigBytes = 4 * d.length; - this._process(); - return this._hash; - }, - clone: function () { - var a = q.clone.call(this); - a._hash = this._hash.clone(); - return a; - }, - })); - s.SHA256 = q._createHelper(f); - s.HmacSHA256 = q._createHmacHelper(f); - })(Math); - - // HMAC SHA256 - (function () { - var h = CryptoJS, - s = h.enc.Utf8; - h.algo.HMAC = h.lib.Base.extend({ - init: function (f, g) { - f = this._hasher = new f.init(); - 'string' == typeof g && (g = s.parse(g)); - var h = f.blockSize, - m = 4 * h; - g.sigBytes > m && (g = f.finalize(g)); - g.clamp(); - for (var r = (this._oKey = g.clone()), l = (this._iKey = g.clone()), k = r.words, n = l.words, j = 0; j < h; j++) - (k[j] ^= 1549556828), (n[j] ^= 909522486); - r.sigBytes = l.sigBytes = m; - this.reset(); - }, - reset: function () { - var f = this._hasher; - f.reset(); - f.update(this._iKey); - }, - update: function (f) { - this._hasher.update(f); - return this; - }, - finalize: function (f) { - var g = this._hasher; - f = g.finalize(f); - g.reset(); - return g.finalize(this._oKey.clone().concat(f)); - }, - }); - })(); - - // Base64 - (function () { - var u = CryptoJS, - p = u.lib.WordArray; - u.enc.Base64 = { - stringify: function (d) { - var l = d.words, - p = d.sigBytes, - t = this._map; - d.clamp(); - d = []; - for (var r = 0; r < p; r += 3) - for ( - var w = - (((l[r >>> 2] >>> (24 - 8 * (r % 4))) & 255) << 16) | - (((l[(r + 1) >>> 2] >>> (24 - 8 * ((r + 1) % 4))) & 255) << 8) | - ((l[(r + 2) >>> 2] >>> (24 - 8 * ((r + 2) % 4))) & 255), - v = 0; - 4 > v && r + 0.75 * v < p; - v++ - ) - d.push(t.charAt((w >>> (6 * (3 - v))) & 63)); - if ((l = t.charAt(64))) for (; d.length % 4; ) d.push(l); - return d.join(''); - }, - parse: function (d) { - var l = d.length, - s = this._map, - t = s.charAt(64); - t && ((t = d.indexOf(t)), -1 != t && (l = t)); - for (var t = [], r = 0, w = 0; w < l; w++) - if (w % 4) { - var v = s.indexOf(d.charAt(w - 1)) << (2 * (w % 4)), - b = s.indexOf(d.charAt(w)) >>> (6 - 2 * (w % 4)); - t[r >>> 2] |= (v | b) << (24 - 8 * (r % 4)); - r++; - } - return p.create(t, r); - }, - _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', - }; - })(); - - // BlockCipher - (function (u) { - function p(b, n, a, c, e, j, k) { - b = b + ((n & a) | (~n & c)) + e + k; - return ((b << j) | (b >>> (32 - j))) + n; - } - function d(b, n, a, c, e, j, k) { - b = b + ((n & c) | (a & ~c)) + e + k; - return ((b << j) | (b >>> (32 - j))) + n; - } - function l(b, n, a, c, e, j, k) { - b = b + (n ^ a ^ c) + e + k; - return ((b << j) | (b >>> (32 - j))) + n; - } - function s(b, n, a, c, e, j, k) { - b = b + (a ^ (n | ~c)) + e + k; - return ((b << j) | (b >>> (32 - j))) + n; - } - for (var t = CryptoJS, r = t.lib, w = r.WordArray, v = r.Hasher, r = t.algo, b = [], x = 0; 64 > x; x++) - b[x] = (4294967296 * u.abs(u.sin(x + 1))) | 0; - r = r.MD5 = v.extend({ - _doReset: function () { - this._hash = new w.init([1732584193, 4023233417, 2562383102, 271733878]); - }, - _doProcessBlock: function (q, n) { - for (var a = 0; 16 > a; a++) { - var c = n + a, - e = q[c]; - q[c] = (((e << 8) | (e >>> 24)) & 16711935) | (((e << 24) | (e >>> 8)) & 4278255360); - } - var a = this._hash.words, - c = q[n + 0], - e = q[n + 1], - j = q[n + 2], - k = q[n + 3], - z = q[n + 4], - r = q[n + 5], - t = q[n + 6], - w = q[n + 7], - v = q[n + 8], - A = q[n + 9], - B = q[n + 10], - C = q[n + 11], - u = q[n + 12], - D = q[n + 13], - E = q[n + 14], - x = q[n + 15], - f = a[0], - m = a[1], - g = a[2], - h = a[3], - f = p(f, m, g, h, c, 7, b[0]), - h = p(h, f, m, g, e, 12, b[1]), - g = p(g, h, f, m, j, 17, b[2]), - m = p(m, g, h, f, k, 22, b[3]), - f = p(f, m, g, h, z, 7, b[4]), - h = p(h, f, m, g, r, 12, b[5]), - g = p(g, h, f, m, t, 17, b[6]), - m = p(m, g, h, f, w, 22, b[7]), - f = p(f, m, g, h, v, 7, b[8]), - h = p(h, f, m, g, A, 12, b[9]), - g = p(g, h, f, m, B, 17, b[10]), - m = p(m, g, h, f, C, 22, b[11]), - f = p(f, m, g, h, u, 7, b[12]), - h = p(h, f, m, g, D, 12, b[13]), - g = p(g, h, f, m, E, 17, b[14]), - m = p(m, g, h, f, x, 22, b[15]), - f = d(f, m, g, h, e, 5, b[16]), - h = d(h, f, m, g, t, 9, b[17]), - g = d(g, h, f, m, C, 14, b[18]), - m = d(m, g, h, f, c, 20, b[19]), - f = d(f, m, g, h, r, 5, b[20]), - h = d(h, f, m, g, B, 9, b[21]), - g = d(g, h, f, m, x, 14, b[22]), - m = d(m, g, h, f, z, 20, b[23]), - f = d(f, m, g, h, A, 5, b[24]), - h = d(h, f, m, g, E, 9, b[25]), - g = d(g, h, f, m, k, 14, b[26]), - m = d(m, g, h, f, v, 20, b[27]), - f = d(f, m, g, h, D, 5, b[28]), - h = d(h, f, m, g, j, 9, b[29]), - g = d(g, h, f, m, w, 14, b[30]), - m = d(m, g, h, f, u, 20, b[31]), - f = l(f, m, g, h, r, 4, b[32]), - h = l(h, f, m, g, v, 11, b[33]), - g = l(g, h, f, m, C, 16, b[34]), - m = l(m, g, h, f, E, 23, b[35]), - f = l(f, m, g, h, e, 4, b[36]), - h = l(h, f, m, g, z, 11, b[37]), - g = l(g, h, f, m, w, 16, b[38]), - m = l(m, g, h, f, B, 23, b[39]), - f = l(f, m, g, h, D, 4, b[40]), - h = l(h, f, m, g, c, 11, b[41]), - g = l(g, h, f, m, k, 16, b[42]), - m = l(m, g, h, f, t, 23, b[43]), - f = l(f, m, g, h, A, 4, b[44]), - h = l(h, f, m, g, u, 11, b[45]), - g = l(g, h, f, m, x, 16, b[46]), - m = l(m, g, h, f, j, 23, b[47]), - f = s(f, m, g, h, c, 6, b[48]), - h = s(h, f, m, g, w, 10, b[49]), - g = s(g, h, f, m, E, 15, b[50]), - m = s(m, g, h, f, r, 21, b[51]), - f = s(f, m, g, h, u, 6, b[52]), - h = s(h, f, m, g, k, 10, b[53]), - g = s(g, h, f, m, B, 15, b[54]), - m = s(m, g, h, f, e, 21, b[55]), - f = s(f, m, g, h, v, 6, b[56]), - h = s(h, f, m, g, x, 10, b[57]), - g = s(g, h, f, m, t, 15, b[58]), - m = s(m, g, h, f, D, 21, b[59]), - f = s(f, m, g, h, z, 6, b[60]), - h = s(h, f, m, g, C, 10, b[61]), - g = s(g, h, f, m, j, 15, b[62]), - m = s(m, g, h, f, A, 21, b[63]); - a[0] = (a[0] + f) | 0; - a[1] = (a[1] + m) | 0; - a[2] = (a[2] + g) | 0; - a[3] = (a[3] + h) | 0; - }, - _doFinalize: function () { - var b = this._data, - n = b.words, - a = 8 * this._nDataBytes, - c = 8 * b.sigBytes; - n[c >>> 5] |= 128 << (24 - (c % 32)); - var e = u.floor(a / 4294967296); - n[(((c + 64) >>> 9) << 4) + 15] = (((e << 8) | (e >>> 24)) & 16711935) | (((e << 24) | (e >>> 8)) & 4278255360); - n[(((c + 64) >>> 9) << 4) + 14] = (((a << 8) | (a >>> 24)) & 16711935) | (((a << 24) | (a >>> 8)) & 4278255360); - b.sigBytes = 4 * (n.length + 1); - this._process(); - b = this._hash; - n = b.words; - for (a = 0; 4 > a; a++) - (c = n[a]), (n[a] = (((c << 8) | (c >>> 24)) & 16711935) | (((c << 24) | (c >>> 8)) & 4278255360)); - return b; - }, - clone: function () { - var b = v.clone.call(this); - b._hash = this._hash.clone(); - return b; - }, - }); - t.MD5 = v._createHelper(r); - t.HmacMD5 = v._createHmacHelper(r); - })(Math); - (function () { - var u = CryptoJS, - p = u.lib, - d = p.Base, - l = p.WordArray, - p = u.algo, - s = (p.EvpKDF = d.extend({ - cfg: d.extend({ keySize: 4, hasher: p.MD5, iterations: 1 }), - init: function (d) { - this.cfg = this.cfg.extend(d); - }, - compute: function (d, r) { - for ( - var p = this.cfg, s = p.hasher.create(), b = l.create(), u = b.words, q = p.keySize, p = p.iterations; - u.length < q; - - ) { - n && s.update(n); - var n = s.update(d).finalize(r); - s.reset(); - for (var a = 1; a < p; a++) (n = s.finalize(n)), s.reset(); - b.concat(n); - } - b.sigBytes = 4 * q; - return b; - }, - })); - u.EvpKDF = function (d, l, p) { - return s.create(p).compute(d, l); - }; - })(); - - // Cipher - CryptoJS.lib.Cipher || - (function (u) { - var p = CryptoJS, - d = p.lib, - l = d.Base, - s = d.WordArray, - t = d.BufferedBlockAlgorithm, - r = p.enc.Base64, - w = p.algo.EvpKDF, - v = (d.Cipher = t.extend({ - cfg: l.extend(), - createEncryptor: function (e, a) { - return this.create(this._ENC_XFORM_MODE, e, a); - }, - createDecryptor: function (e, a) { - return this.create(this._DEC_XFORM_MODE, e, a); - }, - init: function (e, a, b) { - this.cfg = this.cfg.extend(b); - this._xformMode = e; - this._key = a; - this.reset(); - }, - reset: function () { - t.reset.call(this); - this._doReset(); - }, - process: function (e) { - this._append(e); - return this._process(); - }, - finalize: function (e) { - e && this._append(e); - return this._doFinalize(); - }, - keySize: 4, - ivSize: 4, - _ENC_XFORM_MODE: 1, - _DEC_XFORM_MODE: 2, - _createHelper: function (e) { - return { - encrypt: function (b, k, d) { - return ('string' == typeof k ? c : a).encrypt(e, b, k, d); - }, - decrypt: function (b, k, d) { - return ('string' == typeof k ? c : a).decrypt(e, b, k, d); - }, - }; - }, - })); - d.StreamCipher = v.extend({ - _doFinalize: function () { - return this._process(!0); - }, - blockSize: 1, - }); - var b = (p.mode = {}), - x = function (e, a, b) { - var c = this._iv; - c ? (this._iv = u) : (c = this._prevBlock); - for (var d = 0; d < b; d++) e[a + d] ^= c[d]; - }, - q = (d.BlockCipherMode = l.extend({ - createEncryptor: function (e, a) { - return this.Encryptor.create(e, a); - }, - createDecryptor: function (e, a) { - return this.Decryptor.create(e, a); - }, - init: function (e, a) { - this._cipher = e; - this._iv = a; - }, - })).extend(); - q.Encryptor = q.extend({ - processBlock: function (e, a) { - var b = this._cipher, - c = b.blockSize; - x.call(this, e, a, c); - b.encryptBlock(e, a); - this._prevBlock = e.slice(a, a + c); - }, - }); - q.Decryptor = q.extend({ - processBlock: function (e, a) { - var b = this._cipher, - c = b.blockSize, - d = e.slice(a, a + c); - b.decryptBlock(e, a); - x.call(this, e, a, c); - this._prevBlock = d; - }, - }); - b = b.CBC = q; - q = (p.pad = {}).Pkcs7 = { - pad: function (a, b) { - for ( - var c = 4 * b, c = c - (a.sigBytes % c), d = (c << 24) | (c << 16) | (c << 8) | c, l = [], n = 0; - n < c; - n += 4 - ) - l.push(d); - c = s.create(l, c); - a.concat(c); - }, - unpad: function (a) { - a.sigBytes -= a.words[(a.sigBytes - 1) >>> 2] & 255; - }, - }; - d.BlockCipher = v.extend({ - cfg: v.cfg.extend({ mode: b, padding: q }), - reset: function () { - v.reset.call(this); - var a = this.cfg, - b = a.iv, - a = a.mode; - if (this._xformMode == this._ENC_XFORM_MODE) var c = a.createEncryptor; - else (c = a.createDecryptor), (this._minBufferSize = 1); - this._mode = c.call(a, this, b && b.words); - }, - _doProcessBlock: function (a, b) { - this._mode.processBlock(a, b); - }, - _doFinalize: function () { - var a = this.cfg.padding; - if (this._xformMode == this._ENC_XFORM_MODE) { - a.pad(this._data, this.blockSize); - var b = this._process(!0); - } else (b = this._process(!0)), a.unpad(b); - return b; - }, - blockSize: 4, - }); - var n = (d.CipherParams = l.extend({ - init: function (a) { - this.mixIn(a); - }, - toString: function (a) { - return (a || this.formatter).stringify(this); - }, - })), - b = ((p.format = {}).OpenSSL = { - stringify: function (a) { - var b = a.ciphertext; - a = a.salt; - return (a ? s.create([1398893684, 1701076831]).concat(a).concat(b) : b).toString(r); - }, - parse: function (a) { - a = r.parse(a); - var b = a.words; - if (1398893684 == b[0] && 1701076831 == b[1]) { - var c = s.create(b.slice(2, 4)); - b.splice(0, 4); - a.sigBytes -= 16; - } - return n.create({ ciphertext: a, salt: c }); - }, - }), - a = (d.SerializableCipher = l.extend({ - cfg: l.extend({ format: b }), - encrypt: function (a, b, c, d) { - d = this.cfg.extend(d); - var l = a.createEncryptor(c, d); - b = l.finalize(b); - l = l.cfg; - return n.create({ - ciphertext: b, - key: c, - iv: l.iv, - algorithm: a, - mode: l.mode, - padding: l.padding, - blockSize: a.blockSize, - formatter: d.format, - }); - }, - decrypt: function (a, b, c, d) { - d = this.cfg.extend(d); - b = this._parse(b, d.format); - return a.createDecryptor(c, d).finalize(b.ciphertext); - }, - _parse: function (a, b) { - return 'string' == typeof a ? b.parse(a, this) : a; - }, - })), - p = ((p.kdf = {}).OpenSSL = { - execute: function (a, b, c, d) { - d || (d = s.random(8)); - a = w.create({ keySize: b + c }).compute(a, d); - c = s.create(a.words.slice(b), 4 * c); - a.sigBytes = 4 * b; - return n.create({ key: a, iv: c, salt: d }); - }, - }), - c = (d.PasswordBasedCipher = a.extend({ - cfg: a.cfg.extend({ kdf: p }), - encrypt: function (b, c, d, l) { - l = this.cfg.extend(l); - d = l.kdf.execute(d, b.keySize, b.ivSize); - l.iv = d.iv; - b = a.encrypt.call(this, b, c, d.key, l); - b.mixIn(d); - return b; - }, - decrypt: function (b, c, d, l) { - l = this.cfg.extend(l); - c = this._parse(c, l.format); - d = l.kdf.execute(d, b.keySize, b.ivSize, c.salt); - l.iv = d.iv; - return a.decrypt.call(this, b, c, d.key, l); - }, - })); - })(); - - // AES - (function () { - for ( - var u = CryptoJS, - p = u.lib.BlockCipher, - d = u.algo, - l = [], - s = [], - t = [], - r = [], - w = [], - v = [], - b = [], - x = [], - q = [], - n = [], - a = [], - c = 0; - 256 > c; - c++ - ) - a[c] = 128 > c ? c << 1 : (c << 1) ^ 283; - for (var e = 0, j = 0, c = 0; 256 > c; c++) { - var k = j ^ (j << 1) ^ (j << 2) ^ (j << 3) ^ (j << 4), - k = (k >>> 8) ^ (k & 255) ^ 99; - l[e] = k; - s[k] = e; - var z = a[e], - F = a[z], - G = a[F], - y = (257 * a[k]) ^ (16843008 * k); - t[e] = (y << 24) | (y >>> 8); - r[e] = (y << 16) | (y >>> 16); - w[e] = (y << 8) | (y >>> 24); - v[e] = y; - y = (16843009 * G) ^ (65537 * F) ^ (257 * z) ^ (16843008 * e); - b[k] = (y << 24) | (y >>> 8); - x[k] = (y << 16) | (y >>> 16); - q[k] = (y << 8) | (y >>> 24); - n[k] = y; - e ? ((e = z ^ a[a[a[G ^ z]]]), (j ^= a[a[j]])) : (e = j = 1); - } - var H = [0, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54], - d = (d.AES = p.extend({ - _doReset: function () { - for ( - var a = this._key, - c = a.words, - d = a.sigBytes / 4, - a = 4 * ((this._nRounds = d + 6) + 1), - e = (this._keySchedule = []), - j = 0; - j < a; - j++ - ) - if (j < d) e[j] = c[j]; - else { - var k = e[j - 1]; - j % d - ? 6 < d && - 4 == j % d && - (k = (l[k >>> 24] << 24) | (l[(k >>> 16) & 255] << 16) | (l[(k >>> 8) & 255] << 8) | l[k & 255]) - : ((k = (k << 8) | (k >>> 24)), - (k = (l[k >>> 24] << 24) | (l[(k >>> 16) & 255] << 16) | (l[(k >>> 8) & 255] << 8) | l[k & 255]), - (k ^= H[(j / d) | 0] << 24)); - e[j] = e[j - d] ^ k; - } - c = this._invKeySchedule = []; - for (d = 0; d < a; d++) - (j = a - d), - (k = d % 4 ? e[j] : e[j - 4]), - (c[d] = - 4 > d || 4 >= j ? k : b[l[k >>> 24]] ^ x[l[(k >>> 16) & 255]] ^ q[l[(k >>> 8) & 255]] ^ n[l[k & 255]]); - }, - encryptBlock: function (a, b) { - this._doCryptBlock(a, b, this._keySchedule, t, r, w, v, l); - }, - decryptBlock: function (a, c) { - var d = a[c + 1]; - a[c + 1] = a[c + 3]; - a[c + 3] = d; - this._doCryptBlock(a, c, this._invKeySchedule, b, x, q, n, s); - d = a[c + 1]; - a[c + 1] = a[c + 3]; - a[c + 3] = d; - }, - _doCryptBlock: function (a, b, c, d, e, j, l, f) { - for ( - var m = this._nRounds, - g = a[b] ^ c[0], - h = a[b + 1] ^ c[1], - k = a[b + 2] ^ c[2], - n = a[b + 3] ^ c[3], - p = 4, - r = 1; - r < m; - r++ - ) - var q = d[g >>> 24] ^ e[(h >>> 16) & 255] ^ j[(k >>> 8) & 255] ^ l[n & 255] ^ c[p++], - s = d[h >>> 24] ^ e[(k >>> 16) & 255] ^ j[(n >>> 8) & 255] ^ l[g & 255] ^ c[p++], - t = d[k >>> 24] ^ e[(n >>> 16) & 255] ^ j[(g >>> 8) & 255] ^ l[h & 255] ^ c[p++], - n = d[n >>> 24] ^ e[(g >>> 16) & 255] ^ j[(h >>> 8) & 255] ^ l[k & 255] ^ c[p++], - g = q, - h = s, - k = t; - q = ((f[g >>> 24] << 24) | (f[(h >>> 16) & 255] << 16) | (f[(k >>> 8) & 255] << 8) | f[n & 255]) ^ c[p++]; - s = ((f[h >>> 24] << 24) | (f[(k >>> 16) & 255] << 16) | (f[(n >>> 8) & 255] << 8) | f[g & 255]) ^ c[p++]; - t = ((f[k >>> 24] << 24) | (f[(n >>> 16) & 255] << 16) | (f[(g >>> 8) & 255] << 8) | f[h & 255]) ^ c[p++]; - n = ((f[n >>> 24] << 24) | (f[(g >>> 16) & 255] << 16) | (f[(h >>> 8) & 255] << 8) | f[k & 255]) ^ c[p++]; - a[b] = q; - a[b + 1] = s; - a[b + 2] = t; - a[b + 3] = n; - }, - keySize: 8, - })); - u.AES = p._createHelper(d); - })(); - - // Mode ECB - CryptoJS.mode.ECB = (function () { - var ECB = CryptoJS.lib.BlockCipherMode.extend(); - - ECB.Encryptor = ECB.extend({ - processBlock: function (words, offset) { - this._cipher.encryptBlock(words, offset); - }, - }); - - ECB.Decryptor = ECB.extend({ - processBlock: function (words, offset) { - this._cipher.decryptBlock(words, offset); - }, - }); - - return ECB; - })(); - - var hmacSha256 = CryptoJS; - - var CryptoJS$1 = /*@__PURE__*/getDefaultExportFromCjs(hmacSha256); - - /** - * AES-CBC cryptor module. - */ - /** - * AES-CBC cryptor. - * - * AES-CBC cryptor with enhanced cipher strength. - */ - class AesCbcCryptor { - constructor({ cipherKey }) { - this.cipherKey = cipherKey; - this.CryptoJS = CryptoJS$1; - this.encryptedKey = this.CryptoJS.SHA256(cipherKey); - } - // -------------------------------------------------------- - // --------------------- Encryption ----------------------- - // -------------------------------------------------------- - // region Encryption - encrypt(data) { - const stringData = typeof data === 'string' ? data : AesCbcCryptor.decoder.decode(data); - if (stringData.length === 0) - throw new Error('encryption error. empty content'); - const abIv = this.getIv(); - return { - metadata: abIv, - data: decode(this.CryptoJS.AES.encrypt(data, this.encryptedKey, { - iv: this.bufferToWordArray(abIv), - mode: this.CryptoJS.mode.CBC, - }).ciphertext.toString(this.CryptoJS.enc.Base64)), - }; - } - encryptFileData(data) { - return __awaiter(this, void 0, void 0, function* () { - const key = yield this.getKey(); - const iv = this.getIv(); - return { - data: yield crypto.subtle.encrypt({ name: this.algo, iv: iv }, key, data), - metadata: iv, - }; - }); - } - // endregion - // -------------------------------------------------------- - // --------------------- Decryption ----------------------- - // -------------------------------------------------------- - // region Decryption - decrypt(encryptedData) { - if (typeof encryptedData.data === 'string') - throw new Error('Decryption error: data for decryption should be ArrayBuffed.'); - const iv = this.bufferToWordArray(new Uint8ClampedArray(encryptedData.metadata)); - const data = this.bufferToWordArray(new Uint8ClampedArray(encryptedData.data)); - return AesCbcCryptor.encoder.encode(this.CryptoJS.AES.decrypt({ ciphertext: data }, this.encryptedKey, { - iv, - mode: this.CryptoJS.mode.CBC, - }).toString(this.CryptoJS.enc.Utf8)).buffer; - } - decryptFileData(encryptedData) { - return __awaiter(this, void 0, void 0, function* () { - if (typeof encryptedData.data === 'string') - throw new Error('Decryption error: data for decryption should be ArrayBuffed.'); - const key = yield this.getKey(); - return crypto.subtle.decrypt({ name: this.algo, iv: encryptedData.metadata }, key, encryptedData.data); - }); - } - // endregion - // -------------------------------------------------------- - // ----------------------- Helpers ------------------------ - // -------------------------------------------------------- - // region Helpers - get identifier() { - return 'ACRH'; - } - /** - * Cryptor algorithm. - * - * @returns Cryptor module algorithm. - */ - get algo() { - return 'AES-CBC'; - } - /** - * Generate random initialization vector. - * - * @returns Random initialization vector. - */ - getIv() { - return crypto.getRandomValues(new Uint8Array(AesCbcCryptor.BLOCK_SIZE)); - } - /** - * Convert cipher key to the {@link Buffer}. - * - * @returns SHA256 encoded cipher key {@link Buffer}. - */ - getKey() { - return __awaiter(this, void 0, void 0, function* () { - const bKey = AesCbcCryptor.encoder.encode(this.cipherKey); - const abHash = yield crypto.subtle.digest('SHA-256', bKey.buffer); - return crypto.subtle.importKey('raw', abHash, this.algo, true, ['encrypt', 'decrypt']); - }); - } - /** - * Convert bytes array to words array. - * - * @param b - Bytes array (buffer) which should be converted. - * - * @returns Word sized array. - */ - bufferToWordArray(b) { - const wa = []; - let i; - for (i = 0; i < b.length; i += 1) { - wa[(i / 4) | 0] |= b[i] << (24 - 8 * i); - } - return this.CryptoJS.lib.WordArray.create(wa, b.length); - } - /** - * Serialize cryptor information to string. - * - * @returns Serialized cryptor information. - */ - toString() { - return 'AesCbcCryptor {}'; - } - } - /** - * Cryptor block size. - */ - AesCbcCryptor.BLOCK_SIZE = 16; - /** - * {@link string|String} to {@link ArrayBuffer} response decoder. - */ - AesCbcCryptor.encoder = new TextEncoder(); - /** - * {@link ArrayBuffer} to {@link string} decoder. - */ - AesCbcCryptor.decoder = new TextDecoder(); - - /** - * PubNub package utilities module. - * - * @internal - */ - /** - * Object log property names that must never appear in SDK logs. - * - * @internal - */ - const SENSITIVE_LOG_KEYS = new Set(['authKey', 'authKeys', 'secretKey', 'cipherKey', 'token', 'auth']); - /** - * Whether an object log key should be omitted because it may hold a secret. - * - * @param key - Property name from an object being logged. - * - * @returns `true` when the key should be filtered from log output. - * - * @internal - */ - const isSensitiveLogKey = (key) => SENSITIVE_LOG_KEYS.has(key); - /** - * Percent-encode input string. - * - * **Note:** Encode content in accordance of the `PubNub` service requirements. - * - * @param input - Source string or number for encoding. - * - * @returns Percent-encoded string. - * - * @internal - */ - const encodeString = (input) => { - return encodeURIComponent(input).replace(/[!~*'()]/g, (x) => `%${x.charCodeAt(0).toString(16).toUpperCase()}`); - }; - /** - * Percent-encode list of names (channels). - * - * @param names - List of names which should be encoded. - * - * @param [defaultString] - String which should be used in case if {@link names} is empty. - * - * @returns String which contains encoded names joined by non-encoded `,`. - * - * @internal - */ - const encodeNames = (names, defaultString) => { - const encodedNames = names.map((name) => encodeString(name)); - return encodedNames.length ? encodedNames.join(',') : (defaultString !== null && defaultString !== void 0 ? defaultString : ''); - }; - /** - * @internal - */ - const removeSingleOccurrence = (source, elementsToRemove) => { - const removed = Object.fromEntries(elementsToRemove.map((prop) => [prop, false])); - return source.filter((e) => { - if (elementsToRemove.includes(e) && !removed[e]) { - removed[e] = true; - return false; - } - return true; - }); - }; - /** - * @internal - */ - const findUniqueCommonElements = (a, b) => { - return [...a].filter((value) => b.includes(value) && a.indexOf(value) === a.lastIndexOf(value) && b.indexOf(value) === b.lastIndexOf(value)); - }; - /** - * Transform query key / value pairs to the string. - * - * @param query - Key / value pairs of the request query parameters. - * - * @returns Stringified query key / value pairs. - * - * @internal - */ - const queryStringFromObject = (query) => { - return Object.keys(query) - .map((key) => { - const queryValue = query[key]; - if (!Array.isArray(queryValue)) - return `${key}=${encodeString(queryValue)}`; - return queryValue.map((value) => `${key}=${encodeString(value)}`).join('&'); - }) - .join('&'); - }; - /** - * Adjust `timetoken` to represent current time in PubNub's high-precision time format. - * - * @param timetoken - Timetoken recently used for subscribe long-poll request. - * @param [referenceTimetoken] - Previously computed reference timetoken. - * - * @returns Adjusted timetoken if recent timetoken available. - */ - const subscriptionTimetokenFromReference = (timetoken, referenceTimetoken) => { - if (referenceTimetoken === '0' || timetoken === '0') - return undefined; - const timetokenDiff = adjustedTimetokenBy(`${Date.now()}0000`, referenceTimetoken, false); - return adjustedTimetokenBy(timetoken, timetokenDiff, true); - }; - /** - * Create reference timetoken based on subscribe timetoken and the user's local time. - * - * Subscription-based reference timetoken allows later computing approximate timetoken at any point in time. - * - * @param [serviceTimetoken] - Timetoken received from the PubNub subscribe service. - * @param [catchUpTimetoken] - Previously stored or user-provided catch-up timetoken. - * @param [referenceTimetoken] - Previously computed reference timetoken. **Important:** This value should be used - * in the case of restore because the actual time when service and catch-up timetokens are received is really - * different from the current local time. - * - * @returns Reference timetoken. - */ - const referenceSubscribeTimetoken = (serviceTimetoken, catchUpTimetoken, referenceTimetoken) => { - if (!serviceTimetoken || serviceTimetoken.length === 0) - return undefined; - if (catchUpTimetoken && catchUpTimetoken.length > 0 && catchUpTimetoken !== '0') { - // Compensate reference timetoken because catch-up timetoken has been used. - const timetokensDiff = adjustedTimetokenBy(serviceTimetoken, catchUpTimetoken, false); - return adjustedTimetokenBy(referenceTimetoken !== null && referenceTimetoken !== void 0 ? referenceTimetoken : `${Date.now()}0000`, timetokensDiff.replace('-', ''), Number(timetokensDiff) < 0); - } - else if (referenceTimetoken && referenceTimetoken.length > 0 && referenceTimetoken !== '0') - return referenceTimetoken; - else - return `${Date.now()}0000`; - }; - /** - * High-precision time token adjustment. - * - * @param timetoken - Source timetoken which should be adjusted. - * @param value - Value in nanoseconds which should be used for source timetoken adjustment. - * @param increment - Whether source timetoken should be incremented or decremented. - * - * @returns Adjusted high-precision PubNub timetoken. - */ - const adjustedTimetokenBy = (timetoken, value, increment) => { - // Normalize value to the PubNub's high-precision time format. - if (value.startsWith('-')) { - value = value.replace('-', ''); - increment = false; - } - value = value.padStart(17, '0'); - const secA = timetoken.slice(0, 10); - const tickA = timetoken.slice(10, 17); - const secB = value.slice(0, 10); - const tickB = value.slice(10, 17); - let seconds = Number(secA); - let ticks = Number(tickA); - seconds += Number(secB) * (increment ? 1 : -1); - ticks += Number(tickB) * (increment ? 1 : -1); - if (ticks >= 10000000) { - seconds += Math.floor(ticks / 10000000); - ticks %= 10000000; - } - else if (ticks < 0) { - if (seconds > 0) { - seconds -= 1; - ticks += 10000000; - } - else if (seconds < 0) - ticks *= -1; - } - else if (seconds < 0 && ticks > 0) { - seconds += 1; - ticks = 10000000 - ticks; - } - return seconds !== 0 ? `${seconds}${`${ticks}`.padStart(7, '0')}` : `${ticks}`; - }; - /** - * Compute received update (message, event) fingerprint. - * - * @param input - Data payload from subscribe API response. - * - * @returns Received update fingerprint. - */ - const messageFingerprint = (input) => { - const msg = typeof input !== 'string' ? JSON.stringify(input) : input; - const mfp = new Uint32Array(1); - let walk = 0; - let len = msg.length; - while (len-- > 0) - mfp[0] = (mfp[0] << 5) - mfp[0] + msg.charCodeAt(walk++); - return mfp[0].toString(16).padStart(8, '0'); - }; - - /** - * Legacy cryptography module. - * - * @internal - */ - /** - * Convert bytes array to words array. - * - * @param b - Bytes array (buffer) which should be converted. - * - * @returns Word sized array. - * - * @internal - */ - /* eslint-disable @typescript-eslint/no-explicit-any */ - function bufferToWordArray(b) { - const wa = []; - let i; - for (i = 0; i < b.length; i += 1) { - wa[(i / 4) | 0] |= b[i] << (24 - 8 * i); - } - // @ts-expect-error Bundled library without types. - return CryptoJS$1.lib.WordArray.create(wa, b.length); - } - /** - * Legacy cryptography module for files and signature. - * - * @internal - */ - class Crypto { - constructor(configuration) { - this.configuration = configuration; - /** - * Crypto initialization vector. - */ - this.iv = '0123456789012345'; - /** - * List os allowed cipher key encodings. - */ - this.allowedKeyEncodings = ['hex', 'utf8', 'base64', 'binary']; - /** - * Allowed cipher key lengths. - */ - this.allowedKeyLengths = [128, 256]; - /** - * Allowed crypto modes. - */ - this.allowedModes = ['ecb', 'cbc']; - this.logger = configuration.logger; - this.defaultOptions = { - encryptKey: true, - keyEncoding: 'utf8', - keyLength: 256, - mode: 'cbc', - }; - } - /** - * Update registered loggers' manager. - * - * @param [logger] - Logger, which crypto should use. - */ - set logger(logger) { - this._logger = logger; - if (this.logger) { - this.logger.debug('Crypto', () => ({ - messageType: 'object', - message: this.configuration, - details: 'Create with configuration:', - ignoredKeys(key, obj) { - return typeof obj[key] === 'function' || key === 'logger' || isSensitiveLogKey(key); - }, - })); - } - } - /** - * Get loggers' manager. - * - * @returns Loggers' manager (if set). - */ - get logger() { - return this._logger; - } - /** - * Generate HMAC-SHA256 hash from input data. - * - * @param data - Data from which hash should be generated. - * - * @returns HMAC-SHA256 hash from provided `data`. - */ - HMACSHA256(data) { - // @ts-expect-error Bundled library without types. - const hash = CryptoJS$1.HmacSHA256(data, this.configuration.secretKey); - // @ts-expect-error Bundled library without types. - return hash.toString(CryptoJS$1.enc.Base64); - } - /** - * Generate SHA256 hash from input data. - * - * @param data - Data from which hash should be generated. - * - * @returns SHA256 hash from provided `data`. - */ - SHA256(data) { - // @ts-expect-error Bundled library without types. - return CryptoJS$1.SHA256(data).toString(CryptoJS$1.enc.Hex); - } - /** - * Encrypt provided data. - * - * @param data - Source data which should be encrypted. - * @param [customCipherKey] - Custom cipher key (different from defined on client level). - * @param [options] - Specific crypto configuration options. - * - * @returns Encrypted `data`. - */ - encrypt(data, customCipherKey, options) { - if (this.configuration.customEncrypt) { - if (this.logger) - this.logger.warn('Crypto', "'customEncrypt' is deprecated. Consult docs for better alternative."); - return this.configuration.customEncrypt(data); - } - return this.pnEncrypt(data, customCipherKey, options); - } - /** - * Decrypt provided data. - * - * @param data - Encrypted data which should be decrypted. - * @param [customCipherKey] - Custom cipher key (different from defined on client level). - * @param [options] - Specific crypto configuration options. - * - * @returns Decrypted `data`. - */ - decrypt(data, customCipherKey, options) { - if (this.configuration.customDecrypt) { - if (this.logger) - this.logger.warn('Crypto', "'customDecrypt' is deprecated. Consult docs for better alternative."); - return this.configuration.customDecrypt(data); - } - return this.pnDecrypt(data, customCipherKey, options); - } - /** - * Encrypt provided data. - * - * @param data - Source data which should be encrypted. - * @param [customCipherKey] - Custom cipher key (different from defined on client level). - * @param [options] - Specific crypto configuration options. - * - * @returns Encrypted `data` as string. - */ - pnEncrypt(data, customCipherKey, options) { - const decidedCipherKey = customCipherKey !== null && customCipherKey !== void 0 ? customCipherKey : this.configuration.cipherKey; - if (!decidedCipherKey) - return data; - if (this.logger) { - this.logger.debug('Crypto', () => ({ - messageType: 'object', - message: Object.assign({ data }, (options !== null && options !== void 0 ? options : {})), - details: 'Encrypt with parameters:', - ignoredKeys: isSensitiveLogKey, - })); - } - options = this.parseOptions(options); - const mode = this.getMode(options); - const cipherKey = this.getPaddedKey(decidedCipherKey, options); - if (this.configuration.useRandomIVs) { - const waIv = this.getRandomIV(); - // @ts-expect-error Bundled library without types. - const waPayload = CryptoJS$1.AES.encrypt(data, cipherKey, { iv: waIv, mode }).ciphertext; - // @ts-expect-error Bundled library without types. - return waIv.clone().concat(waPayload.clone()).toString(CryptoJS$1.enc.Base64); - } - const iv = this.getIV(options); - // @ts-expect-error Bundled library without types. - const encryptedHexArray = CryptoJS$1.AES.encrypt(data, cipherKey, { iv, mode }).ciphertext; - // @ts-expect-error Bundled library without types. - const base64Encrypted = encryptedHexArray.toString(CryptoJS$1.enc.Base64); - return base64Encrypted || data; - } - /** - * Decrypt provided data. - * - * @param data - Encrypted data which should be decrypted. - * @param [customCipherKey] - Custom cipher key (different from defined on client level). - * @param [options] - Specific crypto configuration options. - * - * @returns Decrypted `data`. - */ - pnDecrypt(data, customCipherKey, options) { - const decidedCipherKey = customCipherKey !== null && customCipherKey !== void 0 ? customCipherKey : this.configuration.cipherKey; - if (!decidedCipherKey) - return data; - if (this.logger) { - this.logger.debug('Crypto', () => ({ - messageType: 'object', - message: Object.assign({ data }, (options !== null && options !== void 0 ? options : {})), - details: 'Decrypt with parameters:', - ignoredKeys: isSensitiveLogKey, - })); - } - options = this.parseOptions(options); - const mode = this.getMode(options); - const cipherKey = this.getPaddedKey(decidedCipherKey, options); - if (this.configuration.useRandomIVs) { - const ciphertext = new Uint8ClampedArray(decode(data)); - const iv = bufferToWordArray(ciphertext.slice(0, 16)); - const payload = bufferToWordArray(ciphertext.slice(16)); - try { - // @ts-expect-error Bundled library without types. - const plainJSON = CryptoJS$1.AES.decrypt({ ciphertext: payload }, cipherKey, { iv, mode }).toString( - // @ts-expect-error Bundled library without types. - CryptoJS$1.enc.Utf8); - return JSON.parse(plainJSON); - } - catch (e) { - if (this.logger) - this.logger.error('Crypto', () => ({ messageType: 'error', message: e })); - return null; - } - } - else { - const iv = this.getIV(options); - try { - // @ts-expect-error Bundled library without types. - const ciphertext = CryptoJS$1.enc.Base64.parse(data); - // @ts-expect-error Bundled library without types. - const plainJSON = CryptoJS$1.AES.decrypt({ ciphertext }, cipherKey, { iv, mode }).toString(CryptoJS$1.enc.Utf8); - return JSON.parse(plainJSON); - } - catch (e) { - if (this.logger) - this.logger.error('Crypto', () => ({ messageType: 'error', message: e })); - return null; - } - } - } - /** - * Pre-process provided custom crypto configuration. - * - * @param incomingOptions - Configuration which should be pre-processed before use. - * - * @returns Normalized crypto configuration options. - */ - parseOptions(incomingOptions) { - var _a, _b, _c, _d; - if (!incomingOptions) - return this.defaultOptions; - // Defaults - const options = { - encryptKey: (_a = incomingOptions.encryptKey) !== null && _a !== void 0 ? _a : this.defaultOptions.encryptKey, - keyEncoding: (_b = incomingOptions.keyEncoding) !== null && _b !== void 0 ? _b : this.defaultOptions.keyEncoding, - keyLength: (_c = incomingOptions.keyLength) !== null && _c !== void 0 ? _c : this.defaultOptions.keyLength, - mode: (_d = incomingOptions.mode) !== null && _d !== void 0 ? _d : this.defaultOptions.mode, - }; - // Validation - if (this.allowedKeyEncodings.indexOf(options.keyEncoding.toLowerCase()) === -1) - options.keyEncoding = this.defaultOptions.keyEncoding; - if (this.allowedKeyLengths.indexOf(options.keyLength) === -1) - options.keyLength = this.defaultOptions.keyLength; - if (this.allowedModes.indexOf(options.mode.toLowerCase()) === -1) - options.mode = this.defaultOptions.mode; - return options; - } - /** - * Decode provided cipher key. - * - * @param key - Key in `encoding` provided by `options`. - * @param options - Crypto configuration options with cipher key details. - * - * @returns Array buffer with decoded key. - */ - decodeKey(key, options) { - // @ts-expect-error Bundled library without types. - if (options.keyEncoding === 'base64') - return CryptoJS$1.enc.Base64.parse(key); - // @ts-expect-error Bundled library without types. - if (options.keyEncoding === 'hex') - return CryptoJS$1.enc.Hex.parse(key); - return key; - } - /** - * Add padding to the cipher key. - * - * @param key - Key which should be padded. - * @param options - Crypto configuration options with cipher key details. - * - * @returns Properly padded cipher key. - */ - getPaddedKey(key, options) { - key = this.decodeKey(key, options); - // @ts-expect-error Bundled library without types. - if (options.encryptKey) - return CryptoJS$1.enc.Utf8.parse(this.SHA256(key).slice(0, 32)); - return key; - } - /** - * Cipher mode. - * - * @param options - Crypto configuration with information about cipher mode. - * - * @returns Crypto cipher mode. - */ - getMode(options) { - // @ts-expect-error Bundled library without types. - if (options.mode === 'ecb') - return CryptoJS$1.mode.ECB; - // @ts-expect-error Bundled library without types. - return CryptoJS$1.mode.CBC; - } - /** - * Cipher initialization vector. - * - * @param options - Crypto configuration with information about cipher mode. - * - * @returns Initialization vector. - */ - getIV(options) { - // @ts-expect-error Bundled library without types. - return options.mode === 'cbc' ? CryptoJS$1.enc.Utf8.parse(this.iv) : null; - } - /** - * Random initialization vector. - * - * @returns Generated random initialization vector. - */ - getRandomIV() { - // @ts-expect-error Bundled library without types. - return CryptoJS$1.lib.WordArray.random(16); - } - } - - /** - * Legacy browser cryptography module. - * - * @internal - */ - /* global crypto */ - /** - * Legacy cryptography implementation for browser-based {@link PubNub} client. - * - * @internal - */ - class WebCryptography { - // -------------------------------------------------------- - // --------------------- Encryption ----------------------- - // -------------------------------------------------------- - // region Encryption - /** - * Encrypt provided source data using specific encryption {@link key}. - * - * @param key - Data encryption key.
**Note:** Same key should be used to `decrypt` data. - * @param input - Source data for encryption. - * - * @returns Encrypted data as object or stream (depending on from source data type). - * - * @throws Error if unknown data type has been passed. - */ - encrypt(key, input) { - return __awaiter(this, void 0, void 0, function* () { - if (!(input instanceof ArrayBuffer) && typeof input !== 'string') - throw new Error('Cannot encrypt this file. In browsers file encryption supports only string or ArrayBuffer'); - const cKey = yield this.getKey(key); - return input instanceof ArrayBuffer ? this.encryptArrayBuffer(cKey, input) : this.encryptString(cKey, input); - }); - } - /** - * Encrypt provided source {@link Buffer} using specific encryption {@link ArrayBuffer}. - * - * @param key - Data encryption key.
**Note:** Same key should be used to `decrypt` {@link ArrayBuffer}. - * @param buffer - Source {@link ArrayBuffer} for encryption. - * - * @returns Encrypted data as {@link ArrayBuffer} object. - */ - encryptArrayBuffer(key, buffer) { - return __awaiter(this, void 0, void 0, function* () { - const abIv = crypto.getRandomValues(new Uint8Array(16)); - return this.concatArrayBuffer(abIv.buffer, yield crypto.subtle.encrypt({ name: 'AES-CBC', iv: abIv }, key, buffer)); - }); - } - /** - * Encrypt provided source {@link string} using specific encryption {@link key}. - * - * @param key - Data encryption key.
**Note:** Same key should be used to `decrypt` {@link string}. - * @param text - Source {@link string} for encryption. - * - * @returns Encrypted data as byte {@link string}. - */ - encryptString(key, text) { - return __awaiter(this, void 0, void 0, function* () { - const abIv = crypto.getRandomValues(new Uint8Array(16)); - const abPlaintext = WebCryptography.encoder.encode(text).buffer; - const abPayload = yield crypto.subtle.encrypt({ name: 'AES-CBC', iv: abIv }, key, abPlaintext); - const ciphertext = this.concatArrayBuffer(abIv.buffer, abPayload); - return WebCryptography.decoder.decode(ciphertext); - }); - } - /** - * Encrypt provided {@link PubNub} File object using specific encryption {@link key}. - * - * @param key - Key for {@link PubNub} File object encryption.
**Note:** Same key should be - * used to `decrypt` data. - * @param file - Source {@link PubNub} File object for encryption. - * @param File - Class constructor for {@link PubNub} File object. - * - * @returns Encrypted data as {@link PubNub} File object. - * - * @throws Error if file is empty or contains unsupported data type. - */ - encryptFile(key, file, File) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b; - if (((_a = file.contentLength) !== null && _a !== void 0 ? _a : 0) <= 0) - throw new Error('encryption error. empty content'); - const bKey = yield this.getKey(key); - const abPlaindata = yield file.toArrayBuffer(); - const abCipherdata = yield this.encryptArrayBuffer(bKey, abPlaindata); - return File.create({ - name: file.name, - mimeType: (_b = file.mimeType) !== null && _b !== void 0 ? _b : 'application/octet-stream', - data: abCipherdata, - }); - }); - } - // endregion - // -------------------------------------------------------- - // --------------------- Decryption ----------------------- - // -------------------------------------------------------- - // region Decryption - /** - * Decrypt provided encrypted data using specific decryption {@link key}. - * - * @param key - Data decryption key.
**Note:** Should be the same as used to `encrypt` data. - * @param input - Encrypted data for decryption. - * - * @returns Decrypted data as object or stream (depending on from encrypted data type). - * - * @throws Error if unknown data type has been passed. - */ - decrypt(key, input) { - return __awaiter(this, void 0, void 0, function* () { - if (!(input instanceof ArrayBuffer) && typeof input !== 'string') - throw new Error('Cannot decrypt this file. In browsers file decryption supports only string or ArrayBuffer'); - const cKey = yield this.getKey(key); - return input instanceof ArrayBuffer ? this.decryptArrayBuffer(cKey, input) : this.decryptString(cKey, input); - }); - } - /** - * Decrypt provided encrypted {@link ArrayBuffer} using specific decryption {@link key}. - * - * @param key - Data decryption key.
**Note:** Should be the same as used to `encrypt` {@link ArrayBuffer}. - * @param buffer - Encrypted {@link ArrayBuffer} for decryption. - * - * @returns Decrypted data as {@link ArrayBuffer} object. - */ - decryptArrayBuffer(key, buffer) { - return __awaiter(this, void 0, void 0, function* () { - const abIv = buffer.slice(0, 16); - if (buffer.slice(WebCryptography.IV_LENGTH).byteLength <= 0) - throw new Error('decryption error: empty content'); - return yield crypto.subtle.decrypt({ name: 'AES-CBC', iv: abIv }, key, buffer.slice(WebCryptography.IV_LENGTH)); - }); - } - /** - * Decrypt provided encrypted {@link string} using specific decryption {@link key}. - * - * @param key - Data decryption key.
**Note:** Should be the same as used to `encrypt` {@link string}. - * @param text - Encrypted {@link string} for decryption. - * - * @returns Decrypted data as byte {@link string}. - */ - decryptString(key, text) { - return __awaiter(this, void 0, void 0, function* () { - const abCiphertext = WebCryptography.encoder.encode(text).buffer; - const abIv = abCiphertext.slice(0, 16); - const abPayload = abCiphertext.slice(16); - const abPlaintext = yield crypto.subtle.decrypt({ name: 'AES-CBC', iv: abIv }, key, abPayload); - return WebCryptography.decoder.decode(abPlaintext); - }); - } - /** - * Decrypt provided {@link PubNub} File object using specific decryption {@link key}. - * - * @param key - Key for {@link PubNub} File object decryption.
**Note:** Should be the same - * as used to `encrypt` data. - * @param file - Encrypted {@link PubNub} File object for decryption. - * @param File - Class constructor for {@link PubNub} File object. - * - * @returns Decrypted data as {@link PubNub} File object. - * - * @throws Error if file is empty or contains unsupported data type. - */ - decryptFile(key, file, File) { - return __awaiter(this, void 0, void 0, function* () { - const bKey = yield this.getKey(key); - const abCipherdata = yield file.toArrayBuffer(); - const abPlaindata = yield this.decryptArrayBuffer(bKey, abCipherdata); - return File.create({ - name: file.name, - mimeType: file.mimeType, - data: abPlaindata, - }); - }); - } - // endregion - // -------------------------------------------------------- - // ----------------------- Helpers ------------------------ - // -------------------------------------------------------- - // region Helpers - /** - * Convert cipher key to the {@link Buffer}. - * - * @param key - String cipher key. - * - * @returns SHA256 HEX encoded cipher key {@link CryptoKey}. - */ - getKey(key) { - return __awaiter(this, void 0, void 0, function* () { - const digest = yield crypto.subtle.digest('SHA-256', WebCryptography.encoder.encode(key)); - const hashHex = Array.from(new Uint8Array(digest)) - .map((b) => b.toString(16).padStart(2, '0')) - .join(''); - const abKey = WebCryptography.encoder.encode(hashHex.slice(0, 32)).buffer; - return crypto.subtle.importKey('raw', abKey, 'AES-CBC', true, ['encrypt', 'decrypt']); - }); - } - /** - * Join two `ArrayBuffer`s. - * - * @param ab1 - `ArrayBuffer` to which other buffer should be appended. - * @param ab2 - `ArrayBuffer` which should appended to the other buffer. - * - * @returns Buffer which starts with `ab1` elements and appended `ab2`. - */ - concatArrayBuffer(ab1, ab2) { - const tmp = new Uint8Array(ab1.byteLength + ab2.byteLength); - tmp.set(new Uint8Array(ab1), 0); - tmp.set(new Uint8Array(ab2), ab1.byteLength); - return tmp.buffer; - } - } - /** - * Random initialization vector size. - */ - WebCryptography.IV_LENGTH = 16; - /** - * {@link string|String} to {@link ArrayBuffer} response decoder. - */ - WebCryptography.encoder = new TextEncoder(); - /** - * {@link ArrayBuffer} to {@link string} decoder. - */ - WebCryptography.decoder = new TextDecoder(); - - /** - * Legacy cryptor module. - */ - /** - * Legacy cryptor. - */ - class LegacyCryptor { - constructor(config) { - this.config = config; - this.cryptor = new Crypto(Object.assign({}, config)); - this.fileCryptor = new WebCryptography(); - } - /** - * Update registered loggers' manager. - * - * @param [logger] - Logger, which crypto should use. - */ - set logger(logger) { - this.cryptor.logger = logger; - if (this.config.useRandomIVs === false) { - logger.warn('LegacyCryptor', `Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients. - Do not disable random IVs in new applications.`); - } - } - // -------------------------------------------------------- - // --------------------- Encryption ----------------------- - // -------------------------------------------------------- - // region Encryption - encrypt(data) { - const stringData = typeof data === 'string' ? data : LegacyCryptor.decoder.decode(data); - return { - data: this.cryptor.encrypt(stringData), - metadata: null, - }; - } - encryptFile(file, File) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - if (!this.config.cipherKey) - throw new PubNubError('File encryption error: cipher key not set.'); - return this.fileCryptor.encryptFile((_a = this.config) === null || _a === void 0 ? void 0 : _a.cipherKey, file, File); - }); - } - // endregion - // -------------------------------------------------------- - // --------------------- Decryption ----------------------- - // -------------------------------------------------------- - // region Decryption - decrypt(encryptedData) { - const data = typeof encryptedData.data === 'string' ? encryptedData.data : encode(encryptedData.data); - return this.cryptor.decrypt(data); - } - decryptFile(file, File) { - return __awaiter(this, void 0, void 0, function* () { - if (!this.config.cipherKey) - throw new PubNubError('File encryption error: cipher key not set.'); - return this.fileCryptor.decryptFile(this.config.cipherKey, file, File); - }); - } - // endregion - // -------------------------------------------------------- - // ----------------------- Helpers ------------------------ - // -------------------------------------------------------- - // region Helpers - get identifier() { - return ''; - } - // endregion - /** - * Serialize cryptor information to string. - * - * @returns Serialized cryptor information. - */ - toString() { - const configurationEntries = Object.entries(this.config).reduce((acc, [key, value]) => { - if (key === 'logger' || isSensitiveLogKey(key)) - return acc; - acc.push(`${key}: ${typeof value === 'function' ? '' : value}`); - return acc; - }, []); - return `LegacyCryptor { ${configurationEntries.join(', ')} }`; - } - } - /** - * `string` to {@link ArrayBuffer} response decoder. - */ - LegacyCryptor.encoder = new TextEncoder(); - /** - * {@link ArrayBuffer} to {@link string} decoder. - */ - LegacyCryptor.decoder = new TextDecoder(); - - /** - * Browser crypto module. - */ - /** - * CryptoModule for browser platform. - */ - class WebCryptoModule extends AbstractCryptoModule { - /** - * Assign registered loggers' manager. - * - * @param logger - Registered loggers' manager. - * - * @internal - */ - set logger(logger) { - if (this.defaultCryptor.identifier === WebCryptoModule.LEGACY_IDENTIFIER) { - logger.warn('CryptoModule', "'legacyCryptoModule' is deprecated. Use 'aesCbcCryptoModule' instead for new applications."); - this.defaultCryptor.logger = logger; - } - else { - const cryptor = this.cryptors.find((cryptor) => cryptor.identifier === WebCryptoModule.LEGACY_IDENTIFIER); - if (cryptor) - cryptor.logger = logger; - } - } - // -------------------------------------------------------- - // --------------- Convenience functions ------------------ - // ------------------------------------------------------- - // region Convenience functions - /** - * Construct crypto module with legacy cryptor for encryption and both legacy and AES-CBC - * cryptors for decryption. - * - * @deprecated Use {@link aesCbcCryptoModule} for new applications. - */ - static legacyCryptoModule(config) { - var _a; - if (!config.cipherKey) - throw new PubNubError('Crypto module error: cipher key not set.'); - if (config.logger) { - config.logger.warn('CryptoModule', "'legacyCryptoModule' is deprecated. Use 'aesCbcCryptoModule' instead for new applications."); - if (config.useRandomIVs === false) { - config.logger.warn('CryptoModule', `Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients. - Do not disable random IVs in new applications.`); - } - } - return new WebCryptoModule({ - default: new LegacyCryptor(Object.assign(Object.assign({}, config), { useRandomIVs: (_a = config.useRandomIVs) !== null && _a !== void 0 ? _a : true })), - cryptors: [new AesCbcCryptor({ cipherKey: config.cipherKey })], - }); - } - static aesCbcCryptoModule(config) { - var _a; - if (!config.cipherKey) - throw new PubNubError('Crypto module error: cipher key not set.'); - return new WebCryptoModule({ - default: new AesCbcCryptor({ cipherKey: config.cipherKey }), - cryptors: [ - new LegacyCryptor(Object.assign(Object.assign({}, config), { useRandomIVs: (_a = config.useRandomIVs) !== null && _a !== void 0 ? _a : true })), - ], - }); - } - /** - * Construct crypto module with `cryptor` as default for data encryption and decryption. - * - * @param defaultCryptor - Default cryptor for data encryption and decryption. - * - * @returns Crypto module with pre-configured default cryptor. - */ - static withDefaultCryptor(defaultCryptor) { - return new this({ default: defaultCryptor }); - } - // endregion - // -------------------------------------------------------- - // --------------------- Encryption ----------------------- - // -------------------------------------------------------- - // region Encryption - encrypt(data) { - // Encrypt data. - const encrypted = data instanceof ArrayBuffer && this.defaultCryptor.identifier === WebCryptoModule.LEGACY_IDENTIFIER - ? this.defaultCryptor.encrypt(WebCryptoModule.decoder.decode(data)) - : this.defaultCryptor.encrypt(data); - if (!encrypted.metadata) - return encrypted.data; - else if (typeof encrypted.data === 'string') - throw new Error('Encryption error: encrypted data should be ArrayBuffed.'); - const headerData = this.getHeaderData(encrypted); - return this.concatArrayBuffer(headerData, encrypted.data); - } - encryptFile(file, File) { - return __awaiter(this, void 0, void 0, function* () { - /** - * Files handled differently in case of Legacy cryptor. - * (as long as we support legacy need to check on instance type) - */ - if (this.defaultCryptor.identifier === CryptorHeader.LEGACY_IDENTIFIER) - return this.defaultCryptor.encryptFile(file, File); - const fileData = yield this.getFileData(file); - const encrypted = yield this.defaultCryptor.encryptFileData(fileData); - if (typeof encrypted.data === 'string') - throw new Error('Encryption error: encrypted data should be ArrayBuffed.'); - return File.create({ - name: file.name, - mimeType: 'application/octet-stream', - data: this.concatArrayBuffer(this.getHeaderData(encrypted), encrypted.data), - }); - }); - } - // endregion - // -------------------------------------------------------- - // --------------------- Decryption ----------------------- - // -------------------------------------------------------- - // region Decryption - decrypt(data) { - const encryptedData = typeof data === 'string' ? decode(data) : data; - const header = CryptorHeader.tryParse(encryptedData); - const cryptor = this.getCryptor(header); - const metadata = header.length > 0 - ? encryptedData.slice(header.length - header.metadataLength, header.length) - : null; - if (encryptedData.slice(header.length).byteLength <= 0) - throw new Error('Decryption error: empty content'); - return cryptor.decrypt({ - data: encryptedData.slice(header.length), - metadata: metadata, - }); - } - decryptFile(file, File) { - return __awaiter(this, void 0, void 0, function* () { - const data = yield file.data.arrayBuffer(); - const header = CryptorHeader.tryParse(data); - const cryptor = this.getCryptor(header); - /** - * Files handled differently in case of Legacy cryptor. - * (as long as we support legacy need to check on instance type) - */ - if ((cryptor === null || cryptor === void 0 ? void 0 : cryptor.identifier) === CryptorHeader.LEGACY_IDENTIFIER) - return cryptor.decryptFile(file, File); - const fileData = yield this.getFileData(data); - const metadata = fileData.slice(header.length - header.metadataLength, header.length); - return File.create({ - name: file.name, - data: yield this.defaultCryptor.decryptFileData({ - data: data.slice(header.length), - metadata: metadata, - }), - }); - }); - } - // endregion - // -------------------------------------------------------- - // ----------------------- Helpers ------------------------ - // -------------------------------------------------------- - // region Helpers - /** - * Retrieve registered cryptor by its identifier. - * - * @param id - Unique cryptor identifier. - * - * @returns Registered cryptor with specified identifier. - * - * @throws Error if cryptor with specified {@link id} can't be found. - */ - getCryptorFromId(id) { - const cryptor = this.getAllCryptors().find((cryptor) => id === cryptor.identifier); - if (cryptor) - return cryptor; - throw Error('Unknown cryptor error'); - } - /** - * Retrieve cryptor by its identifier. - * - * @param header - Header with cryptor-defined data or raw cryptor identifier. - * - * @returns Cryptor which correspond to provided {@link header}. - */ - getCryptor(header) { - if (typeof header === 'string') { - const cryptor = this.getAllCryptors().find((cryptor) => cryptor.identifier === header); - if (cryptor) - return cryptor; - throw new Error('Unknown cryptor error'); - } - else if (header instanceof CryptorHeaderV1) { - return this.getCryptorFromId(header.identifier); - } - } - /** - * Create cryptor header data. - * - * @param encrypted - Encryption data object as source for header data. - * - * @returns Binary representation of the cryptor header data. - */ - getHeaderData(encrypted) { - if (!encrypted.metadata) - return; - const header = CryptorHeader.from(this.defaultCryptor.identifier, encrypted.metadata); - const headerData = new Uint8Array(header.length); - let pos = 0; - headerData.set(header.data, pos); - pos += header.length - encrypted.metadata.byteLength; - headerData.set(new Uint8Array(encrypted.metadata), pos); - return headerData.buffer; - } - /** - * Merge two {@link ArrayBuffer} instances. - * - * @param ab1 - First {@link ArrayBuffer}. - * @param ab2 - Second {@link ArrayBuffer}. - * - * @returns Merged data as {@link ArrayBuffer}. - */ - concatArrayBuffer(ab1, ab2) { - const tmp = new Uint8Array(ab1.byteLength + ab2.byteLength); - tmp.set(new Uint8Array(ab1), 0); - tmp.set(new Uint8Array(ab2), ab1.byteLength); - return tmp.buffer; - } - /** - * Retrieve file content. - * - * @param file - Content of the {@link PubNub} File object. - * - * @returns Normalized file {@link data} as {@link ArrayBuffer}; - */ - getFileData(file) { - return __awaiter(this, void 0, void 0, function* () { - if (file instanceof ArrayBuffer) - return file; - else if (file instanceof PubNubFile) - return file.toArrayBuffer(); - throw new Error('Cannot decrypt/encrypt file. In browsers file encrypt/decrypt supported for string, ArrayBuffer or Blob'); - }); - } - } - /** - * {@link LegacyCryptor|Legacy} cryptor identifier. - */ - WebCryptoModule.LEGACY_IDENTIFIER = ''; - /** - * CryptorHeader Utility - */ - class CryptorHeader { - static from(id, metadata) { - if (id === CryptorHeader.LEGACY_IDENTIFIER) - return; - return new CryptorHeaderV1(id, metadata.byteLength); - } - static tryParse(data) { - const encryptedData = new Uint8Array(data); - let sentinel; - let version = null; - if (encryptedData.byteLength >= 4) { - sentinel = encryptedData.slice(0, 4); - if (this.decoder.decode(sentinel) !== CryptorHeader.SENTINEL) - return WebCryptoModule.LEGACY_IDENTIFIER; - } - if (encryptedData.byteLength >= 5) - version = encryptedData[4]; - else - throw new Error('Decryption error: invalid header version'); - if (version > CryptorHeader.MAX_VERSION) - throw new Error('Decryption error: Unknown cryptor error'); - let identifier; - let pos = 5 + CryptorHeader.IDENTIFIER_LENGTH; - if (encryptedData.byteLength >= pos) - identifier = encryptedData.slice(5, pos); - else - throw new Error('Decryption error: invalid crypto identifier'); - let metadataLength = null; - if (encryptedData.byteLength >= pos + 1) - metadataLength = encryptedData[pos]; - else - throw new Error('Decryption error: invalid metadata length'); - pos += 1; - if (metadataLength === 255 && encryptedData.byteLength >= pos + 2) { - metadataLength = new Uint16Array(encryptedData.slice(pos, pos + 2)).reduce((acc, val) => (acc << 8) + val, 0); - } - return new CryptorHeaderV1(this.decoder.decode(identifier), metadataLength); - } - } - CryptorHeader.SENTINEL = 'PNED'; - CryptorHeader.LEGACY_IDENTIFIER = ''; - CryptorHeader.IDENTIFIER_LENGTH = 4; - CryptorHeader.VERSION = 1; - CryptorHeader.MAX_VERSION = 1; - CryptorHeader.decoder = new TextDecoder(); - // v1 CryptorHeader - class CryptorHeaderV1 { - constructor(id, metadataLength) { - this._identifier = id; - this._metadataLength = metadataLength; - } - get identifier() { - return this._identifier; - } - set identifier(value) { - this._identifier = value; - } - get metadataLength() { - return this._metadataLength; - } - set metadataLength(value) { - this._metadataLength = value; - } - get version() { - return CryptorHeader.VERSION; - } - get length() { - return (CryptorHeader.SENTINEL.length + - 1 + - CryptorHeader.IDENTIFIER_LENGTH + - (this.metadataLength < 255 ? 1 : 3) + - this.metadataLength); - } - get data() { - let pos = 0; - const header = new Uint8Array(this.length); - const encoder = new TextEncoder(); - header.set(encoder.encode(CryptorHeader.SENTINEL)); - pos += CryptorHeader.SENTINEL.length; - header[pos] = this.version; - pos++; - if (this.identifier) - header.set(encoder.encode(this.identifier), pos); - const metadataLength = this.metadataLength; - pos += CryptorHeader.IDENTIFIER_LENGTH; - if (metadataLength < 255) - header[pos] = metadataLength; - else - header.set([255, metadataLength >> 8, metadataLength & 0xff], pos); - return header; - } - } - CryptorHeaderV1.IDENTIFIER_LENGTH = 4; - CryptorHeaderV1.SENTINEL = 'PNED'; - - /** - * REST API endpoint use error module. - * - * @internal - */ - /** - * PubNub REST API call error. - * - * @internal - */ - class PubNubAPIError extends Error { - /** - * Construct API from known error object or {@link PubNub} service error response. - * - * @param errorOrResponse - `Error` or service error response object from which error information - * should be extracted. - * @param [data] - Preprocessed service error response. - * - * @returns `PubNubAPIError` object with known error category and additional information (if - * available). - */ - static create(errorOrResponse, data) { - if (PubNubAPIError.isErrorObject(errorOrResponse)) - return PubNubAPIError.createFromError(errorOrResponse); - else - return PubNubAPIError.createFromServiceResponse(errorOrResponse, data); - } - /** - * Create API error instance from other error object. - * - * @param error - `Error` object provided by network provider (mostly) or other {@link PubNub} client components. - * - * @returns `PubNubAPIError` object with known error category and additional information (if - * available). - */ - static createFromError(error) { - let category = StatusCategory$1.PNUnknownCategory; - let message = 'Unknown error'; - let errorName = 'Error'; - if (!error) - return new PubNubAPIError(message, category, 0); - else if (error instanceof PubNubAPIError) - return error; - if (PubNubAPIError.isErrorObject(error)) { - message = error.message; - errorName = error.name; - } - if (errorName === 'AbortError' || message.indexOf('Aborted') !== -1) { - category = StatusCategory$1.PNCancelledCategory; - message = 'Request cancelled'; - } - else if (message.toLowerCase().indexOf('timeout') !== -1) { - category = StatusCategory$1.PNTimeoutCategory; - message = 'Request timeout'; - } - else if (message.toLowerCase().indexOf('network') !== -1) { - category = StatusCategory$1.PNNetworkIssuesCategory; - message = 'Network issues'; - } - else if (errorName === 'TypeError') { - if (message.indexOf('Load failed') !== -1 || message.indexOf('Failed to fetch') != -1) - category = StatusCategory$1.PNNetworkIssuesCategory; - else - category = StatusCategory$1.PNBadRequestCategory; - } - else if (errorName === 'FetchError') { - const errorCode = error.code; - if (['ECONNREFUSED', 'ENETUNREACH', 'ENOTFOUND', 'ECONNRESET', 'EAI_AGAIN'].includes(errorCode)) - category = StatusCategory$1.PNNetworkIssuesCategory; - if (errorCode === 'ECONNREFUSED') - message = 'Connection refused'; - else if (errorCode === 'ENETUNREACH') - message = 'Network not reachable'; - else if (errorCode === 'ENOTFOUND') - message = 'Server not found'; - else if (errorCode === 'ECONNRESET') - message = 'Connection reset by peer'; - else if (errorCode === 'EAI_AGAIN') - message = 'Name resolution error'; - else if (errorCode === 'ETIMEDOUT') { - category = StatusCategory$1.PNTimeoutCategory; - message = 'Request timeout'; - } - else - message = `Unknown system error: ${error}`; - } - else if (message === 'Request timeout') - category = StatusCategory$1.PNTimeoutCategory; - return new PubNubAPIError(message, category, 0, error); - } - /** - * Construct API from known {@link PubNub} service error response. - * - * @param response - Service error response object from which error information should be - * extracted. - * @param [data] - Preprocessed service error response. - * - * @returns `PubNubAPIError` object with known error category and additional information (if - * available). - */ - static createFromServiceResponse(response, data) { - let category = StatusCategory$1.PNUnknownCategory; - let errorData; - let message = 'Unknown error'; - let { status } = response; - data !== null && data !== void 0 ? data : (data = response.body); - if (status === 402) - message = 'Not available for used key set. Contact support@pubnub.com'; - else if (status === 404) - message = 'Resource not found'; - else if (status === 400) { - category = StatusCategory$1.PNBadRequestCategory; - message = 'Bad request'; - } - else if (status === 403) { - category = StatusCategory$1.PNAccessDeniedCategory; - message = 'Access denied'; - } - else if (status >= 500) { - category = StatusCategory$1.PNServerErrorCategory; - message = 'Internal server error'; - } - if (typeof response === 'object' && Object.keys(response).length === 0) { - category = StatusCategory$1.PNMalformedResponseCategory; - message = 'Malformed response (network issues)'; - status = 400; - } - // Try to get more information about error from service response. - if (data && data.byteLength > 0) { - const decoded = new TextDecoder().decode(data); - if (response.headers['content-type'].indexOf('text/javascript') !== -1 || - response.headers['content-type'].indexOf('application/json') !== -1) { - try { - const errorResponse = JSON.parse(decoded); - if (typeof errorResponse === 'object') { - if (!Array.isArray(errorResponse)) { - if ('error' in errorResponse && - (errorResponse.error === 1 || errorResponse.error === true) && - 'status' in errorResponse && - typeof errorResponse.status === 'number' && - 'message' in errorResponse && - 'service' in errorResponse) { - errorData = errorResponse; - status = errorResponse.status; - } - else - errorData = errorResponse; - if ('error' in errorResponse && errorResponse.error instanceof Error) - errorData = errorResponse.error; - } - else { - // Handling Publish API payload error. - if (typeof errorResponse[0] === 'number' && errorResponse[0] === 0) { - if (errorResponse.length > 1 && typeof errorResponse[1] === 'string') - errorData = errorResponse[1]; - } - } - } - } - catch (_) { - errorData = decoded; - } - } - else if (response.headers['content-type'].indexOf('xml') !== -1) { - const reason = /(.*)<\/Message>/gi.exec(decoded); - message = reason ? `Upload to bucket failed: ${reason[1]}` : 'Upload to bucket failed.'; - } - else { - errorData = decoded; - } - } - return new PubNubAPIError(message, category, status, errorData); - } - /** - * Construct PubNub endpoint error. - * - * @param message - Short API call error description. - * @param category - Error category. - * @param statusCode - Response HTTP status code. - * @param [errorData] - Error information. - */ - constructor(message, category, statusCode, errorData) { - super(message); - this.category = category; - this.statusCode = statusCode; - this.errorData = errorData; - this.name = 'PubNubAPIError'; - } - /** - * Convert API error object to API callback status object. - * - * @param operation - Request operation during which error happened. - * - * @returns Pre-formatted API callback status object. - */ - toStatus(operation) { - return { - error: true, - category: this.category, - operation, - statusCode: this.statusCode, - errorData: this.errorData, - // @ts-expect-error Inner helper for JSON.stringify. - toJSON: function () { - let normalizedErrorData; - const errorData = this.errorData; - if (errorData) { - try { - if (typeof errorData === 'object') { - const errorObject = Object.assign(Object.assign(Object.assign(Object.assign({}, ('name' in errorData ? { name: errorData.name } : {})), ('message' in errorData ? { message: errorData.message } : {})), ('stack' in errorData ? { stack: errorData.stack } : {})), errorData); - normalizedErrorData = JSON.parse(JSON.stringify(errorObject, PubNubAPIError.circularReplacer())); - } - else - normalizedErrorData = errorData; - } - catch (_) { - normalizedErrorData = { error: 'Could not serialize the error object' }; - } - } - // Make sure to exclude `toJSON` function from the final object. - const _a = this, status = __rest(_a, ["toJSON"]); - return JSON.stringify(Object.assign(Object.assign({}, status), { errorData: normalizedErrorData })); - }, - }; - } - /** - * Convert API error object to PubNub client error object. - * - * @param operation - Request operation during which error happened. - * @param [message] - Custom error message. - * - * @returns Client-facing pre-formatted endpoint call error. - */ - toPubNubError(operation, message) { - return new PubNubError(message !== null && message !== void 0 ? message : this.message, this.toStatus(operation)); - } - /** - * Function which handles circular references in serialized JSON. - * - * @returns Circular reference replacer function. - * - * @internal - */ - static circularReplacer() { - const visited = new WeakSet(); - return function (_, value) { - if (typeof value === 'object' && value !== null) { - if (visited.has(value)) - return '[Circular]'; - visited.add(value); - } - return value; - }; - } - /** - * Check whether provided `object` is an `Error` or not. - * - * This check is required because the error object may be tied to a different execution context (global - * environment) and won't pass `instanceof Error` from the main window. - * To protect against monkey-patching, the `fetch` function is taken from an invisible `iframe` and, as a result, - * it is bind to the separate execution context. Errors generated by `fetch` won't pass the simple - * `instanceof Error` test. - * - * @param object - Object which should be checked. - * - * @returns `true` if `object` looks like an `Error` object. - * - * @internal - */ - static isErrorObject(object) { - if (!object || typeof object !== 'object') - return false; - if (object instanceof Error) - return true; - if ('name' in object && - 'message' in object && - typeof object.name === 'string' && - typeof object.message === 'string') { - return true; - } - return Object.prototype.toString.call(object) === '[object Error]'; - } - } - - /** - * Endpoint API operation types. - */ - var RequestOperation; - (function (RequestOperation) { - // -------------------------------------------------------- - // ---------------------- Publish API --------------------- - // -------------------------------------------------------- - /** - * Data publish REST API operation. - */ - RequestOperation["PNPublishOperation"] = "PNPublishOperation"; - /** - * Signal sending REST API operation. - */ - RequestOperation["PNSignalOperation"] = "PNSignalOperation"; - // -------------------------------------------------------- - // --------------------- Subscribe API -------------------- - // -------------------------------------------------------- - /** - * Subscribe for real-time updates REST API operation. - * - * User's presence change on specified entities will trigger `join` event. - */ - RequestOperation["PNSubscribeOperation"] = "PNSubscribeOperation"; - /** - * Unsubscribe from real-time updates REST API operation. - * - * User's presence change on specified entities will trigger `leave` event. - */ - RequestOperation["PNUnsubscribeOperation"] = "PNUnsubscribeOperation"; - // -------------------------------------------------------- - // --------------------- Presence API --------------------- - // -------------------------------------------------------- - /** - * Fetch user's presence information REST API operation. - */ - RequestOperation["PNWhereNowOperation"] = "PNWhereNowOperation"; - /** - * Fetch channel's presence information REST API operation. - */ - RequestOperation["PNHereNowOperation"] = "PNHereNowOperation"; - /** - * Fetch global presence information REST API operation. - */ - RequestOperation["PNGlobalHereNowOperation"] = "PNGlobalHereNowOperation"; - /** - * Update user's information associated with specified channel REST API operation. - */ - RequestOperation["PNSetStateOperation"] = "PNSetStateOperation"; - /** - * Fetch user's information associated with the specified channel REST API operation. - */ - RequestOperation["PNGetStateOperation"] = "PNGetStateOperation"; - /** - * Announce presence on managed channels REST API operation. - */ - RequestOperation["PNHeartbeatOperation"] = "PNHeartbeatOperation"; - // -------------------------------------------------------- - // ----------------- Message Reaction API ----------------- - // -------------------------------------------------------- - /** - * Add a reaction to the specified message REST API operation. - */ - RequestOperation["PNAddMessageActionOperation"] = "PNAddActionOperation"; - /** - * Remove reaction from the specified message REST API operation. - */ - RequestOperation["PNRemoveMessageActionOperation"] = "PNRemoveMessageActionOperation"; - /** - * Fetch reactions for specific message REST API operation. - */ - RequestOperation["PNGetMessageActionsOperation"] = "PNGetMessageActionsOperation"; - RequestOperation["PNTimeOperation"] = "PNTimeOperation"; - // -------------------------------------------------------- - // ---------------------- Storage API --------------------- - // -------------------------------------------------------- - /** - * Channel history REST API operation. - */ - RequestOperation["PNHistoryOperation"] = "PNHistoryOperation"; - /** - * Delete messages from channel history REST API operation. - */ - RequestOperation["PNDeleteMessagesOperation"] = "PNDeleteMessagesOperation"; - /** - * History for channels REST API operation. - */ - RequestOperation["PNFetchMessagesOperation"] = "PNFetchMessagesOperation"; - /** - * Number of messages for channels in specified time frame REST API operation. - */ - RequestOperation["PNMessageCounts"] = "PNMessageCountsOperation"; - // -------------------------------------------------------- - // -------------------- App Context API ------------------- - // -------------------------------------------------------- - /** - * Fetch users metadata REST API operation. - */ - RequestOperation["PNGetAllUUIDMetadataOperation"] = "PNGetAllUUIDMetadataOperation"; - /** - * Fetch user metadata REST API operation. - */ - RequestOperation["PNGetUUIDMetadataOperation"] = "PNGetUUIDMetadataOperation"; - /** - * Set user metadata REST API operation. - */ - RequestOperation["PNSetUUIDMetadataOperation"] = "PNSetUUIDMetadataOperation"; - /** - * Remove user metadata REST API operation. - */ - RequestOperation["PNRemoveUUIDMetadataOperation"] = "PNRemoveUUIDMetadataOperation"; - /** - * Fetch channels metadata REST API operation. - */ - RequestOperation["PNGetAllChannelMetadataOperation"] = "PNGetAllChannelMetadataOperation"; - /** - * Fetch channel metadata REST API operation. - */ - RequestOperation["PNGetChannelMetadataOperation"] = "PNGetChannelMetadataOperation"; - /** - * Set channel metadata REST API operation. - */ - RequestOperation["PNSetChannelMetadataOperation"] = "PNSetChannelMetadataOperation"; - /** - * Remove channel metadata REST API operation. - */ - RequestOperation["PNRemoveChannelMetadataOperation"] = "PNRemoveChannelMetadataOperation"; - /** - * Fetch channel members REST API operation. - */ - RequestOperation["PNGetMembersOperation"] = "PNGetMembersOperation"; - /** - * Update channel members REST API operation. - */ - RequestOperation["PNSetMembersOperation"] = "PNSetMembersOperation"; - /** - * Fetch channel memberships REST API operation. - */ - RequestOperation["PNGetMembershipsOperation"] = "PNGetMembershipsOperation"; - /** - * Update channel memberships REST API operation. - */ - RequestOperation["PNSetMembershipsOperation"] = "PNSetMembershipsOperation"; - // -------------------------------------------------------- - // ------------------- DataSync API ---------------------- - // -------------------------------------------------------- - /** - * Create entity REST API operation. - */ - RequestOperation["PNCreateDataSyncEntityOperation"] = "PNCreateDataSyncEntityOperation"; - /** - * Get entity REST API operation. - */ - RequestOperation["PNGetDataSyncEntityOperation"] = "PNGetDataSyncEntityOperation"; - /** - * Get all entities REST API operation. - */ - RequestOperation["PNGetDataSyncEntitiesOperation"] = "PNGetDataSyncEntitiesOperation"; - /** - * Set entity REST API operation (full replacement via PUT). - */ - RequestOperation["PNSetDataSyncEntityOperation"] = "PNSetDataSyncEntityOperation"; - /** - * Update entity REST API operation (partial update via PATCH). - */ - RequestOperation["PNUpdateDataSyncEntityOperation"] = "PNUpdateDataSyncEntityOperation"; - /** - * Remove entity REST API operation. - */ - RequestOperation["PNRemoveDataSyncEntityOperation"] = "PNRemoveDataSyncEntityOperation"; - /** - * Create relationship REST API operation. - */ - RequestOperation["PNCreateDataSyncRelationshipOperation"] = "PNCreateDataSyncRelationshipOperation"; - /** - * Get relationship REST API operation. - */ - RequestOperation["PNGetDataSyncRelationshipOperation"] = "PNGetDataSyncRelationshipOperation"; - /** - * Get all relationships REST API operation. - */ - RequestOperation["PNGetDataSyncRelationshipsOperation"] = "PNGetDataSyncRelationshipsOperation"; - /** - * Set relationship REST API operation (full replacement via PUT). - */ - RequestOperation["PNSetDataSyncRelationshipOperation"] = "PNSetDataSyncRelationshipOperation"; - /** - * Update relationship REST API operation (partial update via PATCH). - */ - RequestOperation["PNUpdateDataSyncRelationshipOperation"] = "PNUpdateDataSyncRelationshipOperation"; - /** - * Remove relationship REST API operation. - */ - RequestOperation["PNRemoveDataSyncRelationshipOperation"] = "PNRemoveDataSyncRelationshipOperation"; - /** - * Create user REST API operation. - */ - RequestOperation["PNCreateDataSyncUserOperation"] = "PNCreateDataSyncUserOperation"; - /** - * Get user REST API operation. - */ - RequestOperation["PNGetDataSyncUserOperation"] = "PNGetDataSyncUserOperation"; - /** - * Get all users REST API operation. - */ - RequestOperation["PNGetDataSyncUsersOperation"] = "PNGetDataSyncUsersOperation"; - /** - * Set user REST API operation (full replacement via PUT). - */ - RequestOperation["PNSetDataSyncUserOperation"] = "PNSetDataSyncUserOperation"; - /** - * Update user REST API operation (partial update via PATCH). - */ - RequestOperation["PNUpdateDataSyncUserOperation"] = "PNUpdateDataSyncUserOperation"; - /** - * Remove user REST API operation. - */ - RequestOperation["PNRemoveDataSyncUserOperation"] = "PNRemoveDataSyncUserOperation"; - /** - * Create channel REST API operation. - */ - RequestOperation["PNCreateDataSyncChannelOperation"] = "PNCreateDataSyncChannelOperation"; - /** - * Get channel REST API operation. - */ - RequestOperation["PNGetDataSyncChannelOperation"] = "PNGetDataSyncChannelOperation"; - /** - * Get all channels REST API operation. - */ - RequestOperation["PNGetDataSyncChannelsOperation"] = "PNGetDataSyncChannelsOperation"; - /** - * Set channel REST API operation (full replacement via PUT). - */ - RequestOperation["PNSetDataSyncChannelOperation"] = "PNSetDataSyncChannelOperation"; - /** - * Update channel REST API operation (partial update via PATCH). - */ - RequestOperation["PNUpdateDataSyncChannelOperation"] = "PNUpdateDataSyncChannelOperation"; - /** - * Remove channel REST API operation. - */ - RequestOperation["PNRemoveDataSyncChannelOperation"] = "PNRemoveDataSyncChannelOperation"; - /** - * Create membership REST API operation. - */ - RequestOperation["PNCreateDataSyncMembershipOperation"] = "PNCreateDataSyncMembershipOperation"; - /** - * Get membership REST API operation. - */ - RequestOperation["PNGetDataSyncMembershipOperation"] = "PNGetDataSyncMembershipOperation"; - /** - * Get all memberships REST API operation. - */ - RequestOperation["PNGetDataSyncMembershipsOperation"] = "PNGetDataSyncMembershipsOperation"; - /** - * Set membership REST API operation (full replacement via PUT). - */ - RequestOperation["PNSetDataSyncMembershipOperation"] = "PNSetDataSyncMembershipOperation"; - /** - * Update membership REST API operation (partial update via PATCH). - */ - RequestOperation["PNUpdateDataSyncMembershipOperation"] = "PNUpdateDataSyncMembershipOperation"; - /** - * Remove membership REST API operation. - */ - RequestOperation["PNRemoveDataSyncMembershipOperation"] = "PNRemoveDataSyncMembershipOperation"; - // -------------------------------------------------------- - // -------------------- File Upload API ------------------- - // -------------------------------------------------------- - /** - * Fetch list of files sent to the channel REST API operation. - */ - RequestOperation["PNListFilesOperation"] = "PNListFilesOperation"; - /** - * Retrieve file upload URL REST API operation. - */ - RequestOperation["PNGenerateUploadUrlOperation"] = "PNGenerateUploadUrlOperation"; - /** - * Upload file to the channel REST API operation. - */ - RequestOperation["PNPublishFileOperation"] = "PNPublishFileOperation"; - /** - * Publish File Message to the channel REST API operation. - */ - RequestOperation["PNPublishFileMessageOperation"] = "PNPublishFileMessageOperation"; - /** - * Retrieve file download URL REST API operation. - */ - RequestOperation["PNGetFileUrlOperation"] = "PNGetFileUrlOperation"; - /** - * Download file from the channel REST API operation. - */ - RequestOperation["PNDownloadFileOperation"] = "PNDownloadFileOperation"; - /** - * Delete file sent to the channel REST API operation. - */ - RequestOperation["PNDeleteFileOperation"] = "PNDeleteFileOperation"; - // -------------------------------------------------------- - // -------------------- Mobile Push API ------------------- - // -------------------------------------------------------- - /** - * Register channels with device push notifications REST API operation. - */ - RequestOperation["PNAddPushNotificationEnabledChannelsOperation"] = "PNAddPushNotificationEnabledChannelsOperation"; - /** - * Unregister channels with device push notifications REST API operation. - */ - RequestOperation["PNRemovePushNotificationEnabledChannelsOperation"] = "PNRemovePushNotificationEnabledChannelsOperation"; - /** - * Fetch list of channels with enabled push notifications for device REST API operation. - */ - RequestOperation["PNPushNotificationEnabledChannelsOperation"] = "PNPushNotificationEnabledChannelsOperation"; - /** - * Disable push notifications for device REST API operation. - */ - RequestOperation["PNRemoveAllPushNotificationsOperation"] = "PNRemoveAllPushNotificationsOperation"; - // -------------------------------------------------------- - // ------------------ Channel Groups API ------------------ - // -------------------------------------------------------- - /** - * Fetch channels groups list REST API operation. - */ - RequestOperation["PNChannelGroupsOperation"] = "PNChannelGroupsOperation"; - /** - * Remove specified channel group REST API operation. - */ - RequestOperation["PNRemoveGroupOperation"] = "PNRemoveGroupOperation"; - /** - * Fetch list of channels for the specified channel group REST API operation. - */ - RequestOperation["PNChannelsForGroupOperation"] = "PNChannelsForGroupOperation"; - /** - * Add list of channels to the specified channel group REST API operation. - */ - RequestOperation["PNAddChannelsToGroupOperation"] = "PNAddChannelsToGroupOperation"; - /** - * Remove list of channels from the specified channel group REST API operation. - */ - RequestOperation["PNRemoveChannelsFromGroupOperation"] = "PNRemoveChannelsFromGroupOperation"; - // -------------------------------------------------------- - // ----------------------- PAM API ------------------------ - // -------------------------------------------------------- - /** - * Generate authorized token REST API operation. - */ - RequestOperation["PNAccessManagerGrant"] = "PNAccessManagerGrant"; - /** - * Generate authorized token REST API operation. - */ - RequestOperation["PNAccessManagerGrantToken"] = "PNAccessManagerGrantToken"; - RequestOperation["PNAccessManagerAudit"] = "PNAccessManagerAudit"; - /** - * Revoke authorized token REST API operation. - */ - RequestOperation["PNAccessManagerRevokeToken"] = "PNAccessManagerRevokeToken"; - // - // -------------------------------------------------------- - // ---------------- Subscription Utility ------------------ - // -------------------------------------------------------- - /** - * Initial event engine subscription handshake operation. - * - * @internal - */ - RequestOperation["PNHandshakeOperation"] = "PNHandshakeOperation"; - /** - * Event engine subscription loop operation. - * - * @internal - */ - RequestOperation["PNReceiveMessagesOperation"] = "PNReceiveMessagesOperation"; - })(RequestOperation || (RequestOperation = {})); - var RequestOperation$1 = RequestOperation; - - /** - * Subscription Worker transport middleware module. - * - * Middleware optimize subscription feature requests utilizing `Subscription Worker` if available and not disabled - * by user. - * - * @internal - */ - // endregion - /** - * Subscription Worker transport middleware. - */ - class SubscriptionWorkerMiddleware { - constructor(configuration) { - this.configuration = configuration; - /** - * Whether subscription worker has been initialized and ready to handle events. - */ - this.subscriptionWorkerReady = false; - /** - * Map of base64-encoded access tokens to their parsed representations. - */ - this.accessTokensMap = {}; - this.workerEventsQueue = []; - this.callbacks = new Map(); - this.setupSubscriptionWorker(); - } - /** - * Set status emitter from the PubNub client. - * - * @param emitter - Function which should be used to emit events. - */ - set emitStatus(emitter) { - this._emitStatus = emitter; - } - /** - * Update client's `userId`. - * - * @param userId - User ID which will be used by the PubNub client further. - */ - onUserIdChange(userId) { - this.configuration.userId = userId; - this.scheduleEventPost({ - type: 'client-update', - heartbeatInterval: this.configuration.heartbeatInterval, - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - userId: this.configuration.userId, - workerLogLevel: this.configuration.workerLogLevel, - }); - } - /** - * Update presence state associated with `userId`. - * - * @param state - Key-value pair of payloads (states) that should be associated with channels / groups specified as - * keys. - */ - onPresenceStateChange(state) { - this.scheduleEventPost({ - type: 'client-presence-state-update', - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - workerLogLevel: this.configuration.workerLogLevel, - state, - }); - } - /** - * Update client's heartbeat interval change. - * - * @param interval - Interval which should be used by timers for _backup_ heartbeat calls created in `SharedWorker`. - */ - onHeartbeatIntervalChange(interval) { - this.configuration.heartbeatInterval = interval; - this.scheduleEventPost({ - type: 'client-update', - heartbeatInterval: this.configuration.heartbeatInterval, - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - userId: this.configuration.userId, - workerLogLevel: this.configuration.workerLogLevel, - }); - } - /** - * Handle authorization key / token change. - * - * @param [token] - Authorization token which should be used. - */ - onTokenChange(token) { - const updateEvent = { - type: 'client-update', - heartbeatInterval: this.configuration.heartbeatInterval, - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - userId: this.configuration.userId, - workerLogLevel: this.configuration.workerLogLevel, - }; - // Trigger request processing by Service Worker. - this.parsedAccessToken(token) - .then((accessToken) => { - updateEvent.preProcessedToken = accessToken; - updateEvent.accessToken = token; - }) - .then(() => this.scheduleEventPost(updateEvent)); - } - /** - * Disconnect client and terminate ongoing long-poll requests (if needed). - */ - disconnect() { - this.scheduleEventPost({ - type: 'client-disconnect', - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - workerLogLevel: this.configuration.workerLogLevel, - }); - } - /** - * Terminate all ongoing long-poll requests. - */ - terminate() { - this.scheduleEventPost({ - type: 'client-unregister', - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - workerLogLevel: this.configuration.workerLogLevel, - }); - } - makeSendable(req) { - // Use default request flow for non-subscribe / presence leave requests. - if (!req.path.startsWith('/v2/subscribe') && !req.path.endsWith('/heartbeat') && !req.path.endsWith('/leave')) - return this.configuration.transport.makeSendable(req); - this.configuration.logger.debug('SubscriptionWorkerMiddleware', 'Process request with SharedWorker transport.'); - let controller; - const sendRequestEvent = { - type: 'send-request', - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - request: req, - workerLogLevel: this.configuration.workerLogLevel, - }; - if (req.cancellable) { - controller = { - abort: () => { - const cancelRequest = { - type: 'cancel-request', - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - identifier: req.identifier, - workerLogLevel: this.configuration.workerLogLevel, - }; - // Cancel active request with specified identifier. - this.scheduleEventPost(cancelRequest); - }, - }; - } - return [ - new Promise((resolve, reject) => { - // Associate Promise resolution / reject with a request identifier for future usage in - // the `onmessage ` handler block to return results. - this.callbacks.set(req.identifier, { resolve, reject }); - // Trigger request processing by Service Worker. - this.parsedAccessTokenForRequest(req) - .then((accessToken) => (sendRequestEvent.preProcessedToken = accessToken)) - .then(() => this.scheduleEventPost(sendRequestEvent)); - }), - controller, - ]; - } - request(req) { - return req; - } - /** - * Schedule {@link event} publish to the subscription worker. - * - * Subscription worker may not be ready for events processing and this method build queue for the time when worker - * will be ready. - * - * @param event - Event payload for the subscription worker. - * @param outOfOrder - Whether event should be processed first then enqueued queue. - */ - scheduleEventPost(event, outOfOrder = false) { - // Trigger request processing by a subscription worker. - const subscriptionWorker = this.sharedSubscriptionWorker; - if (subscriptionWorker) - subscriptionWorker.port.postMessage(event); - else { - if (outOfOrder) - this.workerEventsQueue.splice(0, 0, event); - else - this.workerEventsQueue.push(event); - } - } - /** - * Dequeue and post events from the queue to the subscription worker. - */ - flushScheduledEvents() { - // Trigger request processing by a subscription worker. - const subscriptionWorker = this.sharedSubscriptionWorker; - if (!subscriptionWorker || this.workerEventsQueue.length === 0) - return; - // Clean up from canceled events. - const outdatedEvents = []; - for (let i = 0; i < this.workerEventsQueue.length; i++) { - const event = this.workerEventsQueue[i]; - // Check whether found request cancel event to search for request send event it cancels. - if (event.type !== 'cancel-request' || i === 0) - continue; - for (let j = 0; j < i; j++) { - const otherEvent = this.workerEventsQueue[j]; - if (otherEvent.type !== 'send-request') - continue; - // Collect outdated events if identifiers match. - if (otherEvent.request.identifier === event.identifier) { - outdatedEvents.push(event, otherEvent); - break; - } - } - } - // Actualizing events queue. - this.workerEventsQueue = this.workerEventsQueue.filter((event) => !outdatedEvents.includes(event)); - this.workerEventsQueue.forEach((event) => subscriptionWorker.port.postMessage(event)); - this.workerEventsQueue = []; - } - /** - * Subscription worker. - * - * @returns Worker which has been registered by the PubNub SDK. - */ - get sharedSubscriptionWorker() { - return this.subscriptionWorkerReady ? this.subscriptionWorker : null; - } - setupSubscriptionWorker() { - if (typeof SharedWorker === 'undefined') - return; - try { - this.subscriptionWorker = new SharedWorker(this.configuration.workerUrl, `/pubnub-${this.configuration.sdkVersion}`); - } - catch (error) { - this.configuration.logger.error('SubscriptionWorkerMiddleware', () => ({ - messageType: 'error', - message: error, - })); - throw error; - } - this.subscriptionWorker.port.start(); - // Register PubNub client within subscription worker. - this.scheduleEventPost({ - type: 'client-register', - clientIdentifier: this.configuration.clientIdentifier, - subscriptionKey: this.configuration.subscriptionKey, - userId: this.configuration.userId, - heartbeatInterval: this.configuration.heartbeatInterval, - workerOfflineClientsCheckInterval: this.configuration.workerOfflineClientsCheckInterval, - workerUnsubscribeOfflineClients: this.configuration.workerUnsubscribeOfflineClients, - workerLogLevel: this.configuration.workerLogLevel, - }, true); - this.subscriptionWorker.port.onmessage = (event) => this.handleWorkerEvent(event); - if (this.shouldAnnounceNewerSharedWorkerVersionAvailability()) - localStorage.setItem('PNSubscriptionSharedWorkerVersion', this.configuration.sdkVersion); - window.addEventListener('storage', (event) => { - if (event.key !== 'PNSubscriptionSharedWorkerVersion' || !event.newValue) - return; - if (this._emitStatus && this.isNewerSharedWorkerVersion(event.newValue)) - this._emitStatus({ error: false, category: StatusCategory$1.PNSharedWorkerUpdatedCategory }); - }); - } - handleWorkerEvent(event) { - const { data } = event; - // Ignoring updates not related to this instance. - if (data.type !== 'shared-worker-ping' && - data.type !== 'shared-worker-connected' && - data.type !== 'shared-worker-console-log' && - data.type !== 'shared-worker-console-dir' && - data.clientIdentifier !== this.configuration.clientIdentifier) - return; - if (data.type === 'shared-worker-connected') { - this.configuration.logger.trace('SharedWorker', 'Ready for events processing.'); - this.subscriptionWorkerReady = true; - this.flushScheduledEvents(); - } - else if (data.type === 'shared-worker-console-log') { - this.configuration.logger.debug('SharedWorker', () => { - if (typeof data.message === 'string' || typeof data.message === 'number' || typeof data.message === 'boolean') { - return { - messageType: 'text', - message: data.message, - }; - } - return data.message; - }); - } - else if (data.type === 'shared-worker-console-dir') { - this.configuration.logger.debug('SharedWorker', () => { - return { - messageType: 'object', - message: data.data, - details: data.message ? data.message : undefined, - }; - }); - } - else if (data.type === 'shared-worker-ping') { - const { subscriptionKey, clientIdentifier } = this.configuration; - this.scheduleEventPost({ - type: 'client-pong', - subscriptionKey, - clientIdentifier, - workerLogLevel: this.configuration.workerLogLevel, - }); - } - else if (data.type === 'request-process-success' || data.type === 'request-process-error') { - if (this.callbacks.has(data.identifier)) { - const { resolve, reject } = this.callbacks.get(data.identifier); - this.callbacks.delete(data.identifier); - if (data.type === 'request-process-success') { - resolve({ - status: data.response.status, - url: data.url, - headers: data.response.headers, - body: data.response.body, - }); - } - else - reject(this.errorFromRequestSendingError(data)); - } - // Handling "backup" heartbeat which doesn't have registered callbacks. - else if (this._emitStatus && data.url.indexOf('/v2/presence') >= 0 && data.url.indexOf('/heartbeat') >= 0) { - if (data.type === 'request-process-success' && this.configuration.announceSuccessfulHeartbeats) { - this._emitStatus({ - statusCode: data.response.status, - error: false, - operation: RequestOperation$1.PNHeartbeatOperation, - category: StatusCategory$1.PNAcknowledgmentCategory, - }); - } - else if (data.type === 'request-process-error' && this.configuration.announceFailedHeartbeats) - this._emitStatus(this.errorFromRequestSendingError(data).toStatus(RequestOperation$1.PNHeartbeatOperation)); - } - } - } - /** - * Get parsed access token object from request. - * - * @param req - Transport request which may contain access token for processing. - * - * @returns Object with stringified access token information and expiration date information. - */ - parsedAccessTokenForRequest(req) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - return this.parsedAccessToken(req.queryParameters ? ((_a = req.queryParameters.auth) !== null && _a !== void 0 ? _a : '') : undefined); - }); - } - /** - * Get parsed access token object. - * - * @param accessToken - Access token for processing. - * - * @returns Object with stringified access token information and expiration date information. - */ - parsedAccessToken(accessToken) { - return __awaiter(this, void 0, void 0, function* () { - if (!accessToken) - return undefined; - else if (this.accessTokensMap[accessToken]) - return this.accessTokensMap[accessToken]; - return this.stringifyAccessToken(accessToken).then(([token, stringifiedToken]) => { - if (!token || !stringifiedToken) - return undefined; - return (this.accessTokensMap = { - [accessToken]: { token: stringifiedToken, expiration: token.timestamp + token.ttl * 60 }, - })[accessToken]; - }); - }); - } - /** - * Stringify access token content. - * - * Stringify information about resources with permissions. - * - * @param tokenString - Base64-encoded access token which should be parsed and stringified. - * - * @returns Tuple with parsed access token and its stringified content hash string. - */ - stringifyAccessToken(tokenString) { - return __awaiter(this, void 0, void 0, function* () { - if (!this.configuration.tokenManager) - return [undefined, undefined]; - const token = this.configuration.tokenManager.parseToken(tokenString); - if (!token) - return [undefined, undefined]; - // Translate permission to short string built from first chars of enabled permission. - const stringifyPermissions = (permission) => Object.entries(permission) - .filter(([_, v]) => v) - .map(([k]) => k[0]) - .sort() - .join(''); - const stringifyResources = (resource) => resource - ? Object.entries(resource) - .sort(([a], [b]) => a.localeCompare(b)) - .map(([type, entries]) => Object.entries(entries || {}) - .sort(([a], [b]) => a.localeCompare(b)) - .map(([name, perms]) => `${type}:${name}=${perms ? stringifyPermissions(perms) : ''}`) - .join(',')) - .join(';') - : ''; - let accessToken = [stringifyResources(token.resources), stringifyResources(token.patterns), token.authorized_uuid] - .filter(Boolean) - .join('|'); - if (typeof crypto !== 'undefined' && crypto.subtle) { - const hash = yield crypto.subtle.digest('SHA-256', new TextEncoder().encode(accessToken)); - accessToken = String.fromCharCode(...Array.from(new Uint8Array(hash))); - } - return [token, typeof btoa !== 'undefined' ? btoa(accessToken) : accessToken]; - }); - } - /** - * Create error from failure received from the `SharedWorker`. - * - * @param sendingError - Request sending error received from the `SharedWorker`. - * - * @returns `PubNubAPIError` instance with request processing failure information. - */ - errorFromRequestSendingError(sendingError) { - let category = StatusCategory$1.PNUnknownCategory; - let message = 'Unknown error'; - // Handle client-side issues (if any). - if (sendingError.error) { - if (sendingError.error.type === 'NETWORK_ISSUE') - category = StatusCategory$1.PNNetworkIssuesCategory; - else if (sendingError.error.type === 'TIMEOUT') - category = StatusCategory$1.PNTimeoutCategory; - else if (sendingError.error.type === 'ABORTED') - category = StatusCategory$1.PNCancelledCategory; - message = `${sendingError.error.message} (${sendingError.identifier})`; - } - // Handle service error response. - else if (sendingError.response) { - const { url, response } = sendingError; - return PubNubAPIError.create({ url, headers: response.headers, body: response.body, status: response.status }, response.body); - } - return new PubNubAPIError(message, category, 0, new Error(message)); - } - /** - * Check whether current subscription `SharedWorker` version should be announced or not. - * - * @returns `true` if local storage is empty (only newer version will add value) or stored version is smaller than - * current. - */ - shouldAnnounceNewerSharedWorkerVersionAvailability() { - const version = localStorage.getItem('PNSubscriptionSharedWorkerVersion'); - if (!version) - return true; - return !this.isNewerSharedWorkerVersion(version); - } - /** - * Check whether current subscription `SharedWorker` version should be announced or not. - * - * @param version - Stored (received on init or event) version of subscription shared worker. - * @returns `true` if provided `version` is newer than current client version. - */ - isNewerSharedWorkerVersion(version) { - const [currentMajor, currentMinor, currentPatch] = this.configuration.sdkVersion.split('.').map(Number); - const [storedMajor, storedMinor, storedPatch] = version.split('.').map(Number); - return storedMajor > currentMajor || storedMinor > currentMinor || storedPatch > currentPatch; - } - } - - /** - * CBOR support module. - * - * @internal - */ - /** - * Re-map CBOR object keys from potentially C buffer strings to actual strings. - * - * @param obj CBOR which should be remapped to stringified keys. - * @param nestingLevel PAM token structure nesting level. - * - * @returns Dictionary with stringified keys. - * - * @internal - */ - function stringifyBufferKeys(obj, nestingLevel = 0) { - const isObject = (value) => typeof value === 'object' && value !== null && value.constructor === Object; - const isString = (value) => typeof value === 'string' || value instanceof String; - const isNumber = (value) => typeof value === 'number' && isFinite(value); - if (!isObject(obj)) - return obj; - const normalizedObject = {}; - Object.keys(obj).forEach((key) => { - const keyIsString = isString(key); - let stringifiedKey = key; - const value = obj[key]; - if (nestingLevel < 2) { - if (keyIsString && key.indexOf(',') >= 0) { - const bytes = key.split(',').map(Number); - stringifiedKey = bytes.reduce((string, byte) => { - return string + String.fromCharCode(byte); - }, ''); - } - else if (isNumber(key) || (keyIsString && !isNaN(Number(key)))) { - stringifiedKey = String.fromCharCode(isNumber(key) ? key : parseInt(key, 10)); - } - } - normalizedObject[stringifiedKey] = isObject(value) ? stringifyBufferKeys(value, nestingLevel + 1) : value; - }); - return normalizedObject; - } - - /** - * {@link PubNub} client configuration module. - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether secured connection should be used by or not. - */ - const USE_SSL = true; - /** - * Whether PubNub client should catch up subscription after network issues. - */ - const RESTORE = true; - /** - * Whether network availability change should be announced with `PNNetworkDownCategory` and - * `PNNetworkUpCategory` state or not. - */ - const AUTO_NETWORK_DETECTION = false; - /** - * Whether messages should be de-duplicated before announcement or not. - */ - const DEDUPE_ON_SUBSCRIBE = false; - /** - * Maximum cache which should be used for message de-duplication functionality. - */ - const DEDUPE_CACHE_SIZE = 100; - /** - * Maximum number of file message publish retries. - */ - const FILE_PUBLISH_RETRY_LIMIT = 5; - /** - * Whether subscription event engine should be used or not. - */ - const ENABLE_EVENT_ENGINE = true; - /** - * Whether configured user presence state should be maintained by the PubNub client or not. - */ - const MAINTAIN_PRESENCE_STATE = true; - /** - * Whether heartbeat should be postponed on successful subscribe response or not. - */ - const USE_SMART_HEARTBEAT = false; - /** - * Whether PubNub client should try to utilize existing TCP connection for new requests or not. - */ - const KEEP_ALIVE$1 = false; - /** - * Whether leave events should be suppressed or not. - */ - const SUPPRESS_LEAVE_EVENTS = false; - /** - * Whether heartbeat request failure should be announced or not. - */ - const ANNOUNCE_HEARTBEAT_FAILURE = true; - /** - * Whether heartbeat request success should be announced or not. - */ - const ANNOUNCE_HEARTBEAT_SUCCESS = false; - /** - * Whether PubNub client instance id should be added to the requests or not. - */ - const USE_INSTANCE_ID = false; - /** - * Whether unique identifier should be added to the request or not. - */ - const USE_REQUEST_ID = true; - /** - * Transactional requests timeout. - */ - const TRANSACTIONAL_REQUEST_TIMEOUT = 15; - /** - * Subscription request timeout. - */ - const SUBSCRIBE_REQUEST_TIMEOUT = 310; - /** - * File upload / download request timeout. - */ - const FILE_REQUEST_TIMEOUT = 300; - /** - * Default user presence timeout. - */ - const PRESENCE_TIMEOUT = 300; - /** - * Maximum user presence timeout. - */ - const PRESENCE_TIMEOUT_MAXIMUM = 320; - /** - * Apply configuration default values. - * - * @param configuration - User-provided configuration. - * - * @internal - */ - const setDefaults$1 = (configuration) => { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; - // Copy configuration. - const configurationCopy = Object.assign({}, configuration); - (_a = configurationCopy.ssl) !== null && _a !== void 0 ? _a : (configurationCopy.ssl = USE_SSL); - (_b = configurationCopy.transactionalRequestTimeout) !== null && _b !== void 0 ? _b : (configurationCopy.transactionalRequestTimeout = TRANSACTIONAL_REQUEST_TIMEOUT); - (_c = configurationCopy.subscribeRequestTimeout) !== null && _c !== void 0 ? _c : (configurationCopy.subscribeRequestTimeout = SUBSCRIBE_REQUEST_TIMEOUT); - (_d = configurationCopy.fileRequestTimeout) !== null && _d !== void 0 ? _d : (configurationCopy.fileRequestTimeout = FILE_REQUEST_TIMEOUT); - (_e = configurationCopy.restore) !== null && _e !== void 0 ? _e : (configurationCopy.restore = RESTORE); - (_f = configurationCopy.useInstanceId) !== null && _f !== void 0 ? _f : (configurationCopy.useInstanceId = USE_INSTANCE_ID); - (_g = configurationCopy.suppressLeaveEvents) !== null && _g !== void 0 ? _g : (configurationCopy.suppressLeaveEvents = SUPPRESS_LEAVE_EVENTS); - (_h = configurationCopy.requestMessageCountThreshold) !== null && _h !== void 0 ? _h : (configurationCopy.requestMessageCountThreshold = DEDUPE_CACHE_SIZE); - (_j = configurationCopy.autoNetworkDetection) !== null && _j !== void 0 ? _j : (configurationCopy.autoNetworkDetection = AUTO_NETWORK_DETECTION); - (_k = configurationCopy.enableEventEngine) !== null && _k !== void 0 ? _k : (configurationCopy.enableEventEngine = ENABLE_EVENT_ENGINE); - (_l = configurationCopy.maintainPresenceState) !== null && _l !== void 0 ? _l : (configurationCopy.maintainPresenceState = MAINTAIN_PRESENCE_STATE); - (_m = configurationCopy.useSmartHeartbeat) !== null && _m !== void 0 ? _m : (configurationCopy.useSmartHeartbeat = USE_SMART_HEARTBEAT); - (_o = configurationCopy.keepAlive) !== null && _o !== void 0 ? _o : (configurationCopy.keepAlive = KEEP_ALIVE$1); - if (configurationCopy.userId && configurationCopy.uuid) - throw new PubNubError("PubNub client configuration error: use only 'userId'"); - (_p = configurationCopy.userId) !== null && _p !== void 0 ? _p : (configurationCopy.userId = configurationCopy.uuid); - if (!configurationCopy.userId) - throw new PubNubError("PubNub client configuration error: 'userId' not set"); - else if (((_q = configurationCopy.userId) === null || _q === void 0 ? void 0 : _q.trim().length) === 0) - throw new PubNubError("PubNub client configuration error: 'userId' is empty"); - // Generate default origin subdomains. - if (!configurationCopy.origin) - configurationCopy.origin = Array.from({ length: 20 }, (_, i) => `ps${i + 1}.pndsn.com`); - const keySet = { - subscribeKey: configurationCopy.subscribeKey, - publishKey: configurationCopy.publishKey, - secretKey: configurationCopy.secretKey, - }; - if (configurationCopy.presenceTimeout !== undefined) { - if (configurationCopy.presenceTimeout > PRESENCE_TIMEOUT_MAXIMUM) { - configurationCopy.presenceTimeout = PRESENCE_TIMEOUT_MAXIMUM; - // eslint-disable-next-line no-console - console.warn('WARNING: Presence timeout is larger than the maximum. Using maximum value: ', PRESENCE_TIMEOUT_MAXIMUM); - } - else if (configurationCopy.presenceTimeout <= 0) { - // eslint-disable-next-line no-console - console.warn('WARNING: Presence timeout should be larger than zero.'); - delete configurationCopy.presenceTimeout; - } - } - if (configurationCopy.presenceTimeout !== undefined) - configurationCopy.heartbeatInterval = configurationCopy.presenceTimeout / 2 - 1; - else - configurationCopy.presenceTimeout = PRESENCE_TIMEOUT; - // Apply extended configuration defaults. - let announceSuccessfulHeartbeats = ANNOUNCE_HEARTBEAT_SUCCESS; - let announceFailedHeartbeats = ANNOUNCE_HEARTBEAT_FAILURE; - let fileUploadPublishRetryLimit = FILE_PUBLISH_RETRY_LIMIT; - let dedupeOnSubscribe = DEDUPE_ON_SUBSCRIBE; - let maximumCacheSize = DEDUPE_CACHE_SIZE; - let useRequestId = USE_REQUEST_ID; - // @ts-expect-error Not documented legacy configuration options. - if (configurationCopy.dedupeOnSubscribe !== undefined && typeof configurationCopy.dedupeOnSubscribe === 'boolean') { - // @ts-expect-error Not documented legacy configuration options. - dedupeOnSubscribe = configurationCopy.dedupeOnSubscribe; - } - // @ts-expect-error Not documented legacy configuration options. - if (configurationCopy.maximumCacheSize !== undefined && typeof configurationCopy.maximumCacheSize === 'number') { - // @ts-expect-error Not documented legacy configuration options. - maximumCacheSize = configurationCopy.maximumCacheSize; - } - // @ts-expect-error Not documented legacy configuration options. - if (configurationCopy.useRequestId !== undefined && typeof configurationCopy.useRequestId === 'boolean') { - // @ts-expect-error Not documented legacy configuration options. - useRequestId = configurationCopy.useRequestId; - } - if ( - // @ts-expect-error Not documented legacy configuration options. - configurationCopy.announceSuccessfulHeartbeats !== undefined && - // @ts-expect-error Not documented legacy configuration options. - typeof configurationCopy.announceSuccessfulHeartbeats === 'boolean') { - // @ts-expect-error Not documented legacy configuration options. - announceSuccessfulHeartbeats = configurationCopy.announceSuccessfulHeartbeats; - } - if ( - // @ts-expect-error Not documented legacy configuration options. - configurationCopy.announceFailedHeartbeats !== undefined && - // @ts-expect-error Not documented legacy configuration options. - typeof configurationCopy.announceFailedHeartbeats === 'boolean') { - // @ts-expect-error Not documented legacy configuration options. - announceFailedHeartbeats = configurationCopy.announceFailedHeartbeats; - } - if ( - // @ts-expect-error Not documented legacy configuration options. - configurationCopy.fileUploadPublishRetryLimit !== undefined && - // @ts-expect-error Not documented legacy configuration options. - typeof configurationCopy.fileUploadPublishRetryLimit === 'number') { - // @ts-expect-error Not documented legacy configuration options. - fileUploadPublishRetryLimit = configurationCopy.fileUploadPublishRetryLimit; - } - return Object.assign(Object.assign({}, configurationCopy), { keySet, - dedupeOnSubscribe, - maximumCacheSize, - useRequestId, - announceSuccessfulHeartbeats, - announceFailedHeartbeats, - fileUploadPublishRetryLimit }); - }; - - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether PubNub client should update its state using browser's reachability events or not. - * - * If the browser fails to detect the network changes from Wi-Fi to LAN and vice versa, or you get - * reconnection issues, set the flag to `false`. This allows the SDK reconnection logic to take over. - */ - const LISTEN_TO_BROWSER_NETWORK_EVENTS = true; - /** - * Whether verbose logging should be enabled for `Subscription` worker to print debug messages or not. - */ - const SUBSCRIPTION_WORKER_LOG_VERBOSITY = false; - /** - * Interval at which Shared Worker should check whether PubNub instances which used it still active or not. - */ - const SUBSCRIPTION_WORKER_OFFLINE_CLIENTS_CHECK_INTERVAL = 10; - /** - * Whether `leave` request should be sent for _offline_ PubNub client or not. - */ - const SUBSCRIPTION_WORKER_UNSUBSCRIBE_OFFLINE_CLIENTS = false; - /** - * Use modern Web Fetch API for network requests by default. - */ - const TRANSPORT = 'fetch'; - /** - * Whether PubNub client should try to utilize existing TCP connection for new requests or not. - */ - const KEEP_ALIVE = true; - /** - * Apply configuration default values. - * - * @param configuration - User-provided configuration. - * - * @internal - */ - const setDefaults = (configuration) => { - var _a, _b, _c, _d, _e, _f; - // Force to disable service workers if the environment doesn't support them. - if (configuration.subscriptionWorkerUrl && typeof SharedWorker === 'undefined') { - configuration.subscriptionWorkerUrl = null; - } - return Object.assign(Object.assign({}, setDefaults$1(configuration)), { - // Set platform-specific options. - listenToBrowserNetworkEvents: (_a = configuration.listenToBrowserNetworkEvents) !== null && _a !== void 0 ? _a : LISTEN_TO_BROWSER_NETWORK_EVENTS, subscriptionWorkerUrl: configuration.subscriptionWorkerUrl, subscriptionWorkerOfflineClientsCheckInterval: (_b = configuration.subscriptionWorkerOfflineClientsCheckInterval) !== null && _b !== void 0 ? _b : SUBSCRIPTION_WORKER_OFFLINE_CLIENTS_CHECK_INTERVAL, subscriptionWorkerUnsubscribeOfflineClients: (_c = configuration.subscriptionWorkerUnsubscribeOfflineClients) !== null && _c !== void 0 ? _c : SUBSCRIPTION_WORKER_UNSUBSCRIBE_OFFLINE_CLIENTS, subscriptionWorkerLogVerbosity: (_d = configuration.subscriptionWorkerLogVerbosity) !== null && _d !== void 0 ? _d : SUBSCRIPTION_WORKER_LOG_VERBOSITY, transport: (_e = configuration.transport) !== null && _e !== void 0 ? _e : TRANSPORT, keepAlive: (_f = configuration.keepAlive) !== null && _f !== void 0 ? _f : KEEP_ALIVE }); - }; - - /** - * Enum with available log levels. - */ - var LogLevel; - (function (LogLevel) { - /** - * Used to notify about every last detail: - * - function calls, - * - full payloads, - * - internal variables, - * - state-machine hops. - */ - LogLevel[LogLevel["Trace"] = 0] = "Trace"; - /** - * Used to notify about broad strokes of your SDK’s logic: - * - inputs/outputs to public methods, - * - network request - * - network response - * - decision branches. - */ - LogLevel[LogLevel["Debug"] = 1] = "Debug"; - /** - * Used to notify summary of what the SDK is doing under the hood: - * - initialized, - * - connected, - * - entity created. - */ - LogLevel[LogLevel["Info"] = 2] = "Info"; - /** - * Used to notify about non-fatal events: - * - deprecations, - * - request retries. - */ - LogLevel[LogLevel["Warn"] = 3] = "Warn"; - /** - * Used to notify about: - * - exceptions, - * - HTTP failures, - * - invalid states. - */ - LogLevel[LogLevel["Error"] = 4] = "Error"; - /** - * Logging disabled. - */ - LogLevel[LogLevel["None"] = 5] = "None"; - })(LogLevel || (LogLevel = {})); - - /** - * Default console-based logger. - * - * **Important:** This logger is always added as part of {@link LoggerManager} instance configuration and can't be - * removed. - * - * @internal - */ - /** - * Custom {@link Logger} implementation to show a message in the native console. - */ - class ConsoleLogger { - /** - * Process a `debug` level message. - * - * @param message - Message which should be handled by custom logger implementation. - */ - debug(message) { - this.log(message); - } - /** - * Process a `error` level message. - * - * @param message - Message which should be handled by custom logger implementation. - */ - error(message) { - this.log(message); - } - /** - * Process an `info` level message. - * - * @param message - Message which should be handled by custom logger implementation. - */ - info(message) { - this.log(message); - } - /** - * Process a `trace` level message. - * - * @param message - Message which should be handled by custom logger implementation. - */ - trace(message) { - this.log(message); - } - /** - * Process an `warn` level message. - * - * @param message - Message which should be handled by custom logger implementation. - */ - warn(message) { - this.log(message); - } - /** - * Stringify logger object. - * - * @returns Serialized logger object. - */ - toString() { - return `ConsoleLogger {}`; - } - /** - * Process log message object. - * - * @param message - Object with information which can be used to identify level and prepare log entry payload. - */ - log(message) { - const logLevelString = LogLevel[message.level]; - const level = logLevelString.toLowerCase(); - console[level === 'trace' ? 'debug' : level](`${message.timestamp.toISOString()} PubNub-${message.pubNubId} ${logLevelString.padEnd(5, ' ')}${message.location ? ` ${message.location}` : ''} ${this.logMessage(message)}`); - } - /** - * Get a pre-formatted log message. - * - * @param message - Log message which should be stringified. - * - * @returns String formatted for log entry in console. - */ - logMessage(message) { - if (message.messageType === 'text') - return message.message; - else if (message.messageType === 'object') - return `${message.details ? `${message.details}\n` : ''}${this.formattedObject(message)}`; - else if (message.messageType === 'network-request') { - const showOnlyBasicInfo = !!message.canceled || !!message.failed; - const headersList = message.minimumLevel === LogLevel.Trace && !showOnlyBasicInfo ? this.formattedHeaders(message) : undefined; - const request = message.message; - const queryString = request.queryParameters && Object.keys(request.queryParameters).length > 0 - ? queryStringFromObject(request.queryParameters) - : undefined; - const url = `${request.origin}${request.path}${queryString ? `?${queryString}` : ''}`; - const formattedBody = !showOnlyBasicInfo ? this.formattedBody(message) : undefined; - let action = 'Sending'; - if (showOnlyBasicInfo) - action = `${!!message.canceled ? 'Canceled' : 'Failed'}${message.details ? ` (${message.details})` : ''}`; - const padding = ((formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.formData) ? 'FormData' : 'Method').length; - return `${action} HTTP request:\n ${this.paddedString('Method', padding)}: ${request.method}\n ${this.paddedString('URL', padding)}: ${url}${headersList ? `\n ${this.paddedString('Headers', padding)}:\n${headersList}` : ''}${(formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.formData) ? `\n ${this.paddedString('FormData', padding)}:\n${formattedBody.formData}` : ''}${(formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.body) ? `\n ${this.paddedString('Body', padding)}:\n${formattedBody.body}` : ''}`; - } - else if (message.messageType === 'network-response') { - const headersList = message.minimumLevel === LogLevel.Trace ? this.formattedHeaders(message) : undefined; - const formattedBody = this.formattedBody(message); - const padding = ((formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.formData) ? 'Headers' : 'Status').length; - const response = message.message; - return `Received HTTP response:\n ${this.paddedString('URL', padding)}: ${response.url}\n ${this.paddedString('Status', padding)}: ${response.status}${message.details ? `\n ${this.paddedString('Details', padding)}: ${message.details}` : ''}${headersList ? `\n ${this.paddedString('Headers', padding)}:\n${headersList}` : ''}${(formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.body) ? `\n ${this.paddedString('Body', padding)}:\n${formattedBody.body}` : ''}`; - } - else if (message.messageType === 'error') { - const formattedStatus = this.formattedErrorStatus(message); - const error = message.message; - return `${error.name}: ${error.message}${formattedStatus ? `\n${formattedStatus}` : ''}`; - } - return ''; - } - /** - * Get a pre-formatted object (dictionary / array). - * - * @param message - Log message which may contain an object for formatting. - * - * @returns String formatted for log entry in console or `undefined` if a log message doesn't have suitable data. - */ - formattedObject(message) { - const stringify = (obj, level = 1, skipIndentOnce = false) => { - const maxIndentReached = level === 10; - const targetIndent = ' '.repeat(level * 2); - const lines = []; - const isIgnored = (key, obj) => { - if (!message.ignoredKeys) - return false; - if (typeof message.ignoredKeys === 'function') - return message.ignoredKeys(key, obj); - return message.ignoredKeys.includes(key); - }; - if (typeof obj === 'string') - lines.push(`${targetIndent}- ${obj}`); - else if (typeof obj === 'number') - lines.push(`${targetIndent}- ${obj}`); - else if (typeof obj === 'boolean') - lines.push(`${targetIndent}- ${obj}`); - else if (obj === null) - lines.push(`${targetIndent}- null`); - else if (obj === undefined) - lines.push(`${targetIndent}- undefined`); - else if (typeof obj === 'function') - lines.push(`${targetIndent}- `); - else if (typeof obj === 'object') { - if (!Array.isArray(obj) && typeof obj.toString === 'function' && obj.toString().indexOf('[object') !== 0) { - lines.push(`${skipIndentOnce ? '' : targetIndent}${obj.toString()}`); - skipIndentOnce = false; - } - else if (Array.isArray(obj)) { - for (const element of obj) { - const indent = skipIndentOnce ? '' : targetIndent; - if (element === null) - lines.push(`${indent}- null`); - else if (element === undefined) - lines.push(`${indent}- undefined`); - else if (typeof element === 'function') - lines.push(`${indent}- `); - else if (typeof element === 'object') { - const isArray = Array.isArray(element); - const entry = maxIndentReached ? '...' : stringify(element, level + 1, !isArray); - lines.push(`${indent}-${isArray && !maxIndentReached ? '\n' : ' '}${entry}`); - } - else - lines.push(`${indent}- ${element}`); - skipIndentOnce = false; - } - } - else { - const object = obj; - const keys = Object.keys(object); - const maxKeyLen = keys.reduce((max, key) => Math.max(max, isIgnored(key, object) ? max : key.length), 0); - for (const key of keys) { - if (isIgnored(key, object)) - continue; - const indent = skipIndentOnce ? '' : targetIndent; - const raw = object[key]; - const paddedKey = key.padEnd(maxKeyLen, ' '); - if (raw === null) - lines.push(`${indent}${paddedKey}: null`); - else if (raw === undefined) - lines.push(`${indent}${paddedKey}: undefined`); - else if (typeof raw === 'function') - lines.push(`${indent}${paddedKey}: `); - else if (typeof raw === 'object') { - const isArray = Array.isArray(raw); - const isEmptyArray = isArray && raw.length === 0; - const isEmptyObject = !isArray && !(raw instanceof String) && Object.keys(raw).length === 0; - const hasToString = !isArray && typeof raw.toString === 'function' && raw.toString().indexOf('[object') !== 0; - const entry = maxIndentReached - ? '...' - : isEmptyArray - ? '[]' - : isEmptyObject - ? '{}' - : stringify(raw, level + 1, hasToString); - lines.push(`${indent}${paddedKey}:${maxIndentReached || hasToString || isEmptyArray || isEmptyObject ? ' ' : '\n'}${entry}`); - } - else - lines.push(`${indent}${paddedKey}: ${raw}`); - skipIndentOnce = false; - } - } - } - return lines.join('\n'); - }; - return stringify(message.message); - } - /** - * Get a pre-formatted headers list. - * - * @param message - Log message which may contain an object with headers to be used for formatting. - * - * @returns String formatted for log entry in console or `undefined` if a log message not related to the network data. - */ - formattedHeaders(message) { - if (!message.message.headers) - return undefined; - const headers = message.message.headers; - const maxHeaderLength = Object.keys(headers).reduce((max, key) => Math.max(max, key.length), 0); - return Object.keys(headers) - .map((key) => ` - ${key.toLowerCase().padEnd(maxHeaderLength, ' ')}: ${headers[key]}`) - .join('\n'); - } - /** - * Get a pre-formatted body. - * - * @param message - Log message which may contain an object with `body` (request or response). - * - * @returns Object with formatted string of form data and / or body for log entry in console or `undefined` if a log - * message not related to the network data. - */ - formattedBody(message) { - var _a; - if (!message.message.headers) - return undefined; - let stringifiedFormData; - let stringifiedBody; - const headers = message.message.headers; - const contentType = (_a = headers['content-type']) !== null && _a !== void 0 ? _a : headers['Content-Type']; - const formData = 'formData' in message.message ? message.message.formData : undefined; - const body = message.message.body; - // The presence of this object means that we are sending `multipart/form-data` (potentially uploading a file). - if (formData) { - const maxFieldLength = formData.reduce((max, { key }) => Math.max(max, key.length), 0); - stringifiedFormData = formData - .map(({ key, value }) => ` - ${key.padEnd(maxFieldLength, ' ')}: ${value}`) - .join('\n'); - } - if (!body) - return { formData: stringifiedFormData }; - if (typeof body === 'string') { - stringifiedBody = ` ${body}`; - } - else if (body instanceof ArrayBuffer || Object.prototype.toString.call(body) === '[object ArrayBuffer]') { - if (contentType && (contentType.indexOf('javascript') !== -1 || contentType.indexOf('json') !== -1)) - stringifiedBody = ` ${ConsoleLogger.decoder.decode(body)}`; - else - stringifiedBody = ` ArrayBuffer { byteLength: ${body.byteLength} }`; - } - else { - stringifiedBody = ` File { name: ${body.name}${body.contentLength ? `, contentLength: ${body.contentLength}` : ''}${body.mimeType ? `, mimeType: ${body.mimeType}` : ''} }`; - } - return { body: stringifiedBody, formData: stringifiedFormData }; - } - /** - * Get a pre-formatted status object. - * - * @param message - Log message which may contain a {@link Status} object. - * - * @returns String formatted for log entry in console or `undefined` if a log message doesn't have {@link Status} - * object. - */ - formattedErrorStatus(message) { - if (!message.message.status) - return undefined; - const status = message.message.status; - const errorData = status.errorData; - let stringifiedErrorData; - if (ConsoleLogger.isError(errorData)) { - stringifiedErrorData = ` ${errorData.name}: ${errorData.message}`; - if (errorData.stack) { - stringifiedErrorData += `\n${errorData.stack - .split('\n') - .map((line) => ` ${line}`) - .join('\n')}`; - } - } - else if (errorData) { - try { - stringifiedErrorData = ` ${JSON.stringify(errorData)}`; - } - catch (_) { - stringifiedErrorData = ` ${errorData}`; - } - } - return ` Category : ${status.category}\n Operation : ${status.operation}\n Status : ${status.statusCode}${stringifiedErrorData ? `\n Error data:\n${stringifiedErrorData}` : ''}`; - } - /** - * Append the required amount of space to provide proper padding. - * - * @param str - Source string which should be appended with necessary number of spaces. - * @param maxLength - Maximum length of the string to which source string should be padded. - * @returns End-padded string. - */ - paddedString(str, maxLength) { - return str.padEnd(maxLength - str.length, ' '); - } - /** - * Check whether passed object is {@link Error} instance. - * - * @param errorData - Object which should be checked. - * - * @returns `true` in case if an object actually {@link Error}. - */ - static isError(errorData) { - if (!errorData) - return false; - return errorData instanceof Error || Object.prototype.toString.call(errorData) === '[object Error]'; - } - } - /** - * Binary data decoder. - */ - ConsoleLogger.decoder = new TextDecoder(); - - /** - * HTTP status codes which represent definitive client-side outcomes and shouldn't be retried. - * - * @internal - */ - const NON_RETRIABLE_STATUS_CODES = [404, 409]; - // -------------------------------------------------------- - // ------------------------ Types ------------------------- - // -------------------------------------------------------- - // region Types - /** - * List of known endpoint groups (by context). - */ - var Endpoint; - (function (Endpoint) { - /** - * Unknown endpoint. - * - * @internal - */ - Endpoint["Unknown"] = "UnknownEndpoint"; - /** - * The endpoints to send messages. - * - * This is related to the following functionality: - * - `publish` - * - `signal` - * - `publish file` - * - `fire` - */ - Endpoint["MessageSend"] = "MessageSendEndpoint"; - /** - * The endpoint for real-time update retrieval. - * - * This is related to the following functionality: - * - `subscribe` - */ - Endpoint["Subscribe"] = "SubscribeEndpoint"; - /** - * The endpoint to access and manage `user_id` presence and fetch channel presence information. - * - * This is related to the following functionality: - * - `get presence state` - * - `set presence state` - * - `here now` - * - `where now` - * - `heartbeat` - */ - Endpoint["Presence"] = "PresenceEndpoint"; - /** - * The endpoint to access and manage files in channel-specific storage. - * - * This is related to the following functionality: - * - `send file` - * - `download file` - * - `list files` - * - `delete file` - */ - Endpoint["Files"] = "FilesEndpoint"; - /** - * The endpoint to access and manage messages for a specific channel(s) in the persistent storage. - * - * This is related to the following functionality: - * - `fetch messages / message actions` - * - `delete messages` - * - `messages count` - */ - Endpoint["MessageStorage"] = "MessageStorageEndpoint"; - /** - * The endpoint to access and manage channel groups. - * - * This is related to the following functionality: - * - `add channels to group` - * - `list channels in group` - * - `remove channels from group` - * - `list channel groups` - */ - Endpoint["ChannelGroups"] = "ChannelGroupsEndpoint"; - /** - * The endpoint to access and manage device registration for channel push notifications. - * - * This is related to the following functionality: - * - `enable channels for push notifications` - * - `list push notification enabled channels` - * - `disable push notifications for channels` - * - `disable push notifications for all channels` - */ - Endpoint["DevicePushNotifications"] = "DevicePushNotificationsEndpoint"; - /** - * The endpoint to access and manage App Context objects. - * - * This is related to the following functionality: - * - `set UUID metadata` - * - `get UUID metadata` - * - `remove UUID metadata` - * - `get all UUID metadata` - * - `set Channel metadata` - * - `get Channel metadata` - * - `remove Channel metadata` - * - `get all Channel metadata` - * - `manage members` - * - `list members` - * - `manage memberships` - * - `list memberships` - */ - Endpoint["AppContext"] = "AppContextEndpoint"; - /** - * The endpoint to access and manage reactions for a specific message. - * - * This is related to the following functionality: - * - `add message action` - * - `get message actions` - * - `remove message action` - */ - Endpoint["MessageReactions"] = "MessageReactionsEndpoint"; - })(Endpoint || (Endpoint = {})); - // endregion - /** - * Failed request retry policy. - */ - class RetryPolicy { - static None() { - return { - shouldRetry(_request, _response, _errorCategory, _attempt, _statusCode) { - return false; - }, - getDelay(_attempt, _response) { - return -1; - }, - validate() { - return true; - }, - }; - } - static LinearRetryPolicy(configuration) { - var _a; - return { - delay: configuration.delay, - maximumRetry: configuration.maximumRetry, - excluded: (_a = configuration.excluded) !== null && _a !== void 0 ? _a : [], - shouldRetry(request, response, error, attempt, statusCode) { - return isRetriableRequest(request, response, error, attempt !== null && attempt !== void 0 ? attempt : 0, this.maximumRetry, this.excluded, statusCode); - }, - getDelay(_, response) { - let delay = -1; - if (response && response.headers['retry-after'] !== undefined) - delay = parseInt(response.headers['retry-after'], 10); - if (delay === -1) - delay = this.delay; - return (delay + Math.random()) * 1000; - }, - validate() { - if (this.delay < 2) - throw new Error('Delay can not be set less than 2 seconds for retry'); - }, - }; - } - static ExponentialRetryPolicy(configuration) { - var _a; - return { - minimumDelay: configuration.minimumDelay, - maximumDelay: configuration.maximumDelay, - maximumRetry: configuration.maximumRetry, - excluded: (_a = configuration.excluded) !== null && _a !== void 0 ? _a : [], - shouldRetry(request, response, error, attempt, statusCode) { - return isRetriableRequest(request, response, error, attempt !== null && attempt !== void 0 ? attempt : 0, this.maximumRetry, this.excluded, statusCode); - }, - getDelay(attempt, response) { - let delay = -1; - if (response && response.headers['retry-after'] !== undefined) - delay = parseInt(response.headers['retry-after'], 10); - if (delay === -1) - delay = Math.min(this.minimumDelay * Math.pow(2, attempt), this.maximumDelay); - return (delay + Math.random()) * 1000; - }, - validate() { - if (this.minimumDelay < 2) - throw new Error('Minimum delay can not be set less than 2 seconds for retry'); - }, - }; - } - } - /** - * Check whether request can be retried or not. - * - * @param req - Request for which retry ability is checked. - * @param res - Service response which should be taken into consideration. - * @param errorCategory - Request processing error category. - * @param retryAttempt - Current retry attempt. - * @param maximumRetry - Maximum retry attempts count according to the retry policy. - * @param excluded - List of endpoints for which retry policy won't be applied. - * @param statusCode - Response HTTP status code (available when request failed with an error and hence there is no - * `res`). - * - * @return `true` if request can be retried. - * - * @internal - */ - const isRetriableRequest = (req, res, errorCategory, retryAttempt, maximumRetry, excluded, statusCode) => { - var _a; - if (errorCategory) { - if (errorCategory === StatusCategory$1.PNCancelledCategory || - errorCategory === StatusCategory$1.PNBadRequestCategory || - errorCategory === StatusCategory$1.PNAccessDeniedCategory) - return false; - } - if (isExcludedRequest(req, excluded)) - return false; - else if (retryAttempt > maximumRetry) - return false; - // Status code is reported separately from the `res` when the request failed with an error. - const status = (_a = res === null || res === void 0 ? void 0 : res.status) !== null && _a !== void 0 ? _a : statusCode; - if (status !== undefined && NON_RETRIABLE_STATUS_CODES.includes(status)) - return false; - return res ? res.status === 429 || res.status >= 500 : true; - }; - /** - * Check whether the provided request is in the list of endpoints for which retry is not allowed or not. - * - * @param req - Request which will be tested. - * @param excluded - List of excluded endpoints configured for retry policy. - * - * @returns `true` if request has been excluded and shouldn't be retried. - * - * @internal - */ - const isExcludedRequest = (req, excluded) => excluded && excluded.length > 0 ? excluded.includes(endpointFromRequest(req)) : false; - /** - * Identify API group from transport request. - * - * @param req - Request for which `path` will be analyzed to identify REST API group. - * - * @returns Endpoint group to which request belongs. - * - * @internal - */ - const endpointFromRequest = (req) => { - let endpoint = Endpoint.Unknown; - if (req.path.startsWith('/v2/subscribe')) - endpoint = Endpoint.Subscribe; - else if (req.path.startsWith('/publish/') || req.path.startsWith('/signal/')) - endpoint = Endpoint.MessageSend; - else if (req.path.startsWith('/v2/presence')) - endpoint = Endpoint.Presence; - else if (req.path.startsWith('/v2/history') || req.path.startsWith('/v3/history')) - endpoint = Endpoint.MessageStorage; - else if (req.path.startsWith('/v1/message-actions/')) - endpoint = Endpoint.MessageReactions; - else if (req.path.startsWith('/v1/channel-registration/')) - endpoint = Endpoint.ChannelGroups; - else if (req.path.startsWith('/v2/objects/')) - endpoint = Endpoint.ChannelGroups; - else if (req.path.startsWith('/v1/push/') || req.path.startsWith('/v2/push/')) - endpoint = Endpoint.DevicePushNotifications; - else if (req.path.startsWith('/v1/files/')) - endpoint = Endpoint.Files; - return endpoint; - }; - - /** - * Logging module manager. - * - * Manager responsible for log requests handling and forwarding to the registered {@link Logger logger} implementations. - */ - class LoggerManager { - /** - * Create and configure loggers' manager. - * - * @param pubNubId - Unique identifier of PubNub instance which will use this logger. - * @param minLogLevel - Minimum messages log level to be logged. - * @param loggers - List of additional loggers which should be used along with user-provided custom loggers. - * - * @internal - */ - constructor(pubNubId, minLogLevel, loggers) { - /** - * Keeping track of previous entry timestamp. - * - * This information will be used to make sure that multiple sequential entries doesn't have same timestamp. Adjustment - * on .001 will be done to make it possible to properly stort entries. - * - * @internal - */ - this.previousEntryTimestamp = 0; - this.pubNubId = pubNubId; - this.minLogLevel = minLogLevel; - this.loggers = loggers; - } - /** - * Get current log level. - * - * @returns Current log level. - * - * @internal - */ - get logLevel() { - return this.minLogLevel; - } - /** - * Process a `trace` level message. - * - * @param location - Call site from which a log message has been sent. - * @param messageFactory - Lazy message factory function or string for a text log message. - * - * @internal - */ - trace(location, messageFactory) { - this.log(LogLevel.Trace, location, messageFactory); - } - /** - * Process a `debug` level message. - * - * @param location - Call site from which a log message has been sent. - * @param messageFactory - Lazy message factory function or string for a text log message. - * - * @internal - */ - debug(location, messageFactory) { - this.log(LogLevel.Debug, location, messageFactory); - } - /** - * Process an `info` level message. - * - * @param location - Call site from which a log message has been sent. - * @param messageFactory - Lazy message factory function or string for a text log message. - * - * @internal - */ - info(location, messageFactory) { - this.log(LogLevel.Info, location, messageFactory); - } - /** - * Process a `warn` level message. - * - * @param location - Call site from which a log message has been sent. - * @param messageFactory - Lazy message factory function or string for a text log message. - * - * @internal - */ - warn(location, messageFactory) { - this.log(LogLevel.Warn, location, messageFactory); - } - /** - * Process an `error` level message. - * - * @param location - Call site from which a log message has been sent. - * @param messageFactory - Lazy message factory function or string for a text log message. - * - * @internal - */ - error(location, messageFactory) { - this.log(LogLevel.Error, location, messageFactory); - } - /** - * Process log message. - * - * @param logLevel - Logged message level. - * @param location - Call site from which a log message has been sent. - * @param messageFactory - Lazy message factory function or string for a text log message. - * - * @internal - */ - log(logLevel, location, messageFactory) { - // Check whether a log message should be handled at all or not. - if (logLevel < this.minLogLevel || this.loggers.length === 0) - return; - const date = new Date(); - if (date.getTime() <= this.previousEntryTimestamp) { - this.previousEntryTimestamp++; - date.setTime(this.previousEntryTimestamp); - } - else - this.previousEntryTimestamp = date.getTime(); - const level = LogLevel[logLevel].toLowerCase(); - const message = Object.assign({ timestamp: date, pubNubId: this.pubNubId, level: logLevel, minimumLevel: this.minLogLevel, location }, (typeof messageFactory === 'function' ? messageFactory() : { messageType: 'text', message: messageFactory })); - this.loggers.forEach((logger) => logger[level](message)); - } - } - - var uuid = {exports: {}}; - - /*! lil-uuid - v0.1 - MIT License - https://github.com/lil-js/uuid */ - uuid.exports; - - (function (module, exports) { - (function (root, factory) { - { - factory(exports); - if (module !== null) { - module.exports = exports.uuid; - } - } - }(commonjsGlobal, function (exports) { - var VERSION = '0.1.0'; - var uuidRegex = { - '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, - '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, - '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, - all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i - }; - - function uuid() { - var uuid = '', i, random; - for (i = 0; i < 32; i++) { - random = Math.random() * 16 | 0; - if (i === 8 || i === 12 || i === 16 || i === 20) uuid += '-'; - uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random)).toString(16); - } - return uuid - } - - function isUUID(str, version) { - var pattern = uuidRegex[version || 'all']; - return pattern && pattern.test(str) || false - } - - uuid.isUUID = isUUID; - uuid.VERSION = VERSION; - - exports.uuid = uuid; - exports.isUUID = isUUID; - })); - } (uuid, uuid.exports)); - - var uuidExports = uuid.exports; - var uuidGenerator$1 = /*@__PURE__*/getDefaultExportFromCjs(uuidExports); - - /** - * Random identifier generator helper module. - * - * @internal - */ - /** @internal */ - var uuidGenerator = { - createUUID() { - if (uuidGenerator$1.uuid) { - return uuidGenerator$1.uuid(); - } - // @ts-expect-error Depending on module type it may be callable. - return uuidGenerator$1(); - }, - }; - - /** - * {@link PubNub} client configuration module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether encryption (if set) should use random initialization vector or not. - * - * @internal - */ - const USE_RANDOM_INITIALIZATION_VECTOR = true; - /** - * Create {@link PubNub} client private configuration object. - * - * @param base - User- and platform-provided configuration. - * @param setupCryptoModule - Platform-provided {@link ICryptoModule} configuration block. - * - * @returns `PubNub` client private configuration. - * - * @internal - */ - const makeConfiguration = (base, setupCryptoModule) => { - var _a, _b, _c, _d; - // Set the default retry policy for subscribing (if new subscribe logic not used). - if (!base.retryConfiguration && base.enableEventEngine) { - base.retryConfiguration = RetryPolicy.ExponentialRetryPolicy({ - minimumDelay: 2, - maximumDelay: 150, - maximumRetry: 6, - excluded: [ - Endpoint.MessageSend, - Endpoint.Presence, - Endpoint.Files, - Endpoint.MessageStorage, - Endpoint.ChannelGroups, - Endpoint.DevicePushNotifications, - Endpoint.AppContext, - Endpoint.MessageReactions, - ], - }); - } - const instanceId = `pn-${uuidGenerator.createUUID()}`; - if (base.logVerbosity) - base.logLevel = LogLevel.Debug; - else if (base.logLevel === undefined) - base.logLevel = LogLevel.None; - // Prepare loggers manager. - const loggerManager = new LoggerManager(hashFromString(instanceId), base.logLevel, [ - ...((_a = base.loggers) !== null && _a !== void 0 ? _a : []), - new ConsoleLogger(), - ]); - if (base.logVerbosity !== undefined) - loggerManager.warn('Configuration', "'logVerbosity' is deprecated. Use 'logLevel' instead."); - // Ensure that retry policy has proper configuration (if has been set). - (_b = base.retryConfiguration) === null || _b === void 0 ? void 0 : _b.validate(); - const explicitUseRandomIVs = base.useRandomIVs; - (_c = base.useRandomIVs) !== null && _c !== void 0 ? _c : (base.useRandomIVs = USE_RANDOM_INITIALIZATION_VECTOR); - if (explicitUseRandomIVs !== undefined) { - loggerManager.warn('Configuration', "'useRandomIVs' is deprecated. Pass it to 'cryptoModule' instead."); - if (explicitUseRandomIVs === false) { - loggerManager.warn('Configuration', `Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients. - Do not disable random IVs in new applications.`); - } - } - // Override origin value. - base.origin = standardOrigin((_d = base.ssl) !== null && _d !== void 0 ? _d : false, base.origin); - const cryptoModule = base.cryptoModule; - if (cryptoModule) - delete base.cryptoModule; - const clientConfiguration = Object.assign(Object.assign({}, base), { _pnsdkSuffix: {}, _loggerManager: loggerManager, _instanceId: instanceId, _cryptoModule: undefined, _cipherKey: undefined, _setupCryptoModule: setupCryptoModule, get instanceId() { - if (base.useInstanceId) - return this._instanceId; - return undefined; - }, - getInstanceId() { - if (base.useInstanceId) - return this._instanceId; - return undefined; - }, - getUserId() { - return this.userId; - }, - setUserId(value) { - if (!value || typeof value !== 'string' || value.trim().length === 0) - throw new Error('Missing or invalid userId parameter. Provide a valid string userId'); - this.userId = value; - }, - logger() { - return this._loggerManager; - }, - getAuthKey() { - return this.authKey; - }, - setAuthKey(authKey) { - this.authKey = authKey; - }, - getFilterExpression() { - return this.filterExpression; - }, - setFilterExpression(expression) { - this.filterExpression = expression; - }, - getCipherKey() { - return this._cipherKey; - }, - setCipherKey(key) { - this._cipherKey = key; - if (!key && this._cryptoModule) { - this._cryptoModule = undefined; - return; - } - else if (!key || !this._setupCryptoModule) - return; - this._cryptoModule = this._setupCryptoModule({ - cipherKey: key, - useRandomIVs: base.useRandomIVs, - customEncrypt: this.getCustomEncrypt(), - customDecrypt: this.getCustomDecrypt(), - logger: this.logger(), - }); - }, - getCryptoModule() { - return this._cryptoModule; - }, - getUseRandomIVs() { - return base.useRandomIVs; - }, - isSharedWorkerEnabled() { - // @ts-expect-error: Access field from web-based SDK configuration. - return base.sdkFamily === 'Web' && base['subscriptionWorkerUrl']; - }, - getKeepPresenceChannelsInPresenceRequests() { - // @ts-expect-error: Access field from web-based SDK configuration. - return base.sdkFamily === 'Web' && base['subscriptionWorkerUrl']; - }, - setPresenceTimeout(value) { - this.heartbeatInterval = value / 2 - 1; - this.presenceTimeout = value; - }, - getPresenceTimeout() { - return this.presenceTimeout; - }, - getHeartbeatInterval() { - return this.heartbeatInterval; - }, - setHeartbeatInterval(interval) { - this.heartbeatInterval = interval; - }, - getTransactionTimeout() { - return this.transactionalRequestTimeout; - }, - getSubscribeTimeout() { - return this.subscribeRequestTimeout; - }, - getFileTimeout() { - return this.fileRequestTimeout; - }, - get PubNubFile() { - return base.PubNubFile; - }, - get version() { - return '13.1.2'; - }, - getVersion() { - return this.version; - }, - _addPnsdkSuffix(name, suffix) { - this._pnsdkSuffix[name] = `${suffix}`; - }, - _getPnsdkSuffix(separator) { - const sdk = Object.values(this._pnsdkSuffix).join(separator); - return sdk.length > 0 ? separator + sdk : ''; - }, - // -------------------------------------------------------- - // ---------------------- Deprecated ---------------------- - // -------------------------------------------------------- - // region Deprecated - getUUID() { - return this.getUserId(); - }, - setUUID(value) { - this.setUserId(value); - }, - getCustomEncrypt() { - return base.customEncrypt; - }, - getCustomDecrypt() { - return base.customDecrypt; - } }); - // Setup `CryptoModule` if possible. - if (base.cipherKey) { - loggerManager.warn('Configuration', "'cipherKey' is deprecated. Use 'cryptoModule' instead."); - clientConfiguration.setCipherKey(base.cipherKey); - } - else if (cryptoModule) - clientConfiguration._cryptoModule = cryptoModule; - return clientConfiguration; - }; - /** - * Decide {@lin PubNub} service REST API origin. - * - * @param secure - Whether preferred to use secured connection or not. - * @param origin - User-provided or default origin. - * - * @returns `PubNub` REST API endpoints origin. - */ - const standardOrigin = (secure, origin) => { - const protocol = secure ? 'https://' : 'http://'; - if (typeof origin === 'string') - return `${protocol}${origin}`; - return `${protocol}${origin[Math.floor(Math.random() * origin.length)]}`; - }; - /** - * Compute 32bit hash string from source value. - * - * @param value - String from which hash string should be computed. - * - * @returns Computed hash. - */ - const hashFromString = (value) => { - let basis = 0x811c9dc5; - for (let i = 0; i < value.length; i++) { - basis ^= value.charCodeAt(i); - basis = (basis + ((basis << 1) + (basis << 4) + (basis << 7) + (basis << 8) + (basis << 24))) >>> 0; - } - return basis.toString(16).padStart(8, '0'); - }; - - /** - * PubNub Access Token Manager module. - * - * @internal - */ - // endregion - /** - * REST API access token manager. - * - * Manager maintains active access token and let parse it to get information about permissions. - * - * @internal - */ - class TokenManager { - constructor(cbor) { - this.cbor = cbor; - } - /** - * Update REST API access token. - * - * **Note:** Token will be applied only for next requests and won't affect ongoing requests. - * - * @param [token] - Access token which should be used to access PubNub REST API. - */ - setToken(token) { - if (token && token.length > 0) - this.token = token; - else - this.token = undefined; - } - /** - * REST API access token. - * - * @returns Previously configured REST API access token. - */ - getToken() { - return this.token; - } - /** - * Parse Base64-encoded access token. - * - * @param tokenString - Base64-encoded access token. - * - * @returns Information about resources and permissions which has been granted for them. - */ - parseToken(tokenString) { - var _a, _b; - const parsed = this.cbor.decodeToken(tokenString); - if (parsed !== undefined) { - const uuidResourcePermissions = parsed.res.uuid ? Object.keys(parsed.res.uuid) : []; - const userResourcePermissions = parsed.res.usr ? Object.keys(parsed.res.usr) : []; - const channelResourcePermissions = Object.keys(parsed.res.chan); - const groupResourcePermissions = Object.keys(parsed.res.grp); - const uuidPatternPermissions = parsed.pat.uuid ? Object.keys(parsed.pat.uuid) : []; - const userPatternPermissions = parsed.pat.usr ? Object.keys(parsed.pat.usr) : []; - const channelPatternPermissions = Object.keys(parsed.pat.chan); - const groupPatternPermissions = Object.keys(parsed.pat.grp); - const result = { - version: parsed.v, - timestamp: parsed.t, - ttl: parsed.ttl, - authorized_uuid: parsed.uuid, - signature: parsed.sig, - }; - const uuidResources = uuidResourcePermissions.length > 0; - const userResources = userResourcePermissions.length > 0; - const channelResources = channelResourcePermissions.length > 0; - const groupResources = groupResourcePermissions.length > 0; - if (uuidResources || userResources || channelResources || groupResources) { - result.resources = {}; - if (uuidResources) { - const uuids = (result.resources.uuids = {}); - uuidResourcePermissions.forEach((id) => (uuids[id] = this.extractPermissions(parsed.res.uuid[id]))); - } - if (userResources) { - const users = (result.resources.users = {}); - userResourcePermissions.forEach((id) => (users[id] = this.extractCrudPermissions(parsed.res.usr[id]))); - } - if (channelResources) { - const channels = (result.resources.channels = {}); - channelResourcePermissions.forEach((id) => (channels[id] = this.extractPermissions(parsed.res.chan[id]))); - } - if (groupResources) { - const groups = (result.resources.groups = {}); - groupResourcePermissions.forEach((id) => (groups[id] = this.extractPermissions(parsed.res.grp[id]))); - } - } - const resourceDataSync = this.extractDataSyncScopes(parsed.res); - if (resourceDataSync) - ((_a = result.resources) !== null && _a !== void 0 ? _a : (result.resources = {})).dataSync = resourceDataSync; - const uuidPatterns = uuidPatternPermissions.length > 0; - const userPatterns = userPatternPermissions.length > 0; - const channelPatterns = channelPatternPermissions.length > 0; - const groupPatterns = groupPatternPermissions.length > 0; - if (uuidPatterns || userPatterns || channelPatterns || groupPatterns) { - result.patterns = {}; - if (uuidPatterns) { - const uuids = (result.patterns.uuids = {}); - uuidPatternPermissions.forEach((id) => (uuids[id] = this.extractPermissions(parsed.pat.uuid[id]))); - } - if (userPatterns) { - const users = (result.patterns.users = {}); - userPatternPermissions.forEach((id) => (users[id] = this.extractCrudPermissions(parsed.pat.usr[id]))); - } - if (channelPatterns) { - const channels = (result.patterns.channels = {}); - channelPatternPermissions.forEach((id) => (channels[id] = this.extractPermissions(parsed.pat.chan[id]))); - } - if (groupPatterns) { - const groups = (result.patterns.groups = {}); - groupPatternPermissions.forEach((id) => (groups[id] = this.extractPermissions(parsed.pat.grp[id]))); - } - } - const patternDataSync = this.extractDataSyncScopes(parsed.pat); - if (patternDataSync) - ((_b = result.patterns) !== null && _b !== void 0 ? _b : (result.patterns = {})).dataSync = patternDataSync; - const categories = this.extractCategories(parsed.cat); - if (categories) - result.categories = categories; - if (parsed.meta && Object.keys(parsed.meta).length > 0) - result.meta = parsed.meta; - return result; - } - return undefined; - } - /** - * Extract resource access permission information. - * - * @param permissions - Bit-encoded resource permissions. - * - * @returns Human-readable resource permissions. - */ - extractPermissions(permissions) { - const permissionsResult = { - read: false, - write: false, - manage: false, - delete: false, - get: false, - update: false, - join: false, - }; - if ((permissions & 128) === 128) - permissionsResult.join = true; - if ((permissions & 64) === 64) - permissionsResult.update = true; - if ((permissions & 32) === 32) - permissionsResult.get = true; - if ((permissions & 8) === 8) - permissionsResult.delete = true; - if ((permissions & 4) === 4) - permissionsResult.manage = true; - if ((permissions & 2) === 2) - permissionsResult.write = true; - if ((permissions & 1) === 1) - permissionsResult.read = true; - return permissionsResult; - } - /** - * Extract category-level permissions from the token `cat` section. - * - * `chan` maps to `channels` and `uuid` maps to `uuids`. `get` is set from the `32` bit. The - * section is omitted when `cat` is absent or empty. - * - * @param cat - Raw `cat` section decoded from the token. - * - * @returns Human-readable category permissions, or `undefined` when none are present. - */ - extractCategories(cat) { - if (!cat) - return undefined; - const result = {}; - if (typeof cat.chan === 'number') - result.channels = { get: (cat.chan & 32) === 32 }; - if (typeof cat.uuid === 'number') - result.uuids = { get: (cat.uuid & 32) === 32 }; - return Object.keys(result).length > 0 ? result : undefined; - } - /** - * Extract DataSync permission scopes from a token permissions section. - * - * The `datasync:*` wire keys are only present for tokens which granted DataSync permissions, so a - * result is returned only when at least one scope carries permissions. - * - * @param section - Raw `res` or `pat` permissions section decoded from the token. - * - * @returns Human-readable DataSync permission scopes, or `undefined` when none are granted. - */ - extractDataSyncScopes(section) { - const dataSyncScopes = [ - ['entities', 'datasync:entities'], - ['relationships', 'datasync:relationships'], - ['memberships', 'datasync:memberships'], - ]; - let result; - dataSyncScopes.forEach(([scope, wireKey]) => { - const permissions = section[wireKey]; - if (!permissions) - return; - const ids = Object.keys(permissions); - if (ids.length === 0) - return; - const scopeResult = ((result !== null && result !== void 0 ? result : (result = {}))[scope] = {}); - ids.forEach((id) => (scopeResult[id] = this.extractCrudPermissions(permissions[id]))); - }); - return result; - } - /** - * Extract CRUD-only access permission information. - * - * Shared by the `usr` wire key (which backs the `users` grant scope) and the `datasync:*` wire - * keys — both carry the same CRUD bit layout and none of the `read` / `write` / `manage` / `join` - * bits decoded by {@link extractPermissions}. - * - * @param permissions - Bit-encoded resource permissions. - * - * @returns Human-readable CRUD resource permissions. - */ - extractCrudPermissions(permissions) { - return { - create: (permissions & 16) === 16, - get: (permissions & 32) === 32, - update: (permissions & 64) === 64, - delete: (permissions & 8) === 8, - }; - } - } - - /** - * Enum representing possible transport methods for HTTP requests. - * - * @enum {number} - */ - var TransportMethod; - (function (TransportMethod) { - /** - * Request will be sent using `GET` method. - */ - TransportMethod["GET"] = "GET"; - /** - * Request will be sent using `POST` method. - */ - TransportMethod["POST"] = "POST"; - /** - * Request will be sent using `PATCH` method. - */ - TransportMethod["PATCH"] = "PATCH"; - /** - * Request will be sent using `PUT` method. - */ - TransportMethod["PUT"] = "PUT"; - /** - * Request will be sent using `DELETE` method. - */ - TransportMethod["DELETE"] = "DELETE"; - /** - * Local request. - * - * Request won't be sent to the service and probably used to compute URL. - */ - TransportMethod["LOCAL"] = "LOCAL"; - })(TransportMethod || (TransportMethod = {})); - - /** - * Common PubNub Network Provider middleware module. - * - * @internal - */ - /** - * Request signature generator. - * - * @internal - */ - class RequestSignature { - constructor(publishKey, secretKey, hasher, logger) { - this.publishKey = publishKey; - this.secretKey = secretKey; - this.hasher = hasher; - this.logger = logger; - } - /** - * Compute request signature. - * - * @param req - Request which will be used to compute signature. - * @returns {string} `v2` request signature. - */ - signature(req) { - const method = req.path.startsWith('/publish') ? TransportMethod.GET : req.method; - let signatureInput = `${method}\n${this.publishKey}\n${req.path}\n${this.queryParameters(req.queryParameters)}\n`; - if (method === TransportMethod.POST || method === TransportMethod.PATCH || method === TransportMethod.PUT) { - const body = req.body; - let payload; - if (body && body instanceof ArrayBuffer) { - payload = RequestSignature.textDecoder.decode(body); - } - else if (body && typeof body !== 'object') { - payload = body; - } - if (payload) - signatureInput += payload; - } - this.logger.trace('RequestSignature', () => ({ - messageType: 'text', - message: `Request signature input:\n${signatureInput}`, - })); - return `v2.${this.hasher(signatureInput, this.secretKey)}` - .replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/=+$/, ''); - } - /** - * Prepare request query parameters for signature. - * - * @param query - Key / value pair of the request query parameters. - * @private - */ - queryParameters(query) { - return Object.keys(query) - .sort() - .map((key) => { - const queryValue = query[key]; - if (!Array.isArray(queryValue)) - return `${key}=${encodeString(queryValue)}`; - return queryValue - .sort() - .map((value) => `${key}=${encodeString(value)}`) - .join('&'); - }) - .join('&'); - } - } - RequestSignature.textDecoder = new TextDecoder('utf-8'); - /** - * Common PubNub Network Provider middleware. - * - * @internal - */ - class PubNubMiddleware { - constructor(configuration) { - this.configuration = configuration; - const { clientConfiguration: { keySet }, shaHMAC, } = configuration; - { - if (keySet.secretKey && shaHMAC) - this.signatureGenerator = new RequestSignature(keySet.publishKey, keySet.secretKey, shaHMAC, this.logger); - } - } - /** - * Retrieve registered loggers' manager. - * - * @returns Registered loggers' manager. - */ - get logger() { - return this.configuration.clientConfiguration.logger(); - } - makeSendable(req) { - const retryPolicy = this.configuration.clientConfiguration.retryConfiguration; - const transport = this.configuration.transport; - // Make requests retryable. - if (retryPolicy !== undefined) { - let retryTimeout; - let activeCancellation; - let canceled = false; - let attempt = 0; - const cancellation = { - abort: (reason) => { - canceled = true; - if (retryTimeout) - clearTimeout(retryTimeout); - if (activeCancellation) - activeCancellation.abort(reason); - }, - }; - const retryableRequest = new Promise((resolve, reject) => { - const trySendRequest = () => { - // Check whether the request already has been canceled and there is no retry should proceed. - if (canceled) - return; - const [attemptPromise, attemptCancellation] = transport.makeSendable(this.request(req)); - activeCancellation = attemptCancellation; - const responseHandler = (res, error) => { - let delay = -1; - // Retry ability (error category, HTTP status code, excluded endpoints and attempts count) is entirely - // decided by the retry policy. - if (retryPolicy.shouldRetry(req, res, error === null || error === void 0 ? void 0 : error.category, attempt + 1, error === null || error === void 0 ? void 0 : error.statusCode)) - delay = retryPolicy.getDelay(attempt, res); - if (delay > 0) { - attempt++; - this.logger.warn('PubNubMiddleware', `HTTP request retry #${attempt} in ${delay}ms.`); - retryTimeout = setTimeout(() => trySendRequest(), delay); - } - else { - if (res) - resolve(res); - else if (error) - reject(error); - } - }; - attemptPromise - .then((res) => responseHandler(res)) - .catch((err) => responseHandler(undefined, err)); - }; - trySendRequest(); - }); - return [retryableRequest, activeCancellation ? cancellation : undefined]; - } - return transport.makeSendable(this.request(req)); - } - request(req) { - var _a; - const { clientConfiguration } = this.configuration; - // Get request patched by transport provider. - req = this.configuration.transport.request(req); - if (!req.queryParameters) - req.queryParameters = {}; - // Modify the request with required information. - if (clientConfiguration.useInstanceId) - req.queryParameters['instanceid'] = clientConfiguration.getInstanceId(); - if (!req.queryParameters['uuid']) - req.queryParameters['uuid'] = clientConfiguration.userId; - if (clientConfiguration.useRequestId) - req.queryParameters['requestid'] = req.identifier; - req.queryParameters['pnsdk'] = this.generatePNSDK(); - (_a = req.origin) !== null && _a !== void 0 ? _a : (req.origin = clientConfiguration.origin); - // Authenticate request if required. - this.authenticateRequest(req); - // Sign request if it is required. - this.signRequest(req); - return req; - } - authenticateRequest(req) { - var _a; - // Access management endpoints don't need authentication (signature required instead). - if (req.path.startsWith('/v2/auth/') || req.path.startsWith('/v3/pam/') || req.path.startsWith('/time')) - return; - const { clientConfiguration, tokenManager } = this.configuration; - const accessKey = (_a = (tokenManager && tokenManager.getToken())) !== null && _a !== void 0 ? _a : clientConfiguration.authKey; - if (accessKey) - req.queryParameters['auth'] = accessKey; - } - /** - * Compute and append request signature. - * - * @param req - Transport request with information which should be used to generate signature. - */ - signRequest(req) { - if (!this.signatureGenerator || req.path.startsWith('/time')) - return; - req.queryParameters['timestamp'] = String(Math.floor(new Date().getTime() / 1000)); - req.queryParameters['signature'] = this.signatureGenerator.signature(req); - } - /** - * Compose `pnsdk` query parameter. - * - * SDK provides ability to set custom name or append vendor information to the `pnsdk` query - * parameter. - * - * @returns Finalized `pnsdk` query parameter value. - */ - generatePNSDK() { - const { clientConfiguration } = this.configuration; - if (clientConfiguration.sdkName) - return clientConfiguration.sdkName; - let base = `PubNub-JS-${clientConfiguration.sdkFamily}`; - if (clientConfiguration.partnerId) - base += `-${clientConfiguration.partnerId}`; - base += `/${clientConfiguration.getVersion()}`; - const pnsdkSuffix = clientConfiguration._getPnsdkSuffix(' '); - if (pnsdkSuffix.length > 0) - base += pnsdkSuffix; - return base; - } - } - - /** - * Common browser and React Native Transport provider module. - * - * @internal - */ - /** - * Class representing a `fetch`-based browser and React Native transport provider. - * - * @internal - */ - class WebTransport { - /** - * Create and configure transport provider for Web and Rect environments. - * - * @param logger - Registered loggers' manager. - * @param [transport] - API, which should be used to make network requests. - * - * @internal - */ - constructor(logger, transport = 'fetch') { - this.logger = logger; - this.transport = transport; - logger.debug('WebTransport', `Create with configuration:\n - transport: ${transport}`); - // Check for `fetch` availability directly (works in DOM and DOM-less contexts such as service workers). - // because a bare `window` reference would throw in a service worker, and a partial `window = self` shim can - // define `window` without `fetch`, so probe the actual `fetch` global via `typeof`. - if (transport === 'fetch' && typeof fetch === 'undefined') { - logger.warn('WebTransport', `'${transport}' not supported in this browser. Fallback to the 'xhr' transport.`); - this.transport = 'xhr'; - } - if (this.transport !== 'fetch') - return; - // Storing reference on original `fetch` function implementation as protection against APM lib monkey patching. - // - // This is done unconditionally (not gated on `isFetchMonkeyPatched()`): APM libraries can defeat that - // detection by overriding stringification to report `[native code]` while still patching `fetch`, so we - // cannot rely on it to decide whether the workaround is needed. `getOriginalFetch()` itself decides how to - // obtain the reference based on the environment (iframe when a DOM is available, context `fetch` otherwise), - // which keeps construction safe in DOM-less contexts such as MV3 service workers. - WebTransport.originalFetch = WebTransport.getOriginalFetch(); - // Check whether `fetch` has been monkey patched or not. - if (this.isFetchMonkeyPatched()) - logger.warn('WebTransport', "Native Web Fetch API 'fetch' function monkey patched."); - } - makeSendable(req) { - const abortController = new AbortController(); - const cancellation = { - abortController, - abort: (reason) => { - if (!abortController.signal.aborted) { - this.logger.trace('WebTransport', `On-demand request aborting: ${reason}`); - abortController.abort(reason); - } - }, - }; - return [ - this.webTransportRequestFromTransportRequest(req).then((request) => { - this.logger.debug('WebTransport', () => ({ messageType: 'network-request', message: req })); - return this.sendRequest(request, cancellation) - .then((response) => response.arrayBuffer().then((arrayBuffer) => [response, arrayBuffer])) - .then((response) => { - const body = response[1].byteLength > 0 ? response[1] : undefined; - const { status, headers: requestHeaders } = response[0]; - const headers = {}; - // Copy Headers object content into plain Record. - requestHeaders.forEach((value, key) => (headers[key] = value.toLowerCase())); - const transportResponse = { status, url: request.url, headers, body }; - this.logger.debug('WebTransport', () => ({ - messageType: 'network-response', - message: transportResponse, - })); - if (status >= 400) - throw PubNubAPIError.create(transportResponse); - return transportResponse; - }) - .catch((error) => { - const errorMessage = (typeof error === 'string' ? error : error.message).toLowerCase(); - let fetchError = typeof error === 'string' ? new Error(error) : error; - if (errorMessage.includes('timeout')) { - this.logger.warn('WebTransport', () => ({ - messageType: 'network-request', - message: req, - details: 'Timeout', - canceled: true, - })); - } - else if (errorMessage.includes('cancel') || errorMessage.includes('abort')) { - this.logger.debug('WebTransport', () => ({ - messageType: 'network-request', - message: req, - details: 'Aborted', - canceled: true, - })); - fetchError = new Error('Aborted'); - fetchError.name = 'AbortError'; - } - else if (errorMessage.includes('network')) { - this.logger.warn('WebTransport', () => ({ - messageType: 'network-request', - message: req, - details: 'Network error', - failed: true, - })); - } - else { - this.logger.warn('WebTransport', () => ({ - messageType: 'network-request', - message: req, - details: PubNubAPIError.create(fetchError).message, - failed: true, - })); - } - throw PubNubAPIError.create(fetchError); - }); - }), - cancellation, - ]; - } - request(req) { - return req; - } - /** - * Send network request using preferred API. - * - * @param req - Transport API agnostic request object with prepared body and URL. - * @param controller - Request cancellation controller (for long-poll requests). - * - * @returns Promise which will be resolved or rejected at the end of network request processing. - * - * @internal - */ - sendRequest(req, controller) { - return __awaiter(this, void 0, void 0, function* () { - if (this.transport === 'fetch') - return this.sendFetchRequest(req, controller); - return this.sendXHRRequest(req, controller); - }); - } - /** - * Send network request using legacy XMLHttpRequest API. - * - * @param req - Transport API agnostic request object with prepared body and URL. - * @param controller - Request cancellation controller (for long-poll requests). - * - * @returns Promise which will be resolved or rejected at the end of network request processing. - * - * @internal - */ - sendFetchRequest(req, controller) { - return __awaiter(this, void 0, void 0, function* () { - let timeoutId; - const requestTimeout = new Promise((_, reject) => { - timeoutId = setTimeout(() => { - clearTimeout(timeoutId); - reject(new Error('Request timeout')); - controller.abort('Cancel because of timeout'); - }, req.timeout * 1000); - }); - const request = new Request(req.url, { - method: req.method, - headers: req.headers, - redirect: 'follow', - body: req.body, - }); - return Promise.race([ - WebTransport.originalFetch(request, { - signal: controller.abortController.signal, - credentials: 'omit', - cache: 'no-cache', - }).then((response) => { - if (timeoutId) - clearTimeout(timeoutId); - return response; - }), - requestTimeout, - ]); - }); - } - /** - * Send network request using legacy XMLHttpRequest API. - * - * @param req - Transport API agnostic request object with prepared body and URL. - * @param controller - Request cancellation controller (for long-poll requests). - * - * @returns Promise which will be resolved or rejected at the end of network request processing. - * - * @internal - */ - sendXHRRequest(req, controller) { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => { - var _a; - const xhr = new XMLHttpRequest(); - xhr.open(req.method, req.url, true); - let aborted = false; - // Setup request - xhr.responseType = 'arraybuffer'; - xhr.timeout = req.timeout * 1000; - controller.abortController.signal.onabort = () => { - if (xhr.readyState == XMLHttpRequest.DONE || xhr.readyState == XMLHttpRequest.UNSENT) - return; - aborted = true; - xhr.abort(); - }; - Object.entries((_a = req.headers) !== null && _a !== void 0 ? _a : {}).forEach(([key, value]) => xhr.setRequestHeader(key, value)); - // Setup handlers to match `fetch` results handling. - xhr.onabort = () => { - reject(new Error('Aborted')); - }; - xhr.ontimeout = () => { - reject(new Error('Request timeout')); - }; - xhr.onerror = () => { - if (!aborted) { - const response = this.transportResponseFromXHR(req.url, xhr); - reject(new Error(PubNubAPIError.create(response).message)); - } - }; - xhr.onload = () => { - const headers = new Headers(); - xhr - .getAllResponseHeaders() - .split('\r\n') - .forEach((header) => { - const [key, value] = header.split(': '); - if (key.length > 1 && value.length > 1) - headers.append(key, value); - }); - resolve(new Response(xhr.response, { status: xhr.status, headers, statusText: xhr.statusText })); - }; - xhr.send(req.body); - }); - }); - } - /** - * Creates a Web Request object from a given {@link TransportRequest} object. - * - * @param req - The {@link TransportRequest} object containing request information. - * - * @returns Request object generated from the {@link TransportRequest} object. - * - * @internal - */ - webTransportRequestFromTransportRequest(req) { - return __awaiter(this, void 0, void 0, function* () { - let body; - let path = req.path; - // Create a multipart request body. - if (req.formData && req.formData.length > 0) { - // Reset query parameters to conform to signed URL - req.queryParameters = {}; - const file = req.body; - const formData = new FormData(); - for (const { key, value } of req.formData) - formData.append(key, value); - try { - const fileData = yield file.toArrayBuffer(); - formData.append('file', new Blob([fileData], { type: 'application/octet-stream' }), file.name); - } - catch (toBufferError) { - this.logger.warn('WebTransport', () => ({ messageType: 'error', message: toBufferError })); - try { - const fileData = yield file.toFileUri(); - // @ts-expect-error React Native File Uri support. - formData.append('file', fileData, file.name); - } - catch (toFileURLError) { - this.logger.error('WebTransport', () => ({ messageType: 'error', message: toFileURLError })); - } - } - body = formData; - } - // Handle regular body payload (if passed). - else if (req.body && (typeof req.body === 'string' || req.body instanceof ArrayBuffer)) { - // Compressing body if the browser has native support. - if (req.compressible && typeof CompressionStream !== 'undefined') { - const bodyArrayBuffer = typeof req.body === 'string' ? WebTransport.encoder.encode(req.body) : req.body; - const initialBodySize = bodyArrayBuffer.byteLength; - const bodyStream = new ReadableStream({ - start(controller) { - controller.enqueue(bodyArrayBuffer); - controller.close(); - }, - }); - body = yield new Response(bodyStream.pipeThrough(new CompressionStream('deflate'))).arrayBuffer(); - this.logger.trace('WebTransport', () => { - const compressedSize = body.byteLength; - const ratio = (compressedSize / initialBodySize).toFixed(2); - return { - messageType: 'text', - message: `Body of ${initialBodySize} bytes, compressed by ${ratio}x to ${compressedSize} bytes.`, - }; - }); - } - else - body = req.body; - } - if (req.queryParameters && Object.keys(req.queryParameters).length !== 0) - path = `${path}?${queryStringFromObject(req.queryParameters)}`; - return { - url: `${req.origin}${path}`, - method: req.method, - headers: req.headers, - timeout: req.timeout, - body, - }; - }); - } - /** - * Check whether the original ` fetch ` has been monkey patched or not. - * - * @returns `true` if original `fetch` has been patched. - */ - isFetchMonkeyPatched(oFetch) { - const fetchString = (oFetch !== null && oFetch !== void 0 ? oFetch : fetch).toString(); - return !fetchString.includes('[native code]') && fetch.name !== 'fetch'; - } - /** - * Create service response from {@link XMLHttpRequest} processing result. - * - * @param url - Used endpoint url. - * @param xhr - `HTTPClient`, which has been used to make a request. - * - * @returns Pre-processed transport response. - */ - transportResponseFromXHR(url, xhr) { - const allHeaders = xhr.getAllResponseHeaders().split('\n'); - const headers = {}; - for (const header of allHeaders) { - const [key, value] = header.trim().split(':'); - if (key && value) - headers[key.toLowerCase()] = value.trim(); - } - return { status: xhr.status, url, headers, body: xhr.response }; - } - /** - * Retrieve the original ` fetch ` implementation. - * - * Retrieve implementation which hasn't been patched by APM tools. - * - * @returns Reference to the `fetch` function. - */ - static getOriginalFetch() { - // The iframe-based APM workaround requires a DOM. In DOM-less contexts (e.g. MV3 service workers) there is - // no `document`, and `fetch` cannot be reached through a fresh browsing context — return the context `fetch` - // directly. This is safe there: without a DOM there is no APM page script to monkey patch `fetch` in the - // first place. This environment check is what keeps the unconditional call in the constructor safe. - // - // `fetch` must be bound to the global scope: native `fetch` requires its `this` to be the `Window` / - // `WorkerGlobalScope`, and it is later invoked detached (`WebTransport.originalFetch(...)`). Without the bind - // a service worker throws "Failed to execute 'fetch' on 'WorkerGlobalScope': Illegal invocation". - if (typeof document === 'undefined' || !document.body) - return fetch.bind(globalThis); - let iframe = document.querySelector('iframe[name="pubnub-context-unpatched-fetch"]'); - if (!iframe) { - iframe = document.createElement('iframe'); - iframe.style.display = 'none'; - iframe.name = 'pubnub-context-unpatched-fetch'; - iframe.src = 'about:blank'; - document.body.appendChild(iframe); - } - if (iframe.contentWindow) - return iframe.contentWindow.fetch.bind(iframe.contentWindow); - return fetch.bind(globalThis); - } - } - /** - * Request body decoder. - * - * @internal - */ - WebTransport.encoder = new TextEncoder(); - /** - * Service {@link ArrayBuffer} response decoder. - * - * @internal - */ - WebTransport.decoder = new TextDecoder(); - - /** - * Network request module. - * - * @internal - */ - /** - * Base REST API request class. - * - * @internal - */ - class AbstractRequest { - /** - * Construct base request. - * - * Constructed request by default won't be cancellable and performed using `GET` HTTP method. - * - * @param params - Request configuration parameters. - */ - constructor(params) { - this.params = params; - /** - * Unique request identifier. - */ - this.requestIdentifier = uuidGenerator.createUUID(); - this._cancellationController = null; - } - /** - * Retrieve configured cancellation controller. - * - * @returns Cancellation controller. - */ - get cancellationController() { - return this._cancellationController; - } - /** - * Update request cancellation controller. - * - * Controller itself provided by transport provider implementation and set only when request - * sending has been scheduled. - * - * @param controller - Cancellation controller or `null` to reset it. - */ - set cancellationController(controller) { - this._cancellationController = controller; - } - /** - * Abort request if possible. - * - * @param [reason] Information about why request has been cancelled. - */ - abort(reason) { - if (this && this.cancellationController) - this.cancellationController.abort(reason); - } - /** - * Target REST API endpoint operation type. - */ - operation() { - throw Error('Should be implemented by subclass.'); - } - /** - * Validate user-provided data before scheduling request. - * - * @returns Error message if request can't be sent without missing or malformed parameters. - */ - validate() { - return undefined; - } - /** - * Parse service response. - * - * @param response - Raw service response which should be parsed. - */ - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return this.deserializeResponse(response); - }); - } - /** - * Create platform-agnostic request object. - * - * @returns Request object which can be processed using platform-specific requirements. - */ - request() { - var _a, _b, _c, _d, _e, _f; - const request = { - method: (_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.method) !== null && _b !== void 0 ? _b : TransportMethod.GET, - path: this.path, - queryParameters: this.queryParameters, - cancellable: (_d = (_c = this.params) === null || _c === void 0 ? void 0 : _c.cancellable) !== null && _d !== void 0 ? _d : false, - compressible: (_f = (_e = this.params) === null || _e === void 0 ? void 0 : _e.compressible) !== null && _f !== void 0 ? _f : false, - timeout: 10, - identifier: this.requestIdentifier, - }; - // Attach headers (if required). - const headers = this.headers; - if (headers) - request.headers = headers; - // Attach body (if required). - if (request.method === TransportMethod.POST || - request.method === TransportMethod.PATCH || - request.method === TransportMethod.PUT) { - const [body, formData] = [this.body, this.formData]; - if (formData) - request.formData = formData; - if (body) - request.body = body; - } - return request; - } - /** - * Target REST API endpoint request headers getter. - * - * @returns Key/value headers which should be used with request. - */ - get headers() { - var _a, _b; - return Object.assign({ 'Accept-Encoding': 'gzip, deflate' }, (((_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.compressible) !== null && _b !== void 0 ? _b : false) ? { 'Content-Encoding': 'deflate' } : {})); - } - /** - * Target REST API endpoint request path getter. - * - * @returns REST API path. - */ - get path() { - throw Error('`path` getter should be implemented by subclass.'); - } - /** - * Target REST API endpoint request query parameters getter. - * - * @returns Key/value pairs which should be appended to the REST API path. - */ - get queryParameters() { - return {}; - } - get formData() { - return undefined; - } - /** - * Target REST API Request body payload getter. - * - * @returns Buffer of stringified data which should be sent with `POST` or `PATCH` request. - */ - get body() { - return undefined; - } - /** - * Deserialize service response. - * - * @param response - Transparent response object with headers and body information. - * - * @returns Deserialized service response data. - * - * @throws {Error} if received service response can't be processed (has unexpected content-type or can't be parsed as - * JSON). - */ - deserializeResponse(response) { - const responseText = AbstractRequest.decoder.decode(response.body); - const contentType = response.headers['content-type']; - let parsedJson; - if (!contentType || (contentType.indexOf('javascript') === -1 && contentType.indexOf('json') === -1)) - throw new PubNubError('Service response error, check status for details', createMalformedResponseError(responseText, response.status)); - try { - parsedJson = JSON.parse(responseText); - } - catch (error) { - console.error('Error parsing JSON response:', error); - throw new PubNubError('Service response error, check status for details', createMalformedResponseError(responseText, response.status)); - } - // Throw and exception in case of client / server error. - if ('status' in parsedJson && typeof parsedJson.status === 'number' && parsedJson.status >= 400) - throw PubNubAPIError.create(response); - return parsedJson; - } - } - /** - * Service `ArrayBuffer` response decoder. - */ - AbstractRequest.decoder = new TextDecoder(); - - /** - * Subscription REST API module. - */ - // -------------------------------------------------------- - // ---------------------- Defaults ------------------------ - // -------------------------------------------------------- - // region Defaults - /** - * Whether should subscribe to channels / groups presence announcements or not. - */ - const WITH_PRESENCE = false; - // endregion - // -------------------------------------------------------- - // ------------------------ Types ------------------------- - // -------------------------------------------------------- - // region Types - /** - * PubNub-defined event types by payload. - */ - var PubNubEventType; - (function (PubNubEventType) { - /** - * Presence change event. - */ - PubNubEventType[PubNubEventType["Presence"] = -2] = "Presence"; - /** - * Regular message event. - * - * **Note:** This is default type assigned for non-presence events if `e` field is missing. - */ - PubNubEventType[PubNubEventType["Message"] = -1] = "Message"; - /** - * Signal data event. - */ - PubNubEventType[PubNubEventType["Signal"] = 1] = "Signal"; - /** - * App Context object event. - */ - PubNubEventType[PubNubEventType["AppContext"] = 2] = "AppContext"; - /** - * Message reaction event. - */ - PubNubEventType[PubNubEventType["MessageAction"] = 3] = "MessageAction"; - /** - * Files event. - */ - PubNubEventType[PubNubEventType["Files"] = 4] = "Files"; - /** - * DataSync object change event. - * - * **Note:** Value must equal `5` to match the service wire value (`e: 5`). - */ - PubNubEventType[PubNubEventType["DataSync"] = 5] = "DataSync"; - })(PubNubEventType || (PubNubEventType = {})); - /** - * Event types which this SDK version knows how to parse. - * - * Events with any other `e` value are ignored: they most likely originate from a service release newer than - * the SDK - */ - const KNOWN_EVENT_TYPES = new Set([ - PubNubEventType.Presence, - PubNubEventType.Message, - PubNubEventType.Signal, - PubNubEventType.AppContext, - PubNubEventType.MessageAction, - PubNubEventType.Files, - PubNubEventType.DataSync, - ]); - /** - * Reserved DataSync system class names (lower-cased) → normalized object kind. - * - * Only consulted when the wire {@link DataSyncData.type} is the generic `entity` / `relationship` - * kind, and only for classes the service marks as `Global` (see {@link DataSyncClassLevel}) — so a - * developer-defined class which happens to share one of these names is not mistaken for a typed - * resource. Keys are compared case-insensitively. - * - * @internal - */ - const DATA_SYNC_RESERVED_CLASSES = { - user: 'user', - channel: 'channel', - membership: 'membership', - }; - // endregion - /** - * Base subscription request implementation. - * - * Subscription request used in small variations in two cases: - * - subscription manager - * - event engine - * - * @internal - */ - class BaseSubscribeRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c; - var _d, _e, _f; - super({ cancellable: true }); - this.parameters = parameters; - // Apply default request parameters. - (_a = (_d = this.parameters).withPresence) !== null && _a !== void 0 ? _a : (_d.withPresence = WITH_PRESENCE); - (_b = (_e = this.parameters).channelGroups) !== null && _b !== void 0 ? _b : (_e.channelGroups = []); - (_c = (_f = this.parameters).channels) !== null && _c !== void 0 ? _c : (_f.channels = []); - } - operation() { - return RequestOperation$1.PNSubscribeOperation; - } - validate() { - const { keySet: { subscribeKey }, channels, channelGroups, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channels && !channelGroups) - return '`channels` and `channelGroups` both should not be empty'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - let serviceResponse; - let responseText; - try { - responseText = AbstractRequest.decoder.decode(response.body); - const parsedJson = JSON.parse(responseText); - serviceResponse = parsedJson; - } - catch (error) { - console.error('Error parsing JSON response:', error); - } - if (!serviceResponse) { - throw new PubNubError('Service response error, check status for details', createMalformedResponseError(responseText, response.status)); - } - const events = serviceResponse.m - .filter((envelope) => { - const subscribable = envelope.b === undefined ? envelope.c : envelope.b; - return ((this.parameters.channels && this.parameters.channels.includes(subscribable)) || - (this.parameters.channelGroups && this.parameters.channelGroups.includes(subscribable))); - }) - .map((envelope) => { - let { e: eventType } = envelope; - // Events delivered on a presence channel are always presence events: the `-pnpres` suffix wins over - // the service-reported type. `envelope.c` is the actual channel (`envelope.b` is the channel group - // name), so this also covers presence delivered through a subscribed channel group. - if (envelope.c.endsWith('-pnpres')) - eventType = PubNubEventType.Presence; - // Resolve missing event type. - else - eventType !== null && eventType !== void 0 ? eventType : (eventType = PubNubEventType.Message); - // Ignore an event type this SDK version cannot parse rather than delivering an unexpected payload. - if (!KNOWN_EVENT_TYPES.has(eventType)) - return undefined; - const pn_mfp = messageFingerprint(envelope.d); - // Check whether payload is string (potentially encrypted data). - if (eventType != PubNubEventType.Presence && - eventType != PubNubEventType.Signal && - typeof envelope.d === 'string') { - if (eventType == PubNubEventType.Message) { - return { - type: PubNubEventType.Message, - data: this.messageFromEnvelope(envelope), - pn_mfp, - }; - } - return { - type: PubNubEventType.Files, - data: this.fileFromEnvelope(envelope), - pn_mfp, - }; - } - else if (eventType == PubNubEventType.Message) { - return { - type: PubNubEventType.Message, - data: this.messageFromEnvelope(envelope), - pn_mfp, - }; - } - else if (eventType === PubNubEventType.Presence) { - return { - type: PubNubEventType.Presence, - data: this.presenceEventFromEnvelope(envelope), - pn_mfp, - }; - } - else if (eventType == PubNubEventType.Signal) { - return { - type: PubNubEventType.Signal, - data: this.signalFromEnvelope(envelope), - pn_mfp, - }; - } - else if (eventType === PubNubEventType.AppContext) { - return { - type: PubNubEventType.AppContext, - data: this.appContextFromEnvelope(envelope), - pn_mfp, - }; - } - else if (eventType === PubNubEventType.MessageAction) { - return { - type: PubNubEventType.MessageAction, - data: this.messageActionFromEnvelope(envelope), - pn_mfp, - }; - } - else if (eventType === PubNubEventType.DataSync) { - const dataSync = this.dataSyncFromEnvelope(envelope); - // Guard: only treat as DataSync when the service marks it so; otherwise fall back to message. - if (dataSync) - return { type: PubNubEventType.DataSync, data: dataSync, pn_mfp }; - return { type: PubNubEventType.Message, data: this.messageFromEnvelope(envelope), pn_mfp }; - } - // The only known event type left is a file event. - return { - type: PubNubEventType.Files, - data: this.fileFromEnvelope(envelope), - pn_mfp, - }; - }) - .filter((event) => event !== undefined); - return { - cursor: { timetoken: serviceResponse.t.t, region: serviceResponse.t.r }, - messages: events, - }; - }); - } - get headers() { - var _a; - return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { accept: 'text/javascript' }); - } - // -------------------------------------------------------- - // ------------------ Envelope parsing -------------------- - // -------------------------------------------------------- - // region Envelope parsing - presenceEventFromEnvelope(envelope) { - var _a; - const { d: payload } = envelope; - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - // Clean up channel and subscription name from presence suffix. - const trimmedChannel = channel.replace('-pnpres', ''); - // Backward compatibility with deprecated properties. - const actualChannel = subscription !== null ? trimmedChannel : null; - const subscribedChannel = subscription !== null ? subscription : trimmedChannel; - // Presence payloads are objects. A string can only reach here when a non-presence payload has been published - // on a `-pnpres` channel: try to read it as JSON and never spread a string (which would add character-indexed - // keys to the event). - let presenceData; - if (typeof payload === 'string') { - try { - const parsed = JSON.parse(payload); - if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) - presenceData = parsed; - } - catch (_b) { - // Not JSON (encrypted or plain-text publish): payload contributes no presence fields. - } - } - else - presenceData = payload; - if (presenceData) { - if ('data' in presenceData) { - // @ts-expect-error This is `state-change` object which should have `state` field. - presenceData['state'] = presenceData.data; - delete presenceData.data; - } - else if ('action' in presenceData && presenceData.action === 'interval') { - presenceData.hereNowRefresh = (_a = presenceData.here_now_refresh) !== null && _a !== void 0 ? _a : false; - delete presenceData.here_now_refresh; - } - } - return Object.assign({ channel: trimmedChannel, subscription, - actualChannel, - subscribedChannel, timetoken: envelope.p.t }, (presenceData !== null && presenceData !== void 0 ? presenceData : {})); - } - messageFromEnvelope(envelope) { - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - const [message, decryptionError] = this.decryptedData(envelope.d); - // Backward compatibility with deprecated properties. - const actualChannel = subscription !== null ? channel : null; - const subscribedChannel = subscription !== null ? subscription : channel; - // Basic message event payload. - const event = { - channel, - subscription, - actualChannel, - subscribedChannel, - timetoken: envelope.p.t, - publisher: envelope.i, - message, - }; - if (envelope.u) - event.userMetadata = envelope.u; - if (envelope.cmt) - event.customMessageType = envelope.cmt; - if (decryptionError) - event.error = decryptionError; - return event; - } - signalFromEnvelope(envelope) { - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - const event = { - channel, - subscription, - timetoken: envelope.p.t, - publisher: envelope.i, - message: envelope.d, - }; - if (envelope.u) - event.userMetadata = envelope.u; - if (envelope.cmt) - event.customMessageType = envelope.cmt; - return event; - } - messageActionFromEnvelope(envelope) { - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - const action = envelope.d; - return { - channel, - subscription, - timetoken: envelope.p.t, - publisher: envelope.i, - event: action.event, - data: Object.assign(Object.assign({}, action.data), { uuid: envelope.i }), - }; - } - appContextFromEnvelope(envelope) { - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - const object = envelope.d; - return { - channel, - subscription, - timetoken: envelope.p.t, - message: object, - }; - } - dataSyncFromEnvelope(envelope) { - var _a; - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - const payload = envelope.d; - const metadata = payload === null || payload === void 0 ? void 0 : payload.metadata; - // Only treat the envelope as DataSync when the service marks it and carries the required fields. - if (!metadata || metadata.source !== 'data-sync' || !metadata.event || !metadata.type) - return undefined; - // Wire `className` is a bare class name (`User`, `Membership`, `Customer`); the `:`-splitting below - // is only there to keep tolerating the retired positional composite (`User::` / `::Customer`). - const classSegments = metadata.className ? metadata.className.split(':') : []; - const nonEmptySegments = classSegments.filter((segment) => segment.length > 0); - const className = nonEmptySegments.length > 0 ? nonEmptySegments[nonEmptySegments.length - 1] : undefined; - const classLevel = metadata.classLevel; - // `classLevel` authoritatively separates the built-in classes from developer-defined ones, so a - // developer class named `User` / `Channel` / `Membership` is not mistaken for a typed resource. - // When it is absent (service predating the field) fall back to the legacy positional heuristic, - // where the system class was the first segment. - const systemClass = classLevel === undefined ? classSegments[0] : classLevel === 'Global' ? className : undefined; - // The service reports the semantic kind directly; the class-name lookup only fills it in for a - // service which still sends the built-in classes under the generic `entity` / `relationship` kind. - const genericType = metadata.type === 'entity' || metadata.type === 'relationship'; - const objectType = genericType - ? (systemClass && DATA_SYNC_RESERVED_CLASSES[systemClass.toLowerCase()]) || metadata.type - : metadata.type; - const parsedVersion = metadata.classVersion !== undefined ? Number.parseInt(`${metadata.classVersion}`, 10) : NaN; - const classVersion = Number.isNaN(parsedVersion) ? undefined : parsedVersion; - const raw = ((_a = payload.data) !== null && _a !== void 0 ? _a : {}); - // Class identity is reported once, on the event, so it is shared by every event shape. - const common = { - version: payload.version, - source: metadata.source, - type: metadata.type, - className, - classLevel, - classVersion, - }; - // `data` mirrors the object as sent by the service, and its shape is tied to `event` / - // `objectType` — which is what makes `message` a discriminated union for the consumer. - let message; - if (metadata.event === 'delete' && objectType === 'membership') { - const data = { - id: raw.id, - deletedAt: raw.deletedAt, - }; - // Membership deletes name the endpoints they joined. Other fields stay trimmed. - if (typeof raw.channelId === 'string') - data.channelId = raw.channelId; - if (typeof raw.userId === 'string') - data.userId = raw.userId; - message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data }); - } - else if (metadata.event === 'delete' && objectType === 'relationship') { - const data = { - id: raw.id, - deletedAt: raw.deletedAt, - }; - // Relationship deletes name the entities they linked. Other fields stay trimmed. - if (typeof raw.entityAId === 'string') - data.entityAId = raw.entityAId; - if (typeof raw.entityBId === 'string') - data.entityBId = raw.entityBId; - message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data }); - } - else if (metadata.event === 'delete') - message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: { id: raw.id, deletedAt: raw.deletedAt } }); - else if (objectType === 'membership') - message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); - else if (objectType === 'relationship') - message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); - else - message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); - return { - channel, - subscription, - timetoken: envelope.p.t, - message, - }; - } - fileFromEnvelope(envelope) { - const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); - const [file, decryptionError] = this.decryptedData(envelope.d); - let errorMessage = decryptionError; - // Basic file event payload. - const event = { - channel, - subscription, - timetoken: envelope.p.t, - publisher: envelope.i, - }; - if (envelope.u) - event.userMetadata = envelope.u; - if (!file) - errorMessage !== null && errorMessage !== void 0 ? errorMessage : (errorMessage = `File information payload is missing.`); - else if (typeof file === 'string') - errorMessage !== null && errorMessage !== void 0 ? errorMessage : (errorMessage = `Unexpected file information payload data type.`); - else { - event.message = file.message; - if (file.file) { - event.file = { - id: file.file.id, - name: file.file.name, - url: this.parameters.getFileUrl({ id: file.file.id, name: file.file.name, channel }), - }; - } - } - if (envelope.cmt) - event.customMessageType = envelope.cmt; - if (errorMessage) - event.error = errorMessage; - return event; - } - // endregion - subscriptionChannelFromEnvelope(envelope) { - return [envelope.c, envelope.b === undefined ? envelope.c : envelope.b]; - } - /** - * Decrypt provided `data`. - * - * @param [data] - Message or file information which should be decrypted if possible. - * - * @returns Tuple with decrypted data and decryption error (if any). - */ - decryptedData(data) { - if (!this.parameters.crypto || typeof data !== 'string') - return [data, undefined]; - let payload; - let error; - try { - const decryptedData = this.parameters.crypto.decrypt(data); - payload = - decryptedData instanceof ArrayBuffer - ? JSON.parse(SubscribeRequest.decoder.decode(decryptedData)) - : decryptedData; - } - catch (err) { - payload = null; - error = `Error while decrypting message content: ${err.message}`; - } - return [(payload !== null && payload !== void 0 ? payload : data), error]; - } - } - /** - * Subscribe request. - * - * @internal - */ - class SubscribeRequest extends BaseSubscribeRequest { - get path() { - var _a; - const { keySet: { subscribeKey }, channels, } = this.parameters; - return `/v2/subscribe/${subscribeKey}/${encodeNames((_a = channels === null || channels === void 0 ? void 0 : channels.sort()) !== null && _a !== void 0 ? _a : [], ',')}/0`; - } - get queryParameters() { - const { channelGroups, filterExpression, heartbeat, state, timetoken, region, onDemand } = this.parameters; - const query = {}; - if (onDemand) - query['on-demand'] = 1; - if (channelGroups && channelGroups.length > 0) - query['channel-group'] = channelGroups.sort().join(','); - if (filterExpression && filterExpression.length > 0) - query['filter-expr'] = filterExpression; - if (heartbeat) - query.heartbeat = heartbeat; - if (state && Object.keys(state).length > 0) - query['state'] = JSON.stringify(state); - if (timetoken !== undefined && typeof timetoken === 'string') { - if (timetoken.length > 0 && timetoken !== '0') - query['tt'] = timetoken; - } - else if (timetoken !== undefined && timetoken > 0) - query['tt'] = timetoken; - if (region) - query['tr'] = region; - return query; - } - } - - /** - * Events dispatcher module. - */ - /** - * Real-time events dispatcher. - * - * Class responsible for listener management and invocation. - * - * @internal - */ - class EventDispatcher { - constructor() { - /** - * Whether listeners has been added or not. - */ - this.hasListeners = false; - /** - * List of registered event handlers. - * - * **Note:** the First element is reserved for type-based event handlers. - */ - this.listeners = [{ count: -1, listener: {} }]; - } - /** - * Set a connection status change event handler. - * - * @param listener - Listener function, which will be called each time when the connection status changes. - */ - set onStatus(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'status' }); - } - /** - * Set a new message handler. - * - * @param listener - Listener function, which will be called each time when a new message - * is received from the real-time network. - */ - set onMessage(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'message' }); - } - /** - * Set a new presence events handler. - * - * @param listener - Listener function, which will be called each time when a new - * presence event is received from the real-time network. - */ - set onPresence(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'presence' }); - } - /** - * Set a new signal handler. - * - * @param listener - Listener function, which will be called each time when a new signal - * is received from the real-time network. - */ - set onSignal(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'signal' }); - } - /** - * Set a new app context event handler. - * - * @param listener - Listener function, which will be called each time when a new - * app context event is received from the real-time network. - */ - set onObjects(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'objects' }); - } - /** - * Set a new message reaction event handler. - * - * @param listener - Listener function, which will be called each time when a - * new message reaction event is received from the real-time network. - */ - set onMessageAction(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'messageAction' }); - } - /** - * Set a new file handler. - * - * @param listener - Listener function, which will be called each time when a new file - * is received from the real-time network. - */ - set onFile(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'file' }); - } - /** - * Set a new DataSync event handler. - * - * @param listener - Listener function, which will be called each time when a new - * DataSync event is received from the real-time network. - */ - set onDataSync(listener) { - this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'dataSync' }); - } - /** - * Dispatch received a real-time update. - * - * @param event - A real-time event from multiplexed subscription. - */ - handleEvent(event) { - if (!this.hasListeners) - return; - if (event.type === PubNubEventType.Message) - this.announce('message', event.data); - else if (event.type === PubNubEventType.Signal) - this.announce('signal', event.data); - else if (event.type === PubNubEventType.Presence) - this.announce('presence', event.data); - else if (event.type === PubNubEventType.AppContext) { - const { data: objectEvent } = event; - const { message: object } = objectEvent; - this.announce('objects', objectEvent); - if (object.type === 'uuid') { - const { message, channel } = objectEvent, restEvent = __rest(objectEvent, ["message", "channel"]); - const { event, type } = object, restObject = __rest(object, ["event", "type"]); - const userEvent = Object.assign(Object.assign({}, restEvent), { spaceId: channel, message: Object.assign(Object.assign({}, restObject), { event: event === 'set' ? 'updated' : 'removed', type: 'user' }) }); - this.announce('user', userEvent); - } - else if (object.type === 'channel') { - const { message, channel } = objectEvent, restEvent = __rest(objectEvent, ["message", "channel"]); - const { event, type } = object, restObject = __rest(object, ["event", "type"]); - const spaceEvent = Object.assign(Object.assign({}, restEvent), { spaceId: channel, message: Object.assign(Object.assign({}, restObject), { event: event === 'set' ? 'updated' : 'removed', type: 'space' }) }); - this.announce('space', spaceEvent); - } - else if (object.type === 'membership') { - const { message, channel } = objectEvent, restEvent = __rest(objectEvent, ["message", "channel"]); - const { event, data } = object, restObject = __rest(object, ["event", "data"]); - const { uuid, channel: channelMeta } = data, restData = __rest(data, ["uuid", "channel"]); - const membershipEvent = Object.assign(Object.assign({}, restEvent), { spaceId: channel, message: Object.assign(Object.assign({}, restObject), { event: event === 'set' ? 'updated' : 'removed', data: Object.assign(Object.assign({}, restData), { user: uuid, space: channelMeta }) }) }); - this.announce('membership', membershipEvent); - } - } - else if (event.type === PubNubEventType.MessageAction) - this.announce('messageAction', event.data); - else if (event.type === PubNubEventType.Files) - this.announce('file', event.data); - else if (event.type === PubNubEventType.DataSync) - this.announce('dataSync', event.data); - } - /** - * Dispatch received connection status change. - * - * @param status - Status object which should be emitter for all status listeners. - */ - handleStatus(status) { - if (!this.hasListeners) - return; - this.announce('status', status); - } - /** - * Add events handler. - * - * @param listener - Events listener configuration object, which lets specify handlers for multiple types of events. - */ - addListener(listener) { - this.updateTypeOrObjectListener({ add: true, listener }); - } - removeListener(listener) { - this.updateTypeOrObjectListener({ add: false, listener }); - } - removeAllListeners() { - this.listeners = [{ count: -1, listener: {} }]; - this.hasListeners = false; - } - updateTypeOrObjectListener(parameters) { - if (parameters.type) { - if (typeof parameters.listener === 'function') - this.listeners[0].listener[parameters.type] = parameters.listener; - else - delete this.listeners[0].listener[parameters.type]; - } - else if (parameters.listener && typeof parameters.listener !== 'function') { - let listenerObject; - let listenerExists = false; - for (listenerObject of this.listeners) { - if (listenerObject.listener === parameters.listener) { - if (parameters.add) { - listenerObject.count++; - listenerExists = true; - } - else { - listenerObject.count--; - if (listenerObject.count === 0) - this.listeners.splice(this.listeners.indexOf(listenerObject), 1); - } - break; - } - } - if (parameters.add && !listenerExists) - this.listeners.push({ count: 1, listener: parameters.listener }); - } - this.hasListeners = this.listeners.length > 1 || Object.keys(this.listeners[0]).length > 0; - } - /** - * Announce a real-time event to all listeners. - * - * @param type - Type of event which should be announced. - * @param event - Announced real-time event payload. - */ - announce(type, event) { - this.listeners.forEach(({ listener }) => { - const typedListener = listener[type]; - // @ts-expect-error Dynamic events mapping. - if (typedListener) - typedListener(event); - }); - } - } - - /** - * Subscription reconnection-manager. - * - * **Note:** Reconnection manger rely on legacy time-based availability check. - * - * @internal - */ - /** - * Network "discovery" manager. - * - * Manager perform periodic `time` API calls to identify network availability. - * - * @internal - */ - class ReconnectionManager { - constructor(time) { - this.time = time; - } - /** - * Configure reconnection handler. - * - * @param callback - Successful availability check notify callback. - */ - onReconnect(callback) { - this.callback = callback; - } - /** - * Start periodic "availability" check. - */ - startPolling() { - this.timeTimer = setInterval(() => this.callTime(), 3000); - } - /** - * Stop periodic "availability" check. - */ - stopPolling() { - if (this.timeTimer) - clearInterval(this.timeTimer); - this.timeTimer = null; - } - callTime() { - this.time((status) => { - if (!status.error) { - this.stopPolling(); - if (this.callback) - this.callback(); - } - }); - } - } - - /** - * Messages de-duplication manager module. - * - * @internal - */ - /** - * Real-time events deduplication manager. - * - * @internal - */ - class DedupingManager { - /** - * Create and configure real-time events de-duplication manager. - * - * @param config - PubNub client configuration object. - */ - constructor(config) { - this.config = config; - config.logger().debug('DedupingManager', () => ({ - messageType: 'object', - message: { maximumCacheSize: config.maximumCacheSize }, - details: 'Create with configuration:', - })); - this.maximumCacheSize = config.maximumCacheSize; - this.hashHistory = []; - } - /** - * Compute unique real-time event payload key. - * - * @param message - Received real-time event payload for which unique key should be computed. - * @returns Unique real-time event payload key in messages cache. - */ - getKey(message) { - var _a; - return `${message.timetoken}-${this.hashCode(JSON.stringify((_a = message.message) !== null && _a !== void 0 ? _a : '')).toString()}`; - } - /** - * Check whether there is similar message already received or not. - * - * @param message - Received real-time event payload which should be checked for duplicates. - * @returns `true` in case if similar payload already has been received before. - */ - isDuplicate(message) { - return this.hashHistory.includes(this.getKey(message)); - } - /** - * Store received message to be used later for duplicate detection. - * - * @param message - Received real-time event payload. - */ - addEntry(message) { - if (this.hashHistory.length >= this.maximumCacheSize) { - this.hashHistory.shift(); - } - this.hashHistory.push(this.getKey(message)); - } - /** - * Clean up cached messages. - */ - clearHistory() { - this.hashHistory = []; - } - /** - * Compute message hash sum. - * - * @param payload - Received payload for which hash sum should be computed. - * @returns {number} - Resulting hash sum. - */ - hashCode(payload) { - let hash = 0; - if (payload.length === 0) - return hash; - for (let i = 0; i < payload.length; i += 1) { - const character = payload.charCodeAt(i); - hash = (hash << 5) - hash + character; // eslint-disable-line - hash = hash & hash; // eslint-disable-line - } - return hash; - } - } - - /** - * Subscription manager module. - * - * @internal - */ - /** - * Subscription loop manager. - * - * @internal - */ - class SubscriptionManager { - constructor(configuration, emitEvent, emitStatus, subscribeCall, heartbeatCall, leaveCall, time) { - this.configuration = configuration; - this.emitEvent = emitEvent; - this.emitStatus = emitStatus; - this.subscribeCall = subscribeCall; - this.heartbeatCall = heartbeatCall; - this.leaveCall = leaveCall; - /** - * Whether user code in event handlers requested disconnection or not. - * - * Won't continue subscription loop if user requested disconnection/unsubscribe from all in response to received - * event. - */ - this.disconnectedWhileHandledEvent = false; - configuration.logger().trace('SubscriptionManager', 'Create manager.'); - this.reconnectionManager = new ReconnectionManager(time); - this.dedupingManager = new DedupingManager(this.configuration); - this.heartbeatChannelGroups = {}; - this.heartbeatChannels = {}; - this.presenceChannelGroups = {}; - this.presenceChannels = {}; - this.heartbeatTimer = null; - this.presenceState = {}; - this.pendingChannelGroupSubscriptions = new Set(); - this.pendingChannelSubscriptions = new Set(); - this.channelGroups = {}; - this.channels = {}; - this.currentTimetoken = '0'; - this.lastTimetoken = '0'; - this.storedTimetoken = null; - this.referenceTimetoken = null; - this.subscriptionStatusAnnounced = false; - this.isOnline = true; - } - // region Information - /** - * Subscription-based current timetoken. - * - * @returns Timetoken based on current timetoken plus diff between current and loop start time. - */ - get subscriptionTimetoken() { - var _a; - return subscriptionTimetokenFromReference(this.currentTimetoken, (_a = this.referenceTimetoken) !== null && _a !== void 0 ? _a : '0'); - } - get subscribedChannels() { - return Object.keys(this.channels); - } - get subscribedChannelGroups() { - return Object.keys(this.channelGroups); - } - get abort() { - return this._subscribeAbort; - } - set abort(call) { - this._subscribeAbort = call; - } - // endregion - // region Subscription - disconnect() { - // Potentially called during received events handling. - // Mark to prevent subscription loop continuation in subscribe response handler. - this.disconnectedWhileHandledEvent = true; - this.stopSubscribeLoop(); - this.stopHeartbeatTimer(); - this.reconnectionManager.stopPolling(); - } - /** - * Restart subscription loop with current state. - * - * @param forUnsubscribe - Whether restarting subscription loop as part of channels list change on - * unsubscribe or not. - */ - reconnect(forUnsubscribe = false) { - this.startSubscribeLoop(forUnsubscribe); - // Starting heartbeat loop for provided channels and groups. - if (!forUnsubscribe && !this.configuration.useSmartHeartbeat) - this.startHeartbeatTimer(); - } - /** - * Update channels and groups used in subscription loop. - * - * @param parameters - Subscribe configuration parameters. - */ - subscribe(parameters) { - const { channels, channelGroups, timetoken, withPresence = false, withHeartbeats = false } = parameters; - if (timetoken) { - this.lastTimetoken = this.currentTimetoken; - this.currentTimetoken = `${timetoken}`; - } - if (this.currentTimetoken !== '0') { - this.storedTimetoken = this.currentTimetoken; - this.currentTimetoken = '0'; - } - channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => { - this.pendingChannelSubscriptions.add(channel); - this.channels[channel] = {}; - if (withPresence) - this.presenceChannels[channel] = {}; - if (withHeartbeats || this.configuration.getHeartbeatInterval()) - this.heartbeatChannels[channel] = {}; - }); - channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => { - this.pendingChannelGroupSubscriptions.add(group); - this.channelGroups[group] = {}; - if (withPresence) - this.presenceChannelGroups[group] = {}; - if (withHeartbeats || this.configuration.getHeartbeatInterval()) - this.heartbeatChannelGroups[group] = {}; - }); - this.subscriptionStatusAnnounced = false; - this.reconnect(); - } - unsubscribe(parameters, isOffline = false) { - let { channels, channelGroups } = parameters; - const actualChannelGroups = new Set(); - const actualChannels = new Set(); - channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => { - if (channel in this.channels) { - delete this.channels[channel]; - actualChannels.add(channel); - if (channel in this.heartbeatChannels) - delete this.heartbeatChannels[channel]; - } - if (channel in this.presenceState) - delete this.presenceState[channel]; - if (channel in this.presenceChannels) { - delete this.presenceChannels[channel]; - actualChannels.add(channel); - } - }); - channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => { - if (group in this.channelGroups) { - delete this.channelGroups[group]; - actualChannelGroups.add(group); - if (group in this.heartbeatChannelGroups) - delete this.heartbeatChannelGroups[group]; - } - if (group in this.presenceState) - delete this.presenceState[group]; - if (group in this.presenceChannelGroups) { - delete this.presenceChannelGroups[group]; - actualChannelGroups.add(group); - } - }); - // There is no need to unsubscribe to empty list of data sources. - if (actualChannels.size === 0 && actualChannelGroups.size === 0) - return; - const lastTimetoken = this.lastTimetoken; - const currentTimetoken = this.currentTimetoken; - if (Object.keys(this.channels).length === 0 && - Object.keys(this.presenceChannels).length === 0 && - Object.keys(this.channelGroups).length === 0 && - Object.keys(this.presenceChannelGroups).length === 0) { - this.lastTimetoken = '0'; - this.currentTimetoken = '0'; - this.referenceTimetoken = null; - this.storedTimetoken = null; - this.region = null; - this.reconnectionManager.stopPolling(); - } - this.reconnect(true); - // Send leave request after long-poll connection closed and loop restarted (the same way as it happens in new - // subscription flow). - if (this.configuration.suppressLeaveEvents === false && !isOffline) { - channelGroups = Array.from(actualChannelGroups); - channels = Array.from(actualChannels); - this.leaveCall({ channels, channelGroups }, (status) => { - const { error } = status, restOfStatus = __rest(status, ["error"]); - let errorMessage; - if (error) { - if (status.errorData && - typeof status.errorData === 'object' && - 'message' in status.errorData && - typeof status.errorData.message === 'string') - errorMessage = status.errorData.message; - else if ('message' in status && typeof status.message === 'string') - errorMessage = status.message; - } - this.emitStatus(Object.assign(Object.assign({}, restOfStatus), { error: errorMessage !== null && errorMessage !== void 0 ? errorMessage : false, affectedChannels: channels, affectedChannelGroups: channelGroups, currentTimetoken, - lastTimetoken })); - }); - } - } - unsubscribeAll(isOffline = false) { - this.disconnectedWhileHandledEvent = true; - this.unsubscribe({ - channels: this.subscribedChannels, - channelGroups: this.subscribedChannelGroups, - }, isOffline); - } - /** - * Start next subscription loop. - * - * @param restartOnUnsubscribe - Whether restarting subscription loop as part of channels list change on - * unsubscribe or not. - * - * @internal - */ - startSubscribeLoop(restartOnUnsubscribe = false) { - this.disconnectedWhileHandledEvent = false; - this.stopSubscribeLoop(); - const channelGroups = [...Object.keys(this.channelGroups)]; - const channels = [...Object.keys(this.channels)]; - Object.keys(this.presenceChannelGroups).forEach((group) => channelGroups.push(`${group}-pnpres`)); - Object.keys(this.presenceChannels).forEach((channel) => channels.push(`${channel}-pnpres`)); - // There is no need to start subscription loop for an empty list of data sources. - if (channels.length === 0 && channelGroups.length === 0) - return; - this.subscribeCall(Object.assign(Object.assign(Object.assign({ channels, - channelGroups, state: this.presenceState, heartbeat: this.configuration.getPresenceTimeout(), timetoken: this.currentTimetoken }, (this.region !== null ? { region: this.region } : {})), (this.configuration.filterExpression ? { filterExpression: this.configuration.filterExpression } : {})), { onDemand: !this.subscriptionStatusAnnounced || restartOnUnsubscribe }), (status, result) => { - this.processSubscribeResponse(status, result); - }); - if (!restartOnUnsubscribe && this.configuration.useSmartHeartbeat) - this.startHeartbeatTimer(); - } - stopSubscribeLoop() { - if (this._subscribeAbort) { - this._subscribeAbort(); - this._subscribeAbort = null; - } - } - /** - * Process subscribe REST API endpoint response. - */ - processSubscribeResponse(status, result) { - if (status.error) { - // Ignore aborted request. - if ((typeof status.errorData === 'object' && - 'name' in status.errorData && - status.errorData.name === 'AbortError') || - status.category === StatusCategory$1.PNCancelledCategory) - return; - if (status.category === StatusCategory$1.PNTimeoutCategory) { - this.startSubscribeLoop(); - } - else if (status.category === StatusCategory$1.PNNetworkIssuesCategory || - status.category === StatusCategory$1.PNMalformedResponseCategory) { - this.disconnect(); - if (status.error && this.configuration.autoNetworkDetection && this.isOnline) { - this.isOnline = false; - this.emitStatus({ category: StatusCategory$1.PNNetworkDownCategory }); - } - this.reconnectionManager.onReconnect(() => { - if (this.configuration.autoNetworkDetection && !this.isOnline) { - this.isOnline = true; - this.emitStatus({ category: StatusCategory$1.PNNetworkUpCategory }); - } - this.reconnect(); - this.subscriptionStatusAnnounced = true; - const reconnectedAnnounce = { - category: StatusCategory$1.PNReconnectedCategory, - operation: status.operation, - lastTimetoken: this.lastTimetoken, - currentTimetoken: this.currentTimetoken, - }; - this.emitStatus(reconnectedAnnounce); - }); - this.reconnectionManager.startPolling(); - this.emitStatus(Object.assign(Object.assign({}, status), { category: StatusCategory$1.PNNetworkIssuesCategory })); - } - else if (status.category === StatusCategory$1.PNBadRequestCategory) { - this.stopHeartbeatTimer(); - this.emitStatus(status); - } - else - this.emitStatus(status); - return; - } - this.referenceTimetoken = referenceSubscribeTimetoken(result.cursor.timetoken, this.storedTimetoken); - if (this.storedTimetoken) { - this.currentTimetoken = this.storedTimetoken; - this.storedTimetoken = null; - } - else { - this.lastTimetoken = this.currentTimetoken; - this.currentTimetoken = result.cursor.timetoken; - } - if (!this.subscriptionStatusAnnounced) { - const connected = { - category: StatusCategory$1.PNConnectedCategory, - operation: status.operation, - affectedChannels: Array.from(this.pendingChannelSubscriptions), - subscribedChannels: this.subscribedChannels, - affectedChannelGroups: Array.from(this.pendingChannelGroupSubscriptions), - lastTimetoken: this.lastTimetoken, - currentTimetoken: this.currentTimetoken, - }; - this.subscriptionStatusAnnounced = true; - this.emitStatus(connected); - // Clear pending channels and groups. - this.pendingChannelGroupSubscriptions.clear(); - this.pendingChannelSubscriptions.clear(); - } - const { messages } = result; - const { requestMessageCountThreshold, dedupeOnSubscribe } = this.configuration; - if (requestMessageCountThreshold && messages.length >= requestMessageCountThreshold) { - this.emitStatus({ - category: StatusCategory$1.PNRequestMessageCountExceededCategory, - operation: status.operation, - }); - } - try { - const cursor = { - timetoken: this.currentTimetoken, - region: this.region ? this.region : undefined, - }; - this.configuration.logger().debug('SubscriptionManager', () => { - const hashedEvents = messages.map((event) => ({ - type: event.type, - data: Object.assign(Object.assign({}, event.data), { pn_mfp: event.pn_mfp }), - })); - return { messageType: 'object', message: hashedEvents, details: 'Received events:' }; - }); - messages.forEach((message) => { - if (dedupeOnSubscribe && 'message' in message.data && 'timetoken' in message.data) { - if (this.dedupingManager.isDuplicate(message.data)) { - this.configuration.logger().warn('SubscriptionManager', () => ({ - messageType: 'object', - message: message.data, - details: 'Duplicate message detected (skipped):', - })); - return; - } - this.dedupingManager.addEntry(message.data); - } - this.emitEvent(cursor, message); - }); - } - catch (e) { - const errorStatus = { - error: true, - category: StatusCategory$1.PNUnknownCategory, - errorData: e, - statusCode: 0, - }; - this.emitStatus(errorStatus); - } - this.region = result.cursor.region; - if (!this.disconnectedWhileHandledEvent) - this.startSubscribeLoop(); - else - this.disconnectedWhileHandledEvent = false; - } - // endregion - // region Presence - /** - * Update `uuid` state which should be sent with subscribe request. - * - * @param parameters - Channels and groups with state which should be associated to `uuid`. - */ - setState(parameters) { - const { state, channels, channelGroups } = parameters; - channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => channel in this.channels && (this.presenceState[channel] = state)); - channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => group in this.channelGroups && (this.presenceState[group] = state)); - } - /** - * Manual presence management. - * - * @param parameters - Desired presence state for provided list of channels and groups. - */ - changePresence(parameters) { - const { connected, channels, channelGroups } = parameters; - if (connected) { - channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => (this.heartbeatChannels[channel] = {})); - channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => (this.heartbeatChannelGroups[group] = {})); - } - else { - channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => { - if (channel in this.heartbeatChannels) - delete this.heartbeatChannels[channel]; - }); - channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => { - if (group in this.heartbeatChannelGroups) - delete this.heartbeatChannelGroups[group]; - }); - if (this.configuration.suppressLeaveEvents === false) { - this.leaveCall({ channels, channelGroups }, (status) => this.emitStatus(status)); - } - } - this.reconnect(); - } - startHeartbeatTimer() { - this.stopHeartbeatTimer(); - const heartbeatInterval = this.configuration.getHeartbeatInterval(); - if (!heartbeatInterval || heartbeatInterval === 0) - return; - // Sending immediate heartbeat only if not working as a smart heartbeat. - if (!this.configuration.useSmartHeartbeat) - this.sendHeartbeat(); - this.heartbeatTimer = setInterval(() => this.sendHeartbeat(), heartbeatInterval * 1000); - } - /** - * Stop heartbeat. - * - * Stop timer which trigger {@link HeartbeatRequest} sending with configured presence intervals. - */ - stopHeartbeatTimer() { - if (!this.heartbeatTimer) - return; - clearInterval(this.heartbeatTimer); - this.heartbeatTimer = null; - } - /** - * Send heartbeat request. - */ - sendHeartbeat() { - const heartbeatChannelGroups = Object.keys(this.heartbeatChannelGroups); - const heartbeatChannels = Object.keys(this.heartbeatChannels); - // There is no need to start heartbeat loop if there is no channels and groups to use. - if (heartbeatChannels.length === 0 && heartbeatChannelGroups.length === 0) - return; - this.heartbeatCall({ - channels: heartbeatChannels, - channelGroups: heartbeatChannelGroups, - heartbeat: this.configuration.getPresenceTimeout(), - state: this.presenceState, - }, (status) => { - if (status.error && this.configuration.announceFailedHeartbeats) - this.emitStatus(status); - if (status.error && this.configuration.autoNetworkDetection && this.isOnline) { - this.isOnline = false; - this.disconnect(); - this.emitStatus({ category: StatusCategory$1.PNNetworkDownCategory }); - this.reconnect(); - } - if (!status.error && this.configuration.announceSuccessfulHeartbeats) - this.emitStatus(status); - }); - } - } - - // endregion - /** - * Base notification payload object. - */ - class BaseNotificationPayload { - /** - * Base notification provider payload object. - * - * @internal - * - * @param payload - Object which contains vendor-specific preformatted push notification payload. - * @param title - Notification main title. - * @param body - Notification body (main messages). - */ - constructor(payload, title, body) { - this._payload = payload; - this.setDefaultPayloadStructure(); - this.title = title; - this.body = body; - } - /** - * Retrieve resulting notification payload content for message. - * - * @returns Preformatted push notification payload data. - */ - get payload() { - return this._payload; - } - /** - * Update notification title. - * - * @param value - New notification title. - */ - set title(value) { - this._title = value; - } - /** - * Update notification subtitle. - * - * @param value - New second-line notification title. - */ - set subtitle(value) { - this._subtitle = value; - } - /** - * Update notification body. - * - * @param value - Update main notification message (shown when expanded). - */ - set body(value) { - this._body = value; - } - /** - * Update application badge number. - * - * @param value - Number which should be shown in application badge upon receiving notification. - */ - set badge(value) { - this._badge = value; - } - /** - * Update notification sound. - * - * @param value - Name of the sound file which should be played upon notification receive. - */ - set sound(value) { - this._sound = value; - } - /** - * Platform-specific structure initialization. - * - * @internal - */ - setDefaultPayloadStructure() { } - /** - * Translate data object into PubNub push notification payload object. - * - * @internal - * - * @returns Preformatted push notification payload. - */ - toObject() { - return {}; - } - } - /** - * Message payload for Apple Push Notification Service. - */ - class APNSNotificationPayload extends BaseNotificationPayload { - constructor() { - super(...arguments); - /** - * Type of push notification service for which payload will be created. - * - * @internal - */ - this._apnsPushType = 'apns'; - /** - * Whether resulting payload should trigger silent notification or not. - * - * @internal - */ - this._isSilent = false; - } - get payload() { - return this._payload; - } - /** - * Update notification receivers configuration. - * - * @param value - New APNS2 configurations. - */ - set configurations(value) { - if (!value || !value.length) - return; - this._configurations = value; - } - /** - * Notification payload. - * - * @returns Platform-specific part of PubNub notification payload. - */ - get notification() { - return this.payload.aps; - } - /** - * Notification title. - * - * @returns Main notification title. - */ - get title() { - return this._title; - } - /** - * Update notification title. - * - * @param value - New notification title. - */ - set title(value) { - if (!value || !value.length) - return; - this.payload.aps.alert.title = value; - this._title = value; - } - /** - * Notification subtitle. - * - * @returns Second-line notification title. - */ - get subtitle() { - return this._subtitle; - } - /** - * Update notification subtitle. - * - * @param value - New second-line notification title. - */ - set subtitle(value) { - if (!value || !value.length) - return; - this.payload.aps.alert.subtitle = value; - this._subtitle = value; - } - /** - * Notification body. - * - * @returns Main notification message (shown when expanded). - */ - get body() { - return this._body; - } - /** - * Update notification body. - * - * @param value - Update main notification message (shown when expanded). - */ - set body(value) { - if (!value || !value.length) - return; - this.payload.aps.alert.body = value; - this._body = value; - } - /** - * Retrieve unread notifications number. - * - * @returns Number of unread notifications which should be shown on application badge. - */ - get badge() { - return this._badge; - } - /** - * Update application badge number. - * - * @param value - Number which should be shown in application badge upon receiving notification. - */ - set badge(value) { - if (value === undefined || value === null) - return; - this.payload.aps.badge = value; - this._badge = value; - } - /** - * Retrieve notification sound file. - * - * @returns Notification sound file name from resource bundle. - */ - get sound() { - return this._sound; - } - /** - * Update notification sound. - * - * @param value - Name of the sound file which should be played upon notification receive. - */ - set sound(value) { - if (!value || !value.length) - return; - this.payload.aps.sound = value; - this._sound = value; - } - /** - * Set whether notification should be silent or not. - * - * `content-available` notification type will be used to deliver silent notification if set to `true`. - * - * @param value - Whether notification should be sent as silent or not. - */ - set silent(value) { - this._isSilent = value; - } - /** - * Setup push notification payload default content. - * - * @internal - */ - setDefaultPayloadStructure() { - this.payload.aps = { alert: {} }; - } - /** - * Translate data object into PubNub push notification payload object. - * - * @internal - * - * @returns Preformatted push notification payload. - */ - toObject() { - const payload = Object.assign({}, this.payload); - const { aps } = payload; - let { alert } = aps; - if (this._isSilent) - aps['content-available'] = 1; - if (this._apnsPushType === 'apns2') { - if (!this._configurations || !this._configurations.length) - throw new ReferenceError('APNS2 configuration is missing'); - const configurations = []; - this._configurations.forEach((configuration) => { - configurations.push(this.objectFromAPNS2Configuration(configuration)); - }); - if (configurations.length) - payload.pn_push = configurations; - } - if (!alert || !Object.keys(alert).length) - delete aps.alert; - if (this._isSilent) { - delete aps.alert; - delete aps.badge; - delete aps.sound; - alert = {}; - } - return this._isSilent || (alert && Object.keys(alert).length) ? payload : null; - } - /** - * Create PubNub push notification service APNS2 configuration information object. - * - * @internal - * - * @param configuration - Source user-provided APNS2 configuration. - * - * @returns Preformatted for PubNub service APNS2 configuration information. - */ - objectFromAPNS2Configuration(configuration) { - if (!configuration.targets || !configuration.targets.length) - throw new ReferenceError('At least one APNS2 target should be provided'); - const { collapseId, expirationDate } = configuration; - const objectifiedConfiguration = { - auth_method: 'token', - targets: configuration.targets.map((target) => this.objectFromAPNSTarget(target)), - version: 'v2', - }; - if (collapseId && collapseId.length) - objectifiedConfiguration.collapse_id = collapseId; - if (expirationDate) - objectifiedConfiguration.expiration = expirationDate.toISOString(); - return objectifiedConfiguration; - } - /** - * Create PubNub push notification service APNS2 target information object. - * - * @internal - * - * @param target - Source user-provided data. - * - * @returns Preformatted for PubNub service APNS2 target information. - */ - objectFromAPNSTarget(target) { - if (!target.topic || !target.topic.length) - throw new TypeError("Target 'topic' undefined."); - const { topic, environment = 'development', excludedDevices = [] } = target; - const objectifiedTarget = { topic, environment }; - if (excludedDevices.length) - objectifiedTarget.excluded_devices = excludedDevices; - return objectifiedTarget; - } - } - /** - * Message payload for Firebase Cloud Messaging service. - */ - class FCMNotificationPayload extends BaseNotificationPayload { - get payload() { - return this._payload; - } - /** - * Notification payload. - * - * @returns Platform-specific part of PubNub notification payload. - */ - get notification() { - return this.payload.notification; - } - /** - * Silent notification payload. - * - * @returns Silent notification payload (data notification). - */ - get data() { - return this.payload.data; - } - /** - * Retrieve Android notification payload and initialize required structure. - * - * @returns Android specific notification payload. - */ - get androidNotification() { - var _c; - return (_c = this.payload.android) === null || _c === void 0 ? void 0 : _c.notification; - } - /** - * Notification title. - * - * @returns Main notification title. - */ - get title() { - return this._title; - } - /** - * Update notification title. - * - * @param value - New notification title. - */ - set title(value) { - if (!value || !value.length) - return; - this.payload.notification.title = value; - this.androidNotification.title = value; - this._title = value; - } - /** - * Notification body. - * - * @returns Main notification message (shown when expanded). - */ - get body() { - return this._body; - } - /** - * Update notification body. - * - * @param value - Update main notification message (shown when expanded). - */ - set body(value) { - if (!value || !value.length) - return; - this.payload.notification.body = value; - this.androidNotification.body = value; - this._body = value; - } - /** - * Retrieve unread notifications number. - * - * @returns Number of unread notifications which should be shown on application badge. - */ - get badge() { - return this._badge; - } - /** - * Update application badge number. - * - * @param value - Number which should be shown in application badge upon receiving notification. - */ - set badge(value) { - if (value === undefined || value === null) - return; - this.androidNotification.notification_count = value; - this._badge = value; - } - /** - * Retrieve notification sound file. - * - * @returns Notification sound file name from resource bundle. - */ - get sound() { - return this._sound; - } - /** - * Update notification sound. - * - * @param value - Name of the sound file which should be played upon notification receive. - */ - set sound(value) { - if (!value || !value.length) - return; - this.androidNotification.sound = value; - this._sound = value; - } - /** - * Retrieve notification icon file. - * - * @returns Notification icon file name from resource bundle. - */ - get icon() { - return this._icon; - } - /** - * Update notification icon. - * - * @param value - Name of the icon file set for `android.notification.icon`. - */ - set icon(value) { - if (!value || !value.length) - return; - this.androidNotification.icon = value; - this._icon = value; - } - /** - * Retrieve notifications grouping tag. - * - * @returns Notifications grouping tag. - */ - get tag() { - return this._tag; - } - /** - * Update notifications grouping tag. - * - * @param value - String set for `android.notification.tag` to group similar notifications. - */ - set tag(value) { - if (!value || !value.length) - return; - this.androidNotification.tag = value; - this._tag = value; - } - /** - * Set whether notification should be silent or not. - * - * All notification data will be sent under `data` field if set to `true`. - * - * @param value - Whether notification should be sent as silent or not. - */ - set silent(value) { - this._isSilent = value; - } - /** - * Setup push notification payload default content. - * - * @internal - */ - setDefaultPayloadStructure() { - this.payload.notification = {}; - this.payload.data = {}; - this.payload.android = { notification: {} }; - } - /** - * Translate data object into PubNub push notification payload object. - * - * @internal - * - * @returns Preformatted push notification payload. - */ - toObject() { - var _c, _e; - const payload = {}; - const notification = Object.assign({}, this.payload.notification); - const android = Object.assign({}, this.payload.android); - const androidNotification = Object.assign({}, ((_c = android.notification) !== null && _c !== void 0 ? _c : {})); - // Strip title/body from android.notification — they belong in top-level notification (or data for silent). - const androidSpecificFields = __rest(androidNotification, ["title", "body"]); - if (this._isSilent) { - // For silent (data-only) notifications, strip all `notification` fields - // (both root and android) and move everything into the root `data` object. - const data = {}; - if (this._title) - data.title = this._title; - if (this._body) - data.body = this._body; - // Merge android-specific notification fields (sound, icon, tag, etc.) into data. - for (const [key, value] of Object.entries(androidSpecificFields)) { - if (value !== undefined && value !== null) - data[key] = String(value); - } - // Merge any existing user-provided custom data. - if (this.payload.data) - Object.assign(data, this.payload.data); - if (Object.keys(data).length) - payload.data = data; - // Exclude `notification` entirely from android — only keep non-notification android fields. - delete android.notification; - if (Object.keys(android).length) { - payload.android = android; - } - } - else { - if (Object.keys(notification).length) - payload.notification = notification; - // Include top-level data if present. - if (this.payload.data && Object.keys(this.payload.data).length) - payload.data = Object.assign({}, this.payload.data); - // android.notification should only contain android-specific fields (sound, icon, tag, etc.). - if (Object.keys(androidSpecificFields).length) { - const androidWithoutNotification = __rest(android, ["notification"]); - payload.android = Object.assign(Object.assign({}, androidWithoutNotification), { notification: androidSpecificFields }); - } - else { - const androidWithoutNotification = __rest(android, ["notification"]); - if (Object.keys(androidWithoutNotification).length) { - payload.android = androidWithoutNotification; - } - } - } - // Preserve other top-level FCM fields (apns, webpush, fcm_options, etc.). - const _f = this.payload, otherFields = __rest(_f, ["notification", "android", "data", "pn_exceptions"]); - Object.assign(payload, otherFields); - if ((_e = this.payload.pn_exceptions) === null || _e === void 0 ? void 0 : _e.length) - payload.pn_exceptions = this.payload.pn_exceptions; - return Object.keys(payload).length ? payload : null; - } - } - class NotificationsPayload { - /** - * Create push notification payload holder. - * - * @internal - * - * @param title - String which will be shown at the top of the notification (below app name). - * @param body - String with message which should be shown when user will check notification. - */ - constructor(title, body) { - this._payload = { apns: {}, fcm: {} }; - this._title = title; - this._body = body; - this.apns = new APNSNotificationPayload(this._payload.apns, title, body); - this.fcm = new FCMNotificationPayload(this._payload.fcm, title, body); - } - /** - * Enable or disable push notification debugging message. - * - * @param value - Whether debug message from push notification scheduler should be published to the specific - * channel or not. - */ - set debugging(value) { - this._debugging = value; - } - /** - * Notification title. - * - * @returns Main notification title. - */ - get title() { - return this._title; - } - /** - * Notification subtitle. - * - * @returns Second-line notification title. - */ - get subtitle() { - return this._subtitle; - } - /** - * Update notification subtitle. - * - * @param value - New second-line notification title. - */ - set subtitle(value) { - this._subtitle = value; - this.apns.subtitle = value; - this.fcm.subtitle = value; - } - /** - * Notification body. - * - * @returns Main notification message (shown when expanded). - */ - get body() { - return this._body; - } - /** - * Retrieve unread notifications number. - * - * @returns Number of unread notifications which should be shown on application badge. - */ - get badge() { - return this._badge; - } - /** - * Update application badge number. - * - * @param value - Number which should be shown in application badge upon receiving notification. - */ - set badge(value) { - this._badge = value; - this.apns.badge = value; - this.fcm.badge = value; - } - /** - * Retrieve notification sound file. - * - * @returns Notification sound file name from resource bundle. - */ - get sound() { - return this._sound; - } - /** - * Update notification sound. - * - * @param value - Name of the sound file which should be played upon notification receive. - */ - set sound(value) { - this._sound = value; - this.apns.sound = value; - this.fcm.sound = value; - } - /** - * Build notifications platform for requested platforms. - * - * @param platforms - List of platforms for which payload should be added to final dictionary. Supported values: - * fcm, apns, and apns2. - * - * @returns Object with data, which can be sent with publish method call and trigger remote notifications for - * specified platforms. - */ - buildPayload(platforms) { - const payload = {}; - if (platforms.includes('apns') || platforms.includes('apns2')) { - // @ts-expect-error Override APNS version. - this.apns._apnsPushType = platforms.includes('apns') ? 'apns' : 'apns2'; - const apnsPayload = this.apns.toObject(); - if (apnsPayload && Object.keys(apnsPayload).length) - payload.pn_apns = apnsPayload; - } - if (platforms.includes('fcm')) { - const fcmPayload = this.fcm.toObject(); - if (fcmPayload && Object.keys(fcmPayload).length) - payload.pn_fcm = fcmPayload; - } - if (Object.keys(payload).length && this._debugging) - payload.pn_debug = true; - return payload; - } - } - - /** - * Event Engine terminate signal listener module. - * - * @internal - */ - /** - * @internal - */ - class Subject { - constructor(sync = false) { - this.sync = sync; - this.listeners = new Set(); - } - subscribe(listener) { - this.listeners.add(listener); - return () => { - this.listeners.delete(listener); - }; - } - notify(event) { - const wrapper = () => { - this.listeners.forEach((listener) => { - listener(event); - }); - }; - if (this.sync) { - wrapper(); - } - else { - setTimeout(wrapper, 0); - } - } - } - - /** - * Event Engine Core state module. - * - * @internal - */ - /** - * Event engine current state object. - * - * State contains current context and list of invocations which should be performed by the Event Engine. - * - * @internal - */ - class State { - transition(context, event) { - var _a; - if (this.transitionMap.has(event.type)) { - return (_a = this.transitionMap.get(event.type)) === null || _a === void 0 ? void 0 : _a(context, event); - } - return undefined; - } - constructor(label) { - this.label = label; - this.transitionMap = new Map(); - this.enterEffects = []; - this.exitEffects = []; - } - on(eventType, transition) { - this.transitionMap.set(eventType, transition); - return this; - } - with(context, effects) { - return [this, context, effects !== null && effects !== void 0 ? effects : []]; - } - onEnter(effect) { - this.enterEffects.push(effect); - return this; - } - onExit(effect) { - this.exitEffects.push(effect); - return this; - } - } - - /** - * Event Engine Core module. - * - * @internal - */ - /** - * Generic event engine. - * - * @internal - */ - class Engine extends Subject { - constructor(logger) { - super(true); - this.logger = logger; - this._pendingEvents = []; - this._inTransition = false; - } - get currentState() { - return this._currentState; - } - get currentContext() { - return this._currentContext; - } - describe(label) { - return new State(label); - } - start(initialState, initialContext) { - this._currentState = initialState; - this._currentContext = initialContext; - this.notify({ - type: 'engineStarted', - state: initialState, - context: initialContext, - }); - return; - } - transition(event) { - if (!this._currentState) { - this.logger.error('Engine', 'Finite state machine is not started'); - throw new Error('Start the engine first'); - } - if (this._inTransition) { - this.logger.trace('Engine', () => ({ - messageType: 'object', - message: event, - details: 'Event engine in transition. Enqueue received event:', - })); - this._pendingEvents.push(event); - return; - } - else - this._inTransition = true; - this.logger.trace('Engine', () => ({ - messageType: 'object', - message: event, - details: 'Event engine received event:', - })); - this.notify({ - type: 'eventReceived', - event: event, - }); - const transition = this._currentState.transition(this._currentContext, event); - if (transition) { - const [newState, newContext, effects] = transition; - this.logger.trace('Engine', `Exiting state: ${this._currentState.label}`); - for (const effect of this._currentState.exitEffects) { - this.notify({ - type: 'invocationDispatched', - invocation: effect(this._currentContext), - }); - } - this.logger.trace('Engine', () => ({ - messageType: 'object', - details: `Entering '${newState.label}' state with context:`, - message: newContext, - })); - const oldState = this._currentState; - this._currentState = newState; - const oldContext = this._currentContext; - this._currentContext = newContext; - this.notify({ - type: 'transitionDone', - fromState: oldState, - fromContext: oldContext, - toState: newState, - toContext: newContext, - event: event, - }); - for (const effect of effects) { - this.notify({ - type: 'invocationDispatched', - invocation: effect, - }); - } - for (const effect of this._currentState.enterEffects) { - this.notify({ - type: 'invocationDispatched', - invocation: effect(this._currentContext), - }); - } - } - else - this.logger.warn('Engine', `No transition from '${this._currentState.label}' found for event: ${event.type}`); - this._inTransition = false; - // Check whether a pending task should be dequeued. - if (this._pendingEvents.length > 0) { - const nextEvent = this._pendingEvents.shift(); - if (nextEvent) { - this.logger.trace('Engine', () => ({ - messageType: 'object', - message: nextEvent, - details: 'De-queueing pending event:', - })); - this.transition(nextEvent); - } - } - } - } - - /** - * Event Engine Core Effects dispatcher module. - * - * @internal - */ - /** - * Event Engine effects dispatcher. - * - * Dispatcher responsible for invocation enqueue and dequeue for processing. - * - * @internal - */ - class Dispatcher { - constructor(dependencies, logger) { - this.dependencies = dependencies; - this.logger = logger; - this.instances = new Map(); - this.handlers = new Map(); - } - on(type, handlerCreator) { - this.handlers.set(type, handlerCreator); - } - dispatch(invocation) { - this.logger.trace('Dispatcher', `Process invocation: ${invocation.type}`); - if (invocation.type === 'CANCEL') { - if (this.instances.has(invocation.payload)) { - const instance = this.instances.get(invocation.payload); - instance === null || instance === void 0 ? void 0 : instance.cancel(); - this.instances.delete(invocation.payload); - } - return; - } - const handlerCreator = this.handlers.get(invocation.type); - if (!handlerCreator) { - this.logger.error('Dispatcher', `Unhandled invocation '${invocation.type}'`); - throw new Error(`Unhandled invocation '${invocation.type}'`); - } - const instance = handlerCreator(invocation.payload, this.dependencies); - this.logger.trace('Dispatcher', () => ({ - messageType: 'object', - details: 'Call invocation handler with parameters:', - message: invocation.payload, - ignoredKeys: ['abortSignal'], - })); - if (invocation.managed) { - this.instances.set(invocation.type, instance); - } - instance.start(); - } - dispose() { - for (const [key, instance] of this.instances.entries()) { - instance.cancel(); - this.instances.delete(key); - } - } - } - - /** - * Event Engine Core types module. - * - * @internal - */ - /** - * Create and configure event engine event. - * - * @internal - */ - function createEvent(type, fn) { - const creator = function (...args) { - return { - type, - payload: fn === null || fn === void 0 ? void 0 : fn(...args), - }; - }; - creator.type = type; - return creator; - } - /** - * Create and configure short-term effect invocation. - * - * @internal - */ - function createEffect(type, fn) { - const creator = (...args) => { - return { type, payload: fn(...args), managed: false }; - }; - creator.type = type; - return creator; - } - /** - * Create and configure long-running effect invocation. - * - * @internal - */ - function createManagedEffect(type, fn) { - const creator = (...args) => { - return { type, payload: fn(...args), managed: true }; - }; - creator.type = type; - creator.cancel = { type: 'CANCEL', payload: type, managed: false }; - return creator; - } - - /** - * Event Engine managed effects terminate signal module. - * - * @internal - */ - class AbortError extends Error { - constructor() { - super('The operation was aborted.'); - this.name = 'AbortError'; - Object.setPrototypeOf(this, new.target.prototype); - } - } - /** - * Event Engine stored effect processing cancellation signal. - * - * @internal - */ - class AbortSignal extends Subject { - constructor() { - super(...arguments); - this._aborted = false; - } - get aborted() { - return this._aborted; - } - throwIfAborted() { - if (this._aborted) { - throw new AbortError(); - } - } - abort() { - this._aborted = true; - this.notify(new AbortError()); - } - } - - /** - * Event Engine Core Effects handler module. - * - * @internal - */ - /** - * Synchronous (short-term) effect invocation handler. - * - * Handler manages effect execution on behalf of effect dispatcher. - * - * @internal - */ - class Handler { - constructor(payload, dependencies) { - this.payload = payload; - this.dependencies = dependencies; - } - } - /** - * Asynchronous (long-running) effect invocation handler. - * - * Handler manages effect execution on behalf of effect dispatcher. - * - * @internal - */ - class AsyncHandler extends Handler { - constructor(payload, dependencies, asyncFunction) { - super(payload, dependencies); - this.asyncFunction = asyncFunction; - this.abortSignal = new AbortSignal(); - } - start() { - this.asyncFunction(this.payload, this.abortSignal, this.dependencies).catch((error) => { - // swallow the error - }); - } - cancel() { - this.abortSignal.abort(); - } - } - /** - * Asynchronous effect invocation handler constructor. - * - * @param handlerFunction - Function which performs asynchronous action and should be called on `start`. - * - * @internal - */ - const asyncHandler = (handlerFunction) => (payload, dependencies) => new AsyncHandler(payload, dependencies, handlerFunction); - - /** - * Presence Event Engine effects module. - * - * @internal - */ - /** - * Presence heartbeat effect. - * - * Performs presence heartbeat REST API call. - * - * @internal - */ - const heartbeat = createManagedEffect('HEARTBEAT', (channels, groups) => ({ - channels, - groups, - })); - /** - * Presence leave effect. - * - * Performs presence leave REST API call. - * - * @internal - */ - const leave = createEffect('LEAVE', (channels, groups) => ({ - channels, - groups, - })); - /** - * Emit presence heartbeat REST API call result status effect. - * - * Notify status change event listeners. - * - * @internal - */ - /* eslint-disable @typescript-eslint/no-explicit-any */ - const emitStatus$1 = createEffect('EMIT_STATUS', (status) => status); - /** - * Heartbeat delay effect. - * - * Delay of configured length (heartbeat interval) before another heartbeat REST API call will be done. - * - * @internal - */ - const wait = createManagedEffect('WAIT', () => ({})); - - /** - * Presence Event Engine events module. - * - * @internal - */ - /** - * Reconnect event. - * - * Event is sent each time when user restores real-time updates processing and notifies other present subscribers - * about joining back. - * - * @internal - */ - const reconnect$1 = createEvent('RECONNECT', () => ({})); - /** - * Disconnect event. - * - * Event is sent when user wants to temporarily stop real-time updates processing and notifies other present - * subscribers about leaving. - * - * @internal - */ - const disconnect$1 = createEvent('DISCONNECT', (isOffline = false) => ({ isOffline })); - /** - * Channel / group join event. - * - * Event is sent when user adds new channels / groups to the active channels / groups list and notifies other present - * subscribers about joining. - * - * @internal - */ - const joined = createEvent('JOINED', (channels, groups) => ({ - channels, - groups, - })); - /** - * Channel / group leave event. - * - * Event is sent when user removes channels / groups from the active channels / groups list and notifies other present - * subscribers about leaving. - * - * @internal - */ - const left = createEvent('LEFT', (channels, groups) => ({ - channels, - groups, - })); - /** - * Leave all event. - * - * Event is sent when user doesn't want to receive any real-time updates anymore and notifies other - * subscribers on previously active channels / groups about leaving. - * - * @internal - */ - const leftAll = createEvent('LEFT_ALL', (isOffline = false) => ({ isOffline })); - /** - * Presence heartbeat success event. - * - * Event is sent by corresponding effect handler if REST API call was successful. - * - * @internal - */ - const heartbeatSuccess = createEvent('HEARTBEAT_SUCCESS', (statusCode) => ({ statusCode })); - /** - * Presence heartbeat did fail event. - * - * Event is sent by corresponding effect handler if REST API call failed. - * - * @internal - */ - const heartbeatFailure = createEvent('HEARTBEAT_FAILURE', (error) => error); - /** - * Delayed presence heartbeat event. - * - * Event is sent by corresponding effect handler when delay timer between heartbeat calls fired. - * - * @internal - */ - const timesUp = createEvent('TIMES_UP', () => ({})); - - /** - * Presence Event Engine effects dispatcher. - * - * @internal - */ - /** - * Presence Event Engine dispatcher. - * - * Dispatcher responsible for presence events handling and corresponding effects execution. - * - * @internal - */ - class PresenceEventEngineDispatcher extends Dispatcher { - constructor(engine, dependencies) { - super(dependencies, dependencies.config.logger()); - this.on(heartbeat.type, asyncHandler((payload_1, abortSignal_1, _a) => __awaiter(this, [payload_1, abortSignal_1, _a], void 0, function* (payload, abortSignal, { heartbeat, presenceState, config }) { - abortSignal.throwIfAborted(); - try { - const result = yield heartbeat(Object.assign(Object.assign({ abortSignal: abortSignal, channels: payload.channels, channelGroups: payload.groups }, (config.maintainPresenceState && { state: presenceState })), { heartbeat: config.presenceTimeout })); - engine.transition(heartbeatSuccess(200)); - } - catch (e) { - if (e instanceof PubNubError) { - if (e.status && e.status.category == StatusCategory$1.PNCancelledCategory) - return; - engine.transition(heartbeatFailure(e)); - } - } - }))); - this.on(leave.type, asyncHandler((payload_1, _1, _a) => __awaiter(this, [payload_1, _1, _a], void 0, function* (payload, _, { leave, config }) { - if (!config.suppressLeaveEvents) { - try { - leave({ - channels: payload.channels, - channelGroups: payload.groups, - }); - } - catch (e) { } - } - }))); - this.on(wait.type, asyncHandler((_1, abortSignal_1, _a) => __awaiter(this, [_1, abortSignal_1, _a], void 0, function* (_, abortSignal, { heartbeatDelay }) { - const { cancelDelay, promise } = heartbeatDelay(); - abortSignal.throwIfAborted(); - const unsubscribeAbortListener = abortSignal.subscribe(() => cancelDelay()); - yield promise; - unsubscribeAbortListener(); - abortSignal.throwIfAborted(); - return engine.transition(timesUp()); - }))); - this.on(emitStatus$1.type, asyncHandler((payload_1, _1, _a) => __awaiter(this, [payload_1, _1, _a], void 0, function* (payload, _, { emitStatus, config }) { - if (config.announceFailedHeartbeats && (payload === null || payload === void 0 ? void 0 : payload.error) === true) { - emitStatus(Object.assign(Object.assign({}, payload), { operation: RequestOperation$1.PNHeartbeatOperation })); - } - else if (config.announceSuccessfulHeartbeats && payload.statusCode === 200) { - emitStatus(Object.assign(Object.assign({}, payload), { error: false, operation: RequestOperation$1.PNHeartbeatOperation, category: StatusCategory$1.PNAcknowledgmentCategory })); - } - }))); - } - } - - /** - * Presence Event Engine state instances. - * - * Isolated from transition handlers so state modules can import sibling states - * without creating circular dependencies. - * - * @internal - */ - /** @internal */ - const HeartbeatInactiveState = new State('HEARTBEAT_INACTIVE'); - /** @internal */ - const HeartbeatingState = new State('HEARTBEATING'); - /** @internal */ - const HeartbeatCooldownState = new State('HEARTBEAT_COOLDOWN'); - /** @internal */ - const HeartbeatStoppedState = new State('HEARTBEAT_STOPPED'); - /** @internal */ - const HeartbeatFailedState = new State('HEARTBEAT_FAILED'); - - /** - * Inactive heratbeating state module. - * - * @internal - */ - /** - * Inactive heratbeating state - * - * State in which Presence Event Engine doesn't process any heartbeat requests (initial state). - * - * @internal - */ - HeartbeatInactiveState.on(joined.type, (_, event) => HeartbeatingState.with({ - channels: event.payload.channels, - groups: event.payload.groups, - })); - - /** - * Heartbeating state module. - * - * @internal - */ - /** - * Heartbeating state module. - * - * State in which Presence Event Engine send heartbeat REST API call. - * - * @internal - */ - HeartbeatingState.onEnter((context) => heartbeat(context.channels, context.groups)); - HeartbeatingState.onExit(() => heartbeat.cancel); - HeartbeatingState.on(heartbeatSuccess.type, (context, event) => HeartbeatCooldownState.with({ channels: context.channels, groups: context.groups }, [ - emitStatus$1(Object.assign({}, event.payload)), - ])); - HeartbeatingState.on(joined.type, (context, event) => HeartbeatingState.with({ - channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], - groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], - })); - HeartbeatingState.on(left.type, (context, event) => { - return HeartbeatingState.with({ - channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), - groups: context.groups.filter((group) => !event.payload.groups.includes(group)), - }, [leave(event.payload.channels, event.payload.groups)]); - }); - HeartbeatingState.on(heartbeatFailure.type, (context, event) => HeartbeatFailedState.with(Object.assign({}, context), [ - ...(event.payload.status ? [emitStatus$1(Object.assign({}, event.payload.status))] : []), - ])); - HeartbeatingState.on(disconnect$1.type, (context, event) => HeartbeatStoppedState.with({ channels: context.channels, groups: context.groups }, [ - ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), - ])); - HeartbeatingState.on(leftAll.type, (context, event) => HeartbeatInactiveState.with(undefined, [ - ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), - ])); - - /** - * Waiting next heartbeat state module. - * - * @internal - */ - /** - * Waiting next heartbeat state. - * - * State in which Presence Event Engine is waiting when delay will run out and next heartbeat call should be done. - * - * @internal - */ - HeartbeatCooldownState.onEnter(() => wait()); - HeartbeatCooldownState.onExit(() => wait.cancel); - HeartbeatCooldownState.on(timesUp.type, (context, _) => HeartbeatingState.with({ - channels: context.channels, - groups: context.groups, - })); - HeartbeatCooldownState.on(joined.type, (context, event) => HeartbeatingState.with({ - channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], - groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], - })); - HeartbeatCooldownState.on(left.type, (context, event) => HeartbeatingState.with({ - channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), - groups: context.groups.filter((group) => !event.payload.groups.includes(group)), - }, [leave(event.payload.channels, event.payload.groups)])); - HeartbeatCooldownState.on(disconnect$1.type, (context, event) => HeartbeatStoppedState.with({ channels: context.channels, groups: context.groups }, [ - ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), - ])); - HeartbeatCooldownState.on(leftAll.type, (context, event) => HeartbeatInactiveState.with(undefined, [ - ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), - ])); - - /** - * Heartbeat stopped state module. - * - * @internal - */ - /** - * Heartbeat stopped state. - * - * State in which Presence Event Engine still has information about active channels / groups, but doesn't wait for - * delayed heartbeat request sending. - * - * @internal - */ - HeartbeatStoppedState.on(joined.type, (context, event) => HeartbeatStoppedState.with({ - channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], - groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], - })); - HeartbeatStoppedState.on(left.type, (context, event) => HeartbeatStoppedState.with({ - channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), - groups: context.groups.filter((group) => !event.payload.groups.includes(group)), - })); - HeartbeatStoppedState.on(reconnect$1.type, (context, _) => HeartbeatingState.with({ - channels: context.channels, - groups: context.groups, - })); - HeartbeatStoppedState.on(leftAll.type, (context, _) => HeartbeatInactiveState.with(undefined)); - - /** - * Failed to heartbeat state module. - * - * @internal - */ - /** - * Failed to heartbeat state. - * - * State in which Subscription Event Engine waits for user to try to reconnect after all retry attempts has been - * exhausted. - * - * @internal - */ - HeartbeatFailedState.on(joined.type, (context, event) => HeartbeatingState.with({ - channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], - groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], - })); - HeartbeatFailedState.on(left.type, (context, event) => HeartbeatingState.with({ - channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), - groups: context.groups.filter((group) => !event.payload.groups.includes(group)), - }, [leave(event.payload.channels, event.payload.groups)])); - HeartbeatFailedState.on(reconnect$1.type, (context, _) => HeartbeatingState.with({ - channels: context.channels, - groups: context.groups, - })); - HeartbeatFailedState.on(disconnect$1.type, (context, event) => HeartbeatStoppedState.with({ channels: context.channels, groups: context.groups }, [ - ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), - ])); - HeartbeatFailedState.on(leftAll.type, (context, event) => HeartbeatInactiveState.with(undefined, [ - ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), - ])); - - /** - * Presence Event Engine module. - * - * @internal - */ - /** - * Presence Event Engine Core. - * - * @internal - */ - class PresenceEventEngine { - get _engine() { - return this.engine; - } - constructor(dependencies) { - this.dependencies = dependencies; - this.channels = []; - this.groups = []; - this.engine = new Engine(dependencies.config.logger()); - this.dispatcher = new PresenceEventEngineDispatcher(this.engine, dependencies); - dependencies.config.logger().debug('PresenceEventEngine', 'Create presence event engine.'); - this._unsubscribeEngine = this.engine.subscribe((change) => { - if (change.type === 'invocationDispatched') { - this.dispatcher.dispatch(change.invocation); - } - }); - this.engine.start(HeartbeatInactiveState, undefined); - } - join({ channels, groups }) { - this.channels = [...this.channels, ...(channels !== null && channels !== void 0 ? channels : []).filter((channel) => !this.channels.includes(channel))]; - this.groups = [...this.groups, ...(groups !== null && groups !== void 0 ? groups : []).filter((group) => !this.groups.includes(group))]; - // Don't make any transitions if there is no channels and groups. - if (this.channels.length === 0 && this.groups.length === 0) - return; - this.engine.transition(joined(this.channels.slice(0), this.groups.slice(0))); - } - leave({ channels, groups }) { - // Update internal channel tracking to prevent stale heartbeat requests - if (channels) - this.channels = this.channels.filter((channel) => !channels.includes(channel)); - if (groups) - this.groups = this.groups.filter((group) => !groups.includes(group)); - if (this.dependencies.presenceState) { - channels === null || channels === void 0 ? void 0 : channels.forEach((c) => delete this.dependencies.presenceState[c]); - groups === null || groups === void 0 ? void 0 : groups.forEach((g) => delete this.dependencies.presenceState[g]); - } - this.engine.transition(left(channels !== null && channels !== void 0 ? channels : [], groups !== null && groups !== void 0 ? groups : [])); - } - leaveAll(isOffline = false) { - // Clear presence state for all current channels and groups - if (this.dependencies.presenceState) { - this.channels.forEach((c) => delete this.dependencies.presenceState[c]); - this.groups.forEach((g) => delete this.dependencies.presenceState[g]); - } - // Reset internal channel and group tracking - this.channels = []; - this.groups = []; - this.engine.transition(leftAll(isOffline)); - } - reconnect() { - this.engine.transition(reconnect$1()); - } - disconnect(isOffline = false) { - this.engine.transition(disconnect$1(isOffline)); - } - dispose() { - this.disconnect(true); - this._unsubscribeEngine(); - this.dispatcher.dispose(); - } - } - - /** - * Subscribe Event Engine events module. - * - * @internal - */ - /** - * Subscription list change event. - * - * Event is sent each time when the user would like to change a list of active channels / groups. - * - * @internal - */ - const subscriptionChange = createEvent('SUBSCRIPTION_CHANGED', (channels, groups, isOffline = false) => ({ - channels, - groups, - isOffline, - })); - /** - * Subscription loop restore. - * - * Event is sent when a user would like to try to catch up on missed updates by providing specific timetoken. - * - * @internal - */ - const restore = createEvent('SUBSCRIPTION_RESTORED', (channels, groups, timetoken, region) => ({ - channels, - groups, - cursor: { - timetoken: timetoken, - region: region !== null && region !== void 0 ? region : 0, - }, - })); - /** - * Initial subscription handshake success event. - * - * Event is sent by the corresponding effect handler if the REST API call was successful. - * - * @internal - */ - const handshakeSuccess = createEvent('HANDSHAKE_SUCCESS', (cursor) => cursor); - /** - * The initial subscription handshake did fail event. - * - * Event is sent by the corresponding effect handler if the REST API call failed. - * - * @internal - */ - const handshakeFailure = createEvent('HANDSHAKE_FAILURE', (error) => error); - /** - * Subscription successfully received real-time updates event. - * - * Event is sent by the corresponding effect handler if the REST API call was successful. - * - * @internal - */ - const receiveSuccess = createEvent('RECEIVE_SUCCESS', (cursor, events) => ({ - cursor, - events, - })); - /** - * Subscription did fail to receive real-time updates event. - * - * Event is sent by the corresponding effect handler if the REST API call failed. - * - * @internal - */ - const receiveFailure = createEvent('RECEIVE_FAILURE', (error) => error); - /** - * Client disconnect event. - * - * Event is sent when the user wants to temporarily stop real-time updates receive. - * - * @internal - */ - const disconnect = createEvent('DISCONNECT', (isOffline = false) => ({ isOffline })); - /** - * Client reconnect event. - * - * Event is sent when the user wants to restore real-time updates receive. - * - * @internal - */ - const reconnect = createEvent('RECONNECT', (timetoken, region) => ({ - cursor: { - timetoken: timetoken !== null && timetoken !== void 0 ? timetoken : '', - region: region !== null && region !== void 0 ? region : 0, - }, - })); - /** - * Completely stop real-time updates receive event. - * - * Event is sent when the user doesn't want to receive any real-time updates anymore. - * - * @internal - */ - const unsubscribeAll = createEvent('UNSUBSCRIBE_ALL', () => ({})); - - /** - * Subscribe Event Engine state instances. - * - * Isolated from transition handlers so state modules can import sibling states - * without creating circular dependencies. - * - * @internal - */ - /** @internal */ - const UnsubscribedState = new State('UNSUBSCRIBED'); - /** @internal */ - const HandshakingState = new State('HANDSHAKING'); - /** @internal */ - const HandshakeStoppedState = new State('HANDSHAKE_STOPPED'); - /** @internal */ - const HandshakeFailedState = new State('HANDSHAKE_FAILED'); - /** @internal */ - const ReceivingState = new State('RECEIVING'); - /** @internal */ - const ReceiveStoppedState = new State('RECEIVE_STOPPED'); - /** @internal */ - const ReceiveFailedState = new State('RECEIVE_FAILED'); - - /** - * Unsubscribed / disconnected state module. - * - * @internal - */ - /** - * Unsubscribed / disconnected state. - * - * State in which Subscription Event Engine doesn't process any real-time updates. - * - * @internal - */ - UnsubscribedState.on(subscriptionChange.type, (_, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ channels: payload.channels, groups: payload.groups, onDemand: true }); - }); - UnsubscribedState.on(restore.type, (_, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region }, - onDemand: true, - }); - }); - - /** - * Subscribe Event Engine effects module. - * - * @internal - */ - /** - * Initial subscription effect. - * - * Performs subscribe REST API call with `tt=0`. - * - * @internal - */ - const handshake = createManagedEffect('HANDSHAKE', (channels, groups, onDemand) => ({ - channels, - groups, - onDemand, - })); - /** - * Real-time updates receive effect. - * - * Performs sequential subscribe REST API call with `tt` set to the value received from the previous subscribe - * REST API call. - * - * @internal - */ - const receiveMessages = createManagedEffect('RECEIVE_MESSAGES', (channels, groups, cursor, onDemand) => ({ - channels, - groups, - cursor, - onDemand, - })); - /** - * Emit real-time updates effect. - * - * Notify event listeners about updates for which listener handlers has been provided. - * - * @internal - */ - const emitMessages = createEffect('EMIT_MESSAGES', (cursor, events) => ({ - cursor, - events, - })); - /** - * Emit subscription status change effect. - * - * Notify status change event listeners. - * - * @internal - */ - const emitStatus = createEffect('EMIT_STATUS', (status) => status); - - /** - * Initial subscription handshake (disconnected) state. - * - * @internal - */ - /** - * Initial subscription handshake (disconnected) state. - * - * State in which Subscription Event Engine tries to receive the subscription cursor for the next sequential - * subscribe REST API calls. - * - * @internal - */ - HandshakingState.onEnter((context) => { var _a; return handshake(context.channels, context.groups, (_a = context.onDemand) !== null && _a !== void 0 ? _a : false); }); - HandshakingState.onExit(() => handshake.cancel); - HandshakingState.on(subscriptionChange.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: context.cursor, - onDemand: true, - }); - }); - HandshakingState.on(handshakeSuccess.type, (context, { payload }) => { - var _a, _b, _c, _d, _e; - return ReceivingState.with({ - channels: context.channels, - groups: context.groups, - cursor: { - timetoken: !!((_a = context.cursor) === null || _a === void 0 ? void 0 : _a.timetoken) ? (_b = context.cursor) === null || _b === void 0 ? void 0 : _b.timetoken : payload.timetoken, - region: payload.region, - }, - referenceTimetoken: referenceSubscribeTimetoken(payload.timetoken, (_c = context.cursor) === null || _c === void 0 ? void 0 : _c.timetoken), - }, [ - emitStatus({ - category: StatusCategory$1.PNConnectedCategory, - affectedChannels: context.channels.slice(0), - affectedChannelGroups: context.groups.slice(0), - operation: RequestOperation$1.PNSubscribeOperation, - currentTimetoken: !!((_d = context.cursor) === null || _d === void 0 ? void 0 : _d.timetoken) ? (_e = context.cursor) === null || _e === void 0 ? void 0 : _e.timetoken : payload.timetoken, - }), - ]); - }); - HandshakingState.on(handshakeFailure.type, (context, event) => { - var _a; - return HandshakeFailedState.with(Object.assign(Object.assign({}, context), { reason: event.payload }), [ - emitStatus({ category: StatusCategory$1.PNConnectionErrorCategory, error: (_a = event.payload.status) === null || _a === void 0 ? void 0 : _a.category }), - ]); - }); - HandshakingState.on(disconnect.type, (context, event) => { - var _a; - if (!event.payload.isOffline) - return HandshakeStoppedState.with(Object.assign({}, context)); - else { - const errorReason = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation); - return HandshakeFailedState.with(Object.assign(Object.assign({}, context), { reason: errorReason }), [ - emitStatus({ - category: StatusCategory$1.PNConnectionErrorCategory, - error: (_a = errorReason.status) === null || _a === void 0 ? void 0 : _a.category, - }), - ]); - } - }); - HandshakingState.on(restore.type, (context, { payload }) => { - var _a; - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || ((_a = context === null || context === void 0 ? void 0 : context.cursor) === null || _a === void 0 ? void 0 : _a.region) || 0 }, - onDemand: true, - }); - }); - HandshakingState.on(unsubscribeAll.type, (_) => UnsubscribedState.with()); - - /** - * Stopped initial subscription handshake (disconnected) state. - * - * @internal - */ - /** - * Stopped initial subscription handshake (disconnected) state. - * - * State in which Subscription Event Engine still has information about subscription but doesn't have subscription - * cursor for next sequential subscribe REST API call. - * - * @internal - */ - HandshakeStoppedState.on(subscriptionChange.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakeStoppedState.with({ channels: payload.channels, groups: payload.groups, cursor: context.cursor }); - }); - HandshakeStoppedState.on(reconnect.type, (context, { payload }) => HandshakingState.with(Object.assign(Object.assign({}, context), { cursor: payload.cursor || context.cursor, onDemand: true }))); - HandshakeStoppedState.on(restore.type, (context, { payload }) => { - var _a; - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakeStoppedState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || ((_a = context.cursor) === null || _a === void 0 ? void 0 : _a.region) || 0 }, - }); - }); - HandshakeStoppedState.on(unsubscribeAll.type, (_) => UnsubscribedState.with()); - - /** - * Failed initial subscription handshake (disconnected) state. - * - * @internal - */ - /** - * Failed initial subscription handshake (disconnected) state. - * - * State in which Subscription Event Engine waits for user to try to reconnect after all retry attempts has been - * exhausted. - * - * @internal - */ - HandshakeFailedState.on(subscriptionChange.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: context.cursor, - onDemand: true, - }); - }); - HandshakeFailedState.on(reconnect.type, (context, { payload }) => HandshakingState.with(Object.assign(Object.assign({}, context), { cursor: payload.cursor || context.cursor, onDemand: true }))); - HandshakeFailedState.on(restore.type, (context, { payload }) => { - var _a, _b; - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { - timetoken: `${payload.cursor.timetoken}`, - region: payload.cursor.region ? payload.cursor.region : ((_b = (_a = context === null || context === void 0 ? void 0 : context.cursor) === null || _a === void 0 ? void 0 : _a.region) !== null && _b !== void 0 ? _b : 0), - }, - onDemand: true, - }); - }); - HandshakeFailedState.on(unsubscribeAll.type, (_) => UnsubscribedState.with()); - - /** - * Receiving real-time updates (connected) state module. - * - * @internal - */ - /** - * Receiving real-time updates (connected) state. - * - * State in which Subscription Event Engine processes any real-time updates. - * - * @internal - */ - ReceivingState.onEnter((context) => { var _a; return receiveMessages(context.channels, context.groups, context.cursor, (_a = context.onDemand) !== null && _a !== void 0 ? _a : false); }); - ReceivingState.onExit(() => receiveMessages.cancel); - ReceivingState.on(receiveSuccess.type, (context, { payload }) => ReceivingState.with({ - channels: context.channels, - groups: context.groups, - cursor: payload.cursor, - referenceTimetoken: referenceSubscribeTimetoken(payload.cursor.timetoken), - }, [emitMessages(context.cursor, payload.events)])); - ReceivingState.on(subscriptionChange.type, (context, { payload }) => { - var _a; - if (payload.channels.length === 0 && payload.groups.length === 0) { - let errorCategory; - if (payload.isOffline) - errorCategory = (_a = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation).status) === null || _a === void 0 ? void 0 : _a.category; - return UnsubscribedState.with(undefined, [ - emitStatus(Object.assign({ category: !payload.isOffline - ? StatusCategory$1.PNDisconnectedCategory - : StatusCategory$1.PNDisconnectedUnexpectedlyCategory, operation: RequestOperation$1.PNUnsubscribeOperation }, (errorCategory ? { error: errorCategory } : {}))), - ]); - } - return ReceivingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: context.cursor, - referenceTimetoken: context.referenceTimetoken, - onDemand: true, - }, [ - emitStatus({ - category: StatusCategory$1.PNSubscriptionChangedCategory, - affectedChannels: payload.channels.slice(0), - affectedChannelGroups: payload.groups.slice(0), - currentTimetoken: context.cursor.timetoken, - }), - ]); - }); - ReceivingState.on(restore.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined, [emitStatus({ category: StatusCategory$1.PNDisconnectedCategory })]); - return ReceivingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || context.cursor.region }, - referenceTimetoken: referenceSubscribeTimetoken(context.cursor.timetoken, `${payload.cursor.timetoken}`, context.referenceTimetoken), - onDemand: true, - }, [ - emitStatus({ - category: StatusCategory$1.PNSubscriptionChangedCategory, - affectedChannels: payload.channels.slice(0), - affectedChannelGroups: payload.groups.slice(0), - currentTimetoken: payload.cursor.timetoken, - }), - ]); - }); - ReceivingState.on(receiveFailure.type, (context, { payload }) => { - var _a; - return ReceiveFailedState.with(Object.assign(Object.assign({}, context), { reason: payload }), [ - emitStatus({ category: StatusCategory$1.PNDisconnectedUnexpectedlyCategory, error: (_a = payload.status) === null || _a === void 0 ? void 0 : _a.category }), - ]); - }); - ReceivingState.on(disconnect.type, (context, event) => { - var _a; - if (!event.payload.isOffline) { - return ReceiveStoppedState.with(Object.assign({}, context), [ - emitStatus({ - category: StatusCategory$1.PNDisconnectedCategory, - operation: RequestOperation$1.PNSubscribeOperation, - }), - ]); - } - else { - const errorReason = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation); - return ReceiveFailedState.with(Object.assign(Object.assign({}, context), { reason: errorReason }), [ - emitStatus({ - category: StatusCategory$1.PNDisconnectedUnexpectedlyCategory, - operation: RequestOperation$1.PNSubscribeOperation, - error: (_a = errorReason.status) === null || _a === void 0 ? void 0 : _a.category, - }), - ]); - } - }); - ReceivingState.on(unsubscribeAll.type, (_) => UnsubscribedState.with(undefined, [ - emitStatus({ - category: StatusCategory$1.PNDisconnectedCategory, - operation: RequestOperation$1.PNUnsubscribeOperation, - }), - ])); - - /** - * Stopped real-time updates (disconnected) state module. - * - * @internal - */ - /** - * Stopped real-time updates (disconnected) state. - * - * State in which Subscription Event Engine still has information about subscription but doesn't process real-time - * updates. - * - * @internal - */ - ReceiveStoppedState.on(subscriptionChange.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return ReceiveStoppedState.with({ channels: payload.channels, groups: payload.groups, cursor: context.cursor }); - }); - ReceiveStoppedState.on(restore.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return ReceiveStoppedState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || context.cursor.region }, - }); - }); - ReceiveStoppedState.on(reconnect.type, (context, { payload }) => { - var _a; - return HandshakingState.with({ - channels: context.channels, - groups: context.groups, - cursor: { - timetoken: !!payload.cursor.timetoken ? (_a = payload.cursor) === null || _a === void 0 ? void 0 : _a.timetoken : context.cursor.timetoken, - region: payload.cursor.region || context.cursor.region, - }, - onDemand: true, - }); - }); - ReceiveStoppedState.on(unsubscribeAll.type, () => UnsubscribedState.with(undefined)); - - /** - * Failed to receive real-time updates (disconnected) state. - * - * @internal - */ - /** - * Failed to receive real-time updates (disconnected) state. - * - * State in which Subscription Event Engine waits for user to try to reconnect after all retry attempts has been - * exhausted. - * - * @internal - */ - ReceiveFailedState.on(reconnect.type, (context, { payload }) => { - var _a; - return HandshakingState.with({ - channels: context.channels, - groups: context.groups, - cursor: { - timetoken: !!payload.cursor.timetoken ? (_a = payload.cursor) === null || _a === void 0 ? void 0 : _a.timetoken : context.cursor.timetoken, - region: payload.cursor.region || context.cursor.region, - }, - onDemand: true, - }); - }); - ReceiveFailedState.on(subscriptionChange.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: context.cursor, - onDemand: true, - }); - }); - ReceiveFailedState.on(restore.type, (context, { payload }) => { - if (payload.channels.length === 0 && payload.groups.length === 0) - return UnsubscribedState.with(undefined); - return HandshakingState.with({ - channels: payload.channels, - groups: payload.groups, - cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || context.cursor.region }, - onDemand: true, - }); - }); - ReceiveFailedState.on(unsubscribeAll.type, (_) => UnsubscribedState.with(undefined)); - - /** - * Subscribe Event Engine effects dispatcher. - * - * @internal - */ - /** - * Subscribe Event Engine dispatcher. - * - * Dispatcher responsible for subscription events handling and corresponding effects execution. - * - * @internal - */ - class EventEngineDispatcher extends Dispatcher { - constructor(engine, dependencies) { - super(dependencies, dependencies.config.logger()); - this.on(handshake.type, asyncHandler((payload_1, abortSignal_1, _a) => __awaiter(this, [payload_1, abortSignal_1, _a], void 0, function* (payload, abortSignal, { handshake, presenceState, config }) { - abortSignal.throwIfAborted(); - try { - const result = yield handshake(Object.assign(Object.assign({ abortSignal: abortSignal, channels: payload.channels, channelGroups: payload.groups, filterExpression: config.filterExpression }, (config.maintainPresenceState && { state: presenceState })), { onDemand: payload.onDemand })); - return engine.transition(handshakeSuccess(result)); - } - catch (e) { - if (e instanceof PubNubError) { - if (e.status && e.status.category == StatusCategory$1.PNCancelledCategory) - return; - return engine.transition(handshakeFailure(e)); - } - } - }))); - this.on(receiveMessages.type, asyncHandler((payload_1, abortSignal_1, _a) => __awaiter(this, [payload_1, abortSignal_1, _a], void 0, function* (payload, abortSignal, { receiveMessages, config }) { - abortSignal.throwIfAborted(); - try { - const result = yield receiveMessages({ - abortSignal: abortSignal, - channels: payload.channels, - channelGroups: payload.groups, - timetoken: payload.cursor.timetoken, - region: payload.cursor.region, - filterExpression: config.filterExpression, - onDemand: payload.onDemand, - }); - engine.transition(receiveSuccess(result.cursor, result.messages)); - } - catch (error) { - if (error instanceof PubNubError) { - if (error.status && error.status.category == StatusCategory$1.PNCancelledCategory) - return; - if (!abortSignal.aborted) - return engine.transition(receiveFailure(error)); - } - } - }))); - this.on(emitMessages.type, asyncHandler((_a, _1, _b) => __awaiter(this, [_a, _1, _b], void 0, function* ({ cursor, events }, _, { emitMessages }) { - if (events.length > 0) - emitMessages(cursor, events); - }))); - this.on(emitStatus.type, asyncHandler((payload_1, _1, _a) => __awaiter(this, [payload_1, _1, _a], void 0, function* (payload, _, { emitStatus }) { return emitStatus(payload); }))); - } - } - - /** - * Subscribe Event Engine module. - * - * @internal - */ - /** - * Subscribe Event Engine Core. - * - * @internal - */ - class EventEngine { - get _engine() { - return this.engine; - } - constructor(dependencies) { - this.channels = []; - this.groups = []; - this.dependencies = dependencies; - this.engine = new Engine(dependencies.config.logger()); - this.dispatcher = new EventEngineDispatcher(this.engine, dependencies); - dependencies.config.logger().debug('EventEngine', 'Create subscribe event engine.'); - this._unsubscribeEngine = this.engine.subscribe((change) => { - if (change.type === 'invocationDispatched') { - this.dispatcher.dispatch(change.invocation); - } - }); - this.engine.start(UnsubscribedState, undefined); - } - /** - * Subscription-based current timetoken. - * - * @returns Timetoken based on current timetoken plus diff between current and loop start time. - */ - get subscriptionTimetoken() { - const currentState = this.engine.currentState; - if (!currentState) - return undefined; - let referenceTimetoken; - let currentTimetoken = '0'; - if (currentState.label === ReceivingState.label) { - const context = this.engine.currentContext; - currentTimetoken = context.cursor.timetoken; - referenceTimetoken = context.referenceTimetoken; - } - return subscriptionTimetokenFromReference(currentTimetoken, referenceTimetoken !== null && referenceTimetoken !== void 0 ? referenceTimetoken : '0'); - } - subscribe({ channels, channelGroups, timetoken, withPresence, }) { - var _a; - // check if the channels and groups are already subscribed - const hasNewChannels = channels === null || channels === void 0 ? void 0 : channels.some((channel) => !this.channels.includes(channel)); - const hasNewGroups = channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.some((group) => !this.groups.includes(group)); - const hasNewSubscriptions = hasNewChannels || hasNewGroups; - this.channels = [...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])]; - this.groups = [...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])]; - if (withPresence) { - this.channels.map((c) => this.channels.push(`${c}-pnpres`)); - this.groups.map((g) => this.groups.push(`${g}-pnpres`)); - } - if (timetoken) { - this.engine.transition(restore(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])])), timetoken)); - } - else { - if (hasNewSubscriptions) { - this.engine.transition(subscriptionChange(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])])))); - } - else { - this.dependencies.config - .logger() - .debug('EventEngine', 'Skipping state transition - all channels/groups already subscribed. Emitting SubscriptionChanged event.'); - // Get current timetoken from state context - const currentState = this.engine.currentState; - const currentContext = this.engine.currentContext; - let currentTimetoken = '0'; - if ((currentState === null || currentState === void 0 ? void 0 : currentState.label) === ReceivingState.label && currentContext) { - const receivingContext = currentContext; - currentTimetoken = (_a = receivingContext.cursor) === null || _a === void 0 ? void 0 : _a.timetoken; - } - // Manually emit SubscriptionChanged status event - this.dependencies.emitStatus({ - category: StatusCategory$1.PNSubscriptionChangedCategory, - affectedChannels: Array.from(new Set(this.channels)), - affectedChannelGroups: Array.from(new Set(this.groups)), - currentTimetoken, - }); - } - } - if (this.dependencies.join) { - this.dependencies.join({ - channels: Array.from(new Set(this.channels.filter((c) => !c.endsWith('-pnpres')))), - groups: Array.from(new Set(this.groups.filter((g) => !g.endsWith('-pnpres')))), - }); - } - } - unsubscribe({ channels = [], channelGroups = [] }) { - const filteredChannels = removeSingleOccurrence(this.channels, [ - ...channels, - ...channels.map((c) => `${c}-pnpres`), - ]); - const filteredGroups = removeSingleOccurrence(this.groups, [ - ...channelGroups, - ...channelGroups.map((c) => `${c}-pnpres`), - ]); - if (new Set(this.channels).size !== new Set(filteredChannels).size || - new Set(this.groups).size !== new Set(filteredGroups).size) { - const channelsToLeave = findUniqueCommonElements(this.channels, channels); - const groupsToLeave = findUniqueCommonElements(this.groups, channelGroups); - if (this.dependencies.presenceState) { - channelsToLeave === null || channelsToLeave === void 0 ? void 0 : channelsToLeave.forEach((c) => delete this.dependencies.presenceState[c]); - groupsToLeave === null || groupsToLeave === void 0 ? void 0 : groupsToLeave.forEach((g) => delete this.dependencies.presenceState[g]); - } - this.channels = filteredChannels; - this.groups = filteredGroups; - this.engine.transition(subscriptionChange(Array.from(new Set(this.channels.slice(0))), Array.from(new Set(this.groups.slice(0))))); - if (this.dependencies.leave) { - this.dependencies.leave({ - channels: channelsToLeave.slice(0), - groups: groupsToLeave.slice(0), - }); - } - } - } - unsubscribeAll(isOffline = false) { - const channelGroups = this.getSubscribedChannelGroups(); - const channels = this.getSubscribedChannels(); - this.channels = []; - this.groups = []; - if (this.dependencies.presenceState) { - Object.keys(this.dependencies.presenceState).forEach((objectName) => { - delete this.dependencies.presenceState[objectName]; - }); - } - this.engine.transition(subscriptionChange(this.channels.slice(0), this.groups.slice(0), isOffline)); - if (this.dependencies.leaveAll) - this.dependencies.leaveAll({ channels, groups: channelGroups, isOffline }); - } - reconnect({ timetoken, region }) { - const channelGroups = this.getSubscribedChannels(); - const channels = this.getSubscribedChannels(); - this.engine.transition(reconnect(timetoken, region)); - if (this.dependencies.presenceReconnect) - this.dependencies.presenceReconnect({ channels, groups: channelGroups }); - } - disconnect(isOffline = false) { - const channelGroups = this.getSubscribedChannels(); - const channels = this.getSubscribedChannels(); - this.engine.transition(disconnect(isOffline)); - if (this.dependencies.presenceDisconnect) - this.dependencies.presenceDisconnect({ channels, groups: channelGroups, isOffline }); - } - getSubscribedChannels() { - return Array.from(new Set(this.channels.slice(0))); - } - getSubscribedChannelGroups() { - return Array.from(new Set(this.groups.slice(0))); - } - dispose() { - this.disconnect(true); - this._unsubscribeEngine(); - this.dispatcher.dispose(); - } - } - - /** - * Publish REST API module. - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether data is published used `POST` body or not. - */ - const SEND_BY_POST = false; - // endregion - /** - * Data publish request. - * - * Request will normalize and encrypt (if required) provided data and push it to the specified - * channel. - * - * @internal - */ - class PublishRequest extends AbstractRequest { - /** - * Construct data publish request. - * - * @param parameters - Request configuration. - */ - constructor(parameters) { - var _a; - const sendByPost = (_a = parameters.sendByPost) !== null && _a !== void 0 ? _a : SEND_BY_POST; - super({ method: sendByPost ? TransportMethod.POST : TransportMethod.GET, compressible: sendByPost }); - this.parameters = parameters; - // Apply default request parameters. - this.parameters.sendByPost = sendByPost; - } - operation() { - return RequestOperation$1.PNPublishOperation; - } - validate() { - const { message, channel, keySet: { publishKey }, } = this.parameters; - if (!channel) - return "Missing 'channel'"; - if (!message) - return "Missing 'message'"; - if (!publishKey) - return "Missing 'publishKey'"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { timetoken: this.deserializeResponse(response)[2] }; - }); - } - get path() { - const { message, channel, keySet } = this.parameters; - const stringifiedPayload = this.prepareMessagePayload(message); - return `/publish/${keySet.publishKey}/${keySet.subscribeKey}/0/${encodeString(channel)}/0${!this.parameters.sendByPost ? `/${encodeString(stringifiedPayload)}` : ''}`; - } - get queryParameters() { - const { customMessageType, meta, replicate, storeInHistory, ttl } = this.parameters; - const query = {}; - if (customMessageType) - query.custom_message_type = customMessageType; - if (storeInHistory !== undefined) - query.store = storeInHistory ? '1' : '0'; - if (ttl !== undefined) - query.ttl = ttl; - if (replicate !== undefined && !replicate) - query.norep = 'true'; - if (meta && typeof meta === 'object') - query.meta = JSON.stringify(meta); - return query; - } - get headers() { - var _a; - if (!this.parameters.sendByPost) - return super.headers; - return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); - } - get body() { - return this.prepareMessagePayload(this.parameters.message); - } - /** - * Pre-process provided data. - * - * Data will be "normalized" and encrypted if `cryptoModule` has been provided. - * - * @param payload - User-provided data which should be pre-processed before use. - * - * @returns Payload which can be used as part of request URL or body. - * - * @throws {Error} in case if provided `payload` or results of `encryption` can't be stringified. - */ - prepareMessagePayload(payload) { - const { crypto } = this.parameters; - if (!crypto) - return JSON.stringify(payload) || ''; - const encrypted = crypto.encrypt(JSON.stringify(payload)); - return JSON.stringify(typeof encrypted === 'string' ? encrypted : encode(encrypted)); - } - } - - /** - * Signal REST API module. - */ - // endregion - /** - * Signal data (size-limited) publish request. - * - * @internal - */ - class SignalRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSignalOperation; - } - validate() { - const { message, channel, keySet: { publishKey }, } = this.parameters; - if (!channel) - return "Missing 'channel'"; - if (!message) - return "Missing 'message'"; - if (!publishKey) - return "Missing 'publishKey'"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { timetoken: this.deserializeResponse(response)[2] }; - }); - } - get path() { - const { keySet: { publishKey, subscribeKey }, channel, message, } = this.parameters; - const stringifiedPayload = JSON.stringify(message); - return `/signal/${publishKey}/${subscribeKey}/0/${encodeString(channel)}/0/${encodeString(stringifiedPayload)}`; - } - get queryParameters() { - const { customMessageType } = this.parameters; - const query = {}; - if (customMessageType) - query.custom_message_type = customMessageType; - return query; - } - } - - /** - * Receive messages subscribe REST API module. - * - * @internal - */ - /** - * Receive messages subscribe request. - * - * @internal - */ - class ReceiveMessagesSubscribeRequest extends BaseSubscribeRequest { - operation() { - return RequestOperation$1.PNReceiveMessagesOperation; - } - validate() { - const validationResult = super.validate(); - if (validationResult) - return validationResult; - if (!this.parameters.timetoken) - return 'timetoken can not be empty'; - if (!this.parameters.region) - return 'region can not be empty'; - } - get path() { - const { keySet: { subscribeKey }, channels = [], } = this.parameters; - return `/v2/subscribe/${subscribeKey}/${encodeNames(channels.sort(), ',')}/0`; - } - get queryParameters() { - const { channelGroups, filterExpression, timetoken, region, heartbeat, onDemand } = this - .parameters; - const query = { ee: '' }; - if (onDemand) - query['on-demand'] = 1; - if (channelGroups && channelGroups.length > 0) - query['channel-group'] = channelGroups.sort().join(','); - if (filterExpression && filterExpression.length > 0) - query['filter-expr'] = filterExpression; - if (typeof timetoken === 'string') { - if (timetoken && timetoken !== '0' && timetoken.length > 0) - query['tt'] = timetoken; - } - else if (timetoken && timetoken > 0) - query['tt'] = timetoken; - if (region) - query['tr'] = region; - if (heartbeat) - query.heartbeat = heartbeat; - return query; - } - } - - /** - * Handshake subscribe REST API module. - * - * @internal - */ - /** - * Handshake subscribe request. - * - * Separate subscribe request required by Event Engine. - * - * @internal - */ - class HandshakeSubscribeRequest extends BaseSubscribeRequest { - operation() { - return RequestOperation$1.PNHandshakeOperation; - } - get path() { - const { keySet: { subscribeKey }, channels = [], } = this.parameters; - return `/v2/subscribe/${subscribeKey}/${encodeNames(channels.sort(), ',')}/0`; - } - get queryParameters() { - const { channelGroups, heartbeat, filterExpression, state, onDemand } = this - .parameters; - const query = { ee: '' }; - if (onDemand) - query['on-demand'] = 1; - if (channelGroups && channelGroups.length > 0) - query['channel-group'] = channelGroups.sort().join(','); - if (filterExpression && filterExpression.length > 0) - query['filter-expr'] = filterExpression; - if (state && Object.keys(state).length > 0) - query['state'] = JSON.stringify(state); - if (heartbeat) - query.heartbeat = heartbeat; - return query; - } - } - - /** - * SubscriptionCapable entity type. - * - * @internal - */ - var SubscriptionType; - (function (SubscriptionType) { - /** - * Channel identifier, which is part of the URI path. - */ - SubscriptionType[SubscriptionType["Channel"] = 0] = "Channel"; - /** - * Channel group identifiers, which is part of the query parameters. - */ - SubscriptionType[SubscriptionType["ChannelGroup"] = 1] = "ChannelGroup"; - })(SubscriptionType || (SubscriptionType = {})); - - /** - * User-provided channels and groups for subscription. - * - * Object contains information about channels and groups for which real-time updates should be retrieved from the - * PubNub network. - * - * @internal - */ - class SubscriptionInput { - /** - * Create a subscription input object. - * - * @param channels - List of channels which will be used with subscribe REST API to receive real-time updates. - * @param channelGroups - List of channel groups which will be used with subscribe REST API to receive real-time - * updates. - */ - constructor({ channels, channelGroups }) { - /** - * Whether the user input is empty or not. - */ - this.isEmpty = true; - this._channelGroups = new Set((channelGroups !== null && channelGroups !== void 0 ? channelGroups : []).filter((value) => value.length > 0)); - this._channels = new Set((channels !== null && channels !== void 0 ? channels : []).filter((value) => value.length > 0)); - this.isEmpty = this._channels.size === 0 && this._channelGroups.size === 0; - } - /** - * Retrieve total length of subscription input. - * - * @returns Number of channels and groups in subscription input. - */ - get length() { - if (this.isEmpty) - return 0; - return this._channels.size + this._channelGroups.size; - } - /** - * Retrieve a list of user-provided channel names. - * - * @returns List of user-provided channel names. - */ - get channels() { - if (this.isEmpty) - return []; - return Array.from(this._channels); - } - /** - * Retrieve a list of user-provided channel group names. - * - * @returns List of user-provided channel group names. - */ - get channelGroups() { - if (this.isEmpty) - return []; - return Array.from(this._channelGroups); - } - /** - * Check if the given name is contained in the channel or channel group. - * - * @param name - Containing the name to be checked. - * - * @returns `true` if the name is found in the channel or channel group, `false` otherwise. - */ - contains(name) { - if (this.isEmpty) - return false; - return this._channels.has(name) || this._channelGroups.has(name); - } - /** - * Create a new subscription input which will contain all channels and channel groups from both inputs. - * - * @param input - Another subscription input that should be used to aggregate data in new instance. - * - * @returns New subscription input instance with combined channels and channel groups. - */ - with(input) { - return new SubscriptionInput({ - channels: [...this._channels, ...input._channels], - channelGroups: [...this._channelGroups, ...input._channelGroups], - }); - } - /** - * Create a new subscription input which will contain only channels and groups which not present in the input. - * - * @param input - Another subscription input which should be used to filter data in new instance. - * - * @returns New subscription input instance with filtered channels and channel groups. - */ - without(input) { - return new SubscriptionInput({ - channels: [...this._channels].filter((value) => !input._channels.has(value)), - channelGroups: [...this._channelGroups].filter((value) => !input._channelGroups.has(value)), - }); - } - /** - * Add data from another subscription input to the receiver. - * - * @param input - Another subscription input whose data should be added to the receiver. - * - * @returns Receiver instance with updated channels and channel groups. - */ - add(input) { - if (input._channelGroups.size > 0) - this._channelGroups = new Set([...this._channelGroups, ...input._channelGroups]); - if (input._channels.size > 0) - this._channels = new Set([...this._channels, ...input._channels]); - this.isEmpty = this._channels.size === 0 && this._channelGroups.size === 0; - return this; - } - /** - * Remove data from another subscription input from the receiver. - * - * @param input - Another subscription input whose data should be removed from the receiver. - * - * @returns Receiver instance with updated channels and channel groups. - */ - remove(input) { - if (input._channelGroups.size > 0) - this._channelGroups = new Set([...this._channelGroups].filter((value) => !input._channelGroups.has(value))); - if (input._channels.size > 0) - this._channels = new Set([...this._channels].filter((value) => !input._channels.has(value))); - return this; - } - /** - * Remove all data from subscription input. - * - * @returns Receiver instance with updated channels and channel groups. - */ - removeAll() { - this._channels.clear(); - this._channelGroups.clear(); - this.isEmpty = true; - return this; - } - /** - * Serialize a subscription input to string. - * - * @returns Printable string representation of a subscription input. - */ - toString() { - return `SubscriptionInput { channels: [${this.channels.join(', ')}], channelGroups: [${this.channelGroups.join(', ')}], is empty: ${this.isEmpty ? 'true' : 'false'}} }`; - } - } - // endregion - - /** - * Subscription state object. - * - * State object used across multiple subscription object clones. - * - * @internal - */ - class SubscriptionBaseState { - /** - * Create a base subscription state object. - * - * @param client - PubNub client which will work with a subscription object. - * @param subscriptionInput - User's input to be used with subscribe REST API. - * @param options - Subscription behavior options. - * @param referenceTimetoken - High-precision timetoken of the moment when subscription was created for entity. - */ - constructor(client, subscriptionInput, options, referenceTimetoken) { - /** - * Whether a subscribable object subscribed or not. - */ - this._isSubscribed = false; - /** - * The list of references to all {@link SubscriptionBase} clones created for this reference. - */ - this.clones = {}; - /** - * List of a parent subscription state objects list. - * - * List is used to track usage of a subscription object in other subscription object sets. - * - * **Important:** Tracking is required to prevent unexpected unsubscriptions if an object still has a parent. - */ - this.parents = []; - /** - * Unique subscription object identifier. - */ - this._id = uuidGenerator.createUUID(); - this.referenceTimetoken = referenceTimetoken; - this.subscriptionInput = subscriptionInput; - this.options = options; - this.client = client; - } - /** - * Get unique subscription object identifier. - * - * @returns Unique subscription object identifier. - */ - get id() { - return this._id; - } - /** - * Check whether a subscription object is the last clone or not. - * - * @returns `true` if a subscription object is the last clone. - */ - get isLastClone() { - return Object.keys(this.clones).length === 1; - } - /** - * Get whether a subscribable object subscribed or not. - * - * **Warning:** This method shouldn't be overridden by {@link SubscriptionSet}. - * - * @returns Whether a subscribable object subscribed or not. - */ - get isSubscribed() { - if (this._isSubscribed) - return true; - // Checking whether any of "parents" is subscribed. - return this.parents.length > 0 && this.parents.some((state) => state.isSubscribed); - } - /** - * Update active subscription state. - * - * @param value - New subscription state. - */ - set isSubscribed(value) { - if (this.isSubscribed === value) - return; - this._isSubscribed = value; - } - /** - * Add a parent subscription state object to mark the linkage. - * - * @param parent - Parent subscription state object. - * - * @internal - */ - addParentState(parent) { - if (!this.parents.includes(parent)) - this.parents.push(parent); - } - /** - * Remove a parent subscription state object. - * - * @param parent - Parent object for which linkage should be broken. - * - * @internal - */ - removeParentState(parent) { - const parentStateIndex = this.parents.indexOf(parent); - if (parentStateIndex !== -1) - this.parents.splice(parentStateIndex, 1); - } - /** - * Store a clone of a {@link SubscriptionBase} instance with a given instance ID. - * - * @param id - The instance ID to associate with clone. - * @param instance - Reference to the subscription instance to store as a clone. - */ - storeClone(id, instance) { - if (!this.clones[id]) - this.clones[id] = instance; - } - } - /** - * Base subscribe object. - * - * Implementation of base functionality used by {@link SubscriptionObject Subscription} and {@link SubscriptionSet}. - */ - class SubscriptionBase { - /** - * Create a subscription object from the state. - * - * @param state - Subscription state object. - * @param subscriptionType - Actual subscription object type. - * - * @internal - */ - constructor(state, subscriptionType = 'Subscription') { - this.subscriptionType = subscriptionType; - /** - * Unique subscription object identifier. - * - * @internal - */ - this.id = uuidGenerator.createUUID(); - /** - * Event emitter, which will notify listeners about updates received for channels / groups. - * - * @internal - */ - this.eventDispatcher = new EventDispatcher(); - this._state = state; - } - /** - * Subscription state. - * - * @returns Subscription state object. - * - * @internal - */ - get state() { - return this._state; - } - /** - * Get a list of channels which is used for subscription. - * - * @returns List of channel names. - */ - get channels() { - return this.state.subscriptionInput.channels.slice(0); - } - /** - * Get a list of channel groups which is used for subscription. - * - * @returns List of channel group names. - */ - get channelGroups() { - return this.state.subscriptionInput.channelGroups.slice(0); - } - // -------------------------------------------------------- - // -------------------- Event emitter --------------------- - // -------------------------------------------------------- - // region Event emitter - /** - * Set a new message handler. - * - * @param listener - Listener function, which will be called each time when a new message - * is received from the real-time network. - */ - set onMessage(listener) { - this.eventDispatcher.onMessage = listener; - } - /** - * Set a new presence events handler. - * - * @param listener - Listener function, which will be called each time when a new - * presence event is received from the real-time network. - */ - set onPresence(listener) { - this.eventDispatcher.onPresence = listener; - } - /** - * Set a new signal handler. - * - * @param listener - Listener function, which will be called each time when a new signal - * is received from the real-time network. - */ - set onSignal(listener) { - this.eventDispatcher.onSignal = listener; - } - /** - * Set a new app context event handler. - * - * @param listener - Listener function, which will be called each time when a new - * app context event is received from the real-time network. - */ - set onObjects(listener) { - this.eventDispatcher.onObjects = listener; - } - /** - * Set a new message reaction event handler. - * - * @param listener - Listener function, which will be called each time when a - * new message reaction event is received from the real-time network. - */ - set onMessageAction(listener) { - this.eventDispatcher.onMessageAction = listener; - } - /** - * Set a new file handler. - * - * @param listener - Listener function, which will be called each time when a new file - * is received from the real-time network. - */ - set onFile(listener) { - this.eventDispatcher.onFile = listener; - } - /** - * Set a new DataSync event handler. - * - * @param listener - Listener function, which will be called each time when a new - * DataSync event is received from the real-time network. - */ - set onDataSync(listener) { - this.eventDispatcher.onDataSync = listener; - } - /** - * Set events handler. - * - * @param listener - Events listener configuration object, which lets specify handlers for multiple - * types of events. - */ - addListener(listener) { - this.eventDispatcher.addListener(listener); - } - /** - * Remove events handler. - * - * @param listener - Event listener configuration, which should be removed from the list of notified - * listeners. **Important:** Should be the same object which has been passed to the {@link addListener}. - */ - removeListener(listener) { - this.eventDispatcher.removeListener(listener); - } - /** - * Remove all events listeners. - */ - removeAllListeners() { - this.eventDispatcher.removeAllListeners(); - } - /** - * Dispatch received a real-time update. - * - * @param cursor - A time cursor for the next portion of events. - * @param event - A real-time event from multiplexed subscription. - * - * @return `true` if receiver has consumed event. - * - * @internal - */ - handleEvent(cursor, event) { - var _a; - if (!this.state.cursor || cursor > this.state.cursor) - this.state.cursor = cursor; - // Check whether this is an old `old` event and it should be ignored or not. - if (this.state.referenceTimetoken && event.data.timetoken < this.state.referenceTimetoken) { - this.state.client.logger.trace(this.subscriptionType, () => ({ - messageType: 'text', - message: `Event timetoken (${event.data.timetoken}) is older than reference timetoken (${this.state.referenceTimetoken}) for ${this.id} subscription object. Ignoring event.`, - })); - return; - } - // Don't pass events which are filtered out by the user-provided function. - if (((_a = this.state.options) === null || _a === void 0 ? void 0 : _a.filter) && !this.state.options.filter(event)) { - this.state.client.logger.trace(this.subscriptionType, `Event filtered out by filter function for ${this.id} subscription object. Ignoring event.`); - return; - } - const clones = Object.values(this.state.clones); - if (clones.length > 0) { - this.state.client.logger.trace(this.subscriptionType, `Notify ${this.id} subscription object clones (count: ${clones.length}) about received event.`); - } - clones.forEach((subscription) => subscription.eventDispatcher.handleEvent(event)); - } - /** - * Graceful object destruction. - * - * This is an instance destructor, which will properly deinitialize it: - * - remove and unset all listeners, - * - try to unsubscribe (if subscribed and there are no more instances interested in the same data stream). - * - * **Important:** {@link SubscriptionBase#dispose dispose} won't have any effect if a subscription object is part of - * set. To gracefully dispose an object, it should be removed from the set using - * {@link SubscriptionSet#removeSubscription removeSubscription} (in this case call of - * {@link SubscriptionBase#dispose dispose} not required. - * - * **Note:** Disposed instance won't call the dispatcher to deliver updates to the listeners. - */ - dispose() { - const keys = Object.keys(this.state.clones); - if (keys.length > 1) { - this.state.client.logger.debug(this.subscriptionType, `Remove subscription object clone on dispose: ${this.id}`); - delete this.state.clones[this.id]; - } - else if (keys.length === 1 && this.state.clones[this.id]) { - this.state.client.logger.debug(this.subscriptionType, `Unsubscribe subscription object on dispose: ${this.id}`); - this.unsubscribe(); - } - } - /** - * Invalidate subscription object. - * - * Clean up resources used by a subscription object. - * - * **Note:** An invalidated instance won't call the dispatcher to deliver updates to the listeners. - * - * @param forDestroy - Whether subscription object invalidated as part of PubNub client destroy process or not. - * - * @internal - */ - invalidate(forDestroy = false) { - this.state._isSubscribed = false; - if (forDestroy) { - delete this.state.clones[this.id]; - if (Object.keys(this.state.clones).length === 0) { - this.state.client.logger.trace(this.subscriptionType, 'Last clone removed. Reset shared subscription state.'); - this.state.subscriptionInput.removeAll(); - this.state.parents = []; - } - } - } - /** - * Start receiving real-time updates. - * - * @param parameters - Additional subscription configuration options which should be used - * for request. - */ - subscribe(parameters) { - if (this.state.isSubscribed) { - this.state.client.logger.trace(this.subscriptionType, 'Already subscribed. Ignoring subscribe request.'); - return; - } - this.state.client.logger.debug(this.subscriptionType, () => { - if (!parameters) - return { messageType: 'text', message: 'Subscribe' }; - return { messageType: 'object', message: parameters, details: 'Subscribe with parameters:' }; - }); - this.state.isSubscribed = true; - this.updateSubscription({ subscribing: true, timetoken: parameters === null || parameters === void 0 ? void 0 : parameters.timetoken }); - } - /** - * Stop real-time events processing. - * - * **Important:** {@link SubscriptionBase#unsubscribe unsubscribe} won't have any effect if a subscription object - * is part of active (subscribed) set. To unsubscribe an object, it should be removed from the set using - * {@link SubscriptionSet#removeSubscription removeSubscription} (in this case call of - * {@link SubscriptionBase#unsubscribe unsubscribe} not required. - * - * **Note:** Unsubscribed instance won't call the dispatcher to deliver updates to the listeners. - */ - unsubscribe() { - // Check whether an instance-level subscription flag not set or parent has active subscription. - if (!this.state._isSubscribed || this.state.isSubscribed) { - // Warn if a user tries to unsubscribe using specific subscription which subscribed as part of a subscription set. - if (!this.state._isSubscribed && this.state.parents.length > 0 && this.state.isSubscribed) { - this.state.client.logger.warn(this.subscriptionType, () => ({ - messageType: 'object', - details: 'Subscription is subscribed as part of a subscription set. Remove from active sets to unsubscribe:', - message: this.state.parents.filter((subscriptionSet) => subscriptionSet.isSubscribed), - })); - return; - } - else if (!this.state._isSubscribed) { - this.state.client.logger.trace(this.subscriptionType, 'Not subscribed. Ignoring unsubscribe request.'); - return; - } - } - this.state.client.logger.debug(this.subscriptionType, 'Unsubscribe'); - this.state.isSubscribed = false; - delete this.state.cursor; - this.updateSubscription({ subscribing: false }); - } - /** - * Update channels and groups used by subscription loop. - * - * @param parameters - Subscription loop update parameters. - * @param parameters.subscribing - Whether subscription updates as part of subscription or unsubscription. - * @param [parameters.timetoken] - Subscription catch-up timetoken. - * @param [parameters.subscriptions] - List of subscriptions which should be used to modify a subscription loop - * object. - * - * @internal - */ - updateSubscription(parameters) { - var _a, _b; - if (parameters === null || parameters === void 0 ? void 0 : parameters.timetoken) { - if (((_a = this.state.cursor) === null || _a === void 0 ? void 0 : _a.timetoken) && ((_b = this.state.cursor) === null || _b === void 0 ? void 0 : _b.timetoken) !== '0') { - if (parameters.timetoken !== '0' && parameters.timetoken > this.state.cursor.timetoken) - this.state.cursor.timetoken = parameters.timetoken; - } - else - this.state.cursor = { timetoken: parameters.timetoken }; - } - const subscriptions = parameters.subscriptions && parameters.subscriptions.length > 0 ? parameters.subscriptions : undefined; - if (parameters.subscribing) { - this.register(Object.assign(Object.assign({}, (parameters.timetoken ? { cursor: this.state.cursor } : {})), (subscriptions ? { subscriptions } : {}))); - } - else - this.unregister(subscriptions); - } - } - - /** - * {@link SubscriptionSet} state object. - * - * State object used across multiple {@link SubscriptionSet} object clones. - * - * @internal - */ - class SubscriptionSetState extends SubscriptionBaseState { - /** - * Create a subscription state object. - * - * @param parameters - State configuration options - * @param parameters.client - PubNub client which will work with a subscription object. - * @param parameters.subscriptions - List of subscriptions managed by set. - * @param [parameters.options] - Subscription behavior options. - */ - constructor(parameters) { - const subscriptionInput = new SubscriptionInput({}); - parameters.subscriptions.forEach((subscription) => subscriptionInput.add(subscription.state.subscriptionInput)); - super(parameters.client, subscriptionInput, parameters.options, parameters.client.subscriptionTimetoken); - this.subscriptions = parameters.subscriptions; - } - /** - * Add a single subscription object to the set. - * - * @param subscription - Another entity's subscription object, which should be added. - */ - addSubscription(subscription) { - if (this.subscriptions.includes(subscription)) - return; - subscription.state.addParentState(this); - this.subscriptions.push(subscription); - // Update subscription input. - this.subscriptionInput.add(subscription.state.subscriptionInput); - } - /** - * Remove a single subscription object from the set. - * - * @param subscription - Another entity's subscription object, which should be removed. - * @param clone - Whether a target subscription is a clone. - */ - removeSubscription(subscription, clone) { - const index = this.subscriptions.indexOf(subscription); - if (index === -1) - return; - this.subscriptions.splice(index, 1); - if (!clone) - subscription.state.removeParentState(this); - // Update subscription input. - this.subscriptionInput.remove(subscription.state.subscriptionInput); - } - /** - * Remove any registered subscription object. - */ - removeAllSubscriptions() { - this.subscriptions.forEach((subscription) => subscription.state.removeParentState(this)); - this.subscriptions.splice(0, this.subscriptions.length); - this.subscriptionInput.removeAll(); - } - } - /** - * Multiple entities subscription set object which can be used to receive and handle real-time - * updates. - * - * Subscription set object represents a collection of per-entity subscription objects and allows - * processing them at once for subscription loop and events handling. - */ - class SubscriptionSet extends SubscriptionBase { - /** - * Create entities' subscription set object. - * - * Subscription set object represents a collection of per-entity subscription objects and allows - * processing them at once for subscription loop and events handling. - * - * @param parameters - Subscription set object configuration. - * - * @returns Ready to use entities' subscription set object. - * - * @internal - */ - constructor(parameters) { - let state; - if ('client' in parameters) { - let subscriptions = []; - if (!parameters.subscriptions && parameters.entities) { - parameters.entities.forEach((entity) => subscriptions.push(entity.subscription(parameters.options))); - } - else if (parameters.subscriptions) - subscriptions = parameters.subscriptions; - state = new SubscriptionSetState({ client: parameters.client, subscriptions, options: parameters.options }); - subscriptions.forEach((subscription) => subscription.state.addParentState(state)); - state.client.logger.debug('SubscriptionSet', () => ({ - messageType: 'object', - details: 'Create subscription set with parameters:', - message: Object.assign({ subscriptions: state.subscriptions }, (parameters.options ? parameters.options : {})), - })); - } - else { - state = parameters.state; - state.client.logger.debug('SubscriptionSet', 'Create subscription set clone'); - } - super(state, 'SubscriptionSet'); - this.state.storeClone(this.id, this); - // Update a parent sets list for original set subscriptions. - state.subscriptions.forEach((subscription) => subscription.addParentSet(this)); - } - /** - * Get a {@link SubscriptionSet} object state. - * - * @returns: {@link SubscriptionSet} object state. - * - * @internal - */ - get state() { - return super.state; - } - /** - * Get a list of entities' subscription objects registered in a subscription set. - * - * @returns Entities' subscription objects list. - */ - get subscriptions() { - return this.state.subscriptions.slice(0); - } - // -------------------------------------------------------- - // -------------------- Event handler --------------------- - // -------------------------------------------------------- - // region Event handler - /** - * Dispatch received a real-time update. - * - * @param cursor - A time cursor for the next portion of events. - * @param event - A real-time event from multiplexed subscription. - * - * @return `true` if receiver has consumed event. - * - * @internal - */ - handleEvent(cursor, event) { - var _a; - // Check whether an event is not designated for this subscription set. - if (!this.state.subscriptionInput.contains((_a = event.data.subscription) !== null && _a !== void 0 ? _a : event.data.channel)) - return; - // Check whether `event` can be processed or not. - if (!this.state._isSubscribed) { - this.state.client.logger.trace(this.subscriptionType, `Subscription set ${this.id} is not subscribed. Ignoring event.`); - return; - } - super.handleEvent(cursor, event); - if (this.state.subscriptions.length > 0) { - this.state.client.logger.trace(this.subscriptionType, `Notify ${this.id} subscription set subscriptions (count: ${this.state.subscriptions.length}) about received event.`); - } - this.state.subscriptions.forEach((subscription) => subscription.handleEvent(cursor, event)); - } - // endregion - /** - User-provided subscription input associated with this {@link SubscriptionSet} object. - * - * @param forUnsubscribe - Whether list subscription input created for unsubscription (means entity should be free). - * - * @returns Subscription input object. - * - * @internal - */ - subscriptionInput(forUnsubscribe = false) { - let subscriptionInput = this.state.subscriptionInput; - this.state.subscriptions.forEach((subscription) => { - if (forUnsubscribe && subscription.state.entity.subscriptionsCount > 0) - subscriptionInput = subscriptionInput.without(subscription.state.subscriptionInput); - }); - return subscriptionInput; - } - /** - * Make a bare copy of the {@link SubscriptionSet} object. - * - * Copy won't have any type-specific listeners or added listener objects but will have the same internal state as - * the source object. - * - * @returns Bare copy of a {@link SubscriptionSet} object. - */ - cloneEmpty() { - return new SubscriptionSet({ state: this.state }); - } - /** - * Graceful {@link SubscriptionSet} destruction. - * - * This is an instance destructor, which will properly deinitialize it: - * - remove and unset all listeners, - * - try to unsubscribe (if subscribed and there are no more instances interested in the same data stream). - * - * **Note:** Disposed instance won't call the dispatcher to deliver updates to the listeners. - */ - dispose() { - const isLastClone = this.state.isLastClone; - this.state.subscriptions.forEach((subscription) => { - subscription.removeParentSet(this); - if (isLastClone) - subscription.state.removeParentState(this.state); - }); - super.dispose(); - } - /** - * Invalidate {@link SubscriptionSet} object. - * - * Clean up resources used by a subscription object. All {@link SubscriptionObject subscription} objects will be - * removed. - * - * **Important:** This method is used only when a global subscription set is used (backward compatibility). - * - * **Note:** An invalidated instance won't call the dispatcher to deliver updates to the listeners. - * - * @param forDestroy - Whether subscription object invalidated as part of PubNub client destroy process or not. - * - * @internal - */ - invalidate(forDestroy = false) { - const subscriptions = forDestroy ? this.state.subscriptions.slice(0) : this.state.subscriptions; - subscriptions.forEach((subscription) => { - if (forDestroy) { - subscription.state.entity.decreaseSubscriptionCount(this.state.id); - subscription.removeParentSet(this); - } - subscription.invalidate(forDestroy); - }); - if (forDestroy) - this.state.removeAllSubscriptions(); - super.invalidate(); - } - /** - * Add an entity's subscription to the subscription set. - * - * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. - * - * @param subscription - Another entity's subscription object, which should be added. - */ - addSubscription(subscription) { - this.addSubscriptions([subscription]); - } - /** - * Add an entity's subscriptions to the subscription set. - * - * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. - * - * @param subscriptions - List of entity's subscription objects, which should be added. - */ - addSubscriptions(subscriptions) { - const inactiveSubscriptions = []; - const activeSubscriptions = []; - this.state.client.logger.debug(this.subscriptionType, () => { - const ignoredSubscriptions = []; - const subscriptionsToAdd = []; - subscriptions.forEach((subscription) => { - if (!this.state.subscriptions.includes(subscription)) - subscriptionsToAdd.push(subscription); - else - ignoredSubscriptions.push(subscription); - }); - return { - messageType: 'object', - details: `Add subscriptions to ${this.id} (subscriptions count: ${this.state.subscriptions.length + subscriptionsToAdd.length}):`, - message: { addedSubscriptions: subscriptionsToAdd, ignoredSubscriptions }, - }; - }); - subscriptions - .filter((subscription) => !this.state.subscriptions.includes(subscription)) - .forEach((subscription) => { - if (subscription.state.isSubscribed) - activeSubscriptions.push(subscription); - else - inactiveSubscriptions.push(subscription); - subscription.addParentSet(this); - this.state.addSubscription(subscription); - }); - // Check whether there are any subscriptions for which the subscription loop should be changed or not. - if ((activeSubscriptions.length === 0 && inactiveSubscriptions.length === 0) || !this.state.isSubscribed) - return; - activeSubscriptions.forEach(({ state }) => state.entity.increaseSubscriptionCount(this.state.id)); - if (inactiveSubscriptions.length > 0) - this.updateSubscription({ subscribing: true, subscriptions: inactiveSubscriptions }); - } - /** - * Remove an entity's subscription object from the set. - * - * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. - * - * @param subscription - Another entity's subscription object, which should be removed. - */ - removeSubscription(subscription) { - this.removeSubscriptions([subscription]); - } - /** - * Remove an entity's subscription objects from the set. - * - * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. - * - * @param subscriptions - List entity's subscription objects, which should be removed. - */ - removeSubscriptions(subscriptions) { - const activeSubscriptions = []; - this.state.client.logger.debug(this.subscriptionType, () => { - const ignoredSubscriptions = []; - const subscriptionsToRemove = []; - subscriptions.forEach((subscription) => { - if (this.state.subscriptions.includes(subscription)) - subscriptionsToRemove.push(subscription); - else - ignoredSubscriptions.push(subscription); - }); - return { - messageType: 'object', - details: `Remove subscriptions from ${this.id} (subscriptions count: ${this.state.subscriptions.length}):`, - message: { removedSubscriptions: subscriptionsToRemove, ignoredSubscriptions }, - }; - }); - subscriptions - .filter((subscription) => this.state.subscriptions.includes(subscription)) - .forEach((subscription) => { - if (subscription.state.isSubscribed) - activeSubscriptions.push(subscription); - subscription.removeParentSet(this); - this.state.removeSubscription(subscription, subscription.parentSetsCount > 1); - }); - // Check whether there are any subscriptions for which the subscription loop should be changed or not. - if (activeSubscriptions.length === 0 || !this.state.isSubscribed) - return; - this.updateSubscription({ subscribing: false, subscriptions: activeSubscriptions }); - } - /** - * Merge with another {@link SubscriptionSet} object. - * - * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. - * - * @param subscriptionSet - Other entities' subscription set, which should be joined. - */ - addSubscriptionSet(subscriptionSet) { - this.addSubscriptions(subscriptionSet.subscriptions); - } - /** - * Subtract another {@link SubscriptionSet} object. - * - * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. - * - * @param subscriptionSet - Other entities' subscription set, which should be subtracted. - */ - removeSubscriptionSet(subscriptionSet) { - this.removeSubscriptions(subscriptionSet.subscriptions); - } - /** - * Register {@link SubscriptionSet} object for real-time events' retrieval. - * - * @param parameters - Object registration parameters. - * @param [parameters.cursor] - Subscription real-time events catch-up cursor. - * @param [parameters.subscriptions] - List of subscription objects which should be registered (in case of partial - * modification). - * - * @internal - */ - register(parameters) { - var _a; - const subscriptions = ((_a = parameters.subscriptions) !== null && _a !== void 0 ? _a : this.state.subscriptions); - subscriptions.forEach(({ state }) => state.entity.increaseSubscriptionCount(this.state.id)); - this.state.client.logger.trace(this.subscriptionType, () => ({ - messageType: 'text', - message: `Register subscription for real-time events: ${this}`, - })); - this.state.client.registerEventHandleCapable(this, parameters.cursor, subscriptions); - } - /** - * Unregister {@link SubscriptionSet} object from real-time events' retrieval. - * - * @param [subscriptions] - List of subscription objects which should be unregistered (in case of partial - * modification). - * - * @internal - */ - unregister(subscriptions) { - const activeSubscriptions = (subscriptions !== null && subscriptions !== void 0 ? subscriptions : this.state.subscriptions); - activeSubscriptions.forEach(({ state }) => state.entity.decreaseSubscriptionCount(this.state.id)); - this.state.client.logger.trace(this.subscriptionType, () => { - if (!subscriptions) { - return { - messageType: 'text', - message: `Unregister subscription from real-time events: ${this}`, - }; - } - else { - return { - messageType: 'object', - message: { - subscription: this, - subscriptions, - }, - details: 'Unregister subscriptions of subscription set from real-time events:', - }; - } - }); - this.state.client.unregisterEventHandleCapable(this, activeSubscriptions); - } - /** - * Stringify subscription object. - * - * @returns Serialized subscription object. - */ - toString() { - const state = this.state; - return `${this.subscriptionType} { id: ${this.id}, stateId: ${state.id}, clonesCount: ${Object.keys(this.state.clones).length}, isSubscribed: ${state.isSubscribed}, subscriptions: [${state.subscriptions - .map((sub) => sub.toString()) - .join(', ')}] }`; - } - } - - /** - * {@link Subscription} state object. - * - * State object used across multiple {@link Subscription} object clones. - * - * @internal - */ - class SubscriptionState extends SubscriptionBaseState { - /** - * Create a subscription state object. - * - * @param parameters - State configuration options - * @param parameters.client - PubNub client which will work with a subscription object. - * @param parameters.entity - Entity for which a subscription object has been created. - * @param [parameters.options] - Subscription behavior options. - */ - constructor(parameters) { - var _a, _b; - const names = parameters.entity.subscriptionNames((_b = (_a = parameters.options) === null || _a === void 0 ? void 0 : _a.receivePresenceEvents) !== null && _b !== void 0 ? _b : false); - const subscriptionInput = new SubscriptionInput({ - [parameters.entity.subscriptionType == SubscriptionType.Channel ? 'channels' : 'channelGroups']: names, - }); - super(parameters.client, subscriptionInput, parameters.options, parameters.client.subscriptionTimetoken); - this.entity = parameters.entity; - } - } - /** - * Single-entity subscription object which can be used to receive and handle real-time updates. - */ - class Subscription extends SubscriptionBase { - /** - * Create a subscribing capable object for entity. - * - * @param parameters - Subscription object configuration. - * - * @internal - */ - constructor(parameters) { - if ('client' in parameters) { - parameters.client.logger.debug('Subscription', () => ({ - messageType: 'object', - details: 'Create subscription with parameters:', - message: Object.assign({ entity: parameters.entity }, (parameters.options ? parameters.options : {})), - })); - } - else - parameters.state.client.logger.debug('Subscription', 'Create subscription clone'); - super('state' in parameters ? parameters.state : new SubscriptionState(parameters)); - /** - * List of subscription {@link SubscriptionSet sets} which contains {@link Subscription subscription}. - * - * List if used to track usage of a specific {@link Subscription subscription} in other subscription - * {@link SubscriptionSet sets}. - * - * **Important:** Tracking is required to prevent cloned instance dispose if there are sets that still use it. - * - * @internal - */ - this.parents = []; - /** - * List of fingerprints from updates which has been handled already. - * - * **Important:** Tracking is required to avoid repetitive call of the subscription object's listener when the object - * is part of multiple subscribed sets. Handler will be called once, and then the fingerprint will be stored in this - * list to avoid another listener call for it. - * - * @internal - */ - this.handledUpdates = []; - this.state.storeClone(this.id, this); - } - /** - * Get a {@link Subscription} object state. - * - * @returns: {@link Subscription} object state. - * - * @internal - */ - get state() { - return super.state; - } - /** - * Get number of {@link SubscriptionSet} which use this subscription object. - * - * @returns Number of {@link SubscriptionSet} which use this subscription object. - * - * @internal - */ - get parentSetsCount() { - return this.parents.length; - } - // -------------------------------------------------------- - // -------------------- Event handler --------------------- - // -------------------------------------------------------- - // region Event handler - /** - * Dispatch received a real-time update. - * - * @param cursor - A time cursor for the next portion of events. - * @param event - A real-time event from multiplexed subscription. - * - * @return `true` if receiver has consumed event. - * - * @internal - */ - handleEvent(cursor, event) { - var _a, _b; - if (!this.state.isSubscribed || - !this.state.subscriptionInput.contains((_a = event.data.subscription) !== null && _a !== void 0 ? _a : event.data.channel)) - return; - if (this.parentSetsCount > 0) { - // Creating from whole payload (not only for published messages). - const fingerprint = messageFingerprint(event.data); - if (this.handledUpdates.includes(fingerprint)) { - this.state.client.logger.trace(this.subscriptionType, `Event (${fingerprint}) already handled by ${this.id}. Ignoring.`); - return; - } - // Update a list of tracked messages and shrink it if too big. - this.handledUpdates.push(fingerprint); - if (this.handledUpdates.length > 10) - this.handledUpdates.shift(); - } - // Check whether an event is not designated for this subscription set. - if (!this.state.subscriptionInput.contains((_b = event.data.subscription) !== null && _b !== void 0 ? _b : event.data.channel)) - return; - super.handleEvent(cursor, event); - } - // endregion - /** - * User-provided subscription input associated with this {@link Subscription} object. - * - * @param forUnsubscribe - Whether list subscription input created for unsubscription (means entity should be free). - * - * @returns Subscription input object. - * - * @internal - */ - subscriptionInput(forUnsubscribe = false) { - if (forUnsubscribe && this.state.entity.subscriptionsCount > 0) - return new SubscriptionInput({}); - return this.state.subscriptionInput; - } - /** - * Make a bare copy of the {@link Subscription} object. - * - * Copy won't have any type-specific listeners or added listener objects but will have the same internal state as - * the source object. - * - * @returns Bare copy of a {@link Subscription} object. - */ - cloneEmpty() { - return new Subscription({ state: this.state }); - } - /** - * Graceful {@link Subscription} object destruction. - * - * This is an instance destructor, which will properly deinitialize it: - * - remove and unset all listeners, - * - try to unsubscribe (if subscribed and there are no more instances interested in the same data stream). - * - * **Important:** {@link Subscription#dispose dispose} won't have any effect if a subscription object is part of - * {@link SubscriptionSet set}. To gracefully dispose an object, it should be removed from the set using - * {@link SubscriptionSet#removeSubscription removeSubscription} (in this case call of - * {@link Subscription#dispose dispose} not required). - * - * **Note:** Disposed instance won't call the dispatcher to deliver updates to the listeners. - */ - dispose() { - if (this.parentSetsCount > 0) { - this.state.client.logger.debug(this.subscriptionType, () => ({ - messageType: 'text', - message: `'${this.state.entity.subscriptionNames()}' subscription still in use. Ignore dispose request.`, - })); - return; - } - this.handledUpdates.splice(0, this.handledUpdates.length); - super.dispose(); - } - /** - * Invalidate subscription object. - * - * Clean up resources used by a subscription object. - * - * **Note:** An invalidated instance won't call the dispatcher to deliver updates to the listeners. - * - * @param forDestroy - Whether subscription object invalidated as part of PubNub client destroy process or not. - * - * @internal - */ - invalidate(forDestroy = false) { - if (forDestroy) - this.state.entity.decreaseSubscriptionCount(this.state.id); - this.handledUpdates.splice(0, this.handledUpdates.length); - super.invalidate(forDestroy); - } - /** - * Add another {@link SubscriptionSet} into which subscription has been added. - * - * @param parent - {@link SubscriptionSet} which has been modified. - * - * @internal - */ - addParentSet(parent) { - if (!this.parents.includes(parent)) { - this.parents.push(parent); - this.state.client.logger.trace(this.subscriptionType, `Add parent subscription set for ${this.id}: ${parent.id}. Parent subscription set count: ${this.parentSetsCount}`); - } - } - /** - * Remove {@link SubscriptionSet} upon subscription removal from it. - * - * @param parent - {@link SubscriptionSet} which has been modified. - * - * @internal - */ - removeParentSet(parent) { - const parentIndex = this.parents.indexOf(parent); - if (parentIndex !== -1) { - this.parents.splice(parentIndex, 1); - this.state.client.logger.trace(this.subscriptionType, `Remove parent subscription set from ${this.id}: ${parent.id}. Parent subscription set count: ${this.parentSetsCount}`); - } - if (this.parentSetsCount === 0) - this.handledUpdates.splice(0, this.handledUpdates.length); - } - /** - * Merge entities' subscription objects into {@link SubscriptionSet}. - * - * @param subscription - Another entity's subscription object to be merged with receiver. - * - * @return {@link SubscriptionSet} which contains both receiver and other entities' subscription objects. - */ - addSubscription(subscription) { - this.state.client.logger.debug(this.subscriptionType, () => ({ - messageType: 'text', - message: `Create set with subscription: ${subscription}`, - })); - const subscriptionSet = new SubscriptionSet({ - client: this.state.client, - subscriptions: [this, subscription], - options: this.state.options, - }); - // Check whether a source subscription is already subscribed or not. - if (!this.state.isSubscribed && !subscription.state.isSubscribed) - return subscriptionSet; - this.state.client.logger.trace(this.subscriptionType, 'Subscribe resulting set because the receiver is already subscribed.'); - // Subscribing resulting subscription set because source subscription was subscribed. - subscriptionSet.subscribe(); - return subscriptionSet; - } - /** - * Register {@link Subscription} object for real-time events' retrieval. - * - * **Note:** Superclass calls this method only in response to a {@link Subscription.subscribe subscribe} method call. - * - * @param parameters - Object registration parameters. - * @param [parameters.cursor] - Subscription real-time events catch-up cursor. - * @param [parameters.subscriptions] - List of subscription objects which should be registered (in case of partial - * modification). - * - * @internal - */ - register(parameters) { - this.state.entity.increaseSubscriptionCount(this.state.id); - this.state.client.logger.trace(this.subscriptionType, () => ({ - messageType: 'text', - message: `Register subscription for real-time events: ${this}`, - })); - this.state.client.registerEventHandleCapable(this, parameters.cursor); - } - /** - * Unregister {@link Subscription} object from real-time events' retrieval. - * - * **Note:** Superclass calls this method only in response to a {@link Subscription.unsubscribe unsubscribe} method - * call. - * - * @param [_subscriptions] - List of subscription objects which should be unregistered (in case of partial - * modification). - * - * @internal - */ - unregister(_subscriptions) { - this.state.entity.decreaseSubscriptionCount(this.state.id); - this.state.client.logger.trace(this.subscriptionType, () => ({ - messageType: 'text', - message: `Unregister subscription from real-time events: ${this}`, - })); - this.handledUpdates.splice(0, this.handledUpdates.length); - this.state.client.unregisterEventHandleCapable(this); - } - /** - * Stringify subscription object. - * - * @returns Serialized subscription object. - */ - toString() { - const state = this.state; - return `${this.subscriptionType} { id: ${this.id}, stateId: ${state.id}, entity: ${state.entity - .subscriptionNames(false) - .pop()}, clonesCount: ${Object.keys(state.clones).length}, isSubscribed: ${state.isSubscribed}, parentSetsCount: ${this.parentSetsCount}, cursor: ${state.cursor ? state.cursor.timetoken : 'not set'}, referenceTimetoken: ${state.referenceTimetoken ? state.referenceTimetoken : 'not set'} }`; - } - } - - /** - * Get Presence State REST API module. - * - * @internal - */ - // endregion - /** - * Get `uuid` presence state request. - * - * @internal - */ - class GetPresenceStateRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b; - var _c, _d; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = (_c = this.parameters).channels) !== null && _a !== void 0 ? _a : (_c.channels = []); - (_b = (_d = this.parameters).channelGroups) !== null && _b !== void 0 ? _b : (_d.channelGroups = []); - } - operation() { - return RequestOperation$1.PNGetStateOperation; - } - validate() { - const { keySet: { subscribeKey }, channels, channelGroups, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - const serviceResponse = this.deserializeResponse(response); - const { channels = [], channelGroups = [] } = this.parameters; - const state = { channels: {} }; - if (channels.length === 1 && channelGroups.length === 0) - state.channels[channels[0]] = serviceResponse.payload; - else - state.channels = serviceResponse.payload; - return state; - }); - } - get path() { - const { keySet: { subscribeKey }, uuid, channels, } = this.parameters; - return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}/uuid/${encodeString(uuid !== null && uuid !== void 0 ? uuid : '')}`; - } - get queryParameters() { - const { channelGroups } = this.parameters; - if (!channelGroups || channelGroups.length === 0) - return {}; - return { 'channel-group': channelGroups.join(',') }; - } - } - - /** - * Set Presence State REST API module. - * - * @internal - */ - // endregion - /** - * Set `uuid` presence state request. - * - * @internal - */ - class SetPresenceStateRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSetStateOperation; - } - validate() { - const { keySet: { subscribeKey }, state, channels = [], channelGroups = [], } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (state === undefined) - return 'Missing State'; - if ((channels === null || channels === void 0 ? void 0 : channels.length) === 0 && (channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.length) === 0) - return 'Please provide a list of channels and/or channel-groups'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { state: this.deserializeResponse(response).payload }; - }); - } - get path() { - const { keySet: { subscribeKey }, uuid, channels, } = this.parameters; - return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}/uuid/${encodeString(uuid)}/data`; - } - get queryParameters() { - const { channelGroups, state } = this.parameters; - const query = { state: JSON.stringify(state) }; - if (channelGroups && channelGroups.length !== 0) - query['channel-group'] = channelGroups.join(','); - return query; - } - } - - /** - * Announce heartbeat REST API module. - * - * @internal - */ - // endregion - /** - * Announce `uuid` presence request. - * - * @internal - */ - class HeartbeatRequest extends AbstractRequest { - constructor(parameters) { - super({ cancellable: true }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNHeartbeatOperation; - } - validate() { - const { keySet: { subscribeKey }, channels = [], channelGroups = [], } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (channels.length === 0 && channelGroups.length === 0) - return 'Please provide a list of channels and/or channel-groups'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - get path() { - const { keySet: { subscribeKey }, channels, } = this.parameters; - return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}/heartbeat`; - } - get queryParameters() { - const { channelGroups, state, heartbeat } = this.parameters; - const query = { heartbeat: `${heartbeat}` }; - if (channelGroups && channelGroups.length !== 0) - query['channel-group'] = channelGroups.join(','); - if (state !== undefined) - query.state = JSON.stringify(state); - return query; - } - } - - /** - * Announce leave REST API module. - * - * @internal - */ - // endregion - /** - * Announce user leave request. - * - * @internal - */ - class PresenceLeaveRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - if (this.parameters.channelGroups) - this.parameters.channelGroups = Array.from(new Set(this.parameters.channelGroups)); - if (this.parameters.channels) - this.parameters.channels = Array.from(new Set(this.parameters.channels)); - } - operation() { - return RequestOperation$1.PNUnsubscribeOperation; - } - validate() { - const { keySet: { subscribeKey }, channels = [], channelGroups = [], } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (channels.length === 0 && channelGroups.length === 0) - return 'At least one `channel` or `channel group` should be provided.'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - get path() { - var _a; - const { keySet: { subscribeKey }, channels, } = this.parameters; - return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames((_a = channels === null || channels === void 0 ? void 0 : channels.sort()) !== null && _a !== void 0 ? _a : [], ',')}/leave`; - } - get queryParameters() { - const { channelGroups } = this.parameters; - if (!channelGroups || channelGroups.length === 0) - return {}; - return { 'channel-group': channelGroups.sort().join(',') }; - } - } - - /** - * `uuid` presence REST API module. - * - * @internal - */ - // endregion - /** - * Get `uuid` presence request. - * - * @internal - */ - class WhereNowRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNWhereNowOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - const serviceResponse = this.deserializeResponse(response); - if (!serviceResponse.payload) - return { channels: [] }; - return { channels: serviceResponse.payload.channels }; - }); - } - get path() { - const { keySet: { subscribeKey }, uuid, } = this.parameters; - return `/v2/presence/sub-key/${subscribeKey}/uuid/${encodeString(uuid)}`; - } - } - - /** - * Channels / channel groups presence REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `uuid` should be included in response or not. - */ - const INCLUDE_UUID$1 = true; - /** - * Whether state associated with `uuid` should be included in response or not. - */ - const INCLUDE_STATE = false; - /** - * Maximum number of participants which can be returned with single response. - */ - const MAXIMUM_COUNT = 1000; - // endregion - /** - * Channel presence request. - * - * @internal - */ - class HereNowRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d; - var _e, _f, _g, _h; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = (_e = this.parameters).queryParameters) !== null && _a !== void 0 ? _a : (_e.queryParameters = {}); - (_b = (_f = this.parameters).includeUUIDs) !== null && _b !== void 0 ? _b : (_f.includeUUIDs = INCLUDE_UUID$1); - (_c = (_g = this.parameters).includeState) !== null && _c !== void 0 ? _c : (_g.includeState = INCLUDE_STATE); - (_d = (_h = this.parameters).limit) !== null && _d !== void 0 ? _d : (_h.limit = MAXIMUM_COUNT); - } - operation() { - const { channels = [], channelGroups = [] } = this.parameters; - return channels.length === 0 && channelGroups.length === 0 - ? RequestOperation$1.PNGlobalHereNowOperation - : RequestOperation$1.PNHereNowOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b; - const serviceResponse = this.deserializeResponse(response); - // Extract general presence information. - const totalChannels = 'occupancy' in serviceResponse ? 1 : serviceResponse.payload.total_channels; - const totalOccupancy = 'occupancy' in serviceResponse ? serviceResponse.occupancy : serviceResponse.payload.total_occupancy; - const channelsPresence = {}; - let channels = {}; - const limit = this.parameters.limit; - let occupancyMatchLimit = false; - // Remap single channel presence to multiple channels presence response. - if ('occupancy' in serviceResponse) { - const channel = this.parameters.channels[0]; - channels[channel] = { uuids: (_a = serviceResponse.uuids) !== null && _a !== void 0 ? _a : [], occupancy: totalOccupancy }; - } - else - channels = (_b = serviceResponse.payload.channels) !== null && _b !== void 0 ? _b : {}; - Object.keys(channels).forEach((channel) => { - const channelEntry = channels[channel]; - channelsPresence[channel] = { - occupants: this.parameters.includeUUIDs - ? channelEntry.uuids.map((uuid) => { - if (typeof uuid === 'string') - return { uuid, state: null }; - return uuid; - }) - : [], - name: channel, - occupancy: channelEntry.occupancy, - }; - if (!occupancyMatchLimit && channelEntry.occupancy === limit) - occupancyMatchLimit = true; - }); - return { - totalChannels, - totalOccupancy, - channels: channelsPresence, - }; - }); - } - get path() { - const { keySet: { subscribeKey }, channels, channelGroups, } = this.parameters; - let path = `/v2/presence/sub-key/${subscribeKey}`; - if ((channels && channels.length > 0) || (channelGroups && channelGroups.length > 0)) - path += `/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}`; - return path; - } - get queryParameters() { - const { channelGroups, includeUUIDs, includeState, limit, offset, queryParameters } = this.parameters; - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (this.operation() === RequestOperation$1.PNHereNowOperation ? { limit } : {})), (this.operation() === RequestOperation$1.PNHereNowOperation && (offset !== null && offset !== void 0 ? offset : 0 > 0) ? { offset } : {})), (!includeUUIDs ? { disable_uuids: '1' } : {})), ((includeState !== null && includeState !== void 0 ? includeState : false) ? { state: '1' } : {})), (channelGroups && channelGroups.length > 0 ? { 'channel-group': channelGroups.join(',') } : {})), queryParameters); - } - } - - /** - * Delete messages REST API module. - * - * @internal - */ - // endregion - /** - * Delete messages from channel history. - * - * @internal - */ - class DeleteMessageRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNDeleteMessagesOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - if (!this.parameters.channel) - return 'Missing channel'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v3/history/sub-key/${subscribeKey}/channel/${encodeString(channel)}`; - } - get queryParameters() { - const { start, end } = this.parameters; - return Object.assign(Object.assign({}, (start ? { start } : {})), (end ? { end } : {})); - } - } - - /** - * Messages count REST API module. - * - * @internal - */ - // endregion - /** - * Count messages request. - * - * @internal - */ - class MessageCountRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNMessageCounts; - } - validate() { - const { keySet: { subscribeKey }, channels, timetoken, channelTimetokens, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channels) - return 'Missing channels'; - if (timetoken && channelTimetokens) - return '`timetoken` and `channelTimetokens` are incompatible together'; - if (!timetoken && !channelTimetokens) - return '`timetoken` or `channelTimetokens` need to be set'; - if (channelTimetokens && channelTimetokens.length > 1 && channelTimetokens.length !== channels.length) - return 'Length of `channelTimetokens` and `channels` do not match'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { channels: this.deserializeResponse(response).channels }; - }); - } - get path() { - return `/v3/history/sub-key/${this.parameters.keySet.subscribeKey}/message-counts/${encodeNames(this.parameters.channels)}`; - } - get queryParameters() { - let { channelTimetokens } = this.parameters; - if (this.parameters.timetoken) - channelTimetokens = [this.parameters.timetoken]; - return Object.assign(Object.assign({}, (channelTimetokens.length === 1 ? { timetoken: channelTimetokens[0] } : {})), (channelTimetokens.length > 1 ? { channelsTimetoken: channelTimetokens.join(',') } : {})); - } - } - - /** - * Get history REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ---------------------- Defaults ------------------------ - // -------------------------------------------------------- - // region Defaults - /** - * Whether verbose logging enabled or not. - */ - const LOG_VERBOSITY$1 = false; - /** - * Whether associated message metadata should be returned or not. - */ - const INCLUDE_METADATA = false; - /** - * Whether timetokens should be returned as strings by default or not. - */ - const STRINGIFY_TIMETOKENS$1 = false; - /** - * Default and maximum number of messages which should be returned. - */ - const MESSAGES_COUNT = 100; - // endregion - /** - * Get single channel messages request. - * - * @internal - */ - class GetHistoryRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c; - super(); - this.parameters = parameters; - // Apply defaults. - if (parameters.count) - parameters.count = Math.min(parameters.count, MESSAGES_COUNT); - else - parameters.count = MESSAGES_COUNT; - (_a = parameters.stringifiedTimeToken) !== null && _a !== void 0 ? _a : (parameters.stringifiedTimeToken = STRINGIFY_TIMETOKENS$1); - (_b = parameters.includeMeta) !== null && _b !== void 0 ? _b : (parameters.includeMeta = INCLUDE_METADATA); - (_c = parameters.logVerbosity) !== null && _c !== void 0 ? _c : (parameters.logVerbosity = LOG_VERBOSITY$1); - } - operation() { - return RequestOperation$1.PNHistoryOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - if (!this.parameters.channel) - return 'Missing channel'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - const serviceResponse = this.deserializeResponse(response); - const messages = serviceResponse[0]; - const startTimeToken = serviceResponse[1]; - const endTimeToken = serviceResponse[2]; - // Handle malformed get history response. - if (!Array.isArray(messages)) - return { messages: [], startTimeToken, endTimeToken }; - return { - messages: messages.map((payload) => { - const processedPayload = this.processPayload(payload.message); - const item = { - entry: processedPayload.payload, - timetoken: payload.timetoken, - }; - if (processedPayload.error) - item.error = processedPayload.error; - if (payload.meta) - item.meta = payload.meta; - return item; - }), - startTimeToken, - endTimeToken, - }; - }); - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v2/history/sub-key/${subscribeKey}/channel/${encodeString(channel)}`; - } - get queryParameters() { - const { start, end, reverse, count, stringifiedTimeToken, includeMeta } = this.parameters; - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: count, include_token: 'true' }, (start ? { start } : {})), (end ? { end } : {})), (stringifiedTimeToken ? { string_message_token: 'true' } : {})), (reverse !== undefined && reverse !== null ? { reverse: reverse.toString() } : {})), (includeMeta ? { include_meta: 'true' } : {})); - } - processPayload(payload) { - const { crypto, logVerbosity } = this.parameters; - if (!crypto || typeof payload !== 'string') - return { payload }; - let decryptedPayload; - let error; - try { - const decryptedData = crypto.decrypt(payload); - decryptedPayload = - decryptedData instanceof ArrayBuffer - ? JSON.parse(GetHistoryRequest.decoder.decode(decryptedData)) - : decryptedData; - } - catch (err) { - if (logVerbosity) - console.log(`decryption error`, err.message); - decryptedPayload = payload; - error = `Error while decrypting message content: ${err.message}`; - } - return { - payload: decryptedPayload, - error, - }; - } - } - - // endregion - // -------------------------------------------------------- - // -------------------- Fetch Messages -------------------- - // -------------------------------------------------------- - // region Fetch Messages - /** - * PubNub-defined message type. - * - * Types of messages which can be retrieved with fetch messages REST API. - */ - var PubNubMessageType; - (function (PubNubMessageType) { - /** - * Regular message. - */ - PubNubMessageType[PubNubMessageType["Message"] = -1] = "Message"; - /** - * File message. - */ - PubNubMessageType[PubNubMessageType["Files"] = 4] = "Files"; - })(PubNubMessageType || (PubNubMessageType = {})); - // endregion - - /** - * Fetch messages REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ---------------------- Defaults ------------------------ - // -------------------------------------------------------- - // region Defaults - /** - * Whether verbose logging enabled or not. - */ - const LOG_VERBOSITY = false; - /** - * Whether message type should be returned or not. - */ - const INCLUDE_MESSAGE_TYPE = true; - /** - * Whether timetokens should be returned as strings by default or not. - */ - const STRINGIFY_TIMETOKENS = false; - /** - * Whether message publisher `uuid` should be returned or not. - */ - const INCLUDE_UUID = true; - /** - * Default number of messages which can be returned for single channel, and it is maximum as well. - */ - const SINGLE_CHANNEL_MESSAGES_COUNT = 100; - /** - * Default number of messages which can be returned for multiple channels or when fetched - * message actions. - */ - const MULTIPLE_CHANNELS_MESSAGES_COUNT = 25; - // endregion - /** - * Fetch messages from channels request. - * - * @internal - */ - class FetchMessagesRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d, _e; - super(); - this.parameters = parameters; - // Apply defaults. - const includeMessageActions = (_a = parameters.includeMessageActions) !== null && _a !== void 0 ? _a : false; - const defaultCount = parameters.channels.length > 1 || includeMessageActions - ? MULTIPLE_CHANNELS_MESSAGES_COUNT - : SINGLE_CHANNEL_MESSAGES_COUNT; - if (!parameters.count) - parameters.count = defaultCount; - else - parameters.count = Math.min(parameters.count, defaultCount); - if (parameters.includeUuid) - parameters.includeUUID = parameters.includeUuid; - else - (_b = parameters.includeUUID) !== null && _b !== void 0 ? _b : (parameters.includeUUID = INCLUDE_UUID); - (_c = parameters.stringifiedTimeToken) !== null && _c !== void 0 ? _c : (parameters.stringifiedTimeToken = STRINGIFY_TIMETOKENS); - (_d = parameters.includeMessageType) !== null && _d !== void 0 ? _d : (parameters.includeMessageType = INCLUDE_MESSAGE_TYPE); - (_e = parameters.logVerbosity) !== null && _e !== void 0 ? _e : (parameters.logVerbosity = LOG_VERBOSITY); - } - operation() { - return RequestOperation$1.PNFetchMessagesOperation; - } - validate() { - const { keySet: { subscribeKey }, channels, includeMessageActions, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channels) - return 'Missing channels'; - if (includeMessageActions !== undefined && includeMessageActions && channels.length > 1) - return ('History can return actions data for a single channel only. Either pass a single channel ' + - 'or disable the includeMessageActions flag.'); - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - const serviceResponse = this.deserializeResponse(response); - const responseChannels = (_a = serviceResponse.channels) !== null && _a !== void 0 ? _a : {}; - const channels = {}; - Object.keys(responseChannels).forEach((channel) => { - // Map service response to expected data object type structure. - channels[channel] = responseChannels[channel].map((payload) => { - // `null` message type means regular message. - if (payload.message_type === null) - payload.message_type = PubNubMessageType.Message; - const processedPayload = this.processPayload(channel, payload); - const item = Object.assign(Object.assign({ channel, timetoken: payload.timetoken, message: processedPayload.payload, messageType: payload.message_type }, (payload.custom_message_type ? { customMessageType: payload.custom_message_type } : {})), { uuid: payload.uuid }); - if (payload.actions) { - const itemWithActions = item; - itemWithActions.actions = payload.actions; - // Backward compatibility for existing users. - // TODO: Remove in next release. - itemWithActions.data = payload.actions; - } - if (payload.meta) - item.meta = payload.meta; - if (processedPayload.error) - item.error = processedPayload.error; - return item; - }); - }); - if (serviceResponse.more) - return { channels, more: serviceResponse.more }; - return { channels }; - }); - } - get path() { - const { keySet: { subscribeKey }, channels, includeMessageActions, } = this.parameters; - const endpoint = !includeMessageActions ? 'history' : 'history-with-actions'; - return `/v3/${endpoint}/sub-key/${subscribeKey}/channel/${encodeNames(channels)}`; - } - get queryParameters() { - const { start, end, count, includeCustomMessageType, includeMessageType, includeMeta, includeUUID, stringifiedTimeToken, } = this.parameters; - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ max: count }, (start ? { start } : {})), (end ? { end } : {})), (stringifiedTimeToken ? { string_message_token: 'true' } : {})), (includeMeta !== undefined && includeMeta ? { include_meta: 'true' } : {})), (includeUUID ? { include_uuid: 'true' } : {})), (includeCustomMessageType !== undefined && includeCustomMessageType !== null - ? { include_custom_message_type: includeCustomMessageType ? 'true' : 'false' } - : {})), (includeMessageType ? { include_message_type: 'true' } : {})); - } - /** - * Parse single channel data entry. - * - * @param channel - Channel for which {@link payload} should be processed. - * @param payload - Source payload which should be processed and parsed to expected type. - * - * @returns - */ - processPayload(channel, payload) { - const { crypto, logVerbosity } = this.parameters; - if (!crypto || typeof payload.message !== 'string') - return { payload: payload.message }; - let decryptedPayload; - let error; - try { - const decryptedData = crypto.decrypt(payload.message); - decryptedPayload = - decryptedData instanceof ArrayBuffer - ? JSON.parse(FetchMessagesRequest.decoder.decode(decryptedData)) - : decryptedData; - } - catch (err) { - if (logVerbosity) - console.log(`decryption error`, err.message); - decryptedPayload = payload.message; - error = `Error while decrypting message content: ${err.message}`; - } - if (!error && - decryptedPayload && - payload.message_type == PubNubMessageType.Files && - typeof decryptedPayload === 'object' && - this.isFileMessage(decryptedPayload)) { - const fileMessage = decryptedPayload; - return { - payload: { - message: fileMessage.message, - file: Object.assign(Object.assign({}, fileMessage.file), { url: this.parameters.getFileUrl({ channel, id: fileMessage.file.id, name: fileMessage.file.name }) }), - }, - error, - }; - } - return { payload: decryptedPayload, error }; - } - /** - * Check whether `payload` potentially represents file message. - * - * @param payload - Fetched message payload. - * - * @returns `true` if payload can be {@link History#FileMessage|FileMessage}. - */ - isFileMessage(payload) { - return payload.file !== undefined; - } - } - - /** - * Get Message Actions REST API module. - * - * @internal - */ - // endregion - /** - * Fetch channel message actions request. - * - * @internal - */ - class GetMessageActionsRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetMessageActionsOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - if (!this.parameters.channel) - return 'Missing message channel'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - const serviceResponse = this.deserializeResponse(response); - let start = null; - let end = null; - if (serviceResponse.data.length > 0) { - start = serviceResponse.data[0].actionTimetoken; - end = serviceResponse.data[serviceResponse.data.length - 1].actionTimetoken; - } - return { - data: serviceResponse.data, - more: serviceResponse.more, - start, - end, - }; - }); - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v1/message-actions/${subscribeKey}/channel/${encodeString(channel)}`; - } - get queryParameters() { - const { limit, start, end } = this.parameters; - return Object.assign(Object.assign(Object.assign({}, (start ? { start } : {})), (end ? { end } : {})), (limit ? { limit } : {})); - } - } - - /** - * Add Message Action REST API module. - * - * @internal - */ - // endregion - /** - * Add Message Reaction request. - * - * @internal - */ - class AddMessageActionRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNAddMessageActionOperation; - } - validate() { - const { keySet: { subscribeKey }, action, channel, messageTimetoken, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channel) - return 'Missing message channel'; - if (!messageTimetoken) - return 'Missing message timetoken'; - if (!action) - return 'Missing Action'; - if (!action.value) - return 'Missing Action.value'; - if (!action.type) - return 'Missing Action.type'; - if (action.type.length > 15) - return 'Action.type value exceed maximum length of 15'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then(({ data }) => ({ data })); - }); - } - get path() { - const { keySet: { subscribeKey }, channel, messageTimetoken, } = this.parameters; - return `/v1/message-actions/${subscribeKey}/channel/${encodeString(channel)}/message/${messageTimetoken}`; - } - get headers() { - var _a; - return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); - } - get body() { - return JSON.stringify(this.parameters.action); - } - } - - /** - * Remove Message Action REST API module. - * - * @internal - */ - // endregion - /** - * Remove specific message action request. - * - * @internal - */ - class RemoveMessageAction extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveMessageActionOperation; - } - validate() { - const { keySet: { subscribeKey }, channel, messageTimetoken, actionTimetoken, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channel) - return 'Missing message action channel'; - if (!messageTimetoken) - return 'Missing message timetoken'; - if (!actionTimetoken) - return 'Missing action timetoken'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then(({ data }) => ({ data })); - }); - } - get path() { - const { keySet: { subscribeKey }, channel, actionTimetoken, messageTimetoken, } = this.parameters; - return `/v1/message-actions/${subscribeKey}/channel/${encodeString(channel)}/message/${messageTimetoken}/action/${actionTimetoken}`; - } - } - - /** - * Publish File Message REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether published file messages should be stored in the channel's history. - */ - const STORE_IN_HISTORY = true; - // endregion - /** - * Publish shared file information request. - * - * @internal - */ - class PublishFileMessageRequest extends AbstractRequest { - constructor(parameters) { - var _a; - var _b; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = (_b = this.parameters).storeInHistory) !== null && _a !== void 0 ? _a : (_b.storeInHistory = STORE_IN_HISTORY); - } - operation() { - return RequestOperation$1.PNPublishFileMessageOperation; - } - validate() { - const { channel, fileId, fileName } = this.parameters; - if (!channel) - return "channel can't be empty"; - if (!fileId) - return "file id can't be empty"; - if (!fileName) - return "file name can't be empty"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { timetoken: this.deserializeResponse(response)[2] }; - }); - } - get path() { - const { message, channel, keySet: { publishKey, subscribeKey }, fileId, fileName, } = this.parameters; - const fileMessage = Object.assign({ file: { - name: fileName, - id: fileId, - } }, (message ? { message } : {})); - return `/v1/files/publish-file/${publishKey}/${subscribeKey}/0/${encodeString(channel)}/0/${encodeString(this.prepareMessagePayload(fileMessage))}`; - } - get queryParameters() { - const { customMessageType, storeInHistory, ttl, meta } = this.parameters; - return Object.assign(Object.assign(Object.assign({ store: storeInHistory ? '1' : '0' }, (customMessageType ? { custom_message_type: customMessageType } : {})), (ttl ? { ttl } : {})), (meta && typeof meta === 'object' ? { meta: JSON.stringify(meta) } : {})); - } - /** - * Pre-process provided data. - * - * Data will be "normalized" and encrypted if `cryptoModule` has been provided. - * - * @param payload - User-provided data which should be pre-processed before use. - * - * @returns Payload which can be used as part of request URL or body. - * - * @throws {Error} in case if provided `payload` or results of `encryption` can't be stringified. - */ - prepareMessagePayload(payload) { - const { crypto } = this.parameters; - if (!crypto) - return JSON.stringify(payload) || ''; - const encrypted = crypto.encrypt(JSON.stringify(payload)); - return JSON.stringify(typeof encrypted === 'string' ? encrypted : encode(encrypted)); - } - } - - /** - * File sharing REST API module. - * - * @internal - */ - // endregion - /** - * File download Url generation request. - * - * Local request which generates Url to download shared file from the specific channel. - * - * @internal - */ - class GetFileDownloadUrlRequest extends AbstractRequest { - /** - * Construct file download Url generation request. - * - * @param parameters - Request configuration. - */ - constructor(parameters) { - super({ method: TransportMethod.LOCAL }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetFileUrlOperation; - } - validate() { - const { channel, id, name } = this.parameters; - if (!channel) - return "channel can't be empty"; - if (!id) - return "file id can't be empty"; - if (!name) - return "file name can't be empty"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return response.url; - }); - } - get path() { - const { channel, id, name, keySet: { subscribeKey }, } = this.parameters; - return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files/${encodeString(id)}/${encodeString(name)}`; - } - } - - /** - * Delete file REST API module. - * - * @internal - */ - // endregion - /** - * Delete File request. - * - * @internal - */ - class DeleteFileRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNDeleteFileOperation; - } - validate() { - const { channel, id, name } = this.parameters; - if (!channel) - return "channel can't be empty"; - if (!id) - return "file id can't be empty"; - if (!name) - return "file name can't be empty"; - } - get path() { - const { keySet: { subscribeKey }, id, channel, name, } = this.parameters; - return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files/${encodeString(id)}/${encodeString(name)}`; - } - } - - /** - * List Files REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Number of files to return in response. - */ - const LIMIT$6 = 100; - // endregion - /** - * Files List request. - * - * @internal - */ - class FilesListRequest extends AbstractRequest { - constructor(parameters) { - var _a; - var _b; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = (_b = this.parameters).limit) !== null && _a !== void 0 ? _a : (_b.limit = LIMIT$6); - } - operation() { - return RequestOperation$1.PNListFilesOperation; - } - validate() { - if (!this.parameters.channel) - return "channel can't be empty"; - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files`; - } - get queryParameters() { - const { limit, next } = this.parameters; - return Object.assign({ limit: limit }, (next ? { next } : {})); - } - } - - /** - * Generate file upload URL REST API request. - * - * @internal - */ - // endregion - /** - * Generate File Upload Url request. - * - * @internal - */ - class GenerateFileUploadUrlRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGenerateUploadUrlOperation; - } - validate() { - if (!this.parameters.channel) - return "channel can't be empty"; - if (!this.parameters.name) - return "'name' can't be empty"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - const serviceResponse = this.deserializeResponse(response); - return { - id: serviceResponse.data.id, - name: serviceResponse.data.name, - url: serviceResponse.file_upload_request.url, - formFields: serviceResponse.file_upload_request.form_fields, - }; - }); - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/generate-upload-url`; - } - get headers() { - var _a; - return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); - } - get body() { - return JSON.stringify({ name: this.parameters.name }); - } - } - - /** - * Upload file REST API request. - * - * @internal - */ - /** - * File Upload request. - * - * @internal - */ - class UploadFileRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - // Use file's actual mime type if available. - const mimeType = parameters.file.mimeType; - if (mimeType) { - parameters.formFields = parameters.formFields.map((entry) => { - if (entry.name === 'Content-Type') - return { name: entry.name, value: mimeType }; - return entry; - }); - } - } - operation() { - return RequestOperation$1.PNPublishFileOperation; - } - validate() { - const { fileId, fileName, file, uploadUrl } = this.parameters; - if (!fileId) - return "Validation failed: file 'id' can't be empty"; - if (!fileName) - return "Validation failed: file 'name' can't be empty"; - if (!file) - return "Validation failed: 'file' can't be empty"; - if (!uploadUrl) - return "Validation failed: file upload 'url' can't be empty"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { - status: response.status, - message: response.body ? UploadFileRequest.decoder.decode(response.body) : 'OK', - }; - }); - } - request() { - return Object.assign(Object.assign({}, super.request()), { origin: new URL(this.parameters.uploadUrl).origin, timeout: 300 }); - } - get path() { - const { pathname, search } = new URL(this.parameters.uploadUrl); - return `${pathname}${search}`; - } - get body() { - return this.parameters.file; - } - get formData() { - return this.parameters.formFields; - } - } - - /** - * Share File API module. - * - * @internal - */ - // endregion - /** - * Send file composed request. - * - * @internal - */ - class SendFileRequest { - constructor(parameters) { - var _a; - this.parameters = parameters; - this.file = (_a = this.parameters.PubNubFile) === null || _a === void 0 ? void 0 : _a.create(parameters.file); - if (!this.file) - throw new Error('File upload error: unable to create File object.'); - } - /** - * Process user-input and upload file. - * - * @returns File upload request response. - */ - process() { - return __awaiter(this, void 0, void 0, function* () { - let fileName; - let fileId; - return this.generateFileUploadUrl() - .then((result) => { - fileName = result.name; - fileId = result.id; - return this.uploadFile(result); - }) - .then((result) => { - if (result.status !== 204) { - throw new PubNubError('Upload to bucket was unsuccessful', { - error: true, - statusCode: result.status, - category: StatusCategory$1.PNUnknownCategory, - operation: RequestOperation$1.PNPublishFileOperation, - errorData: { message: result.message }, - }); - } - }) - .then(() => this.publishFileMessage(fileId, fileName)) - .catch((error) => { - if (error instanceof PubNubError) - throw error; - const apiError = !(error instanceof PubNubAPIError) ? PubNubAPIError.create(error) : error; - throw new PubNubError('File upload error.', apiError.toStatus(RequestOperation$1.PNPublishFileOperation)); - }); - }); - } - /** - * Generate pre-signed file upload Url. - * - * @returns File upload credentials. - */ - generateFileUploadUrl() { - return __awaiter(this, void 0, void 0, function* () { - const request = new GenerateFileUploadUrlRequest(Object.assign(Object.assign({}, this.parameters), { name: this.file.name, keySet: this.parameters.keySet })); - return this.parameters.sendRequest(request); - }); - } - /** - * Prepare and upload {@link PubNub} File object to remote storage. - * - * @param uploadParameters - File upload request parameters. - * - * @returns - */ - uploadFile(uploadParameters) { - return __awaiter(this, void 0, void 0, function* () { - const { cipherKey, PubNubFile, crypto, cryptography } = this.parameters; - const { id, name, url, formFields } = uploadParameters; - // Encrypt file if possible. - if (this.parameters.PubNubFile.supportsEncryptFile) { - if (!cipherKey && crypto) - this.file = (yield crypto.encryptFile(this.file, PubNubFile)); - else if (cipherKey && cryptography) - this.file = (yield cryptography.encryptFile(cipherKey, this.file, PubNubFile)); - } - return this.parameters.sendRequest(new UploadFileRequest({ - fileId: id, - fileName: name, - file: this.file, - uploadUrl: url, - formFields, - })); - }); - } - publishFileMessage(fileId, fileName) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b, _c, _d; - let result = { timetoken: '0' }; - let retries = this.parameters.fileUploadPublishRetryLimit; - let publishError; - let wasSuccessful = false; - do { - try { - result = yield this.parameters.publishFile(Object.assign(Object.assign({}, this.parameters), { fileId, fileName })); - wasSuccessful = true; - } - catch (error) { - if (error instanceof PubNubError) - publishError = error; - retries -= 1; - } - } while (!wasSuccessful && retries > 0); - if (!wasSuccessful) { - throw new PubNubError('Publish failed. You may want to execute that operation manually using pubnub.publishFile', { - error: true, - category: (_b = (_a = publishError.status) === null || _a === void 0 ? void 0 : _a.category) !== null && _b !== void 0 ? _b : StatusCategory$1.PNUnknownCategory, - statusCode: (_d = (_c = publishError.status) === null || _c === void 0 ? void 0 : _c.statusCode) !== null && _d !== void 0 ? _d : 0, - channel: this.parameters.channel, - id: fileId, - name: fileName, - }); - } - else - return { status: 200, timetoken: result.timetoken, id: fileId, name: fileName }; - }); - } - } - - /** - * Common entity interface. - */ - class Entity { - /** - * Create an entity instance. - * - * @param nameOrId - Identifier which will be used with subscription loop. - * @param client - PubNub instance which has been used to create this entity. - * - * @internal - */ - constructor(nameOrId, client) { - /** - * List of subscription state object IDs which are using this entity. - * - * @internal - */ - this.subscriptionStateIds = []; - this.client = client; - this._nameOrId = nameOrId; - } - /** - * Retrieve entity type. - * - * @return One of known {@link EntityType entity types}. - * - * @internal - */ - get entityType() { - return 'Channel'; - } - /** - * Type of subscription entity. - * - * Type defines where it will be used with multiplexed subscribe REST API calls. - * - * @retuerns One of {@link SubscriptionType} enum fields. - * - * @internal - */ - get subscriptionType() { - return SubscriptionType.Channel; - } - /** - * Names for an object to be used in subscription. - * - * Provided strings will be used with multiplexed subscribe REST API calls. - * - * @param receivePresenceEvents - Whether presence events should be observed or not. - * - * @returns List of names with multiplexed subscribe REST API calls (may include additional names to receive presence - * updates). - * - * @internal - */ - subscriptionNames(receivePresenceEvents) { - { - return [ - this._nameOrId, - ...(receivePresenceEvents && !this._nameOrId.endsWith('-pnpres') ? [`${this._nameOrId}-pnpres`] : []), - ]; - } - } - /** - * Create a subscribable's subscription object for real-time updates. - * - * Create a subscription object which can be used to subscribe to the real-time updates sent to the specific data - * stream. - * - * @param [subscriptionOptions] - Subscription object behavior customization options. - * - * @returns Configured and ready to use subscribable's subscription object. - */ - subscription(subscriptionOptions) { - { - return new Subscription({ - client: this.client, - entity: this, - options: subscriptionOptions, - }); - } - } - /** - * How many active subscriptions use this entity. - * - * @internal - */ - get subscriptionsCount() { - return this.subscriptionStateIds.length; - } - /** - * Increase the number of active subscriptions. - * - * @param subscriptionStateId - Unique identifier of the subscription state object which doesn't use entity anymore. - * - * @internal - */ - increaseSubscriptionCount(subscriptionStateId) { - { - if (!this.subscriptionStateIds.includes(subscriptionStateId)) - this.subscriptionStateIds.push(subscriptionStateId); - } - } - /** - * Decrease the number of active subscriptions. - * - * **Note:** As long as the entity is used by at least one subscription, it can't be removed from the subscription. - * - * @param subscriptionStateId - Unique identifier of the subscription state object which doesn't use entity anymore. - * - * @internal - */ - decreaseSubscriptionCount(subscriptionStateId) { - { - const index = this.subscriptionStateIds.indexOf(subscriptionStateId); - if (index >= 0) - this.subscriptionStateIds.splice(index, 1); - } - } - /** - * Stringify entity object. - * - * @returns Serialized entity object. - */ - toString() { - return `${this.entityType} { nameOrId: ${this._nameOrId}, subscriptionsCount: ${this.subscriptionsCount} }`; - } - } - - /** - * Projection names which are observed on the object's base (un-prefixed) data channel. - * - * @internal - */ - const BASE_PROJECTIONS = ['default', '__default__']; - /** - * Key under which the base (un-prefixed) projection is stored in the variants registry. - * - * @internal - */ - const BASE_PROJECTION_KEY = ''; - /** - * Normalize a user-provided DataSync projection name. - * - * **Note:** Only the projection name is normalized. A DataSync object identifier is always used - * verbatim (so wildcard identifiers keep working by construction). - * - * @param [projection] - Projection name as provided by the user. - * - * @returns Trimmed projection name or `undefined` when the base projection is requested. - * - * @internal - */ - const normalizedProjection = (projection) => { - if (!projection) - return undefined; - const trimmed = projection.trim(); - if (trimmed.length === 0 || BASE_PROJECTIONS.includes(trimmed.toLowerCase())) - return undefined; - return trimmed; - }; - /** - * Base class for DataSync objects which can be observed with the subscribe REST API. - * - * A DataSync object is observed on a data channel named after its identifier, optionally prefixed - * with the name of an observed projection: `__{projection}__{id}`. - * - * **Note:** The identifier is used verbatim, so an identifier which already looks prefixed - * (`__admin__u1`) will be prefixed again when a projection is requested (`__admin____admin__u1`). - */ - class DataSyncSubscribable extends Entity { - /** - * Create a DataSync object entity. - * - * @param nameOrId - Unique DataSync object identifier (used verbatim). - * @param client - PubNub instance which has been used to create this entity. - * @param [projection] - Name of the projection which should be observed by this entity. - * - * @internal - */ - constructor(nameOrId, client, projection) { - super(nameOrId, client); - this._projection = normalizedProjection(projection); - } - /** - * Get unique DataSync object identifier. - * - * @returns DataSync object identifier. - */ - get id() { - return this._nameOrId; - } - /** - * Get the name of the projection which is observed by this entity. - * - * **Note:** A projection is chosen per subscription - * ({@link DataSyncSubscriptionOptions#projection}), so an entity created by the PubNub client - * always reports `undefined` here: it is the base-projection entity, and the entities bound to - * other projections are internal to it. - * - * @returns Observed projection name or `undefined` when the object is observed through its base - * projection. - */ - get projection() { - return this._projection; - } - /** - * Name of the data channel which is used with multiplexed subscribe REST API calls. - * - * @returns Name of the observed data channel. - * - * @internal - */ - get subscriptionChannel() { - return this._projection ? `__${this._projection}__${this._nameOrId}` : this._nameOrId; - } - /** - * Names for an object to be used in subscription. - * - * **Note:** A DataSync object is observed on a single data channel; presence events are not - * supported for it and `_receivePresenceEvents` is ignored. - * - * @param _receivePresenceEvents - Whether presence events should be observed or not. - * - * @returns List of names with multiplexed subscribe REST API calls. - * - * @internal - */ - subscriptionNames(_receivePresenceEvents) { - return [this.subscriptionChannel]; - } - /** - * Create a DataSync object's subscription object for real-time updates. - * - * @param [subscriptionOptions] - Subscription object behavior customization options. - * - * @returns Configured and ready to use DataSync object's subscription object. - * - * @example - * ```typescript - * // Observe the object itself. - * pubnub.dataSyncUser('u1').subscription().subscribe(); - * - * // Observe the `admin` projection of the object (the `__admin__u1` data channel). - * pubnub.dataSyncUser('u1').subscription({ projection: 'admin' }).subscribe(); - * ``` - */ - subscription(subscriptionOptions) { - { - const entity = this.entityForProjection(normalizedProjection(subscriptionOptions === null || subscriptionOptions === void 0 ? void 0 : subscriptionOptions.projection)); - // Each projection is observed on its own data channel, so it must be represented by its own - // entity instance (see `variants`). Let the entity which owns the requested projection create - // the subscription object for itself: it resolves that same projection to itself, so this - // delegation is always a single hop. - if (entity !== this) - return entity.subscription(subscriptionOptions); - return super.subscription(subscriptionOptions); - } - } - /** - * Resolve the entity which observes the same DataSync object through `projection`. - * - * @param [projection] - Normalized name of the projection to observe. - * - * @returns Receiver itself, or the memoized sibling entity bound to `projection`. - * - * @internal - */ - entityForProjection(projection) { - var _a, _b, _c; - var _d; - if (projection === this._projection) - return this; - // Register the receiver in the shared registry, so that it can be resolved back from siblings. - // - // Note: the receiver is added with an element assignment and never as part of an object literal - // which is assigned to `variants`. Declaration files for this module are inferred from the - // compiled JavaScript (`allowJs`), where a `this.variants = { ...: this }` statement would make - // the inferred member type reference the inaccessible polymorphic `this` type (TS2527). - const variants = ((_a = this.variants) !== null && _a !== void 0 ? _a : (this.variants = {})); - (_c = variants[_d = (_b = this._projection) !== null && _b !== void 0 ? _b : BASE_PROJECTION_KEY]) !== null && _c !== void 0 ? _c : (variants[_d] = this); - const key = projection !== null && projection !== void 0 ? projection : BASE_PROJECTION_KEY; - let entity = variants[key]; - if (!entity) { - entity = variants[key] = this.withProjection(projection); - entity.variants = variants; - } - return entity; - } - /** - * Stringify entity object. - * - * @returns Serialized entity object. - */ - toString() { - var _a; - return (`${this.entityType} { id: ${this._nameOrId}, projection: ${(_a = this._projection) !== null && _a !== void 0 ? _a : 'none'}, ` + - `channel: ${this.subscriptionChannel}, subscriptionsCount: ${this.subscriptionsCount} }`); - } - } - - /** - * First-class object which provides access to the real-time updates of a DataSync `Relationship` - * object. - * - * **Important:** The service delivers relationship changes on the data channels of **both linked - * entities** (`entityAId` and `entityBId`), and never on the relationship's own identifier. Observe - * `pubnub.dataSyncEntity(...)` for the linked entities to receive relationship updates; this entity - * is only useful if a key set is configured to publish relationship changes on the relationship - * identifier itself. - */ - class DataSyncRelationship extends DataSyncSubscribable { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'DataSyncRelationship'; - } - /** - * Create a copy of the receiver which observes `projection` of the same DataSync `Relationship` - * object. - * - * @param [projection] - Normalized name of the projection to observe. - * - * @returns `DataSyncRelationship` entity bound to `projection`. - * - * @internal - */ - withProjection(projection) { - return new DataSyncRelationship(this._nameOrId, this.client, projection); - } - } - - /** - * First-class object which provides access to the real-time updates of a DataSync `Membership` - * object. - * - * **Note:** A membership identifier is composite (`{userId}:{channelId}`) and is used verbatim as - * the name of the observed data channel. - * - * **Important:** The service delivers membership changes on the data channels of **both linked - * entities** (the user identifier and the channel identifier), and never on the membership's own - * identifier. Observe `pubnub.dataSyncUser(...)` and/or `pubnub.dataSyncChannel(...)` to receive - * membership updates; this entity is only useful if a key set is configured to publish membership - * changes on the membership identifier itself. - */ - class DataSyncMembership extends DataSyncSubscribable { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'DataSyncMembership'; - } - /** - * Create a copy of the receiver which observes `projection` of the same DataSync `Membership` - * object. - * - * @param [projection] - Normalized name of the projection to observe. - * - * @returns `DataSyncMembership` entity bound to `projection`. - * - * @internal - */ - withProjection(projection) { - return new DataSyncMembership(this._nameOrId, this.client, projection); - } - } - - /** - * First-class object which provides access to the real-time updates of a DataSync `Channel` object. - */ - class DataSyncChannel extends DataSyncSubscribable { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'DataSyncChannel'; - } - /** - * Create a copy of the receiver which observes `projection` of the same DataSync `Channel` object. - * - * @param [projection] - Normalized name of the projection to observe. - * - * @returns `DataSyncChannel` entity bound to `projection`. - * - * @internal - */ - withProjection(projection) { - return new DataSyncChannel(this._nameOrId, this.client, projection); - } - } - - /** - * First-class object which provides access to the real-time updates of a DataSync `Entity` object. - */ - class DataSyncEntity extends DataSyncSubscribable { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'DataSyncEntity'; - } - /** - * Create a copy of the receiver which observes `projection` of the same DataSync `Entity` object. - * - * @param [projection] - Normalized name of the projection to observe. - * - * @returns `DataSyncEntity` entity bound to `projection`. - * - * @internal - */ - withProjection(projection) { - return new DataSyncEntity(this._nameOrId, this.client, projection); - } - } - - /** - * First-class objects which provides access to the channel app context object-specific APIs. - */ - class ChannelMetadata extends Entity { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'ChannelMetadata'; - } - /** - * Get unique channel metadata object identifier. - * - * @returns Channel metadata identifier. - */ - get id() { - return this._nameOrId; - } - /** - * Names for an object to be used in subscription. - * - * Provided strings will be used with multiplexed subscribe REST API calls. - * - * @param _receivePresenceEvents - Whether presence events should be observed or not. - * - * @returns List of names with multiplexed subscribe REST API calls (may include additional names to receive presence - * updates). - * - * @internal - */ - subscriptionNames(_receivePresenceEvents) { - return [this.id]; - } - } - - /** - * First-class object which provides access to the real-time updates of a DataSync `User` object. - */ - class DataSyncUser extends DataSyncSubscribable { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'DataSyncUser'; - } - /** - * Create a copy of the receiver which observes `projection` of the same DataSync `User` object. - * - * @param [projection] - Normalized name of the projection to observe. - * - * @returns `DataSyncUser` entity bound to `projection`. - * - * @internal - */ - withProjection(projection) { - return new DataSyncUser(this._nameOrId, this.client, projection); - } - } - - /** - * First-class objects which provides access to the channel group-specific APIs. - */ - class ChannelGroup extends Entity { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'ChannelGroups'; - } - /** - * Get a unique channel group name. - * - * @returns Channel group name. - */ - get name() { - return this._nameOrId; - } - /** - * Type of subscription entity. - * - * Type defines where it will be used with multiplexed subscribe REST API calls. - * - * @retuerns One of {@link SubscriptionType} enum fields. - * - * @internal - */ - get subscriptionType() { - return SubscriptionType.ChannelGroup; - } - } - - /** - * First-class objects which provides access to the user app context object-specific APIs. - */ - class UserMetadata extends Entity { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'UserMetadata'; - } - /** - * Get unique user metadata object identifier. - * - * @returns User metadata identifier. - */ - get id() { - return this._nameOrId; - } - /** - * Names for an object to be used in subscription. - * - * Provided strings will be used with multiplexed subscribe REST API calls. - * - * @param _receivePresenceEvents - Whether presence events should be observed or not. - * - * @returns List of names with multiplexed subscribe REST API calls (may include additional names to receive presence - * updates). - * - * @internal - */ - subscriptionNames(_receivePresenceEvents) { - return [this.id]; - } - } - - /** - * First-class objects which provides access to the channel-specific APIs. - */ - class Channel extends Entity { - /** - * Retrieve entity type. - * - * @return One of known entity types. - * - * @internal - */ - get entityType() { - return 'Channel'; - } - /** - * Get a unique channel name. - * - * @returns Channel name. - */ - get name() { - return this._nameOrId; - } - } - - /** - * Remove channel group channels REST API module. - * - * @internal - */ - // endregion - /** - * Remove channel group channels request. - * - * @internal - */ - // prettier-ignore - class RemoveChannelGroupChannelsRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveChannelsFromGroupOperation; - } - validate() { - const { keySet: { subscribeKey }, channels, channelGroup, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channelGroup) - return 'Missing Channel Group'; - if (!channels) - return 'Missing channels'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - get path() { - const { keySet: { subscribeKey }, channelGroup, } = this.parameters; - return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}`; - } - get queryParameters() { - return { remove: this.parameters.channels.join(',') }; - } - } - - /** - * Add channel group channels REST API module. - * - * @internal - */ - // endregion - /** - * Add channel group channels request. - * - * @internal - */ - class AddChannelGroupChannelsRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNAddChannelsToGroupOperation; - } - validate() { - const { keySet: { subscribeKey }, channels, channelGroup, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!channelGroup) - return 'Missing Channel Group'; - if (!channels) - return 'Missing channels'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - get path() { - const { keySet: { subscribeKey }, channelGroup, } = this.parameters; - return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}`; - } - get queryParameters() { - return { add: this.parameters.channels.join(',') }; - } - } - - /** - * List channel group channels REST API module. - * - * @internal - */ - // endregion - /** - * List Channel Group Channels request. - * - * @internal - */ - class ListChannelGroupChannels extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNChannelsForGroupOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - if (!this.parameters.channelGroup) - return 'Missing Channel Group'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { channels: this.deserializeResponse(response).payload.channels }; - }); - } - get path() { - const { keySet: { subscribeKey }, channelGroup, } = this.parameters; - return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}`; - } - } - - /** - * Delete channel group REST API module. - * - * @internal - */ - // endregion - /** - * Channel group delete request. - * - * @internal - */ - class DeleteChannelGroupRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveGroupOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - if (!this.parameters.channelGroup) - return 'Missing Channel Group'; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - get path() { - const { keySet: { subscribeKey }, channelGroup, } = this.parameters; - return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}/remove`; - } - } - - /** - * List All Channel Groups REST API module. - * - * @internal - */ - // endregion - /** - * List all channel groups request. - * - * @internal - */ - class ListChannelGroupsRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNChannelGroupsOperation; - } - validate() { - if (!this.parameters.keySet.subscribeKey) - return 'Missing Subscribe Key'; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { groups: this.deserializeResponse(response).payload.groups }; - }); - } - get path() { - return `/v1/channel-registration/sub-key/${this.parameters.keySet.subscribeKey}/channel-group`; - } - } - - /** - * PubNub Channel Groups API module. - */ - /** - * PubNub Stream / Channel group API interface. - */ - class PubNubChannelGroups { - /** - * Create stream / channel group API access object. - * - * @param logger - Registered loggers' manager. - * @param keySet - PubNub account keys set which should be used for REST API calls. - * @param sendRequest - Function which should be used to send REST API calls. - * - * @internal - */ - constructor(logger, keySet, - /* eslint-disable @typescript-eslint/no-explicit-any */ - sendRequest) { - this.sendRequest = sendRequest; - this.logger = logger; - this.keySet = keySet; - } - /** - * Fetch channel group channels. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get channel group channels response or `void` in case if `callback` - * provided. - */ - listChannels(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'List channel group channels with parameters:', - })); - const request = new ListChannelGroupChannels(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `List channel group channels success. Received ${response.channels.length} channels.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Fetch all channel groups. - * - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all channel groups response or `void` in case if `callback` provided. - * - * @deprecated - */ - listGroups(callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', 'List all channel groups.'); - const request = new ListChannelGroupsRequest({ keySet: this.keySet }); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `List all channel groups success. Received ${response.groups.length} groups.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Add channels to the channel group. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous add channels to the channel group response or `void` in case if - * `callback` provided. - */ - addChannels(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Add channels to the channel group with parameters:', - })); - const request = new AddChannelGroupChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = () => { - this.logger.debug('PubNub', `Add channels to the channel group success.`); - }; - if (callback) - return this.sendRequest(request, (status) => { - if (!status.error) - logResponse(); - callback(status); - }); - return this.sendRequest(request).then((response) => { - logResponse(); - return response; - }); - }); - } - /** - * Remove channels from the channel group. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove channels from the channel group response or `void` in - * case if `callback` provided. - */ - removeChannels(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove channels from the channel group with parameters:', - })); - const request = new RemoveChannelGroupChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = () => { - this.logger.debug('PubNub', `Remove channels from the channel group success.`); - }; - if (callback) - return this.sendRequest(request, (status) => { - if (!status.error) - logResponse(); - callback(status); - }); - return this.sendRequest(request).then((response) => { - logResponse(); - return response; - }); - }); - } - /** - * Remove a channel group. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove channel group response or `void` in case if `callback` provided. - */ - deleteGroup(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove a channel group with parameters:', - })); - const request = new DeleteChannelGroupRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = () => { - this.logger.debug('PubNub', `Remove a channel group success. Removed '${parameters.channelGroup}' channel group.'`); - }; - if (callback) - return this.sendRequest(request, (status) => { - if (!status.error) - logResponse(); - callback(status); - }); - return this.sendRequest(request).then((response) => { - logResponse(); - return response; - }); - }); - } - } - - /** - * Manage channels enabled for device push REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Environment for which APNS2 notifications - */ - const ENVIRONMENT = 'development'; - /** - * Maximum number of channels in `list` response. - */ - const MAX_COUNT = 1000; - // endregion - /** - * Base push notification request. - * - * @internal - */ - class BasePushNotificationChannelsRequest extends AbstractRequest { - constructor(parameters) { - var _a; - var _b; - super(); - this.parameters = parameters; - // Apply request defaults - if (this.parameters.pushGateway === 'apns2') - (_a = (_b = this.parameters).environment) !== null && _a !== void 0 ? _a : (_b.environment = ENVIRONMENT); - if (this.parameters.count && this.parameters.count > MAX_COUNT) - this.parameters.count = MAX_COUNT; - } - operation() { - throw Error('Should be implemented in subclass.'); - } - validate() { - const { keySet: { subscribeKey }, action, device, pushGateway, } = this.parameters; - if (!subscribeKey) - return 'Missing Subscribe Key'; - if (!device) - return 'Missing Device ID (device)'; - if ((action === 'add' || action === 'remove') && - (!('channels' in this.parameters) || this.parameters.channels.length === 0)) - return 'Missing Channels'; - if (!pushGateway) - return 'Missing GW Type (pushGateway: fcm or apns2)'; - if (this.parameters.pushGateway === 'apns2' && !this.parameters.topic) - return 'Missing APNS2 topic'; - } - get path() { - const { keySet: { subscribeKey }, action, device, pushGateway, } = this.parameters; - let path = pushGateway === 'apns2' - ? `/v2/push/sub-key/${subscribeKey}/devices-apns2/${device}` - : `/v1/push/sub-key/${subscribeKey}/devices/${device}`; - if (action === 'remove-device') - path = `${path}/remove`; - return path; - } - get queryParameters() { - const { start, count } = this.parameters; - let query = Object.assign(Object.assign({ type: this.parameters.pushGateway }, (start ? { start } : {})), (count && count > 0 ? { count } : {})); - if ('channels' in this.parameters) - query[this.parameters.action] = this.parameters.channels.join(','); - if (this.parameters.pushGateway === 'apns2') { - const { environment, topic } = this.parameters; - query = Object.assign(Object.assign({}, query), { environment: environment, topic }); - } - return query; - } - } - - /** - * Unregister Channels from Device push REST API module. - * - * @internal - */ - // endregion - /** - * Unregister channels from device push request. - * - * @internal - */ - // prettier-ignore - class RemoveDevicePushNotificationChannelsRequest extends BasePushNotificationChannelsRequest { - constructor(parameters) { - super(Object.assign(Object.assign({}, parameters), { action: 'remove' })); - } - operation() { - return RequestOperation$1.PNRemovePushNotificationEnabledChannelsOperation; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - } - - /** - * List Device push enabled channels REST API module. - * - * @internal - */ - // endregion - /** - * List device push enabled channels request. - * - * @internal - */ - // prettier-ignore - class ListDevicePushNotificationChannelsRequest extends BasePushNotificationChannelsRequest { - constructor(parameters) { - super(Object.assign(Object.assign({}, parameters), { action: 'list' })); - } - operation() { - return RequestOperation$1.PNPushNotificationEnabledChannelsOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { channels: this.deserializeResponse(response) }; - }); - } - } - - /** - * Register Channels with Device push REST API module. - * - * @internal - */ - // endregion - /** - * Register channels with device push request. - * - * @internal - */ - // prettier-ignore - class AddDevicePushNotificationChannelsRequest extends BasePushNotificationChannelsRequest { - constructor(parameters) { - super(Object.assign(Object.assign({}, parameters), { action: 'add' })); - } - operation() { - return RequestOperation$1.PNAddPushNotificationEnabledChannelsOperation; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - } - - /** - * Unregister Device push REST API module. - * - * @internal - */ - // endregion - /** - * Unregister device push notifications request. - * - * @internal - */ - // prettier-ignore - class RemoveDevicePushNotificationRequest extends BasePushNotificationChannelsRequest { - constructor(parameters) { - super(Object.assign(Object.assign({}, parameters), { action: 'remove-device' })); - } - operation() { - return RequestOperation$1.PNRemoveAllPushNotificationsOperation; - } - parse(response) { - const _super = Object.create(null, { - parse: { get: () => super.parse } - }); - return __awaiter(this, void 0, void 0, function* () { - return _super.parse.call(this, response).then((_) => ({})); - }); - } - } - - /** - * PubNub Push Notifications API module. - */ - /** - * PubNub Push Notifications API interface. - */ - class PubNubPushNotifications { - /** - * Create mobile push notifications API access object. - * - * @param logger - Registered loggers' manager. - * @param keySet - PubNub account keys set which should be used for REST API calls. - * @param sendRequest - Function which should be used to send REST API calls. - * - * @internal - */ - constructor(logger, keySet, - /* eslint-disable @typescript-eslint/no-explicit-any */ - sendRequest) { - this.sendRequest = sendRequest; - this.logger = logger; - this.keySet = keySet; - } - /** - * Fetch device's push notification enabled channels. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get device channels response or `void` in case if `callback` provided. - */ - listChannels(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `List push-enabled channels with parameters:`, - })); - const request = new ListDevicePushNotificationChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `List push-enabled channels success. Received ${response.channels.length} channels.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Enable push notifications on channels for device. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - */ - addChannels(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Add push-enabled channels with parameters:`, - })); - const request = new AddDevicePushNotificationChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = () => { - this.logger.debug('PubNub', `Add push-enabled channels success.`); - }; - if (callback) - return this.sendRequest(request, (status) => { - if (!status.error) - logResponse(); - callback(status); - }); - return this.sendRequest(request).then((response) => { - logResponse(); - return response; - }); - }); - } - /** - * Disable push notifications on channels for device. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - */ - removeChannels(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove push-enabled channels with parameters:`, - })); - const request = new RemoveDevicePushNotificationChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = () => { - this.logger.debug('PubNub', `Remove push-enabled channels success.`); - }; - if (callback) - return this.sendRequest(request, (status) => { - if (!status.error) - logResponse(); - callback(status); - }); - return this.sendRequest(request).then((response) => { - logResponse(); - return response; - }); - }); - } - /** - * Disable push notifications for device. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - */ - deleteDevice(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove push notifications for device with parameters:`, - })); - const request = new RemoveDevicePushNotificationRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = () => { - this.logger.debug('PubNub', `Remove push notifications for device success.`); - }; - if (callback) - return this.sendRequest(request, (status) => { - if (!status.error) - logResponse(); - callback(status); - }); - return this.sendRequest(request).then((response) => { - logResponse(); - return response; - }); - }); - } - } - - /** - * Get All Channel Metadata REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Channel` custom fields should be included in response or not. - */ - const INCLUDE_CUSTOM_FIELDS$9 = false; - /** - * Whether total number of channels should be included in response or not. - */ - const INCLUDE_TOTAL_COUNT$4 = false; - /** - * Number of objects to return in response. - */ - const LIMIT$5 = 100; - // endregion - /** - * Get All Channels Metadata request. - * - * @internal - */ - class GetAllChannelsMetadataRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d; - var _e, _f; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_e = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_e.customFields = INCLUDE_CUSTOM_FIELDS$9); - (_c = (_f = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_f.totalCount = INCLUDE_TOTAL_COUNT$4); - (_d = parameters.limit) !== null && _d !== void 0 ? _d : (parameters.limit = LIMIT$5); - } - operation() { - return RequestOperation$1.PNGetAllChannelMetadataOperation; - } - get path() { - return `/v2/objects/${this.parameters.keySet.subscribeKey}/channels`; - } - get queryParameters() { - const { include, page, filter, sort, limit } = this.parameters; - let sorting = ''; - if (typeof sort === 'string') - sorting = sort; - else - sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ include: ['status', 'type', ...(include.customFields ? ['custom'] : [])].join(','), count: `${include.totalCount}` }, (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Remove Channel Metadata REST API module. - * - * @internal - */ - // endregion - /** - * Remove Channel Metadata request. - * - * @internal - */ - class RemoveChannelMetadataRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveChannelMetadataOperation; - } - validate() { - if (!this.parameters.channel) - return 'Channel cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}`; - } - } - - /** - * Get UUID Memberships REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Membership` custom field should be included in response or not. - */ - const INCLUDE_CUSTOM_FIELDS$8 = false; - /** - * Whether membership's `status` field should be included in response or not. - */ - const INCLUDE_STATUS$3 = false; - /** - * Whether membership's `type` field should be included in response or not. - */ - const INCLUDE_TYPE$3 = false; - /** - * Whether total number of memberships should be included in response or not. - */ - const INCLUDE_TOTAL_COUNT$3 = false; - /** - * Whether `Channel` fields should be included in response or not. - */ - const INCLUDE_CHANNEL_FIELDS$1 = false; - /** - * Whether `Channel` status field should be included in response or not. - */ - const INCLUDE_CHANNEL_STATUS_FIELD$1 = false; - /** - * Whether `Channel` type field should be included in response or not. - */ - const INCLUDE_CHANNEL_TYPE_FIELD$1 = false; - /** - * Whether `Channel` custom field should be included in response or not. - */ - const INCLUDE_CHANNEL_CUSTOM_FIELDS$1 = false; - /** - * Number of objects to return in response. - */ - const LIMIT$4 = 100; - // endregion - /** - * Get UUID Memberships request. - * - * @internal - */ - class GetUUIDMembershipsRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; - var _l, _m, _o, _p, _q, _r, _s, _t; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$8); - (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT$3); - (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS$3); - (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE$3); - (_f = (_q = parameters.include).channelFields) !== null && _f !== void 0 ? _f : (_q.channelFields = INCLUDE_CHANNEL_FIELDS$1); - (_g = (_r = parameters.include).customChannelFields) !== null && _g !== void 0 ? _g : (_r.customChannelFields = INCLUDE_CHANNEL_CUSTOM_FIELDS$1); - (_h = (_s = parameters.include).channelStatusField) !== null && _h !== void 0 ? _h : (_s.channelStatusField = INCLUDE_CHANNEL_STATUS_FIELD$1); - (_j = (_t = parameters.include).channelTypeField) !== null && _j !== void 0 ? _j : (_t.channelTypeField = INCLUDE_CHANNEL_TYPE_FIELD$1); - (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT$4); - // Remap for backward compatibility. - if (this.parameters.userId) - this.parameters.uuid = this.parameters.userId; - } - operation() { - return RequestOperation$1.PNGetMembershipsOperation; - } - validate() { - if (!this.parameters.uuid) - return "'uuid' cannot be empty"; - } - get path() { - const { keySet: { subscribeKey }, uuid, } = this.parameters; - return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}/channels`; - } - get queryParameters() { - const { include, page, filter, sort, limit } = this.parameters; - let sorting = ''; - if (typeof sort === 'string') - sorting = sort; - else - sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - const includeFlags = []; - if (include.statusField) - includeFlags.push('status'); - if (include.typeField) - includeFlags.push('type'); - if (include.customFields) - includeFlags.push('custom'); - if (include.channelFields) - includeFlags.push('channel'); - if (include.channelStatusField) - includeFlags.push('channel.status'); - if (include.channelTypeField) - includeFlags.push('channel.type'); - if (include.customChannelFields) - includeFlags.push('channel.custom'); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set UUID Memberships REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Membership` custom field should be included in response or not. - */ - const INCLUDE_CUSTOM_FIELDS$7 = false; - /** - * Whether membership's `status` field should be included in response or not. - */ - const INCLUDE_STATUS$2 = false; - /** - * Whether membership's `type` field should be included in response or not. - */ - const INCLUDE_TYPE$2 = false; - /** - * Whether total number of memberships should be included in response or not. - */ - const INCLUDE_TOTAL_COUNT$2 = false; - /** - * Whether `Channel` fields should be included in response or not. - */ - const INCLUDE_CHANNEL_FIELDS = false; - /** - * Whether `Channel` status field should be included in response or not. - */ - const INCLUDE_CHANNEL_STATUS_FIELD = false; - /** - * Whether `Channel` type field should be included in response or not. - */ - const INCLUDE_CHANNEL_TYPE_FIELD = false; - /** - * Whether `Channel` custom field should be included in response or not. - */ - const INCLUDE_CHANNEL_CUSTOM_FIELDS = false; - /** - * Number of objects to return in response. - */ - const LIMIT$3 = 100; - // endregion - /** - * Set UUID Memberships request. - * - * @internal - */ - class SetUUIDMembershipsRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; - var _l, _m, _o, _p, _q, _r, _s, _t; - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$7); - (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT$2); - (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS$2); - (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE$2); - (_f = (_q = parameters.include).channelFields) !== null && _f !== void 0 ? _f : (_q.channelFields = INCLUDE_CHANNEL_FIELDS); - (_g = (_r = parameters.include).customChannelFields) !== null && _g !== void 0 ? _g : (_r.customChannelFields = INCLUDE_CHANNEL_CUSTOM_FIELDS); - (_h = (_s = parameters.include).channelStatusField) !== null && _h !== void 0 ? _h : (_s.channelStatusField = INCLUDE_CHANNEL_STATUS_FIELD); - (_j = (_t = parameters.include).channelTypeField) !== null && _j !== void 0 ? _j : (_t.channelTypeField = INCLUDE_CHANNEL_TYPE_FIELD); - (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT$3); - // Remap for backward compatibility. - if (this.parameters.userId) - this.parameters.uuid = this.parameters.userId; - } - operation() { - return RequestOperation$1.PNSetMembershipsOperation; - } - validate() { - const { uuid, channels } = this.parameters; - if (!uuid) - return "'uuid' cannot be empty"; - if (!channels || channels.length === 0) - return 'Channels cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, uuid, } = this.parameters; - return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}/channels`; - } - get queryParameters() { - const { include, page, filter, sort, limit } = this.parameters; - let sorting = ''; - if (typeof sort === 'string') - sorting = sort; - else - sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - const includeFlags = ['channel.status', 'channel.type', 'status']; - if (include.statusField) - includeFlags.push('status'); - if (include.typeField) - includeFlags.push('type'); - if (include.customFields) - includeFlags.push('custom'); - if (include.channelFields) - includeFlags.push('channel'); - if (include.channelStatusField) - includeFlags.push('channel.status'); - if (include.channelTypeField) - includeFlags.push('channel.type'); - if (include.customChannelFields) - includeFlags.push('channel.custom'); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); - } - get headers() { - var _a; - return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); - } - get body() { - const { channels, type } = this.parameters; - return JSON.stringify({ - [`${type}`]: channels.map((channel) => { - if (typeof channel === 'string') { - return { channel: { id: channel } }; - } - else { - return { channel: { id: channel.id }, status: channel.status, type: channel.type, custom: channel.custom }; - } - }), - }); - } - } - - /** - * Get All UUID Metadata REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Channel` custom field should be included by default or not. - */ - const INCLUDE_CUSTOM_FIELDS$6 = false; - /** - * Number of objects to return in response. - */ - const LIMIT$2 = 100; - // endregion - /** - * Get All UUIDs Metadata request. - * - * @internal - */ - class GetAllUUIDMetadataRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c; - var _d; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_d = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_d.customFields = INCLUDE_CUSTOM_FIELDS$6); - (_c = parameters.limit) !== null && _c !== void 0 ? _c : (parameters.limit = LIMIT$2); - } - operation() { - return RequestOperation$1.PNGetAllUUIDMetadataOperation; - } - get path() { - return `/v2/objects/${this.parameters.keySet.subscribeKey}/uuids`; - } - get queryParameters() { - const { include, page, filter, sort, limit } = this.parameters; - let sorting = ''; - if (typeof sort === 'string') - sorting = sort; - else - sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ include: ['status', 'type', ...(include.customFields ? ['custom'] : [])].join(',') }, (include.totalCount !== undefined ? { count: `${include.totalCount}` } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Get Channel Metadata REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Channel` custom field should be included by default or not. - */ - const INCLUDE_CUSTOM_FIELDS$5 = true; - // endregion - /** - * Get Channel Metadata request. - * - * @internal - */ - class GetChannelMetadataRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b; - var _c; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS$5); - } - operation() { - return RequestOperation$1.PNGetChannelMetadataOperation; - } - validate() { - if (!this.parameters.channel) - return 'Channel cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}`; - } - get queryParameters() { - return { - include: ['status', 'type', ...(this.parameters.include.customFields ? ['custom'] : [])].join(','), - }; - } - } - - /** - * Set Channel Metadata REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Channel` custom field should be included by default or not. - */ - const INCLUDE_CUSTOM_FIELDS$4 = true; - // endregion - /** - * Set Channel Metadata request. - * - * @internal - */ - class SetChannelMetadataRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b; - var _c; - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS$4); - } - operation() { - return RequestOperation$1.PNSetChannelMetadataOperation; - } - validate() { - if (!this.parameters.channel) - return 'Channel cannot be empty'; - if (!this.parameters.data) - return 'Data cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json' }); - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}`; - } - get queryParameters() { - return { - include: ['status', 'type', ...(this.parameters.include.customFields ? ['custom'] : [])].join(','), - }; - } - get body() { - return JSON.stringify(this.parameters.data); - } - } - - /** - * Remove UUID Metadata REST API module. - * - * @internal - */ - // endregion - /** - * Remove UUID Metadata request. - * - * @internal - */ - class RemoveUUIDMetadataRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - // Remap for backward compatibility. - if (this.parameters.userId) - this.parameters.uuid = this.parameters.userId; - } - operation() { - return RequestOperation$1.PNRemoveUUIDMetadataOperation; - } - validate() { - if (!this.parameters.uuid) - return "'uuid' cannot be empty"; - } - get path() { - const { keySet: { subscribeKey }, uuid, } = this.parameters; - return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}`; - } - } - - /** - * Get Channel Members REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Member` custom field should be included in response or not. - */ - const INCLUDE_CUSTOM_FIELDS$3 = false; - /** - * Whether member's `status` field should be included in response or not. - */ - const INCLUDE_STATUS$1 = false; - /** - * Whether member's `type` field should be included in response or not. - */ - const INCLUDE_TYPE$1 = false; - /** - * Whether total number of members should be included in response or not. - */ - const INCLUDE_TOTAL_COUNT$1 = false; - /** - * Whether `UUID` fields should be included in response or not. - */ - const INCLUDE_UUID_FIELDS$1 = false; - /** - * Whether `UUID` status field should be included in response or not. - */ - const INCLUDE_UUID_STATUS_FIELD$1 = false; - /** - * Whether `UUID` type field should be included in response or not. - */ - const INCLUDE_UUID_TYPE_FIELD$1 = false; - /** - * Whether `UUID` custom field should be included in response or not. - */ - const INCLUDE_UUID_CUSTOM_FIELDS$1 = false; - /** - * Number of objects to return in response. - */ - const LIMIT$1 = 100; - // endregion - /** - * Get Channel Members request. - * - * @internal - */ - class GetChannelMembersRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; - var _l, _m, _o, _p, _q, _r, _s, _t; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$3); - (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT$1); - (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS$1); - (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE$1); - (_f = (_q = parameters.include).UUIDFields) !== null && _f !== void 0 ? _f : (_q.UUIDFields = INCLUDE_UUID_FIELDS$1); - (_g = (_r = parameters.include).customUUIDFields) !== null && _g !== void 0 ? _g : (_r.customUUIDFields = INCLUDE_UUID_CUSTOM_FIELDS$1); - (_h = (_s = parameters.include).UUIDStatusField) !== null && _h !== void 0 ? _h : (_s.UUIDStatusField = INCLUDE_UUID_STATUS_FIELD$1); - (_j = (_t = parameters.include).UUIDTypeField) !== null && _j !== void 0 ? _j : (_t.UUIDTypeField = INCLUDE_UUID_TYPE_FIELD$1); - (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT$1); - } - operation() { - return RequestOperation$1.PNSetMembersOperation; - } - validate() { - if (!this.parameters.channel) - return 'Channel cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}/uuids`; - } - get queryParameters() { - const { include, page, filter, sort, limit } = this.parameters; - let sorting = ''; - if (typeof sort === 'string') - sorting = sort; - else - sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - const includeFlags = []; - if (include.statusField) - includeFlags.push('status'); - if (include.typeField) - includeFlags.push('type'); - if (include.customFields) - includeFlags.push('custom'); - if (include.UUIDFields) - includeFlags.push('uuid'); - if (include.UUIDStatusField) - includeFlags.push('uuid.status'); - if (include.UUIDTypeField) - includeFlags.push('uuid.type'); - if (include.customUUIDFields) - includeFlags.push('uuid.custom'); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set Channel Members REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Member` custom field should be included in response or not. - */ - const INCLUDE_CUSTOM_FIELDS$2 = false; - /** - * Whether member's `status` field should be included in response or not. - */ - const INCLUDE_STATUS = false; - /** - * Whether member's `type` field should be included in response or not. - */ - const INCLUDE_TYPE = false; - /** - * Whether total number of members should be included in response or not. - */ - const INCLUDE_TOTAL_COUNT = false; - /** - * Whether `UUID` fields should be included in response or not. - */ - const INCLUDE_UUID_FIELDS = false; - /** - * Whether `UUID` status field should be included in response or not. - */ - const INCLUDE_UUID_STATUS_FIELD = false; - /** - * Whether `UUID` type field should be included in response or not. - */ - const INCLUDE_UUID_TYPE_FIELD = false; - /** - * Whether `UUID` custom field should be included in response or not. - */ - const INCLUDE_UUID_CUSTOM_FIELDS = false; - /** - * Number of objects to return in response. - */ - const LIMIT = 100; - // endregion - /** - * Set Channel Members request. - * - * @internal - */ - class SetChannelMembersRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; - var _l, _m, _o, _p, _q, _r, _s, _t; - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$2); - (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT); - (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS); - (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE); - (_f = (_q = parameters.include).UUIDFields) !== null && _f !== void 0 ? _f : (_q.UUIDFields = INCLUDE_UUID_FIELDS); - (_g = (_r = parameters.include).customUUIDFields) !== null && _g !== void 0 ? _g : (_r.customUUIDFields = INCLUDE_UUID_CUSTOM_FIELDS); - (_h = (_s = parameters.include).UUIDStatusField) !== null && _h !== void 0 ? _h : (_s.UUIDStatusField = INCLUDE_UUID_STATUS_FIELD); - (_j = (_t = parameters.include).UUIDTypeField) !== null && _j !== void 0 ? _j : (_t.UUIDTypeField = INCLUDE_UUID_TYPE_FIELD); - (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT); - } - operation() { - return RequestOperation$1.PNSetMembersOperation; - } - validate() { - const { channel, uuids } = this.parameters; - if (!channel) - return 'Channel cannot be empty'; - if (!uuids || uuids.length === 0) - return 'UUIDs cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, channel, } = this.parameters; - return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}/uuids`; - } - get queryParameters() { - const { include, page, filter, sort, limit } = this.parameters; - let sorting = ''; - if (typeof sort === 'string') - sorting = sort; - else - sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - const includeFlags = ['uuid.status', 'uuid.type', 'type']; - if (include.statusField) - includeFlags.push('status'); - if (include.typeField) - includeFlags.push('type'); - if (include.customFields) - includeFlags.push('custom'); - if (include.UUIDFields) - includeFlags.push('uuid'); - if (include.UUIDStatusField) - includeFlags.push('uuid.status'); - if (include.UUIDTypeField) - includeFlags.push('uuid.type'); - if (include.customUUIDFields) - includeFlags.push('uuid.custom'); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); - } - get headers() { - var _a; - return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); - } - get body() { - const { uuids, type } = this.parameters; - return JSON.stringify({ - [`${type}`]: uuids.map((uuid) => { - if (typeof uuid === 'string') { - return { uuid: { id: uuid } }; - } - else { - return { uuid: { id: uuid.id }, status: uuid.status, type: uuid.type, custom: uuid.custom }; - } - }), - }); - } - } - - /** - * Get UUID Metadata REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether UUID custom field should be included by default or not. - */ - const INCLUDE_CUSTOM_FIELDS$1 = true; - // endregion - /** - * Get UUID Metadata request. - * - * @internal - */ - class GetUUIDMetadataRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b; - var _c; - super(); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS$1); - // Remap for backward compatibility. - if (this.parameters.userId) - this.parameters.uuid = this.parameters.userId; - } - operation() { - return RequestOperation$1.PNGetUUIDMetadataOperation; - } - validate() { - if (!this.parameters.uuid) - return "'uuid' cannot be empty"; - } - get path() { - const { keySet: { subscribeKey }, uuid, } = this.parameters; - return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}`; - } - get queryParameters() { - const { include } = this.parameters; - return { include: ['status', 'type', ...(include.customFields ? ['custom'] : [])].join(',') }; - } - } - - /** - * Set UUID Metadata REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Whether `Channel` custom field should be included by default or not. - */ - const INCLUDE_CUSTOM_FIELDS = true; - // endregion - /** - * Set UUID Metadata request. - * - * @internal - */ - class SetUUIDMetadataRequest extends AbstractRequest { - constructor(parameters) { - var _a, _b; - var _c; - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - // Apply default request parameters. - (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); - (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS); - // Remap for backward compatibility. - if (this.parameters.userId) - this.parameters.uuid = this.parameters.userId; - } - operation() { - return RequestOperation$1.PNSetUUIDMetadataOperation; - } - validate() { - if (!this.parameters.uuid) - return "'uuid' cannot be empty"; - if (!this.parameters.data) - return 'Data cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json' }); - } - get path() { - const { keySet: { subscribeKey }, uuid, } = this.parameters; - return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}`; - } - get queryParameters() { - return { - include: ['status', 'type', ...(this.parameters.include.customFields ? ['custom'] : [])].join(','), - }; - } - get body() { - return JSON.stringify(this.parameters.data); - } - } - - /** - * PubNub Objects API module. - */ - /** - * PubNub App Context API interface. - */ - class PubNubObjects { - /** - * Create app context API access object. - * - * @param configuration - Extended PubNub client configuration object. - * @param sendRequest - Function which should be used to send REST API calls. - * - * @internal - */ - constructor(configuration, - /* eslint-disable @typescript-eslint/no-explicit-any */ - sendRequest) { - this.keySet = configuration.keySet; - this.configuration = configuration; - this.sendRequest = sendRequest; - } - /** - * Get registered loggers' manager. - * - * @returns Registered loggers' manager. - * - * @internal - */ - get logger() { - return this.configuration.logger(); - } - /** - * Fetch a paginated list of UUID Metadata objects. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all UUID metadata response or `void` in case if `callback` provided. - */ - getAllUUIDMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, - details: `Get all UUID metadata objects with parameters:`, - })); - return this._getAllUUIDMetadata(parametersOrCallback, callback); - }); - } - /** - * Fetch a paginated list of UUID Metadata objects. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all UUID metadata response or `void` in case if `callback` provided. - * - * @internal - */ - _getAllUUIDMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - // Get user request parameters. - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - const request = new GetAllUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get all UUID metadata success. Received ${response.totalCount} UUID metadata objects.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Fetch a specific UUID Metadata object. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get UUID metadata response or `void` in case if `callback` provided. - */ - getUUIDMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' - ? { uuid: this.configuration.userId } - : parametersOrCallback, - details: `Get ${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} UUID metadata object with parameters:`, - })); - return this._getUUIDMetadata(parametersOrCallback, callback); - }); - } - /** - * Fetch a specific UUID Metadata object. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get UUID metadata response or `void` in case if `callback` provided. - * - * @internal - */ - _getUUIDMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - // Get user request parameters. - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - if (parameters.userId) { - this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); - parameters.uuid = parameters.userId; - } - (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); - const request = new GetUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get UUID metadata object success. Received '${parameters.uuid}' UUID metadata object.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Update a specific UUID Metadata object. - * - * @param parameters - Request configuration parameters. Will set UUID metadata for currently - * configured PubNub client `uuid` if not set. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set UUID metadata response or `void` in case if `callback` provided. - */ - setUUIDMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Set UUID metadata object with parameters:`, - })); - return this._setUUIDMetadata(parameters, callback); - }); - } - /** - * Update a specific UUID Metadata object. - * - * @internal - * - * @param parameters - Request configuration parameters. Will set UUID metadata for currently - * configured PubNub client `uuid` if not set. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set UUID metadata response or `void` in case if `callback` provided. - */ - _setUUIDMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - if (parameters.userId) { - this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); - parameters.uuid = parameters.userId; - } - (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); - const request = new SetUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Set UUID metadata object success. Updated '${parameters.uuid}' UUID metadata object.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Remove a specific UUID Metadata object. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous UUID metadata remove response or `void` in case if `callback` provided. - */ - removeUUIDMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' - ? { uuid: this.configuration.userId } - : parametersOrCallback, - details: `Remove${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} UUID metadata object with parameters:`, - })); - return this._removeUUIDMetadata(parametersOrCallback, callback); - }); - } - /** - * Remove a specific UUID Metadata object. - * - * @internal - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous UUID metadata remove response or `void` in case if `callback` provided. - */ - _removeUUIDMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - // Get user request parameters. - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - if (parameters.userId) { - this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); - parameters.uuid = parameters.userId; - } - (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); - const request = new RemoveUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Remove UUID metadata object success. Removed '${parameters.uuid}' UUID metadata object.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Fetch a paginated list of Channel Metadata objects. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all Channel metadata response or `void` in case if `callback` - * provided. - */ - getAllChannelMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, - details: `Get all Channel metadata objects with parameters:`, - })); - return this._getAllChannelMetadata(parametersOrCallback, callback); - }); - } - /** - * Fetch a paginated list of Channel Metadata objects. - * - * @internal - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all Channel metadata response or `void` in case if `callback` - * provided. - */ - _getAllChannelMetadata(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - // Get user request parameters. - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - const request = new GetAllChannelsMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get all Channel metadata objects success. Received ${response.totalCount} Channel metadata objects.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Fetch Channel Metadata object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get Channel metadata response or `void` in case if `callback` provided. - */ - getChannelMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Get Channel metadata object with parameters:`, - })); - return this._getChannelMetadata(parameters, callback); - }); - } - /** - * Fetch Channel Metadata object. - * - * @internal - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get Channel metadata response or `void` in case if `callback` provided. - */ - _getChannelMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - const request = new GetChannelMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get Channel metadata object success. Received '${parameters.channel}' Channel metadata object.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Update specific Channel Metadata object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set Channel metadata response or `void` in case if `callback` provided. - */ - setChannelMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Set Channel metadata object with parameters:`, - })); - return this._setChannelMetadata(parameters, callback); - }); - } - /** - * Update specific Channel Metadata object. - * - * @internal - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set Channel metadata response or `void` in case if `callback` provided. - */ - _setChannelMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - const request = new SetChannelMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Set Channel metadata object success. Updated '${parameters.channel}' Channel metadata object.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Remove a specific Channel Metadata object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous Channel metadata remove response or `void` in case if `callback` - * provided. - */ - removeChannelMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove Channel metadata object with parameters:`, - })); - return this._removeChannelMetadata(parameters, callback); - }); - } - /** - * Remove a specific Channel Metadata object. - * - * @internal - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous Channel metadata remove response or `void` in case if `callback` - * provided. - */ - _removeChannelMetadata(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - const request = new RemoveChannelMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Remove Channel metadata object success. Removed '${parameters.channel}' Channel metadata object.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Fetch a paginated list of Channel Member objects. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get Channel Members response or `void` in case if `callback` provided. - */ - getChannelMembers(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Get channel members with parameters:`, - })); - const request = new GetChannelMembersRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get channel members success. Received ${response.totalCount} channel members.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Update specific Channel Members list. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update Channel members list response or `void` in case if `callback` - * provided. - */ - setChannelMembers(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Set channel members with parameters:`, - })); - const request = new SetChannelMembersRequest(Object.assign(Object.assign({}, parameters), { type: 'set', keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Set channel members success. There are ${response.totalCount} channel members now.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Remove Members from the Channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous Channel Members remove response or `void` in case if `callback` provided. - */ - removeChannelMembers(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove channel members with parameters:`, - })); - const request = new SetChannelMembersRequest(Object.assign(Object.assign({}, parameters), { type: 'delete', keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Remove channel members success. There are ${response.totalCount} channel members now.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Fetch a specific UUID Memberships list. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get UUID Memberships response or `void` in case if `callback` provided. - */ - getMemberships(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - // Get user request parameters. - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - if (parameters.userId) { - this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); - parameters.uuid = parameters.userId; - } - (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Get memberships with parameters:`, - })); - const request = new GetUUIDMembershipsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get memberships success. Received ${response.totalCount} memberships.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Update specific UUID Memberships list. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update UUID Memberships list response or `void` in case if `callback` - * provided. - */ - setMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - if (parameters.userId) { - this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); - parameters.uuid = parameters.userId; - } - (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Set memberships with parameters:`, - })); - const request = new SetUUIDMembershipsRequest(Object.assign(Object.assign({}, parameters), { type: 'set', keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Set memberships success. There are ${response.totalCount} memberships now.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - /** - * Remove a specific UUID Memberships. - * - * @param parameters - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous UUID Memberships remove response or `void` in case if `callback` - * provided. - */ - removeMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - if (parameters.userId) { - this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); - parameters.uuid = parameters.userId; - } - (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove memberships with parameters:`, - })); - const request = new SetUUIDMembershipsRequest(Object.assign(Object.assign({}, parameters), { type: 'delete', keySet: this.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Remove memberships success. There are ${response.totalCount} memberships now.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - // endregion - // endregion - // -------------------------------------------------------- - // --------------------- Deprecated API ------------------- - // -------------------------------------------------------- - // region Deprecated - /** - * Fetch paginated list of specific Space members or specific User memberships. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get specific Space members or specific User memberships response. - * - * @deprecated Use {@link PubNubObjects#getChannelMembers getChannelMembers} or - * {@link PubNubObjects#getMemberships getMemberships} methods instead. - */ - fetchMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b; - this.logger.warn('PubNub', "'fetchMemberships' is deprecated. Use 'pubnub.objects.getChannelMembers' or 'pubnub.objects.getMemberships'" + - ' instead.'); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Fetch memberships with parameters:`, - })); - if ('spaceId' in parameters) { - const spaceParameters = parameters; - const mappedParameters = { - channel: (_a = spaceParameters.spaceId) !== null && _a !== void 0 ? _a : spaceParameters.channel, - filter: spaceParameters.filter, - limit: spaceParameters.limit, - page: spaceParameters.page, - include: Object.assign({}, spaceParameters.include), - sort: spaceParameters.sort - ? Object.fromEntries(Object.entries(spaceParameters.sort).map(([key, value]) => [key.replace('user', 'uuid'), value])) - : undefined, - }; - // Map Members object to the older version. - const mapMembers = (response) => ({ - status: response.status, - data: response.data.map((members) => ({ - user: members.uuid, - custom: members.custom, - updated: members.updated, - eTag: members.eTag, - })), - totalCount: response.totalCount, - next: response.next, - prev: response.prev, - }); - if (callback) - return this.getChannelMembers(mappedParameters, (status, result) => { - callback(status, result ? mapMembers(result) : result); - }); - return this.getChannelMembers(mappedParameters).then(mapMembers); - } - const userParameters = parameters; - const mappedParameters = { - uuid: (_b = userParameters.userId) !== null && _b !== void 0 ? _b : userParameters.uuid, - filter: userParameters.filter, - limit: userParameters.limit, - page: userParameters.page, - include: Object.assign({}, userParameters.include), - sort: userParameters.sort - ? Object.fromEntries(Object.entries(userParameters.sort).map(([key, value]) => [key.replace('space', 'channel'), value])) - : undefined, - }; - // Map Memberships object to the older version. - const mapMemberships = (response) => ({ - status: response.status, - data: response.data.map((membership) => ({ - space: membership.channel, - custom: membership.custom, - updated: membership.updated, - eTag: membership.eTag, - })), - totalCount: response.totalCount, - next: response.next, - prev: response.prev, - }); - if (callback) - return this.getMemberships(mappedParameters, (status, result) => { - callback(status, result ? mapMemberships(result) : result); - }); - return this.getMemberships(mappedParameters).then(mapMemberships); - }); - } - /** - * Add members to specific Space or memberships specific User. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous add members to specific Space or memberships specific User response or - * `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubObjects#setChannelMembers setChannelMembers} or - * {@link PubNubObjects#setMemberships setMemberships} methods instead. - */ - addMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b, _c, _d, _e, _f; - this.logger.warn('PubNub', "'addMemberships' is deprecated. Use 'pubnub.objects.setChannelMembers' or 'pubnub.objects.setMemberships'" + - ' instead.'); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Add memberships with parameters:`, - })); - if ('spaceId' in parameters) { - const spaceParameters = parameters; - const mappedParameters = { - channel: (_a = spaceParameters.spaceId) !== null && _a !== void 0 ? _a : spaceParameters.channel, - uuids: (_c = (_b = spaceParameters.users) === null || _b === void 0 ? void 0 : _b.map((user) => { - if (typeof user === 'string') - return user; - return { id: user.userId, custom: user.custom }; - })) !== null && _c !== void 0 ? _c : spaceParameters.uuids, - limit: 0, - }; - if (callback) - return this.setChannelMembers(mappedParameters, callback); - return this.setChannelMembers(mappedParameters); - } - const userParameters = parameters; - const mappedParameters = { - uuid: (_d = userParameters.userId) !== null && _d !== void 0 ? _d : userParameters.uuid, - channels: (_f = (_e = userParameters.spaces) === null || _e === void 0 ? void 0 : _e.map((space) => { - if (typeof space === 'string') - return space; - return { - id: space.spaceId, - custom: space.custom, - }; - })) !== null && _f !== void 0 ? _f : userParameters.channels, - limit: 0, - }; - if (callback) - return this.setMemberships(mappedParameters, callback); - return this.setMemberships(mappedParameters); - }); - } - } - - /** - * Create User REST API module. - * - * @internal - */ - // endregion - /** - * Create User request. - * - * @internal - */ - class CreateUserRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNCreateDataSyncUserOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.data) - return 'User data cannot be empty'; - if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) - return 'Entity class version cannot be empty'; - } - get headers() { - var _a; - const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.user+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/users`; - } - get body() { - const { id, class: entityClass, classLevel, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), (entityClass !== undefined ? { entityClass } : {})), { entityClassVersion: data.classVersion }), (classLevel !== undefined ? { entityClassLevel: classLevel } : {})), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * PubNub DataSync API type definitions. - * - * Types for Entity Class CRUD operations. - */ - /** - * Serialize a {@link DataSyncSort} into the query value the service expects. - * - * A raw string is passed through unchanged. An object is turned into a list of `field:order` - * entries (a `null` direction emits the bare field name, letting the service apply its default - * ascending order). Mirrors the App Context `getAllChannelMetadata` sort handling. - * - * @internal - */ - function serializeDataSyncSort(sort) { - if (typeof sort === 'string') - return sort; - return Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); - } - /** - * Convert user-friendly patch input to JSON Patch operations (request format). - * - * `path`/`from` are passed through verbatim — callers supply the exact RFC 6901 pointer. Do not - * reintroduce dot-notation translation here: splitting on `.` makes stored field names that - * contain a `.` unaddressable. - * - * - Each key in `add` becomes an "add" operation. - * - Each key in `replace` becomes a "replace" operation. - * - Each entry in `remove` becomes a "remove" operation. - * - Each `{ from, path }` pair in `move` becomes a "move" operation. - * - Each `{ from, path }` pair in `copy` becomes a "copy" operation. - * - Each key in `test` becomes a "test" operation. - * - * @internal - */ - function toJsonPatchOperations(input) { - const { add, replace, remove, move, copy, test } = input; - const ops = []; - if (add) { - for (const [path, value] of Object.entries(add)) { - ops.push({ op: 'add', path, value }); - } - } - if (replace) { - for (const [path, value] of Object.entries(replace)) { - ops.push({ op: 'replace', path, value }); - } - } - if (remove) { - for (const path of remove) { - ops.push({ op: 'remove', path }); - } - } - if (move) { - for (const { from, path } of move) { - ops.push({ op: 'move', from, path }); - } - } - if (copy) { - for (const { from, path } of copy) { - ops.push({ op: 'copy', from, path }); - } - } - if (test) { - for (const [path, value] of Object.entries(test)) { - ops.push({ op: 'test', path, value }); - } - } - return ops; - } - - /** - * Get Users REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Default number of items per page. - */ - const DEFAULT_LIMIT$4 = 20; - // endregion - /** - * Get Users request. - * - * @internal - */ - class GetUsersRequest extends AbstractRequest { - constructor(parameters) { - var _a; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$4); - } - operation() { - return RequestOperation$1.PNGetDataSyncUsersOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - get path() { - return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/users`; - } - get queryParameters() { - const { class: entityClass, classVersion, classLevel, cursor, limit, filter, filterFast, sort } = this.parameters; - const sorting = serializeDataSyncSort(sort); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (entityClass ? { entity_class: entityClass } : {})), (classVersion !== undefined ? { entity_class_version: `${classVersion}` } : {})), (classLevel ? { entity_class_level: classLevel } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set User REST API module. - * - * Full resource replacement via PUT. - * - * @internal - */ - // endregion - /** - * Set User request. - * - * @internal - */ - class SetUserRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PUT }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSetDataSyncUserOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'User id cannot be empty'; - if (!this.parameters.data) - return 'User data cannot be empty'; - if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) - return 'Entity class version cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.user+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; - } - get body() { - const { data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign({ entityClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Remove User REST API module. - * - * @internal - */ - // endregion - /** - * Remove User request. - * - * @internal - */ - class RemoveUserRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveDataSyncUserOperation; - } - validate() { - if (!this.parameters.id) - return 'User id cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.keys(headers).length > 0 ? headers : undefined; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { status: response.status }; - }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; - } - } - - /** - * Update User REST API module. - * - * Partial update via JSON Patch (RFC 6902). - * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` - * (JSON Pointer paths), and `move`/`copy` (JSON Pointer `{ from, path }` pairs) - * and converts them to JSON Patch operations. Paths are sent verbatim. - * - * @internal - */ - // endregion - /** - * Update User request. - * - * @internal - */ - class UpdateUserRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNUpdateDataSyncUserOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'User id cannot be empty'; - const { add, replace, remove, move, copy, test } = this.parameters; - const hasAdd = add && Object.keys(add).length > 0; - const hasReplace = replace && Object.keys(replace).length > 0; - const hasRemove = remove && remove.length > 0; - const hasMove = move && move.length > 0; - const hasCopy = copy && copy.length > 0; - const hasTest = test && Object.keys(test).length > 0; - if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) - return 'At least one of add, replace, remove, move, copy, or test must be provided'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; - } - get body() { - const { add, replace, remove, move, copy, test } = this.parameters; - const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); - return JSON.stringify(jsonPatchOps); - } - } - - /** - * Get User REST API module. - * - * @internal - */ - // endregion - /** - * Get User request. - * - * @internal - */ - class GetUserRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetDataSyncUserOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'User id cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; - } - } - - /** - * Create Channel REST API module. - * - * @internal - */ - // endregion - /** - * Create Channel request. - * - * @internal - */ - class CreateChannelRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNCreateDataSyncChannelOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.data) - return 'Channel data cannot be empty'; - if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) - return 'Entity class version cannot be empty'; - } - get headers() { - var _a; - const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.channel+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/channels`; - } - get body() { - const { id, class: entityClass, classLevel, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), (entityClass !== undefined ? { entityClass } : {})), { entityClassVersion: data.classVersion }), (classLevel !== undefined ? { entityClassLevel: classLevel } : {})), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Get Channels REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Default number of items per page. - */ - const DEFAULT_LIMIT$3 = 20; - // endregion - /** - * Get Channels request. - * - * @internal - */ - class GetChannelsRequest extends AbstractRequest { - constructor(parameters) { - var _a; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$3); - } - operation() { - return RequestOperation$1.PNGetDataSyncChannelsOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - get path() { - return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/channels`; - } - get queryParameters() { - const { class: entityClass, classVersion, classLevel, cursor, limit, filter, filterFast, sort } = this.parameters; - const sorting = serializeDataSyncSort(sort); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (entityClass ? { entity_class: entityClass } : {})), (classVersion !== undefined ? { entity_class_version: `${classVersion}` } : {})), (classLevel ? { entity_class_level: classLevel } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set Channel REST API module. - * - * Full resource replacement via PUT. - * - * @internal - */ - // endregion - /** - * Set Channel request. - * - * @internal - */ - class SetChannelRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PUT }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSetDataSyncChannelOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Channel id cannot be empty'; - if (!this.parameters.data) - return 'Channel data cannot be empty'; - if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) - return 'Entity class version cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.channel+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; - } - get body() { - const { data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign({ entityClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Remove Channel REST API module. - * - * @internal - */ - // endregion - /** - * Remove Channel request. - * - * @internal - */ - class RemoveChannelRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveDataSyncChannelOperation; - } - validate() { - if (!this.parameters.id) - return 'Channel id cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.keys(headers).length > 0 ? headers : undefined; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { status: response.status }; - }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; - } - } - - /** - * Update Channel REST API module. - * - * Partial update via JSON Patch (RFC 6902). - * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` - * (JSON Pointer paths), and `move`/`copy` (JSON Pointer from → path pairs), - * converting them to JSON Patch operations. Paths are sent verbatim. - * - * @internal - */ - // endregion - /** - * Update Channel request. - * - * @internal - */ - class UpdateChannelRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNUpdateDataSyncChannelOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Channel id cannot be empty'; - const { add, replace, remove, move, copy, test } = this.parameters; - const hasAdd = add && Object.keys(add).length > 0; - const hasReplace = replace && Object.keys(replace).length > 0; - const hasRemove = remove && remove.length > 0; - const hasMove = move && move.length > 0; - const hasCopy = copy && copy.length > 0; - const hasTest = test && Object.keys(test).length > 0; - if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) - return 'At least one of add, replace, remove, move, copy, or test must be provided'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; - } - get body() { - const { add, replace, remove, move, copy, test } = this.parameters; - const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); - return JSON.stringify(jsonPatchOps); - } - } - - /** - * Get Channel REST API module. - * - * @internal - */ - // endregion - /** - * Get Channel request. - * - * @internal - */ - class GetChannelRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetDataSyncChannelOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Channel id cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; - } - } - - /** - * Create Membership REST API module. - * - * @internal - */ - // endregion - /** - * Create Membership request. - * - * @internal - */ - class CreateMembershipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNCreateDataSyncMembershipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.userId) - return 'User id cannot be empty'; - if (!this.parameters.channelId) - return 'Channel id cannot be empty'; - if (!this.parameters.data) - return 'Membership data cannot be empty'; - if (!this.parameters.data.classVersion) - return 'Membership class version cannot be empty'; - } - get headers() { - var _a; - const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.membership+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/memberships`; - } - get body() { - const { id, userId, channelId, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), { userId, - channelId, relationshipClassVersion: data.classVersion }), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Get Memberships REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Default number of items per page. - */ - const DEFAULT_LIMIT$2 = 20; - // endregion - /** - * Get Memberships request. - * - * @internal - */ - class GetMembershipsRequest extends AbstractRequest { - constructor(parameters) { - var _a; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$2); - } - operation() { - return RequestOperation$1.PNGetDataSyncMembershipsOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - get path() { - return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/memberships`; - } - get queryParameters() { - const { userId, channelId, classVersion, cursor, limit, filter, filterFast, sort } = this.parameters; - const sorting = serializeDataSyncSort(sort); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (userId ? { user_id: userId } : {})), (channelId ? { channel_id: channelId } : {})), (classVersion !== undefined ? { relationship_class_version: `${classVersion}` } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set Membership REST API module. - * - * Full resource replacement via PUT. - * - * @internal - */ - // endregion - /** - * Set Membership request. - * - * @internal - */ - class SetMembershipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PUT }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSetDataSyncMembershipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Membership id cannot be empty'; - if (!this.parameters.userId) - return 'User id cannot be empty'; - if (!this.parameters.channelId) - return 'Channel id cannot be empty'; - if (!this.parameters.data) - return 'Membership data cannot be empty'; - if (!this.parameters.data.classVersion) - return 'Membership class version cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.membership+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; - } - get body() { - const { userId, channelId, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign({ userId, - channelId, relationshipClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Remove Membership REST API module. - * - * @internal - */ - // endregion - /** - * Remove Membership request. - * - * @internal - */ - class RemoveMembershipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveDataSyncMembershipOperation; - } - validate() { - if (!this.parameters.id) - return 'Membership id cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.keys(headers).length > 0 ? headers : undefined; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { status: response.status }; - }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; - } - } - - /** - * Update Membership REST API module. - * - * Partial update via JSON Patch (RFC 6902). - * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` - * (JSON Pointer paths), and `move`/`copy` (JSON Pointer `{ from, path }` pairs) - * and converts them to JSON Patch operations. Paths are sent verbatim. - * - * @internal - */ - // endregion - /** - * Update Membership request. - * - * @internal - */ - class UpdateMembershipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNUpdateDataSyncMembershipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Membership id cannot be empty'; - const { add, replace, remove, move, copy, test } = this.parameters; - const hasAdd = add && Object.keys(add).length > 0; - const hasReplace = replace && Object.keys(replace).length > 0; - const hasRemove = remove && remove.length > 0; - const hasMove = move && move.length > 0; - const hasCopy = copy && copy.length > 0; - const hasTest = test && Object.keys(test).length > 0; - if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) - return 'At least one of add, replace, remove, move, copy, or test must be provided'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; - } - get body() { - const { add, replace, remove, move, copy, test } = this.parameters; - const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); - return JSON.stringify(jsonPatchOps); - } - } - - /** - * Get Membership REST API module. - * - * @internal - */ - // endregion - /** - * Get Membership request. - * - * @internal - */ - class GetMembershipRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetDataSyncMembershipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Membership id cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; - } - } - - /** - * Create Relationship REST API module. - * - * @internal - */ - // endregion - /** - * Create Relationship request. - * - * @internal - */ - class CreateRelationshipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNCreateDataSyncRelationshipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.entityAId) - return 'Entity A id cannot be empty'; - if (!this.parameters.entityBId) - return 'Entity B id cannot be empty'; - if (!this.parameters.class) - return 'Relationship class cannot be empty'; - if (!this.parameters.data) - return 'Relationship data cannot be empty'; - if (!this.parameters.data.classVersion) - return 'Relationship class version cannot be empty'; - } - get headers() { - var _a; - const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.relationship+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/relationships`; - } - get body() { - const { id, class: relationshipClass, entityAId, entityBId, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), { entityAId, - entityBId, - relationshipClass, relationshipClassVersion: data.classVersion }), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Get Relationships REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Default number of items per page. - */ - const DEFAULT_LIMIT$1 = 20; - // endregion - /** - * Get Relationships request. - * - * @internal - */ - class GetRelationshipsRequest extends AbstractRequest { - constructor(parameters) { - var _a; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$1); - } - operation() { - return RequestOperation$1.PNGetDataSyncRelationshipsOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.class) - return 'Relationship class cannot be empty'; - } - get path() { - return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/relationships`; - } - get queryParameters() { - const { class: relationshipClass, classVersion, entityAId, entityBId, cursor, limit, filter, filterFast, sort, } = this.parameters; - const sorting = serializeDataSyncSort(sort); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ relationship_class: relationshipClass }, (classVersion !== undefined ? { relationship_class_version: `${classVersion}` } : {})), (entityAId ? { entity_a_id: entityAId } : {})), (entityBId ? { entity_b_id: entityBId } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set Relationship REST API module. - * - * Full resource replacement via PUT. - * - * @internal - */ - // endregion - /** - * Set Relationship request. - * - * @internal - */ - class SetRelationshipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PUT }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSetDataSyncRelationshipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Relationship id cannot be empty'; - if (!this.parameters.entityAId) - return 'Entity A id cannot be empty'; - if (!this.parameters.entityBId) - return 'Entity B id cannot be empty'; - if (!this.parameters.data) - return 'Relationship data cannot be empty'; - if (!this.parameters.data.classVersion) - return 'Relationship class version cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.relationship+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; - } - get body() { - const { entityAId, entityBId, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign({ entityAId, - entityBId, relationshipClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Remove Relationship REST API module. - * - * @internal - */ - // endregion - /** - * Remove Relationship request. - * - * @internal - */ - class RemoveRelationshipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveDataSyncRelationshipOperation; - } - validate() { - if (!this.parameters.id) - return 'Relationship id cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.keys(headers).length > 0 ? headers : undefined; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { status: response.status }; - }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; - } - } - - /** - * Update Relationship REST API module. - * - * Partial update via JSON Patch (RFC 6902). - * Accepts `add` and `replace` (JSON Pointer key-value pairs), `remove` - * (JSON Pointer paths), `move` and `copy` (`{ from, path }` JSON Pointer pairs), - * and `test` (JSON Pointer key-value pairs) and converts them to JSON Patch - * operations. Paths are sent verbatim. - * - * @internal - */ - // endregion - /** - * Update Relationship request. - * - * @internal - */ - class UpdateRelationshipRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNUpdateDataSyncRelationshipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Relationship id cannot be empty'; - const { add, replace, remove, move, copy, test } = this.parameters; - const hasAdd = add && Object.keys(add).length > 0; - const hasReplace = replace && Object.keys(replace).length > 0; - const hasRemove = remove && remove.length > 0; - const hasMove = move && move.length > 0; - const hasCopy = copy && copy.length > 0; - const hasTest = test && Object.keys(test).length > 0; - if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) - return 'At least one of add, replace, remove, move, copy, or test must be provided'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; - } - get body() { - const { add, replace, remove, move, copy, test } = this.parameters; - const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); - return JSON.stringify(jsonPatchOps); - } - } - - /** - * Get Relationship REST API module. - * - * @internal - */ - // endregion - /** - * Get Relationship request. - * - * @internal - */ - class GetRelationshipRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetDataSyncRelationshipOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Relationship id cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; - } - } - - /** - * Create Entity REST API module. - * - * @internal - */ - // endregion - /** - * Create Entity request. - * - * @internal - */ - class CreateEntityRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.POST }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNCreateDataSyncEntityOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.class) - return 'Entity class cannot be empty'; - if (!this.parameters.data) - return 'Entity data cannot be empty'; - if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) - return 'Entity class version cannot be empty'; - } - get headers() { - var _a; - const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.entity+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/entities`; - } - get body() { - const { id, class: entityClass, classLevel, data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), { entityClass, entityClassVersion: data.classVersion }), (classLevel !== undefined ? { entityClassLevel: classLevel } : {})), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Get Entities REST API module. - * - * @internal - */ - // -------------------------------------------------------- - // ----------------------- Defaults ----------------------- - // -------------------------------------------------------- - // region Defaults - /** - * Default number of items per page. - */ - const DEFAULT_LIMIT = 20; - // endregion - /** - * Get Entities request. - * - * @internal - */ - class GetEntitiesRequest extends AbstractRequest { - constructor(parameters) { - var _a; - super(); - this.parameters = parameters; - // Apply defaults. - (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT); - } - operation() { - return RequestOperation$1.PNGetDataSyncEntitiesOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.class) - return 'Entity class cannot be empty'; - } - get path() { - return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/entities`; - } - get queryParameters() { - const { class: entityClass, classVersion, classLevel, cursor, limit, filter, filterFast, sort } = this.parameters; - const sorting = serializeDataSyncSort(sort); - return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ entity_class: entityClass }, (classVersion !== undefined ? { entity_class_version: `${classVersion}` } : {})), (classLevel ? { entity_class_level: classLevel } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); - } - } - - /** - * Set Entity REST API module. - * - * Full resource replacement via PUT. - * Note: `entityClass` is immutable and cannot be changed via update. - * - * @internal - */ - // endregion - /** - * Set Entity request. - * - * @internal - */ - class SetEntityRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PUT }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNSetDataSyncEntityOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Entity id cannot be empty'; - if (!this.parameters.data) - return 'Entity data cannot be empty'; - if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) - return 'Entity class version cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.entity+json;version=1' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; - } - get body() { - const { data } = this.parameters; - return JSON.stringify({ - data: Object.assign(Object.assign({ entityClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), - }); - } - } - - /** - * Remove Entity REST API module. - * - * @internal - */ - // endregion - /** - * Remove Entity request. - * - * @internal - */ - class RemoveEntityRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.DELETE }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNRemoveDataSyncEntityOperation; - } - validate() { - if (!this.parameters.id) - return 'Entity id cannot be empty'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.keys(headers).length > 0 ? headers : undefined; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { status: response.status }; - }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; - } - } - - /** - * Update Entity REST API module. - * - * Partial update via JSON Patch (RFC 6902). - * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` - * (JSON Pointer paths), and `move`/`copy` (JSON Pointer from/path pairs), and - * converts them to JSON Patch operations. Paths are sent verbatim. - * - * @internal - */ - // endregion - /** - * Update Entity request. - * - * @internal - */ - class UpdateEntityRequest extends AbstractRequest { - constructor(parameters) { - super({ method: TransportMethod.PATCH }); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNUpdateDataSyncEntityOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Entity id cannot be empty'; - const { add, replace, remove, move, copy, test } = this.parameters; - const hasAdd = add && Object.keys(add).length > 0; - const hasReplace = replace && Object.keys(replace).length > 0; - const hasRemove = remove && remove.length > 0; - const hasMove = move && move.length > 0; - const hasCopy = copy && copy.length > 0; - const hasTest = test && Object.keys(test).length > 0; - if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) - return 'At least one of add, replace, remove, move, copy, or test must be provided'; - } - get headers() { - var _a; - let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; - if (this.parameters.ifMatchesEtag) - headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); - return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; - } - get body() { - const { add, replace, remove, move, copy, test } = this.parameters; - const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); - return JSON.stringify(jsonPatchOps); - } - } - - /** - * Get Entity REST API module. - * - * @internal - */ - // endregion - /** - * Get Entity request. - * - * @internal - */ - class GetEntityRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNGetDataSyncEntityOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - // The DataSync service returns the object envelope ({ data } or { data, meta }) without a - // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). - const parsed = this.deserializeResponse(response); - return Object.assign(Object.assign({}, parsed), { status: response.status }); - }); - } - validate() { - if (!this.parameters.id) - return 'Entity id cannot be empty'; - } - get path() { - const { keySet: { subscribeKey }, id, } = this.parameters; - return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; - } - } - - /** - * PubNub DataSync API module. - */ - /** - * PubNub DataSync API interface. - */ - class PubNubDataSync { - /** - * Create DataSync API access object. - * - * @param configuration - Extended PubNub client configuration object. - * @param sendRequest - Function which should be used to send REST API calls. - * - * @internal - */ - constructor(configuration, - /* eslint-disable @typescript-eslint/no-explicit-any */ - sendRequest) { - this.keySet = configuration.keySet; - this.configuration = configuration; - this.sendRequest = sendRequest; - } - /** - * Get registered loggers' manager. - * - * @returns Registered loggers' manager. - * - * @internal - */ - get logger() { - return this.configuration.logger(); - } - /** - * Create a new Entity. - * - * To change a field later with `updateEntity`, address it by its JSON Pointer: `classVersion` is - * patched as `/entityClassVersion`, `status` as `/status`, and payload fields as - * `/payload/`. `class` and `classLevel` are immutable and cannot be patched. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create entity response or `void` in case if `callback` provided. - */ - createEntity(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Create Entity with parameters:', - })); - const request = new CreateEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a specific Entity. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get entity response or `void` in case if `callback` provided. - */ - getEntity(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Entity with parameters:', - })); - const request = new GetEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a paginated list of Entities for a given Entity Class. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get entities response or `void` in case if `callback` provided. - */ - getEntities(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Entities with parameters:', - })); - const request = new GetEntitiesRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Set an Entity (full replacement via PUT). - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set entity response or `void` in case if `callback` provided. - */ - setEntity(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Set Entity with parameters:', - })); - const request = new SetEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Update an Entity (partial update via JSON Patch RFC 6902). - * - * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which - * is the name an entity carries in responses and real-time events: - * - * - `classVersion` → `/entityClassVersion` - * - `status` → `/status` - * - a payload field → `/payload/`; nest deeper with more segments, e.g. - * `/payload/address/city`. A field name that contains a `.` is written as-is - * (`/payload/user.name`). - * - * `entityClass` and `entityClassLevel` are immutable and cannot be patched. - * - * @example - * ```typescript - * await pubnub.dataSync.updateEntity({ - * id, - * replace: { '/status': 'inactive', '/payload/creditScore': 810 }, - * remove: ['/payload/legacyField'], - * }); - * ``` - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update entity response or `void` in case if `callback` provided. - */ - updateEntity(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Update Entity with parameters:', - })); - const request = new UpdateEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Remove an Entity. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove entity response or `void` in case if `callback` provided. - */ - removeEntity(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove Entity with parameters:', - })); - const request = new RemoveEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Create a new Relationship. - * - * To change a field later with `updateRelationship`, address it by its JSON Pointer: - * `classVersion` is patched as `/relationshipClassVersion`, `status` as `/status`, and payload - * fields as `/payload/`. `class`, `entityAId`, and `entityBId` are immutable and - * cannot be patched. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create relationship response or `void` in case if `callback` provided. - */ - createRelationship(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Create Relationship with parameters:', - })); - const request = new CreateRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a specific Relationship. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get relationship response or `void` in case if `callback` provided. - */ - getRelationship(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Relationship with parameters:', - })); - const request = new GetRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a paginated list of Relationships. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get relationships response or `void` in case if `callback` provided. - */ - getRelationships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Relationships with parameters:', - })); - const request = new GetRelationshipsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Set a Relationship (full replacement via PUT). - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set relationship response or `void` in case if `callback` provided. - */ - setRelationship(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Set Relationship with parameters:', - })); - const request = new SetRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Update a Relationship (partial update via JSON Patch RFC 6902). - * - * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which - * is the name a relationship carries in responses and real-time events: - * - * - `classVersion` → `/relationshipClassVersion` - * - `status` → `/status` - * - a payload field → `/payload/`; nest deeper with more segments, e.g. - * `/payload/address/city`. A field name that contains a `.` is written as-is - * (`/payload/user.name`). - * - * `relationshipClass`, `entityAId`, and `entityBId` are immutable and cannot be patched. - * - * @example - * ```typescript - * await pubnub.dataSync.updateRelationship({ - * id, - * replace: { '/status': 'inactive', '/payload/label': 'primary' }, - * remove: ['/payload/legacyField'], - * }); - * ``` - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update relationship response or `void` in case if `callback` provided. - */ - updateRelationship(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Update Relationship with parameters:', - })); - const request = new UpdateRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Remove a Relationship. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove relationship response or `void` in case if `callback` provided. - */ - removeRelationship(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove Relationship with parameters:', - })); - const request = new RemoveRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Create a new User. - * - * To change a field later with `updateUser`, address it by its JSON Pointer: `classVersion` is - * patched as `/entityClassVersion`, `status` as `/status`, and payload fields as - * `/payload/`. `class` and `classLevel` are immutable and cannot be patched. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create user response or `void` in case if `callback` provided. - */ - createUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Create User with parameters:', - })); - const request = new CreateUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a specific User. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get user response or `void` in case if `callback` provided. - */ - getUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get User with parameters:', - })); - const request = new GetUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a paginated list of Users. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get users response or `void` in case if `callback` provided. - */ - getUsers(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Users with parameters:', - })); - const request = new GetUsersRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Set a User (full replacement via PUT). - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set user response or `void` in case if `callback` provided. - */ - setUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Set User with parameters:', - })); - const request = new SetUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Update a User (partial update via JSON Patch RFC 6902). - * - * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which - * is the name a user carries in responses and real-time events: - * - * - `classVersion` → `/entityClassVersion` - * - `status` → `/status` - * - a payload field → `/payload/`; nest deeper with more segments, e.g. - * `/payload/address/city`. A field name that contains a `.` is written as-is - * (`/payload/user.name`). - * - * `entityClass` and `entityClassLevel` are immutable and cannot be patched. - * - * @example - * ```typescript - * await pubnub.dataSync.updateUser({ - * id, - * replace: { '/status': 'inactive', '/payload/email': 'alice.v@acme.test' }, - * remove: ['/payload/legacyField'], - * }); - * ``` - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update user response or `void` in case if `callback` provided. - */ - updateUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Update User with parameters:', - })); - const request = new UpdateUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Remove a User. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove user response or `void` in case if `callback` provided. - */ - removeUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove User with parameters:', - })); - const request = new RemoveUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Create a new Channel. - * - * To change a field later with `updateChannel`, address it by its JSON Pointer: `classVersion` - * is patched as `/entityClassVersion`, `status` as `/status`, and payload fields as - * `/payload/`. `class` and `classLevel` are immutable and cannot be patched. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create channel response or `void` in case if `callback` provided. - */ - createChannel(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Create Channel with parameters:', - })); - const request = new CreateChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a specific Channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get channel response or `void` in case if `callback` provided. - */ - getChannel(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Channel with parameters:', - })); - const request = new GetChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a paginated list of Channels. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get channels response or `void` in case if `callback` provided. - */ - getChannels(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Channels with parameters:', - })); - const request = new GetChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Set a Channel (full replacement via PUT). - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set channel response or `void` in case if `callback` provided. - */ - setChannel(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Set Channel with parameters:', - })); - const request = new SetChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Update a Channel (partial update via JSON Patch RFC 6902). - * - * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which - * is the name a channel carries in responses and real-time events: - * - * - `classVersion` → `/entityClassVersion` - * - `status` → `/status` - * - a payload field → `/payload/`; nest deeper with more segments, e.g. - * `/payload/address/city`. A field name that contains a `.` is written as-is - * (`/payload/user.name`). - * - * `entityClass` and `entityClassLevel` are immutable and cannot be patched. - * - * @example - * ```typescript - * await pubnub.dataSync.updateChannel({ - * id, - * replace: { '/status': 'inactive', '/payload/memberCount': 42 }, - * remove: ['/payload/legacyField'], - * }); - * ``` - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update channel response or `void` in case if `callback` provided. - */ - updateChannel(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Update Channel with parameters:', - })); - const request = new UpdateChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Remove a Channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove channel response or `void` in case if `callback` provided. - */ - removeChannel(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove Channel with parameters:', - })); - const request = new RemoveChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Create a new Membership (associates a User with a Channel). - * - * To change a field later with `updateMembership`, address it by its JSON Pointer: - * `classVersion` is patched as `/relationshipClassVersion`, `status` as `/status`, and payload - * fields as `/payload/`. `userId` and `channelId` are immutable and cannot be patched. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create membership response or `void` in case if `callback` provided. - */ - createMembership(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Create Membership with parameters:', - })); - const request = new CreateMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a specific Membership. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get membership response or `void` in case if `callback` provided. - */ - getMembership(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Membership with parameters:', - })); - const request = new GetMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Get a paginated list of Memberships. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get memberships response or `void` in case if `callback` provided. - */ - getMemberships(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; - callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get Memberships with parameters:', - })); - const request = new GetMembershipsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Set a Membership (full replacement via PUT). - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set membership response or `void` in case if `callback` provided. - */ - setMembership(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Set Membership with parameters:', - })); - const request = new SetMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Update a Membership (partial update via JSON Patch RFC 6902). - * - * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which - * is the name a membership carries in responses and real-time events: - * - * - `classVersion` → `/relationshipClassVersion` - * - `status` → `/status` - * - a payload field → `/payload/`; nest deeper with more segments, e.g. - * `/payload/address/city`. A field name that contains a `.` is written as-is - * (`/payload/user.name`). - * - * `userId` and `channelId` are immutable and cannot be patched. - * - * @example - * ```typescript - * await pubnub.dataSync.updateMembership({ - * id, - * replace: { '/status': 'inactive', '/payload/role': 'moderator' }, - * remove: ['/payload/legacyField'], - * }); - * ``` - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update membership response or `void` in case if `callback` provided. - */ - updateMembership(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Update Membership with parameters:', - })); - const request = new UpdateMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - /** - * Remove a Membership. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove membership response or `void` in case if `callback` provided. - */ - removeMembership(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove Membership with parameters:', - })); - const request = new RemoveMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); - if (callback) - return this.sendRequest(request, callback); - return this.sendRequest(request); - }); - } - } - - /** - * Time REST API module. - */ - // endregion - /** - * Get current PubNub high-precision time request. - * - * @internal - */ - class TimeRequest extends AbstractRequest { - constructor() { - super(); - } - operation() { - return RequestOperation$1.PNTimeOperation; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - return { timetoken: this.deserializeResponse(response)[0] }; - }); - } - get path() { - return '/time/0'; - } - } - - /** - * Download File REST API module. - * - * @internal - */ - // endregion - /** - * Download File request. - * - * @internal - */ - class DownloadFileRequest extends AbstractRequest { - constructor(parameters) { - super(); - this.parameters = parameters; - } - operation() { - return RequestOperation$1.PNDownloadFileOperation; - } - validate() { - const { channel, id, name } = this.parameters; - if (!channel) - return "channel can't be empty"; - if (!id) - return "file id can't be empty"; - if (!name) - return "file name can't be empty"; - } - parse(response) { - return __awaiter(this, void 0, void 0, function* () { - const { cipherKey, crypto, cryptography, name, PubNubFile } = this.parameters; - const mimeType = response.headers['content-type']; - let decryptedFile; - let body = response.body; - if (PubNubFile.supportsEncryptFile && (cipherKey || crypto)) { - if (cipherKey && cryptography) - body = yield cryptography.decrypt(cipherKey, body); - else if (!cipherKey && crypto) - decryptedFile = yield crypto.decryptFile(PubNubFile.create({ data: body, name: name, mimeType }), PubNubFile); - } - return (decryptedFile - ? decryptedFile - : PubNubFile.create({ - data: body, - name, - mimeType, - })); - }); - } - get path() { - const { keySet: { subscribeKey }, channel, id, name, } = this.parameters; - return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files/${encodeString(id)}/${encodeString(name)}`; - } - } - - /** - * Core PubNub API module. - */ - // endregion - /** - * Platform-agnostic PubNub client core. - */ - class PubNubCore { - /** - * Construct notification payload which will trigger push notification. - * - * @param title - Title which will be shown on notification. - * @param body - Payload which will be sent as part of notification. - * - * @returns Pre-formatted message payload which will trigger push notification. - */ - static notificationPayload(title, body) { - { - return new NotificationsPayload(title, body); - } - } - /** - * Generate unique identifier. - * - * @returns Unique identifier. - */ - static generateUUID() { - return uuidGenerator.createUUID(); - } - // endregion - /** - * Create and configure PubNub client core. - * - * @param configuration - PubNub client core configuration. - * @returns Configured and ready to use PubNub client. - * - * @internal - */ - constructor(configuration) { - /** - * List of subscribe capable objects with active subscriptions. - * - * Track list of {@link Subscription} and {@link SubscriptionSet} objects with active - * subscription. - * - * @internal - */ - this.eventHandleCapable = {}; - /** - * Created entities. - * - * Map of entities which have been created to access. - * - * @internal - */ - this.entities = {}; - this._configuration = configuration.configuration; - this.cryptography = configuration.cryptography; - this.tokenManager = configuration.tokenManager; - this.transport = configuration.transport; - this.crypto = configuration.crypto; - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: configuration.configuration, - details: 'Create with configuration:', - ignoredKeys(key, obj) { - return typeof obj[key] === 'function' || key.startsWith('_') || key === 'keySet' || isSensitiveLogKey(key); - }, - })); - // API group entry points initialization. - this._objects = new PubNubObjects(this._configuration, this.sendRequest.bind(this)); - this._dataSync = new PubNubDataSync(this._configuration, this.sendRequest.bind(this)); - this._channelGroups = new PubNubChannelGroups(this._configuration.logger(), this._configuration.keySet, this.sendRequest.bind(this)); - this._push = new PubNubPushNotifications(this._configuration.logger(), this._configuration.keySet, this.sendRequest.bind(this)); - { - // Prepare for a real-time events announcement. - this.eventDispatcher = new EventDispatcher(); - if (this._configuration.enableEventEngine) { - { - this.logger.debug('PubNub', 'Using new subscription loop management.'); - let heartbeatInterval = this._configuration.getHeartbeatInterval(); - this.presenceState = {}; - { - if (heartbeatInterval) { - this.presenceEventEngine = new PresenceEventEngine({ - heartbeat: (parameters, callback) => { - this.logger.trace('PresenceEventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Heartbeat with parameters:', - })); - return this.heartbeat(parameters, callback); - }, - leave: (parameters) => { - this.logger.trace('PresenceEventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Leave with parameters:', - })); - this.makeUnsubscribe(parameters, () => { }); - }, - heartbeatDelay: () => { - let cancelDelay = () => { }; - const promise = new Promise((resolve, reject) => { - heartbeatInterval = this._configuration.getHeartbeatInterval(); - if (!heartbeatInterval) - reject(new PubNubError('Heartbeat interval has been reset.')); - else { - const timeoutId = setTimeout(() => { - resolve(); - }, heartbeatInterval * 1000); - cancelDelay = () => { - clearTimeout(timeoutId); - reject(new PubNubError('Heartbeat interval has been cancelled.')); - }; - } - }); - return { cancelDelay, promise }; - }, - emitStatus: (status) => this.emitStatus(status), - config: this._configuration, - presenceState: this.presenceState, - }); - } - } - this.eventEngine = new EventEngine({ - handshake: (parameters) => { - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Handshake with parameters:', - ignoredKeys: ['abortSignal', 'crypto', 'timeout', 'keySet', 'getFileUrl'], - })); - return this.subscribeHandshake(parameters); - }, - receiveMessages: (parameters) => { - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Receive messages with parameters:', - ignoredKeys: ['abortSignal', 'crypto', 'timeout', 'keySet', 'getFileUrl'], - })); - return this.subscribeReceiveMessages(parameters); - }, - join: (parameters) => { - var _a, _b; - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Join with parameters:', - })); - if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { - this.logger.trace('EventEngine', "Ignoring 'join' announcement request."); - return; - } - this.join(parameters); - }, - leave: (parameters) => { - var _a, _b; - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Leave with parameters:', - })); - if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { - this.logger.trace('EventEngine', "Ignoring 'leave' announcement request."); - return; - } - this.leave(parameters); - }, - leaveAll: (parameters) => { - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Leave all with parameters:', - })); - this.leaveAll(parameters); - }, - presenceReconnect: (parameters) => { - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Reconnect with parameters:', - })); - this.presenceReconnect(parameters); - }, - presenceDisconnect: (parameters) => { - this.logger.trace('EventEngine', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Disconnect with parameters:', - })); - this.presenceDisconnect(parameters); - }, - presenceState: this.presenceState, - config: this._configuration, - emitMessages: (cursor, events) => { - try { - this.logger.debug('EventEngine', () => { - const hashedEvents = events.map((event) => { - const pn_mfp = event.type === PubNubEventType.Message || event.type === PubNubEventType.Signal - ? messageFingerprint(event.data.message) - : undefined; - return pn_mfp ? { type: event.type, data: Object.assign(Object.assign({}, event.data), { pn_mfp }) } : event; - }); - return { messageType: 'object', message: hashedEvents, details: 'Received events:' }; - }); - events.forEach((event) => this.emitEvent(cursor, event)); - } - catch (e) { - const errorStatus = { - error: true, - category: StatusCategory$1.PNUnknownCategory, - errorData: e, - statusCode: 0, - }; - this.emitStatus(errorStatus); - } - }, - emitStatus: (status) => this.emitStatus(status), - }); - } - } - else { - { - this.logger.debug('PubNub', 'Using legacy subscription loop management.'); - this.subscriptionManager = new SubscriptionManager(this._configuration, (cursor, event) => { - try { - this.emitEvent(cursor, event); - } - catch (e) { - const errorStatus = { - error: true, - category: StatusCategory$1.PNUnknownCategory, - errorData: e, - statusCode: 0, - }; - this.emitStatus(errorStatus); - } - }, this.emitStatus.bind(this), (parameters, callback) => { - this.logger.trace('SubscriptionManager', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Subscribe with parameters:', - ignoredKeys: ['crypto', 'timeout', 'keySet', 'getFileUrl'], - })); - this.makeSubscribe(parameters, callback); - }, (parameters, callback) => { - this.logger.trace('SubscriptionManager', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Heartbeat with parameters:', - ignoredKeys: ['crypto', 'timeout', 'keySet', 'getFileUrl'], - })); - return this.heartbeat(parameters, callback); - }, (parameters, callback) => { - this.logger.trace('SubscriptionManager', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Leave with parameters:', - })); - this.makeUnsubscribe(parameters, callback); - }, this.time.bind(this)); - } - } - } - } - // -------------------------------------------------------- - // -------------------- Configuration ---------------------- - // -------------------------------------------------------- - // region Configuration - /** - * PubNub client configuration. - * - * @returns Currently user PubNub client configuration. - */ - get configuration() { - return this._configuration; - } - /** - * Current PubNub client configuration. - * - * @returns Currently user PubNub client configuration. - * - * @deprecated Use {@link configuration} getter instead. - */ - get _config() { - return this.configuration; - } - /** - * REST API endpoint access authorization key. - * - * It is required to have `authorization key` with required permissions to access REST API - * endpoints when `PAM` enabled for user key set. - */ - get authKey() { - var _a; - return (_a = this._configuration.authKey) !== null && _a !== void 0 ? _a : undefined; - } - /** - * REST API endpoint access authorization key. - * - * It is required to have `authorization key` with required permissions to access REST API - * endpoints when `PAM` enabled for user key set. - */ - getAuthKey() { - return this.authKey; - } - /** - * Change REST API endpoint access authorization key. - * - * @param authKey - New authorization key which should be used with new requests. - */ - setAuthKey(authKey) { - this.logger.debug('PubNub', 'Auth key updated.'); - this._configuration.setAuthKey(authKey); - if (this.onAuthenticationChange) - this.onAuthenticationChange(authKey); - } - /** - * Get a PubNub client user identifier. - * - * @returns Current PubNub client user identifier. - */ - get userId() { - return this._configuration.userId; - } - /** - * Change the current PubNub client user identifier. - * - * **Important:** Change won't affect ongoing REST API calls. - * **Warning:** Because ongoing REST API calls won't be canceled there could happen unexpected events like implicit - * `join` event for the previous `userId` after a long-poll subscribe request will receive a response. To avoid this - * it is advised to unsubscribe from all/disconnect before changing `userId`. - * - * @param value - New PubNub client user identifier. - * - * @throws Error empty user identifier has been provided. - */ - set userId(value) { - if (!value || typeof value !== 'string' || value.trim().length === 0) { - const error = new Error('Missing or invalid userId parameter. Provide a valid string userId'); - this.logger.error('PubNub', () => ({ messageType: 'error', message: error })); - throw error; - } - this.logger.debug('PubNub', `Set user ID: ${value}`); - this._configuration.userId = value; - if (this.onUserIdChange) - this.onUserIdChange(this._configuration.userId); - } - /** - * Get a PubNub client user identifier. - * - * @returns Current PubNub client user identifier. - */ - getUserId() { - return this._configuration.userId; - } - /** - * Change the current PubNub client user identifier. - * - * **Important:** Change won't affect ongoing REST API calls. - * - * @param value - New PubNub client user identifier. - * - * @throws Error empty user identifier has been provided. - */ - setUserId(value) { - this.userId = value; - } - /** - * Real-time updates filtering expression. - * - * @returns Filtering expression. - */ - get filterExpression() { - var _a; - return (_a = this._configuration.getFilterExpression()) !== null && _a !== void 0 ? _a : undefined; - } - /** - * Real-time updates filtering expression. - * - * @returns Filtering expression. - */ - getFilterExpression() { - return this.filterExpression; - } - /** - * Update real-time updates filtering expression. - * - * @param expression - New expression which should be used or `undefined` to disable filtering. - */ - set filterExpression(expression) { - this.logger.debug('PubNub', `Set filter expression: ${expression}`); - this._configuration.setFilterExpression(expression); - } - /** - * Update real-time updates filtering expression. - * - * @param expression - New expression which should be used or `undefined` to disable filtering. - */ - setFilterExpression(expression) { - this.logger.debug('PubNub', `Set filter expression: ${expression}`); - this.filterExpression = expression; - } - /** - * Dta encryption / decryption key. - * - * @returns Currently used key for data encryption / decryption. - */ - get cipherKey() { - return this._configuration.getCipherKey(); - } - /** - * Change data encryption / decryption key. - * - * @param key - New key which should be used for data encryption / decryption. - */ - set cipherKey(key) { - this._configuration.setCipherKey(key); - } - /** - * Change data encryption / decryption key. - * - * @param key - New key which should be used for data encryption / decryption. - */ - setCipherKey(key) { - this.logger.debug('PubNub', 'Cipher key updated.'); - this.cipherKey = key; - } - /** - * Change a heartbeat requests interval. - * - * @param interval - New presence request heartbeat intervals. - */ - set heartbeatInterval(interval) { - var _a; - this.logger.debug('PubNub', `Set heartbeat interval: ${interval}`); - this._configuration.setHeartbeatInterval(interval); - if (this.onHeartbeatIntervalChange) - this.onHeartbeatIntervalChange((_a = this._configuration.getHeartbeatInterval()) !== null && _a !== void 0 ? _a : 0); - } - /** - * Change a heartbeat requests interval. - * - * @param interval - New presence request heartbeat intervals. - */ - setHeartbeatInterval(interval) { - this.heartbeatInterval = interval; - } - /** - * Get registered loggers' manager. - * - * @returns Registered loggers' manager. - */ - get logger() { - return this._configuration.logger(); - } - /** - * Get PubNub SDK version. - * - * @returns Current SDK version. - */ - getVersion() { - return this._configuration.getVersion(); - } - /** - * Add framework's prefix. - * - * @param name - Name of the framework which would want to add own data into `pnsdk` suffix. - * @param suffix - Suffix with information about a framework. - */ - _addPnsdkSuffix(name, suffix) { - this.logger.debug('PubNub', `Add '${name}' 'pnsdk' suffix: ${suffix}`); - this._configuration._addPnsdkSuffix(name, suffix); - } - // -------------------------------------------------------- - // ---------------------- Deprecated ---------------------- - // -------------------------------------------------------- - // region Deprecated - /** - * Get a PubNub client user identifier. - * - * @returns Current PubNub client user identifier. - * - * @deprecated Use the {@link getUserId} or {@link userId} getter instead. - */ - getUUID() { - return this.userId; - } - /** - * Change the current PubNub client user identifier. - * - * **Important:** Change won't affect ongoing REST API calls. - * - * @param value - New PubNub client user identifier. - * - * @throws Error empty user identifier has been provided. - * - * @deprecated Use the {@link PubNubCore#setUserId setUserId} or {@link PubNubCore#userId userId} setter instead. - */ - setUUID(value) { - this.logger.warn('PubNub', "'setUserId` is deprecated, please use 'setUserId' or 'userId' setter instead."); - this.logger.debug('PubNub', `Set UUID: ${value}`); - this.userId = value; - } - /** - * Custom data encryption method. - * - * @deprecated Instead use {@link cryptoModule} for data encryption. - */ - get customEncrypt() { - return this._configuration.getCustomEncrypt(); - } - /** - * Custom data decryption method. - * - * @deprecated Instead use {@link cryptoModule} for data decryption. - */ - get customDecrypt() { - return this._configuration.getCustomDecrypt(); - } - // endregion - // endregion - // -------------------------------------------------------- - // ---------------------- Entities ------------------------ - // -------------------------------------------------------- - // region Entities - /** - * Create a `Channel` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param name - Unique channel name. - * @returns `Channel` entity. - */ - channel(name) { - let channel = this.entities[`${name}_ch`]; - if (!channel) - channel = this.entities[`${name}_ch`] = new Channel(name, this); - return channel; - } - /** - * Create a `ChannelGroup` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param name - Unique channel group name. - * @returns `ChannelGroup` entity. - */ - channelGroup(name) { - let channelGroup = this.entities[`${name}_chg`]; - if (!channelGroup) - channelGroup = this.entities[`${name}_chg`] = new ChannelGroup(name, this); - return channelGroup; - } - /** - * Create a `ChannelMetadata` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param id - Unique channel metadata object identifier. - * @returns `ChannelMetadata` entity. - */ - channelMetadata(id) { - let metadata = this.entities[`${id}_chm`]; - if (!metadata) - metadata = this.entities[`${id}_chm`] = new ChannelMetadata(id, this); - return metadata; - } - /** - * Create a `UserMetadata` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param id - Unique user metadata object identifier. - * @returns `UserMetadata` entity. - */ - userMetadata(id) { - let metadata = this.entities[`${id}_um`]; - if (!metadata) - metadata = this.entities[`${id}_um`] = new UserMetadata(id, this); - return metadata; - } - /** - * Create a `DataSyncUser` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param id - Unique DataSync `User` object identifier (used verbatim, so wildcard identifiers - * like `user.*` are supported). - * @returns `DataSyncUser` entity. - */ - dataSyncUser(id) { - let entity = this.entities[`${id}_dsu`]; - if (!entity) - entity = this.entities[`${id}_dsu`] = new DataSyncUser(id, this); - return entity; - } - /** - * Create a `DataSyncChannel` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param id - Unique DataSync `Channel` object identifier (used verbatim, so wildcard identifiers - * like `channel.*` are supported). - * @returns `DataSyncChannel` entity. - */ - dataSyncChannel(id) { - let entity = this.entities[`${id}_dsc`]; - if (!entity) - entity = this.entities[`${id}_dsc`] = new DataSyncChannel(id, this); - return entity; - } - /** - * Create a `DataSyncMembership` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * **Important:** Membership changes are delivered on the data channels of both linked entities - * (the user and the channel identifier), not on the membership identifier — use - * {@link PubNubCore#dataSyncUser dataSyncUser} / {@link PubNubCore#dataSyncChannel - * dataSyncChannel} to observe them. - * - * @param id - Unique DataSync `Membership` object identifier (`{userId}:{channelId}`, used - * verbatim, so wildcard identifiers like `user-123:*` are supported). - * @returns `DataSyncMembership` entity. - */ - dataSyncMembership(id) { - let entity = this.entities[`${id}_dsm`]; - if (!entity) - entity = this.entities[`${id}_dsm`] = new DataSyncMembership(id, this); - return entity; - } - /** - * Create a `DataSyncEntity` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * @param id - Unique DataSync `Entity` object identifier (used verbatim, so wildcard identifiers - * like `customer.*` are supported). - * @returns `DataSyncEntity` entity. - */ - dataSyncEntity(id) { - let entity = this.entities[`${id}_dse`]; - if (!entity) - entity = this.entities[`${id}_dse`] = new DataSyncEntity(id, this); - return entity; - } - /** - * Create a `DataSyncRelationship` entity. - * - * Entity can be used for the interaction with the following API: - * - `subscribe` - * - * **Important:** Relationship changes are delivered on the data channels of both linked entities - * (`entityAId` and `entityBId`), not on the relationship identifier — use - * {@link PubNubCore#dataSyncEntity dataSyncEntity} to observe them. - * - * @param id - Unique DataSync `Relationship` object identifier (used verbatim, so wildcard - * identifiers like `owns.*` are supported). - * @returns `DataSyncRelationship` entity. - */ - dataSyncRelationship(id) { - let entity = this.entities[`${id}_dsr`]; - if (!entity) - entity = this.entities[`${id}_dsr`] = new DataSyncRelationship(id, this); - return entity; - } - /** - * Create subscriptions set object. - * - * @param parameters - Subscriptions set configuration parameters. - */ - subscriptionSet(parameters) { - var _a, _b; - { - // Prepare a list of entities for a set. - const entities = []; - (_a = parameters.channels) === null || _a === void 0 ? void 0 : _a.forEach((name) => entities.push(this.channel(name))); - (_b = parameters.channelGroups) === null || _b === void 0 ? void 0 : _b.forEach((name) => entities.push(this.channelGroup(name))); - return new SubscriptionSet({ client: this, entities, options: parameters.subscriptionOptions }); - } - } - /** - * Schedule request execution. - * - * @internal - * - * @param request - REST API request. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous request execution and response parsing result or `void` in case if - * `callback` provided. - * - * @throws PubNubError in case of request processing error. - */ - sendRequest(request, callback) { - return __awaiter(this, void 0, void 0, function* () { - // Validate user-input. - const validationResult = request.validate(); - if (validationResult) { - const validationError = createValidationError(validationResult); - this.logger.error('PubNub', () => ({ messageType: 'error', message: validationError })); - if (callback) - return callback(validationError, null); - throw new PubNubError('Validation failed, check status for details', validationError); - } - // Complete request configuration. - const transportRequest = request.request(); - const operation = request.operation(); - if ((transportRequest.formData && transportRequest.formData.length > 0) || - operation === RequestOperation$1.PNDownloadFileOperation) { - // Set file upload / download request delay. - transportRequest.timeout = this._configuration.getFileTimeout(); - } - else { - if (operation === RequestOperation$1.PNSubscribeOperation || - operation === RequestOperation$1.PNReceiveMessagesOperation) - transportRequest.timeout = this._configuration.getSubscribeTimeout(); - else - transportRequest.timeout = this._configuration.getTransactionTimeout(); - } - // API request processing status. - const status = { - error: false, - operation, - category: StatusCategory$1.PNAcknowledgmentCategory, - statusCode: 0, - }; - const [sendableRequest, cancellationController] = this.transport.makeSendable(transportRequest); - /** - * **Important:** Because of multiple environments where JS SDK can be used, control over - * cancellation had to be inverted to let the transport provider solve a request cancellation task - * more efficiently. As a result, cancellation controller can be retrieved and used only after - * the request will be scheduled by the transport provider. - */ - request.cancellationController = cancellationController ? cancellationController : null; - return sendableRequest - .then((response) => { - status.statusCode = response.status; - // Handle a special case when request completed but not fully processed by PubNub service. - if (response.status !== 200 && response.status !== 204) { - const responseText = PubNubCore.decoder.decode(response.body); - const contentType = response.headers['content-type']; - if (contentType || contentType.indexOf('javascript') !== -1 || contentType.indexOf('json') !== -1) { - const json = JSON.parse(responseText); - if (typeof json === 'object' && 'error' in json && json.error && typeof json.error === 'object') - status.errorData = json.error; - } - else - status.responseText = responseText; - } - return request.parse(response); - }) - .then((parsed) => { - // Notify callback (if possible). - if (callback) - return callback(status, parsed); - return parsed; - }) - .catch((error) => { - const apiError = !(error instanceof PubNubAPIError) ? PubNubAPIError.create(error) : error; - // Notify callback (if possible). - if (callback) { - if (apiError.category !== StatusCategory$1.PNCancelledCategory) { - this.logger.error('PubNub', () => ({ - messageType: 'error', - message: apiError.toPubNubError(operation, 'REST API request processing error, check status for details'), - })); - } - return callback(apiError.toStatus(operation), null); - } - const pubNubError = apiError.toPubNubError(operation, 'REST API request processing error, check status for details'); - if (apiError.category !== StatusCategory$1.PNCancelledCategory) - this.logger.error('PubNub', () => ({ messageType: 'error', message: pubNubError })); - throw pubNubError; - }); - }); - } - /** - * Unsubscribe from all channels and groups. - * - * @param [isOffline] - Whether `offline` presence should be notified or not. - */ - destroy(isOffline = false) { - this.logger.info('PubNub', 'Destroying PubNub client.'); - { - if (this._globalSubscriptionSet) { - this._globalSubscriptionSet.invalidate(true); - this._globalSubscriptionSet = undefined; - } - Object.values(this.eventHandleCapable).forEach((subscription) => subscription.invalidate(true)); - this.eventHandleCapable = {}; - if (this.subscriptionManager) { - this.subscriptionManager.unsubscribeAll(isOffline); - this.subscriptionManager.disconnect(); - } - else if (this.eventEngine) - this.eventEngine.unsubscribeAll(isOffline); - } - { - if (this.presenceEventEngine) - this.presenceEventEngine.leaveAll(isOffline); - } - } - /** - * Unsubscribe from all channels and groups. - * - * @deprecated Use {@link destroy} method instead. - */ - stop() { - this.logger.warn('PubNub', "'stop' is deprecated, please use 'destroy' instead."); - this.destroy(); - } - /** - * Publish data to a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous publish data response or `void` in case if `callback` provided. - */ - publish(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Publish with parameters:', - })); - const isFireRequest = parameters.replicate === false && parameters.storeInHistory === false; - const request = new PublishRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule() })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `${isFireRequest ? 'Fire' : 'Publish'} success with timetoken: ${response.timetoken}`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Signal data to a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous signal data response or `void` in case if `callback` provided. - */ - signal(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Signal with parameters:', - })); - const request = new SignalRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Publish success with timetoken: ${response.timetoken}`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * `Fire` a data to a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous signal data response or `void` in case if `callback` provided. - * - * @deprecated Use {@link publish} method instead. - */ - fire(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Fire with parameters:', - })); - callback !== null && callback !== void 0 ? callback : (callback = () => { }); - return this.publish(Object.assign(Object.assign({}, parameters), { replicate: false, storeInHistory: false }), callback); - }); - } - // endregion - // -------------------------------------------------------- - // -------------------- Subscribe API --------------------- - // -------------------------------------------------------- - // region Subscribe API - /** - * Global subscription set which supports legacy subscription interface. - * - * @returns Global subscription set. - * - * @internal - */ - get globalSubscriptionSet() { - if (!this._globalSubscriptionSet) - this._globalSubscriptionSet = this.subscriptionSet({}); - return this._globalSubscriptionSet; - } - /** - * Subscription-based current timetoken. - * - * @returns Timetoken based on current timetoken plus diff between current and loop start time. - * - * @internal - */ - get subscriptionTimetoken() { - { - if (this.subscriptionManager) - return this.subscriptionManager.subscriptionTimetoken; - else if (this.eventEngine) - return this.eventEngine.subscriptionTimetoken; - } - return undefined; - } - /** - * Get list of channels on which PubNub client currently subscribed. - * - * @returns List of active channels. - */ - getSubscribedChannels() { - { - if (this.subscriptionManager) - return this.subscriptionManager.subscribedChannels; - else if (this.eventEngine) - return this.eventEngine.getSubscribedChannels(); - } - return []; - } - /** - * Get list of channel groups on which PubNub client currently subscribed. - * - * @returns List of active channel groups. - */ - getSubscribedChannelGroups() { - { - if (this.subscriptionManager) - return this.subscriptionManager.subscribedChannelGroups; - else if (this.eventEngine) - return this.eventEngine.getSubscribedChannelGroups(); - } - return []; - } - /** - * Register an events handler object ({@link Subscription} or {@link SubscriptionSet}) with an active subscription. - * - * @param subscription - {@link Subscription} or {@link SubscriptionSet} object. - * @param [cursor] - Subscription catchup timetoken. - * @param [subscriptions] - List of subscriptions for partial subscription loop update. - * - * @internal - */ - registerEventHandleCapable(subscription, cursor, subscriptions) { - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign(Object.assign({ subscription: subscription }, (cursor ? { cursor } : [])), (subscriptions ? { subscriptions } : {})), - details: `Register event handle capable:`, - })); - if (!this.eventHandleCapable[subscription.state.id]) - this.eventHandleCapable[subscription.state.id] = subscription; - let subscriptionInput; - if (!subscriptions || subscriptions.length === 0) - subscriptionInput = subscription.subscriptionInput(false); - else { - subscriptionInput = new SubscriptionInput({}); - subscriptions.forEach((subscription) => subscriptionInput.add(subscription.subscriptionInput(false))); - } - const parameters = {}; - parameters.channels = subscriptionInput.channels; - parameters.channelGroups = subscriptionInput.channelGroups; - if (cursor) - parameters.timetoken = cursor.timetoken; - if (this.subscriptionManager) - this.subscriptionManager.subscribe(parameters); - else if (this.eventEngine) - this.eventEngine.subscribe(parameters); - } - } - /** - * Unregister an events handler object ({@link Subscription} or {@link SubscriptionSet}) with inactive subscription. - * - * @param subscription - {@link Subscription} or {@link SubscriptionSet} object. - * @param [subscriptions] - List of subscriptions for partial subscription loop update. - * - * @internal - */ - unregisterEventHandleCapable(subscription, subscriptions) { - { - if (!this.eventHandleCapable[subscription.state.id]) - return; - const inUseSubscriptions = []; - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: { subscription: subscription, subscriptions }, - details: `Unregister event handle capable:`, - })); - // Check whether only subscription object has been passed to be unregistered. - let shouldDeleteEventHandler = !subscriptions || subscriptions.length === 0; - // Check whether subscription set is unregistering with all managed Subscription objects, - if (!shouldDeleteEventHandler && - subscription instanceof SubscriptionSet && - subscription.subscriptions.length === (subscriptions === null || subscriptions === void 0 ? void 0 : subscriptions.length)) - shouldDeleteEventHandler = subscription.subscriptions.every((sub) => subscriptions.includes(sub)); - if (shouldDeleteEventHandler) - delete this.eventHandleCapable[subscription.state.id]; - let subscriptionInput; - if (!subscriptions || subscriptions.length === 0) { - subscriptionInput = subscription.subscriptionInput(true); - if (subscriptionInput.isEmpty) - inUseSubscriptions.push(subscription); - } - else { - subscriptionInput = new SubscriptionInput({}); - subscriptions.forEach((subscription) => { - const input = subscription.subscriptionInput(true); - if (input.isEmpty) - inUseSubscriptions.push(subscription); - else - subscriptionInput.add(input); - }); - } - if (inUseSubscriptions.length > 0) { - this.logger.trace('PubNub', () => { - const entities = []; - if (inUseSubscriptions[0] instanceof SubscriptionSet) { - inUseSubscriptions[0].subscriptions.forEach((subscription) => entities.push(subscription.state.entity)); - } - else - inUseSubscriptions.forEach((subscription) => entities.push(subscription.state.entity)); - return { - messageType: 'object', - message: { entities }, - details: `Can't unregister event handle capable because entities still in use:`, - }; - }); - } - if (subscriptionInput.isEmpty) - return; - else { - const _channelGroupsInUse = []; - const _channelsInUse = []; - Object.values(this.eventHandleCapable).forEach((_subscription) => { - const _subscriptionInput = _subscription.subscriptionInput(false); - const _subscriptionChannelGroups = _subscriptionInput.channelGroups; - const _subscriptionChannels = _subscriptionInput.channels; - _channelGroupsInUse.push(...subscriptionInput.channelGroups.filter((channel) => _subscriptionChannelGroups.includes(channel))); - _channelsInUse.push(...subscriptionInput.channels.filter((channel) => _subscriptionChannels.includes(channel))); - }); - if (_channelsInUse.length > 0 || _channelGroupsInUse.length > 0) { - this.logger.trace('PubNub', () => { - const _entitiesInUse = []; - const addEntityIfInUse = (entity) => { - const namesOrIds = entity.subscriptionNames(true); - const checkList = entity.subscriptionType === SubscriptionType.Channel ? _channelsInUse : _channelGroupsInUse; - if (namesOrIds.some((id) => checkList.includes(id))) - _entitiesInUse.push(entity); - }; - Object.values(this.eventHandleCapable).forEach((_subscription) => { - if (_subscription instanceof SubscriptionSet) { - _subscription.subscriptions.forEach((_subscriptionInSet) => { - addEntityIfInUse(_subscriptionInSet.state.entity); - }); - } - else if (_subscription instanceof Subscription) - addEntityIfInUse(_subscription.state.entity); - }); - let details = 'Some entities still in use:'; - if (_channelsInUse.length + _channelGroupsInUse.length === subscriptionInput.length) - details = "Can't unregister event handle capable because entities still in use:"; - return { messageType: 'object', message: { entities: _entitiesInUse }, details }; - }); - subscriptionInput.remove(new SubscriptionInput({ channels: _channelsInUse, channelGroups: _channelGroupsInUse })); - if (subscriptionInput.isEmpty) - return; - } - } - const parameters = {}; - parameters.channels = subscriptionInput.channels; - parameters.channelGroups = subscriptionInput.channelGroups; - if (this.subscriptionManager) - this.subscriptionManager.unsubscribe(parameters); - else if (this.eventEngine) - this.eventEngine.unsubscribe(parameters); - } - } - /** - * Subscribe to specified channels and groups real-time events. - * - * @param parameters - Request configuration parameters. - */ - subscribe(parameters) { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Subscribe with parameters:', - })); - // The addition of a new subscription set into the subscribed global subscription set will update the active - // subscription loop with new channels and groups. - const subscriptionSet = this.subscriptionSet(Object.assign(Object.assign({}, parameters), { subscriptionOptions: { receivePresenceEvents: parameters.withPresence } })); - this.globalSubscriptionSet.addSubscriptionSet(subscriptionSet); - subscriptionSet.dispose(); - const timetoken = typeof parameters.timetoken === 'number' ? `${parameters.timetoken}` : parameters.timetoken; - this.globalSubscriptionSet.subscribe({ timetoken }); - } - } - /** - * Perform subscribe request. - * - * **Note:** Method passed into managers to let them use it when required. - * - * @internal - * - * @param parameters - Request configuration parameters. - * @param callback - Request completion handler callback. - */ - makeSubscribe(parameters, callback) { - { - // `on-demand` query parameter not required for non-SharedWorker environment. - if (!this._configuration.isSharedWorkerEnabled()) - parameters.onDemand = false; - const request = new SubscribeRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); - this.sendRequest(request, (status, result) => { - var _a; - if (this.subscriptionManager && ((_a = this.subscriptionManager.abort) === null || _a === void 0 ? void 0 : _a.identifier) === request.requestIdentifier) - this.subscriptionManager.abort = null; - callback(status, result); - }); - /** - * Allow subscription cancellation. - * - * **Note:** Had to be done after scheduling because the transport provider returns the cancellation - * controller only when schedule new request. - */ - if (this.subscriptionManager) { - // Creating an identifiable abort caller. - const callableAbort = () => request.abort('Cancel long-poll subscribe request'); - callableAbort.identifier = request.requestIdentifier; - this.subscriptionManager.abort = callableAbort; - } - } - } - /** - * Unsubscribe from specified channels and groups real-time events. - * - * @param parameters - Request configuration parameters. - */ - unsubscribe(parameters) { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Unsubscribe with parameters:', - })); - if (!this._globalSubscriptionSet) { - this.logger.debug('PubNub', 'There are no active subscriptions. Ignore.'); - return; - } - const subscriptions = this.globalSubscriptionSet.subscriptions.filter((subscription) => { - var _a, _b; - const subscriptionInput = subscription.subscriptionInput(false); - if (subscriptionInput.isEmpty) - return false; - for (const channel of (_a = parameters.channels) !== null && _a !== void 0 ? _a : []) - if (subscriptionInput.contains(channel)) - return true; - for (const group of (_b = parameters.channelGroups) !== null && _b !== void 0 ? _b : []) - if (subscriptionInput.contains(group)) - return true; - }); - // Removal from the active subscription also will cause `unsubscribe`. - if (subscriptions.length > 0) - this.globalSubscriptionSet.removeSubscriptions(subscriptions); - } - } - /** - * Perform unsubscribe request. - * - * **Note:** Method passed into managers to let them use it when required. - * - * @internal - * - * @param parameters - Request configuration parameters. - * @param callback - Request completion handler callback. - */ - makeUnsubscribe(parameters, callback) { - { - // Filtering out presence channels and groups. - let { channels, channelGroups } = parameters; - // Remove `-pnpres` channels / groups if they not acceptable in the current PubNub client configuration. - if (!this._configuration.getKeepPresenceChannelsInPresenceRequests()) { - if (channelGroups) - channelGroups = channelGroups.filter((channelGroup) => !channelGroup.endsWith('-pnpres')); - if (channels) - channels = channels.filter((channel) => !channel.endsWith('-pnpres')); - } - // Complete immediately request only for presence channels. - if ((channelGroups !== null && channelGroups !== void 0 ? channelGroups : []).length === 0 && (channels !== null && channels !== void 0 ? channels : []).length === 0) { - return callback({ - error: false, - operation: RequestOperation$1.PNUnsubscribeOperation, - category: StatusCategory$1.PNAcknowledgmentCategory, - statusCode: 200, - }); - } - this.sendRequest(new PresenceLeaveRequest({ channels, channelGroups, keySet: this._configuration.keySet }), callback); - } - } - /** - * Unsubscribe from all channels and groups. - */ - unsubscribeAll() { - { - this.logger.debug('PubNub', 'Unsubscribe all channels and groups'); - // Keeping a subscription set instance after invalidation so to make it possible to deliver the expected - // disconnection status. - if (this._globalSubscriptionSet) - this._globalSubscriptionSet.invalidate(false); - Object.values(this.eventHandleCapable).forEach((subscription) => subscription.invalidate(false)); - this.eventHandleCapable = {}; - if (this.subscriptionManager) - this.subscriptionManager.unsubscribeAll(); - else if (this.eventEngine) - this.eventEngine.unsubscribeAll(); - } - } - /** - * Temporarily disconnect from the real-time events stream. - * - * **Note:** `isOffline` is set to `true` only when a client experiences network issues. - * - * @param [isOffline] - Whether `offline` presence should be notified or not. - */ - disconnect(isOffline = false) { - { - this.logger.debug('PubNub', `Disconnect (while offline? ${!!isOffline ? 'yes' : 'no'})`); - if (this.subscriptionManager) - this.subscriptionManager.disconnect(); - else if (this.eventEngine) - this.eventEngine.disconnect(isOffline); - } - } - /** - * Restore connection to the real-time events stream. - * - * @param parameters - Reconnection catch-up configuration. **Note:** available only with the enabled event engine. - */ - reconnect(parameters) { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Reconnect with parameters:', - })); - if (this.subscriptionManager) - this.subscriptionManager.reconnect(); - else if (this.eventEngine) - this.eventEngine.reconnect(parameters !== null && parameters !== void 0 ? parameters : {}); - } - } - /** - * Event engine handshake subscribe. - * - * @internal - * - * @param parameters - Request configuration parameters. - */ - subscribeHandshake(parameters) { - return __awaiter(this, void 0, void 0, function* () { - { - // `on-demand` query parameter not required for non-SharedWorker environment. - if (!this._configuration.isSharedWorkerEnabled()) - parameters.onDemand = false; - if (!parameters.heartbeat) - parameters.heartbeat = this._configuration.getPresenceTimeout(); - const request = new HandshakeSubscribeRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); - const abortUnsubscribe = parameters.abortSignal.subscribe((err) => { - request.abort('Cancel subscribe handshake request'); - }); - /** - * Allow subscription cancellation. - * - * **Note:** Had to be done after scheduling because the transport provider returns the cancellation - * controller only when schedule new request. - */ - const handshakeResponse = this.sendRequest(request); - return handshakeResponse.then((response) => { - abortUnsubscribe(); - return response.cursor; - }); - } - }); - } - /** - * Event engine receive messages subscribe. - * - * @internal - * - * @param parameters - Request configuration parameters. - */ - subscribeReceiveMessages(parameters) { - return __awaiter(this, void 0, void 0, function* () { - { - // `on-demand` query parameter not required for non-SharedWorker environment. - if (!this._configuration.isSharedWorkerEnabled()) - parameters.onDemand = false; - if (!parameters.heartbeat) - parameters.heartbeat = this._configuration.getPresenceTimeout(); - const request = new ReceiveMessagesSubscribeRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); - const abortUnsubscribe = parameters.abortSignal.subscribe((err) => { - request.abort('Cancel long-poll subscribe request'); - }); - /** - * Allow subscription cancellation. - * - * **Note:** Had to be done after scheduling because the transport provider returns the cancellation - * controller only when schedule new request. - */ - const receiveResponse = this.sendRequest(request); - return receiveResponse.then((response) => { - abortUnsubscribe(); - return response; - }); - } - }); - } - /** - * Get reactions to a specific message. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get reactions response or `void` in case if `callback` provided. - */ - getMessageActions(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get message actions with parameters:', - })); - const request = new GetMessageActionsRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get message actions success. Received ${response.data.length} message actions.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Add a reaction to a specific message. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous add a reaction response or `void` in case if `callback` provided. - */ - addMessageAction(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Add message action with parameters:', - })); - const request = new AddMessageActionRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Message action add success. Message action added with timetoken: ${response.data.actionTimetoken}`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Remove a reaction from a specific message. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous remove a reaction response or `void` in case if `callback` provided. - */ - removeMessageAction(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Remove message action with parameters:', - })); - const request = new RemoveMessageAction(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Message action remove success. Removed message action with ${parameters.actionTimetoken} timetoken.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Fetch messages history for channels. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous fetch messages response or `void` in case if `callback` provided. - */ - fetchMessages(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Fetch messages with parameters:', - })); - const request = new FetchMessagesRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); - const logResponse = (response) => { - if (!response) - return; - const messagesCount = Object.values(response.channels).reduce((acc, message) => acc + message.length, 0); - this.logger.debug('PubNub', `Fetch messages success. Received ${messagesCount} messages.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Delete messages from the channel history. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous delete messages response or `void` in case if `callback` provided. - * - */ - deleteMessages(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Delete messages with parameters:', - })); - const request = new DeleteMessageRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Delete messages success.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Count messages from the channels' history. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous count messages response or `void` in case if `callback` provided. - */ - messageCounts(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get messages count with parameters:', - })); - const request = new MessageCountRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - const messagesCount = Object.values(response.channels).reduce((acc, messagesCount) => acc + messagesCount, 0); - this.logger.debug('PubNub', `Get messages count success. There are ${messagesCount} messages since provided reference timetoken${parameters.channelTimetokens ? parameters.channelTimetokens.join(',') : ''.length > 1 ? 's' : ''}.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Fetch single channel history. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous fetch channel history response or `void` in case if `callback` provided. - * - * @deprecated - */ - history(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Fetch history with parameters:', - })); - const request = new GetHistoryRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule() })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Fetch history success. Received ${response.messages.length} messages.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Get channel's presence information. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get channel's presence response or `void` in case if `callback` provided. - */ - hereNow(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Here now with parameters:', - })); - const request = new HereNowRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Here now success. There are ${response.totalOccupancy} participants in ${response.totalChannels} channels.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Get user's presence information. - * - * Get list of channels to which `uuid` currently subscribed. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get user's presence response or `void` in case if `callback` provided. - */ - whereNow(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Where now with parameters:', - })); - const request = new WhereNowRequest({ - uuid: (_a = parameters.uuid) !== null && _a !== void 0 ? _a : this._configuration.userId, - keySet: this._configuration.keySet, - }); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Where now success. Currently present in ${response.channels.length} channels.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Get associated user's data for channels and groups. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get user's data response or `void` in case if `callback` provided. - */ - getState(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Get presence state with parameters:', - })); - const request = new GetPresenceStateRequest(Object.assign(Object.assign({}, parameters), { uuid: (_a = parameters.uuid) !== null && _a !== void 0 ? _a : this._configuration.userId, keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get presence state success. Received presence state for ${Object.keys(response.channels).length} channels.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Set associated user's data for channels and groups. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous set user's data response or `void` in case if `callback` provided. - */ - setState(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b; - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Set presence state with parameters:', - })); - const { keySet, userId: userId } = this._configuration; - const heartbeat = this._configuration.getPresenceTimeout(); - let request; - // Maintain presence information (if required). - if (this._configuration.enableEventEngine && this.presenceState) { - const presenceState = this.presenceState; - (_a = parameters.channels) === null || _a === void 0 ? void 0 : _a.forEach((channel) => (presenceState[channel] = parameters.state)); - if ('channelGroups' in parameters) { - (_b = parameters.channelGroups) === null || _b === void 0 ? void 0 : _b.forEach((group) => (presenceState[group] = parameters.state)); - } - if (this.onPresenceStateChange) - this.onPresenceStateChange(this.presenceState); - } - // Check whether the state should be set with heartbeat or not. - if ('withHeartbeat' in parameters && parameters.withHeartbeat) { - request = new HeartbeatRequest(Object.assign(Object.assign({}, parameters), { keySet, heartbeat })); - } - else { - request = new SetPresenceStateRequest(Object.assign(Object.assign({}, parameters), { keySet, uuid: userId })); - } - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Set presence state success.${request instanceof HeartbeatRequest ? ' Presence state has been set using heartbeat endpoint.' : ''}`); - }; - // Update state used by subscription manager. - if (this.subscriptionManager) { - this.subscriptionManager.setState(parameters); - if (this.onPresenceStateChange) - this.onPresenceStateChange(this.subscriptionManager.presenceState); - } - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - // endregion - // region Change presence state - /** - * Manual presence management. - * - * @param parameters - Desired presence state for a provided list of channels and groups. - */ - presence(parameters) { - var _a; - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Change presence with parameters:', - })); - (_a = this.subscriptionManager) === null || _a === void 0 ? void 0 : _a.changePresence(parameters); - } - } - // endregion - // region Heartbeat - /** - * Announce user presence - * - * @internal - * - * @param parameters - Desired presence state for provided list of channels and groups. - * @param callback - Request completion handler callback. - */ - heartbeat(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Heartbeat with parameters:', - })); - // Filtering out presence channels and groups. - let { channels, channelGroups } = parameters; - // Remove `-pnpres` channels / groups if they not acceptable in the current PubNub client configuration. - if (channelGroups) - channelGroups = channelGroups.filter((channelGroup) => !channelGroup.endsWith('-pnpres')); - if (channels) - channels = channels.filter((channel) => !channel.endsWith('-pnpres')); - // Complete immediately request only for presence channels. - if ((channelGroups !== null && channelGroups !== void 0 ? channelGroups : []).length === 0 && (channels !== null && channels !== void 0 ? channels : []).length === 0) { - const responseStatus = { - error: false, - operation: RequestOperation$1.PNHeartbeatOperation, - category: StatusCategory$1.PNAcknowledgmentCategory, - statusCode: 200, - }; - this.logger.trace('PubNub', 'There are no active subscriptions. Ignore.'); - if (callback) - return callback(responseStatus, {}); - return Promise.resolve(responseStatus); - } - const request = new HeartbeatRequest(Object.assign(Object.assign({}, parameters), { channels: [...new Set(channels)], channelGroups: [...new Set(channelGroups)], keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.trace('PubNub', 'Heartbeat success.'); - }; - const abortUnsubscribe = (_a = parameters.abortSignal) === null || _a === void 0 ? void 0 : _a.subscribe((err) => { - request.abort('Cancel long-poll subscribe request'); - }); - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - if (abortUnsubscribe) - abortUnsubscribe(); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - if (abortUnsubscribe) - abortUnsubscribe(); - return response; - }); - } - }); - } - // endregion - // region Join - /** - * Announce user `join` on specified list of channels and groups. - * - * @internal - * - * @param parameters - List of channels and groups where `join` event should be sent. - */ - join(parameters) { - var _a, _b; - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Join with parameters:', - })); - if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { - this.logger.trace('PubNub', "Ignoring 'join' announcement request."); - return; - } - if (this.presenceEventEngine) - this.presenceEventEngine.join(parameters); - else { - this.heartbeat(Object.assign(Object.assign({ channels: parameters.channels, channelGroups: parameters.groups }, (this._configuration.maintainPresenceState && - this.presenceState && - Object.keys(this.presenceState).length > 0 && { state: this.presenceState })), { heartbeat: this._configuration.getPresenceTimeout() }), () => { }); - } - } - } - /** - * Reconnect presence event engine after network issues. - * - * @param parameters - List of channels and groups where `join` event should be sent. - * - * @internal - */ - presenceReconnect(parameters) { - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Presence reconnect with parameters:', - })); - if (this.presenceEventEngine) - this.presenceEventEngine.reconnect(); - else { - this.heartbeat(Object.assign(Object.assign({ channels: parameters.channels, channelGroups: parameters.groups }, (this._configuration.maintainPresenceState && { state: this.presenceState })), { heartbeat: this._configuration.getPresenceTimeout() }), () => { }); - } - } - } - // endregion - // region Leave - /** - * Announce user `leave` on specified list of channels and groups. - * - * @internal - * - * @param parameters - List of channels and groups where `leave` event should be sent. - */ - leave(parameters) { - var _a, _b, _c; - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Leave with parameters:', - })); - if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { - this.logger.trace('PubNub', "Ignoring 'leave' announcement request."); - return; - } - if (this.presenceEventEngine) - (_c = this.presenceEventEngine) === null || _c === void 0 ? void 0 : _c.leave(parameters); - else - this.makeUnsubscribe({ channels: parameters.channels, channelGroups: parameters.groups }, () => { }); - } - } - /** - * Announce user `leave` on all subscribed channels. - * - * @internal - * - * @param parameters - List of channels and groups where `leave` event should be sent. - */ - leaveAll(parameters = {}) { - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Leave all with parameters:', - })); - if (this.presenceEventEngine) - this.presenceEventEngine.leaveAll(!!parameters.isOffline); - else if (!parameters.isOffline) - this.makeUnsubscribe({ channels: parameters.channels, channelGroups: parameters.groups }, () => { }); - } - } - /** - * Announce user `leave` on disconnection. - * - * @internal - * - * @param parameters - List of channels and groups where `leave` event should be sent. - */ - presenceDisconnect(parameters) { - { - this.logger.trace('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: 'Presence disconnect parameters:', - })); - if (this.presenceEventEngine) - this.presenceEventEngine.disconnect(!!parameters.isOffline); - else if (!parameters.isOffline) - this.makeUnsubscribe({ channels: parameters.channels, channelGroups: parameters.groups }, () => { }); - } - } - /** - * Grant token permission. - * - * Generate an access token with requested permissions. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous grant token response or `void` in case if `callback` provided. - */ - grantToken(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('Grant Token error: PAM module disabled'); - }); - } - /** - * Revoke token permission. - * - * @param token - Access token for which permissions should be revoked. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous revoke token response or `void` in case if `callback` provided. - */ - revokeToken(token, callback) { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('Revoke Token error: PAM module disabled'); - }); - } - // endregion - // region Token Manipulation - /** - * Get a current access token. - * - * @returns Previously configured access token using {@link setToken} method. - */ - get token() { - return this.tokenManager && this.tokenManager.getToken(); - } - /** - * Get a current access token. - * - * @returns Previously configured access token using {@link setToken} method. - */ - getToken() { - return this.token; - } - /** - * Set current access token. - * - * @param token - New access token which should be used with next REST API endpoint calls. - */ - set token(token) { - if (this.tokenManager) - this.tokenManager.setToken(token); - if (this.onAuthenticationChange) - this.onAuthenticationChange(token); - } - /** - * Set current access token. - * - * @param token - New access token which should be used with next REST API endpoint calls. - */ - setToken(token) { - this.logger.debug('PubNub', 'Access token updated.'); - this.token = token; - } - /** - * Parse access token. - * - * Parse token to see what permissions token owner has. - * - * @param token - Token which should be parsed. - * - * @returns Token's permissions information for the resources. - */ - parseToken(token) { - this.logger.debug('PubNub', 'Parse access token.'); - return this.tokenManager && this.tokenManager.parseToken(token); - } - /** - * Grant auth key(s) permission. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous grant auth key(s) permissions or `void` in case if `callback` provided. - * - * @deprecated Use {@link grantToken} and {@link setToken} methods instead. - */ - grant(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('Grant error: PAM module disabled'); - }); - } - /** - * Audit auth key(s) permission. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @deprecated - * - * @deprecated Use {@link grantToken} and {@link setToken} methods instead. - */ - audit(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - throw new Error('Grant Permissions error: PAM module disabled'); - }); - } - // endregion - // endregion - // endregion - // -------------------------------------------------------- - // ------------------- App Context API -------------------- - // -------------------------------------------------------- - // region App Context API - /** - * PubNub App Context API group. - */ - get objects() { - return this._objects; - } - // -------------------------------------------------------- - // -------------------- DataSync API --------------------- - // -------------------------------------------------------- - // region DataSync API - /** - * PubNub DataSync API group. - */ - get dataSync() { - return this._dataSync; - } - /** - Fetch a paginated list of User objects. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all User objects response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.getAllUUIDMetadata getAllUUIDMetadata} method instead. - */ - fetchUsers(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'fetchUsers' is deprecated. Use 'pubnub.objects.getAllUUIDMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, - details: `Fetch all User objects with parameters:`, - })); - return this.objects._getAllUUIDMetadata(parametersOrCallback, callback); - } - }); - } - /** - * Fetch User object for a currently configured PubNub client `uuid`. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get User object response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.getUUIDMetadata getUUIDMetadata} method instead. - */ - fetchUser(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'fetchUser' is deprecated. Use 'pubnub.objects.getUUIDMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' - ? { uuid: this.userId } - : parametersOrCallback, - details: `Fetch${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} User object with parameters:`, - })); - return this.objects._getUUIDMetadata(parametersOrCallback, callback); - } - }); - } - /** - * Create a User object. - * - * @param parameters - Request configuration parameters. Will create a User object for a currently - * configured PubNub client `uuid` if not set. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create User object response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.setUUIDMetadata setUUIDMetadata} method instead. - */ - createUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'createUser' is deprecated. Use 'pubnub.objects.setUUIDMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Create User object with parameters:`, - })); - return this.objects._setUUIDMetadata(parameters, callback); - } - }); - } - /** - * Update a User object. - * - * @param parameters - Request configuration parameters. Will update a User object for a currently - * configured PubNub client `uuid` if not set. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update User object response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.setUUIDMetadata setUUIDMetadata} method instead. - */ - updateUser(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.warn('PubNub', "'updateUser' is deprecated. Use 'pubnub.objects.setUUIDMetadata' instead."); - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Update User object with parameters:`, - })); - return this.objects._setUUIDMetadata(parameters, callback); - } - }); - } - /** - * Remove a specific User object. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous User object removes response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.removeUUIDMetadata removeUUIDMetadata} method instead. - */ - removeUser(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'removeUser' is deprecated. Use 'pubnub.objects.removeUUIDMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' - ? { uuid: this.userId } - : parametersOrCallback, - details: `Remove${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} User object with parameters:`, - })); - return this.objects._removeUUIDMetadata(parametersOrCallback, callback); - } - }); - } - /** - * Fetch a paginated list of Space objects. - * - * @param [parametersOrCallback] - Request configuration parameters or callback from overload. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get all Space objects response or `void` in case if `callback` - * provided. - * - * @deprecated Use {@link PubNubCore#objects.getAllChannelMetadata getAllChannelMetadata} method instead. - */ - fetchSpaces(parametersOrCallback, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'fetchSpaces' is deprecated. Use 'pubnub.objects.getAllChannelMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, - details: `Fetch all Space objects with parameters:`, - })); - return this.objects._getAllChannelMetadata(parametersOrCallback, callback); - } - }); - } - /** - * Fetch a specific Space object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get Space object response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.getChannelMetadata getChannelMetadata} method instead. - */ - fetchSpace(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'fetchSpace' is deprecated. Use 'pubnub.objects.getChannelMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Fetch Space object with parameters:`, - })); - return this.objects._getChannelMetadata(parameters, callback); - } - }); - } - /** - * Create specific Space object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous create Space object response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.setChannelMetadata setChannelMetadata} method instead. - */ - createSpace(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'createSpace' is deprecated. Use 'pubnub.objects.setChannelMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Create Space object with parameters:`, - })); - return this.objects._setChannelMetadata(parameters, callback); - } - }); - } - /** - * Update specific Space object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update Space object response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.setChannelMetadata setChannelMetadata} method instead. - */ - updateSpace(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'updateSpace' is deprecated. Use 'pubnub.objects.setChannelMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Update Space object with parameters:`, - })); - return this.objects._setChannelMetadata(parameters, callback); - } - }); - } - /** - * Remove a specific Space object. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous Space object remove response or `void` in case if `callback` - * provided. - * - * @deprecated Use {@link PubNubCore#objects.removeChannelMetadata removeChannelMetadata} method instead. - */ - removeSpace(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'removeSpace' is deprecated. Use 'pubnub.objects.removeChannelMetadata' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove Space object with parameters:`, - })); - return this.objects._removeChannelMetadata(parameters, callback); - } - }); - } - /** - * Fetch a paginated list of specific Space members or specific User memberships. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get specific Space members or specific User memberships response or - * `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.getChannelMembers getChannelMembers} or - * {@link PubNubCore#objects.getMemberships getMemberships} methods instead. - */ - fetchMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - return this.objects.fetchMemberships(parameters, callback); - }); - } - /** - * Add members to specific Space or memberships specific User. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous add members to specific Space or memberships specific User response or - * `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.setChannelMembers setChannelMembers} or - * {@link PubNubCore#objects.setMemberships setMemberships} methods instead. - */ - addMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - return this.objects.addMemberships(parameters, callback); - }); - } - /** - * Update specific Space members or User memberships. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous update Space members or User memberships response or `void` in case - * if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.setChannelMembers setChannelMembers} or - * {@link PubNubCore#objects.setMemberships setMemberships} methods instead. - */ - updateMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.warn('PubNub', "'addMemberships' is deprecated. Use 'pubnub.objects.setChannelMembers' or 'pubnub.objects.setMemberships'" + - ' instead.'); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Update memberships with parameters:`, - })); - return this.objects.addMemberships(parameters, callback); - } - }); - } - /** - * Remove User membership. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous memberships modification response or `void` in case if `callback` provided. - * - * @deprecated Use {@link PubNubCore#objects.removeMemberships removeMemberships} or - * {@link PubNubCore#objects.removeChannelMembers removeChannelMembers} methods instead from `objects` API group. - */ - removeMemberships(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - var _a, _b, _c; - { - this.logger.warn('PubNub', "'removeMemberships' is deprecated. Use 'pubnub.objects.removeMemberships' or" + - " 'pubnub.objects.removeChannelMembers' instead."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Remove memberships with parameters:`, - })); - if ('spaceId' in parameters) { - const spaceParameters = parameters; - const requestParameters = { - channel: (_a = spaceParameters.spaceId) !== null && _a !== void 0 ? _a : spaceParameters.channel, - uuids: (_b = spaceParameters.userIds) !== null && _b !== void 0 ? _b : spaceParameters.uuids, - limit: 0, - }; - if (callback) - return this.objects.removeChannelMembers(requestParameters, callback); - return this.objects.removeChannelMembers(requestParameters); - } - const userParameters = parameters; - const requestParameters = { - uuid: userParameters.userId, - channels: (_c = userParameters.spaceIds) !== null && _c !== void 0 ? _c : userParameters.channels, - limit: 0, - }; - if (callback) - return this.objects.removeMemberships(requestParameters, callback); - return this.objects.removeMemberships(requestParameters); - } - }); - } - // endregion - // endregion - // -------------------------------------------------------- - // ----------------- Channel Groups API ------------------- - // -------------------------------------------------------- - // region Channel Groups API - /** - * PubNub Channel Groups API group. - */ - get channelGroups() { - return this._channelGroups; - } - // endregion - // -------------------------------------------------------- - // ---------------- Push Notifications API ----------------- - // -------------------------------------------------------- - // region Push Notifications API - /** - * PubNub Push Notifications API group. - */ - get push() { - return this._push; - } - /** - * Share file to a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous file sharing response or `void` in case if `callback` provided. - */ - sendFile(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - if (!this._configuration.PubNubFile) - throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Send file with parameters:`, - })); - const sendFileRequest = new SendFileRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, PubNubFile: this._configuration.PubNubFile, fileUploadPublishRetryLimit: this._configuration.fileUploadPublishRetryLimit, file: parameters.file, sendRequest: this.sendRequest.bind(this), publishFile: this.publishFile.bind(this), crypto: this._configuration.getCryptoModule(), cryptography: this.cryptography ? this.cryptography : undefined })); - const status = { - error: false, - operation: RequestOperation$1.PNPublishFileOperation, - category: StatusCategory$1.PNAcknowledgmentCategory, - statusCode: 0, - }; - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Send file success. File shared with ${response.id} ID.`); - }; - return sendFileRequest - .process() - .then((response) => { - status.statusCode = response.status; - logResponse(response); - if (callback) - return callback(status, response); - return response; - }) - .catch((error) => { - let errorStatus; - if (error instanceof PubNubError) - errorStatus = error.status; - else if (error instanceof PubNubAPIError) - errorStatus = error.toStatus(status.operation); - this.logger.error('PubNub', () => ({ - messageType: 'error', - message: new PubNubError('File sending error. Check status for details', errorStatus), - })); - // Notify callback (if possible). - if (callback && errorStatus) - callback(errorStatus, null); - throw new PubNubError('REST API request processing error. Check status for details', errorStatus); - }); - } - }); - } - /** - * Publish file message to a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous publish file message response or `void` in case if `callback` provided. - */ - publishFile(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - if (!this._configuration.PubNubFile) - throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Publish file message with parameters:`, - })); - const request = new PublishFileMessageRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule() })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Publish file message success. File message published with timetoken: ${response.timetoken}`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - * Retrieve list of shared files in specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous shared files list response or `void` in case if `callback` provided. - */ - listFiles(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `List files with parameters:`, - })); - const request = new FilesListRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `List files success. There are ${response.count} uploaded files.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - // endregion - // region Get Download Url - /** - * Get file download Url. - * - * @param parameters - Request configuration parameters. - * - * @returns File download Url. - */ - getFileUrl(parameters) { - var _a; - { - const request = this.transport.request(new GetFileDownloadUrlRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })).request()); - const query = (_a = request.queryParameters) !== null && _a !== void 0 ? _a : {}; - const queryString = Object.keys(query) - .map((key) => { - const queryValue = query[key]; - if (!Array.isArray(queryValue)) - return `${key}=${encodeString(queryValue)}`; - return queryValue.map((value) => `${key}=${encodeString(value)}`).join('&'); - }) - .join('&'); - return `${request.origin}${request.path}?${queryString}`; - } - } - /** - * Download a shared file from a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous download shared file response or `void` in case if `callback` provided. - */ - downloadFile(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - if (!this._configuration.PubNubFile) - throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform."); - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Download file with parameters:`, - })); - const request = new DownloadFileRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, PubNubFile: this._configuration.PubNubFile, cryptography: this.cryptography ? this.cryptography : undefined, crypto: this._configuration.getCryptoModule() })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Download file success.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return (yield this.sendRequest(request).then((response) => { - logResponse(response); - return response; - })); - } - }); - } - /** - * Delete a shared file from a specific channel. - * - * @param parameters - Request configuration parameters. - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous delete shared file response or `void` in case if `callback` provided. - */ - deleteFile(parameters, callback) { - return __awaiter(this, void 0, void 0, function* () { - { - this.logger.debug('PubNub', () => ({ - messageType: 'object', - message: Object.assign({}, parameters), - details: `Delete file with parameters:`, - })); - const request = new DeleteFileRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Delete file success. Deleted file with ${parameters.id} ID.`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - } - }); - } - /** - Get current high-precision timetoken. - * - * @param [callback] - Request completion handler callback. - * - * @returns Asynchronous get current timetoken response or `void` in case if `callback` provided. - */ - time(callback) { - return __awaiter(this, void 0, void 0, function* () { - this.logger.debug('PubNub', 'Get service time.'); - const request = new TimeRequest(); - const logResponse = (response) => { - if (!response) - return; - this.logger.debug('PubNub', `Get service time success. Current timetoken: ${response.timetoken}`); - }; - if (callback) - return this.sendRequest(request, (status, response) => { - logResponse(response); - callback(status, response); - }); - return this.sendRequest(request).then((response) => { - logResponse(response); - return response; - }); - }); - } - // endregion - // -------------------------------------------------------- - // -------------------- Event emitter --------------------- - // -------------------------------------------------------- - // region Event emitter - /** - * Emit received a status update. - * - * Use global and local event dispatchers to deliver a status object. - * - * @param status - Status object which should be emitted through the listeners. - * - * @internal - */ - emitStatus(status) { - var _a; - (_a = this.eventDispatcher) === null || _a === void 0 ? void 0 : _a.handleStatus(status); - } - /** - * Emit receiver real-time event. - * - * Use global and local event dispatchers to deliver an event object. - * - * @param cursor - Next subscription loop timetoken. - * @param event - Event object which should be emitted through the listeners. - * - * @internal - */ - emitEvent(cursor, event) { - var _a; - { - if (this._globalSubscriptionSet) - this._globalSubscriptionSet.handleEvent(cursor, event); - (_a = this.eventDispatcher) === null || _a === void 0 ? void 0 : _a.handleEvent(event); - Object.values(this.eventHandleCapable).forEach((eventHandleCapable) => { - if (eventHandleCapable !== this._globalSubscriptionSet) - eventHandleCapable.handleEvent(cursor, event); - }); - } - } - /** - * Set a connection status change event handler. - * - * @param listener - Listener function, which will be called each time when the connection status changes. - */ - set onStatus(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onStatus = listener; - } - } - /** - * Set a new message handler. - * - * @param listener - Listener function, which will be called each time when a new message - * is received from the real-time network. - */ - set onMessage(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onMessage = listener; - } - } - /** - * Set a new presence events handler. - * - * @param listener - Listener function, which will be called each time when a new - * presence event is received from the real-time network. - */ - set onPresence(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onPresence = listener; - } - } - /** - * Set a new signal handler. - * - * @param listener - Listener function, which will be called each time when a new signal - * is received from the real-time network. - */ - set onSignal(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onSignal = listener; - } - } - /** - * Set a new app context event handler. - * - * @param listener - Listener function, which will be called each time when a new - * app context event is received from the real-time network. - */ - set onObjects(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onObjects = listener; - } - } - /** - * Set a new message reaction event handler. - * - * @param listener - Listener function, which will be called each time when a - * new message reaction event is received from the real-time network. - */ - set onMessageAction(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onMessageAction = listener; - } - } - /** - * Set a new file handler. - * - * @param listener - Listener function, which will be called each time when a new file - * is received from the real-time network. - */ - set onFile(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onFile = listener; - } - } - /** - * Set a new DataSync event handler. - * - * @param listener - Listener function, which will be called each time when a new - * DataSync event is received from the real-time network. - */ - set onDataSync(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.onDataSync = listener; - } - } - /** - * Set events handler. - * - * @param listener - Events listener configuration object, which lets specify handlers for multiple - * types of events. - */ - addListener(listener) { - { - if (this.eventDispatcher) { - this.eventDispatcher.addListener(listener); - } - } - } - /** - * Remove real-time event listener. - * - * @param listener - Event listener configuration, which should be removed from the list of notified - * listeners. **Important:** Should be the same object which has been passed to the - * {@link addListener}. - */ - removeListener(listener) { - { - if (this.eventDispatcher) - this.eventDispatcher.removeListener(listener); - } - } - /** - * Clear all real-time event listeners. - */ - removeAllListeners() { - { - if (this.eventDispatcher) - this.eventDispatcher.removeAllListeners(); - } - } - // endregion - // -------------------------------------------------------- - // ------------------ Cryptography API -------------------- - // -------------------------------------------------------- - // region Cryptography - // region Common - /** - * Encrypt data. - * - * @param data - Stringified data which should be encrypted using `CryptoModule`. - * @param [customCipherKey] - Cipher key which should be used to encrypt data. **Deprecated:** - * use {@link Configuration#cryptoModule|cryptoModule} instead. - * - * @returns Data encryption result as a string. - * - * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. - */ - encrypt(data, customCipherKey) { - this.logger.warn('PubNub', "'encrypt' is deprecated. Use cryptoModule instead."); - const cryptoModule = this._configuration.getCryptoModule(); - if (!customCipherKey && cryptoModule && typeof data === 'string') { - const encrypted = cryptoModule.encrypt(data); - return typeof encrypted === 'string' ? encrypted : encode(encrypted); - } - if (!this.crypto) - throw new Error('Encryption error: cypher key not set'); - { - return this.crypto.encrypt(data, customCipherKey); - } - } - /** - * Decrypt data. - * - * @param data - Stringified data which should be encrypted using `CryptoModule`. - * @param [customCipherKey] - Cipher key which should be used to decrypt data. **Deprecated:** - * use {@link Configuration#cryptoModule|cryptoModule} instead. - * - * @returns Data decryption result as an object. - * - * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. - */ - decrypt(data, customCipherKey) { - this.logger.warn('PubNub', "'decrypt' is deprecated. Use cryptoModule instead."); - const cryptoModule = this._configuration.getCryptoModule(); - if (!customCipherKey && cryptoModule) { - const decrypted = cryptoModule.decrypt(data); - return decrypted instanceof ArrayBuffer ? JSON.parse(new TextDecoder().decode(decrypted)) : decrypted; - } - if (!this.crypto) - throw new Error('Decryption error: cypher key not set'); - { - return this.crypto.decrypt(data, customCipherKey); - } - } - /** - * Encrypt file content. - * - * @param keyOrFile - Cipher key which should be used to encrypt data or file which should be - * encrypted using `CryptoModule`. - * @param [file] - File which should be encrypted using legacy cryptography. - * - * @returns Asynchronous file encryption result. - * - * @throws Error if a source file isn't provided. - * @throws File constructor not provided. - * @throws Crypto module is missing (if non-legacy flow used). - * - * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. - */ - encryptFile(keyOrFile, file) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - if (typeof keyOrFile !== 'string') - file = keyOrFile; - if (!file) - throw new Error('File encryption error. Source file is missing.'); - if (!this._configuration.PubNubFile) - throw new Error('File encryption error. File constructor not configured.'); - if (typeof keyOrFile !== 'string' && !this._configuration.getCryptoModule()) - throw new Error('File encryption error. Crypto module not configured.'); - if (typeof keyOrFile === 'string') { - if (!this.cryptography) - throw new Error('File encryption error. File encryption not available'); - return this.cryptography.encryptFile(keyOrFile, file, this._configuration.PubNubFile); - } - return (_a = this._configuration.getCryptoModule()) === null || _a === void 0 ? void 0 : _a.encryptFile(file, this._configuration.PubNubFile); - }); - } - /** - * Decrypt file content. - * - * @param keyOrFile - Cipher key which should be used to decrypt data or file which should be - * decrypted using `CryptoModule`. - * @param [file] - File which should be decrypted using legacy cryptography. - * - * @returns Asynchronous file decryption result. - * - * @throws Error if source file isn't provided. - * @throws File constructor not provided. - * @throws Crypto module is missing (if non-legacy flow used). - * - * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. - */ - decryptFile(keyOrFile, file) { - return __awaiter(this, void 0, void 0, function* () { - var _a; - if (typeof keyOrFile !== 'string') - file = keyOrFile; - if (!file) - throw new Error('File encryption error. Source file is missing.'); - if (!this._configuration.PubNubFile) - throw new Error('File decryption error. File constructor' + ' not configured.'); - if (typeof keyOrFile === 'string' && !this._configuration.getCryptoModule()) - throw new Error('File decryption error. Crypto module not configured.'); - if (typeof keyOrFile === 'string') { - if (!this.cryptography) - throw new Error('File decryption error. File decryption not available'); - return this.cryptography.decryptFile(keyOrFile, file, this._configuration.PubNubFile); - } - return (_a = this._configuration.getCryptoModule()) === null || _a === void 0 ? void 0 : _a.decryptFile(file, this._configuration.PubNubFile); - }); - } - } - /** - * {@link ArrayBuffer} to {@link string} decoder. - * - * @internal - */ - PubNubCore.decoder = new TextDecoder(); - // -------------------------------------------------------- - // ----------------------- Static ------------------------- - // -------------------------------------------------------- - // region Static - /** - * Type of REST API endpoint which reported status. - */ - PubNubCore.OPERATIONS = RequestOperation$1; - /** - * API call status category. - */ - PubNubCore.CATEGORIES = StatusCategory$1; - /** - * Enum with API endpoint groups which can be used with retry policy to set up exclusions (which shouldn't be - * retried). - */ - PubNubCore.Endpoint = Endpoint; - /** - * Exponential retry policy constructor. - */ - PubNubCore.ExponentialRetryPolicy = RetryPolicy.ExponentialRetryPolicy; - /** - * Linear retry policy constructor. - */ - PubNubCore.LinearRetryPolicy = RetryPolicy.LinearRetryPolicy; - /** - * Disabled / inactive retry policy. - * - * **Note:** By default `ExponentialRetryPolicy` is set for subscribe requests and this one can be used to disable - * retry policy for all requests (setting `undefined` for retry configuration will set default policy). - */ - PubNubCore.NoneRetryPolicy = RetryPolicy.None; - /** - * Available minimum log levels. - */ - PubNubCore.LogLevel = LogLevel; - - /** - * Cbor decoder module. - * - * @internal - */ - /** - * CBOR data decoder. - * - * @internal - */ - class Cbor { - constructor(decode, base64ToBinary) { - this.decode = decode; - this.base64ToBinary = base64ToBinary; - } - /** - * Decode CBOR base64-encoded object. - * - * @param tokenString - Base64-encoded token. - * - * @returns Token object decoded from CBOR. - */ - decodeToken(tokenString) { - let padding = ''; - if (tokenString.length % 4 === 3) - padding = '='; - else if (tokenString.length % 4 === 2) - padding = '=='; - const cleaned = tokenString.replace(/-/gi, '+').replace(/_/gi, '/') + padding; - const result = this.decode(this.base64ToBinary(cleaned)); - return typeof result === 'object' ? result : undefined; - } - } - - /* eslint no-bitwise: ["error", { "allow": ["~", "&", ">>"] }] */ - /* global navigator */ - /** - * PubNub client for browser platform. - */ - class PubNub extends PubNubCore { - /** - * Create and configure the PubNub client core. - * - * @param configuration - User-provided PubNub client configuration. - * - * @returns Configured and ready to use PubNub client. - */ - constructor(configuration) { - var _a; - const sharedWorkerRequested = configuration.subscriptionWorkerUrl !== undefined; - const configurationCopy = setDefaults(configuration); - const platformConfiguration = Object.assign(Object.assign({}, configurationCopy), { sdkFamily: 'Web' }); - platformConfiguration.PubNubFile = PubNubFile; - // Prepare full client configuration. - const clientConfiguration = makeConfiguration(platformConfiguration, (cryptoConfiguration) => { - if (!cryptoConfiguration.cipherKey) - return undefined; - { - const cryptoModule = new WebCryptoModule({ - default: new LegacyCryptor(Object.assign(Object.assign({}, cryptoConfiguration), (!cryptoConfiguration.logger ? { logger: clientConfiguration.logger() } : {}))), - cryptors: [new AesCbcCryptor({ cipherKey: cryptoConfiguration.cipherKey })], - }); - return cryptoModule; - } - }); - if (configuration.subscriptionWorkerLogVerbosity) - configuration.subscriptionWorkerLogLevel = LogLevel.Debug; - else if (configuration.subscriptionWorkerLogLevel === undefined) - configuration.subscriptionWorkerLogLevel = LogLevel.None; - if (configuration.subscriptionWorkerLogVerbosity !== undefined) { - clientConfiguration - .logger() - .warn('Configuration', "'subscriptionWorkerLogVerbosity' is deprecated. Use 'subscriptionWorkerLogLevel' instead."); - } - { - // Ensure that the logger has been passed to the user-provided crypto module. - if (clientConfiguration.getCryptoModule()) - clientConfiguration.getCryptoModule().logger = clientConfiguration.logger(); - } - // Prepare Token manager. - let tokenManager; - { - tokenManager = new TokenManager(new Cbor((arrayBuffer) => stringifyBufferKeys(CborReader.decode(arrayBuffer)), decode)); - } - // Legacy crypto (legacy data encryption / decryption and request signature support). - let crypto; - { - if (clientConfiguration.getCipherKey() || clientConfiguration.secretKey) { - crypto = new Crypto({ - secretKey: clientConfiguration.secretKey, - cipherKey: clientConfiguration.getCipherKey(), - useRandomIVs: clientConfiguration.getUseRandomIVs(), - customEncrypt: clientConfiguration.getCustomEncrypt(), - customDecrypt: clientConfiguration.getCustomDecrypt(), - logger: clientConfiguration.logger(), - }); - } - } - // Settings change handlers - let heartbeatIntervalChangeHandler = () => { }; - let presenceStateChangeHandler = () => { }; - let authenticationChangeHandler = () => { }; - let userIdChangeHandler = () => { }; - let cryptography; - cryptography = new WebCryptography(); - // Setup transport provider. - let transport = new WebTransport(clientConfiguration.logger(), platformConfiguration.transport); - { - if (configurationCopy.subscriptionWorkerUrl) { - try { - // Inject subscription worker into the transport provider stack. - const middleware = new SubscriptionWorkerMiddleware({ - clientIdentifier: clientConfiguration._instanceId, - subscriptionKey: clientConfiguration.subscribeKey, - userId: clientConfiguration.getUserId(), - workerUrl: configurationCopy.subscriptionWorkerUrl, - sdkVersion: clientConfiguration.getVersion(), - heartbeatInterval: clientConfiguration.getHeartbeatInterval(), - announceSuccessfulHeartbeats: clientConfiguration.announceSuccessfulHeartbeats, - announceFailedHeartbeats: clientConfiguration.announceFailedHeartbeats, - workerOfflineClientsCheckInterval: platformConfiguration.subscriptionWorkerOfflineClientsCheckInterval, - workerUnsubscribeOfflineClients: platformConfiguration.subscriptionWorkerUnsubscribeOfflineClients, - workerLogLevel: platformConfiguration.subscriptionWorkerLogLevel, - tokenManager, - transport, - logger: clientConfiguration.logger(), - }); - presenceStateChangeHandler = (state) => middleware.onPresenceStateChange(state); - heartbeatIntervalChangeHandler = (interval) => middleware.onHeartbeatIntervalChange(interval); - authenticationChangeHandler = (auth) => middleware.onTokenChange(auth); - userIdChangeHandler = (userId) => middleware.onUserIdChange(userId); - transport = middleware; - if (configurationCopy.subscriptionWorkerUnsubscribeOfflineClients && - typeof window !== 'undefined' && - window.addEventListener) { - window.addEventListener('pagehide', (event) => { - if (!event.persisted) - middleware.terminate(); - }, { once: true }); - } - } - catch (e) { - clientConfiguration.logger().error('PubNub', () => ({ - messageType: 'error', - message: e, - })); - } - } - else if (sharedWorkerRequested) { - clientConfiguration - .logger() - .warn('PubNub', 'SharedWorker not supported in this browser. Fallback to the original transport.'); - } - } - const transportMiddleware = new PubNubMiddleware({ - clientConfiguration, - tokenManager, - transport, - }); - super({ - configuration: clientConfiguration, - transport: transportMiddleware, - cryptography, - tokenManager, - crypto, - }); - /** - * PubNub File constructor. - */ - this.File = PubNubFile; - this.onHeartbeatIntervalChange = heartbeatIntervalChangeHandler; - this.onAuthenticationChange = authenticationChangeHandler; - this.onPresenceStateChange = presenceStateChangeHandler; - this.onUserIdChange = userIdChangeHandler; - { - if (transport instanceof SubscriptionWorkerMiddleware) { - transport.emitStatus = this.emitStatus.bind(this); - const disconnect = this.disconnect.bind(this); - this.disconnect = (isOffline) => { - transport.disconnect(); - disconnect(); - }; - } - } - // `window` is unavailable in DOM-less contexts (e.g. MV3 service workers); only attach network - // listeners when a `window` with event support actually exists. - if (((_a = configuration.listenToBrowserNetworkEvents) !== null && _a !== void 0 ? _a : true) && - typeof window !== 'undefined' && - window.addEventListener) { - window.addEventListener('offline', () => { - this.networkDownDetected(); - }); - window.addEventListener('online', () => { - this.networkUpDetected(); - }); - } - } - networkDownDetected() { - this.logger.debug('PubNub', 'Network down detected'); - this.emitStatus({ category: PubNub.CATEGORIES.PNNetworkDownCategory }); - if (this._configuration.restore) - this.disconnect(true); - else - this.destroy(true); - } - networkUpDetected() { - this.logger.debug('PubNub', 'Network up detected'); - this.emitStatus({ category: PubNub.CATEGORIES.PNNetworkUpCategory }); - this.reconnect(); - } - } - /** - * Data encryption / decryption module constructor. - */ - PubNub.CryptoModule = WebCryptoModule ; - - return PubNub; - -})); + }; + + /** + * Crypto module. + */ + class AbstractCryptoModule { + // -------------------------------------------------------- + // --------------- Convenience functions ------------------ + // -------------------------------------------------------- + // region Convenience functions + /** + * Construct crypto module with legacy cryptor for encryption and both legacy and AES-CBC + * cryptors for decryption. + * + * @param config Cryptors configuration options. + * + * @returns Crypto module which encrypts data using legacy cryptor. + * + * @throws Error if `config.cipherKey` not set. + * + * @deprecated Use {@link aesCbcCryptoModule} for new applications. + */ + static legacyCryptoModule(config) { + throw new Error('Should be implemented by concrete crypto module implementation.'); + } + /** + * Construct crypto module with AES-CBC cryptor for encryption and both AES-CBC and legacy + * cryptors for decryption. + * + * @param config Cryptors configuration options. + * + * @returns Crypto module which encrypts data using AES-CBC cryptor. + * + * @throws Error if `config.cipherKey` not set. + */ + static aesCbcCryptoModule(config) { + throw new Error('Should be implemented by concrete crypto module implementation.'); + } + // endregion + constructor(configuration) { + var _a; + this.defaultCryptor = configuration.default; + this.cryptors = (_a = configuration.cryptors) !== null && _a !== void 0 ? _a : []; + } + /** + * Assign registered loggers' manager. + * + * @param _logger - Registered loggers' manager. + * + * @internal + */ + set logger(_logger) { + throw new Error('Method not implemented.'); + } + // endregion + // -------------------------------------------------------- + // ----------------------- Helpers ------------------------ + // -------------------------------------------------------- + // region Helpers + /** + * Retrieve list of module's cryptors. + * + * @internal + */ + getAllCryptors() { + return [this.defaultCryptor, ...this.cryptors]; + } + // endregion + /** + * Serialize crypto module information to string. + * + * @returns Serialized crypto module information. + */ + toString() { + return `AbstractCryptoModule { default: ${this.defaultCryptor.toString()}, cryptors: [${this.cryptors.map((c) => c.toString()).join(', ')}]}`; + } + } + /** + * `String` to {@link ArrayBuffer} response decoder. + * + * @internal + */ + AbstractCryptoModule.encoder = new TextEncoder(); + /** + * {@link ArrayBuffer} to {@link string} decoder. + * + * @internal + */ + AbstractCryptoModule.decoder = new TextDecoder(); + + /* global File, FileReader */ + /** + * Browser {@link PubNub} File object module. + */ + // endregion + /** + * Web implementation for {@link PubNub} File object. + * + * **Important:** Class should implement constructor and class fields from {@link PubNubFileConstructor}. + */ + class PubNubFile { + // endregion + static create(file) { + return new PubNubFile(file); + } + constructor(file) { + let contentLength; + let fileMimeType; + let fileName; + let fileData; + if (file instanceof File) { + fileData = file; + fileName = file.name; + fileMimeType = file.type; + contentLength = file.size; + } + else if ('data' in file) { + const contents = file.data; + fileMimeType = file.mimeType; + fileName = file.name; + fileData = new File([contents], fileName, { type: fileMimeType }); + contentLength = fileData.size; + } + if (fileData === undefined) + throw new Error("Couldn't construct a file out of supplied options."); + if (fileName === undefined) + throw new Error("Couldn't guess filename out of the options. Please provide one."); + if (contentLength) + this.contentLength = contentLength; + this.mimeType = fileMimeType; + this.data = fileData; + this.name = fileName; + } + /** + * Convert {@link PubNub} File object content to {@link Buffer}. + * + * @throws Error because {@link Buffer} not available in browser environment. + */ + toBuffer() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('This feature is only supported in Node.js environments.'); + }); + } + /** + * Convert {@link PubNub} File object content to {@link ArrayBuffer}. + * + * @returns Asynchronous results of conversion to the {@link ArrayBuffer}. + */ + toArrayBuffer() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.addEventListener('load', () => { + if (reader.result instanceof ArrayBuffer) + return resolve(reader.result); + }); + reader.addEventListener('error', () => reject(reader.error)); + reader.readAsArrayBuffer(this.data); + }); + }); + } + /** + * Convert {@link PubNub} File object content to {@link string}. + * + * @returns Asynchronous results of conversion to the {@link string}. + */ + toString() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.addEventListener('load', () => { + if (typeof reader.result === 'string') { + return resolve(reader.result); + } + }); + reader.addEventListener('error', () => { + reject(reader.error); + }); + reader.readAsBinaryString(this.data); + }); + }); + } + /** + * Convert {@link PubNub} File object content to {@link Readable} stream. + * + * @throws Error because {@link Readable} stream not available in browser environment. + */ + toStream() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('This feature is only supported in Node.js environments.'); + }); + } + /** + * Convert {@link PubNub} File object content to {@link File}. + * + * @returns Asynchronous results of conversion to the {@link File}. + */ + toFile() { + return __awaiter(this, void 0, void 0, function* () { + return this.data; + }); + } + /** + * Convert {@link PubNub} File object content to file `Uri`. + * + * @throws Error because file `Uri` not available in browser environment. + */ + toFileUri() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('This feature is only supported in React Native environments.'); + }); + } + /** + * Convert {@link PubNub} File object content to {@link Blob}. + * + * @returns Asynchronous results of conversion to the {@link Blob}. + */ + toBlob() { + return __awaiter(this, void 0, void 0, function* () { + return this.data; + }); + } + } + // region Class properties + /** + * Whether {@link Blob} data supported by platform or not. + */ + PubNubFile.supportsBlob = typeof Blob !== 'undefined'; + /** + * Whether {@link File} data supported by platform or not. + */ + PubNubFile.supportsFile = typeof File !== 'undefined'; + /** + * Whether {@link Buffer} data supported by platform or not. + */ + PubNubFile.supportsBuffer = false; + /** + * Whether {@link Stream} data supported by platform or not. + */ + PubNubFile.supportsStream = false; + /** + * Whether {@link String} data supported by platform or not. + */ + PubNubFile.supportsString = true; + /** + * Whether {@link ArrayBuffer} supported by platform or not. + */ + PubNubFile.supportsArrayBuffer = true; + /** + * Whether {@link PubNub} File object encryption supported or not. + */ + PubNubFile.supportsEncryptFile = true; + /** + * Whether `File Uri` data supported by platform or not. + */ + PubNubFile.supportsFileUri = false; + + /** + * Base64 support module. + * + * @internal + */ + const BASE64_CHARMAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + /** + * Decode a Base64 encoded string. + * + * @param paddedInput Base64 string with padding + * @returns ArrayBuffer with decoded data + * + * @internal + */ + function decode(paddedInput) { + // Remove up to last two equal signs. + const input = paddedInput.replace(/==?$/, ''); + const outputLength = Math.floor((input.length / 4) * 3); + // Prepare output buffer. + const data = new ArrayBuffer(outputLength); + const view = new Uint8Array(data); + let cursor = 0; + /** + * Returns the next integer representation of a sixtet of bytes from the input + * @returns sixtet of bytes + */ + function nextSixtet() { + const char = input.charAt(cursor++); + const index = BASE64_CHARMAP.indexOf(char); + if (index === -1) { + throw new Error(`Illegal character at ${cursor}: ${input.charAt(cursor - 1)}`); + } + return index; + } + for (let i = 0; i < outputLength; i += 3) { + // Obtain four sixtets + const sx1 = nextSixtet(); + const sx2 = nextSixtet(); + const sx3 = nextSixtet(); + const sx4 = nextSixtet(); + // Encode them as three octets + const oc1 = ((sx1 & 0b00111111) << 2) | (sx2 >> 4); + const oc2 = ((sx2 & 0b00001111) << 4) | (sx3 >> 2); + const oc3 = ((sx3 & 0b00000011) << 6) | (sx4 >> 0); + view[i] = oc1; + // Skip padding bytes. + if (sx3 != 64) + view[i + 1] = oc2; + if (sx4 != 64) + view[i + 2] = oc3; + } + return data; + } + /** + * Encode `ArrayBuffer` as a Base64 encoded string. + * + * @param input ArrayBuffer with source data. + * @returns Base64 string with padding. + * + * @internal + */ + function encode(input) { + let base64 = ''; + const encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + const bytes = new Uint8Array(input); + const byteLength = bytes.byteLength; + const byteRemainder = byteLength % 3; + const mainLength = byteLength - byteRemainder; + let a, b, c, d; + let chunk; + // Main loop deals with bytes in chunks of 3 + for (let i = 0; i < mainLength; i = i + 3) { + // Combine the three bytes into a single integer + chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; + // Use bitmasks to extract 6-bit segments from the triplet + a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18 + b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12 + c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6 + d = chunk & 63; // 63 = 2^6 - 1 + // Convert the raw binary segments to the appropriate ASCII encoding + base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]; + } + // Deal with the remaining bytes and padding + if (byteRemainder == 1) { + chunk = bytes[mainLength]; + a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2 + // Set the 4 least significant bits to zero + b = (chunk & 3) << 4; // 3 = 2^2 - 1 + base64 += encodings[a] + encodings[b] + '=='; + } + else if (byteRemainder == 2) { + chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]; + a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10 + b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4 + // Set the 2 least significant bits to zero + c = (chunk & 15) << 2; // 15 = 2^4 - 1 + base64 += encodings[a] + encodings[b] + encodings[c] + '='; + } + return base64; + } + + /** + * Request processing status categories. + */ + var StatusCategory; + (function (StatusCategory) { + /** + * Call failed when network was unable to complete the call. + */ + StatusCategory["PNNetworkIssuesCategory"] = "PNNetworkIssuesCategory"; + /** + * Network call timed out. + */ + StatusCategory["PNTimeoutCategory"] = "PNTimeoutCategory"; + /** + * Request has been cancelled. + */ + StatusCategory["PNCancelledCategory"] = "PNCancelledCategory"; + /** + * Server responded with bad response. + */ + StatusCategory["PNBadRequestCategory"] = "PNBadRequestCategory"; + /** + * Server responded with access denied. + */ + StatusCategory["PNAccessDeniedCategory"] = "PNAccessDeniedCategory"; + /** + * Incomplete parameters provided for used endpoint. + */ + StatusCategory["PNValidationErrorCategory"] = "PNValidationErrorCategory"; + /** + * PubNub request acknowledgment status. + * + * Some API endpoints respond with request processing status w/o useful data. + */ + StatusCategory["PNAcknowledgmentCategory"] = "PNAcknowledgmentCategory"; + /** + * PubNub service or intermediate "actor" returned unexpected response. + * + * There can be few sources of unexpected return with success code: + * - proxy server / VPN; + * - Wi-Fi hotspot authorization page. + */ + StatusCategory["PNMalformedResponseCategory"] = "PNMalformedResponseCategory"; + /** + * Server can't process request. + * + * There can be few sources of unexpected return with success code: + * - potentially an ongoing incident; + * - proxy server / VPN. + */ + StatusCategory["PNServerErrorCategory"] = "PNServerErrorCategory"; + /** + * Something strange happened; please check the logs. + */ + StatusCategory["PNUnknownCategory"] = "PNUnknownCategory"; + // -------------------------------------------------------- + // --------------------- Network status ------------------- + // -------------------------------------------------------- + /** + * SDK will announce when the network appears to be connected again. + */ + StatusCategory["PNNetworkUpCategory"] = "PNNetworkUpCategory"; + /** + * SDK will announce when the network appears to down. + */ + StatusCategory["PNNetworkDownCategory"] = "PNNetworkDownCategory"; + // -------------------------------------------------------- + // -------------------- Real-time events ------------------ + // -------------------------------------------------------- + /** + * PubNub client reconnected to the real-time updates stream. + */ + StatusCategory["PNReconnectedCategory"] = "PNReconnectedCategory"; + /** + * PubNub client connected to the real-time updates stream. + */ + StatusCategory["PNConnectedCategory"] = "PNConnectedCategory"; + /** + * Set of active channels and groups has been changed. + */ + StatusCategory["PNSubscriptionChangedCategory"] = "PNSubscriptionChangedCategory"; + /** + * Received real-time updates exceed specified threshold. + * + * After temporary disconnection and catchup, this category means that potentially some + * real-time updates have been pushed into `storage` and need to be requested separately. + */ + StatusCategory["PNRequestMessageCountExceededCategory"] = "PNRequestMessageCountExceededCategory"; + /** + * PubNub client disconnected from the real-time updates streams. + */ + StatusCategory["PNDisconnectedCategory"] = "PNDisconnectedCategory"; + /** + * PubNub client wasn't able to connect to the real-time updates streams. + */ + StatusCategory["PNConnectionErrorCategory"] = "PNConnectionErrorCategory"; + /** + * PubNub client unexpectedly disconnected from the real-time updates streams. + */ + StatusCategory["PNDisconnectedUnexpectedlyCategory"] = "PNDisconnectedUnexpectedlyCategory"; + // -------------------------------------------------------- + // ------------------ Shared worker events ---------------- + // -------------------------------------------------------- + /** + * SDK will announce when newer shared worker will be 'noticed'. + */ + StatusCategory["PNSharedWorkerUpdatedCategory"] = "PNSharedWorkerUpdatedCategory"; + })(StatusCategory || (StatusCategory = {})); + var StatusCategory$1 = StatusCategory; + + /** + * PubNub operation error module. + */ + /** + * PubNub operation error. + * + * When an operation can't be performed or there is an error from the server, this object will be returned. + */ + class PubNubError extends Error { + /** + * Create PubNub operation error. + * + * @param message - Message with details about why operation failed. + * @param [status] - Additional information about performed operation. + * + * @returns Configured and ready to use PubNub operation error. + * + * @internal + */ + constructor(message, status) { + super(message); + this.status = status; + this.name = 'PubNubError'; + this.message = message; + Object.setPrototypeOf(this, new.target.prototype); + } + } + /** + * Create error status object. + * + * @param errorPayload - Additional information which should be attached to the error status object. + * @param category - Occurred error category. + * + * @returns Error status object. + * + * @internal + */ + function createError(errorPayload, category) { + var _a; + (_a = errorPayload.statusCode) !== null && _a !== void 0 ? _a : (errorPayload.statusCode = 0); + return Object.assign(Object.assign({}, errorPayload), { statusCode: errorPayload.statusCode, category, error: true }); + } + /** + * Create operation arguments validation error status object. + * + * @param message - Information about failed validation requirement. + * @param [statusCode] - Operation HTTP status code. + * + * @returns Operation validation error status object. + * + * @internal + */ + function createValidationError(message, statusCode) { + return createError(Object.assign({ message }, ({})), StatusCategory$1.PNValidationErrorCategory); + } + /** + * Create malformed service response error status object. + * + * @param [responseText] - Stringified original service response. + * @param [statusCode] - Operation HTTP status code. + */ + function createMalformedResponseError(responseText, statusCode) { + return createError(Object.assign(Object.assign({ message: 'Unable to deserialize service response' }, (responseText !== undefined ? { responseText } : {})), (statusCode !== undefined ? { statusCode } : {})), StatusCategory$1.PNMalformedResponseCategory); + } + + /** + * CryptoJS implementation. + * + * @internal + */ + + /*eslint-disable */ + + /* + CryptoJS v3.1.2 + code.google.com/p/crypto-js + (c) 2009-2013 by Jeff Mott. All rights reserved. + code.google.com/p/crypto-js/wiki/License + */ + var CryptoJS = + CryptoJS || + (function (h, s) { + var f = {}, + g = (f.lib = {}), + q = function () {}, + m = (g.Base = { + extend: function (a) { + q.prototype = this; + var c = new q(); + a && c.mixIn(a); + c.hasOwnProperty('init') || + (c.init = function () { + c.$super.init.apply(this, arguments); + }); + c.init.prototype = c; + c.$super = this; + return c; + }, + create: function () { + var a = this.extend(); + a.init.apply(a, arguments); + return a; + }, + init: function () {}, + mixIn: function (a) { + for (var c in a) a.hasOwnProperty(c) && (this[c] = a[c]); + a.hasOwnProperty('toString') && (this.toString = a.toString); + }, + clone: function () { + return this.init.prototype.extend(this); + }, + }), + r = (g.WordArray = m.extend({ + init: function (a, c) { + a = this.words = a || []; + this.sigBytes = c != s ? c : 4 * a.length; + }, + toString: function (a) { + return (a || k).stringify(this); + }, + concat: function (a) { + var c = this.words, + d = a.words, + b = this.sigBytes; + a = a.sigBytes; + this.clamp(); + if (b % 4) + for (var e = 0; e < a; e++) + c[(b + e) >>> 2] |= ((d[e >>> 2] >>> (24 - 8 * (e % 4))) & 255) << (24 - 8 * ((b + e) % 4)); + else if (65535 < d.length) for (e = 0; e < a; e += 4) c[(b + e) >>> 2] = d[e >>> 2]; + else c.push.apply(c, d); + this.sigBytes += a; + return this; + }, + clamp: function () { + var a = this.words, + c = this.sigBytes; + a[c >>> 2] &= 4294967295 << (32 - 8 * (c % 4)); + a.length = h.ceil(c / 4); + }, + clone: function () { + var a = m.clone.call(this); + a.words = this.words.slice(0); + return a; + }, + random: function (a) { + for (var c = [], d = 0; d < a; d += 4) c.push((4294967296 * h.random()) | 0); + return new r.init(c, a); + }, + })), + l = (f.enc = {}), + k = (l.Hex = { + stringify: function (a) { + var c = a.words; + a = a.sigBytes; + for (var d = [], b = 0; b < a; b++) { + var e = (c[b >>> 2] >>> (24 - 8 * (b % 4))) & 255; + d.push((e >>> 4).toString(16)); + d.push((e & 15).toString(16)); + } + return d.join(''); + }, + parse: function (a) { + for (var c = a.length, d = [], b = 0; b < c; b += 2) + d[b >>> 3] |= parseInt(a.substr(b, 2), 16) << (24 - 4 * (b % 8)); + return new r.init(d, c / 2); + }, + }), + n = (l.Latin1 = { + stringify: function (a) { + var c = a.words; + a = a.sigBytes; + for (var d = [], b = 0; b < a; b++) d.push(String.fromCharCode((c[b >>> 2] >>> (24 - 8 * (b % 4))) & 255)); + return d.join(''); + }, + parse: function (a) { + for (var c = a.length, d = [], b = 0; b < c; b++) d[b >>> 2] |= (a.charCodeAt(b) & 255) << (24 - 8 * (b % 4)); + return new r.init(d, c); + }, + }), + j = (l.Utf8 = { + stringify: function (a) { + try { + return decodeURIComponent(escape(n.stringify(a))); + } catch (c) { + throw Error('Malformed UTF-8 data'); + } + }, + parse: function (a) { + return n.parse(unescape(encodeURIComponent(a))); + }, + }), + u = (g.BufferedBlockAlgorithm = m.extend({ + reset: function () { + this._data = new r.init(); + this._nDataBytes = 0; + }, + _append: function (a) { + 'string' == typeof a && (a = j.parse(a)); + this._data.concat(a); + this._nDataBytes += a.sigBytes; + }, + _process: function (a) { + var c = this._data, + d = c.words, + b = c.sigBytes, + e = this.blockSize, + f = b / (4 * e), + f = a ? h.ceil(f) : h.max((f | 0) - this._minBufferSize, 0); + a = f * e; + b = h.min(4 * a, b); + if (a) { + for (var g = 0; g < a; g += e) this._doProcessBlock(d, g); + g = d.splice(0, a); + c.sigBytes -= b; + } + return new r.init(g, b); + }, + clone: function () { + var a = m.clone.call(this); + a._data = this._data.clone(); + return a; + }, + _minBufferSize: 0, + })); + g.Hasher = u.extend({ + cfg: m.extend(), + init: function (a) { + this.cfg = this.cfg.extend(a); + this.reset(); + }, + reset: function () { + u.reset.call(this); + this._doReset(); + }, + update: function (a) { + this._append(a); + this._process(); + return this; + }, + finalize: function (a) { + a && this._append(a); + return this._doFinalize(); + }, + blockSize: 16, + _createHelper: function (a) { + return function (c, d) { + return new a.init(d).finalize(c); + }; + }, + _createHmacHelper: function (a) { + return function (c, d) { + return new t.HMAC.init(a, d).finalize(c); + }; + }, + }); + var t = (f.algo = {}); + return f; + })(Math); + + // SHA256 + (function (h) { + for ( + var s = CryptoJS, + f = s.lib, + g = f.WordArray, + q = f.Hasher, + f = s.algo, + m = [], + r = [], + l = function (a) { + return (4294967296 * (a - (a | 0))) | 0; + }, + k = 2, + n = 0; + 64 > n; + + ) { + var j; + a: { + j = k; + for (var u = h.sqrt(j), t = 2; t <= u; t++) + if (!(j % t)) { + j = !1; + break a; + } + j = !0; + } + j && (8 > n && (m[n] = l(h.pow(k, 0.5))), (r[n] = l(h.pow(k, 1 / 3))), n++); + k++; + } + var a = [], + f = (f.SHA256 = q.extend({ + _doReset: function () { + this._hash = new g.init(m.slice(0)); + }, + _doProcessBlock: function (c, d) { + for ( + var b = this._hash.words, + e = b[0], + f = b[1], + g = b[2], + j = b[3], + h = b[4], + m = b[5], + n = b[6], + q = b[7], + p = 0; + 64 > p; + p++ + ) { + if (16 > p) a[p] = c[d + p] | 0; + else { + var k = a[p - 15], + l = a[p - 2]; + a[p] = + (((k << 25) | (k >>> 7)) ^ ((k << 14) | (k >>> 18)) ^ (k >>> 3)) + + a[p - 7] + + (((l << 15) | (l >>> 17)) ^ ((l << 13) | (l >>> 19)) ^ (l >>> 10)) + + a[p - 16]; + } + k = + q + + (((h << 26) | (h >>> 6)) ^ ((h << 21) | (h >>> 11)) ^ ((h << 7) | (h >>> 25))) + + ((h & m) ^ (~h & n)) + + r[p] + + a[p]; + l = + (((e << 30) | (e >>> 2)) ^ ((e << 19) | (e >>> 13)) ^ ((e << 10) | (e >>> 22))) + + ((e & f) ^ (e & g) ^ (f & g)); + q = n; + n = m; + m = h; + h = (j + k) | 0; + j = g; + g = f; + f = e; + e = (k + l) | 0; + } + b[0] = (b[0] + e) | 0; + b[1] = (b[1] + f) | 0; + b[2] = (b[2] + g) | 0; + b[3] = (b[3] + j) | 0; + b[4] = (b[4] + h) | 0; + b[5] = (b[5] + m) | 0; + b[6] = (b[6] + n) | 0; + b[7] = (b[7] + q) | 0; + }, + _doFinalize: function () { + var a = this._data, + d = a.words, + b = 8 * this._nDataBytes, + e = 8 * a.sigBytes; + d[e >>> 5] |= 128 << (24 - (e % 32)); + d[(((e + 64) >>> 9) << 4) + 14] = h.floor(b / 4294967296); + d[(((e + 64) >>> 9) << 4) + 15] = b; + a.sigBytes = 4 * d.length; + this._process(); + return this._hash; + }, + clone: function () { + var a = q.clone.call(this); + a._hash = this._hash.clone(); + return a; + }, + })); + s.SHA256 = q._createHelper(f); + s.HmacSHA256 = q._createHmacHelper(f); + })(Math); + + // HMAC SHA256 + (function () { + var h = CryptoJS, + s = h.enc.Utf8; + h.algo.HMAC = h.lib.Base.extend({ + init: function (f, g) { + f = this._hasher = new f.init(); + 'string' == typeof g && (g = s.parse(g)); + var h = f.blockSize, + m = 4 * h; + g.sigBytes > m && (g = f.finalize(g)); + g.clamp(); + for (var r = (this._oKey = g.clone()), l = (this._iKey = g.clone()), k = r.words, n = l.words, j = 0; j < h; j++) + (k[j] ^= 1549556828), (n[j] ^= 909522486); + r.sigBytes = l.sigBytes = m; + this.reset(); + }, + reset: function () { + var f = this._hasher; + f.reset(); + f.update(this._iKey); + }, + update: function (f) { + this._hasher.update(f); + return this; + }, + finalize: function (f) { + var g = this._hasher; + f = g.finalize(f); + g.reset(); + return g.finalize(this._oKey.clone().concat(f)); + }, + }); + })(); + + // Base64 + (function () { + var u = CryptoJS, + p = u.lib.WordArray; + u.enc.Base64 = { + stringify: function (d) { + var l = d.words, + p = d.sigBytes, + t = this._map; + d.clamp(); + d = []; + for (var r = 0; r < p; r += 3) + for ( + var w = + (((l[r >>> 2] >>> (24 - 8 * (r % 4))) & 255) << 16) | + (((l[(r + 1) >>> 2] >>> (24 - 8 * ((r + 1) % 4))) & 255) << 8) | + ((l[(r + 2) >>> 2] >>> (24 - 8 * ((r + 2) % 4))) & 255), + v = 0; + 4 > v && r + 0.75 * v < p; + v++ + ) + d.push(t.charAt((w >>> (6 * (3 - v))) & 63)); + if ((l = t.charAt(64))) for (; d.length % 4; ) d.push(l); + return d.join(''); + }, + parse: function (d) { + var l = d.length, + s = this._map, + t = s.charAt(64); + t && ((t = d.indexOf(t)), -1 != t && (l = t)); + for (var t = [], r = 0, w = 0; w < l; w++) + if (w % 4) { + var v = s.indexOf(d.charAt(w - 1)) << (2 * (w % 4)), + b = s.indexOf(d.charAt(w)) >>> (6 - 2 * (w % 4)); + t[r >>> 2] |= (v | b) << (24 - 8 * (r % 4)); + r++; + } + return p.create(t, r); + }, + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', + }; + })(); + + // BlockCipher + (function (u) { + function p(b, n, a, c, e, j, k) { + b = b + ((n & a) | (~n & c)) + e + k; + return ((b << j) | (b >>> (32 - j))) + n; + } + function d(b, n, a, c, e, j, k) { + b = b + ((n & c) | (a & ~c)) + e + k; + return ((b << j) | (b >>> (32 - j))) + n; + } + function l(b, n, a, c, e, j, k) { + b = b + (n ^ a ^ c) + e + k; + return ((b << j) | (b >>> (32 - j))) + n; + } + function s(b, n, a, c, e, j, k) { + b = b + (a ^ (n | ~c)) + e + k; + return ((b << j) | (b >>> (32 - j))) + n; + } + for (var t = CryptoJS, r = t.lib, w = r.WordArray, v = r.Hasher, r = t.algo, b = [], x = 0; 64 > x; x++) + b[x] = (4294967296 * u.abs(u.sin(x + 1))) | 0; + r = r.MD5 = v.extend({ + _doReset: function () { + this._hash = new w.init([1732584193, 4023233417, 2562383102, 271733878]); + }, + _doProcessBlock: function (q, n) { + for (var a = 0; 16 > a; a++) { + var c = n + a, + e = q[c]; + q[c] = (((e << 8) | (e >>> 24)) & 16711935) | (((e << 24) | (e >>> 8)) & 4278255360); + } + var a = this._hash.words, + c = q[n + 0], + e = q[n + 1], + j = q[n + 2], + k = q[n + 3], + z = q[n + 4], + r = q[n + 5], + t = q[n + 6], + w = q[n + 7], + v = q[n + 8], + A = q[n + 9], + B = q[n + 10], + C = q[n + 11], + u = q[n + 12], + D = q[n + 13], + E = q[n + 14], + x = q[n + 15], + f = a[0], + m = a[1], + g = a[2], + h = a[3], + f = p(f, m, g, h, c, 7, b[0]), + h = p(h, f, m, g, e, 12, b[1]), + g = p(g, h, f, m, j, 17, b[2]), + m = p(m, g, h, f, k, 22, b[3]), + f = p(f, m, g, h, z, 7, b[4]), + h = p(h, f, m, g, r, 12, b[5]), + g = p(g, h, f, m, t, 17, b[6]), + m = p(m, g, h, f, w, 22, b[7]), + f = p(f, m, g, h, v, 7, b[8]), + h = p(h, f, m, g, A, 12, b[9]), + g = p(g, h, f, m, B, 17, b[10]), + m = p(m, g, h, f, C, 22, b[11]), + f = p(f, m, g, h, u, 7, b[12]), + h = p(h, f, m, g, D, 12, b[13]), + g = p(g, h, f, m, E, 17, b[14]), + m = p(m, g, h, f, x, 22, b[15]), + f = d(f, m, g, h, e, 5, b[16]), + h = d(h, f, m, g, t, 9, b[17]), + g = d(g, h, f, m, C, 14, b[18]), + m = d(m, g, h, f, c, 20, b[19]), + f = d(f, m, g, h, r, 5, b[20]), + h = d(h, f, m, g, B, 9, b[21]), + g = d(g, h, f, m, x, 14, b[22]), + m = d(m, g, h, f, z, 20, b[23]), + f = d(f, m, g, h, A, 5, b[24]), + h = d(h, f, m, g, E, 9, b[25]), + g = d(g, h, f, m, k, 14, b[26]), + m = d(m, g, h, f, v, 20, b[27]), + f = d(f, m, g, h, D, 5, b[28]), + h = d(h, f, m, g, j, 9, b[29]), + g = d(g, h, f, m, w, 14, b[30]), + m = d(m, g, h, f, u, 20, b[31]), + f = l(f, m, g, h, r, 4, b[32]), + h = l(h, f, m, g, v, 11, b[33]), + g = l(g, h, f, m, C, 16, b[34]), + m = l(m, g, h, f, E, 23, b[35]), + f = l(f, m, g, h, e, 4, b[36]), + h = l(h, f, m, g, z, 11, b[37]), + g = l(g, h, f, m, w, 16, b[38]), + m = l(m, g, h, f, B, 23, b[39]), + f = l(f, m, g, h, D, 4, b[40]), + h = l(h, f, m, g, c, 11, b[41]), + g = l(g, h, f, m, k, 16, b[42]), + m = l(m, g, h, f, t, 23, b[43]), + f = l(f, m, g, h, A, 4, b[44]), + h = l(h, f, m, g, u, 11, b[45]), + g = l(g, h, f, m, x, 16, b[46]), + m = l(m, g, h, f, j, 23, b[47]), + f = s(f, m, g, h, c, 6, b[48]), + h = s(h, f, m, g, w, 10, b[49]), + g = s(g, h, f, m, E, 15, b[50]), + m = s(m, g, h, f, r, 21, b[51]), + f = s(f, m, g, h, u, 6, b[52]), + h = s(h, f, m, g, k, 10, b[53]), + g = s(g, h, f, m, B, 15, b[54]), + m = s(m, g, h, f, e, 21, b[55]), + f = s(f, m, g, h, v, 6, b[56]), + h = s(h, f, m, g, x, 10, b[57]), + g = s(g, h, f, m, t, 15, b[58]), + m = s(m, g, h, f, D, 21, b[59]), + f = s(f, m, g, h, z, 6, b[60]), + h = s(h, f, m, g, C, 10, b[61]), + g = s(g, h, f, m, j, 15, b[62]), + m = s(m, g, h, f, A, 21, b[63]); + a[0] = (a[0] + f) | 0; + a[1] = (a[1] + m) | 0; + a[2] = (a[2] + g) | 0; + a[3] = (a[3] + h) | 0; + }, + _doFinalize: function () { + var b = this._data, + n = b.words, + a = 8 * this._nDataBytes, + c = 8 * b.sigBytes; + n[c >>> 5] |= 128 << (24 - (c % 32)); + var e = u.floor(a / 4294967296); + n[(((c + 64) >>> 9) << 4) + 15] = (((e << 8) | (e >>> 24)) & 16711935) | (((e << 24) | (e >>> 8)) & 4278255360); + n[(((c + 64) >>> 9) << 4) + 14] = (((a << 8) | (a >>> 24)) & 16711935) | (((a << 24) | (a >>> 8)) & 4278255360); + b.sigBytes = 4 * (n.length + 1); + this._process(); + b = this._hash; + n = b.words; + for (a = 0; 4 > a; a++) + (c = n[a]), (n[a] = (((c << 8) | (c >>> 24)) & 16711935) | (((c << 24) | (c >>> 8)) & 4278255360)); + return b; + }, + clone: function () { + var b = v.clone.call(this); + b._hash = this._hash.clone(); + return b; + }, + }); + t.MD5 = v._createHelper(r); + t.HmacMD5 = v._createHmacHelper(r); + })(Math); + (function () { + var u = CryptoJS, + p = u.lib, + d = p.Base, + l = p.WordArray, + p = u.algo, + s = (p.EvpKDF = d.extend({ + cfg: d.extend({ keySize: 4, hasher: p.MD5, iterations: 1 }), + init: function (d) { + this.cfg = this.cfg.extend(d); + }, + compute: function (d, r) { + for ( + var p = this.cfg, s = p.hasher.create(), b = l.create(), u = b.words, q = p.keySize, p = p.iterations; + u.length < q; + + ) { + n && s.update(n); + var n = s.update(d).finalize(r); + s.reset(); + for (var a = 1; a < p; a++) (n = s.finalize(n)), s.reset(); + b.concat(n); + } + b.sigBytes = 4 * q; + return b; + }, + })); + u.EvpKDF = function (d, l, p) { + return s.create(p).compute(d, l); + }; + })(); + + // Cipher + CryptoJS.lib.Cipher || + (function (u) { + var p = CryptoJS, + d = p.lib, + l = d.Base, + s = d.WordArray, + t = d.BufferedBlockAlgorithm, + r = p.enc.Base64, + w = p.algo.EvpKDF, + v = (d.Cipher = t.extend({ + cfg: l.extend(), + createEncryptor: function (e, a) { + return this.create(this._ENC_XFORM_MODE, e, a); + }, + createDecryptor: function (e, a) { + return this.create(this._DEC_XFORM_MODE, e, a); + }, + init: function (e, a, b) { + this.cfg = this.cfg.extend(b); + this._xformMode = e; + this._key = a; + this.reset(); + }, + reset: function () { + t.reset.call(this); + this._doReset(); + }, + process: function (e) { + this._append(e); + return this._process(); + }, + finalize: function (e) { + e && this._append(e); + return this._doFinalize(); + }, + keySize: 4, + ivSize: 4, + _ENC_XFORM_MODE: 1, + _DEC_XFORM_MODE: 2, + _createHelper: function (e) { + return { + encrypt: function (b, k, d) { + return ('string' == typeof k ? c : a).encrypt(e, b, k, d); + }, + decrypt: function (b, k, d) { + return ('string' == typeof k ? c : a).decrypt(e, b, k, d); + }, + }; + }, + })); + d.StreamCipher = v.extend({ + _doFinalize: function () { + return this._process(!0); + }, + blockSize: 1, + }); + var b = (p.mode = {}), + x = function (e, a, b) { + var c = this._iv; + c ? (this._iv = u) : (c = this._prevBlock); + for (var d = 0; d < b; d++) e[a + d] ^= c[d]; + }, + q = (d.BlockCipherMode = l.extend({ + createEncryptor: function (e, a) { + return this.Encryptor.create(e, a); + }, + createDecryptor: function (e, a) { + return this.Decryptor.create(e, a); + }, + init: function (e, a) { + this._cipher = e; + this._iv = a; + }, + })).extend(); + q.Encryptor = q.extend({ + processBlock: function (e, a) { + var b = this._cipher, + c = b.blockSize; + x.call(this, e, a, c); + b.encryptBlock(e, a); + this._prevBlock = e.slice(a, a + c); + }, + }); + q.Decryptor = q.extend({ + processBlock: function (e, a) { + var b = this._cipher, + c = b.blockSize, + d = e.slice(a, a + c); + b.decryptBlock(e, a); + x.call(this, e, a, c); + this._prevBlock = d; + }, + }); + b = b.CBC = q; + q = (p.pad = {}).Pkcs7 = { + pad: function (a, b) { + for ( + var c = 4 * b, c = c - (a.sigBytes % c), d = (c << 24) | (c << 16) | (c << 8) | c, l = [], n = 0; + n < c; + n += 4 + ) + l.push(d); + c = s.create(l, c); + a.concat(c); + }, + unpad: function (a) { + a.sigBytes -= a.words[(a.sigBytes - 1) >>> 2] & 255; + }, + }; + d.BlockCipher = v.extend({ + cfg: v.cfg.extend({ mode: b, padding: q }), + reset: function () { + v.reset.call(this); + var a = this.cfg, + b = a.iv, + a = a.mode; + if (this._xformMode == this._ENC_XFORM_MODE) var c = a.createEncryptor; + else (c = a.createDecryptor), (this._minBufferSize = 1); + this._mode = c.call(a, this, b && b.words); + }, + _doProcessBlock: function (a, b) { + this._mode.processBlock(a, b); + }, + _doFinalize: function () { + var a = this.cfg.padding; + if (this._xformMode == this._ENC_XFORM_MODE) { + a.pad(this._data, this.blockSize); + var b = this._process(!0); + } else (b = this._process(!0)), a.unpad(b); + return b; + }, + blockSize: 4, + }); + var n = (d.CipherParams = l.extend({ + init: function (a) { + this.mixIn(a); + }, + toString: function (a) { + return (a || this.formatter).stringify(this); + }, + })), + b = ((p.format = {}).OpenSSL = { + stringify: function (a) { + var b = a.ciphertext; + a = a.salt; + return (a ? s.create([1398893684, 1701076831]).concat(a).concat(b) : b).toString(r); + }, + parse: function (a) { + a = r.parse(a); + var b = a.words; + if (1398893684 == b[0] && 1701076831 == b[1]) { + var c = s.create(b.slice(2, 4)); + b.splice(0, 4); + a.sigBytes -= 16; + } + return n.create({ ciphertext: a, salt: c }); + }, + }), + a = (d.SerializableCipher = l.extend({ + cfg: l.extend({ format: b }), + encrypt: function (a, b, c, d) { + d = this.cfg.extend(d); + var l = a.createEncryptor(c, d); + b = l.finalize(b); + l = l.cfg; + return n.create({ + ciphertext: b, + key: c, + iv: l.iv, + algorithm: a, + mode: l.mode, + padding: l.padding, + blockSize: a.blockSize, + formatter: d.format, + }); + }, + decrypt: function (a, b, c, d) { + d = this.cfg.extend(d); + b = this._parse(b, d.format); + return a.createDecryptor(c, d).finalize(b.ciphertext); + }, + _parse: function (a, b) { + return 'string' == typeof a ? b.parse(a, this) : a; + }, + })), + p = ((p.kdf = {}).OpenSSL = { + execute: function (a, b, c, d) { + d || (d = s.random(8)); + a = w.create({ keySize: b + c }).compute(a, d); + c = s.create(a.words.slice(b), 4 * c); + a.sigBytes = 4 * b; + return n.create({ key: a, iv: c, salt: d }); + }, + }), + c = (d.PasswordBasedCipher = a.extend({ + cfg: a.cfg.extend({ kdf: p }), + encrypt: function (b, c, d, l) { + l = this.cfg.extend(l); + d = l.kdf.execute(d, b.keySize, b.ivSize); + l.iv = d.iv; + b = a.encrypt.call(this, b, c, d.key, l); + b.mixIn(d); + return b; + }, + decrypt: function (b, c, d, l) { + l = this.cfg.extend(l); + c = this._parse(c, l.format); + d = l.kdf.execute(d, b.keySize, b.ivSize, c.salt); + l.iv = d.iv; + return a.decrypt.call(this, b, c, d.key, l); + }, + })); + })(); + + // AES + (function () { + for ( + var u = CryptoJS, + p = u.lib.BlockCipher, + d = u.algo, + l = [], + s = [], + t = [], + r = [], + w = [], + v = [], + b = [], + x = [], + q = [], + n = [], + a = [], + c = 0; + 256 > c; + c++ + ) + a[c] = 128 > c ? c << 1 : (c << 1) ^ 283; + for (var e = 0, j = 0, c = 0; 256 > c; c++) { + var k = j ^ (j << 1) ^ (j << 2) ^ (j << 3) ^ (j << 4), + k = (k >>> 8) ^ (k & 255) ^ 99; + l[e] = k; + s[k] = e; + var z = a[e], + F = a[z], + G = a[F], + y = (257 * a[k]) ^ (16843008 * k); + t[e] = (y << 24) | (y >>> 8); + r[e] = (y << 16) | (y >>> 16); + w[e] = (y << 8) | (y >>> 24); + v[e] = y; + y = (16843009 * G) ^ (65537 * F) ^ (257 * z) ^ (16843008 * e); + b[k] = (y << 24) | (y >>> 8); + x[k] = (y << 16) | (y >>> 16); + q[k] = (y << 8) | (y >>> 24); + n[k] = y; + e ? ((e = z ^ a[a[a[G ^ z]]]), (j ^= a[a[j]])) : (e = j = 1); + } + var H = [0, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54], + d = (d.AES = p.extend({ + _doReset: function () { + for ( + var a = this._key, + c = a.words, + d = a.sigBytes / 4, + a = 4 * ((this._nRounds = d + 6) + 1), + e = (this._keySchedule = []), + j = 0; + j < a; + j++ + ) + if (j < d) e[j] = c[j]; + else { + var k = e[j - 1]; + j % d + ? 6 < d && + 4 == j % d && + (k = (l[k >>> 24] << 24) | (l[(k >>> 16) & 255] << 16) | (l[(k >>> 8) & 255] << 8) | l[k & 255]) + : ((k = (k << 8) | (k >>> 24)), + (k = (l[k >>> 24] << 24) | (l[(k >>> 16) & 255] << 16) | (l[(k >>> 8) & 255] << 8) | l[k & 255]), + (k ^= H[(j / d) | 0] << 24)); + e[j] = e[j - d] ^ k; + } + c = this._invKeySchedule = []; + for (d = 0; d < a; d++) + (j = a - d), + (k = d % 4 ? e[j] : e[j - 4]), + (c[d] = + 4 > d || 4 >= j ? k : b[l[k >>> 24]] ^ x[l[(k >>> 16) & 255]] ^ q[l[(k >>> 8) & 255]] ^ n[l[k & 255]]); + }, + encryptBlock: function (a, b) { + this._doCryptBlock(a, b, this._keySchedule, t, r, w, v, l); + }, + decryptBlock: function (a, c) { + var d = a[c + 1]; + a[c + 1] = a[c + 3]; + a[c + 3] = d; + this._doCryptBlock(a, c, this._invKeySchedule, b, x, q, n, s); + d = a[c + 1]; + a[c + 1] = a[c + 3]; + a[c + 3] = d; + }, + _doCryptBlock: function (a, b, c, d, e, j, l, f) { + for ( + var m = this._nRounds, + g = a[b] ^ c[0], + h = a[b + 1] ^ c[1], + k = a[b + 2] ^ c[2], + n = a[b + 3] ^ c[3], + p = 4, + r = 1; + r < m; + r++ + ) + var q = d[g >>> 24] ^ e[(h >>> 16) & 255] ^ j[(k >>> 8) & 255] ^ l[n & 255] ^ c[p++], + s = d[h >>> 24] ^ e[(k >>> 16) & 255] ^ j[(n >>> 8) & 255] ^ l[g & 255] ^ c[p++], + t = d[k >>> 24] ^ e[(n >>> 16) & 255] ^ j[(g >>> 8) & 255] ^ l[h & 255] ^ c[p++], + n = d[n >>> 24] ^ e[(g >>> 16) & 255] ^ j[(h >>> 8) & 255] ^ l[k & 255] ^ c[p++], + g = q, + h = s, + k = t; + q = ((f[g >>> 24] << 24) | (f[(h >>> 16) & 255] << 16) | (f[(k >>> 8) & 255] << 8) | f[n & 255]) ^ c[p++]; + s = ((f[h >>> 24] << 24) | (f[(k >>> 16) & 255] << 16) | (f[(n >>> 8) & 255] << 8) | f[g & 255]) ^ c[p++]; + t = ((f[k >>> 24] << 24) | (f[(n >>> 16) & 255] << 16) | (f[(g >>> 8) & 255] << 8) | f[h & 255]) ^ c[p++]; + n = ((f[n >>> 24] << 24) | (f[(g >>> 16) & 255] << 16) | (f[(h >>> 8) & 255] << 8) | f[k & 255]) ^ c[p++]; + a[b] = q; + a[b + 1] = s; + a[b + 2] = t; + a[b + 3] = n; + }, + keySize: 8, + })); + u.AES = p._createHelper(d); + })(); + + // Mode ECB + CryptoJS.mode.ECB = (function () { + var ECB = CryptoJS.lib.BlockCipherMode.extend(); + + ECB.Encryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.encryptBlock(words, offset); + }, + }); + + ECB.Decryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.decryptBlock(words, offset); + }, + }); + + return ECB; + })(); + + var hmacSha256 = CryptoJS; + + var CryptoJS$1 = /*@__PURE__*/getDefaultExportFromCjs(hmacSha256); + + /** + * AES-CBC cryptor module. + */ + /** + * AES-CBC cryptor. + * + * AES-CBC cryptor with enhanced cipher strength. + */ + class AesCbcCryptor { + constructor({ cipherKey }) { + this.cipherKey = cipherKey; + this.CryptoJS = CryptoJS$1; + this.encryptedKey = this.CryptoJS.SHA256(cipherKey); + } + // -------------------------------------------------------- + // --------------------- Encryption ----------------------- + // -------------------------------------------------------- + // region Encryption + encrypt(data) { + const stringData = typeof data === 'string' ? data : AesCbcCryptor.decoder.decode(data); + if (stringData.length === 0) + throw new Error('encryption error. empty content'); + const abIv = this.getIv(); + return { + metadata: abIv, + data: decode(this.CryptoJS.AES.encrypt(data, this.encryptedKey, { + iv: this.bufferToWordArray(abIv), + mode: this.CryptoJS.mode.CBC, + }).ciphertext.toString(this.CryptoJS.enc.Base64)), + }; + } + encryptFileData(data) { + return __awaiter(this, void 0, void 0, function* () { + const key = yield this.getKey(); + const iv = this.getIv(); + return { + data: yield crypto.subtle.encrypt({ name: this.algo, iv: iv }, key, data), + metadata: iv, + }; + }); + } + // endregion + // -------------------------------------------------------- + // --------------------- Decryption ----------------------- + // -------------------------------------------------------- + // region Decryption + decrypt(encryptedData) { + if (typeof encryptedData.data === 'string') + throw new Error('Decryption error: data for decryption should be ArrayBuffed.'); + const iv = this.bufferToWordArray(new Uint8ClampedArray(encryptedData.metadata)); + const data = this.bufferToWordArray(new Uint8ClampedArray(encryptedData.data)); + return AesCbcCryptor.encoder.encode(this.CryptoJS.AES.decrypt({ ciphertext: data }, this.encryptedKey, { + iv, + mode: this.CryptoJS.mode.CBC, + }).toString(this.CryptoJS.enc.Utf8)).buffer; + } + decryptFileData(encryptedData) { + return __awaiter(this, void 0, void 0, function* () { + if (typeof encryptedData.data === 'string') + throw new Error('Decryption error: data for decryption should be ArrayBuffed.'); + const key = yield this.getKey(); + return crypto.subtle.decrypt({ name: this.algo, iv: encryptedData.metadata }, key, encryptedData.data); + }); + } + // endregion + // -------------------------------------------------------- + // ----------------------- Helpers ------------------------ + // -------------------------------------------------------- + // region Helpers + get identifier() { + return 'ACRH'; + } + /** + * Cryptor algorithm. + * + * @returns Cryptor module algorithm. + */ + get algo() { + return 'AES-CBC'; + } + /** + * Generate random initialization vector. + * + * @returns Random initialization vector. + */ + getIv() { + return crypto.getRandomValues(new Uint8Array(AesCbcCryptor.BLOCK_SIZE)); + } + /** + * Convert cipher key to the {@link Buffer}. + * + * @returns SHA256 encoded cipher key {@link Buffer}. + */ + getKey() { + return __awaiter(this, void 0, void 0, function* () { + const bKey = AesCbcCryptor.encoder.encode(this.cipherKey); + const abHash = yield crypto.subtle.digest('SHA-256', bKey.buffer); + return crypto.subtle.importKey('raw', abHash, this.algo, true, ['encrypt', 'decrypt']); + }); + } + /** + * Convert bytes array to words array. + * + * @param b - Bytes array (buffer) which should be converted. + * + * @returns Word sized array. + */ + bufferToWordArray(b) { + const wa = []; + let i; + for (i = 0; i < b.length; i += 1) { + wa[(i / 4) | 0] |= b[i] << (24 - 8 * i); + } + return this.CryptoJS.lib.WordArray.create(wa, b.length); + } + /** + * Serialize cryptor information to string. + * + * @returns Serialized cryptor information. + */ + toString() { + return 'AesCbcCryptor {}'; + } + } + /** + * Cryptor block size. + */ + AesCbcCryptor.BLOCK_SIZE = 16; + /** + * {@link string|String} to {@link ArrayBuffer} response decoder. + */ + AesCbcCryptor.encoder = new TextEncoder(); + /** + * {@link ArrayBuffer} to {@link string} decoder. + */ + AesCbcCryptor.decoder = new TextDecoder(); + + /** + * PubNub package utilities module. + * + * @internal + */ + /** + * Object log property names that must never appear in SDK logs. + * + * @internal + */ + const SENSITIVE_LOG_KEYS = new Set(['authKey', 'authKeys', 'secretKey', 'cipherKey', 'token', 'auth']); + /** + * Whether an object log key should be omitted because it may hold a secret. + * + * @param key - Property name from an object being logged. + * + * @returns `true` when the key should be filtered from log output. + * + * @internal + */ + const isSensitiveLogKey = (key) => SENSITIVE_LOG_KEYS.has(key); + /** + * Percent-encode input string. + * + * **Note:** Encode content in accordance of the `PubNub` service requirements. + * + * @param input - Source string or number for encoding. + * + * @returns Percent-encoded string. + * + * @internal + */ + const encodeString = (input) => { + return encodeURIComponent(input).replace(/[!~*'()]/g, (x) => `%${x.charCodeAt(0).toString(16).toUpperCase()}`); + }; + /** + * Percent-encode list of names (channels). + * + * @param names - List of names which should be encoded. + * + * @param [defaultString] - String which should be used in case if {@link names} is empty. + * + * @returns String which contains encoded names joined by non-encoded `,`. + * + * @internal + */ + const encodeNames = (names, defaultString) => { + const encodedNames = names.map((name) => encodeString(name)); + return encodedNames.length ? encodedNames.join(',') : (defaultString !== null && defaultString !== void 0 ? defaultString : ''); + }; + /** + * @internal + */ + const removeSingleOccurrence = (source, elementsToRemove) => { + const removed = Object.fromEntries(elementsToRemove.map((prop) => [prop, false])); + return source.filter((e) => { + if (elementsToRemove.includes(e) && !removed[e]) { + removed[e] = true; + return false; + } + return true; + }); + }; + /** + * @internal + */ + const findUniqueCommonElements = (a, b) => { + return [...a].filter((value) => b.includes(value) && a.indexOf(value) === a.lastIndexOf(value) && b.indexOf(value) === b.lastIndexOf(value)); + }; + /** + * Transform query key / value pairs to the string. + * + * @param query - Key / value pairs of the request query parameters. + * + * @returns Stringified query key / value pairs. + * + * @internal + */ + const queryStringFromObject = (query) => { + return Object.keys(query) + .map((key) => { + const queryValue = query[key]; + if (!Array.isArray(queryValue)) + return `${key}=${encodeString(queryValue)}`; + return queryValue.map((value) => `${key}=${encodeString(value)}`).join('&'); + }) + .join('&'); + }; + /** + * Adjust `timetoken` to represent current time in PubNub's high-precision time format. + * + * @param timetoken - Timetoken recently used for subscribe long-poll request. + * @param [referenceTimetoken] - Previously computed reference timetoken. + * + * @returns Adjusted timetoken if recent timetoken available. + */ + const subscriptionTimetokenFromReference = (timetoken, referenceTimetoken) => { + if (referenceTimetoken === '0' || timetoken === '0') + return undefined; + const timetokenDiff = adjustedTimetokenBy(`${Date.now()}0000`, referenceTimetoken, false); + return adjustedTimetokenBy(timetoken, timetokenDiff, true); + }; + /** + * Create reference timetoken based on subscribe timetoken and the user's local time. + * + * Subscription-based reference timetoken allows later computing approximate timetoken at any point in time. + * + * @param [serviceTimetoken] - Timetoken received from the PubNub subscribe service. + * @param [catchUpTimetoken] - Previously stored or user-provided catch-up timetoken. + * @param [referenceTimetoken] - Previously computed reference timetoken. **Important:** This value should be used + * in the case of restore because the actual time when service and catch-up timetokens are received is really + * different from the current local time. + * + * @returns Reference timetoken. + */ + const referenceSubscribeTimetoken = (serviceTimetoken, catchUpTimetoken, referenceTimetoken) => { + if (!serviceTimetoken || serviceTimetoken.length === 0) + return undefined; + if (catchUpTimetoken && catchUpTimetoken.length > 0 && catchUpTimetoken !== '0') { + // Compensate reference timetoken because catch-up timetoken has been used. + const timetokensDiff = adjustedTimetokenBy(serviceTimetoken, catchUpTimetoken, false); + return adjustedTimetokenBy(referenceTimetoken !== null && referenceTimetoken !== void 0 ? referenceTimetoken : `${Date.now()}0000`, timetokensDiff.replace('-', ''), Number(timetokensDiff) < 0); + } + else if (referenceTimetoken && referenceTimetoken.length > 0 && referenceTimetoken !== '0') + return referenceTimetoken; + else + return `${Date.now()}0000`; + }; + /** + * High-precision time token adjustment. + * + * @param timetoken - Source timetoken which should be adjusted. + * @param value - Value in nanoseconds which should be used for source timetoken adjustment. + * @param increment - Whether source timetoken should be incremented or decremented. + * + * @returns Adjusted high-precision PubNub timetoken. + */ + const adjustedTimetokenBy = (timetoken, value, increment) => { + // Normalize value to the PubNub's high-precision time format. + if (value.startsWith('-')) { + value = value.replace('-', ''); + increment = false; + } + value = value.padStart(17, '0'); + const secA = timetoken.slice(0, 10); + const tickA = timetoken.slice(10, 17); + const secB = value.slice(0, 10); + const tickB = value.slice(10, 17); + let seconds = Number(secA); + let ticks = Number(tickA); + seconds += Number(secB) * (increment ? 1 : -1); + ticks += Number(tickB) * (increment ? 1 : -1); + if (ticks >= 10000000) { + seconds += Math.floor(ticks / 10000000); + ticks %= 10000000; + } + else if (ticks < 0) { + if (seconds > 0) { + seconds -= 1; + ticks += 10000000; + } + else if (seconds < 0) + ticks *= -1; + } + else if (seconds < 0 && ticks > 0) { + seconds += 1; + ticks = 10000000 - ticks; + } + return seconds !== 0 ? `${seconds}${`${ticks}`.padStart(7, '0')}` : `${ticks}`; + }; + /** + * Compute received update (message, event) fingerprint. + * + * @param input - Data payload from subscribe API response. + * + * @returns Received update fingerprint. + */ + const messageFingerprint = (input) => { + const msg = typeof input !== 'string' ? JSON.stringify(input) : input; + const mfp = new Uint32Array(1); + let walk = 0; + let len = msg.length; + while (len-- > 0) + mfp[0] = (mfp[0] << 5) - mfp[0] + msg.charCodeAt(walk++); + return mfp[0].toString(16).padStart(8, '0'); + }; + + /** + * Legacy cryptography module. + * + * @internal + */ + /** + * Convert bytes array to words array. + * + * @param b - Bytes array (buffer) which should be converted. + * + * @returns Word sized array. + * + * @internal + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ + function bufferToWordArray(b) { + const wa = []; + let i; + for (i = 0; i < b.length; i += 1) { + wa[(i / 4) | 0] |= b[i] << (24 - 8 * i); + } + // @ts-expect-error Bundled library without types. + return CryptoJS$1.lib.WordArray.create(wa, b.length); + } + /** + * Legacy cryptography module for files and signature. + * + * @internal + */ + class Crypto { + constructor(configuration) { + this.configuration = configuration; + /** + * Crypto initialization vector. + */ + this.iv = '0123456789012345'; + /** + * List os allowed cipher key encodings. + */ + this.allowedKeyEncodings = ['hex', 'utf8', 'base64', 'binary']; + /** + * Allowed cipher key lengths. + */ + this.allowedKeyLengths = [128, 256]; + /** + * Allowed crypto modes. + */ + this.allowedModes = ['ecb', 'cbc']; + this.logger = configuration.logger; + this.defaultOptions = { + encryptKey: true, + keyEncoding: 'utf8', + keyLength: 256, + mode: 'cbc', + }; + } + /** + * Update registered loggers' manager. + * + * @param [logger] - Logger, which crypto should use. + */ + set logger(logger) { + this._logger = logger; + if (this.logger) { + this.logger.debug('Crypto', () => ({ + messageType: 'object', + message: this.configuration, + details: 'Create with configuration:', + ignoredKeys(key, obj) { + return typeof obj[key] === 'function' || key === 'logger' || isSensitiveLogKey(key); + }, + })); + } + } + /** + * Get loggers' manager. + * + * @returns Loggers' manager (if set). + */ + get logger() { + return this._logger; + } + /** + * Generate HMAC-SHA256 hash from input data. + * + * @param data - Data from which hash should be generated. + * + * @returns HMAC-SHA256 hash from provided `data`. + */ + HMACSHA256(data) { + // @ts-expect-error Bundled library without types. + const hash = CryptoJS$1.HmacSHA256(data, this.configuration.secretKey); + // @ts-expect-error Bundled library without types. + return hash.toString(CryptoJS$1.enc.Base64); + } + /** + * Generate SHA256 hash from input data. + * + * @param data - Data from which hash should be generated. + * + * @returns SHA256 hash from provided `data`. + */ + SHA256(data) { + // @ts-expect-error Bundled library without types. + return CryptoJS$1.SHA256(data).toString(CryptoJS$1.enc.Hex); + } + /** + * Encrypt provided data. + * + * @param data - Source data which should be encrypted. + * @param [customCipherKey] - Custom cipher key (different from defined on client level). + * @param [options] - Specific crypto configuration options. + * + * @returns Encrypted `data`. + */ + encrypt(data, customCipherKey, options) { + if (this.configuration.customEncrypt) { + if (this.logger) + this.logger.warn('Crypto', "'customEncrypt' is deprecated. Consult docs for better alternative."); + return this.configuration.customEncrypt(data); + } + return this.pnEncrypt(data, customCipherKey, options); + } + /** + * Decrypt provided data. + * + * @param data - Encrypted data which should be decrypted. + * @param [customCipherKey] - Custom cipher key (different from defined on client level). + * @param [options] - Specific crypto configuration options. + * + * @returns Decrypted `data`. + */ + decrypt(data, customCipherKey, options) { + if (this.configuration.customDecrypt) { + if (this.logger) + this.logger.warn('Crypto', "'customDecrypt' is deprecated. Consult docs for better alternative."); + return this.configuration.customDecrypt(data); + } + return this.pnDecrypt(data, customCipherKey, options); + } + /** + * Encrypt provided data. + * + * @param data - Source data which should be encrypted. + * @param [customCipherKey] - Custom cipher key (different from defined on client level). + * @param [options] - Specific crypto configuration options. + * + * @returns Encrypted `data` as string. + */ + pnEncrypt(data, customCipherKey, options) { + const decidedCipherKey = customCipherKey !== null && customCipherKey !== void 0 ? customCipherKey : this.configuration.cipherKey; + if (!decidedCipherKey) + return data; + if (this.logger) { + this.logger.debug('Crypto', () => ({ + messageType: 'object', + message: Object.assign({ data }, (options !== null && options !== void 0 ? options : {})), + details: 'Encrypt with parameters:', + ignoredKeys: isSensitiveLogKey, + })); + } + options = this.parseOptions(options); + const mode = this.getMode(options); + const cipherKey = this.getPaddedKey(decidedCipherKey, options); + if (this.configuration.useRandomIVs) { + const waIv = this.getRandomIV(); + // @ts-expect-error Bundled library without types. + const waPayload = CryptoJS$1.AES.encrypt(data, cipherKey, { iv: waIv, mode }).ciphertext; + // @ts-expect-error Bundled library without types. + return waIv.clone().concat(waPayload.clone()).toString(CryptoJS$1.enc.Base64); + } + const iv = this.getIV(options); + // @ts-expect-error Bundled library without types. + const encryptedHexArray = CryptoJS$1.AES.encrypt(data, cipherKey, { iv, mode }).ciphertext; + // @ts-expect-error Bundled library without types. + const base64Encrypted = encryptedHexArray.toString(CryptoJS$1.enc.Base64); + return base64Encrypted || data; + } + /** + * Decrypt provided data. + * + * @param data - Encrypted data which should be decrypted. + * @param [customCipherKey] - Custom cipher key (different from defined on client level). + * @param [options] - Specific crypto configuration options. + * + * @returns Decrypted `data`. + */ + pnDecrypt(data, customCipherKey, options) { + const decidedCipherKey = customCipherKey !== null && customCipherKey !== void 0 ? customCipherKey : this.configuration.cipherKey; + if (!decidedCipherKey) + return data; + if (this.logger) { + this.logger.debug('Crypto', () => ({ + messageType: 'object', + message: Object.assign({ data }, (options !== null && options !== void 0 ? options : {})), + details: 'Decrypt with parameters:', + ignoredKeys: isSensitiveLogKey, + })); + } + options = this.parseOptions(options); + const mode = this.getMode(options); + const cipherKey = this.getPaddedKey(decidedCipherKey, options); + if (this.configuration.useRandomIVs) { + const ciphertext = new Uint8ClampedArray(decode(data)); + const iv = bufferToWordArray(ciphertext.slice(0, 16)); + const payload = bufferToWordArray(ciphertext.slice(16)); + try { + // @ts-expect-error Bundled library without types. + const plainJSON = CryptoJS$1.AES.decrypt({ ciphertext: payload }, cipherKey, { iv, mode }).toString( + // @ts-expect-error Bundled library without types. + CryptoJS$1.enc.Utf8); + return JSON.parse(plainJSON); + } + catch (e) { + if (this.logger) + this.logger.error('Crypto', () => ({ messageType: 'error', message: e })); + return null; + } + } + else { + const iv = this.getIV(options); + try { + // @ts-expect-error Bundled library without types. + const ciphertext = CryptoJS$1.enc.Base64.parse(data); + // @ts-expect-error Bundled library without types. + const plainJSON = CryptoJS$1.AES.decrypt({ ciphertext }, cipherKey, { iv, mode }).toString(CryptoJS$1.enc.Utf8); + return JSON.parse(plainJSON); + } + catch (e) { + if (this.logger) + this.logger.error('Crypto', () => ({ messageType: 'error', message: e })); + return null; + } + } + } + /** + * Pre-process provided custom crypto configuration. + * + * @param incomingOptions - Configuration which should be pre-processed before use. + * + * @returns Normalized crypto configuration options. + */ + parseOptions(incomingOptions) { + var _a, _b, _c, _d; + if (!incomingOptions) + return this.defaultOptions; + // Defaults + const options = { + encryptKey: (_a = incomingOptions.encryptKey) !== null && _a !== void 0 ? _a : this.defaultOptions.encryptKey, + keyEncoding: (_b = incomingOptions.keyEncoding) !== null && _b !== void 0 ? _b : this.defaultOptions.keyEncoding, + keyLength: (_c = incomingOptions.keyLength) !== null && _c !== void 0 ? _c : this.defaultOptions.keyLength, + mode: (_d = incomingOptions.mode) !== null && _d !== void 0 ? _d : this.defaultOptions.mode, + }; + // Validation + if (this.allowedKeyEncodings.indexOf(options.keyEncoding.toLowerCase()) === -1) + options.keyEncoding = this.defaultOptions.keyEncoding; + if (this.allowedKeyLengths.indexOf(options.keyLength) === -1) + options.keyLength = this.defaultOptions.keyLength; + if (this.allowedModes.indexOf(options.mode.toLowerCase()) === -1) + options.mode = this.defaultOptions.mode; + return options; + } + /** + * Decode provided cipher key. + * + * @param key - Key in `encoding` provided by `options`. + * @param options - Crypto configuration options with cipher key details. + * + * @returns Array buffer with decoded key. + */ + decodeKey(key, options) { + // @ts-expect-error Bundled library without types. + if (options.keyEncoding === 'base64') + return CryptoJS$1.enc.Base64.parse(key); + // @ts-expect-error Bundled library without types. + if (options.keyEncoding === 'hex') + return CryptoJS$1.enc.Hex.parse(key); + return key; + } + /** + * Add padding to the cipher key. + * + * @param key - Key which should be padded. + * @param options - Crypto configuration options with cipher key details. + * + * @returns Properly padded cipher key. + */ + getPaddedKey(key, options) { + key = this.decodeKey(key, options); + // @ts-expect-error Bundled library without types. + if (options.encryptKey) + return CryptoJS$1.enc.Utf8.parse(this.SHA256(key).slice(0, 32)); + return key; + } + /** + * Cipher mode. + * + * @param options - Crypto configuration with information about cipher mode. + * + * @returns Crypto cipher mode. + */ + getMode(options) { + // @ts-expect-error Bundled library without types. + if (options.mode === 'ecb') + return CryptoJS$1.mode.ECB; + // @ts-expect-error Bundled library without types. + return CryptoJS$1.mode.CBC; + } + /** + * Cipher initialization vector. + * + * @param options - Crypto configuration with information about cipher mode. + * + * @returns Initialization vector. + */ + getIV(options) { + // @ts-expect-error Bundled library without types. + return options.mode === 'cbc' ? CryptoJS$1.enc.Utf8.parse(this.iv) : null; + } + /** + * Random initialization vector. + * + * @returns Generated random initialization vector. + */ + getRandomIV() { + // @ts-expect-error Bundled library without types. + return CryptoJS$1.lib.WordArray.random(16); + } + } + + /** + * Legacy browser cryptography module. + * + * @internal + */ + /* global crypto */ + /** + * Legacy cryptography implementation for browser-based {@link PubNub} client. + * + * @internal + */ + class WebCryptography { + // -------------------------------------------------------- + // --------------------- Encryption ----------------------- + // -------------------------------------------------------- + // region Encryption + /** + * Encrypt provided source data using specific encryption {@link key}. + * + * @param key - Data encryption key.
**Note:** Same key should be used to `decrypt` data. + * @param input - Source data for encryption. + * + * @returns Encrypted data as object or stream (depending on from source data type). + * + * @throws Error if unknown data type has been passed. + */ + encrypt(key, input) { + return __awaiter(this, void 0, void 0, function* () { + if (!(input instanceof ArrayBuffer) && typeof input !== 'string') + throw new Error('Cannot encrypt this file. In browsers file encryption supports only string or ArrayBuffer'); + const cKey = yield this.getKey(key); + return input instanceof ArrayBuffer ? this.encryptArrayBuffer(cKey, input) : this.encryptString(cKey, input); + }); + } + /** + * Encrypt provided source {@link Buffer} using specific encryption {@link ArrayBuffer}. + * + * @param key - Data encryption key.
**Note:** Same key should be used to `decrypt` {@link ArrayBuffer}. + * @param buffer - Source {@link ArrayBuffer} for encryption. + * + * @returns Encrypted data as {@link ArrayBuffer} object. + */ + encryptArrayBuffer(key, buffer) { + return __awaiter(this, void 0, void 0, function* () { + const abIv = crypto.getRandomValues(new Uint8Array(16)); + return this.concatArrayBuffer(abIv.buffer, yield crypto.subtle.encrypt({ name: 'AES-CBC', iv: abIv }, key, buffer)); + }); + } + /** + * Encrypt provided source {@link string} using specific encryption {@link key}. + * + * @param key - Data encryption key.
**Note:** Same key should be used to `decrypt` {@link string}. + * @param text - Source {@link string} for encryption. + * + * @returns Encrypted data as byte {@link string}. + */ + encryptString(key, text) { + return __awaiter(this, void 0, void 0, function* () { + const abIv = crypto.getRandomValues(new Uint8Array(16)); + const abPlaintext = WebCryptography.encoder.encode(text).buffer; + const abPayload = yield crypto.subtle.encrypt({ name: 'AES-CBC', iv: abIv }, key, abPlaintext); + const ciphertext = this.concatArrayBuffer(abIv.buffer, abPayload); + return WebCryptography.decoder.decode(ciphertext); + }); + } + /** + * Encrypt provided {@link PubNub} File object using specific encryption {@link key}. + * + * @param key - Key for {@link PubNub} File object encryption.
**Note:** Same key should be + * used to `decrypt` data. + * @param file - Source {@link PubNub} File object for encryption. + * @param File - Class constructor for {@link PubNub} File object. + * + * @returns Encrypted data as {@link PubNub} File object. + * + * @throws Error if file is empty or contains unsupported data type. + */ + encryptFile(key, file, File) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b; + if (((_a = file.contentLength) !== null && _a !== void 0 ? _a : 0) <= 0) + throw new Error('encryption error. empty content'); + const bKey = yield this.getKey(key); + const abPlaindata = yield file.toArrayBuffer(); + const abCipherdata = yield this.encryptArrayBuffer(bKey, abPlaindata); + return File.create({ + name: file.name, + mimeType: (_b = file.mimeType) !== null && _b !== void 0 ? _b : 'application/octet-stream', + data: abCipherdata, + }); + }); + } + // endregion + // -------------------------------------------------------- + // --------------------- Decryption ----------------------- + // -------------------------------------------------------- + // region Decryption + /** + * Decrypt provided encrypted data using specific decryption {@link key}. + * + * @param key - Data decryption key.
**Note:** Should be the same as used to `encrypt` data. + * @param input - Encrypted data for decryption. + * + * @returns Decrypted data as object or stream (depending on from encrypted data type). + * + * @throws Error if unknown data type has been passed. + */ + decrypt(key, input) { + return __awaiter(this, void 0, void 0, function* () { + if (!(input instanceof ArrayBuffer) && typeof input !== 'string') + throw new Error('Cannot decrypt this file. In browsers file decryption supports only string or ArrayBuffer'); + const cKey = yield this.getKey(key); + return input instanceof ArrayBuffer ? this.decryptArrayBuffer(cKey, input) : this.decryptString(cKey, input); + }); + } + /** + * Decrypt provided encrypted {@link ArrayBuffer} using specific decryption {@link key}. + * + * @param key - Data decryption key.
**Note:** Should be the same as used to `encrypt` {@link ArrayBuffer}. + * @param buffer - Encrypted {@link ArrayBuffer} for decryption. + * + * @returns Decrypted data as {@link ArrayBuffer} object. + */ + decryptArrayBuffer(key, buffer) { + return __awaiter(this, void 0, void 0, function* () { + const abIv = buffer.slice(0, 16); + if (buffer.slice(WebCryptography.IV_LENGTH).byteLength <= 0) + throw new Error('decryption error: empty content'); + return yield crypto.subtle.decrypt({ name: 'AES-CBC', iv: abIv }, key, buffer.slice(WebCryptography.IV_LENGTH)); + }); + } + /** + * Decrypt provided encrypted {@link string} using specific decryption {@link key}. + * + * @param key - Data decryption key.
**Note:** Should be the same as used to `encrypt` {@link string}. + * @param text - Encrypted {@link string} for decryption. + * + * @returns Decrypted data as byte {@link string}. + */ + decryptString(key, text) { + return __awaiter(this, void 0, void 0, function* () { + const abCiphertext = WebCryptography.encoder.encode(text).buffer; + const abIv = abCiphertext.slice(0, 16); + const abPayload = abCiphertext.slice(16); + const abPlaintext = yield crypto.subtle.decrypt({ name: 'AES-CBC', iv: abIv }, key, abPayload); + return WebCryptography.decoder.decode(abPlaintext); + }); + } + /** + * Decrypt provided {@link PubNub} File object using specific decryption {@link key}. + * + * @param key - Key for {@link PubNub} File object decryption.
**Note:** Should be the same + * as used to `encrypt` data. + * @param file - Encrypted {@link PubNub} File object for decryption. + * @param File - Class constructor for {@link PubNub} File object. + * + * @returns Decrypted data as {@link PubNub} File object. + * + * @throws Error if file is empty or contains unsupported data type. + */ + decryptFile(key, file, File) { + return __awaiter(this, void 0, void 0, function* () { + const bKey = yield this.getKey(key); + const abCipherdata = yield file.toArrayBuffer(); + const abPlaindata = yield this.decryptArrayBuffer(bKey, abCipherdata); + return File.create({ + name: file.name, + mimeType: file.mimeType, + data: abPlaindata, + }); + }); + } + // endregion + // -------------------------------------------------------- + // ----------------------- Helpers ------------------------ + // -------------------------------------------------------- + // region Helpers + /** + * Convert cipher key to the {@link Buffer}. + * + * @param key - String cipher key. + * + * @returns SHA256 HEX encoded cipher key {@link CryptoKey}. + */ + getKey(key) { + return __awaiter(this, void 0, void 0, function* () { + const digest = yield crypto.subtle.digest('SHA-256', WebCryptography.encoder.encode(key)); + const hashHex = Array.from(new Uint8Array(digest)) + .map((b) => b.toString(16).padStart(2, '0')) + .join(''); + const abKey = WebCryptography.encoder.encode(hashHex.slice(0, 32)).buffer; + return crypto.subtle.importKey('raw', abKey, 'AES-CBC', true, ['encrypt', 'decrypt']); + }); + } + /** + * Join two `ArrayBuffer`s. + * + * @param ab1 - `ArrayBuffer` to which other buffer should be appended. + * @param ab2 - `ArrayBuffer` which should appended to the other buffer. + * + * @returns Buffer which starts with `ab1` elements and appended `ab2`. + */ + concatArrayBuffer(ab1, ab2) { + const tmp = new Uint8Array(ab1.byteLength + ab2.byteLength); + tmp.set(new Uint8Array(ab1), 0); + tmp.set(new Uint8Array(ab2), ab1.byteLength); + return tmp.buffer; + } + } + /** + * Random initialization vector size. + */ + WebCryptography.IV_LENGTH = 16; + /** + * {@link string|String} to {@link ArrayBuffer} response decoder. + */ + WebCryptography.encoder = new TextEncoder(); + /** + * {@link ArrayBuffer} to {@link string} decoder. + */ + WebCryptography.decoder = new TextDecoder(); + + /** + * Legacy cryptor module. + */ + /** + * Legacy cryptor. + */ + class LegacyCryptor { + constructor(config) { + this.config = config; + this.cryptor = new Crypto(Object.assign({}, config)); + this.fileCryptor = new WebCryptography(); + } + /** + * Update registered loggers' manager. + * + * @param [logger] - Logger, which crypto should use. + */ + set logger(logger) { + this.cryptor.logger = logger; + if (this.config.useRandomIVs === false) { + logger.warn('LegacyCryptor', `Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients. + Do not disable random IVs in new applications.`); + } + } + // -------------------------------------------------------- + // --------------------- Encryption ----------------------- + // -------------------------------------------------------- + // region Encryption + encrypt(data) { + const stringData = typeof data === 'string' ? data : LegacyCryptor.decoder.decode(data); + return { + data: this.cryptor.encrypt(stringData), + metadata: null, + }; + } + encryptFile(file, File) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + if (!this.config.cipherKey) + throw new PubNubError('File encryption error: cipher key not set.'); + return this.fileCryptor.encryptFile((_a = this.config) === null || _a === void 0 ? void 0 : _a.cipherKey, file, File); + }); + } + // endregion + // -------------------------------------------------------- + // --------------------- Decryption ----------------------- + // -------------------------------------------------------- + // region Decryption + decrypt(encryptedData) { + const data = typeof encryptedData.data === 'string' ? encryptedData.data : encode(encryptedData.data); + return this.cryptor.decrypt(data); + } + decryptFile(file, File) { + return __awaiter(this, void 0, void 0, function* () { + if (!this.config.cipherKey) + throw new PubNubError('File encryption error: cipher key not set.'); + return this.fileCryptor.decryptFile(this.config.cipherKey, file, File); + }); + } + // endregion + // -------------------------------------------------------- + // ----------------------- Helpers ------------------------ + // -------------------------------------------------------- + // region Helpers + get identifier() { + return ''; + } + // endregion + /** + * Serialize cryptor information to string. + * + * @returns Serialized cryptor information. + */ + toString() { + const configurationEntries = Object.entries(this.config).reduce((acc, [key, value]) => { + if (key === 'logger' || isSensitiveLogKey(key)) + return acc; + acc.push(`${key}: ${typeof value === 'function' ? '' : value}`); + return acc; + }, []); + return `LegacyCryptor { ${configurationEntries.join(', ')} }`; + } + } + /** + * `string` to {@link ArrayBuffer} response decoder. + */ + LegacyCryptor.encoder = new TextEncoder(); + /** + * {@link ArrayBuffer} to {@link string} decoder. + */ + LegacyCryptor.decoder = new TextDecoder(); + + /** + * Browser crypto module. + */ + /** + * CryptoModule for browser platform. + */ + class WebCryptoModule extends AbstractCryptoModule { + /** + * Assign registered loggers' manager. + * + * @param logger - Registered loggers' manager. + * + * @internal + */ + set logger(logger) { + if (this.defaultCryptor.identifier === WebCryptoModule.LEGACY_IDENTIFIER) { + logger.warn('CryptoModule', "'legacyCryptoModule' is deprecated. Use 'aesCbcCryptoModule' instead for new applications."); + this.defaultCryptor.logger = logger; + } + else { + const cryptor = this.cryptors.find((cryptor) => cryptor.identifier === WebCryptoModule.LEGACY_IDENTIFIER); + if (cryptor) + cryptor.logger = logger; + } + } + // -------------------------------------------------------- + // --------------- Convenience functions ------------------ + // ------------------------------------------------------- + // region Convenience functions + /** + * Construct crypto module with legacy cryptor for encryption and both legacy and AES-CBC + * cryptors for decryption. + * + * @deprecated Use {@link aesCbcCryptoModule} for new applications. + */ + static legacyCryptoModule(config) { + var _a; + if (!config.cipherKey) + throw new PubNubError('Crypto module error: cipher key not set.'); + if (config.logger) { + config.logger.warn('CryptoModule', "'legacyCryptoModule' is deprecated. Use 'aesCbcCryptoModule' instead for new applications."); + if (config.useRandomIVs === false) { + config.logger.warn('CryptoModule', `Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients. + Do not disable random IVs in new applications.`); + } + } + return new WebCryptoModule({ + default: new LegacyCryptor(Object.assign(Object.assign({}, config), { useRandomIVs: (_a = config.useRandomIVs) !== null && _a !== void 0 ? _a : true })), + cryptors: [new AesCbcCryptor({ cipherKey: config.cipherKey })], + }); + } + static aesCbcCryptoModule(config) { + var _a; + if (!config.cipherKey) + throw new PubNubError('Crypto module error: cipher key not set.'); + return new WebCryptoModule({ + default: new AesCbcCryptor({ cipherKey: config.cipherKey }), + cryptors: [ + new LegacyCryptor(Object.assign(Object.assign({}, config), { useRandomIVs: (_a = config.useRandomIVs) !== null && _a !== void 0 ? _a : true })), + ], + }); + } + /** + * Construct crypto module with `cryptor` as default for data encryption and decryption. + * + * @param defaultCryptor - Default cryptor for data encryption and decryption. + * + * @returns Crypto module with pre-configured default cryptor. + */ + static withDefaultCryptor(defaultCryptor) { + return new this({ default: defaultCryptor }); + } + // endregion + // -------------------------------------------------------- + // --------------------- Encryption ----------------------- + // -------------------------------------------------------- + // region Encryption + encrypt(data) { + // Encrypt data. + const encrypted = data instanceof ArrayBuffer && this.defaultCryptor.identifier === WebCryptoModule.LEGACY_IDENTIFIER + ? this.defaultCryptor.encrypt(WebCryptoModule.decoder.decode(data)) + : this.defaultCryptor.encrypt(data); + if (!encrypted.metadata) + return encrypted.data; + else if (typeof encrypted.data === 'string') + throw new Error('Encryption error: encrypted data should be ArrayBuffed.'); + const headerData = this.getHeaderData(encrypted); + return this.concatArrayBuffer(headerData, encrypted.data); + } + encryptFile(file, File) { + return __awaiter(this, void 0, void 0, function* () { + /** + * Files handled differently in case of Legacy cryptor. + * (as long as we support legacy need to check on instance type) + */ + if (this.defaultCryptor.identifier === CryptorHeader.LEGACY_IDENTIFIER) + return this.defaultCryptor.encryptFile(file, File); + const fileData = yield this.getFileData(file); + const encrypted = yield this.defaultCryptor.encryptFileData(fileData); + if (typeof encrypted.data === 'string') + throw new Error('Encryption error: encrypted data should be ArrayBuffed.'); + return File.create({ + name: file.name, + mimeType: 'application/octet-stream', + data: this.concatArrayBuffer(this.getHeaderData(encrypted), encrypted.data), + }); + }); + } + // endregion + // -------------------------------------------------------- + // --------------------- Decryption ----------------------- + // -------------------------------------------------------- + // region Decryption + decrypt(data) { + const encryptedData = typeof data === 'string' ? decode(data) : data; + const header = CryptorHeader.tryParse(encryptedData); + const cryptor = this.getCryptor(header); + const metadata = header.length > 0 + ? encryptedData.slice(header.length - header.metadataLength, header.length) + : null; + if (encryptedData.slice(header.length).byteLength <= 0) + throw new Error('Decryption error: empty content'); + return cryptor.decrypt({ + data: encryptedData.slice(header.length), + metadata: metadata, + }); + } + decryptFile(file, File) { + return __awaiter(this, void 0, void 0, function* () { + const data = yield file.data.arrayBuffer(); + const header = CryptorHeader.tryParse(data); + const cryptor = this.getCryptor(header); + /** + * Files handled differently in case of Legacy cryptor. + * (as long as we support legacy need to check on instance type) + */ + if ((cryptor === null || cryptor === void 0 ? void 0 : cryptor.identifier) === CryptorHeader.LEGACY_IDENTIFIER) + return cryptor.decryptFile(file, File); + const fileData = yield this.getFileData(data); + const metadata = fileData.slice(header.length - header.metadataLength, header.length); + return File.create({ + name: file.name, + data: yield this.defaultCryptor.decryptFileData({ + data: data.slice(header.length), + metadata: metadata, + }), + }); + }); + } + // endregion + // -------------------------------------------------------- + // ----------------------- Helpers ------------------------ + // -------------------------------------------------------- + // region Helpers + /** + * Retrieve registered cryptor by its identifier. + * + * @param id - Unique cryptor identifier. + * + * @returns Registered cryptor with specified identifier. + * + * @throws Error if cryptor with specified {@link id} can't be found. + */ + getCryptorFromId(id) { + const cryptor = this.getAllCryptors().find((cryptor) => id === cryptor.identifier); + if (cryptor) + return cryptor; + throw Error('Unknown cryptor error'); + } + /** + * Retrieve cryptor by its identifier. + * + * @param header - Header with cryptor-defined data or raw cryptor identifier. + * + * @returns Cryptor which correspond to provided {@link header}. + */ + getCryptor(header) { + if (typeof header === 'string') { + const cryptor = this.getAllCryptors().find((cryptor) => cryptor.identifier === header); + if (cryptor) + return cryptor; + throw new Error('Unknown cryptor error'); + } + else if (header instanceof CryptorHeaderV1) { + return this.getCryptorFromId(header.identifier); + } + } + /** + * Create cryptor header data. + * + * @param encrypted - Encryption data object as source for header data. + * + * @returns Binary representation of the cryptor header data. + */ + getHeaderData(encrypted) { + if (!encrypted.metadata) + return; + const header = CryptorHeader.from(this.defaultCryptor.identifier, encrypted.metadata); + const headerData = new Uint8Array(header.length); + let pos = 0; + headerData.set(header.data, pos); + pos += header.length - encrypted.metadata.byteLength; + headerData.set(new Uint8Array(encrypted.metadata), pos); + return headerData.buffer; + } + /** + * Merge two {@link ArrayBuffer} instances. + * + * @param ab1 - First {@link ArrayBuffer}. + * @param ab2 - Second {@link ArrayBuffer}. + * + * @returns Merged data as {@link ArrayBuffer}. + */ + concatArrayBuffer(ab1, ab2) { + const tmp = new Uint8Array(ab1.byteLength + ab2.byteLength); + tmp.set(new Uint8Array(ab1), 0); + tmp.set(new Uint8Array(ab2), ab1.byteLength); + return tmp.buffer; + } + /** + * Retrieve file content. + * + * @param file - Content of the {@link PubNub} File object. + * + * @returns Normalized file {@link data} as {@link ArrayBuffer}; + */ + getFileData(file) { + return __awaiter(this, void 0, void 0, function* () { + if (file instanceof ArrayBuffer) + return file; + else if (file instanceof PubNubFile) + return file.toArrayBuffer(); + throw new Error('Cannot decrypt/encrypt file. In browsers file encrypt/decrypt supported for string, ArrayBuffer or Blob'); + }); + } + } + /** + * {@link LegacyCryptor|Legacy} cryptor identifier. + */ + WebCryptoModule.LEGACY_IDENTIFIER = ''; + /** + * CryptorHeader Utility + */ + class CryptorHeader { + static from(id, metadata) { + if (id === CryptorHeader.LEGACY_IDENTIFIER) + return; + return new CryptorHeaderV1(id, metadata.byteLength); + } + static tryParse(data) { + const encryptedData = new Uint8Array(data); + let sentinel; + let version = null; + if (encryptedData.byteLength >= 4) { + sentinel = encryptedData.slice(0, 4); + if (this.decoder.decode(sentinel) !== CryptorHeader.SENTINEL) + return WebCryptoModule.LEGACY_IDENTIFIER; + } + if (encryptedData.byteLength >= 5) + version = encryptedData[4]; + else + throw new Error('Decryption error: invalid header version'); + if (version > CryptorHeader.MAX_VERSION) + throw new Error('Decryption error: Unknown cryptor error'); + let identifier; + let pos = 5 + CryptorHeader.IDENTIFIER_LENGTH; + if (encryptedData.byteLength >= pos) + identifier = encryptedData.slice(5, pos); + else + throw new Error('Decryption error: invalid crypto identifier'); + let metadataLength = null; + if (encryptedData.byteLength >= pos + 1) + metadataLength = encryptedData[pos]; + else + throw new Error('Decryption error: invalid metadata length'); + pos += 1; + if (metadataLength === 255 && encryptedData.byteLength >= pos + 2) { + metadataLength = new Uint16Array(encryptedData.slice(pos, pos + 2)).reduce((acc, val) => (acc << 8) + val, 0); + } + return new CryptorHeaderV1(this.decoder.decode(identifier), metadataLength); + } + } + CryptorHeader.SENTINEL = 'PNED'; + CryptorHeader.LEGACY_IDENTIFIER = ''; + CryptorHeader.IDENTIFIER_LENGTH = 4; + CryptorHeader.VERSION = 1; + CryptorHeader.MAX_VERSION = 1; + CryptorHeader.decoder = new TextDecoder(); + // v1 CryptorHeader + class CryptorHeaderV1 { + constructor(id, metadataLength) { + this._identifier = id; + this._metadataLength = metadataLength; + } + get identifier() { + return this._identifier; + } + set identifier(value) { + this._identifier = value; + } + get metadataLength() { + return this._metadataLength; + } + set metadataLength(value) { + this._metadataLength = value; + } + get version() { + return CryptorHeader.VERSION; + } + get length() { + return (CryptorHeader.SENTINEL.length + + 1 + + CryptorHeader.IDENTIFIER_LENGTH + + (this.metadataLength < 255 ? 1 : 3) + + this.metadataLength); + } + get data() { + let pos = 0; + const header = new Uint8Array(this.length); + const encoder = new TextEncoder(); + header.set(encoder.encode(CryptorHeader.SENTINEL)); + pos += CryptorHeader.SENTINEL.length; + header[pos] = this.version; + pos++; + if (this.identifier) + header.set(encoder.encode(this.identifier), pos); + const metadataLength = this.metadataLength; + pos += CryptorHeader.IDENTIFIER_LENGTH; + if (metadataLength < 255) + header[pos] = metadataLength; + else + header.set([255, metadataLength >> 8, metadataLength & 0xff], pos); + return header; + } + } + CryptorHeaderV1.IDENTIFIER_LENGTH = 4; + CryptorHeaderV1.SENTINEL = 'PNED'; + + /** + * REST API endpoint use error module. + * + * @internal + */ + /** + * PubNub REST API call error. + * + * @internal + */ + class PubNubAPIError extends Error { + /** + * Construct API from known error object or {@link PubNub} service error response. + * + * @param errorOrResponse - `Error` or service error response object from which error information + * should be extracted. + * @param [data] - Preprocessed service error response. + * + * @returns `PubNubAPIError` object with known error category and additional information (if + * available). + */ + static create(errorOrResponse, data) { + if (PubNubAPIError.isErrorObject(errorOrResponse)) + return PubNubAPIError.createFromError(errorOrResponse); + else + return PubNubAPIError.createFromServiceResponse(errorOrResponse, data); + } + /** + * Create API error instance from other error object. + * + * @param error - `Error` object provided by network provider (mostly) or other {@link PubNub} client components. + * + * @returns `PubNubAPIError` object with known error category and additional information (if + * available). + */ + static createFromError(error) { + let category = StatusCategory$1.PNUnknownCategory; + let message = 'Unknown error'; + let errorName = 'Error'; + if (!error) + return new PubNubAPIError(message, category, 0); + else if (error instanceof PubNubAPIError) + return error; + if (PubNubAPIError.isErrorObject(error)) { + message = error.message; + errorName = error.name; + } + if (errorName === 'AbortError' || message.indexOf('Aborted') !== -1) { + category = StatusCategory$1.PNCancelledCategory; + message = 'Request cancelled'; + } + else if (message.toLowerCase().indexOf('timeout') !== -1) { + category = StatusCategory$1.PNTimeoutCategory; + message = 'Request timeout'; + } + else if (message.toLowerCase().indexOf('network') !== -1) { + category = StatusCategory$1.PNNetworkIssuesCategory; + message = 'Network issues'; + } + else if (errorName === 'TypeError') { + if (message.indexOf('Load failed') !== -1 || message.indexOf('Failed to fetch') != -1) + category = StatusCategory$1.PNNetworkIssuesCategory; + else + category = StatusCategory$1.PNBadRequestCategory; + } + else if (errorName === 'FetchError') { + const errorCode = error.code; + if (['ECONNREFUSED', 'ENETUNREACH', 'ENOTFOUND', 'ECONNRESET', 'EAI_AGAIN'].includes(errorCode)) + category = StatusCategory$1.PNNetworkIssuesCategory; + if (errorCode === 'ECONNREFUSED') + message = 'Connection refused'; + else if (errorCode === 'ENETUNREACH') + message = 'Network not reachable'; + else if (errorCode === 'ENOTFOUND') + message = 'Server not found'; + else if (errorCode === 'ECONNRESET') + message = 'Connection reset by peer'; + else if (errorCode === 'EAI_AGAIN') + message = 'Name resolution error'; + else if (errorCode === 'ETIMEDOUT') { + category = StatusCategory$1.PNTimeoutCategory; + message = 'Request timeout'; + } + else + message = `Unknown system error: ${error}`; + } + else if (message === 'Request timeout') + category = StatusCategory$1.PNTimeoutCategory; + return new PubNubAPIError(message, category, 0, error); + } + /** + * Construct API from known {@link PubNub} service error response. + * + * @param response - Service error response object from which error information should be + * extracted. + * @param [data] - Preprocessed service error response. + * + * @returns `PubNubAPIError` object with known error category and additional information (if + * available). + */ + static createFromServiceResponse(response, data) { + let category = StatusCategory$1.PNUnknownCategory; + let errorData; + let message = 'Unknown error'; + let { status } = response; + data !== null && data !== void 0 ? data : (data = response.body); + if (status === 402) + message = 'Not available for used key set. Contact support@pubnub.com'; + else if (status === 404) + message = 'Resource not found'; + else if (status === 400) { + category = StatusCategory$1.PNBadRequestCategory; + message = 'Bad request'; + } + else if (status === 403) { + category = StatusCategory$1.PNAccessDeniedCategory; + message = 'Access denied'; + } + else if (status >= 500) { + category = StatusCategory$1.PNServerErrorCategory; + message = 'Internal server error'; + } + if (typeof response === 'object' && Object.keys(response).length === 0) { + category = StatusCategory$1.PNMalformedResponseCategory; + message = 'Malformed response (network issues)'; + status = 400; + } + // Try to get more information about error from service response. + if (data && data.byteLength > 0) { + const decoded = new TextDecoder().decode(data); + if (response.headers['content-type'].indexOf('text/javascript') !== -1 || + response.headers['content-type'].indexOf('application/json') !== -1) { + try { + const errorResponse = JSON.parse(decoded); + if (typeof errorResponse === 'object') { + if (!Array.isArray(errorResponse)) { + if ('error' in errorResponse && + (errorResponse.error === 1 || errorResponse.error === true) && + 'status' in errorResponse && + typeof errorResponse.status === 'number' && + 'message' in errorResponse && + 'service' in errorResponse) { + errorData = errorResponse; + status = errorResponse.status; + } + else + errorData = errorResponse; + if ('error' in errorResponse && errorResponse.error instanceof Error) + errorData = errorResponse.error; + } + else { + // Handling Publish API payload error. + if (typeof errorResponse[0] === 'number' && errorResponse[0] === 0) { + if (errorResponse.length > 1 && typeof errorResponse[1] === 'string') + errorData = errorResponse[1]; + } + } + } + } + catch (_) { + errorData = decoded; + } + } + else if (response.headers['content-type'].indexOf('xml') !== -1) { + const reason = /(.*)<\/Message>/gi.exec(decoded); + message = reason ? `Upload to bucket failed: ${reason[1]}` : 'Upload to bucket failed.'; + } + else { + errorData = decoded; + } + } + return new PubNubAPIError(message, category, status, errorData); + } + /** + * Construct PubNub endpoint error. + * + * @param message - Short API call error description. + * @param category - Error category. + * @param statusCode - Response HTTP status code. + * @param [errorData] - Error information. + */ + constructor(message, category, statusCode, errorData) { + super(message); + this.category = category; + this.statusCode = statusCode; + this.errorData = errorData; + this.name = 'PubNubAPIError'; + } + /** + * Convert API error object to API callback status object. + * + * @param operation - Request operation during which error happened. + * + * @returns Pre-formatted API callback status object. + */ + toStatus(operation) { + return { + error: true, + category: this.category, + operation, + statusCode: this.statusCode, + errorData: this.errorData, + // @ts-expect-error Inner helper for JSON.stringify. + toJSON: function () { + let normalizedErrorData; + const errorData = this.errorData; + if (errorData) { + try { + if (typeof errorData === 'object') { + const errorObject = Object.assign(Object.assign(Object.assign(Object.assign({}, ('name' in errorData ? { name: errorData.name } : {})), ('message' in errorData ? { message: errorData.message } : {})), ('stack' in errorData ? { stack: errorData.stack } : {})), errorData); + normalizedErrorData = JSON.parse(JSON.stringify(errorObject, PubNubAPIError.circularReplacer())); + } + else + normalizedErrorData = errorData; + } + catch (_) { + normalizedErrorData = { error: 'Could not serialize the error object' }; + } + } + // Make sure to exclude `toJSON` function from the final object. + const _a = this, status = __rest(_a, ["toJSON"]); + return JSON.stringify(Object.assign(Object.assign({}, status), { errorData: normalizedErrorData })); + }, + }; + } + /** + * Convert API error object to PubNub client error object. + * + * @param operation - Request operation during which error happened. + * @param [message] - Custom error message. + * + * @returns Client-facing pre-formatted endpoint call error. + */ + toPubNubError(operation, message) { + return new PubNubError(message !== null && message !== void 0 ? message : this.message, this.toStatus(operation)); + } + /** + * Function which handles circular references in serialized JSON. + * + * @returns Circular reference replacer function. + * + * @internal + */ + static circularReplacer() { + const visited = new WeakSet(); + return function (_, value) { + if (typeof value === 'object' && value !== null) { + if (visited.has(value)) + return '[Circular]'; + visited.add(value); + } + return value; + }; + } + /** + * Check whether provided `object` is an `Error` or not. + * + * This check is required because the error object may be tied to a different execution context (global + * environment) and won't pass `instanceof Error` from the main window. + * To protect against monkey-patching, the `fetch` function is taken from an invisible `iframe` and, as a result, + * it is bind to the separate execution context. Errors generated by `fetch` won't pass the simple + * `instanceof Error` test. + * + * @param object - Object which should be checked. + * + * @returns `true` if `object` looks like an `Error` object. + * + * @internal + */ + static isErrorObject(object) { + if (!object || typeof object !== 'object') + return false; + if (object instanceof Error) + return true; + if ('name' in object && + 'message' in object && + typeof object.name === 'string' && + typeof object.message === 'string') { + return true; + } + return Object.prototype.toString.call(object) === '[object Error]'; + } + } + + /** + * Endpoint API operation types. + */ + var RequestOperation; + (function (RequestOperation) { + // -------------------------------------------------------- + // ---------------------- Publish API --------------------- + // -------------------------------------------------------- + /** + * Data publish REST API operation. + */ + RequestOperation["PNPublishOperation"] = "PNPublishOperation"; + /** + * Signal sending REST API operation. + */ + RequestOperation["PNSignalOperation"] = "PNSignalOperation"; + // -------------------------------------------------------- + // --------------------- Subscribe API -------------------- + // -------------------------------------------------------- + /** + * Subscribe for real-time updates REST API operation. + * + * User's presence change on specified entities will trigger `join` event. + */ + RequestOperation["PNSubscribeOperation"] = "PNSubscribeOperation"; + /** + * Unsubscribe from real-time updates REST API operation. + * + * User's presence change on specified entities will trigger `leave` event. + */ + RequestOperation["PNUnsubscribeOperation"] = "PNUnsubscribeOperation"; + // -------------------------------------------------------- + // --------------------- Presence API --------------------- + // -------------------------------------------------------- + /** + * Fetch user's presence information REST API operation. + */ + RequestOperation["PNWhereNowOperation"] = "PNWhereNowOperation"; + /** + * Fetch channel's presence information REST API operation. + */ + RequestOperation["PNHereNowOperation"] = "PNHereNowOperation"; + /** + * Fetch global presence information REST API operation. + */ + RequestOperation["PNGlobalHereNowOperation"] = "PNGlobalHereNowOperation"; + /** + * Update user's information associated with specified channel REST API operation. + */ + RequestOperation["PNSetStateOperation"] = "PNSetStateOperation"; + /** + * Fetch user's information associated with the specified channel REST API operation. + */ + RequestOperation["PNGetStateOperation"] = "PNGetStateOperation"; + /** + * Announce presence on managed channels REST API operation. + */ + RequestOperation["PNHeartbeatOperation"] = "PNHeartbeatOperation"; + // -------------------------------------------------------- + // ----------------- Message Reaction API ----------------- + // -------------------------------------------------------- + /** + * Add a reaction to the specified message REST API operation. + */ + RequestOperation["PNAddMessageActionOperation"] = "PNAddActionOperation"; + /** + * Remove reaction from the specified message REST API operation. + */ + RequestOperation["PNRemoveMessageActionOperation"] = "PNRemoveMessageActionOperation"; + /** + * Fetch reactions for specific message REST API operation. + */ + RequestOperation["PNGetMessageActionsOperation"] = "PNGetMessageActionsOperation"; + RequestOperation["PNTimeOperation"] = "PNTimeOperation"; + // -------------------------------------------------------- + // ---------------------- Storage API --------------------- + // -------------------------------------------------------- + /** + * Channel history REST API operation. + */ + RequestOperation["PNHistoryOperation"] = "PNHistoryOperation"; + /** + * Delete messages from channel history REST API operation. + */ + RequestOperation["PNDeleteMessagesOperation"] = "PNDeleteMessagesOperation"; + /** + * History for channels REST API operation. + */ + RequestOperation["PNFetchMessagesOperation"] = "PNFetchMessagesOperation"; + /** + * Number of messages for channels in specified time frame REST API operation. + */ + RequestOperation["PNMessageCounts"] = "PNMessageCountsOperation"; + // -------------------------------------------------------- + // -------------------- App Context API ------------------- + // -------------------------------------------------------- + /** + * Fetch users metadata REST API operation. + */ + RequestOperation["PNGetAllUUIDMetadataOperation"] = "PNGetAllUUIDMetadataOperation"; + /** + * Fetch user metadata REST API operation. + */ + RequestOperation["PNGetUUIDMetadataOperation"] = "PNGetUUIDMetadataOperation"; + /** + * Set user metadata REST API operation. + */ + RequestOperation["PNSetUUIDMetadataOperation"] = "PNSetUUIDMetadataOperation"; + /** + * Remove user metadata REST API operation. + */ + RequestOperation["PNRemoveUUIDMetadataOperation"] = "PNRemoveUUIDMetadataOperation"; + /** + * Fetch channels metadata REST API operation. + */ + RequestOperation["PNGetAllChannelMetadataOperation"] = "PNGetAllChannelMetadataOperation"; + /** + * Fetch channel metadata REST API operation. + */ + RequestOperation["PNGetChannelMetadataOperation"] = "PNGetChannelMetadataOperation"; + /** + * Set channel metadata REST API operation. + */ + RequestOperation["PNSetChannelMetadataOperation"] = "PNSetChannelMetadataOperation"; + /** + * Remove channel metadata REST API operation. + */ + RequestOperation["PNRemoveChannelMetadataOperation"] = "PNRemoveChannelMetadataOperation"; + /** + * Fetch channel members REST API operation. + */ + RequestOperation["PNGetMembersOperation"] = "PNGetMembersOperation"; + /** + * Update channel members REST API operation. + */ + RequestOperation["PNSetMembersOperation"] = "PNSetMembersOperation"; + /** + * Fetch channel memberships REST API operation. + */ + RequestOperation["PNGetMembershipsOperation"] = "PNGetMembershipsOperation"; + /** + * Update channel memberships REST API operation. + */ + RequestOperation["PNSetMembershipsOperation"] = "PNSetMembershipsOperation"; + // -------------------------------------------------------- + // ------------------- DataSync API ---------------------- + // -------------------------------------------------------- + /** + * Create entity REST API operation. + */ + RequestOperation["PNCreateDataSyncEntityOperation"] = "PNCreateDataSyncEntityOperation"; + /** + * Get entity REST API operation. + */ + RequestOperation["PNGetDataSyncEntityOperation"] = "PNGetDataSyncEntityOperation"; + /** + * Get all entities REST API operation. + */ + RequestOperation["PNGetDataSyncEntitiesOperation"] = "PNGetDataSyncEntitiesOperation"; + /** + * Set entity REST API operation (full replacement via PUT). + */ + RequestOperation["PNSetDataSyncEntityOperation"] = "PNSetDataSyncEntityOperation"; + /** + * Update entity REST API operation (partial update via PATCH). + */ + RequestOperation["PNUpdateDataSyncEntityOperation"] = "PNUpdateDataSyncEntityOperation"; + /** + * Remove entity REST API operation. + */ + RequestOperation["PNRemoveDataSyncEntityOperation"] = "PNRemoveDataSyncEntityOperation"; + /** + * Create relationship REST API operation. + */ + RequestOperation["PNCreateDataSyncRelationshipOperation"] = "PNCreateDataSyncRelationshipOperation"; + /** + * Get relationship REST API operation. + */ + RequestOperation["PNGetDataSyncRelationshipOperation"] = "PNGetDataSyncRelationshipOperation"; + /** + * Get all relationships REST API operation. + */ + RequestOperation["PNGetDataSyncRelationshipsOperation"] = "PNGetDataSyncRelationshipsOperation"; + /** + * Set relationship REST API operation (full replacement via PUT). + */ + RequestOperation["PNSetDataSyncRelationshipOperation"] = "PNSetDataSyncRelationshipOperation"; + /** + * Update relationship REST API operation (partial update via PATCH). + */ + RequestOperation["PNUpdateDataSyncRelationshipOperation"] = "PNUpdateDataSyncRelationshipOperation"; + /** + * Remove relationship REST API operation. + */ + RequestOperation["PNRemoveDataSyncRelationshipOperation"] = "PNRemoveDataSyncRelationshipOperation"; + /** + * Create user REST API operation. + */ + RequestOperation["PNCreateDataSyncUserOperation"] = "PNCreateDataSyncUserOperation"; + /** + * Get user REST API operation. + */ + RequestOperation["PNGetDataSyncUserOperation"] = "PNGetDataSyncUserOperation"; + /** + * Get all users REST API operation. + */ + RequestOperation["PNGetDataSyncUsersOperation"] = "PNGetDataSyncUsersOperation"; + /** + * Set user REST API operation (full replacement via PUT). + */ + RequestOperation["PNSetDataSyncUserOperation"] = "PNSetDataSyncUserOperation"; + /** + * Update user REST API operation (partial update via PATCH). + */ + RequestOperation["PNUpdateDataSyncUserOperation"] = "PNUpdateDataSyncUserOperation"; + /** + * Remove user REST API operation. + */ + RequestOperation["PNRemoveDataSyncUserOperation"] = "PNRemoveDataSyncUserOperation"; + /** + * Create channel REST API operation. + */ + RequestOperation["PNCreateDataSyncChannelOperation"] = "PNCreateDataSyncChannelOperation"; + /** + * Get channel REST API operation. + */ + RequestOperation["PNGetDataSyncChannelOperation"] = "PNGetDataSyncChannelOperation"; + /** + * Get all channels REST API operation. + */ + RequestOperation["PNGetDataSyncChannelsOperation"] = "PNGetDataSyncChannelsOperation"; + /** + * Set channel REST API operation (full replacement via PUT). + */ + RequestOperation["PNSetDataSyncChannelOperation"] = "PNSetDataSyncChannelOperation"; + /** + * Update channel REST API operation (partial update via PATCH). + */ + RequestOperation["PNUpdateDataSyncChannelOperation"] = "PNUpdateDataSyncChannelOperation"; + /** + * Remove channel REST API operation. + */ + RequestOperation["PNRemoveDataSyncChannelOperation"] = "PNRemoveDataSyncChannelOperation"; + /** + * Create membership REST API operation. + */ + RequestOperation["PNCreateDataSyncMembershipOperation"] = "PNCreateDataSyncMembershipOperation"; + /** + * Get membership REST API operation. + */ + RequestOperation["PNGetDataSyncMembershipOperation"] = "PNGetDataSyncMembershipOperation"; + /** + * Get all memberships REST API operation. + */ + RequestOperation["PNGetDataSyncMembershipsOperation"] = "PNGetDataSyncMembershipsOperation"; + /** + * Set membership REST API operation (full replacement via PUT). + */ + RequestOperation["PNSetDataSyncMembershipOperation"] = "PNSetDataSyncMembershipOperation"; + /** + * Update membership REST API operation (partial update via PATCH). + */ + RequestOperation["PNUpdateDataSyncMembershipOperation"] = "PNUpdateDataSyncMembershipOperation"; + /** + * Remove membership REST API operation. + */ + RequestOperation["PNRemoveDataSyncMembershipOperation"] = "PNRemoveDataSyncMembershipOperation"; + // -------------------------------------------------------- + // -------------------- File Upload API ------------------- + // -------------------------------------------------------- + /** + * Fetch list of files sent to the channel REST API operation. + */ + RequestOperation["PNListFilesOperation"] = "PNListFilesOperation"; + /** + * Retrieve file upload URL REST API operation. + */ + RequestOperation["PNGenerateUploadUrlOperation"] = "PNGenerateUploadUrlOperation"; + /** + * Upload file to the channel REST API operation. + */ + RequestOperation["PNPublishFileOperation"] = "PNPublishFileOperation"; + /** + * Publish File Message to the channel REST API operation. + */ + RequestOperation["PNPublishFileMessageOperation"] = "PNPublishFileMessageOperation"; + /** + * Retrieve file download URL REST API operation. + */ + RequestOperation["PNGetFileUrlOperation"] = "PNGetFileUrlOperation"; + /** + * Download file from the channel REST API operation. + */ + RequestOperation["PNDownloadFileOperation"] = "PNDownloadFileOperation"; + /** + * Delete file sent to the channel REST API operation. + */ + RequestOperation["PNDeleteFileOperation"] = "PNDeleteFileOperation"; + // -------------------------------------------------------- + // -------------------- Mobile Push API ------------------- + // -------------------------------------------------------- + /** + * Register channels with device push notifications REST API operation. + */ + RequestOperation["PNAddPushNotificationEnabledChannelsOperation"] = "PNAddPushNotificationEnabledChannelsOperation"; + /** + * Unregister channels with device push notifications REST API operation. + */ + RequestOperation["PNRemovePushNotificationEnabledChannelsOperation"] = "PNRemovePushNotificationEnabledChannelsOperation"; + /** + * Fetch list of channels with enabled push notifications for device REST API operation. + */ + RequestOperation["PNPushNotificationEnabledChannelsOperation"] = "PNPushNotificationEnabledChannelsOperation"; + /** + * Disable push notifications for device REST API operation. + */ + RequestOperation["PNRemoveAllPushNotificationsOperation"] = "PNRemoveAllPushNotificationsOperation"; + // -------------------------------------------------------- + // ------------------ Channel Groups API ------------------ + // -------------------------------------------------------- + /** + * Fetch channels groups list REST API operation. + */ + RequestOperation["PNChannelGroupsOperation"] = "PNChannelGroupsOperation"; + /** + * Remove specified channel group REST API operation. + */ + RequestOperation["PNRemoveGroupOperation"] = "PNRemoveGroupOperation"; + /** + * Fetch list of channels for the specified channel group REST API operation. + */ + RequestOperation["PNChannelsForGroupOperation"] = "PNChannelsForGroupOperation"; + /** + * Add list of channels to the specified channel group REST API operation. + */ + RequestOperation["PNAddChannelsToGroupOperation"] = "PNAddChannelsToGroupOperation"; + /** + * Remove list of channels from the specified channel group REST API operation. + */ + RequestOperation["PNRemoveChannelsFromGroupOperation"] = "PNRemoveChannelsFromGroupOperation"; + // -------------------------------------------------------- + // ----------------------- PAM API ------------------------ + // -------------------------------------------------------- + /** + * Generate authorized token REST API operation. + */ + RequestOperation["PNAccessManagerGrant"] = "PNAccessManagerGrant"; + /** + * Generate authorized token REST API operation. + */ + RequestOperation["PNAccessManagerGrantToken"] = "PNAccessManagerGrantToken"; + RequestOperation["PNAccessManagerAudit"] = "PNAccessManagerAudit"; + /** + * Revoke authorized token REST API operation. + */ + RequestOperation["PNAccessManagerRevokeToken"] = "PNAccessManagerRevokeToken"; + // + // -------------------------------------------------------- + // ---------------- Subscription Utility ------------------ + // -------------------------------------------------------- + /** + * Initial event engine subscription handshake operation. + * + * @internal + */ + RequestOperation["PNHandshakeOperation"] = "PNHandshakeOperation"; + /** + * Event engine subscription loop operation. + * + * @internal + */ + RequestOperation["PNReceiveMessagesOperation"] = "PNReceiveMessagesOperation"; + })(RequestOperation || (RequestOperation = {})); + var RequestOperation$1 = RequestOperation; + + /** + * Subscription Worker transport middleware module. + * + * Middleware optimize subscription feature requests utilizing `Subscription Worker` if available and not disabled + * by user. + * + * @internal + */ + // endregion + /** + * Subscription Worker transport middleware. + */ + class SubscriptionWorkerMiddleware { + constructor(configuration) { + this.configuration = configuration; + /** + * Whether subscription worker has been initialized and ready to handle events. + */ + this.subscriptionWorkerReady = false; + /** + * Map of base64-encoded access tokens to their parsed representations. + */ + this.accessTokensMap = {}; + this.workerEventsQueue = []; + this.callbacks = new Map(); + this.setupSubscriptionWorker(); + } + /** + * Set status emitter from the PubNub client. + * + * @param emitter - Function which should be used to emit events. + */ + set emitStatus(emitter) { + this._emitStatus = emitter; + } + /** + * Update client's `userId`. + * + * @param userId - User ID which will be used by the PubNub client further. + */ + onUserIdChange(userId) { + this.configuration.userId = userId; + this.scheduleEventPost({ + type: 'client-update', + heartbeatInterval: this.configuration.heartbeatInterval, + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + userId: this.configuration.userId, + workerLogLevel: this.configuration.workerLogLevel, + }); + } + /** + * Update presence state associated with `userId`. + * + * @param state - Key-value pair of payloads (states) that should be associated with channels / groups specified as + * keys. + */ + onPresenceStateChange(state) { + this.scheduleEventPost({ + type: 'client-presence-state-update', + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + workerLogLevel: this.configuration.workerLogLevel, + state, + }); + } + /** + * Update client's heartbeat interval change. + * + * @param interval - Interval which should be used by timers for _backup_ heartbeat calls created in `SharedWorker`. + */ + onHeartbeatIntervalChange(interval) { + this.configuration.heartbeatInterval = interval; + this.scheduleEventPost({ + type: 'client-update', + heartbeatInterval: this.configuration.heartbeatInterval, + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + userId: this.configuration.userId, + workerLogLevel: this.configuration.workerLogLevel, + }); + } + /** + * Handle authorization key / token change. + * + * @param [token] - Authorization token which should be used. + */ + onTokenChange(token) { + const updateEvent = { + type: 'client-update', + heartbeatInterval: this.configuration.heartbeatInterval, + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + userId: this.configuration.userId, + workerLogLevel: this.configuration.workerLogLevel, + }; + // Trigger request processing by Service Worker. + this.parsedAccessToken(token) + .then((accessToken) => { + updateEvent.preProcessedToken = accessToken; + updateEvent.accessToken = token; + }) + .then(() => this.scheduleEventPost(updateEvent)); + } + /** + * Disconnect client and terminate ongoing long-poll requests (if needed). + */ + disconnect() { + this.scheduleEventPost({ + type: 'client-disconnect', + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + workerLogLevel: this.configuration.workerLogLevel, + }); + } + /** + * Terminate all ongoing long-poll requests. + */ + terminate() { + this.scheduleEventPost({ + type: 'client-unregister', + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + workerLogLevel: this.configuration.workerLogLevel, + }); + } + makeSendable(req) { + // Use default request flow for non-subscribe / presence leave requests. + if (!req.path.startsWith('/v2/subscribe') && !req.path.endsWith('/heartbeat') && !req.path.endsWith('/leave')) + return this.configuration.transport.makeSendable(req); + this.configuration.logger.debug('SubscriptionWorkerMiddleware', 'Process request with SharedWorker transport.'); + let controller; + const sendRequestEvent = { + type: 'send-request', + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + request: req, + workerLogLevel: this.configuration.workerLogLevel, + }; + if (req.cancellable) { + controller = { + abort: () => { + const cancelRequest = { + type: 'cancel-request', + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + identifier: req.identifier, + workerLogLevel: this.configuration.workerLogLevel, + }; + // Cancel active request with specified identifier. + this.scheduleEventPost(cancelRequest); + }, + }; + } + return [ + new Promise((resolve, reject) => { + // Associate Promise resolution / reject with a request identifier for future usage in + // the `onmessage ` handler block to return results. + this.callbacks.set(req.identifier, { resolve, reject }); + // Trigger request processing by Service Worker. + this.parsedAccessTokenForRequest(req) + .then((accessToken) => (sendRequestEvent.preProcessedToken = accessToken)) + .then(() => this.scheduleEventPost(sendRequestEvent)); + }), + controller, + ]; + } + request(req) { + return req; + } + /** + * Schedule {@link event} publish to the subscription worker. + * + * Subscription worker may not be ready for events processing and this method build queue for the time when worker + * will be ready. + * + * @param event - Event payload for the subscription worker. + * @param outOfOrder - Whether event should be processed first then enqueued queue. + */ + scheduleEventPost(event, outOfOrder = false) { + // Trigger request processing by a subscription worker. + const subscriptionWorker = this.sharedSubscriptionWorker; + if (subscriptionWorker) + subscriptionWorker.port.postMessage(event); + else { + if (outOfOrder) + this.workerEventsQueue.splice(0, 0, event); + else + this.workerEventsQueue.push(event); + } + } + /** + * Dequeue and post events from the queue to the subscription worker. + */ + flushScheduledEvents() { + // Trigger request processing by a subscription worker. + const subscriptionWorker = this.sharedSubscriptionWorker; + if (!subscriptionWorker || this.workerEventsQueue.length === 0) + return; + // Clean up from canceled events. + const outdatedEvents = []; + for (let i = 0; i < this.workerEventsQueue.length; i++) { + const event = this.workerEventsQueue[i]; + // Check whether found request cancel event to search for request send event it cancels. + if (event.type !== 'cancel-request' || i === 0) + continue; + for (let j = 0; j < i; j++) { + const otherEvent = this.workerEventsQueue[j]; + if (otherEvent.type !== 'send-request') + continue; + // Collect outdated events if identifiers match. + if (otherEvent.request.identifier === event.identifier) { + outdatedEvents.push(event, otherEvent); + break; + } + } + } + // Actualizing events queue. + this.workerEventsQueue = this.workerEventsQueue.filter((event) => !outdatedEvents.includes(event)); + this.workerEventsQueue.forEach((event) => subscriptionWorker.port.postMessage(event)); + this.workerEventsQueue = []; + } + /** + * Subscription worker. + * + * @returns Worker which has been registered by the PubNub SDK. + */ + get sharedSubscriptionWorker() { + return this.subscriptionWorkerReady ? this.subscriptionWorker : null; + } + setupSubscriptionWorker() { + if (typeof SharedWorker === 'undefined') + return; + try { + this.subscriptionWorker = new SharedWorker(this.configuration.workerUrl, `/pubnub-${this.configuration.sdkVersion}`); + } + catch (error) { + this.configuration.logger.error('SubscriptionWorkerMiddleware', () => ({ + messageType: 'error', + message: error, + })); + throw error; + } + this.subscriptionWorker.port.start(); + // Register PubNub client within subscription worker. + this.scheduleEventPost({ + type: 'client-register', + clientIdentifier: this.configuration.clientIdentifier, + subscriptionKey: this.configuration.subscriptionKey, + userId: this.configuration.userId, + heartbeatInterval: this.configuration.heartbeatInterval, + workerOfflineClientsCheckInterval: this.configuration.workerOfflineClientsCheckInterval, + workerUnsubscribeOfflineClients: this.configuration.workerUnsubscribeOfflineClients, + workerLogLevel: this.configuration.workerLogLevel, + }, true); + this.subscriptionWorker.port.onmessage = (event) => this.handleWorkerEvent(event); + if (this.shouldAnnounceNewerSharedWorkerVersionAvailability()) + localStorage.setItem('PNSubscriptionSharedWorkerVersion', this.configuration.sdkVersion); + window.addEventListener('storage', (event) => { + if (event.key !== 'PNSubscriptionSharedWorkerVersion' || !event.newValue) + return; + if (this._emitStatus && this.isNewerSharedWorkerVersion(event.newValue)) + this._emitStatus({ error: false, category: StatusCategory$1.PNSharedWorkerUpdatedCategory }); + }); + } + handleWorkerEvent(event) { + const { data } = event; + // Ignoring updates not related to this instance. + if (data.type !== 'shared-worker-ping' && + data.type !== 'shared-worker-connected' && + data.type !== 'shared-worker-console-log' && + data.type !== 'shared-worker-console-dir' && + data.clientIdentifier !== this.configuration.clientIdentifier) + return; + if (data.type === 'shared-worker-connected') { + this.configuration.logger.trace('SharedWorker', 'Ready for events processing.'); + this.subscriptionWorkerReady = true; + this.flushScheduledEvents(); + } + else if (data.type === 'shared-worker-console-log') { + this.configuration.logger.debug('SharedWorker', () => { + if (typeof data.message === 'string' || typeof data.message === 'number' || typeof data.message === 'boolean') { + return { + messageType: 'text', + message: data.message, + }; + } + return data.message; + }); + } + else if (data.type === 'shared-worker-console-dir') { + this.configuration.logger.debug('SharedWorker', () => { + return { + messageType: 'object', + message: data.data, + details: data.message ? data.message : undefined, + }; + }); + } + else if (data.type === 'shared-worker-ping') { + const { subscriptionKey, clientIdentifier } = this.configuration; + this.scheduleEventPost({ + type: 'client-pong', + subscriptionKey, + clientIdentifier, + workerLogLevel: this.configuration.workerLogLevel, + }); + } + else if (data.type === 'request-process-success' || data.type === 'request-process-error') { + if (this.callbacks.has(data.identifier)) { + const { resolve, reject } = this.callbacks.get(data.identifier); + this.callbacks.delete(data.identifier); + if (data.type === 'request-process-success') { + resolve({ + status: data.response.status, + url: data.url, + headers: data.response.headers, + body: data.response.body, + }); + } + else + reject(this.errorFromRequestSendingError(data)); + } + // Handling "backup" heartbeat which doesn't have registered callbacks. + else if (this._emitStatus && data.url.indexOf('/v2/presence') >= 0 && data.url.indexOf('/heartbeat') >= 0) { + if (data.type === 'request-process-success' && this.configuration.announceSuccessfulHeartbeats) { + this._emitStatus({ + statusCode: data.response.status, + error: false, + operation: RequestOperation$1.PNHeartbeatOperation, + category: StatusCategory$1.PNAcknowledgmentCategory, + }); + } + else if (data.type === 'request-process-error' && this.configuration.announceFailedHeartbeats) + this._emitStatus(this.errorFromRequestSendingError(data).toStatus(RequestOperation$1.PNHeartbeatOperation)); + } + } + } + /** + * Get parsed access token object from request. + * + * @param req - Transport request which may contain access token for processing. + * + * @returns Object with stringified access token information and expiration date information. + */ + parsedAccessTokenForRequest(req) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + return this.parsedAccessToken(req.queryParameters ? ((_a = req.queryParameters.auth) !== null && _a !== void 0 ? _a : '') : undefined); + }); + } + /** + * Get parsed access token object. + * + * @param accessToken - Access token for processing. + * + * @returns Object with stringified access token information and expiration date information. + */ + parsedAccessToken(accessToken) { + return __awaiter(this, void 0, void 0, function* () { + if (!accessToken) + return undefined; + else if (this.accessTokensMap[accessToken]) + return this.accessTokensMap[accessToken]; + return this.stringifyAccessToken(accessToken).then(([token, stringifiedToken]) => { + if (!token || !stringifiedToken) + return undefined; + return (this.accessTokensMap = { + [accessToken]: { token: stringifiedToken, expiration: token.timestamp + token.ttl * 60 }, + })[accessToken]; + }); + }); + } + /** + * Stringify access token content. + * + * Stringify information about resources with permissions. + * + * @param tokenString - Base64-encoded access token which should be parsed and stringified. + * + * @returns Tuple with parsed access token and its stringified content hash string. + */ + stringifyAccessToken(tokenString) { + return __awaiter(this, void 0, void 0, function* () { + if (!this.configuration.tokenManager) + return [undefined, undefined]; + const token = this.configuration.tokenManager.parseToken(tokenString); + if (!token) + return [undefined, undefined]; + // Translate permission to short string built from first chars of enabled permission. + const stringifyPermissions = (permission) => Object.entries(permission) + .filter(([_, v]) => v) + .map(([k]) => k[0]) + .sort() + .join(''); + const stringifyResources = (resource) => resource + ? Object.entries(resource) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([type, entries]) => Object.entries(entries || {}) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([name, perms]) => `${type}:${name}=${perms ? stringifyPermissions(perms) : ''}`) + .join(',')) + .join(';') + : ''; + let accessToken = [stringifyResources(token.resources), stringifyResources(token.patterns), token.authorized_uuid] + .filter(Boolean) + .join('|'); + if (typeof crypto !== 'undefined' && crypto.subtle) { + const hash = yield crypto.subtle.digest('SHA-256', new TextEncoder().encode(accessToken)); + accessToken = String.fromCharCode(...Array.from(new Uint8Array(hash))); + } + return [token, typeof btoa !== 'undefined' ? btoa(accessToken) : accessToken]; + }); + } + /** + * Create error from failure received from the `SharedWorker`. + * + * @param sendingError - Request sending error received from the `SharedWorker`. + * + * @returns `PubNubAPIError` instance with request processing failure information. + */ + errorFromRequestSendingError(sendingError) { + let category = StatusCategory$1.PNUnknownCategory; + let message = 'Unknown error'; + // Handle client-side issues (if any). + if (sendingError.error) { + if (sendingError.error.type === 'NETWORK_ISSUE') + category = StatusCategory$1.PNNetworkIssuesCategory; + else if (sendingError.error.type === 'TIMEOUT') + category = StatusCategory$1.PNTimeoutCategory; + else if (sendingError.error.type === 'ABORTED') + category = StatusCategory$1.PNCancelledCategory; + message = `${sendingError.error.message} (${sendingError.identifier})`; + } + // Handle service error response. + else if (sendingError.response) { + const { url, response } = sendingError; + return PubNubAPIError.create({ url, headers: response.headers, body: response.body, status: response.status }, response.body); + } + return new PubNubAPIError(message, category, 0, new Error(message)); + } + /** + * Check whether current subscription `SharedWorker` version should be announced or not. + * + * @returns `true` if local storage is empty (only newer version will add value) or stored version is smaller than + * current. + */ + shouldAnnounceNewerSharedWorkerVersionAvailability() { + const version = localStorage.getItem('PNSubscriptionSharedWorkerVersion'); + if (!version) + return true; + return !this.isNewerSharedWorkerVersion(version); + } + /** + * Check whether current subscription `SharedWorker` version should be announced or not. + * + * @param version - Stored (received on init or event) version of subscription shared worker. + * @returns `true` if provided `version` is newer than current client version. + */ + isNewerSharedWorkerVersion(version) { + const [currentMajor, currentMinor, currentPatch] = this.configuration.sdkVersion.split('.').map(Number); + const [storedMajor, storedMinor, storedPatch] = version.split('.').map(Number); + return storedMajor > currentMajor || storedMinor > currentMinor || storedPatch > currentPatch; + } + } + + /** + * CBOR support module. + * + * @internal + */ + /** + * Re-map CBOR object keys from potentially C buffer strings to actual strings. + * + * @param obj CBOR which should be remapped to stringified keys. + * @param nestingLevel PAM token structure nesting level. + * + * @returns Dictionary with stringified keys. + * + * @internal + */ + function stringifyBufferKeys(obj, nestingLevel = 0) { + const isObject = (value) => typeof value === 'object' && value !== null && value.constructor === Object; + const isString = (value) => typeof value === 'string' || value instanceof String; + const isNumber = (value) => typeof value === 'number' && isFinite(value); + if (!isObject(obj)) + return obj; + const normalizedObject = {}; + Object.keys(obj).forEach((key) => { + const keyIsString = isString(key); + let stringifiedKey = key; + const value = obj[key]; + if (nestingLevel < 2) { + if (keyIsString && key.indexOf(',') >= 0) { + const bytes = key.split(',').map(Number); + stringifiedKey = bytes.reduce((string, byte) => { + return string + String.fromCharCode(byte); + }, ''); + } + else if (isNumber(key) || (keyIsString && !isNaN(Number(key)))) { + stringifiedKey = String.fromCharCode(isNumber(key) ? key : parseInt(key, 10)); + } + } + normalizedObject[stringifiedKey] = isObject(value) ? stringifyBufferKeys(value, nestingLevel + 1) : value; + }); + return normalizedObject; + } + + /** + * {@link PubNub} client configuration module. + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether secured connection should be used by or not. + */ + const USE_SSL = true; + /** + * Whether PubNub client should catch up subscription after network issues. + */ + const RESTORE = true; + /** + * Whether network availability change should be announced with `PNNetworkDownCategory` and + * `PNNetworkUpCategory` state or not. + */ + const AUTO_NETWORK_DETECTION = false; + /** + * Whether messages should be de-duplicated before announcement or not. + */ + const DEDUPE_ON_SUBSCRIBE = false; + /** + * Maximum cache which should be used for message de-duplication functionality. + */ + const DEDUPE_CACHE_SIZE = 100; + /** + * Maximum number of file message publish retries. + */ + const FILE_PUBLISH_RETRY_LIMIT = 5; + /** + * Whether subscription event engine should be used or not. + */ + const ENABLE_EVENT_ENGINE = true; + /** + * Whether configured user presence state should be maintained by the PubNub client or not. + */ + const MAINTAIN_PRESENCE_STATE = true; + /** + * Whether heartbeat should be postponed on successful subscribe response or not. + */ + const USE_SMART_HEARTBEAT = false; + /** + * Whether PubNub client should try to utilize existing TCP connection for new requests or not. + */ + const KEEP_ALIVE$1 = false; + /** + * Whether leave events should be suppressed or not. + */ + const SUPPRESS_LEAVE_EVENTS = false; + /** + * Whether heartbeat request failure should be announced or not. + */ + const ANNOUNCE_HEARTBEAT_FAILURE = true; + /** + * Whether heartbeat request success should be announced or not. + */ + const ANNOUNCE_HEARTBEAT_SUCCESS = false; + /** + * Whether PubNub client instance id should be added to the requests or not. + */ + const USE_INSTANCE_ID = false; + /** + * Whether unique identifier should be added to the request or not. + */ + const USE_REQUEST_ID = true; + /** + * Transactional requests timeout. + */ + const TRANSACTIONAL_REQUEST_TIMEOUT = 15; + /** + * Subscription request timeout. + */ + const SUBSCRIBE_REQUEST_TIMEOUT = 310; + /** + * File upload / download request timeout. + */ + const FILE_REQUEST_TIMEOUT = 300; + /** + * Default user presence timeout. + */ + const PRESENCE_TIMEOUT = 300; + /** + * Maximum user presence timeout. + */ + const PRESENCE_TIMEOUT_MAXIMUM = 320; + /** + * Apply configuration default values. + * + * @param configuration - User-provided configuration. + * + * @internal + */ + const setDefaults$1 = (configuration) => { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; + // Copy configuration. + const configurationCopy = Object.assign({}, configuration); + (_a = configurationCopy.ssl) !== null && _a !== void 0 ? _a : (configurationCopy.ssl = USE_SSL); + (_b = configurationCopy.transactionalRequestTimeout) !== null && _b !== void 0 ? _b : (configurationCopy.transactionalRequestTimeout = TRANSACTIONAL_REQUEST_TIMEOUT); + (_c = configurationCopy.subscribeRequestTimeout) !== null && _c !== void 0 ? _c : (configurationCopy.subscribeRequestTimeout = SUBSCRIBE_REQUEST_TIMEOUT); + (_d = configurationCopy.fileRequestTimeout) !== null && _d !== void 0 ? _d : (configurationCopy.fileRequestTimeout = FILE_REQUEST_TIMEOUT); + (_e = configurationCopy.restore) !== null && _e !== void 0 ? _e : (configurationCopy.restore = RESTORE); + (_f = configurationCopy.useInstanceId) !== null && _f !== void 0 ? _f : (configurationCopy.useInstanceId = USE_INSTANCE_ID); + (_g = configurationCopy.suppressLeaveEvents) !== null && _g !== void 0 ? _g : (configurationCopy.suppressLeaveEvents = SUPPRESS_LEAVE_EVENTS); + (_h = configurationCopy.requestMessageCountThreshold) !== null && _h !== void 0 ? _h : (configurationCopy.requestMessageCountThreshold = DEDUPE_CACHE_SIZE); + (_j = configurationCopy.autoNetworkDetection) !== null && _j !== void 0 ? _j : (configurationCopy.autoNetworkDetection = AUTO_NETWORK_DETECTION); + (_k = configurationCopy.enableEventEngine) !== null && _k !== void 0 ? _k : (configurationCopy.enableEventEngine = ENABLE_EVENT_ENGINE); + (_l = configurationCopy.maintainPresenceState) !== null && _l !== void 0 ? _l : (configurationCopy.maintainPresenceState = MAINTAIN_PRESENCE_STATE); + (_m = configurationCopy.useSmartHeartbeat) !== null && _m !== void 0 ? _m : (configurationCopy.useSmartHeartbeat = USE_SMART_HEARTBEAT); + (_o = configurationCopy.keepAlive) !== null && _o !== void 0 ? _o : (configurationCopy.keepAlive = KEEP_ALIVE$1); + if (configurationCopy.userId && configurationCopy.uuid) + throw new PubNubError("PubNub client configuration error: use only 'userId'"); + (_p = configurationCopy.userId) !== null && _p !== void 0 ? _p : (configurationCopy.userId = configurationCopy.uuid); + if (!configurationCopy.userId) + throw new PubNubError("PubNub client configuration error: 'userId' not set"); + else if (((_q = configurationCopy.userId) === null || _q === void 0 ? void 0 : _q.trim().length) === 0) + throw new PubNubError("PubNub client configuration error: 'userId' is empty"); + // Generate default origin subdomains. + if (!configurationCopy.origin) + configurationCopy.origin = Array.from({ length: 20 }, (_, i) => `ps${i + 1}.pndsn.com`); + const keySet = { + subscribeKey: configurationCopy.subscribeKey, + publishKey: configurationCopy.publishKey, + secretKey: configurationCopy.secretKey, + }; + if (configurationCopy.presenceTimeout !== undefined) { + if (configurationCopy.presenceTimeout > PRESENCE_TIMEOUT_MAXIMUM) { + configurationCopy.presenceTimeout = PRESENCE_TIMEOUT_MAXIMUM; + // eslint-disable-next-line no-console + console.warn('WARNING: Presence timeout is larger than the maximum. Using maximum value: ', PRESENCE_TIMEOUT_MAXIMUM); + } + else if (configurationCopy.presenceTimeout <= 0) { + // eslint-disable-next-line no-console + console.warn('WARNING: Presence timeout should be larger than zero.'); + delete configurationCopy.presenceTimeout; + } + } + if (configurationCopy.presenceTimeout !== undefined) + configurationCopy.heartbeatInterval = configurationCopy.presenceTimeout / 2 - 1; + else + configurationCopy.presenceTimeout = PRESENCE_TIMEOUT; + // Apply extended configuration defaults. + let announceSuccessfulHeartbeats = ANNOUNCE_HEARTBEAT_SUCCESS; + let announceFailedHeartbeats = ANNOUNCE_HEARTBEAT_FAILURE; + let fileUploadPublishRetryLimit = FILE_PUBLISH_RETRY_LIMIT; + let dedupeOnSubscribe = DEDUPE_ON_SUBSCRIBE; + let maximumCacheSize = DEDUPE_CACHE_SIZE; + let useRequestId = USE_REQUEST_ID; + // @ts-expect-error Not documented legacy configuration options. + if (configurationCopy.dedupeOnSubscribe !== undefined && typeof configurationCopy.dedupeOnSubscribe === 'boolean') { + // @ts-expect-error Not documented legacy configuration options. + dedupeOnSubscribe = configurationCopy.dedupeOnSubscribe; + } + // @ts-expect-error Not documented legacy configuration options. + if (configurationCopy.maximumCacheSize !== undefined && typeof configurationCopy.maximumCacheSize === 'number') { + // @ts-expect-error Not documented legacy configuration options. + maximumCacheSize = configurationCopy.maximumCacheSize; + } + // @ts-expect-error Not documented legacy configuration options. + if (configurationCopy.useRequestId !== undefined && typeof configurationCopy.useRequestId === 'boolean') { + // @ts-expect-error Not documented legacy configuration options. + useRequestId = configurationCopy.useRequestId; + } + if ( + // @ts-expect-error Not documented legacy configuration options. + configurationCopy.announceSuccessfulHeartbeats !== undefined && + // @ts-expect-error Not documented legacy configuration options. + typeof configurationCopy.announceSuccessfulHeartbeats === 'boolean') { + // @ts-expect-error Not documented legacy configuration options. + announceSuccessfulHeartbeats = configurationCopy.announceSuccessfulHeartbeats; + } + if ( + // @ts-expect-error Not documented legacy configuration options. + configurationCopy.announceFailedHeartbeats !== undefined && + // @ts-expect-error Not documented legacy configuration options. + typeof configurationCopy.announceFailedHeartbeats === 'boolean') { + // @ts-expect-error Not documented legacy configuration options. + announceFailedHeartbeats = configurationCopy.announceFailedHeartbeats; + } + if ( + // @ts-expect-error Not documented legacy configuration options. + configurationCopy.fileUploadPublishRetryLimit !== undefined && + // @ts-expect-error Not documented legacy configuration options. + typeof configurationCopy.fileUploadPublishRetryLimit === 'number') { + // @ts-expect-error Not documented legacy configuration options. + fileUploadPublishRetryLimit = configurationCopy.fileUploadPublishRetryLimit; + } + return Object.assign(Object.assign({}, configurationCopy), { keySet, + dedupeOnSubscribe, + maximumCacheSize, + useRequestId, + announceSuccessfulHeartbeats, + announceFailedHeartbeats, + fileUploadPublishRetryLimit }); + }; + + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether PubNub client should update its state using browser's reachability events or not. + * + * If the browser fails to detect the network changes from Wi-Fi to LAN and vice versa, or you get + * reconnection issues, set the flag to `false`. This allows the SDK reconnection logic to take over. + */ + const LISTEN_TO_BROWSER_NETWORK_EVENTS = true; + /** + * Whether verbose logging should be enabled for `Subscription` worker to print debug messages or not. + */ + const SUBSCRIPTION_WORKER_LOG_VERBOSITY = false; + /** + * Interval at which Shared Worker should check whether PubNub instances which used it still active or not. + */ + const SUBSCRIPTION_WORKER_OFFLINE_CLIENTS_CHECK_INTERVAL = 10; + /** + * Whether `leave` request should be sent for _offline_ PubNub client or not. + */ + const SUBSCRIPTION_WORKER_UNSUBSCRIBE_OFFLINE_CLIENTS = false; + /** + * Use modern Web Fetch API for network requests by default. + */ + const TRANSPORT = 'fetch'; + /** + * Whether PubNub client should try to utilize existing TCP connection for new requests or not. + */ + const KEEP_ALIVE = true; + /** + * Apply configuration default values. + * + * @param configuration - User-provided configuration. + * + * @internal + */ + const setDefaults = (configuration) => { + var _a, _b, _c, _d, _e, _f; + // Force to disable service workers if the environment doesn't support them. + if (configuration.subscriptionWorkerUrl && typeof SharedWorker === 'undefined') { + configuration.subscriptionWorkerUrl = null; + } + return Object.assign(Object.assign({}, setDefaults$1(configuration)), { + // Set platform-specific options. + listenToBrowserNetworkEvents: (_a = configuration.listenToBrowserNetworkEvents) !== null && _a !== void 0 ? _a : LISTEN_TO_BROWSER_NETWORK_EVENTS, subscriptionWorkerUrl: configuration.subscriptionWorkerUrl, subscriptionWorkerOfflineClientsCheckInterval: (_b = configuration.subscriptionWorkerOfflineClientsCheckInterval) !== null && _b !== void 0 ? _b : SUBSCRIPTION_WORKER_OFFLINE_CLIENTS_CHECK_INTERVAL, subscriptionWorkerUnsubscribeOfflineClients: (_c = configuration.subscriptionWorkerUnsubscribeOfflineClients) !== null && _c !== void 0 ? _c : SUBSCRIPTION_WORKER_UNSUBSCRIBE_OFFLINE_CLIENTS, subscriptionWorkerLogVerbosity: (_d = configuration.subscriptionWorkerLogVerbosity) !== null && _d !== void 0 ? _d : SUBSCRIPTION_WORKER_LOG_VERBOSITY, transport: (_e = configuration.transport) !== null && _e !== void 0 ? _e : TRANSPORT, keepAlive: (_f = configuration.keepAlive) !== null && _f !== void 0 ? _f : KEEP_ALIVE }); + }; + + /** + * Enum with available log levels. + */ + var LogLevel; + (function (LogLevel) { + /** + * Used to notify about every last detail: + * - function calls, + * - full payloads, + * - internal variables, + * - state-machine hops. + */ + LogLevel[LogLevel["Trace"] = 0] = "Trace"; + /** + * Used to notify about broad strokes of your SDK’s logic: + * - inputs/outputs to public methods, + * - network request + * - network response + * - decision branches. + */ + LogLevel[LogLevel["Debug"] = 1] = "Debug"; + /** + * Used to notify summary of what the SDK is doing under the hood: + * - initialized, + * - connected, + * - entity created. + */ + LogLevel[LogLevel["Info"] = 2] = "Info"; + /** + * Used to notify about non-fatal events: + * - deprecations, + * - request retries. + */ + LogLevel[LogLevel["Warn"] = 3] = "Warn"; + /** + * Used to notify about: + * - exceptions, + * - HTTP failures, + * - invalid states. + */ + LogLevel[LogLevel["Error"] = 4] = "Error"; + /** + * Logging disabled. + */ + LogLevel[LogLevel["None"] = 5] = "None"; + })(LogLevel || (LogLevel = {})); + + /** + * Default console-based logger. + * + * **Important:** This logger is always added as part of {@link LoggerManager} instance configuration and can't be + * removed. + * + * @internal + */ + /** + * Custom {@link Logger} implementation to show a message in the native console. + */ + class ConsoleLogger { + /** + * Process a `debug` level message. + * + * @param message - Message which should be handled by custom logger implementation. + */ + debug(message) { + this.log(message); + } + /** + * Process a `error` level message. + * + * @param message - Message which should be handled by custom logger implementation. + */ + error(message) { + this.log(message); + } + /** + * Process an `info` level message. + * + * @param message - Message which should be handled by custom logger implementation. + */ + info(message) { + this.log(message); + } + /** + * Process a `trace` level message. + * + * @param message - Message which should be handled by custom logger implementation. + */ + trace(message) { + this.log(message); + } + /** + * Process an `warn` level message. + * + * @param message - Message which should be handled by custom logger implementation. + */ + warn(message) { + this.log(message); + } + /** + * Stringify logger object. + * + * @returns Serialized logger object. + */ + toString() { + return `ConsoleLogger {}`; + } + /** + * Process log message object. + * + * @param message - Object with information which can be used to identify level and prepare log entry payload. + */ + log(message) { + const logLevelString = LogLevel[message.level]; + const level = logLevelString.toLowerCase(); + console[level === 'trace' ? 'debug' : level](`${message.timestamp.toISOString()} PubNub-${message.pubNubId} ${logLevelString.padEnd(5, ' ')}${message.location ? ` ${message.location}` : ''} ${this.logMessage(message)}`); + } + /** + * Get a pre-formatted log message. + * + * @param message - Log message which should be stringified. + * + * @returns String formatted for log entry in console. + */ + logMessage(message) { + if (message.messageType === 'text') + return message.message; + else if (message.messageType === 'object') + return `${message.details ? `${message.details}\n` : ''}${this.formattedObject(message)}`; + else if (message.messageType === 'network-request') { + const showOnlyBasicInfo = !!message.canceled || !!message.failed; + const headersList = message.minimumLevel === LogLevel.Trace && !showOnlyBasicInfo ? this.formattedHeaders(message) : undefined; + const request = message.message; + const queryString = request.queryParameters && Object.keys(request.queryParameters).length > 0 + ? queryStringFromObject(request.queryParameters) + : undefined; + const url = `${request.origin}${request.path}${queryString ? `?${queryString}` : ''}`; + const formattedBody = !showOnlyBasicInfo ? this.formattedBody(message) : undefined; + let action = 'Sending'; + if (showOnlyBasicInfo) + action = `${!!message.canceled ? 'Canceled' : 'Failed'}${message.details ? ` (${message.details})` : ''}`; + const padding = ((formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.formData) ? 'FormData' : 'Method').length; + return `${action} HTTP request:\n ${this.paddedString('Method', padding)}: ${request.method}\n ${this.paddedString('URL', padding)}: ${url}${headersList ? `\n ${this.paddedString('Headers', padding)}:\n${headersList}` : ''}${(formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.formData) ? `\n ${this.paddedString('FormData', padding)}:\n${formattedBody.formData}` : ''}${(formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.body) ? `\n ${this.paddedString('Body', padding)}:\n${formattedBody.body}` : ''}`; + } + else if (message.messageType === 'network-response') { + const headersList = message.minimumLevel === LogLevel.Trace ? this.formattedHeaders(message) : undefined; + const formattedBody = this.formattedBody(message); + const padding = ((formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.formData) ? 'Headers' : 'Status').length; + const response = message.message; + return `Received HTTP response:\n ${this.paddedString('URL', padding)}: ${response.url}\n ${this.paddedString('Status', padding)}: ${response.status}${message.details ? `\n ${this.paddedString('Details', padding)}: ${message.details}` : ''}${headersList ? `\n ${this.paddedString('Headers', padding)}:\n${headersList}` : ''}${(formattedBody === null || formattedBody === void 0 ? void 0 : formattedBody.body) ? `\n ${this.paddedString('Body', padding)}:\n${formattedBody.body}` : ''}`; + } + else if (message.messageType === 'error') { + const formattedStatus = this.formattedErrorStatus(message); + const error = message.message; + return `${error.name}: ${error.message}${formattedStatus ? `\n${formattedStatus}` : ''}`; + } + return ''; + } + /** + * Get a pre-formatted object (dictionary / array). + * + * @param message - Log message which may contain an object for formatting. + * + * @returns String formatted for log entry in console or `undefined` if a log message doesn't have suitable data. + */ + formattedObject(message) { + const stringify = (obj, level = 1, skipIndentOnce = false) => { + const maxIndentReached = level === 10; + const targetIndent = ' '.repeat(level * 2); + const lines = []; + const isIgnored = (key, obj) => { + if (!message.ignoredKeys) + return false; + if (typeof message.ignoredKeys === 'function') + return message.ignoredKeys(key, obj); + return message.ignoredKeys.includes(key); + }; + if (typeof obj === 'string') + lines.push(`${targetIndent}- ${obj}`); + else if (typeof obj === 'number') + lines.push(`${targetIndent}- ${obj}`); + else if (typeof obj === 'boolean') + lines.push(`${targetIndent}- ${obj}`); + else if (obj === null) + lines.push(`${targetIndent}- null`); + else if (obj === undefined) + lines.push(`${targetIndent}- undefined`); + else if (typeof obj === 'function') + lines.push(`${targetIndent}- `); + else if (typeof obj === 'object') { + if (!Array.isArray(obj) && typeof obj.toString === 'function' && obj.toString().indexOf('[object') !== 0) { + lines.push(`${skipIndentOnce ? '' : targetIndent}${obj.toString()}`); + skipIndentOnce = false; + } + else if (Array.isArray(obj)) { + for (const element of obj) { + const indent = skipIndentOnce ? '' : targetIndent; + if (element === null) + lines.push(`${indent}- null`); + else if (element === undefined) + lines.push(`${indent}- undefined`); + else if (typeof element === 'function') + lines.push(`${indent}- `); + else if (typeof element === 'object') { + const isArray = Array.isArray(element); + const entry = maxIndentReached ? '...' : stringify(element, level + 1, !isArray); + lines.push(`${indent}-${isArray && !maxIndentReached ? '\n' : ' '}${entry}`); + } + else + lines.push(`${indent}- ${element}`); + skipIndentOnce = false; + } + } + else { + const object = obj; + const keys = Object.keys(object); + const maxKeyLen = keys.reduce((max, key) => Math.max(max, isIgnored(key, object) ? max : key.length), 0); + for (const key of keys) { + if (isIgnored(key, object)) + continue; + const indent = skipIndentOnce ? '' : targetIndent; + const raw = object[key]; + const paddedKey = key.padEnd(maxKeyLen, ' '); + if (raw === null) + lines.push(`${indent}${paddedKey}: null`); + else if (raw === undefined) + lines.push(`${indent}${paddedKey}: undefined`); + else if (typeof raw === 'function') + lines.push(`${indent}${paddedKey}: `); + else if (typeof raw === 'object') { + const isArray = Array.isArray(raw); + const isEmptyArray = isArray && raw.length === 0; + const isEmptyObject = !isArray && !(raw instanceof String) && Object.keys(raw).length === 0; + const hasToString = !isArray && typeof raw.toString === 'function' && raw.toString().indexOf('[object') !== 0; + const entry = maxIndentReached + ? '...' + : isEmptyArray + ? '[]' + : isEmptyObject + ? '{}' + : stringify(raw, level + 1, hasToString); + lines.push(`${indent}${paddedKey}:${maxIndentReached || hasToString || isEmptyArray || isEmptyObject ? ' ' : '\n'}${entry}`); + } + else + lines.push(`${indent}${paddedKey}: ${raw}`); + skipIndentOnce = false; + } + } + } + return lines.join('\n'); + }; + return stringify(message.message); + } + /** + * Get a pre-formatted headers list. + * + * @param message - Log message which may contain an object with headers to be used for formatting. + * + * @returns String formatted for log entry in console or `undefined` if a log message not related to the network data. + */ + formattedHeaders(message) { + if (!message.message.headers) + return undefined; + const headers = message.message.headers; + const maxHeaderLength = Object.keys(headers).reduce((max, key) => Math.max(max, key.length), 0); + return Object.keys(headers) + .map((key) => ` - ${key.toLowerCase().padEnd(maxHeaderLength, ' ')}: ${headers[key]}`) + .join('\n'); + } + /** + * Get a pre-formatted body. + * + * @param message - Log message which may contain an object with `body` (request or response). + * + * @returns Object with formatted string of form data and / or body for log entry in console or `undefined` if a log + * message not related to the network data. + */ + formattedBody(message) { + var _a; + if (!message.message.headers) + return undefined; + let stringifiedFormData; + let stringifiedBody; + const headers = message.message.headers; + const contentType = (_a = headers['content-type']) !== null && _a !== void 0 ? _a : headers['Content-Type']; + const formData = 'formData' in message.message ? message.message.formData : undefined; + const body = message.message.body; + // The presence of this object means that we are sending `multipart/form-data` (potentially uploading a file). + if (formData) { + const maxFieldLength = formData.reduce((max, { key }) => Math.max(max, key.length), 0); + stringifiedFormData = formData + .map(({ key, value }) => ` - ${key.padEnd(maxFieldLength, ' ')}: ${value}`) + .join('\n'); + } + if (!body) + return { formData: stringifiedFormData }; + if (typeof body === 'string') { + stringifiedBody = ` ${body}`; + } + else if (body instanceof ArrayBuffer || Object.prototype.toString.call(body) === '[object ArrayBuffer]') { + if (contentType && (contentType.indexOf('javascript') !== -1 || contentType.indexOf('json') !== -1)) + stringifiedBody = ` ${ConsoleLogger.decoder.decode(body)}`; + else + stringifiedBody = ` ArrayBuffer { byteLength: ${body.byteLength} }`; + } + else { + stringifiedBody = ` File { name: ${body.name}${body.contentLength ? `, contentLength: ${body.contentLength}` : ''}${body.mimeType ? `, mimeType: ${body.mimeType}` : ''} }`; + } + return { body: stringifiedBody, formData: stringifiedFormData }; + } + /** + * Get a pre-formatted status object. + * + * @param message - Log message which may contain a {@link Status} object. + * + * @returns String formatted for log entry in console or `undefined` if a log message doesn't have {@link Status} + * object. + */ + formattedErrorStatus(message) { + if (!message.message.status) + return undefined; + const status = message.message.status; + const errorData = status.errorData; + let stringifiedErrorData; + if (ConsoleLogger.isError(errorData)) { + stringifiedErrorData = ` ${errorData.name}: ${errorData.message}`; + if (errorData.stack) { + stringifiedErrorData += `\n${errorData.stack + .split('\n') + .map((line) => ` ${line}`) + .join('\n')}`; + } + } + else if (errorData) { + try { + stringifiedErrorData = ` ${JSON.stringify(errorData)}`; + } + catch (_) { + stringifiedErrorData = ` ${errorData}`; + } + } + return ` Category : ${status.category}\n Operation : ${status.operation}\n Status : ${status.statusCode}${stringifiedErrorData ? `\n Error data:\n${stringifiedErrorData}` : ''}`; + } + /** + * Append the required amount of space to provide proper padding. + * + * @param str - Source string which should be appended with necessary number of spaces. + * @param maxLength - Maximum length of the string to which source string should be padded. + * @returns End-padded string. + */ + paddedString(str, maxLength) { + return str.padEnd(maxLength - str.length, ' '); + } + /** + * Check whether passed object is {@link Error} instance. + * + * @param errorData - Object which should be checked. + * + * @returns `true` in case if an object actually {@link Error}. + */ + static isError(errorData) { + if (!errorData) + return false; + return errorData instanceof Error || Object.prototype.toString.call(errorData) === '[object Error]'; + } + } + /** + * Binary data decoder. + */ + ConsoleLogger.decoder = new TextDecoder(); + + /** + * HTTP status codes which represent definitive client-side outcomes and shouldn't be retried. + * + * @internal + */ + const NON_RETRIABLE_STATUS_CODES = [404, 409]; + // -------------------------------------------------------- + // ------------------------ Types ------------------------- + // -------------------------------------------------------- + // region Types + /** + * List of known endpoint groups (by context). + */ + var Endpoint; + (function (Endpoint) { + /** + * Unknown endpoint. + * + * @internal + */ + Endpoint["Unknown"] = "UnknownEndpoint"; + /** + * The endpoints to send messages. + * + * This is related to the following functionality: + * - `publish` + * - `signal` + * - `publish file` + * - `fire` + */ + Endpoint["MessageSend"] = "MessageSendEndpoint"; + /** + * The endpoint for real-time update retrieval. + * + * This is related to the following functionality: + * - `subscribe` + */ + Endpoint["Subscribe"] = "SubscribeEndpoint"; + /** + * The endpoint to access and manage `user_id` presence and fetch channel presence information. + * + * This is related to the following functionality: + * - `get presence state` + * - `set presence state` + * - `here now` + * - `where now` + * - `heartbeat` + */ + Endpoint["Presence"] = "PresenceEndpoint"; + /** + * The endpoint to access and manage files in channel-specific storage. + * + * This is related to the following functionality: + * - `send file` + * - `download file` + * - `list files` + * - `delete file` + */ + Endpoint["Files"] = "FilesEndpoint"; + /** + * The endpoint to access and manage messages for a specific channel(s) in the persistent storage. + * + * This is related to the following functionality: + * - `fetch messages / message actions` + * - `delete messages` + * - `messages count` + */ + Endpoint["MessageStorage"] = "MessageStorageEndpoint"; + /** + * The endpoint to access and manage channel groups. + * + * This is related to the following functionality: + * - `add channels to group` + * - `list channels in group` + * - `remove channels from group` + * - `list channel groups` + */ + Endpoint["ChannelGroups"] = "ChannelGroupsEndpoint"; + /** + * The endpoint to access and manage device registration for channel push notifications. + * + * This is related to the following functionality: + * - `enable channels for push notifications` + * - `list push notification enabled channels` + * - `disable push notifications for channels` + * - `disable push notifications for all channels` + */ + Endpoint["DevicePushNotifications"] = "DevicePushNotificationsEndpoint"; + /** + * The endpoint to access and manage App Context objects. + * + * This is related to the following functionality: + * - `set UUID metadata` + * - `get UUID metadata` + * - `remove UUID metadata` + * - `get all UUID metadata` + * - `set Channel metadata` + * - `get Channel metadata` + * - `remove Channel metadata` + * - `get all Channel metadata` + * - `manage members` + * - `list members` + * - `manage memberships` + * - `list memberships` + */ + Endpoint["AppContext"] = "AppContextEndpoint"; + /** + * The endpoint to access and manage reactions for a specific message. + * + * This is related to the following functionality: + * - `add message action` + * - `get message actions` + * - `remove message action` + */ + Endpoint["MessageReactions"] = "MessageReactionsEndpoint"; + })(Endpoint || (Endpoint = {})); + // endregion + /** + * Failed request retry policy. + */ + class RetryPolicy { + static None() { + return { + shouldRetry(_request, _response, _errorCategory, _attempt, _statusCode) { + return false; + }, + getDelay(_attempt, _response) { + return -1; + }, + validate() { + return true; + }, + }; + } + static LinearRetryPolicy(configuration) { + var _a; + return { + delay: configuration.delay, + maximumRetry: configuration.maximumRetry, + excluded: (_a = configuration.excluded) !== null && _a !== void 0 ? _a : [], + shouldRetry(request, response, error, attempt, statusCode) { + return isRetriableRequest(request, response, error, attempt !== null && attempt !== void 0 ? attempt : 0, this.maximumRetry, this.excluded, statusCode); + }, + getDelay(_, response) { + let delay = -1; + if (response && response.headers['retry-after'] !== undefined) + delay = parseInt(response.headers['retry-after'], 10); + if (delay === -1) + delay = this.delay; + return (delay + Math.random()) * 1000; + }, + validate() { + if (this.delay < 2) + throw new Error('Delay can not be set less than 2 seconds for retry'); + }, + }; + } + static ExponentialRetryPolicy(configuration) { + var _a; + return { + minimumDelay: configuration.minimumDelay, + maximumDelay: configuration.maximumDelay, + maximumRetry: configuration.maximumRetry, + excluded: (_a = configuration.excluded) !== null && _a !== void 0 ? _a : [], + shouldRetry(request, response, error, attempt, statusCode) { + return isRetriableRequest(request, response, error, attempt !== null && attempt !== void 0 ? attempt : 0, this.maximumRetry, this.excluded, statusCode); + }, + getDelay(attempt, response) { + let delay = -1; + if (response && response.headers['retry-after'] !== undefined) + delay = parseInt(response.headers['retry-after'], 10); + if (delay === -1) + delay = Math.min(this.minimumDelay * Math.pow(2, attempt), this.maximumDelay); + return (delay + Math.random()) * 1000; + }, + validate() { + if (this.minimumDelay < 2) + throw new Error('Minimum delay can not be set less than 2 seconds for retry'); + }, + }; + } + } + /** + * Check whether request can be retried or not. + * + * @param req - Request for which retry ability is checked. + * @param res - Service response which should be taken into consideration. + * @param errorCategory - Request processing error category. + * @param retryAttempt - Current retry attempt. + * @param maximumRetry - Maximum retry attempts count according to the retry policy. + * @param excluded - List of endpoints for which retry policy won't be applied. + * @param statusCode - Response HTTP status code (available when request failed with an error and hence there is no + * `res`). + * + * @return `true` if request can be retried. + * + * @internal + */ + const isRetriableRequest = (req, res, errorCategory, retryAttempt, maximumRetry, excluded, statusCode) => { + var _a; + if (errorCategory) { + if (errorCategory === StatusCategory$1.PNCancelledCategory || + errorCategory === StatusCategory$1.PNBadRequestCategory || + errorCategory === StatusCategory$1.PNAccessDeniedCategory) + return false; + } + if (isExcludedRequest(req, excluded)) + return false; + else if (retryAttempt > maximumRetry) + return false; + // Status code is reported separately from the `res` when the request failed with an error. + const status = (_a = res === null || res === void 0 ? void 0 : res.status) !== null && _a !== void 0 ? _a : statusCode; + if (status !== undefined && NON_RETRIABLE_STATUS_CODES.includes(status)) + return false; + return res ? res.status === 429 || res.status >= 500 : true; + }; + /** + * Check whether the provided request is in the list of endpoints for which retry is not allowed or not. + * + * @param req - Request which will be tested. + * @param excluded - List of excluded endpoints configured for retry policy. + * + * @returns `true` if request has been excluded and shouldn't be retried. + * + * @internal + */ + const isExcludedRequest = (req, excluded) => excluded && excluded.length > 0 ? excluded.includes(endpointFromRequest(req)) : false; + /** + * Identify API group from transport request. + * + * @param req - Request for which `path` will be analyzed to identify REST API group. + * + * @returns Endpoint group to which request belongs. + * + * @internal + */ + const endpointFromRequest = (req) => { + let endpoint = Endpoint.Unknown; + if (req.path.startsWith('/v2/subscribe')) + endpoint = Endpoint.Subscribe; + else if (req.path.startsWith('/publish/') || req.path.startsWith('/signal/')) + endpoint = Endpoint.MessageSend; + else if (req.path.startsWith('/v2/presence')) + endpoint = Endpoint.Presence; + else if (req.path.startsWith('/v2/history') || req.path.startsWith('/v3/history')) + endpoint = Endpoint.MessageStorage; + else if (req.path.startsWith('/v1/message-actions/')) + endpoint = Endpoint.MessageReactions; + else if (req.path.startsWith('/v1/channel-registration/')) + endpoint = Endpoint.ChannelGroups; + else if (req.path.startsWith('/v2/objects/')) + endpoint = Endpoint.ChannelGroups; + else if (req.path.startsWith('/v1/push/') || req.path.startsWith('/v2/push/')) + endpoint = Endpoint.DevicePushNotifications; + else if (req.path.startsWith('/v1/files/')) + endpoint = Endpoint.Files; + return endpoint; + }; + + /** + * Logging module manager. + * + * Manager responsible for log requests handling and forwarding to the registered {@link Logger logger} implementations. + */ + class LoggerManager { + /** + * Create and configure loggers' manager. + * + * @param pubNubId - Unique identifier of PubNub instance which will use this logger. + * @param minLogLevel - Minimum messages log level to be logged. + * @param loggers - List of additional loggers which should be used along with user-provided custom loggers. + * + * @internal + */ + constructor(pubNubId, minLogLevel, loggers) { + /** + * Keeping track of previous entry timestamp. + * + * This information will be used to make sure that multiple sequential entries doesn't have same timestamp. Adjustment + * on .001 will be done to make it possible to properly stort entries. + * + * @internal + */ + this.previousEntryTimestamp = 0; + this.pubNubId = pubNubId; + this.minLogLevel = minLogLevel; + this.loggers = loggers; + } + /** + * Get current log level. + * + * @returns Current log level. + * + * @internal + */ + get logLevel() { + return this.minLogLevel; + } + /** + * Process a `trace` level message. + * + * @param location - Call site from which a log message has been sent. + * @param messageFactory - Lazy message factory function or string for a text log message. + * + * @internal + */ + trace(location, messageFactory) { + this.log(LogLevel.Trace, location, messageFactory); + } + /** + * Process a `debug` level message. + * + * @param location - Call site from which a log message has been sent. + * @param messageFactory - Lazy message factory function or string for a text log message. + * + * @internal + */ + debug(location, messageFactory) { + this.log(LogLevel.Debug, location, messageFactory); + } + /** + * Process an `info` level message. + * + * @param location - Call site from which a log message has been sent. + * @param messageFactory - Lazy message factory function or string for a text log message. + * + * @internal + */ + info(location, messageFactory) { + this.log(LogLevel.Info, location, messageFactory); + } + /** + * Process a `warn` level message. + * + * @param location - Call site from which a log message has been sent. + * @param messageFactory - Lazy message factory function or string for a text log message. + * + * @internal + */ + warn(location, messageFactory) { + this.log(LogLevel.Warn, location, messageFactory); + } + /** + * Process an `error` level message. + * + * @param location - Call site from which a log message has been sent. + * @param messageFactory - Lazy message factory function or string for a text log message. + * + * @internal + */ + error(location, messageFactory) { + this.log(LogLevel.Error, location, messageFactory); + } + /** + * Process log message. + * + * @param logLevel - Logged message level. + * @param location - Call site from which a log message has been sent. + * @param messageFactory - Lazy message factory function or string for a text log message. + * + * @internal + */ + log(logLevel, location, messageFactory) { + // Check whether a log message should be handled at all or not. + if (logLevel < this.minLogLevel || this.loggers.length === 0) + return; + const date = new Date(); + if (date.getTime() <= this.previousEntryTimestamp) { + this.previousEntryTimestamp++; + date.setTime(this.previousEntryTimestamp); + } + else + this.previousEntryTimestamp = date.getTime(); + const level = LogLevel[logLevel].toLowerCase(); + const message = Object.assign({ timestamp: date, pubNubId: this.pubNubId, level: logLevel, minimumLevel: this.minLogLevel, location }, (typeof messageFactory === 'function' ? messageFactory() : { messageType: 'text', message: messageFactory })); + this.loggers.forEach((logger) => logger[level](message)); + } + } + + var uuid = {exports: {}}; + + /*! lil-uuid - v0.1 - MIT License - https://github.com/lil-js/uuid */ + uuid.exports; + + (function (module, exports) { + (function (root, factory) { + { + factory(exports); + if (module !== null) { + module.exports = exports.uuid; + } + } + }(commonjsGlobal, function (exports) { + var VERSION = '0.1.0'; + var uuidRegex = { + '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, + '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i + }; + + function uuid() { + var uuid = '', i, random; + for (i = 0; i < 32; i++) { + random = Math.random() * 16 | 0; + if (i === 8 || i === 12 || i === 16 || i === 20) uuid += '-'; + uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random)).toString(16); + } + return uuid + } + + function isUUID(str, version) { + var pattern = uuidRegex[version || 'all']; + return pattern && pattern.test(str) || false + } + + uuid.isUUID = isUUID; + uuid.VERSION = VERSION; + + exports.uuid = uuid; + exports.isUUID = isUUID; + })); + } (uuid, uuid.exports)); + + var uuidExports = uuid.exports; + var uuidGenerator$1 = /*@__PURE__*/getDefaultExportFromCjs(uuidExports); + + /** + * Random identifier generator helper module. + * + * @internal + */ + /** @internal */ + var uuidGenerator = { + createUUID() { + if (uuidGenerator$1.uuid) { + return uuidGenerator$1.uuid(); + } + // @ts-expect-error Depending on module type it may be callable. + return uuidGenerator$1(); + }, + }; + + /** + * {@link PubNub} client configuration module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether encryption (if set) should use random initialization vector or not. + * + * @internal + */ + const USE_RANDOM_INITIALIZATION_VECTOR = true; + /** + * Create {@link PubNub} client private configuration object. + * + * @param base - User- and platform-provided configuration. + * @param setupCryptoModule - Platform-provided {@link ICryptoModule} configuration block. + * + * @returns `PubNub` client private configuration. + * + * @internal + */ + const makeConfiguration = (base, setupCryptoModule) => { + var _a, _b, _c, _d; + // Set the default retry policy for subscribing (if new subscribe logic not used). + if (!base.retryConfiguration && base.enableEventEngine) { + base.retryConfiguration = RetryPolicy.ExponentialRetryPolicy({ + minimumDelay: 2, + maximumDelay: 150, + maximumRetry: 6, + excluded: [ + Endpoint.MessageSend, + Endpoint.Presence, + Endpoint.Files, + Endpoint.MessageStorage, + Endpoint.ChannelGroups, + Endpoint.DevicePushNotifications, + Endpoint.AppContext, + Endpoint.MessageReactions, + ], + }); + } + const instanceId = `pn-${uuidGenerator.createUUID()}`; + if (base.logVerbosity) + base.logLevel = LogLevel.Debug; + else if (base.logLevel === undefined) + base.logLevel = LogLevel.None; + // Prepare loggers manager. + const loggerManager = new LoggerManager(hashFromString(instanceId), base.logLevel, [ + ...((_a = base.loggers) !== null && _a !== void 0 ? _a : []), + new ConsoleLogger(), + ]); + if (base.logVerbosity !== undefined) + loggerManager.warn('Configuration', "'logVerbosity' is deprecated. Use 'logLevel' instead."); + // Ensure that retry policy has proper configuration (if has been set). + (_b = base.retryConfiguration) === null || _b === void 0 ? void 0 : _b.validate(); + const explicitUseRandomIVs = base.useRandomIVs; + (_c = base.useRandomIVs) !== null && _c !== void 0 ? _c : (base.useRandomIVs = USE_RANDOM_INITIALIZATION_VECTOR); + if (explicitUseRandomIVs !== undefined) { + loggerManager.warn('Configuration', "'useRandomIVs' is deprecated. Pass it to 'cryptoModule' instead."); + if (explicitUseRandomIVs === false) { + loggerManager.warn('Configuration', `Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients. + Do not disable random IVs in new applications.`); + } + } + // Override origin value. + base.origin = standardOrigin((_d = base.ssl) !== null && _d !== void 0 ? _d : false, base.origin); + const cryptoModule = base.cryptoModule; + if (cryptoModule) + delete base.cryptoModule; + const clientConfiguration = Object.assign(Object.assign({}, base), { _pnsdkSuffix: {}, _loggerManager: loggerManager, _instanceId: instanceId, _cryptoModule: undefined, _cipherKey: undefined, _setupCryptoModule: setupCryptoModule, get instanceId() { + if (base.useInstanceId) + return this._instanceId; + return undefined; + }, + getInstanceId() { + if (base.useInstanceId) + return this._instanceId; + return undefined; + }, + getUserId() { + return this.userId; + }, + setUserId(value) { + if (!value || typeof value !== 'string' || value.trim().length === 0) + throw new Error('Missing or invalid userId parameter. Provide a valid string userId'); + this.userId = value; + }, + logger() { + return this._loggerManager; + }, + getAuthKey() { + return this.authKey; + }, + setAuthKey(authKey) { + this.authKey = authKey; + }, + getFilterExpression() { + return this.filterExpression; + }, + setFilterExpression(expression) { + this.filterExpression = expression; + }, + getCipherKey() { + return this._cipherKey; + }, + setCipherKey(key) { + this._cipherKey = key; + if (!key && this._cryptoModule) { + this._cryptoModule = undefined; + return; + } + else if (!key || !this._setupCryptoModule) + return; + this._cryptoModule = this._setupCryptoModule({ + cipherKey: key, + useRandomIVs: base.useRandomIVs, + customEncrypt: this.getCustomEncrypt(), + customDecrypt: this.getCustomDecrypt(), + logger: this.logger(), + }); + }, + getCryptoModule() { + return this._cryptoModule; + }, + getUseRandomIVs() { + return base.useRandomIVs; + }, + isSharedWorkerEnabled() { + // @ts-expect-error: Access field from web-based SDK configuration. + return base.sdkFamily === 'Web' && base['subscriptionWorkerUrl']; + }, + getKeepPresenceChannelsInPresenceRequests() { + // @ts-expect-error: Access field from web-based SDK configuration. + return base.sdkFamily === 'Web' && base['subscriptionWorkerUrl']; + }, + setPresenceTimeout(value) { + this.heartbeatInterval = value / 2 - 1; + this.presenceTimeout = value; + }, + getPresenceTimeout() { + return this.presenceTimeout; + }, + getHeartbeatInterval() { + return this.heartbeatInterval; + }, + setHeartbeatInterval(interval) { + this.heartbeatInterval = interval; + }, + getTransactionTimeout() { + return this.transactionalRequestTimeout; + }, + getSubscribeTimeout() { + return this.subscribeRequestTimeout; + }, + getFileTimeout() { + return this.fileRequestTimeout; + }, + get PubNubFile() { + return base.PubNubFile; + }, + get version() { + return '13.1.3'; + }, + getVersion() { + return this.version; + }, + _addPnsdkSuffix(name, suffix) { + this._pnsdkSuffix[name] = `${suffix}`; + }, + _getPnsdkSuffix(separator) { + const sdk = Object.values(this._pnsdkSuffix).join(separator); + return sdk.length > 0 ? separator + sdk : ''; + }, + // -------------------------------------------------------- + // ---------------------- Deprecated ---------------------- + // -------------------------------------------------------- + // region Deprecated + getUUID() { + return this.getUserId(); + }, + setUUID(value) { + this.setUserId(value); + }, + getCustomEncrypt() { + return base.customEncrypt; + }, + getCustomDecrypt() { + return base.customDecrypt; + } }); + // Setup `CryptoModule` if possible. + if (base.cipherKey) { + loggerManager.warn('Configuration', "'cipherKey' is deprecated. Use 'cryptoModule' instead."); + clientConfiguration.setCipherKey(base.cipherKey); + } + else if (cryptoModule) + clientConfiguration._cryptoModule = cryptoModule; + return clientConfiguration; + }; + /** + * Decide {@lin PubNub} service REST API origin. + * + * @param secure - Whether preferred to use secured connection or not. + * @param origin - User-provided or default origin. + * + * @returns `PubNub` REST API endpoints origin. + */ + const standardOrigin = (secure, origin) => { + const protocol = secure ? 'https://' : 'http://'; + if (typeof origin === 'string') + return `${protocol}${origin}`; + return `${protocol}${origin[Math.floor(Math.random() * origin.length)]}`; + }; + /** + * Compute 32bit hash string from source value. + * + * @param value - String from which hash string should be computed. + * + * @returns Computed hash. + */ + const hashFromString = (value) => { + let basis = 0x811c9dc5; + for (let i = 0; i < value.length; i++) { + basis ^= value.charCodeAt(i); + basis = (basis + ((basis << 1) + (basis << 4) + (basis << 7) + (basis << 8) + (basis << 24))) >>> 0; + } + return basis.toString(16).padStart(8, '0'); + }; + + /** + * PubNub Access Token Manager module. + * + * @internal + */ + // endregion + /** + * REST API access token manager. + * + * Manager maintains active access token and let parse it to get information about permissions. + * + * @internal + */ + class TokenManager { + constructor(cbor) { + this.cbor = cbor; + } + /** + * Update REST API access token. + * + * **Note:** Token will be applied only for next requests and won't affect ongoing requests. + * + * @param [token] - Access token which should be used to access PubNub REST API. + */ + setToken(token) { + if (token && token.length > 0) + this.token = token; + else + this.token = undefined; + } + /** + * REST API access token. + * + * @returns Previously configured REST API access token. + */ + getToken() { + return this.token; + } + /** + * Parse Base64-encoded access token. + * + * @param tokenString - Base64-encoded access token. + * + * @returns Information about resources and permissions which has been granted for them. + */ + parseToken(tokenString) { + var _a, _b; + const parsed = this.cbor.decodeToken(tokenString); + if (parsed !== undefined) { + const uuidResourcePermissions = parsed.res.uuid ? Object.keys(parsed.res.uuid) : []; + const userResourcePermissions = parsed.res.usr ? Object.keys(parsed.res.usr) : []; + const channelResourcePermissions = Object.keys(parsed.res.chan); + const groupResourcePermissions = Object.keys(parsed.res.grp); + const uuidPatternPermissions = parsed.pat.uuid ? Object.keys(parsed.pat.uuid) : []; + const userPatternPermissions = parsed.pat.usr ? Object.keys(parsed.pat.usr) : []; + const channelPatternPermissions = Object.keys(parsed.pat.chan); + const groupPatternPermissions = Object.keys(parsed.pat.grp); + const result = { + version: parsed.v, + timestamp: parsed.t, + ttl: parsed.ttl, + authorized_uuid: parsed.uuid, + signature: parsed.sig, + }; + const uuidResources = uuidResourcePermissions.length > 0; + const userResources = userResourcePermissions.length > 0; + const channelResources = channelResourcePermissions.length > 0; + const groupResources = groupResourcePermissions.length > 0; + if (uuidResources || userResources || channelResources || groupResources) { + result.resources = {}; + if (uuidResources) { + const uuids = (result.resources.uuids = {}); + uuidResourcePermissions.forEach((id) => (uuids[id] = this.extractPermissions(parsed.res.uuid[id]))); + } + if (userResources) { + const users = (result.resources.users = {}); + userResourcePermissions.forEach((id) => (users[id] = this.extractCrudPermissions(parsed.res.usr[id]))); + } + if (channelResources) { + const channels = (result.resources.channels = {}); + channelResourcePermissions.forEach((id) => (channels[id] = this.extractPermissions(parsed.res.chan[id]))); + } + if (groupResources) { + const groups = (result.resources.groups = {}); + groupResourcePermissions.forEach((id) => (groups[id] = this.extractPermissions(parsed.res.grp[id]))); + } + } + const resourceDataSync = this.extractDataSyncScopes(parsed.res); + if (resourceDataSync) + ((_a = result.resources) !== null && _a !== void 0 ? _a : (result.resources = {})).dataSync = resourceDataSync; + const uuidPatterns = uuidPatternPermissions.length > 0; + const userPatterns = userPatternPermissions.length > 0; + const channelPatterns = channelPatternPermissions.length > 0; + const groupPatterns = groupPatternPermissions.length > 0; + if (uuidPatterns || userPatterns || channelPatterns || groupPatterns) { + result.patterns = {}; + if (uuidPatterns) { + const uuids = (result.patterns.uuids = {}); + uuidPatternPermissions.forEach((id) => (uuids[id] = this.extractPermissions(parsed.pat.uuid[id]))); + } + if (userPatterns) { + const users = (result.patterns.users = {}); + userPatternPermissions.forEach((id) => (users[id] = this.extractCrudPermissions(parsed.pat.usr[id]))); + } + if (channelPatterns) { + const channels = (result.patterns.channels = {}); + channelPatternPermissions.forEach((id) => (channels[id] = this.extractPermissions(parsed.pat.chan[id]))); + } + if (groupPatterns) { + const groups = (result.patterns.groups = {}); + groupPatternPermissions.forEach((id) => (groups[id] = this.extractPermissions(parsed.pat.grp[id]))); + } + } + const patternDataSync = this.extractDataSyncScopes(parsed.pat); + if (patternDataSync) + ((_b = result.patterns) !== null && _b !== void 0 ? _b : (result.patterns = {})).dataSync = patternDataSync; + const categories = this.extractCategories(parsed.cat); + if (categories) + result.categories = categories; + if (parsed.meta && Object.keys(parsed.meta).length > 0) + result.meta = parsed.meta; + return result; + } + return undefined; + } + /** + * Extract resource access permission information. + * + * @param permissions - Bit-encoded resource permissions. + * + * @returns Human-readable resource permissions. + */ + extractPermissions(permissions) { + const permissionsResult = { + read: false, + write: false, + manage: false, + delete: false, + get: false, + update: false, + join: false, + }; + if ((permissions & 128) === 128) + permissionsResult.join = true; + if ((permissions & 64) === 64) + permissionsResult.update = true; + if ((permissions & 32) === 32) + permissionsResult.get = true; + if ((permissions & 8) === 8) + permissionsResult.delete = true; + if ((permissions & 4) === 4) + permissionsResult.manage = true; + if ((permissions & 2) === 2) + permissionsResult.write = true; + if ((permissions & 1) === 1) + permissionsResult.read = true; + return permissionsResult; + } + /** + * Extract category-level permissions from the token `cat` section. + * + * `chan` maps to `channels` and `uuid` maps to `uuids`. `get` is set from the `32` bit. The + * section is omitted when `cat` is absent or empty. + * + * @param cat - Raw `cat` section decoded from the token. + * + * @returns Human-readable category permissions, or `undefined` when none are present. + */ + extractCategories(cat) { + if (!cat) + return undefined; + const result = {}; + if (typeof cat.chan === 'number') + result.channels = { get: (cat.chan & 32) === 32 }; + if (typeof cat.uuid === 'number') + result.uuids = { get: (cat.uuid & 32) === 32 }; + return Object.keys(result).length > 0 ? result : undefined; + } + /** + * Extract DataSync permission scopes from a token permissions section. + * + * The `datasync:*` wire keys are only present for tokens which granted DataSync permissions, so a + * result is returned only when at least one scope carries permissions. + * + * @param section - Raw `res` or `pat` permissions section decoded from the token. + * + * @returns Human-readable DataSync permission scopes, or `undefined` when none are granted. + */ + extractDataSyncScopes(section) { + const dataSyncScopes = [ + ['entities', 'datasync:entities'], + ['relationships', 'datasync:relationships'], + ['memberships', 'datasync:memberships'], + ]; + let result; + dataSyncScopes.forEach(([scope, wireKey]) => { + const permissions = section[wireKey]; + if (!permissions) + return; + const ids = Object.keys(permissions); + if (ids.length === 0) + return; + const scopeResult = ((result !== null && result !== void 0 ? result : (result = {}))[scope] = {}); + ids.forEach((id) => (scopeResult[id] = this.extractCrudPermissions(permissions[id]))); + }); + return result; + } + /** + * Extract CRUD-only access permission information. + * + * Shared by the `usr` wire key (which backs the `users` grant scope) and the `datasync:*` wire + * keys — both carry the same CRUD bit layout and none of the `read` / `write` / `manage` / `join` + * bits decoded by {@link extractPermissions}. + * + * @param permissions - Bit-encoded resource permissions. + * + * @returns Human-readable CRUD resource permissions. + */ + extractCrudPermissions(permissions) { + return { + create: (permissions & 16) === 16, + get: (permissions & 32) === 32, + update: (permissions & 64) === 64, + delete: (permissions & 8) === 8, + }; + } + } + + /** + * Enum representing possible transport methods for HTTP requests. + * + * @enum {number} + */ + var TransportMethod; + (function (TransportMethod) { + /** + * Request will be sent using `GET` method. + */ + TransportMethod["GET"] = "GET"; + /** + * Request will be sent using `POST` method. + */ + TransportMethod["POST"] = "POST"; + /** + * Request will be sent using `PATCH` method. + */ + TransportMethod["PATCH"] = "PATCH"; + /** + * Request will be sent using `PUT` method. + */ + TransportMethod["PUT"] = "PUT"; + /** + * Request will be sent using `DELETE` method. + */ + TransportMethod["DELETE"] = "DELETE"; + /** + * Local request. + * + * Request won't be sent to the service and probably used to compute URL. + */ + TransportMethod["LOCAL"] = "LOCAL"; + })(TransportMethod || (TransportMethod = {})); + + /** + * Common PubNub Network Provider middleware module. + * + * @internal + */ + /** + * Request signature generator. + * + * @internal + */ + class RequestSignature { + constructor(publishKey, secretKey, hasher, logger) { + this.publishKey = publishKey; + this.secretKey = secretKey; + this.hasher = hasher; + this.logger = logger; + } + /** + * Compute request signature. + * + * @param req - Request which will be used to compute signature. + * @returns {string} `v2` request signature. + */ + signature(req) { + const method = req.path.startsWith('/publish') ? TransportMethod.GET : req.method; + let signatureInput = `${method}\n${this.publishKey}\n${req.path}\n${this.queryParameters(req.queryParameters)}\n`; + if (method === TransportMethod.POST || method === TransportMethod.PATCH || method === TransportMethod.PUT) { + const body = req.body; + let payload; + if (body && body instanceof ArrayBuffer) { + payload = RequestSignature.textDecoder.decode(body); + } + else if (body && typeof body !== 'object') { + payload = body; + } + if (payload) + signatureInput += payload; + } + this.logger.trace('RequestSignature', () => ({ + messageType: 'text', + message: `Request signature input:\n${signatureInput}`, + })); + return `v2.${this.hasher(signatureInput, this.secretKey)}` + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/, ''); + } + /** + * Prepare request query parameters for signature. + * + * @param query - Key / value pair of the request query parameters. + * @private + */ + queryParameters(query) { + return Object.keys(query) + .sort() + .map((key) => { + const queryValue = query[key]; + if (!Array.isArray(queryValue)) + return `${key}=${encodeString(queryValue)}`; + return queryValue + .sort() + .map((value) => `${key}=${encodeString(value)}`) + .join('&'); + }) + .join('&'); + } + } + RequestSignature.textDecoder = new TextDecoder('utf-8'); + /** + * Common PubNub Network Provider middleware. + * + * @internal + */ + class PubNubMiddleware { + constructor(configuration) { + this.configuration = configuration; + const { clientConfiguration: { keySet }, shaHMAC, } = configuration; + { + if (keySet.secretKey && shaHMAC) + this.signatureGenerator = new RequestSignature(keySet.publishKey, keySet.secretKey, shaHMAC, this.logger); + } + } + /** + * Retrieve registered loggers' manager. + * + * @returns Registered loggers' manager. + */ + get logger() { + return this.configuration.clientConfiguration.logger(); + } + makeSendable(req) { + const retryPolicy = this.configuration.clientConfiguration.retryConfiguration; + const transport = this.configuration.transport; + // Make requests retryable. + if (retryPolicy !== undefined) { + let retryTimeout; + let activeCancellation; + let canceled = false; + let attempt = 0; + const cancellation = { + abort: (reason) => { + canceled = true; + if (retryTimeout) + clearTimeout(retryTimeout); + if (activeCancellation) + activeCancellation.abort(reason); + }, + }; + const retryableRequest = new Promise((resolve, reject) => { + const trySendRequest = () => { + // Check whether the request already has been canceled and there is no retry should proceed. + if (canceled) + return; + const [attemptPromise, attemptCancellation] = transport.makeSendable(this.request(req)); + activeCancellation = attemptCancellation; + const responseHandler = (res, error) => { + let delay = -1; + // Retry ability (error category, HTTP status code, excluded endpoints and attempts count) is entirely + // decided by the retry policy. + if (retryPolicy.shouldRetry(req, res, error === null || error === void 0 ? void 0 : error.category, attempt + 1, error === null || error === void 0 ? void 0 : error.statusCode)) + delay = retryPolicy.getDelay(attempt, res); + if (delay > 0) { + attempt++; + this.logger.warn('PubNubMiddleware', `HTTP request retry #${attempt} in ${delay}ms.`); + retryTimeout = setTimeout(() => trySendRequest(), delay); + } + else { + if (res) + resolve(res); + else if (error) + reject(error); + } + }; + attemptPromise + .then((res) => responseHandler(res)) + .catch((err) => responseHandler(undefined, err)); + }; + trySendRequest(); + }); + return [retryableRequest, activeCancellation ? cancellation : undefined]; + } + return transport.makeSendable(this.request(req)); + } + request(req) { + var _a; + const { clientConfiguration } = this.configuration; + // Get request patched by transport provider. + req = this.configuration.transport.request(req); + if (!req.queryParameters) + req.queryParameters = {}; + // Modify the request with required information. + if (clientConfiguration.useInstanceId) + req.queryParameters['instanceid'] = clientConfiguration.getInstanceId(); + if (!req.queryParameters['uuid']) + req.queryParameters['uuid'] = clientConfiguration.userId; + if (clientConfiguration.useRequestId) + req.queryParameters['requestid'] = req.identifier; + req.queryParameters['pnsdk'] = this.generatePNSDK(); + (_a = req.origin) !== null && _a !== void 0 ? _a : (req.origin = clientConfiguration.origin); + // Authenticate request if required. + this.authenticateRequest(req); + // Sign request if it is required. + this.signRequest(req); + return req; + } + authenticateRequest(req) { + var _a; + // Access management endpoints don't need authentication (signature required instead). + if (req.path.startsWith('/v2/auth/') || req.path.startsWith('/v3/pam/') || req.path.startsWith('/time')) + return; + const { clientConfiguration, tokenManager } = this.configuration; + const accessKey = (_a = (tokenManager && tokenManager.getToken())) !== null && _a !== void 0 ? _a : clientConfiguration.authKey; + if (accessKey) + req.queryParameters['auth'] = accessKey; + } + /** + * Compute and append request signature. + * + * @param req - Transport request with information which should be used to generate signature. + */ + signRequest(req) { + if (!this.signatureGenerator || req.path.startsWith('/time')) + return; + req.queryParameters['timestamp'] = String(Math.floor(new Date().getTime() / 1000)); + req.queryParameters['signature'] = this.signatureGenerator.signature(req); + } + /** + * Compose `pnsdk` query parameter. + * + * SDK provides ability to set custom name or append vendor information to the `pnsdk` query + * parameter. + * + * @returns Finalized `pnsdk` query parameter value. + */ + generatePNSDK() { + const { clientConfiguration } = this.configuration; + if (clientConfiguration.sdkName) + return clientConfiguration.sdkName; + let base = `PubNub-JS-${clientConfiguration.sdkFamily}`; + if (clientConfiguration.partnerId) + base += `-${clientConfiguration.partnerId}`; + base += `/${clientConfiguration.getVersion()}`; + const pnsdkSuffix = clientConfiguration._getPnsdkSuffix(' '); + if (pnsdkSuffix.length > 0) + base += pnsdkSuffix; + return base; + } + } + + /** + * Common browser and React Native Transport provider module. + * + * @internal + */ + /** + * Class representing a `fetch`-based browser and React Native transport provider. + * + * @internal + */ + class WebTransport { + /** + * Create and configure transport provider for Web and Rect environments. + * + * @param logger - Registered loggers' manager. + * @param [transport] - API, which should be used to make network requests. + * + * @internal + */ + constructor(logger, transport = 'fetch') { + this.logger = logger; + this.transport = transport; + logger.debug('WebTransport', `Create with configuration:\n - transport: ${transport}`); + // Check for `fetch` availability directly (works in DOM and DOM-less contexts such as service workers). + // because a bare `window` reference would throw in a service worker, and a partial `window = self` shim can + // define `window` without `fetch`, so probe the actual `fetch` global via `typeof`. + if (transport === 'fetch' && typeof fetch === 'undefined') { + logger.warn('WebTransport', `'${transport}' not supported in this browser. Fallback to the 'xhr' transport.`); + this.transport = 'xhr'; + } + if (this.transport !== 'fetch') + return; + // Storing reference on original `fetch` function implementation as protection against APM lib monkey patching. + // + // This is done unconditionally (not gated on `isFetchMonkeyPatched()`): APM libraries can defeat that + // detection by overriding stringification to report `[native code]` while still patching `fetch`, so we + // cannot rely on it to decide whether the workaround is needed. `getOriginalFetch()` itself decides how to + // obtain the reference based on the environment (iframe when a DOM is available, context `fetch` otherwise), + // which keeps construction safe in DOM-less contexts such as MV3 service workers. + WebTransport.originalFetch = WebTransport.getOriginalFetch(); + // Check whether `fetch` has been monkey patched or not. + if (this.isFetchMonkeyPatched()) + logger.warn('WebTransport', "Native Web Fetch API 'fetch' function monkey patched."); + } + makeSendable(req) { + const abortController = new AbortController(); + const cancellation = { + abortController, + abort: (reason) => { + if (!abortController.signal.aborted) { + this.logger.trace('WebTransport', `On-demand request aborting: ${reason}`); + abortController.abort(reason); + } + }, + }; + return [ + this.webTransportRequestFromTransportRequest(req).then((request) => { + this.logger.debug('WebTransport', () => ({ messageType: 'network-request', message: req })); + return this.sendRequest(request, cancellation) + .then((response) => response.arrayBuffer().then((arrayBuffer) => [response, arrayBuffer])) + .then((response) => { + const body = response[1].byteLength > 0 ? response[1] : undefined; + const { status, headers: requestHeaders } = response[0]; + const headers = {}; + // Copy Headers object content into plain Record. + requestHeaders.forEach((value, key) => (headers[key] = value.toLowerCase())); + const transportResponse = { status, url: request.url, headers, body }; + this.logger.debug('WebTransport', () => ({ + messageType: 'network-response', + message: transportResponse, + })); + if (status >= 400) + throw PubNubAPIError.create(transportResponse); + return transportResponse; + }) + .catch((error) => { + const errorMessage = (typeof error === 'string' ? error : error.message).toLowerCase(); + let fetchError = typeof error === 'string' ? new Error(error) : error; + if (errorMessage.includes('timeout')) { + this.logger.warn('WebTransport', () => ({ + messageType: 'network-request', + message: req, + details: 'Timeout', + canceled: true, + })); + } + else if (errorMessage.includes('cancel') || errorMessage.includes('abort')) { + this.logger.debug('WebTransport', () => ({ + messageType: 'network-request', + message: req, + details: 'Aborted', + canceled: true, + })); + fetchError = new Error('Aborted'); + fetchError.name = 'AbortError'; + } + else if (errorMessage.includes('network')) { + this.logger.warn('WebTransport', () => ({ + messageType: 'network-request', + message: req, + details: 'Network error', + failed: true, + })); + } + else { + this.logger.warn('WebTransport', () => ({ + messageType: 'network-request', + message: req, + details: PubNubAPIError.create(fetchError).message, + failed: true, + })); + } + throw PubNubAPIError.create(fetchError); + }); + }), + cancellation, + ]; + } + request(req) { + return req; + } + /** + * Send network request using preferred API. + * + * @param req - Transport API agnostic request object with prepared body and URL. + * @param controller - Request cancellation controller (for long-poll requests). + * + * @returns Promise which will be resolved or rejected at the end of network request processing. + * + * @internal + */ + sendRequest(req, controller) { + return __awaiter(this, void 0, void 0, function* () { + if (this.transport === 'fetch') + return this.sendFetchRequest(req, controller); + return this.sendXHRRequest(req, controller); + }); + } + /** + * Send network request using legacy XMLHttpRequest API. + * + * @param req - Transport API agnostic request object with prepared body and URL. + * @param controller - Request cancellation controller (for long-poll requests). + * + * @returns Promise which will be resolved or rejected at the end of network request processing. + * + * @internal + */ + sendFetchRequest(req, controller) { + return __awaiter(this, void 0, void 0, function* () { + let timeoutId; + const requestTimeout = new Promise((_, reject) => { + timeoutId = setTimeout(() => { + clearTimeout(timeoutId); + reject(new Error('Request timeout')); + controller.abort('Cancel because of timeout'); + }, req.timeout * 1000); + }); + const request = new Request(req.url, { + method: req.method, + headers: req.headers, + redirect: 'follow', + body: req.body, + }); + return Promise.race([ + WebTransport.originalFetch(request, { + signal: controller.abortController.signal, + credentials: 'omit', + cache: 'no-cache', + }).then((response) => { + if (timeoutId) + clearTimeout(timeoutId); + return response; + }), + requestTimeout, + ]); + }); + } + /** + * Send network request using legacy XMLHttpRequest API. + * + * @param req - Transport API agnostic request object with prepared body and URL. + * @param controller - Request cancellation controller (for long-poll requests). + * + * @returns Promise which will be resolved or rejected at the end of network request processing. + * + * @internal + */ + sendXHRRequest(req, controller) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + var _a; + const xhr = new XMLHttpRequest(); + xhr.open(req.method, req.url, true); + let aborted = false; + // Setup request + xhr.responseType = 'arraybuffer'; + xhr.timeout = req.timeout * 1000; + controller.abortController.signal.onabort = () => { + if (xhr.readyState == XMLHttpRequest.DONE || xhr.readyState == XMLHttpRequest.UNSENT) + return; + aborted = true; + xhr.abort(); + }; + Object.entries((_a = req.headers) !== null && _a !== void 0 ? _a : {}).forEach(([key, value]) => xhr.setRequestHeader(key, value)); + // Setup handlers to match `fetch` results handling. + xhr.onabort = () => { + reject(new Error('Aborted')); + }; + xhr.ontimeout = () => { + reject(new Error('Request timeout')); + }; + xhr.onerror = () => { + if (!aborted) { + const response = this.transportResponseFromXHR(req.url, xhr); + reject(new Error(PubNubAPIError.create(response).message)); + } + }; + xhr.onload = () => { + const headers = new Headers(); + xhr + .getAllResponseHeaders() + .split('\r\n') + .forEach((header) => { + const [key, value] = header.split(': '); + if (key.length > 1 && value.length > 1) + headers.append(key, value); + }); + resolve(new Response(xhr.response, { status: xhr.status, headers, statusText: xhr.statusText })); + }; + xhr.send(req.body); + }); + }); + } + /** + * Creates a Web Request object from a given {@link TransportRequest} object. + * + * @param req - The {@link TransportRequest} object containing request information. + * + * @returns Request object generated from the {@link TransportRequest} object. + * + * @internal + */ + webTransportRequestFromTransportRequest(req) { + return __awaiter(this, void 0, void 0, function* () { + let body; + let path = req.path; + // Create a multipart request body. + if (req.formData && req.formData.length > 0) { + // Reset query parameters to conform to signed URL + req.queryParameters = {}; + const file = req.body; + const formData = new FormData(); + for (const { key, value } of req.formData) + formData.append(key, value); + try { + const fileData = yield file.toArrayBuffer(); + formData.append('file', new Blob([fileData], { type: 'application/octet-stream' }), file.name); + } + catch (toBufferError) { + this.logger.warn('WebTransport', () => ({ messageType: 'error', message: toBufferError })); + try { + const fileData = yield file.toFileUri(); + // @ts-expect-error React Native File Uri support. + formData.append('file', fileData, file.name); + } + catch (toFileURLError) { + this.logger.error('WebTransport', () => ({ messageType: 'error', message: toFileURLError })); + } + } + body = formData; + } + // Handle regular body payload (if passed). + else if (req.body && (typeof req.body === 'string' || req.body instanceof ArrayBuffer)) { + // Compressing body if the browser has native support. + if (req.compressible && typeof CompressionStream !== 'undefined') { + const bodyArrayBuffer = typeof req.body === 'string' ? WebTransport.encoder.encode(req.body) : req.body; + const initialBodySize = bodyArrayBuffer.byteLength; + const bodyStream = new ReadableStream({ + start(controller) { + controller.enqueue(bodyArrayBuffer); + controller.close(); + }, + }); + body = yield new Response(bodyStream.pipeThrough(new CompressionStream('deflate'))).arrayBuffer(); + this.logger.trace('WebTransport', () => { + const compressedSize = body.byteLength; + const ratio = (compressedSize / initialBodySize).toFixed(2); + return { + messageType: 'text', + message: `Body of ${initialBodySize} bytes, compressed by ${ratio}x to ${compressedSize} bytes.`, + }; + }); + } + else + body = req.body; + } + if (req.queryParameters && Object.keys(req.queryParameters).length !== 0) + path = `${path}?${queryStringFromObject(req.queryParameters)}`; + return { + url: `${req.origin}${path}`, + method: req.method, + headers: req.headers, + timeout: req.timeout, + body, + }; + }); + } + /** + * Check whether the original ` fetch ` has been monkey patched or not. + * + * @returns `true` if original `fetch` has been patched. + */ + isFetchMonkeyPatched(oFetch) { + const fetchString = (oFetch !== null && oFetch !== void 0 ? oFetch : fetch).toString(); + return !fetchString.includes('[native code]') && fetch.name !== 'fetch'; + } + /** + * Create service response from {@link XMLHttpRequest} processing result. + * + * @param url - Used endpoint url. + * @param xhr - `HTTPClient`, which has been used to make a request. + * + * @returns Pre-processed transport response. + */ + transportResponseFromXHR(url, xhr) { + const allHeaders = xhr.getAllResponseHeaders().split('\n'); + const headers = {}; + for (const header of allHeaders) { + const [key, value] = header.trim().split(':'); + if (key && value) + headers[key.toLowerCase()] = value.trim(); + } + return { status: xhr.status, url, headers, body: xhr.response }; + } + /** + * Retrieve the original ` fetch ` implementation. + * + * Retrieve implementation which hasn't been patched by APM tools. + * + * @returns Reference to the `fetch` function. + */ + static getOriginalFetch() { + // The iframe-based APM workaround requires a DOM. In DOM-less contexts (e.g. MV3 service workers) there is + // no `document`, and `fetch` cannot be reached through a fresh browsing context — return the context `fetch` + // directly. This is safe there: without a DOM there is no APM page script to monkey patch `fetch` in the + // first place. This environment check is what keeps the unconditional call in the constructor safe. + // + // `fetch` must be bound to the global scope: native `fetch` requires its `this` to be the `Window` / + // `WorkerGlobalScope`, and it is later invoked detached (`WebTransport.originalFetch(...)`). Without the bind + // a service worker throws "Failed to execute 'fetch' on 'WorkerGlobalScope': Illegal invocation". + if (typeof document === 'undefined' || !document.body) + return fetch.bind(globalThis); + let iframe = document.querySelector('iframe[name="pubnub-context-unpatched-fetch"]'); + if (!iframe) { + iframe = document.createElement('iframe'); + iframe.style.display = 'none'; + iframe.name = 'pubnub-context-unpatched-fetch'; + iframe.src = 'about:blank'; + document.body.appendChild(iframe); + } + if (iframe.contentWindow) + return iframe.contentWindow.fetch.bind(iframe.contentWindow); + return fetch.bind(globalThis); + } + } + /** + * Request body decoder. + * + * @internal + */ + WebTransport.encoder = new TextEncoder(); + /** + * Service {@link ArrayBuffer} response decoder. + * + * @internal + */ + WebTransport.decoder = new TextDecoder(); + + /** + * Network request module. + * + * @internal + */ + /** + * Base REST API request class. + * + * @internal + */ + class AbstractRequest { + /** + * Construct base request. + * + * Constructed request by default won't be cancellable and performed using `GET` HTTP method. + * + * @param params - Request configuration parameters. + */ + constructor(params) { + this.params = params; + /** + * Unique request identifier. + */ + this.requestIdentifier = uuidGenerator.createUUID(); + this._cancellationController = null; + } + /** + * Retrieve configured cancellation controller. + * + * @returns Cancellation controller. + */ + get cancellationController() { + return this._cancellationController; + } + /** + * Update request cancellation controller. + * + * Controller itself provided by transport provider implementation and set only when request + * sending has been scheduled. + * + * @param controller - Cancellation controller or `null` to reset it. + */ + set cancellationController(controller) { + this._cancellationController = controller; + } + /** + * Abort request if possible. + * + * @param [reason] Information about why request has been cancelled. + */ + abort(reason) { + if (this && this.cancellationController) + this.cancellationController.abort(reason); + } + /** + * Target REST API endpoint operation type. + */ + operation() { + throw Error('Should be implemented by subclass.'); + } + /** + * Validate user-provided data before scheduling request. + * + * @returns Error message if request can't be sent without missing or malformed parameters. + */ + validate() { + return undefined; + } + /** + * Parse service response. + * + * @param response - Raw service response which should be parsed. + */ + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return this.deserializeResponse(response); + }); + } + /** + * Create platform-agnostic request object. + * + * @returns Request object which can be processed using platform-specific requirements. + */ + request() { + var _a, _b, _c, _d, _e, _f; + const request = { + method: (_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.method) !== null && _b !== void 0 ? _b : TransportMethod.GET, + path: this.path, + queryParameters: this.queryParameters, + cancellable: (_d = (_c = this.params) === null || _c === void 0 ? void 0 : _c.cancellable) !== null && _d !== void 0 ? _d : false, + compressible: (_f = (_e = this.params) === null || _e === void 0 ? void 0 : _e.compressible) !== null && _f !== void 0 ? _f : false, + timeout: 10, + identifier: this.requestIdentifier, + }; + // Attach headers (if required). + const headers = this.headers; + if (headers) + request.headers = headers; + // Attach body (if required). + if (request.method === TransportMethod.POST || + request.method === TransportMethod.PATCH || + request.method === TransportMethod.PUT) { + const [body, formData] = [this.body, this.formData]; + if (formData) + request.formData = formData; + if (body) + request.body = body; + } + return request; + } + /** + * Target REST API endpoint request headers getter. + * + * @returns Key/value headers which should be used with request. + */ + get headers() { + var _a, _b; + return Object.assign({ 'Accept-Encoding': 'gzip, deflate' }, (((_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.compressible) !== null && _b !== void 0 ? _b : false) ? { 'Content-Encoding': 'deflate' } : {})); + } + /** + * Target REST API endpoint request path getter. + * + * @returns REST API path. + */ + get path() { + throw Error('`path` getter should be implemented by subclass.'); + } + /** + * Target REST API endpoint request query parameters getter. + * + * @returns Key/value pairs which should be appended to the REST API path. + */ + get queryParameters() { + return {}; + } + get formData() { + return undefined; + } + /** + * Target REST API Request body payload getter. + * + * @returns Buffer of stringified data which should be sent with `POST` or `PATCH` request. + */ + get body() { + return undefined; + } + /** + * Deserialize service response. + * + * @param response - Transparent response object with headers and body information. + * + * @returns Deserialized service response data. + * + * @throws {Error} if received service response can't be processed (has unexpected content-type or can't be parsed as + * JSON). + */ + deserializeResponse(response) { + const responseText = AbstractRequest.decoder.decode(response.body); + const contentType = response.headers['content-type']; + let parsedJson; + if (!contentType || (contentType.indexOf('javascript') === -1 && contentType.indexOf('json') === -1)) + throw new PubNubError('Service response error, check status for details', createMalformedResponseError(responseText, response.status)); + try { + parsedJson = JSON.parse(responseText); + } + catch (error) { + console.error('Error parsing JSON response:', error); + throw new PubNubError('Service response error, check status for details', createMalformedResponseError(responseText, response.status)); + } + // Throw and exception in case of client / server error. + if ('status' in parsedJson && typeof parsedJson.status === 'number' && parsedJson.status >= 400) + throw PubNubAPIError.create(response); + return parsedJson; + } + } + /** + * Service `ArrayBuffer` response decoder. + */ + AbstractRequest.decoder = new TextDecoder(); + + /** + * Subscription REST API module. + */ + // -------------------------------------------------------- + // ---------------------- Defaults ------------------------ + // -------------------------------------------------------- + // region Defaults + /** + * Whether should subscribe to channels / groups presence announcements or not. + */ + const WITH_PRESENCE = false; + // endregion + // -------------------------------------------------------- + // ------------------------ Types ------------------------- + // -------------------------------------------------------- + // region Types + /** + * PubNub-defined event types by payload. + */ + var PubNubEventType; + (function (PubNubEventType) { + /** + * Presence change event. + */ + PubNubEventType[PubNubEventType["Presence"] = -2] = "Presence"; + /** + * Regular message event. + * + * **Note:** This is default type assigned for non-presence events if `e` field is missing. + */ + PubNubEventType[PubNubEventType["Message"] = -1] = "Message"; + /** + * Signal data event. + */ + PubNubEventType[PubNubEventType["Signal"] = 1] = "Signal"; + /** + * App Context object event. + */ + PubNubEventType[PubNubEventType["AppContext"] = 2] = "AppContext"; + /** + * Message reaction event. + */ + PubNubEventType[PubNubEventType["MessageAction"] = 3] = "MessageAction"; + /** + * Files event. + */ + PubNubEventType[PubNubEventType["Files"] = 4] = "Files"; + /** + * DataSync object change event. + * + * **Note:** Value must equal `5` to match the service wire value (`e: 5`). + */ + PubNubEventType[PubNubEventType["DataSync"] = 5] = "DataSync"; + })(PubNubEventType || (PubNubEventType = {})); + /** + * Event types which this SDK version knows how to parse. + * + * Events with any other `e` value are ignored: they most likely originate from a service release newer than + * the SDK + */ + const KNOWN_EVENT_TYPES = new Set([ + PubNubEventType.Presence, + PubNubEventType.Message, + PubNubEventType.Signal, + PubNubEventType.AppContext, + PubNubEventType.MessageAction, + PubNubEventType.Files, + PubNubEventType.DataSync, + ]); + /** + * Reserved DataSync system class names (lower-cased) → normalized object kind. + * + * Only consulted when the wire {@link DataSyncData.type} is the generic `entity` / `relationship` + * kind, and only for classes the service marks as `Global` (see {@link DataSyncClassLevel}) — so a + * developer-defined class which happens to share one of these names is not mistaken for a typed + * resource. Keys are compared case-insensitively. + * + * @internal + */ + const DATA_SYNC_RESERVED_CLASSES = { + user: 'user', + channel: 'channel', + membership: 'membership', + }; + // endregion + /** + * Base subscription request implementation. + * + * Subscription request used in small variations in two cases: + * - subscription manager + * - event engine + * + * @internal + */ + class BaseSubscribeRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c; + var _d, _e, _f; + super({ cancellable: true }); + this.parameters = parameters; + // Apply default request parameters. + (_a = (_d = this.parameters).withPresence) !== null && _a !== void 0 ? _a : (_d.withPresence = WITH_PRESENCE); + (_b = (_e = this.parameters).channelGroups) !== null && _b !== void 0 ? _b : (_e.channelGroups = []); + (_c = (_f = this.parameters).channels) !== null && _c !== void 0 ? _c : (_f.channels = []); + } + operation() { + return RequestOperation$1.PNSubscribeOperation; + } + validate() { + const { keySet: { subscribeKey }, channels, channelGroups, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channels && !channelGroups) + return '`channels` and `channelGroups` both should not be empty'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + let serviceResponse; + let responseText; + try { + responseText = AbstractRequest.decoder.decode(response.body); + const parsedJson = JSON.parse(responseText); + serviceResponse = parsedJson; + } + catch (error) { + console.error('Error parsing JSON response:', error); + } + if (!serviceResponse) { + throw new PubNubError('Service response error, check status for details', createMalformedResponseError(responseText, response.status)); + } + const events = serviceResponse.m + .filter((envelope) => { + const subscribable = envelope.b === undefined ? envelope.c : envelope.b; + return ((this.parameters.channels && this.parameters.channels.includes(subscribable)) || + (this.parameters.channelGroups && this.parameters.channelGroups.includes(subscribable))); + }) + .map((envelope) => { + let { e: eventType } = envelope; + // Events delivered on a presence channel are always presence events: the `-pnpres` suffix wins over + // the service-reported type. `envelope.c` is the actual channel (`envelope.b` is the channel group + // name), so this also covers presence delivered through a subscribed channel group. + if (envelope.c.endsWith('-pnpres')) + eventType = PubNubEventType.Presence; + // Resolve missing event type. + else + eventType !== null && eventType !== void 0 ? eventType : (eventType = PubNubEventType.Message); + // Ignore an event type this SDK version cannot parse rather than delivering an unexpected payload. + if (!KNOWN_EVENT_TYPES.has(eventType)) + return undefined; + const pn_mfp = messageFingerprint(envelope.d); + // Check whether payload is string (potentially encrypted data). + if (eventType != PubNubEventType.Presence && + eventType != PubNubEventType.Signal && + typeof envelope.d === 'string') { + if (eventType == PubNubEventType.Message) { + return { + type: PubNubEventType.Message, + data: this.messageFromEnvelope(envelope), + pn_mfp, + }; + } + return { + type: PubNubEventType.Files, + data: this.fileFromEnvelope(envelope), + pn_mfp, + }; + } + else if (eventType == PubNubEventType.Message) { + return { + type: PubNubEventType.Message, + data: this.messageFromEnvelope(envelope), + pn_mfp, + }; + } + else if (eventType === PubNubEventType.Presence) { + return { + type: PubNubEventType.Presence, + data: this.presenceEventFromEnvelope(envelope), + pn_mfp, + }; + } + else if (eventType == PubNubEventType.Signal) { + return { + type: PubNubEventType.Signal, + data: this.signalFromEnvelope(envelope), + pn_mfp, + }; + } + else if (eventType === PubNubEventType.AppContext) { + return { + type: PubNubEventType.AppContext, + data: this.appContextFromEnvelope(envelope), + pn_mfp, + }; + } + else if (eventType === PubNubEventType.MessageAction) { + return { + type: PubNubEventType.MessageAction, + data: this.messageActionFromEnvelope(envelope), + pn_mfp, + }; + } + else if (eventType === PubNubEventType.DataSync) { + const dataSync = this.dataSyncFromEnvelope(envelope); + // Guard: only treat as DataSync when the service marks it so; otherwise fall back to message. + if (dataSync) + return { type: PubNubEventType.DataSync, data: dataSync, pn_mfp }; + return { type: PubNubEventType.Message, data: this.messageFromEnvelope(envelope), pn_mfp }; + } + // The only known event type left is a file event. + return { + type: PubNubEventType.Files, + data: this.fileFromEnvelope(envelope), + pn_mfp, + }; + }) + .filter((event) => event !== undefined); + return { + cursor: { timetoken: serviceResponse.t.t, region: serviceResponse.t.r }, + messages: events, + }; + }); + } + get headers() { + var _a; + return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { accept: 'text/javascript' }); + } + // -------------------------------------------------------- + // ------------------ Envelope parsing -------------------- + // -------------------------------------------------------- + // region Envelope parsing + presenceEventFromEnvelope(envelope) { + var _a; + const { d: payload } = envelope; + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + // Clean up channel and subscription name from presence suffix. + const trimmedChannel = channel.replace('-pnpres', ''); + // Backward compatibility with deprecated properties. + const actualChannel = subscription !== null ? trimmedChannel : null; + const subscribedChannel = subscription !== null ? subscription : trimmedChannel; + // Presence payloads are objects. A string can only reach here when a non-presence payload has been published + // on a `-pnpres` channel: try to read it as JSON and never spread a string (which would add character-indexed + // keys to the event). + let presenceData; + if (typeof payload === 'string') { + try { + const parsed = JSON.parse(payload); + if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) + presenceData = parsed; + } + catch (_b) { + // Not JSON (encrypted or plain-text publish): payload contributes no presence fields. + } + } + else + presenceData = payload; + if (presenceData) { + if ('data' in presenceData) { + // @ts-expect-error This is `state-change` object which should have `state` field. + presenceData['state'] = presenceData.data; + delete presenceData.data; + } + else if ('action' in presenceData && presenceData.action === 'interval') { + presenceData.hereNowRefresh = (_a = presenceData.here_now_refresh) !== null && _a !== void 0 ? _a : false; + delete presenceData.here_now_refresh; + } + } + return Object.assign({ channel: trimmedChannel, subscription, + actualChannel, + subscribedChannel, timetoken: envelope.p.t }, (presenceData !== null && presenceData !== void 0 ? presenceData : {})); + } + messageFromEnvelope(envelope) { + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + const [message, decryptionError] = this.decryptedData(envelope.d); + // Backward compatibility with deprecated properties. + const actualChannel = subscription !== null ? channel : null; + const subscribedChannel = subscription !== null ? subscription : channel; + // Basic message event payload. + const event = { + channel, + subscription, + actualChannel, + subscribedChannel, + timetoken: envelope.p.t, + publisher: envelope.i, + message, + }; + if (envelope.u) + event.userMetadata = envelope.u; + if (envelope.cmt) + event.customMessageType = envelope.cmt; + if (decryptionError) + event.error = decryptionError; + return event; + } + signalFromEnvelope(envelope) { + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + const event = { + channel, + subscription, + timetoken: envelope.p.t, + publisher: envelope.i, + message: envelope.d, + }; + if (envelope.u) + event.userMetadata = envelope.u; + if (envelope.cmt) + event.customMessageType = envelope.cmt; + return event; + } + messageActionFromEnvelope(envelope) { + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + const action = envelope.d; + return { + channel, + subscription, + timetoken: envelope.p.t, + publisher: envelope.i, + event: action.event, + data: Object.assign(Object.assign({}, action.data), { uuid: envelope.i }), + }; + } + appContextFromEnvelope(envelope) { + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + const object = envelope.d; + return { + channel, + subscription, + timetoken: envelope.p.t, + message: object, + }; + } + dataSyncFromEnvelope(envelope) { + var _a; + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + const payload = envelope.d; + const metadata = payload === null || payload === void 0 ? void 0 : payload.metadata; + // Only treat the envelope as DataSync when the service marks it and carries the required fields. + if (!metadata || metadata.source !== 'data-sync' || !metadata.event || !metadata.type) + return undefined; + // Wire `className` is a bare class name (`User`, `Membership`, `Customer`); the `:`-splitting below + // is only there to keep tolerating the retired positional composite (`User::` / `::Customer`). + const classSegments = metadata.className ? metadata.className.split(':') : []; + const nonEmptySegments = classSegments.filter((segment) => segment.length > 0); + const className = nonEmptySegments.length > 0 ? nonEmptySegments[nonEmptySegments.length - 1] : undefined; + const classLevel = metadata.classLevel; + // `classLevel` authoritatively separates the built-in classes from developer-defined ones, so a + // developer class named `User` / `Channel` / `Membership` is not mistaken for a typed resource. + // When it is absent (service predating the field) fall back to the legacy positional heuristic, + // where the system class was the first segment. + const systemClass = classLevel === undefined ? classSegments[0] : classLevel === 'Global' ? className : undefined; + // The service reports the semantic kind directly; the class-name lookup only fills it in for a + // service which still sends the built-in classes under the generic `entity` / `relationship` kind. + const genericType = metadata.type === 'entity' || metadata.type === 'relationship'; + const objectType = genericType + ? (systemClass && DATA_SYNC_RESERVED_CLASSES[systemClass.toLowerCase()]) || metadata.type + : metadata.type; + const parsedVersion = metadata.classVersion !== undefined ? Number.parseInt(`${metadata.classVersion}`, 10) : NaN; + const classVersion = Number.isNaN(parsedVersion) ? undefined : parsedVersion; + const raw = ((_a = payload.data) !== null && _a !== void 0 ? _a : {}); + // Class identity is reported once, on the event, so it is shared by every event shape. + const common = { + version: payload.version, + source: metadata.source, + type: metadata.type, + className, + classLevel, + classVersion, + }; + // `data` mirrors the object as sent by the service, and its shape is tied to `event` / + // `objectType` — which is what makes `message` a discriminated union for the consumer. + let message; + if (metadata.event === 'delete' && objectType === 'membership') { + const data = { + id: raw.id, + deletedAt: raw.deletedAt, + }; + // Membership deletes name the endpoints they joined. Other fields stay trimmed. + if (typeof raw.channelId === 'string') + data.channelId = raw.channelId; + if (typeof raw.userId === 'string') + data.userId = raw.userId; + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data }); + } + else if (metadata.event === 'delete' && objectType === 'relationship') { + const data = { + id: raw.id, + deletedAt: raw.deletedAt, + }; + // Relationship deletes name the entities they linked. Other fields stay trimmed. + if (typeof raw.entityAId === 'string') + data.entityAId = raw.entityAId; + if (typeof raw.entityBId === 'string') + data.entityBId = raw.entityBId; + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data }); + } + else if (metadata.event === 'delete') + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: { id: raw.id, deletedAt: raw.deletedAt } }); + else if (objectType === 'membership') + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); + else if (objectType === 'relationship') + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); + else + message = Object.assign(Object.assign({}, common), { event: metadata.event, objectType, data: Object.assign({}, raw) }); + return { + channel, + subscription, + timetoken: envelope.p.t, + message, + }; + } + fileFromEnvelope(envelope) { + const [channel, subscription] = this.subscriptionChannelFromEnvelope(envelope); + const [file, decryptionError] = this.decryptedData(envelope.d); + let errorMessage = decryptionError; + // Basic file event payload. + const event = { + channel, + subscription, + timetoken: envelope.p.t, + publisher: envelope.i, + }; + if (envelope.u) + event.userMetadata = envelope.u; + if (!file) + errorMessage !== null && errorMessage !== void 0 ? errorMessage : (errorMessage = `File information payload is missing.`); + else if (typeof file === 'string') + errorMessage !== null && errorMessage !== void 0 ? errorMessage : (errorMessage = `Unexpected file information payload data type.`); + else { + event.message = file.message; + if (file.file) { + event.file = { + id: file.file.id, + name: file.file.name, + url: this.parameters.getFileUrl({ id: file.file.id, name: file.file.name, channel }), + }; + } + } + if (envelope.cmt) + event.customMessageType = envelope.cmt; + if (errorMessage) + event.error = errorMessage; + return event; + } + // endregion + subscriptionChannelFromEnvelope(envelope) { + return [envelope.c, envelope.b === undefined ? envelope.c : envelope.b]; + } + /** + * Decrypt provided `data`. + * + * @param [data] - Message or file information which should be decrypted if possible. + * + * @returns Tuple with decrypted data and decryption error (if any). + */ + decryptedData(data) { + if (!this.parameters.crypto || typeof data !== 'string') + return [data, undefined]; + let payload; + let error; + try { + const decryptedData = this.parameters.crypto.decrypt(data); + payload = + decryptedData instanceof ArrayBuffer + ? JSON.parse(SubscribeRequest.decoder.decode(decryptedData)) + : decryptedData; + } + catch (err) { + payload = null; + error = `Error while decrypting message content: ${err.message}`; + } + return [(payload !== null && payload !== void 0 ? payload : data), error]; + } + } + /** + * Subscribe request. + * + * @internal + */ + class SubscribeRequest extends BaseSubscribeRequest { + get path() { + var _a; + const { keySet: { subscribeKey }, channels, } = this.parameters; + return `/v2/subscribe/${subscribeKey}/${encodeNames((_a = channels === null || channels === void 0 ? void 0 : channels.sort()) !== null && _a !== void 0 ? _a : [], ',')}/0`; + } + get queryParameters() { + const { channelGroups, filterExpression, heartbeat, state, timetoken, region, onDemand } = this.parameters; + const query = {}; + if (onDemand) + query['on-demand'] = 1; + if (channelGroups && channelGroups.length > 0) + query['channel-group'] = channelGroups.sort().join(','); + if (filterExpression && filterExpression.length > 0) + query['filter-expr'] = filterExpression; + if (heartbeat) + query.heartbeat = heartbeat; + if (state && Object.keys(state).length > 0) + query['state'] = JSON.stringify(state); + if (timetoken !== undefined && typeof timetoken === 'string') { + if (timetoken.length > 0 && timetoken !== '0') + query['tt'] = timetoken; + } + else if (timetoken !== undefined && timetoken > 0) + query['tt'] = timetoken; + if (region) + query['tr'] = region; + return query; + } + } + + /** + * Events dispatcher module. + */ + /** + * Real-time events dispatcher. + * + * Class responsible for listener management and invocation. + * + * @internal + */ + class EventDispatcher { + constructor() { + /** + * Whether listeners has been added or not. + */ + this.hasListeners = false; + /** + * List of registered event handlers. + * + * **Note:** the First element is reserved for type-based event handlers. + */ + this.listeners = [{ count: -1, listener: {} }]; + } + /** + * Set a connection status change event handler. + * + * @param listener - Listener function, which will be called each time when the connection status changes. + */ + set onStatus(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'status' }); + } + /** + * Set a new message handler. + * + * @param listener - Listener function, which will be called each time when a new message + * is received from the real-time network. + */ + set onMessage(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'message' }); + } + /** + * Set a new presence events handler. + * + * @param listener - Listener function, which will be called each time when a new + * presence event is received from the real-time network. + */ + set onPresence(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'presence' }); + } + /** + * Set a new signal handler. + * + * @param listener - Listener function, which will be called each time when a new signal + * is received from the real-time network. + */ + set onSignal(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'signal' }); + } + /** + * Set a new app context event handler. + * + * @param listener - Listener function, which will be called each time when a new + * app context event is received from the real-time network. + */ + set onObjects(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'objects' }); + } + /** + * Set a new message reaction event handler. + * + * @param listener - Listener function, which will be called each time when a + * new message reaction event is received from the real-time network. + */ + set onMessageAction(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'messageAction' }); + } + /** + * Set a new file handler. + * + * @param listener - Listener function, which will be called each time when a new file + * is received from the real-time network. + */ + set onFile(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'file' }); + } + /** + * Set a new DataSync event handler. + * + * @param listener - Listener function, which will be called each time when a new + * DataSync event is received from the real-time network. + */ + set onDataSync(listener) { + this.updateTypeOrObjectListener({ add: !!listener, listener, type: 'dataSync' }); + } + /** + * Dispatch received a real-time update. + * + * @param event - A real-time event from multiplexed subscription. + */ + handleEvent(event) { + if (!this.hasListeners) + return; + if (event.type === PubNubEventType.Message) + this.announce('message', event.data); + else if (event.type === PubNubEventType.Signal) + this.announce('signal', event.data); + else if (event.type === PubNubEventType.Presence) + this.announce('presence', event.data); + else if (event.type === PubNubEventType.AppContext) { + const { data: objectEvent } = event; + const { message: object } = objectEvent; + this.announce('objects', objectEvent); + if (object.type === 'uuid') { + const { message, channel } = objectEvent, restEvent = __rest(objectEvent, ["message", "channel"]); + const { event, type } = object, restObject = __rest(object, ["event", "type"]); + const userEvent = Object.assign(Object.assign({}, restEvent), { spaceId: channel, message: Object.assign(Object.assign({}, restObject), { event: event === 'set' ? 'updated' : 'removed', type: 'user' }) }); + this.announce('user', userEvent); + } + else if (object.type === 'channel') { + const { message, channel } = objectEvent, restEvent = __rest(objectEvent, ["message", "channel"]); + const { event, type } = object, restObject = __rest(object, ["event", "type"]); + const spaceEvent = Object.assign(Object.assign({}, restEvent), { spaceId: channel, message: Object.assign(Object.assign({}, restObject), { event: event === 'set' ? 'updated' : 'removed', type: 'space' }) }); + this.announce('space', spaceEvent); + } + else if (object.type === 'membership') { + const { message, channel } = objectEvent, restEvent = __rest(objectEvent, ["message", "channel"]); + const { event, data } = object, restObject = __rest(object, ["event", "data"]); + const { uuid, channel: channelMeta } = data, restData = __rest(data, ["uuid", "channel"]); + const membershipEvent = Object.assign(Object.assign({}, restEvent), { spaceId: channel, message: Object.assign(Object.assign({}, restObject), { event: event === 'set' ? 'updated' : 'removed', data: Object.assign(Object.assign({}, restData), { user: uuid, space: channelMeta }) }) }); + this.announce('membership', membershipEvent); + } + } + else if (event.type === PubNubEventType.MessageAction) + this.announce('messageAction', event.data); + else if (event.type === PubNubEventType.Files) + this.announce('file', event.data); + else if (event.type === PubNubEventType.DataSync) + this.announce('dataSync', event.data); + } + /** + * Dispatch received connection status change. + * + * @param status - Status object which should be emitter for all status listeners. + */ + handleStatus(status) { + if (!this.hasListeners) + return; + this.announce('status', status); + } + /** + * Add events handler. + * + * @param listener - Events listener configuration object, which lets specify handlers for multiple types of events. + */ + addListener(listener) { + this.updateTypeOrObjectListener({ add: true, listener }); + } + removeListener(listener) { + this.updateTypeOrObjectListener({ add: false, listener }); + } + removeAllListeners() { + this.listeners = [{ count: -1, listener: {} }]; + this.hasListeners = false; + } + updateTypeOrObjectListener(parameters) { + if (parameters.type) { + if (typeof parameters.listener === 'function') + this.listeners[0].listener[parameters.type] = parameters.listener; + else + delete this.listeners[0].listener[parameters.type]; + } + else if (parameters.listener && typeof parameters.listener !== 'function') { + let listenerObject; + let listenerExists = false; + for (listenerObject of this.listeners) { + if (listenerObject.listener === parameters.listener) { + if (parameters.add) { + listenerObject.count++; + listenerExists = true; + } + else { + listenerObject.count--; + if (listenerObject.count === 0) + this.listeners.splice(this.listeners.indexOf(listenerObject), 1); + } + break; + } + } + if (parameters.add && !listenerExists) + this.listeners.push({ count: 1, listener: parameters.listener }); + } + this.hasListeners = this.listeners.length > 1 || Object.keys(this.listeners[0]).length > 0; + } + /** + * Announce a real-time event to all listeners. + * + * @param type - Type of event which should be announced. + * @param event - Announced real-time event payload. + */ + announce(type, event) { + this.listeners.forEach(({ listener }) => { + const typedListener = listener[type]; + // @ts-expect-error Dynamic events mapping. + if (typedListener) + typedListener(event); + }); + } + } + + /** + * Subscription reconnection-manager. + * + * **Note:** Reconnection manger rely on legacy time-based availability check. + * + * @internal + */ + /** + * Network "discovery" manager. + * + * Manager perform periodic `time` API calls to identify network availability. + * + * @internal + */ + class ReconnectionManager { + constructor(time) { + this.time = time; + } + /** + * Configure reconnection handler. + * + * @param callback - Successful availability check notify callback. + */ + onReconnect(callback) { + this.callback = callback; + } + /** + * Start periodic "availability" check. + */ + startPolling() { + this.timeTimer = setInterval(() => this.callTime(), 3000); + } + /** + * Stop periodic "availability" check. + */ + stopPolling() { + if (this.timeTimer) + clearInterval(this.timeTimer); + this.timeTimer = null; + } + callTime() { + this.time((status) => { + if (!status.error) { + this.stopPolling(); + if (this.callback) + this.callback(); + } + }); + } + } + + /** + * Messages de-duplication manager module. + * + * @internal + */ + /** + * Real-time events deduplication manager. + * + * @internal + */ + class DedupingManager { + /** + * Create and configure real-time events de-duplication manager. + * + * @param config - PubNub client configuration object. + */ + constructor(config) { + this.config = config; + config.logger().debug('DedupingManager', () => ({ + messageType: 'object', + message: { maximumCacheSize: config.maximumCacheSize }, + details: 'Create with configuration:', + })); + this.maximumCacheSize = config.maximumCacheSize; + this.hashHistory = []; + } + /** + * Compute unique real-time event payload key. + * + * @param message - Received real-time event payload for which unique key should be computed. + * @returns Unique real-time event payload key in messages cache. + */ + getKey(message) { + var _a; + return `${message.timetoken}-${this.hashCode(JSON.stringify((_a = message.message) !== null && _a !== void 0 ? _a : '')).toString()}`; + } + /** + * Check whether there is similar message already received or not. + * + * @param message - Received real-time event payload which should be checked for duplicates. + * @returns `true` in case if similar payload already has been received before. + */ + isDuplicate(message) { + return this.hashHistory.includes(this.getKey(message)); + } + /** + * Store received message to be used later for duplicate detection. + * + * @param message - Received real-time event payload. + */ + addEntry(message) { + if (this.hashHistory.length >= this.maximumCacheSize) { + this.hashHistory.shift(); + } + this.hashHistory.push(this.getKey(message)); + } + /** + * Clean up cached messages. + */ + clearHistory() { + this.hashHistory = []; + } + /** + * Compute message hash sum. + * + * @param payload - Received payload for which hash sum should be computed. + * @returns {number} - Resulting hash sum. + */ + hashCode(payload) { + let hash = 0; + if (payload.length === 0) + return hash; + for (let i = 0; i < payload.length; i += 1) { + const character = payload.charCodeAt(i); + hash = (hash << 5) - hash + character; // eslint-disable-line + hash = hash & hash; // eslint-disable-line + } + return hash; + } + } + + /** + * Subscription manager module. + * + * @internal + */ + /** + * Subscription loop manager. + * + * @internal + */ + class SubscriptionManager { + constructor(configuration, emitEvent, emitStatus, subscribeCall, heartbeatCall, leaveCall, time) { + this.configuration = configuration; + this.emitEvent = emitEvent; + this.emitStatus = emitStatus; + this.subscribeCall = subscribeCall; + this.heartbeatCall = heartbeatCall; + this.leaveCall = leaveCall; + /** + * Whether user code in event handlers requested disconnection or not. + * + * Won't continue subscription loop if user requested disconnection/unsubscribe from all in response to received + * event. + */ + this.disconnectedWhileHandledEvent = false; + configuration.logger().trace('SubscriptionManager', 'Create manager.'); + this.reconnectionManager = new ReconnectionManager(time); + this.dedupingManager = new DedupingManager(this.configuration); + this.heartbeatChannelGroups = {}; + this.heartbeatChannels = {}; + this.presenceChannelGroups = {}; + this.presenceChannels = {}; + this.heartbeatTimer = null; + this.presenceState = {}; + this.pendingChannelGroupSubscriptions = new Set(); + this.pendingChannelSubscriptions = new Set(); + this.channelGroups = {}; + this.channels = {}; + this.currentTimetoken = '0'; + this.lastTimetoken = '0'; + this.storedTimetoken = null; + this.referenceTimetoken = null; + this.subscriptionStatusAnnounced = false; + this.isOnline = true; + } + // region Information + /** + * Subscription-based current timetoken. + * + * @returns Timetoken based on current timetoken plus diff between current and loop start time. + */ + get subscriptionTimetoken() { + var _a; + return subscriptionTimetokenFromReference(this.currentTimetoken, (_a = this.referenceTimetoken) !== null && _a !== void 0 ? _a : '0'); + } + get subscribedChannels() { + return Object.keys(this.channels); + } + get subscribedChannelGroups() { + return Object.keys(this.channelGroups); + } + get abort() { + return this._subscribeAbort; + } + set abort(call) { + this._subscribeAbort = call; + } + // endregion + // region Subscription + disconnect() { + // Potentially called during received events handling. + // Mark to prevent subscription loop continuation in subscribe response handler. + this.disconnectedWhileHandledEvent = true; + this.stopSubscribeLoop(); + this.stopHeartbeatTimer(); + this.reconnectionManager.stopPolling(); + } + /** + * Restart subscription loop with current state. + * + * @param forUnsubscribe - Whether restarting subscription loop as part of channels list change on + * unsubscribe or not. + */ + reconnect(forUnsubscribe = false) { + this.startSubscribeLoop(forUnsubscribe); + // Starting heartbeat loop for provided channels and groups. + if (!forUnsubscribe && !this.configuration.useSmartHeartbeat) + this.startHeartbeatTimer(); + } + /** + * Update channels and groups used in subscription loop. + * + * @param parameters - Subscribe configuration parameters. + */ + subscribe(parameters) { + const { channels, channelGroups, timetoken, withPresence = false, withHeartbeats = false } = parameters; + if (timetoken) { + this.lastTimetoken = this.currentTimetoken; + this.currentTimetoken = `${timetoken}`; + } + if (this.currentTimetoken !== '0') { + this.storedTimetoken = this.currentTimetoken; + this.currentTimetoken = '0'; + } + channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => { + this.pendingChannelSubscriptions.add(channel); + this.channels[channel] = {}; + if (withPresence) + this.presenceChannels[channel] = {}; + if (withHeartbeats || this.configuration.getHeartbeatInterval()) + this.heartbeatChannels[channel] = {}; + }); + channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => { + this.pendingChannelGroupSubscriptions.add(group); + this.channelGroups[group] = {}; + if (withPresence) + this.presenceChannelGroups[group] = {}; + if (withHeartbeats || this.configuration.getHeartbeatInterval()) + this.heartbeatChannelGroups[group] = {}; + }); + this.subscriptionStatusAnnounced = false; + this.reconnect(); + } + unsubscribe(parameters, isOffline = false) { + let { channels, channelGroups } = parameters; + const actualChannelGroups = new Set(); + const actualChannels = new Set(); + channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => { + if (channel in this.channels) { + delete this.channels[channel]; + actualChannels.add(channel); + if (channel in this.heartbeatChannels) + delete this.heartbeatChannels[channel]; + } + if (channel in this.presenceState) + delete this.presenceState[channel]; + if (channel in this.presenceChannels) { + delete this.presenceChannels[channel]; + actualChannels.add(channel); + } + }); + channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => { + if (group in this.channelGroups) { + delete this.channelGroups[group]; + actualChannelGroups.add(group); + if (group in this.heartbeatChannelGroups) + delete this.heartbeatChannelGroups[group]; + } + if (group in this.presenceState) + delete this.presenceState[group]; + if (group in this.presenceChannelGroups) { + delete this.presenceChannelGroups[group]; + actualChannelGroups.add(group); + } + }); + // There is no need to unsubscribe to empty list of data sources. + if (actualChannels.size === 0 && actualChannelGroups.size === 0) + return; + const lastTimetoken = this.lastTimetoken; + const currentTimetoken = this.currentTimetoken; + if (Object.keys(this.channels).length === 0 && + Object.keys(this.presenceChannels).length === 0 && + Object.keys(this.channelGroups).length === 0 && + Object.keys(this.presenceChannelGroups).length === 0) { + this.lastTimetoken = '0'; + this.currentTimetoken = '0'; + this.referenceTimetoken = null; + this.storedTimetoken = null; + this.region = null; + this.reconnectionManager.stopPolling(); + } + this.reconnect(true); + // Send leave request after long-poll connection closed and loop restarted (the same way as it happens in new + // subscription flow). + if (this.configuration.suppressLeaveEvents === false && !isOffline) { + channelGroups = Array.from(actualChannelGroups); + channels = Array.from(actualChannels); + this.leaveCall({ channels, channelGroups }, (status) => { + const { error } = status, restOfStatus = __rest(status, ["error"]); + let errorMessage; + if (error) { + if (status.errorData && + typeof status.errorData === 'object' && + 'message' in status.errorData && + typeof status.errorData.message === 'string') + errorMessage = status.errorData.message; + else if ('message' in status && typeof status.message === 'string') + errorMessage = status.message; + } + this.emitStatus(Object.assign(Object.assign({}, restOfStatus), { error: errorMessage !== null && errorMessage !== void 0 ? errorMessage : false, affectedChannels: channels, affectedChannelGroups: channelGroups, currentTimetoken, + lastTimetoken })); + }); + } + } + unsubscribeAll(isOffline = false) { + this.disconnectedWhileHandledEvent = true; + this.unsubscribe({ + channels: this.subscribedChannels, + channelGroups: this.subscribedChannelGroups, + }, isOffline); + } + /** + * Start next subscription loop. + * + * @param restartOnUnsubscribe - Whether restarting subscription loop as part of channels list change on + * unsubscribe or not. + * + * @internal + */ + startSubscribeLoop(restartOnUnsubscribe = false) { + this.disconnectedWhileHandledEvent = false; + this.stopSubscribeLoop(); + const channelGroups = [...Object.keys(this.channelGroups)]; + const channels = [...Object.keys(this.channels)]; + Object.keys(this.presenceChannelGroups).forEach((group) => channelGroups.push(`${group}-pnpres`)); + Object.keys(this.presenceChannels).forEach((channel) => channels.push(`${channel}-pnpres`)); + // There is no need to start subscription loop for an empty list of data sources. + if (channels.length === 0 && channelGroups.length === 0) + return; + this.subscribeCall(Object.assign(Object.assign(Object.assign({ channels, + channelGroups, state: this.presenceState, heartbeat: this.configuration.getPresenceTimeout(), timetoken: this.currentTimetoken }, (this.region !== null ? { region: this.region } : {})), (this.configuration.filterExpression ? { filterExpression: this.configuration.filterExpression } : {})), { onDemand: !this.subscriptionStatusAnnounced || restartOnUnsubscribe }), (status, result) => { + this.processSubscribeResponse(status, result); + }); + if (!restartOnUnsubscribe && this.configuration.useSmartHeartbeat) + this.startHeartbeatTimer(); + } + stopSubscribeLoop() { + if (this._subscribeAbort) { + this._subscribeAbort(); + this._subscribeAbort = null; + } + } + /** + * Process subscribe REST API endpoint response. + */ + processSubscribeResponse(status, result) { + if (status.error) { + // Ignore aborted request. + if ((typeof status.errorData === 'object' && + 'name' in status.errorData && + status.errorData.name === 'AbortError') || + status.category === StatusCategory$1.PNCancelledCategory) + return; + if (status.category === StatusCategory$1.PNTimeoutCategory) { + this.startSubscribeLoop(); + } + else if (status.category === StatusCategory$1.PNNetworkIssuesCategory || + status.category === StatusCategory$1.PNMalformedResponseCategory) { + this.disconnect(); + if (status.error && this.configuration.autoNetworkDetection && this.isOnline) { + this.isOnline = false; + this.emitStatus({ category: StatusCategory$1.PNNetworkDownCategory }); + } + this.reconnectionManager.onReconnect(() => { + if (this.configuration.autoNetworkDetection && !this.isOnline) { + this.isOnline = true; + this.emitStatus({ category: StatusCategory$1.PNNetworkUpCategory }); + } + this.reconnect(); + this.subscriptionStatusAnnounced = true; + const reconnectedAnnounce = { + category: StatusCategory$1.PNReconnectedCategory, + operation: status.operation, + lastTimetoken: this.lastTimetoken, + currentTimetoken: this.currentTimetoken, + }; + this.emitStatus(reconnectedAnnounce); + }); + this.reconnectionManager.startPolling(); + this.emitStatus(Object.assign(Object.assign({}, status), { category: StatusCategory$1.PNNetworkIssuesCategory })); + } + else if (status.category === StatusCategory$1.PNBadRequestCategory) { + this.stopHeartbeatTimer(); + this.emitStatus(status); + } + else + this.emitStatus(status); + return; + } + this.referenceTimetoken = referenceSubscribeTimetoken(result.cursor.timetoken, this.storedTimetoken); + if (this.storedTimetoken) { + this.currentTimetoken = this.storedTimetoken; + this.storedTimetoken = null; + } + else { + this.lastTimetoken = this.currentTimetoken; + this.currentTimetoken = result.cursor.timetoken; + } + if (!this.subscriptionStatusAnnounced) { + const connected = { + category: StatusCategory$1.PNConnectedCategory, + operation: status.operation, + affectedChannels: Array.from(this.pendingChannelSubscriptions), + subscribedChannels: this.subscribedChannels, + affectedChannelGroups: Array.from(this.pendingChannelGroupSubscriptions), + lastTimetoken: this.lastTimetoken, + currentTimetoken: this.currentTimetoken, + }; + this.subscriptionStatusAnnounced = true; + this.emitStatus(connected); + // Clear pending channels and groups. + this.pendingChannelGroupSubscriptions.clear(); + this.pendingChannelSubscriptions.clear(); + } + const { messages } = result; + const { requestMessageCountThreshold, dedupeOnSubscribe } = this.configuration; + if (requestMessageCountThreshold && messages.length >= requestMessageCountThreshold) { + this.emitStatus({ + category: StatusCategory$1.PNRequestMessageCountExceededCategory, + operation: status.operation, + }); + } + try { + const cursor = { + timetoken: this.currentTimetoken, + region: this.region ? this.region : undefined, + }; + this.configuration.logger().debug('SubscriptionManager', () => { + const hashedEvents = messages.map((event) => ({ + type: event.type, + data: Object.assign(Object.assign({}, event.data), { pn_mfp: event.pn_mfp }), + })); + return { messageType: 'object', message: hashedEvents, details: 'Received events:' }; + }); + messages.forEach((message) => { + if (dedupeOnSubscribe && 'message' in message.data && 'timetoken' in message.data) { + if (this.dedupingManager.isDuplicate(message.data)) { + this.configuration.logger().warn('SubscriptionManager', () => ({ + messageType: 'object', + message: message.data, + details: 'Duplicate message detected (skipped):', + })); + return; + } + this.dedupingManager.addEntry(message.data); + } + this.emitEvent(cursor, message); + }); + } + catch (e) { + const errorStatus = { + error: true, + category: StatusCategory$1.PNUnknownCategory, + errorData: e, + statusCode: 0, + }; + this.emitStatus(errorStatus); + } + this.region = result.cursor.region; + if (!this.disconnectedWhileHandledEvent) + this.startSubscribeLoop(); + else + this.disconnectedWhileHandledEvent = false; + } + // endregion + // region Presence + /** + * Update `uuid` state which should be sent with subscribe request. + * + * @param parameters - Channels and groups with state which should be associated to `uuid`. + */ + setState(parameters) { + const { state, channels, channelGroups } = parameters; + channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => channel in this.channels && (this.presenceState[channel] = state)); + channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => group in this.channelGroups && (this.presenceState[group] = state)); + } + /** + * Manual presence management. + * + * @param parameters - Desired presence state for provided list of channels and groups. + */ + changePresence(parameters) { + const { connected, channels, channelGroups } = parameters; + if (connected) { + channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => (this.heartbeatChannels[channel] = {})); + channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => (this.heartbeatChannelGroups[group] = {})); + } + else { + channels === null || channels === void 0 ? void 0 : channels.forEach((channel) => { + if (channel in this.heartbeatChannels) + delete this.heartbeatChannels[channel]; + }); + channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.forEach((group) => { + if (group in this.heartbeatChannelGroups) + delete this.heartbeatChannelGroups[group]; + }); + if (this.configuration.suppressLeaveEvents === false) { + this.leaveCall({ channels, channelGroups }, (status) => this.emitStatus(status)); + } + } + this.reconnect(); + } + startHeartbeatTimer() { + this.stopHeartbeatTimer(); + const heartbeatInterval = this.configuration.getHeartbeatInterval(); + if (!heartbeatInterval || heartbeatInterval === 0) + return; + // Sending immediate heartbeat only if not working as a smart heartbeat. + if (!this.configuration.useSmartHeartbeat) + this.sendHeartbeat(); + this.heartbeatTimer = setInterval(() => this.sendHeartbeat(), heartbeatInterval * 1000); + } + /** + * Stop heartbeat. + * + * Stop timer which trigger {@link HeartbeatRequest} sending with configured presence intervals. + */ + stopHeartbeatTimer() { + if (!this.heartbeatTimer) + return; + clearInterval(this.heartbeatTimer); + this.heartbeatTimer = null; + } + /** + * Send heartbeat request. + */ + sendHeartbeat() { + const heartbeatChannelGroups = Object.keys(this.heartbeatChannelGroups); + const heartbeatChannels = Object.keys(this.heartbeatChannels); + // There is no need to start heartbeat loop if there is no channels and groups to use. + if (heartbeatChannels.length === 0 && heartbeatChannelGroups.length === 0) + return; + this.heartbeatCall({ + channels: heartbeatChannels, + channelGroups: heartbeatChannelGroups, + heartbeat: this.configuration.getPresenceTimeout(), + state: this.presenceState, + }, (status) => { + if (status.error && this.configuration.announceFailedHeartbeats) + this.emitStatus(status); + if (status.error && this.configuration.autoNetworkDetection && this.isOnline) { + this.isOnline = false; + this.disconnect(); + this.emitStatus({ category: StatusCategory$1.PNNetworkDownCategory }); + this.reconnect(); + } + if (!status.error && this.configuration.announceSuccessfulHeartbeats) + this.emitStatus(status); + }); + } + } + + // endregion + /** + * Base notification payload object. + */ + class BaseNotificationPayload { + /** + * Base notification provider payload object. + * + * @internal + * + * @param payload - Object which contains vendor-specific preformatted push notification payload. + * @param title - Notification main title. + * @param body - Notification body (main messages). + */ + constructor(payload, title, body) { + this._payload = payload; + this.setDefaultPayloadStructure(); + this.title = title; + this.body = body; + } + /** + * Retrieve resulting notification payload content for message. + * + * @returns Preformatted push notification payload data. + */ + get payload() { + return this._payload; + } + /** + * Update notification title. + * + * @param value - New notification title. + */ + set title(value) { + this._title = value; + } + /** + * Update notification subtitle. + * + * @param value - New second-line notification title. + */ + set subtitle(value) { + this._subtitle = value; + } + /** + * Update notification body. + * + * @param value - Update main notification message (shown when expanded). + */ + set body(value) { + this._body = value; + } + /** + * Update application badge number. + * + * @param value - Number which should be shown in application badge upon receiving notification. + */ + set badge(value) { + this._badge = value; + } + /** + * Update notification sound. + * + * @param value - Name of the sound file which should be played upon notification receive. + */ + set sound(value) { + this._sound = value; + } + /** + * Platform-specific structure initialization. + * + * @internal + */ + setDefaultPayloadStructure() { } + /** + * Translate data object into PubNub push notification payload object. + * + * @internal + * + * @returns Preformatted push notification payload. + */ + toObject() { + return {}; + } + } + /** + * Message payload for Apple Push Notification Service. + */ + class APNSNotificationPayload extends BaseNotificationPayload { + constructor() { + super(...arguments); + /** + * Type of push notification service for which payload will be created. + * + * @internal + */ + this._apnsPushType = 'apns'; + /** + * Whether resulting payload should trigger silent notification or not. + * + * @internal + */ + this._isSilent = false; + } + get payload() { + return this._payload; + } + /** + * Update notification receivers configuration. + * + * @param value - New APNS2 configurations. + */ + set configurations(value) { + if (!value || !value.length) + return; + this._configurations = value; + } + /** + * Notification payload. + * + * @returns Platform-specific part of PubNub notification payload. + */ + get notification() { + return this.payload.aps; + } + /** + * Notification title. + * + * @returns Main notification title. + */ + get title() { + return this._title; + } + /** + * Update notification title. + * + * @param value - New notification title. + */ + set title(value) { + if (!value || !value.length) + return; + this.payload.aps.alert.title = value; + this._title = value; + } + /** + * Notification subtitle. + * + * @returns Second-line notification title. + */ + get subtitle() { + return this._subtitle; + } + /** + * Update notification subtitle. + * + * @param value - New second-line notification title. + */ + set subtitle(value) { + if (!value || !value.length) + return; + this.payload.aps.alert.subtitle = value; + this._subtitle = value; + } + /** + * Notification body. + * + * @returns Main notification message (shown when expanded). + */ + get body() { + return this._body; + } + /** + * Update notification body. + * + * @param value - Update main notification message (shown when expanded). + */ + set body(value) { + if (!value || !value.length) + return; + this.payload.aps.alert.body = value; + this._body = value; + } + /** + * Retrieve unread notifications number. + * + * @returns Number of unread notifications which should be shown on application badge. + */ + get badge() { + return this._badge; + } + /** + * Update application badge number. + * + * @param value - Number which should be shown in application badge upon receiving notification. + */ + set badge(value) { + if (value === undefined || value === null) + return; + this.payload.aps.badge = value; + this._badge = value; + } + /** + * Retrieve notification sound file. + * + * @returns Notification sound file name from resource bundle. + */ + get sound() { + return this._sound; + } + /** + * Update notification sound. + * + * @param value - Name of the sound file which should be played upon notification receive. + */ + set sound(value) { + if (!value || !value.length) + return; + this.payload.aps.sound = value; + this._sound = value; + } + /** + * Set whether notification should be silent or not. + * + * `content-available` notification type will be used to deliver silent notification if set to `true`. + * + * @param value - Whether notification should be sent as silent or not. + */ + set silent(value) { + this._isSilent = value; + } + /** + * Setup push notification payload default content. + * + * @internal + */ + setDefaultPayloadStructure() { + this.payload.aps = { alert: {} }; + } + /** + * Translate data object into PubNub push notification payload object. + * + * @internal + * + * @returns Preformatted push notification payload. + */ + toObject() { + const payload = Object.assign({}, this.payload); + const { aps } = payload; + let { alert } = aps; + if (this._isSilent) + aps['content-available'] = 1; + if (this._apnsPushType === 'apns2') { + if (!this._configurations || !this._configurations.length) + throw new ReferenceError('APNS2 configuration is missing'); + const configurations = []; + this._configurations.forEach((configuration) => { + configurations.push(this.objectFromAPNS2Configuration(configuration)); + }); + if (configurations.length) + payload.pn_push = configurations; + } + if (!alert || !Object.keys(alert).length) + delete aps.alert; + if (this._isSilent) { + delete aps.alert; + delete aps.badge; + delete aps.sound; + alert = {}; + } + return this._isSilent || (alert && Object.keys(alert).length) ? payload : null; + } + /** + * Create PubNub push notification service APNS2 configuration information object. + * + * @internal + * + * @param configuration - Source user-provided APNS2 configuration. + * + * @returns Preformatted for PubNub service APNS2 configuration information. + */ + objectFromAPNS2Configuration(configuration) { + if (!configuration.targets || !configuration.targets.length) + throw new ReferenceError('At least one APNS2 target should be provided'); + const { collapseId, expirationDate } = configuration; + const objectifiedConfiguration = { + auth_method: 'token', + targets: configuration.targets.map((target) => this.objectFromAPNSTarget(target)), + version: 'v2', + }; + if (collapseId && collapseId.length) + objectifiedConfiguration.collapse_id = collapseId; + if (expirationDate) + objectifiedConfiguration.expiration = expirationDate.toISOString(); + return objectifiedConfiguration; + } + /** + * Create PubNub push notification service APNS2 target information object. + * + * @internal + * + * @param target - Source user-provided data. + * + * @returns Preformatted for PubNub service APNS2 target information. + */ + objectFromAPNSTarget(target) { + if (!target.topic || !target.topic.length) + throw new TypeError("Target 'topic' undefined."); + const { topic, environment = 'development', excludedDevices = [] } = target; + const objectifiedTarget = { topic, environment }; + if (excludedDevices.length) + objectifiedTarget.excluded_devices = excludedDevices; + return objectifiedTarget; + } + } + /** + * Message payload for Firebase Cloud Messaging service. + */ + class FCMNotificationPayload extends BaseNotificationPayload { + get payload() { + return this._payload; + } + /** + * Notification payload. + * + * @returns Platform-specific part of PubNub notification payload. + */ + get notification() { + return this.payload.notification; + } + /** + * Silent notification payload. + * + * @returns Silent notification payload (data notification). + */ + get data() { + return this.payload.data; + } + /** + * Retrieve Android notification payload and initialize required structure. + * + * @returns Android specific notification payload. + */ + get androidNotification() { + var _c; + return (_c = this.payload.android) === null || _c === void 0 ? void 0 : _c.notification; + } + /** + * Notification title. + * + * @returns Main notification title. + */ + get title() { + return this._title; + } + /** + * Update notification title. + * + * @param value - New notification title. + */ + set title(value) { + if (!value || !value.length) + return; + this.payload.notification.title = value; + this.androidNotification.title = value; + this._title = value; + } + /** + * Notification body. + * + * @returns Main notification message (shown when expanded). + */ + get body() { + return this._body; + } + /** + * Update notification body. + * + * @param value - Update main notification message (shown when expanded). + */ + set body(value) { + if (!value || !value.length) + return; + this.payload.notification.body = value; + this.androidNotification.body = value; + this._body = value; + } + /** + * Retrieve unread notifications number. + * + * @returns Number of unread notifications which should be shown on application badge. + */ + get badge() { + return this._badge; + } + /** + * Update application badge number. + * + * @param value - Number which should be shown in application badge upon receiving notification. + */ + set badge(value) { + if (value === undefined || value === null) + return; + this.androidNotification.notification_count = value; + this._badge = value; + } + /** + * Retrieve notification sound file. + * + * @returns Notification sound file name from resource bundle. + */ + get sound() { + return this._sound; + } + /** + * Update notification sound. + * + * @param value - Name of the sound file which should be played upon notification receive. + */ + set sound(value) { + if (!value || !value.length) + return; + this.androidNotification.sound = value; + this._sound = value; + } + /** + * Retrieve notification icon file. + * + * @returns Notification icon file name from resource bundle. + */ + get icon() { + return this._icon; + } + /** + * Update notification icon. + * + * @param value - Name of the icon file set for `android.notification.icon`. + */ + set icon(value) { + if (!value || !value.length) + return; + this.androidNotification.icon = value; + this._icon = value; + } + /** + * Retrieve notifications grouping tag. + * + * @returns Notifications grouping tag. + */ + get tag() { + return this._tag; + } + /** + * Update notifications grouping tag. + * + * @param value - String set for `android.notification.tag` to group similar notifications. + */ + set tag(value) { + if (!value || !value.length) + return; + this.androidNotification.tag = value; + this._tag = value; + } + /** + * Set whether notification should be silent or not. + * + * All notification data will be sent under `data` field if set to `true`. + * + * @param value - Whether notification should be sent as silent or not. + */ + set silent(value) { + this._isSilent = value; + } + /** + * Setup push notification payload default content. + * + * @internal + */ + setDefaultPayloadStructure() { + this.payload.notification = {}; + this.payload.data = {}; + this.payload.android = { notification: {} }; + } + /** + * Translate data object into PubNub push notification payload object. + * + * @internal + * + * @returns Preformatted push notification payload. + */ + toObject() { + var _c, _e; + const payload = {}; + const notification = Object.assign({}, this.payload.notification); + const android = Object.assign({}, this.payload.android); + const androidNotification = Object.assign({}, ((_c = android.notification) !== null && _c !== void 0 ? _c : {})); + // Strip title/body from android.notification — they belong in top-level notification (or data for silent). + const androidSpecificFields = __rest(androidNotification, ["title", "body"]); + if (this._isSilent) { + // For silent (data-only) notifications, strip all `notification` fields + // (both root and android) and move everything into the root `data` object. + const data = {}; + if (this._title) + data.title = this._title; + if (this._body) + data.body = this._body; + // Merge android-specific notification fields (sound, icon, tag, etc.) into data. + for (const [key, value] of Object.entries(androidSpecificFields)) { + if (value !== undefined && value !== null) + data[key] = String(value); + } + // Merge any existing user-provided custom data. + if (this.payload.data) + Object.assign(data, this.payload.data); + if (Object.keys(data).length) + payload.data = data; + // Exclude `notification` entirely from android — only keep non-notification android fields. + delete android.notification; + if (Object.keys(android).length) { + payload.android = android; + } + } + else { + if (Object.keys(notification).length) + payload.notification = notification; + // Include top-level data if present. + if (this.payload.data && Object.keys(this.payload.data).length) + payload.data = Object.assign({}, this.payload.data); + // android.notification should only contain android-specific fields (sound, icon, tag, etc.). + if (Object.keys(androidSpecificFields).length) { + const androidWithoutNotification = __rest(android, ["notification"]); + payload.android = Object.assign(Object.assign({}, androidWithoutNotification), { notification: androidSpecificFields }); + } + else { + const androidWithoutNotification = __rest(android, ["notification"]); + if (Object.keys(androidWithoutNotification).length) { + payload.android = androidWithoutNotification; + } + } + } + // Preserve other top-level FCM fields (apns, webpush, fcm_options, etc.). + const _f = this.payload, otherFields = __rest(_f, ["notification", "android", "data", "pn_exceptions"]); + Object.assign(payload, otherFields); + if ((_e = this.payload.pn_exceptions) === null || _e === void 0 ? void 0 : _e.length) + payload.pn_exceptions = this.payload.pn_exceptions; + return Object.keys(payload).length ? payload : null; + } + } + class NotificationsPayload { + /** + * Create push notification payload holder. + * + * @internal + * + * @param title - String which will be shown at the top of the notification (below app name). + * @param body - String with message which should be shown when user will check notification. + */ + constructor(title, body) { + this._payload = { apns: {}, fcm: {} }; + this._title = title; + this._body = body; + this.apns = new APNSNotificationPayload(this._payload.apns, title, body); + this.fcm = new FCMNotificationPayload(this._payload.fcm, title, body); + } + /** + * Enable or disable push notification debugging message. + * + * @param value - Whether debug message from push notification scheduler should be published to the specific + * channel or not. + */ + set debugging(value) { + this._debugging = value; + } + /** + * Notification title. + * + * @returns Main notification title. + */ + get title() { + return this._title; + } + /** + * Notification subtitle. + * + * @returns Second-line notification title. + */ + get subtitle() { + return this._subtitle; + } + /** + * Update notification subtitle. + * + * @param value - New second-line notification title. + */ + set subtitle(value) { + this._subtitle = value; + this.apns.subtitle = value; + this.fcm.subtitle = value; + } + /** + * Notification body. + * + * @returns Main notification message (shown when expanded). + */ + get body() { + return this._body; + } + /** + * Retrieve unread notifications number. + * + * @returns Number of unread notifications which should be shown on application badge. + */ + get badge() { + return this._badge; + } + /** + * Update application badge number. + * + * @param value - Number which should be shown in application badge upon receiving notification. + */ + set badge(value) { + this._badge = value; + this.apns.badge = value; + this.fcm.badge = value; + } + /** + * Retrieve notification sound file. + * + * @returns Notification sound file name from resource bundle. + */ + get sound() { + return this._sound; + } + /** + * Update notification sound. + * + * @param value - Name of the sound file which should be played upon notification receive. + */ + set sound(value) { + this._sound = value; + this.apns.sound = value; + this.fcm.sound = value; + } + /** + * Build notifications platform for requested platforms. + * + * @param platforms - List of platforms for which payload should be added to final dictionary. Supported values: + * fcm, apns, and apns2. + * + * @returns Object with data, which can be sent with publish method call and trigger remote notifications for + * specified platforms. + */ + buildPayload(platforms) { + const payload = {}; + if (platforms.includes('apns') || platforms.includes('apns2')) { + // @ts-expect-error Override APNS version. + this.apns._apnsPushType = platforms.includes('apns') ? 'apns' : 'apns2'; + const apnsPayload = this.apns.toObject(); + if (apnsPayload && Object.keys(apnsPayload).length) + payload.pn_apns = apnsPayload; + } + if (platforms.includes('fcm')) { + const fcmPayload = this.fcm.toObject(); + if (fcmPayload && Object.keys(fcmPayload).length) + payload.pn_fcm = fcmPayload; + } + if (Object.keys(payload).length && this._debugging) + payload.pn_debug = true; + return payload; + } + } + + /** + * Event Engine terminate signal listener module. + * + * @internal + */ + /** + * @internal + */ + class Subject { + constructor(sync = false) { + this.sync = sync; + this.listeners = new Set(); + } + subscribe(listener) { + this.listeners.add(listener); + return () => { + this.listeners.delete(listener); + }; + } + notify(event) { + const wrapper = () => { + this.listeners.forEach((listener) => { + listener(event); + }); + }; + if (this.sync) { + wrapper(); + } + else { + setTimeout(wrapper, 0); + } + } + } + + /** + * Event Engine Core state module. + * + * @internal + */ + /** + * Event engine current state object. + * + * State contains current context and list of invocations which should be performed by the Event Engine. + * + * @internal + */ + class State { + transition(context, event) { + var _a; + if (this.transitionMap.has(event.type)) { + return (_a = this.transitionMap.get(event.type)) === null || _a === void 0 ? void 0 : _a(context, event); + } + return undefined; + } + constructor(label) { + this.label = label; + this.transitionMap = new Map(); + this.enterEffects = []; + this.exitEffects = []; + } + on(eventType, transition) { + this.transitionMap.set(eventType, transition); + return this; + } + with(context, effects) { + return [this, context, effects !== null && effects !== void 0 ? effects : []]; + } + onEnter(effect) { + this.enterEffects.push(effect); + return this; + } + onExit(effect) { + this.exitEffects.push(effect); + return this; + } + } + + /** + * Event Engine Core module. + * + * @internal + */ + /** + * Generic event engine. + * + * @internal + */ + class Engine extends Subject { + constructor(logger) { + super(true); + this.logger = logger; + this._pendingEvents = []; + this._inTransition = false; + } + get currentState() { + return this._currentState; + } + get currentContext() { + return this._currentContext; + } + describe(label) { + return new State(label); + } + start(initialState, initialContext) { + this._currentState = initialState; + this._currentContext = initialContext; + this.notify({ + type: 'engineStarted', + state: initialState, + context: initialContext, + }); + return; + } + transition(event) { + if (!this._currentState) { + this.logger.error('Engine', 'Finite state machine is not started'); + throw new Error('Start the engine first'); + } + if (this._inTransition) { + this.logger.trace('Engine', () => ({ + messageType: 'object', + message: event, + details: 'Event engine in transition. Enqueue received event:', + })); + this._pendingEvents.push(event); + return; + } + else + this._inTransition = true; + this.logger.trace('Engine', () => ({ + messageType: 'object', + message: event, + details: 'Event engine received event:', + })); + this.notify({ + type: 'eventReceived', + event: event, + }); + const transition = this._currentState.transition(this._currentContext, event); + if (transition) { + const [newState, newContext, effects] = transition; + this.logger.trace('Engine', `Exiting state: ${this._currentState.label}`); + for (const effect of this._currentState.exitEffects) { + this.notify({ + type: 'invocationDispatched', + invocation: effect(this._currentContext), + }); + } + this.logger.trace('Engine', () => ({ + messageType: 'object', + details: `Entering '${newState.label}' state with context:`, + message: newContext, + })); + const oldState = this._currentState; + this._currentState = newState; + const oldContext = this._currentContext; + this._currentContext = newContext; + this.notify({ + type: 'transitionDone', + fromState: oldState, + fromContext: oldContext, + toState: newState, + toContext: newContext, + event: event, + }); + for (const effect of effects) { + this.notify({ + type: 'invocationDispatched', + invocation: effect, + }); + } + for (const effect of this._currentState.enterEffects) { + this.notify({ + type: 'invocationDispatched', + invocation: effect(this._currentContext), + }); + } + } + else + this.logger.warn('Engine', `No transition from '${this._currentState.label}' found for event: ${event.type}`); + this._inTransition = false; + // Check whether a pending task should be dequeued. + if (this._pendingEvents.length > 0) { + const nextEvent = this._pendingEvents.shift(); + if (nextEvent) { + this.logger.trace('Engine', () => ({ + messageType: 'object', + message: nextEvent, + details: 'De-queueing pending event:', + })); + this.transition(nextEvent); + } + } + } + } + + /** + * Event Engine Core Effects dispatcher module. + * + * @internal + */ + /** + * Event Engine effects dispatcher. + * + * Dispatcher responsible for invocation enqueue and dequeue for processing. + * + * @internal + */ + class Dispatcher { + constructor(dependencies, logger) { + this.dependencies = dependencies; + this.logger = logger; + this.instances = new Map(); + this.handlers = new Map(); + } + on(type, handlerCreator) { + this.handlers.set(type, handlerCreator); + } + dispatch(invocation) { + this.logger.trace('Dispatcher', `Process invocation: ${invocation.type}`); + if (invocation.type === 'CANCEL') { + if (this.instances.has(invocation.payload)) { + const instance = this.instances.get(invocation.payload); + instance === null || instance === void 0 ? void 0 : instance.cancel(); + this.instances.delete(invocation.payload); + } + return; + } + const handlerCreator = this.handlers.get(invocation.type); + if (!handlerCreator) { + this.logger.error('Dispatcher', `Unhandled invocation '${invocation.type}'`); + throw new Error(`Unhandled invocation '${invocation.type}'`); + } + const instance = handlerCreator(invocation.payload, this.dependencies); + this.logger.trace('Dispatcher', () => ({ + messageType: 'object', + details: 'Call invocation handler with parameters:', + message: invocation.payload, + ignoredKeys: ['abortSignal'], + })); + if (invocation.managed) { + this.instances.set(invocation.type, instance); + } + instance.start(); + } + dispose() { + for (const [key, instance] of this.instances.entries()) { + instance.cancel(); + this.instances.delete(key); + } + } + } + + /** + * Event Engine Core types module. + * + * @internal + */ + /** + * Create and configure event engine event. + * + * @internal + */ + function createEvent(type, fn) { + const creator = function (...args) { + return { + type, + payload: fn === null || fn === void 0 ? void 0 : fn(...args), + }; + }; + creator.type = type; + return creator; + } + /** + * Create and configure short-term effect invocation. + * + * @internal + */ + function createEffect(type, fn) { + const creator = (...args) => { + return { type, payload: fn(...args), managed: false }; + }; + creator.type = type; + return creator; + } + /** + * Create and configure long-running effect invocation. + * + * @internal + */ + function createManagedEffect(type, fn) { + const creator = (...args) => { + return { type, payload: fn(...args), managed: true }; + }; + creator.type = type; + creator.cancel = { type: 'CANCEL', payload: type, managed: false }; + return creator; + } + + /** + * Event Engine managed effects terminate signal module. + * + * @internal + */ + class AbortError extends Error { + constructor() { + super('The operation was aborted.'); + this.name = 'AbortError'; + Object.setPrototypeOf(this, new.target.prototype); + } + } + /** + * Event Engine stored effect processing cancellation signal. + * + * @internal + */ + class AbortSignal extends Subject { + constructor() { + super(...arguments); + this._aborted = false; + } + get aborted() { + return this._aborted; + } + throwIfAborted() { + if (this._aborted) { + throw new AbortError(); + } + } + abort() { + this._aborted = true; + this.notify(new AbortError()); + } + } + + /** + * Event Engine Core Effects handler module. + * + * @internal + */ + /** + * Synchronous (short-term) effect invocation handler. + * + * Handler manages effect execution on behalf of effect dispatcher. + * + * @internal + */ + class Handler { + constructor(payload, dependencies) { + this.payload = payload; + this.dependencies = dependencies; + } + } + /** + * Asynchronous (long-running) effect invocation handler. + * + * Handler manages effect execution on behalf of effect dispatcher. + * + * @internal + */ + class AsyncHandler extends Handler { + constructor(payload, dependencies, asyncFunction) { + super(payload, dependencies); + this.asyncFunction = asyncFunction; + this.abortSignal = new AbortSignal(); + } + start() { + this.asyncFunction(this.payload, this.abortSignal, this.dependencies).catch((error) => { + // swallow the error + }); + } + cancel() { + this.abortSignal.abort(); + } + } + /** + * Asynchronous effect invocation handler constructor. + * + * @param handlerFunction - Function which performs asynchronous action and should be called on `start`. + * + * @internal + */ + const asyncHandler = (handlerFunction) => (payload, dependencies) => new AsyncHandler(payload, dependencies, handlerFunction); + + /** + * Presence Event Engine effects module. + * + * @internal + */ + /** + * Presence heartbeat effect. + * + * Performs presence heartbeat REST API call. + * + * @internal + */ + const heartbeat = createManagedEffect('HEARTBEAT', (channels, groups) => ({ + channels, + groups, + })); + /** + * Presence leave effect. + * + * Performs presence leave REST API call. + * + * @internal + */ + const leave = createEffect('LEAVE', (channels, groups) => ({ + channels, + groups, + })); + /** + * Emit presence heartbeat REST API call result status effect. + * + * Notify status change event listeners. + * + * @internal + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ + const emitStatus$1 = createEffect('EMIT_STATUS', (status) => status); + /** + * Heartbeat delay effect. + * + * Delay of configured length (heartbeat interval) before another heartbeat REST API call will be done. + * + * @internal + */ + const wait = createManagedEffect('WAIT', () => ({})); + + /** + * Presence Event Engine events module. + * + * @internal + */ + /** + * Reconnect event. + * + * Event is sent each time when user restores real-time updates processing and notifies other present subscribers + * about joining back. + * + * @internal + */ + const reconnect$1 = createEvent('RECONNECT', () => ({})); + /** + * Disconnect event. + * + * Event is sent when user wants to temporarily stop real-time updates processing and notifies other present + * subscribers about leaving. + * + * @internal + */ + const disconnect$1 = createEvent('DISCONNECT', (isOffline = false) => ({ isOffline })); + /** + * Channel / group join event. + * + * Event is sent when user adds new channels / groups to the active channels / groups list and notifies other present + * subscribers about joining. + * + * @internal + */ + const joined = createEvent('JOINED', (channels, groups) => ({ + channels, + groups, + })); + /** + * Channel / group leave event. + * + * Event is sent when user removes channels / groups from the active channels / groups list and notifies other present + * subscribers about leaving. + * + * @internal + */ + const left = createEvent('LEFT', (channels, groups) => ({ + channels, + groups, + })); + /** + * Leave all event. + * + * Event is sent when user doesn't want to receive any real-time updates anymore and notifies other + * subscribers on previously active channels / groups about leaving. + * + * @internal + */ + const leftAll = createEvent('LEFT_ALL', (isOffline = false) => ({ isOffline })); + /** + * Presence heartbeat success event. + * + * Event is sent by corresponding effect handler if REST API call was successful. + * + * @internal + */ + const heartbeatSuccess = createEvent('HEARTBEAT_SUCCESS', (statusCode) => ({ statusCode })); + /** + * Presence heartbeat did fail event. + * + * Event is sent by corresponding effect handler if REST API call failed. + * + * @internal + */ + const heartbeatFailure = createEvent('HEARTBEAT_FAILURE', (error) => error); + /** + * Delayed presence heartbeat event. + * + * Event is sent by corresponding effect handler when delay timer between heartbeat calls fired. + * + * @internal + */ + const timesUp = createEvent('TIMES_UP', () => ({})); + + /** + * Presence Event Engine effects dispatcher. + * + * @internal + */ + /** + * Presence Event Engine dispatcher. + * + * Dispatcher responsible for presence events handling and corresponding effects execution. + * + * @internal + */ + class PresenceEventEngineDispatcher extends Dispatcher { + constructor(engine, dependencies) { + super(dependencies, dependencies.config.logger()); + this.on(heartbeat.type, asyncHandler((payload_1, abortSignal_1, _a) => __awaiter(this, [payload_1, abortSignal_1, _a], void 0, function* (payload, abortSignal, { heartbeat, presenceState, config }) { + abortSignal.throwIfAborted(); + try { + const result = yield heartbeat(Object.assign(Object.assign({ abortSignal: abortSignal, channels: payload.channels, channelGroups: payload.groups }, (config.maintainPresenceState && { state: presenceState })), { heartbeat: config.presenceTimeout })); + engine.transition(heartbeatSuccess(200)); + } + catch (e) { + if (e instanceof PubNubError) { + if (e.status && e.status.category == StatusCategory$1.PNCancelledCategory) + return; + engine.transition(heartbeatFailure(e)); + } + } + }))); + this.on(leave.type, asyncHandler((payload_1, _1, _a) => __awaiter(this, [payload_1, _1, _a], void 0, function* (payload, _, { leave, config }) { + if (!config.suppressLeaveEvents) { + try { + leave({ + channels: payload.channels, + channelGroups: payload.groups, + }); + } + catch (e) { } + } + }))); + this.on(wait.type, asyncHandler((_1, abortSignal_1, _a) => __awaiter(this, [_1, abortSignal_1, _a], void 0, function* (_, abortSignal, { heartbeatDelay }) { + const { cancelDelay, promise } = heartbeatDelay(); + abortSignal.throwIfAborted(); + const unsubscribeAbortListener = abortSignal.subscribe(() => cancelDelay()); + yield promise; + unsubscribeAbortListener(); + abortSignal.throwIfAborted(); + return engine.transition(timesUp()); + }))); + this.on(emitStatus$1.type, asyncHandler((payload_1, _1, _a) => __awaiter(this, [payload_1, _1, _a], void 0, function* (payload, _, { emitStatus, config }) { + if (config.announceFailedHeartbeats && (payload === null || payload === void 0 ? void 0 : payload.error) === true) { + emitStatus(Object.assign(Object.assign({}, payload), { operation: RequestOperation$1.PNHeartbeatOperation })); + } + else if (config.announceSuccessfulHeartbeats && payload.statusCode === 200) { + emitStatus(Object.assign(Object.assign({}, payload), { error: false, operation: RequestOperation$1.PNHeartbeatOperation, category: StatusCategory$1.PNAcknowledgmentCategory })); + } + }))); + } + } + + /** + * Presence Event Engine state instances. + * + * Isolated from transition handlers so state modules can import sibling states + * without creating circular dependencies. + * + * @internal + */ + /** @internal */ + const HeartbeatInactiveState = new State('HEARTBEAT_INACTIVE'); + /** @internal */ + const HeartbeatingState = new State('HEARTBEATING'); + /** @internal */ + const HeartbeatCooldownState = new State('HEARTBEAT_COOLDOWN'); + /** @internal */ + const HeartbeatStoppedState = new State('HEARTBEAT_STOPPED'); + /** @internal */ + const HeartbeatFailedState = new State('HEARTBEAT_FAILED'); + + /** + * Inactive heratbeating state module. + * + * @internal + */ + /** + * Inactive heratbeating state + * + * State in which Presence Event Engine doesn't process any heartbeat requests (initial state). + * + * @internal + */ + HeartbeatInactiveState.on(joined.type, (_, event) => HeartbeatingState.with({ + channels: event.payload.channels, + groups: event.payload.groups, + })); + + /** + * Heartbeating state module. + * + * @internal + */ + /** + * Heartbeating state module. + * + * State in which Presence Event Engine send heartbeat REST API call. + * + * @internal + */ + HeartbeatingState.onEnter((context) => heartbeat(context.channels, context.groups)); + HeartbeatingState.onExit(() => heartbeat.cancel); + HeartbeatingState.on(heartbeatSuccess.type, (context, event) => HeartbeatCooldownState.with({ channels: context.channels, groups: context.groups }, [ + emitStatus$1(Object.assign({}, event.payload)), + ])); + HeartbeatingState.on(joined.type, (context, event) => HeartbeatingState.with({ + channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], + groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], + })); + HeartbeatingState.on(left.type, (context, event) => { + return HeartbeatingState.with({ + channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), + groups: context.groups.filter((group) => !event.payload.groups.includes(group)), + }, [leave(event.payload.channels, event.payload.groups)]); + }); + HeartbeatingState.on(heartbeatFailure.type, (context, event) => HeartbeatFailedState.with(Object.assign({}, context), [ + ...(event.payload.status ? [emitStatus$1(Object.assign({}, event.payload.status))] : []), + ])); + HeartbeatingState.on(disconnect$1.type, (context, event) => HeartbeatStoppedState.with({ channels: context.channels, groups: context.groups }, [ + ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), + ])); + HeartbeatingState.on(leftAll.type, (context, event) => HeartbeatInactiveState.with(undefined, [ + ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), + ])); + + /** + * Waiting next heartbeat state module. + * + * @internal + */ + /** + * Waiting next heartbeat state. + * + * State in which Presence Event Engine is waiting when delay will run out and next heartbeat call should be done. + * + * @internal + */ + HeartbeatCooldownState.onEnter(() => wait()); + HeartbeatCooldownState.onExit(() => wait.cancel); + HeartbeatCooldownState.on(timesUp.type, (context, _) => HeartbeatingState.with({ + channels: context.channels, + groups: context.groups, + })); + HeartbeatCooldownState.on(joined.type, (context, event) => HeartbeatingState.with({ + channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], + groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], + })); + HeartbeatCooldownState.on(left.type, (context, event) => HeartbeatingState.with({ + channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), + groups: context.groups.filter((group) => !event.payload.groups.includes(group)), + }, [leave(event.payload.channels, event.payload.groups)])); + HeartbeatCooldownState.on(disconnect$1.type, (context, event) => HeartbeatStoppedState.with({ channels: context.channels, groups: context.groups }, [ + ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), + ])); + HeartbeatCooldownState.on(leftAll.type, (context, event) => HeartbeatInactiveState.with(undefined, [ + ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), + ])); + + /** + * Heartbeat stopped state module. + * + * @internal + */ + /** + * Heartbeat stopped state. + * + * State in which Presence Event Engine still has information about active channels / groups, but doesn't wait for + * delayed heartbeat request sending. + * + * @internal + */ + HeartbeatStoppedState.on(joined.type, (context, event) => HeartbeatStoppedState.with({ + channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], + groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], + })); + HeartbeatStoppedState.on(left.type, (context, event) => HeartbeatStoppedState.with({ + channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), + groups: context.groups.filter((group) => !event.payload.groups.includes(group)), + })); + HeartbeatStoppedState.on(reconnect$1.type, (context, _) => HeartbeatingState.with({ + channels: context.channels, + groups: context.groups, + })); + HeartbeatStoppedState.on(leftAll.type, (context, _) => HeartbeatInactiveState.with(undefined)); + + /** + * Failed to heartbeat state module. + * + * @internal + */ + /** + * Failed to heartbeat state. + * + * State in which Subscription Event Engine waits for user to try to reconnect after all retry attempts has been + * exhausted. + * + * @internal + */ + HeartbeatFailedState.on(joined.type, (context, event) => HeartbeatingState.with({ + channels: [...context.channels, ...event.payload.channels.filter((channel) => !context.channels.includes(channel))], + groups: [...context.groups, ...event.payload.groups.filter((group) => !context.groups.includes(group))], + })); + HeartbeatFailedState.on(left.type, (context, event) => HeartbeatingState.with({ + channels: context.channels.filter((channel) => !event.payload.channels.includes(channel)), + groups: context.groups.filter((group) => !event.payload.groups.includes(group)), + }, [leave(event.payload.channels, event.payload.groups)])); + HeartbeatFailedState.on(reconnect$1.type, (context, _) => HeartbeatingState.with({ + channels: context.channels, + groups: context.groups, + })); + HeartbeatFailedState.on(disconnect$1.type, (context, event) => HeartbeatStoppedState.with({ channels: context.channels, groups: context.groups }, [ + ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), + ])); + HeartbeatFailedState.on(leftAll.type, (context, event) => HeartbeatInactiveState.with(undefined, [ + ...(!event.payload.isOffline ? [leave(context.channels, context.groups)] : []), + ])); + + /** + * Presence Event Engine module. + * + * @internal + */ + /** + * Presence Event Engine Core. + * + * @internal + */ + class PresenceEventEngine { + get _engine() { + return this.engine; + } + constructor(dependencies) { + this.dependencies = dependencies; + this.channels = []; + this.groups = []; + this.engine = new Engine(dependencies.config.logger()); + this.dispatcher = new PresenceEventEngineDispatcher(this.engine, dependencies); + dependencies.config.logger().debug('PresenceEventEngine', 'Create presence event engine.'); + this._unsubscribeEngine = this.engine.subscribe((change) => { + if (change.type === 'invocationDispatched') { + this.dispatcher.dispatch(change.invocation); + } + }); + this.engine.start(HeartbeatInactiveState, undefined); + } + join({ channels, groups }) { + this.channels = [...this.channels, ...(channels !== null && channels !== void 0 ? channels : []).filter((channel) => !this.channels.includes(channel))]; + this.groups = [...this.groups, ...(groups !== null && groups !== void 0 ? groups : []).filter((group) => !this.groups.includes(group))]; + // Don't make any transitions if there is no channels and groups. + if (this.channels.length === 0 && this.groups.length === 0) + return; + this.engine.transition(joined(this.channels.slice(0), this.groups.slice(0))); + } + leave({ channels, groups }) { + // Update internal channel tracking to prevent stale heartbeat requests + if (channels) + this.channels = this.channels.filter((channel) => !channels.includes(channel)); + if (groups) + this.groups = this.groups.filter((group) => !groups.includes(group)); + if (this.dependencies.presenceState) { + channels === null || channels === void 0 ? void 0 : channels.forEach((c) => delete this.dependencies.presenceState[c]); + groups === null || groups === void 0 ? void 0 : groups.forEach((g) => delete this.dependencies.presenceState[g]); + } + this.engine.transition(left(channels !== null && channels !== void 0 ? channels : [], groups !== null && groups !== void 0 ? groups : [])); + } + leaveAll(isOffline = false) { + // Clear presence state for all current channels and groups + if (this.dependencies.presenceState) { + this.channels.forEach((c) => delete this.dependencies.presenceState[c]); + this.groups.forEach((g) => delete this.dependencies.presenceState[g]); + } + // Reset internal channel and group tracking + this.channels = []; + this.groups = []; + this.engine.transition(leftAll(isOffline)); + } + reconnect() { + this.engine.transition(reconnect$1()); + } + disconnect(isOffline = false) { + this.engine.transition(disconnect$1(isOffline)); + } + dispose() { + this.disconnect(true); + this._unsubscribeEngine(); + this.dispatcher.dispose(); + } + } + + /** + * Subscribe Event Engine events module. + * + * @internal + */ + /** + * Subscription list change event. + * + * Event is sent each time when the user would like to change a list of active channels / groups. + * + * @internal + */ + const subscriptionChange = createEvent('SUBSCRIPTION_CHANGED', (channels, groups, isOffline = false) => ({ + channels, + groups, + isOffline, + })); + /** + * Subscription loop restore. + * + * Event is sent when a user would like to try to catch up on missed updates by providing specific timetoken. + * + * @internal + */ + const restore = createEvent('SUBSCRIPTION_RESTORED', (channels, groups, timetoken, region) => ({ + channels, + groups, + cursor: { + timetoken: timetoken, + region: region !== null && region !== void 0 ? region : 0, + }, + })); + /** + * Initial subscription handshake success event. + * + * Event is sent by the corresponding effect handler if the REST API call was successful. + * + * @internal + */ + const handshakeSuccess = createEvent('HANDSHAKE_SUCCESS', (cursor) => cursor); + /** + * The initial subscription handshake did fail event. + * + * Event is sent by the corresponding effect handler if the REST API call failed. + * + * @internal + */ + const handshakeFailure = createEvent('HANDSHAKE_FAILURE', (error) => error); + /** + * Subscription successfully received real-time updates event. + * + * Event is sent by the corresponding effect handler if the REST API call was successful. + * + * @internal + */ + const receiveSuccess = createEvent('RECEIVE_SUCCESS', (cursor, events) => ({ + cursor, + events, + })); + /** + * Subscription did fail to receive real-time updates event. + * + * Event is sent by the corresponding effect handler if the REST API call failed. + * + * @internal + */ + const receiveFailure = createEvent('RECEIVE_FAILURE', (error) => error); + /** + * Client disconnect event. + * + * Event is sent when the user wants to temporarily stop real-time updates receive. + * + * @internal + */ + const disconnect = createEvent('DISCONNECT', (isOffline = false) => ({ isOffline })); + /** + * Client reconnect event. + * + * Event is sent when the user wants to restore real-time updates receive. + * + * @internal + */ + const reconnect = createEvent('RECONNECT', (timetoken, region) => ({ + cursor: { + timetoken: timetoken !== null && timetoken !== void 0 ? timetoken : '', + region: region !== null && region !== void 0 ? region : 0, + }, + })); + /** + * Completely stop real-time updates receive event. + * + * Event is sent when the user doesn't want to receive any real-time updates anymore. + * + * @internal + */ + const unsubscribeAll = createEvent('UNSUBSCRIBE_ALL', () => ({})); + + /** + * Subscribe Event Engine state instances. + * + * Isolated from transition handlers so state modules can import sibling states + * without creating circular dependencies. + * + * @internal + */ + /** @internal */ + const UnsubscribedState = new State('UNSUBSCRIBED'); + /** @internal */ + const HandshakingState = new State('HANDSHAKING'); + /** @internal */ + const HandshakeStoppedState = new State('HANDSHAKE_STOPPED'); + /** @internal */ + const HandshakeFailedState = new State('HANDSHAKE_FAILED'); + /** @internal */ + const ReceivingState = new State('RECEIVING'); + /** @internal */ + const ReceiveStoppedState = new State('RECEIVE_STOPPED'); + /** @internal */ + const ReceiveFailedState = new State('RECEIVE_FAILED'); + + /** + * Unsubscribed / disconnected state module. + * + * @internal + */ + /** + * Unsubscribed / disconnected state. + * + * State in which Subscription Event Engine doesn't process any real-time updates. + * + * @internal + */ + UnsubscribedState.on(subscriptionChange.type, (_, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ channels: payload.channels, groups: payload.groups, onDemand: true }); + }); + UnsubscribedState.on(restore.type, (_, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region }, + onDemand: true, + }); + }); + + /** + * Subscribe Event Engine effects module. + * + * @internal + */ + /** + * Initial subscription effect. + * + * Performs subscribe REST API call with `tt=0`. + * + * @internal + */ + const handshake = createManagedEffect('HANDSHAKE', (channels, groups, onDemand) => ({ + channels, + groups, + onDemand, + })); + /** + * Real-time updates receive effect. + * + * Performs sequential subscribe REST API call with `tt` set to the value received from the previous subscribe + * REST API call. + * + * @internal + */ + const receiveMessages = createManagedEffect('RECEIVE_MESSAGES', (channels, groups, cursor, onDemand) => ({ + channels, + groups, + cursor, + onDemand, + })); + /** + * Emit real-time updates effect. + * + * Notify event listeners about updates for which listener handlers has been provided. + * + * @internal + */ + const emitMessages = createEffect('EMIT_MESSAGES', (cursor, events) => ({ + cursor, + events, + })); + /** + * Emit subscription status change effect. + * + * Notify status change event listeners. + * + * @internal + */ + const emitStatus = createEffect('EMIT_STATUS', (status) => status); + + /** + * Initial subscription handshake (disconnected) state. + * + * @internal + */ + /** + * Initial subscription handshake (disconnected) state. + * + * State in which Subscription Event Engine tries to receive the subscription cursor for the next sequential + * subscribe REST API calls. + * + * @internal + */ + HandshakingState.onEnter((context) => { var _a; return handshake(context.channels, context.groups, (_a = context.onDemand) !== null && _a !== void 0 ? _a : false); }); + HandshakingState.onExit(() => handshake.cancel); + HandshakingState.on(subscriptionChange.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: context.cursor, + onDemand: true, + }); + }); + HandshakingState.on(handshakeSuccess.type, (context, { payload }) => { + var _a, _b, _c, _d, _e; + return ReceivingState.with({ + channels: context.channels, + groups: context.groups, + cursor: { + timetoken: !!((_a = context.cursor) === null || _a === void 0 ? void 0 : _a.timetoken) ? (_b = context.cursor) === null || _b === void 0 ? void 0 : _b.timetoken : payload.timetoken, + region: payload.region, + }, + referenceTimetoken: referenceSubscribeTimetoken(payload.timetoken, (_c = context.cursor) === null || _c === void 0 ? void 0 : _c.timetoken), + }, [ + emitStatus({ + category: StatusCategory$1.PNConnectedCategory, + affectedChannels: context.channels.slice(0), + affectedChannelGroups: context.groups.slice(0), + operation: RequestOperation$1.PNSubscribeOperation, + currentTimetoken: !!((_d = context.cursor) === null || _d === void 0 ? void 0 : _d.timetoken) ? (_e = context.cursor) === null || _e === void 0 ? void 0 : _e.timetoken : payload.timetoken, + }), + ]); + }); + HandshakingState.on(handshakeFailure.type, (context, event) => { + var _a; + return HandshakeFailedState.with(Object.assign(Object.assign({}, context), { reason: event.payload }), [ + emitStatus({ category: StatusCategory$1.PNConnectionErrorCategory, error: (_a = event.payload.status) === null || _a === void 0 ? void 0 : _a.category }), + ]); + }); + HandshakingState.on(disconnect.type, (context, event) => { + var _a; + if (!event.payload.isOffline) + return HandshakeStoppedState.with(Object.assign({}, context)); + else { + const errorReason = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation); + return HandshakeFailedState.with(Object.assign(Object.assign({}, context), { reason: errorReason }), [ + emitStatus({ + category: StatusCategory$1.PNConnectionErrorCategory, + error: (_a = errorReason.status) === null || _a === void 0 ? void 0 : _a.category, + }), + ]); + } + }); + HandshakingState.on(restore.type, (context, { payload }) => { + var _a; + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || ((_a = context === null || context === void 0 ? void 0 : context.cursor) === null || _a === void 0 ? void 0 : _a.region) || 0 }, + onDemand: true, + }); + }); + HandshakingState.on(unsubscribeAll.type, (_) => UnsubscribedState.with()); + + /** + * Stopped initial subscription handshake (disconnected) state. + * + * @internal + */ + /** + * Stopped initial subscription handshake (disconnected) state. + * + * State in which Subscription Event Engine still has information about subscription but doesn't have subscription + * cursor for next sequential subscribe REST API call. + * + * @internal + */ + HandshakeStoppedState.on(subscriptionChange.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakeStoppedState.with({ channels: payload.channels, groups: payload.groups, cursor: context.cursor }); + }); + HandshakeStoppedState.on(reconnect.type, (context, { payload }) => HandshakingState.with(Object.assign(Object.assign({}, context), { cursor: payload.cursor || context.cursor, onDemand: true }))); + HandshakeStoppedState.on(restore.type, (context, { payload }) => { + var _a; + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakeStoppedState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || ((_a = context.cursor) === null || _a === void 0 ? void 0 : _a.region) || 0 }, + }); + }); + HandshakeStoppedState.on(unsubscribeAll.type, (_) => UnsubscribedState.with()); + + /** + * Failed initial subscription handshake (disconnected) state. + * + * @internal + */ + /** + * Failed initial subscription handshake (disconnected) state. + * + * State in which Subscription Event Engine waits for user to try to reconnect after all retry attempts has been + * exhausted. + * + * @internal + */ + HandshakeFailedState.on(subscriptionChange.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: context.cursor, + onDemand: true, + }); + }); + HandshakeFailedState.on(reconnect.type, (context, { payload }) => HandshakingState.with(Object.assign(Object.assign({}, context), { cursor: payload.cursor || context.cursor, onDemand: true }))); + HandshakeFailedState.on(restore.type, (context, { payload }) => { + var _a, _b; + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { + timetoken: `${payload.cursor.timetoken}`, + region: payload.cursor.region ? payload.cursor.region : ((_b = (_a = context === null || context === void 0 ? void 0 : context.cursor) === null || _a === void 0 ? void 0 : _a.region) !== null && _b !== void 0 ? _b : 0), + }, + onDemand: true, + }); + }); + HandshakeFailedState.on(unsubscribeAll.type, (_) => UnsubscribedState.with()); + + /** + * Receiving real-time updates (connected) state module. + * + * @internal + */ + /** + * Receiving real-time updates (connected) state. + * + * State in which Subscription Event Engine processes any real-time updates. + * + * @internal + */ + ReceivingState.onEnter((context) => { var _a; return receiveMessages(context.channels, context.groups, context.cursor, (_a = context.onDemand) !== null && _a !== void 0 ? _a : false); }); + ReceivingState.onExit(() => receiveMessages.cancel); + ReceivingState.on(receiveSuccess.type, (context, { payload }) => ReceivingState.with({ + channels: context.channels, + groups: context.groups, + cursor: payload.cursor, + referenceTimetoken: referenceSubscribeTimetoken(payload.cursor.timetoken), + }, [emitMessages(context.cursor, payload.events)])); + ReceivingState.on(subscriptionChange.type, (context, { payload }) => { + var _a; + if (payload.channels.length === 0 && payload.groups.length === 0) { + let errorCategory; + if (payload.isOffline) + errorCategory = (_a = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation).status) === null || _a === void 0 ? void 0 : _a.category; + return UnsubscribedState.with(undefined, [ + emitStatus(Object.assign({ category: !payload.isOffline + ? StatusCategory$1.PNDisconnectedCategory + : StatusCategory$1.PNDisconnectedUnexpectedlyCategory, operation: RequestOperation$1.PNUnsubscribeOperation }, (errorCategory ? { error: errorCategory } : {}))), + ]); + } + return ReceivingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: context.cursor, + referenceTimetoken: context.referenceTimetoken, + onDemand: true, + }, [ + emitStatus({ + category: StatusCategory$1.PNSubscriptionChangedCategory, + affectedChannels: payload.channels.slice(0), + affectedChannelGroups: payload.groups.slice(0), + currentTimetoken: context.cursor.timetoken, + }), + ]); + }); + ReceivingState.on(restore.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined, [emitStatus({ category: StatusCategory$1.PNDisconnectedCategory })]); + return ReceivingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || context.cursor.region }, + referenceTimetoken: referenceSubscribeTimetoken(context.cursor.timetoken, `${payload.cursor.timetoken}`, context.referenceTimetoken), + onDemand: true, + }, [ + emitStatus({ + category: StatusCategory$1.PNSubscriptionChangedCategory, + affectedChannels: payload.channels.slice(0), + affectedChannelGroups: payload.groups.slice(0), + currentTimetoken: payload.cursor.timetoken, + }), + ]); + }); + ReceivingState.on(receiveFailure.type, (context, { payload }) => { + var _a; + return ReceiveFailedState.with(Object.assign(Object.assign({}, context), { reason: payload }), [ + emitStatus({ category: StatusCategory$1.PNDisconnectedUnexpectedlyCategory, error: (_a = payload.status) === null || _a === void 0 ? void 0 : _a.category }), + ]); + }); + ReceivingState.on(disconnect.type, (context, event) => { + var _a; + if (!event.payload.isOffline) { + return ReceiveStoppedState.with(Object.assign({}, context), [ + emitStatus({ + category: StatusCategory$1.PNDisconnectedCategory, + operation: RequestOperation$1.PNSubscribeOperation, + }), + ]); + } + else { + const errorReason = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation); + return ReceiveFailedState.with(Object.assign(Object.assign({}, context), { reason: errorReason }), [ + emitStatus({ + category: StatusCategory$1.PNDisconnectedUnexpectedlyCategory, + operation: RequestOperation$1.PNSubscribeOperation, + error: (_a = errorReason.status) === null || _a === void 0 ? void 0 : _a.category, + }), + ]); + } + }); + ReceivingState.on(unsubscribeAll.type, (_) => UnsubscribedState.with(undefined, [ + emitStatus({ + category: StatusCategory$1.PNDisconnectedCategory, + operation: RequestOperation$1.PNUnsubscribeOperation, + }), + ])); + + /** + * Stopped real-time updates (disconnected) state module. + * + * @internal + */ + /** + * Stopped real-time updates (disconnected) state. + * + * State in which Subscription Event Engine still has information about subscription but doesn't process real-time + * updates. + * + * @internal + */ + ReceiveStoppedState.on(subscriptionChange.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return ReceiveStoppedState.with({ channels: payload.channels, groups: payload.groups, cursor: context.cursor }); + }); + ReceiveStoppedState.on(restore.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return ReceiveStoppedState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || context.cursor.region }, + }); + }); + ReceiveStoppedState.on(reconnect.type, (context, { payload }) => { + var _a; + return HandshakingState.with({ + channels: context.channels, + groups: context.groups, + cursor: { + timetoken: !!payload.cursor.timetoken ? (_a = payload.cursor) === null || _a === void 0 ? void 0 : _a.timetoken : context.cursor.timetoken, + region: payload.cursor.region || context.cursor.region, + }, + onDemand: true, + }); + }); + ReceiveStoppedState.on(unsubscribeAll.type, () => UnsubscribedState.with(undefined)); + + /** + * Failed to receive real-time updates (disconnected) state. + * + * @internal + */ + /** + * Failed to receive real-time updates (disconnected) state. + * + * State in which Subscription Event Engine waits for user to try to reconnect after all retry attempts has been + * exhausted. + * + * @internal + */ + ReceiveFailedState.on(reconnect.type, (context, { payload }) => { + var _a; + return HandshakingState.with({ + channels: context.channels, + groups: context.groups, + cursor: { + timetoken: !!payload.cursor.timetoken ? (_a = payload.cursor) === null || _a === void 0 ? void 0 : _a.timetoken : context.cursor.timetoken, + region: payload.cursor.region || context.cursor.region, + }, + onDemand: true, + }); + }); + ReceiveFailedState.on(subscriptionChange.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: context.cursor, + onDemand: true, + }); + }); + ReceiveFailedState.on(restore.type, (context, { payload }) => { + if (payload.channels.length === 0 && payload.groups.length === 0) + return UnsubscribedState.with(undefined); + return HandshakingState.with({ + channels: payload.channels, + groups: payload.groups, + cursor: { timetoken: `${payload.cursor.timetoken}`, region: payload.cursor.region || context.cursor.region }, + onDemand: true, + }); + }); + ReceiveFailedState.on(unsubscribeAll.type, (_) => UnsubscribedState.with(undefined)); + + /** + * Subscribe Event Engine effects dispatcher. + * + * @internal + */ + /** + * Subscribe Event Engine dispatcher. + * + * Dispatcher responsible for subscription events handling and corresponding effects execution. + * + * @internal + */ + class EventEngineDispatcher extends Dispatcher { + constructor(engine, dependencies) { + super(dependencies, dependencies.config.logger()); + this.on(handshake.type, asyncHandler((payload_1, abortSignal_1, _a) => __awaiter(this, [payload_1, abortSignal_1, _a], void 0, function* (payload, abortSignal, { handshake, presenceState, config }) { + abortSignal.throwIfAborted(); + try { + const result = yield handshake(Object.assign(Object.assign({ abortSignal: abortSignal, channels: payload.channels, channelGroups: payload.groups, filterExpression: config.filterExpression }, (config.maintainPresenceState && { state: presenceState })), { onDemand: payload.onDemand })); + return engine.transition(handshakeSuccess(result)); + } + catch (e) { + if (e instanceof PubNubError) { + if (e.status && e.status.category == StatusCategory$1.PNCancelledCategory) + return; + return engine.transition(handshakeFailure(e)); + } + } + }))); + this.on(receiveMessages.type, asyncHandler((payload_1, abortSignal_1, _a) => __awaiter(this, [payload_1, abortSignal_1, _a], void 0, function* (payload, abortSignal, { receiveMessages, config }) { + abortSignal.throwIfAborted(); + try { + const result = yield receiveMessages({ + abortSignal: abortSignal, + channels: payload.channels, + channelGroups: payload.groups, + timetoken: payload.cursor.timetoken, + region: payload.cursor.region, + filterExpression: config.filterExpression, + onDemand: payload.onDemand, + }); + engine.transition(receiveSuccess(result.cursor, result.messages)); + } + catch (error) { + if (error instanceof PubNubError) { + if (error.status && error.status.category == StatusCategory$1.PNCancelledCategory) + return; + if (!abortSignal.aborted) + return engine.transition(receiveFailure(error)); + } + } + }))); + this.on(emitMessages.type, asyncHandler((_a, _1, _b) => __awaiter(this, [_a, _1, _b], void 0, function* ({ cursor, events }, _, { emitMessages }) { + if (events.length > 0) + emitMessages(cursor, events); + }))); + this.on(emitStatus.type, asyncHandler((payload_1, _1, _a) => __awaiter(this, [payload_1, _1, _a], void 0, function* (payload, _, { emitStatus }) { return emitStatus(payload); }))); + } + } + + /** + * Subscribe Event Engine module. + * + * @internal + */ + /** + * Subscribe Event Engine Core. + * + * @internal + */ + class EventEngine { + get _engine() { + return this.engine; + } + constructor(dependencies) { + this.channels = []; + this.groups = []; + this.dependencies = dependencies; + this.engine = new Engine(dependencies.config.logger()); + this.dispatcher = new EventEngineDispatcher(this.engine, dependencies); + dependencies.config.logger().debug('EventEngine', 'Create subscribe event engine.'); + this._unsubscribeEngine = this.engine.subscribe((change) => { + if (change.type === 'invocationDispatched') { + this.dispatcher.dispatch(change.invocation); + } + }); + this.engine.start(UnsubscribedState, undefined); + } + /** + * Subscription-based current timetoken. + * + * @returns Timetoken based on current timetoken plus diff between current and loop start time. + */ + get subscriptionTimetoken() { + const currentState = this.engine.currentState; + if (!currentState) + return undefined; + let referenceTimetoken; + let currentTimetoken = '0'; + if (currentState.label === ReceivingState.label) { + const context = this.engine.currentContext; + currentTimetoken = context.cursor.timetoken; + referenceTimetoken = context.referenceTimetoken; + } + return subscriptionTimetokenFromReference(currentTimetoken, referenceTimetoken !== null && referenceTimetoken !== void 0 ? referenceTimetoken : '0'); + } + subscribe({ channels, channelGroups, timetoken, withPresence, }) { + var _a; + // check if the channels and groups are already subscribed + const hasNewChannels = channels === null || channels === void 0 ? void 0 : channels.some((channel) => !this.channels.includes(channel)); + const hasNewGroups = channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.some((group) => !this.groups.includes(group)); + const hasNewSubscriptions = hasNewChannels || hasNewGroups; + this.channels = [...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])]; + this.groups = [...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])]; + if (withPresence) { + this.channels.map((c) => this.channels.push(`${c}-pnpres`)); + this.groups.map((g) => this.groups.push(`${g}-pnpres`)); + } + if (timetoken) { + this.engine.transition(restore(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])])), timetoken)); + } + else { + if (hasNewSubscriptions) { + this.engine.transition(subscriptionChange(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])])))); + } + else { + this.dependencies.config + .logger() + .debug('EventEngine', 'Skipping state transition - all channels/groups already subscribed. Emitting SubscriptionChanged event.'); + // Get current timetoken from state context + const currentState = this.engine.currentState; + const currentContext = this.engine.currentContext; + let currentTimetoken = '0'; + if ((currentState === null || currentState === void 0 ? void 0 : currentState.label) === ReceivingState.label && currentContext) { + const receivingContext = currentContext; + currentTimetoken = (_a = receivingContext.cursor) === null || _a === void 0 ? void 0 : _a.timetoken; + } + // Manually emit SubscriptionChanged status event + this.dependencies.emitStatus({ + category: StatusCategory$1.PNSubscriptionChangedCategory, + affectedChannels: Array.from(new Set(this.channels)), + affectedChannelGroups: Array.from(new Set(this.groups)), + currentTimetoken, + }); + } + } + if (this.dependencies.join) { + this.dependencies.join({ + channels: Array.from(new Set(this.channels.filter((c) => !c.endsWith('-pnpres')))), + groups: Array.from(new Set(this.groups.filter((g) => !g.endsWith('-pnpres')))), + }); + } + } + unsubscribe({ channels = [], channelGroups = [] }) { + const filteredChannels = removeSingleOccurrence(this.channels, [ + ...channels, + ...channels.map((c) => `${c}-pnpres`), + ]); + const filteredGroups = removeSingleOccurrence(this.groups, [ + ...channelGroups, + ...channelGroups.map((c) => `${c}-pnpres`), + ]); + if (new Set(this.channels).size !== new Set(filteredChannels).size || + new Set(this.groups).size !== new Set(filteredGroups).size) { + const channelsToLeave = findUniqueCommonElements(this.channels, channels); + const groupsToLeave = findUniqueCommonElements(this.groups, channelGroups); + if (this.dependencies.presenceState) { + channelsToLeave === null || channelsToLeave === void 0 ? void 0 : channelsToLeave.forEach((c) => delete this.dependencies.presenceState[c]); + groupsToLeave === null || groupsToLeave === void 0 ? void 0 : groupsToLeave.forEach((g) => delete this.dependencies.presenceState[g]); + } + this.channels = filteredChannels; + this.groups = filteredGroups; + this.engine.transition(subscriptionChange(Array.from(new Set(this.channels.slice(0))), Array.from(new Set(this.groups.slice(0))))); + if (this.dependencies.leave) { + this.dependencies.leave({ + channels: channelsToLeave.slice(0), + groups: groupsToLeave.slice(0), + }); + } + } + } + unsubscribeAll(isOffline = false) { + const channelGroups = this.getSubscribedChannelGroups(); + const channels = this.getSubscribedChannels(); + this.channels = []; + this.groups = []; + if (this.dependencies.presenceState) { + Object.keys(this.dependencies.presenceState).forEach((objectName) => { + delete this.dependencies.presenceState[objectName]; + }); + } + this.engine.transition(subscriptionChange(this.channels.slice(0), this.groups.slice(0), isOffline)); + if (this.dependencies.leaveAll) + this.dependencies.leaveAll({ channels, groups: channelGroups, isOffline }); + } + reconnect({ timetoken, region }) { + const channelGroups = this.getSubscribedChannels(); + const channels = this.getSubscribedChannels(); + this.engine.transition(reconnect(timetoken, region)); + if (this.dependencies.presenceReconnect) + this.dependencies.presenceReconnect({ channels, groups: channelGroups }); + } + disconnect(isOffline = false) { + const channelGroups = this.getSubscribedChannels(); + const channels = this.getSubscribedChannels(); + this.engine.transition(disconnect(isOffline)); + if (this.dependencies.presenceDisconnect) + this.dependencies.presenceDisconnect({ channels, groups: channelGroups, isOffline }); + } + getSubscribedChannels() { + return Array.from(new Set(this.channels.slice(0))); + } + getSubscribedChannelGroups() { + return Array.from(new Set(this.groups.slice(0))); + } + dispose() { + this.disconnect(true); + this._unsubscribeEngine(); + this.dispatcher.dispose(); + } + } + + /** + * Publish REST API module. + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether data is published used `POST` body or not. + */ + const SEND_BY_POST = false; + // endregion + /** + * Data publish request. + * + * Request will normalize and encrypt (if required) provided data and push it to the specified + * channel. + * + * @internal + */ + class PublishRequest extends AbstractRequest { + /** + * Construct data publish request. + * + * @param parameters - Request configuration. + */ + constructor(parameters) { + var _a; + const sendByPost = (_a = parameters.sendByPost) !== null && _a !== void 0 ? _a : SEND_BY_POST; + super({ method: sendByPost ? TransportMethod.POST : TransportMethod.GET, compressible: sendByPost }); + this.parameters = parameters; + // Apply default request parameters. + this.parameters.sendByPost = sendByPost; + } + operation() { + return RequestOperation$1.PNPublishOperation; + } + validate() { + const { message, channel, keySet: { publishKey }, } = this.parameters; + if (!channel) + return "Missing 'channel'"; + if (!message) + return "Missing 'message'"; + if (!publishKey) + return "Missing 'publishKey'"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { timetoken: this.deserializeResponse(response)[2] }; + }); + } + get path() { + const { message, channel, keySet } = this.parameters; + const stringifiedPayload = this.prepareMessagePayload(message); + return `/publish/${keySet.publishKey}/${keySet.subscribeKey}/0/${encodeString(channel)}/0${!this.parameters.sendByPost ? `/${encodeString(stringifiedPayload)}` : ''}`; + } + get queryParameters() { + const { customMessageType, meta, replicate, storeInHistory, ttl } = this.parameters; + const query = {}; + if (customMessageType) + query.custom_message_type = customMessageType; + if (storeInHistory !== undefined) + query.store = storeInHistory ? '1' : '0'; + if (ttl !== undefined) + query.ttl = ttl; + if (replicate !== undefined && !replicate) + query.norep = 'true'; + if (meta && typeof meta === 'object') + query.meta = JSON.stringify(meta); + return query; + } + get headers() { + var _a; + if (!this.parameters.sendByPost) + return super.headers; + return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); + } + get body() { + return this.prepareMessagePayload(this.parameters.message); + } + /** + * Pre-process provided data. + * + * Data will be "normalized" and encrypted if `cryptoModule` has been provided. + * + * @param payload - User-provided data which should be pre-processed before use. + * + * @returns Payload which can be used as part of request URL or body. + * + * @throws {Error} in case if provided `payload` or results of `encryption` can't be stringified. + */ + prepareMessagePayload(payload) { + const { crypto } = this.parameters; + if (!crypto) + return JSON.stringify(payload) || ''; + const encrypted = crypto.encrypt(JSON.stringify(payload)); + return JSON.stringify(typeof encrypted === 'string' ? encrypted : encode(encrypted)); + } + } + + /** + * Signal REST API module. + */ + // endregion + /** + * Signal data (size-limited) publish request. + * + * @internal + */ + class SignalRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSignalOperation; + } + validate() { + const { message, channel, keySet: { publishKey }, } = this.parameters; + if (!channel) + return "Missing 'channel'"; + if (!message) + return "Missing 'message'"; + if (!publishKey) + return "Missing 'publishKey'"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { timetoken: this.deserializeResponse(response)[2] }; + }); + } + get path() { + const { keySet: { publishKey, subscribeKey }, channel, message, } = this.parameters; + const stringifiedPayload = JSON.stringify(message); + return `/signal/${publishKey}/${subscribeKey}/0/${encodeString(channel)}/0/${encodeString(stringifiedPayload)}`; + } + get queryParameters() { + const { customMessageType } = this.parameters; + const query = {}; + if (customMessageType) + query.custom_message_type = customMessageType; + return query; + } + } + + /** + * Receive messages subscribe REST API module. + * + * @internal + */ + /** + * Receive messages subscribe request. + * + * @internal + */ + class ReceiveMessagesSubscribeRequest extends BaseSubscribeRequest { + operation() { + return RequestOperation$1.PNReceiveMessagesOperation; + } + validate() { + const validationResult = super.validate(); + if (validationResult) + return validationResult; + if (!this.parameters.timetoken) + return 'timetoken can not be empty'; + if (!this.parameters.region) + return 'region can not be empty'; + } + get path() { + const { keySet: { subscribeKey }, channels = [], } = this.parameters; + return `/v2/subscribe/${subscribeKey}/${encodeNames(channels.sort(), ',')}/0`; + } + get queryParameters() { + const { channelGroups, filterExpression, timetoken, region, heartbeat, onDemand } = this + .parameters; + const query = { ee: '' }; + if (onDemand) + query['on-demand'] = 1; + if (channelGroups && channelGroups.length > 0) + query['channel-group'] = channelGroups.sort().join(','); + if (filterExpression && filterExpression.length > 0) + query['filter-expr'] = filterExpression; + if (typeof timetoken === 'string') { + if (timetoken && timetoken !== '0' && timetoken.length > 0) + query['tt'] = timetoken; + } + else if (timetoken && timetoken > 0) + query['tt'] = timetoken; + if (region) + query['tr'] = region; + if (heartbeat) + query.heartbeat = heartbeat; + return query; + } + } + + /** + * Handshake subscribe REST API module. + * + * @internal + */ + /** + * Handshake subscribe request. + * + * Separate subscribe request required by Event Engine. + * + * @internal + */ + class HandshakeSubscribeRequest extends BaseSubscribeRequest { + operation() { + return RequestOperation$1.PNHandshakeOperation; + } + get path() { + const { keySet: { subscribeKey }, channels = [], } = this.parameters; + return `/v2/subscribe/${subscribeKey}/${encodeNames(channels.sort(), ',')}/0`; + } + get queryParameters() { + const { channelGroups, heartbeat, filterExpression, state, onDemand } = this + .parameters; + const query = { ee: '' }; + if (onDemand) + query['on-demand'] = 1; + if (channelGroups && channelGroups.length > 0) + query['channel-group'] = channelGroups.sort().join(','); + if (filterExpression && filterExpression.length > 0) + query['filter-expr'] = filterExpression; + if (state && Object.keys(state).length > 0) + query['state'] = JSON.stringify(state); + if (heartbeat) + query.heartbeat = heartbeat; + return query; + } + } + + /** + * SubscriptionCapable entity type. + * + * @internal + */ + var SubscriptionType; + (function (SubscriptionType) { + /** + * Channel identifier, which is part of the URI path. + */ + SubscriptionType[SubscriptionType["Channel"] = 0] = "Channel"; + /** + * Channel group identifiers, which is part of the query parameters. + */ + SubscriptionType[SubscriptionType["ChannelGroup"] = 1] = "ChannelGroup"; + })(SubscriptionType || (SubscriptionType = {})); + + /** + * User-provided channels and groups for subscription. + * + * Object contains information about channels and groups for which real-time updates should be retrieved from the + * PubNub network. + * + * @internal + */ + class SubscriptionInput { + /** + * Create a subscription input object. + * + * @param channels - List of channels which will be used with subscribe REST API to receive real-time updates. + * @param channelGroups - List of channel groups which will be used with subscribe REST API to receive real-time + * updates. + */ + constructor({ channels, channelGroups }) { + /** + * Whether the user input is empty or not. + */ + this.isEmpty = true; + this._channelGroups = new Set((channelGroups !== null && channelGroups !== void 0 ? channelGroups : []).filter((value) => value.length > 0)); + this._channels = new Set((channels !== null && channels !== void 0 ? channels : []).filter((value) => value.length > 0)); + this.isEmpty = this._channels.size === 0 && this._channelGroups.size === 0; + } + /** + * Retrieve total length of subscription input. + * + * @returns Number of channels and groups in subscription input. + */ + get length() { + if (this.isEmpty) + return 0; + return this._channels.size + this._channelGroups.size; + } + /** + * Retrieve a list of user-provided channel names. + * + * @returns List of user-provided channel names. + */ + get channels() { + if (this.isEmpty) + return []; + return Array.from(this._channels); + } + /** + * Retrieve a list of user-provided channel group names. + * + * @returns List of user-provided channel group names. + */ + get channelGroups() { + if (this.isEmpty) + return []; + return Array.from(this._channelGroups); + } + /** + * Check if the given name is contained in the channel or channel group. + * + * @param name - Containing the name to be checked. + * + * @returns `true` if the name is found in the channel or channel group, `false` otherwise. + */ + contains(name) { + if (this.isEmpty) + return false; + return this._channels.has(name) || this._channelGroups.has(name); + } + /** + * Create a new subscription input which will contain all channels and channel groups from both inputs. + * + * @param input - Another subscription input that should be used to aggregate data in new instance. + * + * @returns New subscription input instance with combined channels and channel groups. + */ + with(input) { + return new SubscriptionInput({ + channels: [...this._channels, ...input._channels], + channelGroups: [...this._channelGroups, ...input._channelGroups], + }); + } + /** + * Create a new subscription input which will contain only channels and groups which not present in the input. + * + * @param input - Another subscription input which should be used to filter data in new instance. + * + * @returns New subscription input instance with filtered channels and channel groups. + */ + without(input) { + return new SubscriptionInput({ + channels: [...this._channels].filter((value) => !input._channels.has(value)), + channelGroups: [...this._channelGroups].filter((value) => !input._channelGroups.has(value)), + }); + } + /** + * Add data from another subscription input to the receiver. + * + * @param input - Another subscription input whose data should be added to the receiver. + * + * @returns Receiver instance with updated channels and channel groups. + */ + add(input) { + if (input._channelGroups.size > 0) + this._channelGroups = new Set([...this._channelGroups, ...input._channelGroups]); + if (input._channels.size > 0) + this._channels = new Set([...this._channels, ...input._channels]); + this.isEmpty = this._channels.size === 0 && this._channelGroups.size === 0; + return this; + } + /** + * Remove data from another subscription input from the receiver. + * + * @param input - Another subscription input whose data should be removed from the receiver. + * + * @returns Receiver instance with updated channels and channel groups. + */ + remove(input) { + if (input._channelGroups.size > 0) + this._channelGroups = new Set([...this._channelGroups].filter((value) => !input._channelGroups.has(value))); + if (input._channels.size > 0) + this._channels = new Set([...this._channels].filter((value) => !input._channels.has(value))); + return this; + } + /** + * Remove all data from subscription input. + * + * @returns Receiver instance with updated channels and channel groups. + */ + removeAll() { + this._channels.clear(); + this._channelGroups.clear(); + this.isEmpty = true; + return this; + } + /** + * Serialize a subscription input to string. + * + * @returns Printable string representation of a subscription input. + */ + toString() { + return `SubscriptionInput { channels: [${this.channels.join(', ')}], channelGroups: [${this.channelGroups.join(', ')}], is empty: ${this.isEmpty ? 'true' : 'false'}} }`; + } + } + // endregion + + /** + * Subscription state object. + * + * State object used across multiple subscription object clones. + * + * @internal + */ + class SubscriptionBaseState { + /** + * Create a base subscription state object. + * + * @param client - PubNub client which will work with a subscription object. + * @param subscriptionInput - User's input to be used with subscribe REST API. + * @param options - Subscription behavior options. + * @param referenceTimetoken - High-precision timetoken of the moment when subscription was created for entity. + */ + constructor(client, subscriptionInput, options, referenceTimetoken) { + /** + * Whether a subscribable object subscribed or not. + */ + this._isSubscribed = false; + /** + * The list of references to all {@link SubscriptionBase} clones created for this reference. + */ + this.clones = {}; + /** + * List of a parent subscription state objects list. + * + * List is used to track usage of a subscription object in other subscription object sets. + * + * **Important:** Tracking is required to prevent unexpected unsubscriptions if an object still has a parent. + */ + this.parents = []; + /** + * Unique subscription object identifier. + */ + this._id = uuidGenerator.createUUID(); + this.referenceTimetoken = referenceTimetoken; + this.subscriptionInput = subscriptionInput; + this.options = options; + this.client = client; + } + /** + * Get unique subscription object identifier. + * + * @returns Unique subscription object identifier. + */ + get id() { + return this._id; + } + /** + * Check whether a subscription object is the last clone or not. + * + * @returns `true` if a subscription object is the last clone. + */ + get isLastClone() { + return Object.keys(this.clones).length === 1; + } + /** + * Get whether a subscribable object subscribed or not. + * + * **Warning:** This method shouldn't be overridden by {@link SubscriptionSet}. + * + * @returns Whether a subscribable object subscribed or not. + */ + get isSubscribed() { + if (this._isSubscribed) + return true; + // Checking whether any of "parents" is subscribed. + return this.parents.length > 0 && this.parents.some((state) => state.isSubscribed); + } + /** + * Update active subscription state. + * + * @param value - New subscription state. + */ + set isSubscribed(value) { + if (this.isSubscribed === value) + return; + this._isSubscribed = value; + } + /** + * Add a parent subscription state object to mark the linkage. + * + * @param parent - Parent subscription state object. + * + * @internal + */ + addParentState(parent) { + if (!this.parents.includes(parent)) + this.parents.push(parent); + } + /** + * Remove a parent subscription state object. + * + * @param parent - Parent object for which linkage should be broken. + * + * @internal + */ + removeParentState(parent) { + const parentStateIndex = this.parents.indexOf(parent); + if (parentStateIndex !== -1) + this.parents.splice(parentStateIndex, 1); + } + /** + * Store a clone of a {@link SubscriptionBase} instance with a given instance ID. + * + * @param id - The instance ID to associate with clone. + * @param instance - Reference to the subscription instance to store as a clone. + */ + storeClone(id, instance) { + if (!this.clones[id]) + this.clones[id] = instance; + } + } + /** + * Base subscribe object. + * + * Implementation of base functionality used by {@link SubscriptionObject Subscription} and {@link SubscriptionSet}. + */ + class SubscriptionBase { + /** + * Create a subscription object from the state. + * + * @param state - Subscription state object. + * @param subscriptionType - Actual subscription object type. + * + * @internal + */ + constructor(state, subscriptionType = 'Subscription') { + this.subscriptionType = subscriptionType; + /** + * Unique subscription object identifier. + * + * @internal + */ + this.id = uuidGenerator.createUUID(); + /** + * Event emitter, which will notify listeners about updates received for channels / groups. + * + * @internal + */ + this.eventDispatcher = new EventDispatcher(); + this._state = state; + } + /** + * Subscription state. + * + * @returns Subscription state object. + * + * @internal + */ + get state() { + return this._state; + } + /** + * Get a list of channels which is used for subscription. + * + * @returns List of channel names. + */ + get channels() { + return this.state.subscriptionInput.channels.slice(0); + } + /** + * Get a list of channel groups which is used for subscription. + * + * @returns List of channel group names. + */ + get channelGroups() { + return this.state.subscriptionInput.channelGroups.slice(0); + } + // -------------------------------------------------------- + // -------------------- Event emitter --------------------- + // -------------------------------------------------------- + // region Event emitter + /** + * Set a new message handler. + * + * @param listener - Listener function, which will be called each time when a new message + * is received from the real-time network. + */ + set onMessage(listener) { + this.eventDispatcher.onMessage = listener; + } + /** + * Set a new presence events handler. + * + * @param listener - Listener function, which will be called each time when a new + * presence event is received from the real-time network. + */ + set onPresence(listener) { + this.eventDispatcher.onPresence = listener; + } + /** + * Set a new signal handler. + * + * @param listener - Listener function, which will be called each time when a new signal + * is received from the real-time network. + */ + set onSignal(listener) { + this.eventDispatcher.onSignal = listener; + } + /** + * Set a new app context event handler. + * + * @param listener - Listener function, which will be called each time when a new + * app context event is received from the real-time network. + */ + set onObjects(listener) { + this.eventDispatcher.onObjects = listener; + } + /** + * Set a new message reaction event handler. + * + * @param listener - Listener function, which will be called each time when a + * new message reaction event is received from the real-time network. + */ + set onMessageAction(listener) { + this.eventDispatcher.onMessageAction = listener; + } + /** + * Set a new file handler. + * + * @param listener - Listener function, which will be called each time when a new file + * is received from the real-time network. + */ + set onFile(listener) { + this.eventDispatcher.onFile = listener; + } + /** + * Set a new DataSync event handler. + * + * @param listener - Listener function, which will be called each time when a new + * DataSync event is received from the real-time network. + */ + set onDataSync(listener) { + this.eventDispatcher.onDataSync = listener; + } + /** + * Set events handler. + * + * @param listener - Events listener configuration object, which lets specify handlers for multiple + * types of events. + */ + addListener(listener) { + this.eventDispatcher.addListener(listener); + } + /** + * Remove events handler. + * + * @param listener - Event listener configuration, which should be removed from the list of notified + * listeners. **Important:** Should be the same object which has been passed to the {@link addListener}. + */ + removeListener(listener) { + this.eventDispatcher.removeListener(listener); + } + /** + * Remove all events listeners. + */ + removeAllListeners() { + this.eventDispatcher.removeAllListeners(); + } + /** + * Dispatch received a real-time update. + * + * @param cursor - A time cursor for the next portion of events. + * @param event - A real-time event from multiplexed subscription. + * + * @return `true` if receiver has consumed event. + * + * @internal + */ + handleEvent(cursor, event) { + var _a; + if (!this.state.cursor || cursor > this.state.cursor) + this.state.cursor = cursor; + // Check whether this is an old `old` event and it should be ignored or not. + if (this.state.referenceTimetoken && event.data.timetoken < this.state.referenceTimetoken) { + this.state.client.logger.trace(this.subscriptionType, () => ({ + messageType: 'text', + message: `Event timetoken (${event.data.timetoken}) is older than reference timetoken (${this.state.referenceTimetoken}) for ${this.id} subscription object. Ignoring event.`, + })); + return; + } + // Don't pass events which are filtered out by the user-provided function. + if (((_a = this.state.options) === null || _a === void 0 ? void 0 : _a.filter) && !this.state.options.filter(event)) { + this.state.client.logger.trace(this.subscriptionType, `Event filtered out by filter function for ${this.id} subscription object. Ignoring event.`); + return; + } + const clones = Object.values(this.state.clones); + if (clones.length > 0) { + this.state.client.logger.trace(this.subscriptionType, `Notify ${this.id} subscription object clones (count: ${clones.length}) about received event.`); + } + clones.forEach((subscription) => subscription.eventDispatcher.handleEvent(event)); + } + /** + * Graceful object destruction. + * + * This is an instance destructor, which will properly deinitialize it: + * - remove and unset all listeners, + * - try to unsubscribe (if subscribed and there are no more instances interested in the same data stream). + * + * **Important:** {@link SubscriptionBase#dispose dispose} won't have any effect if a subscription object is part of + * set. To gracefully dispose an object, it should be removed from the set using + * {@link SubscriptionSet#removeSubscription removeSubscription} (in this case call of + * {@link SubscriptionBase#dispose dispose} not required. + * + * **Note:** Disposed instance won't call the dispatcher to deliver updates to the listeners. + */ + dispose() { + const keys = Object.keys(this.state.clones); + if (keys.length > 1) { + this.state.client.logger.debug(this.subscriptionType, `Remove subscription object clone on dispose: ${this.id}`); + delete this.state.clones[this.id]; + } + else if (keys.length === 1 && this.state.clones[this.id]) { + this.state.client.logger.debug(this.subscriptionType, `Unsubscribe subscription object on dispose: ${this.id}`); + this.unsubscribe(); + } + } + /** + * Invalidate subscription object. + * + * Clean up resources used by a subscription object. + * + * **Note:** An invalidated instance won't call the dispatcher to deliver updates to the listeners. + * + * @param forDestroy - Whether subscription object invalidated as part of PubNub client destroy process or not. + * + * @internal + */ + invalidate(forDestroy = false) { + this.state._isSubscribed = false; + if (forDestroy) { + delete this.state.clones[this.id]; + if (Object.keys(this.state.clones).length === 0) { + this.state.client.logger.trace(this.subscriptionType, 'Last clone removed. Reset shared subscription state.'); + this.state.subscriptionInput.removeAll(); + this.state.parents = []; + } + } + } + /** + * Start receiving real-time updates. + * + * @param parameters - Additional subscription configuration options which should be used + * for request. + */ + subscribe(parameters) { + if (this.state.isSubscribed) { + this.state.client.logger.trace(this.subscriptionType, 'Already subscribed. Ignoring subscribe request.'); + return; + } + this.state.client.logger.debug(this.subscriptionType, () => { + if (!parameters) + return { messageType: 'text', message: 'Subscribe' }; + return { messageType: 'object', message: parameters, details: 'Subscribe with parameters:' }; + }); + this.state.isSubscribed = true; + this.updateSubscription({ subscribing: true, timetoken: parameters === null || parameters === void 0 ? void 0 : parameters.timetoken }); + } + /** + * Stop real-time events processing. + * + * **Important:** {@link SubscriptionBase#unsubscribe unsubscribe} won't have any effect if a subscription object + * is part of active (subscribed) set. To unsubscribe an object, it should be removed from the set using + * {@link SubscriptionSet#removeSubscription removeSubscription} (in this case call of + * {@link SubscriptionBase#unsubscribe unsubscribe} not required. + * + * **Note:** Unsubscribed instance won't call the dispatcher to deliver updates to the listeners. + */ + unsubscribe() { + // Check whether an instance-level subscription flag not set or parent has active subscription. + if (!this.state._isSubscribed || this.state.isSubscribed) { + // Warn if a user tries to unsubscribe using specific subscription which subscribed as part of a subscription set. + if (!this.state._isSubscribed && this.state.parents.length > 0 && this.state.isSubscribed) { + this.state.client.logger.warn(this.subscriptionType, () => ({ + messageType: 'object', + details: 'Subscription is subscribed as part of a subscription set. Remove from active sets to unsubscribe:', + message: this.state.parents.filter((subscriptionSet) => subscriptionSet.isSubscribed), + })); + return; + } + else if (!this.state._isSubscribed) { + this.state.client.logger.trace(this.subscriptionType, 'Not subscribed. Ignoring unsubscribe request.'); + return; + } + } + this.state.client.logger.debug(this.subscriptionType, 'Unsubscribe'); + this.state.isSubscribed = false; + delete this.state.cursor; + this.updateSubscription({ subscribing: false }); + } + /** + * Update channels and groups used by subscription loop. + * + * @param parameters - Subscription loop update parameters. + * @param parameters.subscribing - Whether subscription updates as part of subscription or unsubscription. + * @param [parameters.timetoken] - Subscription catch-up timetoken. + * @param [parameters.subscriptions] - List of subscriptions which should be used to modify a subscription loop + * object. + * + * @internal + */ + updateSubscription(parameters) { + var _a, _b; + if (parameters === null || parameters === void 0 ? void 0 : parameters.timetoken) { + if (((_a = this.state.cursor) === null || _a === void 0 ? void 0 : _a.timetoken) && ((_b = this.state.cursor) === null || _b === void 0 ? void 0 : _b.timetoken) !== '0') { + if (parameters.timetoken !== '0' && parameters.timetoken > this.state.cursor.timetoken) + this.state.cursor.timetoken = parameters.timetoken; + } + else + this.state.cursor = { timetoken: parameters.timetoken }; + } + const subscriptions = parameters.subscriptions && parameters.subscriptions.length > 0 ? parameters.subscriptions : undefined; + if (parameters.subscribing) { + this.register(Object.assign(Object.assign({}, (parameters.timetoken ? { cursor: this.state.cursor } : {})), (subscriptions ? { subscriptions } : {}))); + } + else + this.unregister(subscriptions); + } + } + + /** + * {@link SubscriptionSet} state object. + * + * State object used across multiple {@link SubscriptionSet} object clones. + * + * @internal + */ + class SubscriptionSetState extends SubscriptionBaseState { + /** + * Create a subscription state object. + * + * @param parameters - State configuration options + * @param parameters.client - PubNub client which will work with a subscription object. + * @param parameters.subscriptions - List of subscriptions managed by set. + * @param [parameters.options] - Subscription behavior options. + */ + constructor(parameters) { + const subscriptionInput = new SubscriptionInput({}); + parameters.subscriptions.forEach((subscription) => subscriptionInput.add(subscription.state.subscriptionInput)); + super(parameters.client, subscriptionInput, parameters.options, parameters.client.subscriptionTimetoken); + this.subscriptions = parameters.subscriptions; + } + /** + * Add a single subscription object to the set. + * + * @param subscription - Another entity's subscription object, which should be added. + */ + addSubscription(subscription) { + if (this.subscriptions.includes(subscription)) + return; + subscription.state.addParentState(this); + this.subscriptions.push(subscription); + // Update subscription input. + this.subscriptionInput.add(subscription.state.subscriptionInput); + } + /** + * Remove a single subscription object from the set. + * + * @param subscription - Another entity's subscription object, which should be removed. + * @param clone - Whether a target subscription is a clone. + */ + removeSubscription(subscription, clone) { + const index = this.subscriptions.indexOf(subscription); + if (index === -1) + return; + this.subscriptions.splice(index, 1); + if (!clone) + subscription.state.removeParentState(this); + // Update subscription input. + this.subscriptionInput.remove(subscription.state.subscriptionInput); + } + /** + * Remove any registered subscription object. + */ + removeAllSubscriptions() { + this.subscriptions.forEach((subscription) => subscription.state.removeParentState(this)); + this.subscriptions.splice(0, this.subscriptions.length); + this.subscriptionInput.removeAll(); + } + } + /** + * Multiple entities subscription set object which can be used to receive and handle real-time + * updates. + * + * Subscription set object represents a collection of per-entity subscription objects and allows + * processing them at once for subscription loop and events handling. + */ + class SubscriptionSet extends SubscriptionBase { + /** + * Create entities' subscription set object. + * + * Subscription set object represents a collection of per-entity subscription objects and allows + * processing them at once for subscription loop and events handling. + * + * @param parameters - Subscription set object configuration. + * + * @returns Ready to use entities' subscription set object. + * + * @internal + */ + constructor(parameters) { + let state; + if ('client' in parameters) { + let subscriptions = []; + if (!parameters.subscriptions && parameters.entities) { + parameters.entities.forEach((entity) => subscriptions.push(entity.subscription(parameters.options))); + } + else if (parameters.subscriptions) + subscriptions = parameters.subscriptions; + state = new SubscriptionSetState({ client: parameters.client, subscriptions, options: parameters.options }); + subscriptions.forEach((subscription) => subscription.state.addParentState(state)); + state.client.logger.debug('SubscriptionSet', () => ({ + messageType: 'object', + details: 'Create subscription set with parameters:', + message: Object.assign({ subscriptions: state.subscriptions }, (parameters.options ? parameters.options : {})), + })); + } + else { + state = parameters.state; + state.client.logger.debug('SubscriptionSet', 'Create subscription set clone'); + } + super(state, 'SubscriptionSet'); + this.state.storeClone(this.id, this); + // Update a parent sets list for original set subscriptions. + state.subscriptions.forEach((subscription) => subscription.addParentSet(this)); + } + /** + * Get a {@link SubscriptionSet} object state. + * + * @returns: {@link SubscriptionSet} object state. + * + * @internal + */ + get state() { + return super.state; + } + /** + * Get a list of entities' subscription objects registered in a subscription set. + * + * @returns Entities' subscription objects list. + */ + get subscriptions() { + return this.state.subscriptions.slice(0); + } + // -------------------------------------------------------- + // -------------------- Event handler --------------------- + // -------------------------------------------------------- + // region Event handler + /** + * Dispatch received a real-time update. + * + * @param cursor - A time cursor for the next portion of events. + * @param event - A real-time event from multiplexed subscription. + * + * @return `true` if receiver has consumed event. + * + * @internal + */ + handleEvent(cursor, event) { + var _a; + // Check whether an event is not designated for this subscription set. + if (!this.state.subscriptionInput.contains((_a = event.data.subscription) !== null && _a !== void 0 ? _a : event.data.channel)) + return; + // Check whether `event` can be processed or not. + if (!this.state._isSubscribed) { + this.state.client.logger.trace(this.subscriptionType, `Subscription set ${this.id} is not subscribed. Ignoring event.`); + return; + } + super.handleEvent(cursor, event); + if (this.state.subscriptions.length > 0) { + this.state.client.logger.trace(this.subscriptionType, `Notify ${this.id} subscription set subscriptions (count: ${this.state.subscriptions.length}) about received event.`); + } + this.state.subscriptions.forEach((subscription) => subscription.handleEvent(cursor, event)); + } + // endregion + /** + User-provided subscription input associated with this {@link SubscriptionSet} object. + * + * @param forUnsubscribe - Whether list subscription input created for unsubscription (means entity should be free). + * + * @returns Subscription input object. + * + * @internal + */ + subscriptionInput(forUnsubscribe = false) { + let subscriptionInput = this.state.subscriptionInput; + this.state.subscriptions.forEach((subscription) => { + if (forUnsubscribe && subscription.state.entity.subscriptionsCount > 0) + subscriptionInput = subscriptionInput.without(subscription.state.subscriptionInput); + }); + return subscriptionInput; + } + /** + * Make a bare copy of the {@link SubscriptionSet} object. + * + * Copy won't have any type-specific listeners or added listener objects but will have the same internal state as + * the source object. + * + * @returns Bare copy of a {@link SubscriptionSet} object. + */ + cloneEmpty() { + return new SubscriptionSet({ state: this.state }); + } + /** + * Graceful {@link SubscriptionSet} destruction. + * + * This is an instance destructor, which will properly deinitialize it: + * - remove and unset all listeners, + * - try to unsubscribe (if subscribed and there are no more instances interested in the same data stream). + * + * **Note:** Disposed instance won't call the dispatcher to deliver updates to the listeners. + */ + dispose() { + const isLastClone = this.state.isLastClone; + this.state.subscriptions.forEach((subscription) => { + subscription.removeParentSet(this); + if (isLastClone) + subscription.state.removeParentState(this.state); + }); + super.dispose(); + } + /** + * Invalidate {@link SubscriptionSet} object. + * + * Clean up resources used by a subscription object. All {@link SubscriptionObject subscription} objects will be + * removed. + * + * **Important:** This method is used only when a global subscription set is used (backward compatibility). + * + * **Note:** An invalidated instance won't call the dispatcher to deliver updates to the listeners. + * + * @param forDestroy - Whether subscription object invalidated as part of PubNub client destroy process or not. + * + * @internal + */ + invalidate(forDestroy = false) { + const subscriptions = forDestroy ? this.state.subscriptions.slice(0) : this.state.subscriptions; + subscriptions.forEach((subscription) => { + if (forDestroy) { + subscription.state.entity.decreaseSubscriptionCount(this.state.id); + subscription.removeParentSet(this); + } + subscription.invalidate(forDestroy); + }); + if (forDestroy) + this.state.removeAllSubscriptions(); + super.invalidate(); + } + /** + * Add an entity's subscription to the subscription set. + * + * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. + * + * @param subscription - Another entity's subscription object, which should be added. + */ + addSubscription(subscription) { + this.addSubscriptions([subscription]); + } + /** + * Add an entity's subscriptions to the subscription set. + * + * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. + * + * @param subscriptions - List of entity's subscription objects, which should be added. + */ + addSubscriptions(subscriptions) { + const inactiveSubscriptions = []; + const activeSubscriptions = []; + this.state.client.logger.debug(this.subscriptionType, () => { + const ignoredSubscriptions = []; + const subscriptionsToAdd = []; + subscriptions.forEach((subscription) => { + if (!this.state.subscriptions.includes(subscription)) + subscriptionsToAdd.push(subscription); + else + ignoredSubscriptions.push(subscription); + }); + return { + messageType: 'object', + details: `Add subscriptions to ${this.id} (subscriptions count: ${this.state.subscriptions.length + subscriptionsToAdd.length}):`, + message: { addedSubscriptions: subscriptionsToAdd, ignoredSubscriptions }, + }; + }); + subscriptions + .filter((subscription) => !this.state.subscriptions.includes(subscription)) + .forEach((subscription) => { + if (subscription.state.isSubscribed) + activeSubscriptions.push(subscription); + else + inactiveSubscriptions.push(subscription); + subscription.addParentSet(this); + this.state.addSubscription(subscription); + }); + // Check whether there are any subscriptions for which the subscription loop should be changed or not. + if ((activeSubscriptions.length === 0 && inactiveSubscriptions.length === 0) || !this.state.isSubscribed) + return; + activeSubscriptions.forEach(({ state }) => state.entity.increaseSubscriptionCount(this.state.id)); + if (inactiveSubscriptions.length > 0) + this.updateSubscription({ subscribing: true, subscriptions: inactiveSubscriptions }); + } + /** + * Remove an entity's subscription object from the set. + * + * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. + * + * @param subscription - Another entity's subscription object, which should be removed. + */ + removeSubscription(subscription) { + this.removeSubscriptions([subscription]); + } + /** + * Remove an entity's subscription objects from the set. + * + * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. + * + * @param subscriptions - List entity's subscription objects, which should be removed. + */ + removeSubscriptions(subscriptions) { + const activeSubscriptions = []; + this.state.client.logger.debug(this.subscriptionType, () => { + const ignoredSubscriptions = []; + const subscriptionsToRemove = []; + subscriptions.forEach((subscription) => { + if (this.state.subscriptions.includes(subscription)) + subscriptionsToRemove.push(subscription); + else + ignoredSubscriptions.push(subscription); + }); + return { + messageType: 'object', + details: `Remove subscriptions from ${this.id} (subscriptions count: ${this.state.subscriptions.length}):`, + message: { removedSubscriptions: subscriptionsToRemove, ignoredSubscriptions }, + }; + }); + subscriptions + .filter((subscription) => this.state.subscriptions.includes(subscription)) + .forEach((subscription) => { + if (subscription.state.isSubscribed) + activeSubscriptions.push(subscription); + subscription.removeParentSet(this); + this.state.removeSubscription(subscription, subscription.parentSetsCount > 1); + }); + // Check whether there are any subscriptions for which the subscription loop should be changed or not. + if (activeSubscriptions.length === 0 || !this.state.isSubscribed) + return; + this.updateSubscription({ subscribing: false, subscriptions: activeSubscriptions }); + } + /** + * Merge with another {@link SubscriptionSet} object. + * + * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. + * + * @param subscriptionSet - Other entities' subscription set, which should be joined. + */ + addSubscriptionSet(subscriptionSet) { + this.addSubscriptions(subscriptionSet.subscriptions); + } + /** + * Subtract another {@link SubscriptionSet} object. + * + * **Important:** Changes will be effective immediately if {@link SubscriptionSet} already subscribed. + * + * @param subscriptionSet - Other entities' subscription set, which should be subtracted. + */ + removeSubscriptionSet(subscriptionSet) { + this.removeSubscriptions(subscriptionSet.subscriptions); + } + /** + * Register {@link SubscriptionSet} object for real-time events' retrieval. + * + * @param parameters - Object registration parameters. + * @param [parameters.cursor] - Subscription real-time events catch-up cursor. + * @param [parameters.subscriptions] - List of subscription objects which should be registered (in case of partial + * modification). + * + * @internal + */ + register(parameters) { + var _a; + const subscriptions = ((_a = parameters.subscriptions) !== null && _a !== void 0 ? _a : this.state.subscriptions); + subscriptions.forEach(({ state }) => state.entity.increaseSubscriptionCount(this.state.id)); + this.state.client.logger.trace(this.subscriptionType, () => ({ + messageType: 'text', + message: `Register subscription for real-time events: ${this}`, + })); + this.state.client.registerEventHandleCapable(this, parameters.cursor, subscriptions); + } + /** + * Unregister {@link SubscriptionSet} object from real-time events' retrieval. + * + * @param [subscriptions] - List of subscription objects which should be unregistered (in case of partial + * modification). + * + * @internal + */ + unregister(subscriptions) { + const activeSubscriptions = (subscriptions !== null && subscriptions !== void 0 ? subscriptions : this.state.subscriptions); + activeSubscriptions.forEach(({ state }) => state.entity.decreaseSubscriptionCount(this.state.id)); + this.state.client.logger.trace(this.subscriptionType, () => { + if (!subscriptions) { + return { + messageType: 'text', + message: `Unregister subscription from real-time events: ${this}`, + }; + } + else { + return { + messageType: 'object', + message: { + subscription: this, + subscriptions, + }, + details: 'Unregister subscriptions of subscription set from real-time events:', + }; + } + }); + this.state.client.unregisterEventHandleCapable(this, activeSubscriptions); + } + /** + * Stringify subscription object. + * + * @returns Serialized subscription object. + */ + toString() { + const state = this.state; + return `${this.subscriptionType} { id: ${this.id}, stateId: ${state.id}, clonesCount: ${Object.keys(this.state.clones).length}, isSubscribed: ${state.isSubscribed}, subscriptions: [${state.subscriptions + .map((sub) => sub.toString()) + .join(', ')}] }`; + } + } + + /** + * {@link Subscription} state object. + * + * State object used across multiple {@link Subscription} object clones. + * + * @internal + */ + class SubscriptionState extends SubscriptionBaseState { + /** + * Create a subscription state object. + * + * @param parameters - State configuration options + * @param parameters.client - PubNub client which will work with a subscription object. + * @param parameters.entity - Entity for which a subscription object has been created. + * @param [parameters.options] - Subscription behavior options. + */ + constructor(parameters) { + var _a, _b; + const names = parameters.entity.subscriptionNames((_b = (_a = parameters.options) === null || _a === void 0 ? void 0 : _a.receivePresenceEvents) !== null && _b !== void 0 ? _b : false); + const subscriptionInput = new SubscriptionInput({ + [parameters.entity.subscriptionType == SubscriptionType.Channel ? 'channels' : 'channelGroups']: names, + }); + super(parameters.client, subscriptionInput, parameters.options, parameters.client.subscriptionTimetoken); + this.entity = parameters.entity; + } + } + /** + * Single-entity subscription object which can be used to receive and handle real-time updates. + */ + class Subscription extends SubscriptionBase { + /** + * Create a subscribing capable object for entity. + * + * @param parameters - Subscription object configuration. + * + * @internal + */ + constructor(parameters) { + if ('client' in parameters) { + parameters.client.logger.debug('Subscription', () => ({ + messageType: 'object', + details: 'Create subscription with parameters:', + message: Object.assign({ entity: parameters.entity }, (parameters.options ? parameters.options : {})), + })); + } + else + parameters.state.client.logger.debug('Subscription', 'Create subscription clone'); + super('state' in parameters ? parameters.state : new SubscriptionState(parameters)); + /** + * List of subscription {@link SubscriptionSet sets} which contains {@link Subscription subscription}. + * + * List if used to track usage of a specific {@link Subscription subscription} in other subscription + * {@link SubscriptionSet sets}. + * + * **Important:** Tracking is required to prevent cloned instance dispose if there are sets that still use it. + * + * @internal + */ + this.parents = []; + /** + * List of fingerprints from updates which has been handled already. + * + * **Important:** Tracking is required to avoid repetitive call of the subscription object's listener when the object + * is part of multiple subscribed sets. Handler will be called once, and then the fingerprint will be stored in this + * list to avoid another listener call for it. + * + * @internal + */ + this.handledUpdates = []; + this.state.storeClone(this.id, this); + } + /** + * Get a {@link Subscription} object state. + * + * @returns: {@link Subscription} object state. + * + * @internal + */ + get state() { + return super.state; + } + /** + * Get number of {@link SubscriptionSet} which use this subscription object. + * + * @returns Number of {@link SubscriptionSet} which use this subscription object. + * + * @internal + */ + get parentSetsCount() { + return this.parents.length; + } + // -------------------------------------------------------- + // -------------------- Event handler --------------------- + // -------------------------------------------------------- + // region Event handler + /** + * Dispatch received a real-time update. + * + * @param cursor - A time cursor for the next portion of events. + * @param event - A real-time event from multiplexed subscription. + * + * @return `true` if receiver has consumed event. + * + * @internal + */ + handleEvent(cursor, event) { + var _a, _b; + if (!this.state.isSubscribed || + !this.state.subscriptionInput.contains((_a = event.data.subscription) !== null && _a !== void 0 ? _a : event.data.channel)) + return; + if (this.parentSetsCount > 0) { + // Creating from whole payload (not only for published messages). + const fingerprint = messageFingerprint(event.data); + if (this.handledUpdates.includes(fingerprint)) { + this.state.client.logger.trace(this.subscriptionType, `Event (${fingerprint}) already handled by ${this.id}. Ignoring.`); + return; + } + // Update a list of tracked messages and shrink it if too big. + this.handledUpdates.push(fingerprint); + if (this.handledUpdates.length > 10) + this.handledUpdates.shift(); + } + // Check whether an event is not designated for this subscription set. + if (!this.state.subscriptionInput.contains((_b = event.data.subscription) !== null && _b !== void 0 ? _b : event.data.channel)) + return; + super.handleEvent(cursor, event); + } + // endregion + /** + * User-provided subscription input associated with this {@link Subscription} object. + * + * @param forUnsubscribe - Whether list subscription input created for unsubscription (means entity should be free). + * + * @returns Subscription input object. + * + * @internal + */ + subscriptionInput(forUnsubscribe = false) { + if (forUnsubscribe && this.state.entity.subscriptionsCount > 0) + return new SubscriptionInput({}); + return this.state.subscriptionInput; + } + /** + * Make a bare copy of the {@link Subscription} object. + * + * Copy won't have any type-specific listeners or added listener objects but will have the same internal state as + * the source object. + * + * @returns Bare copy of a {@link Subscription} object. + */ + cloneEmpty() { + return new Subscription({ state: this.state }); + } + /** + * Graceful {@link Subscription} object destruction. + * + * This is an instance destructor, which will properly deinitialize it: + * - remove and unset all listeners, + * - try to unsubscribe (if subscribed and there are no more instances interested in the same data stream). + * + * **Important:** {@link Subscription#dispose dispose} won't have any effect if a subscription object is part of + * {@link SubscriptionSet set}. To gracefully dispose an object, it should be removed from the set using + * {@link SubscriptionSet#removeSubscription removeSubscription} (in this case call of + * {@link Subscription#dispose dispose} not required). + * + * **Note:** Disposed instance won't call the dispatcher to deliver updates to the listeners. + */ + dispose() { + if (this.parentSetsCount > 0) { + this.state.client.logger.debug(this.subscriptionType, () => ({ + messageType: 'text', + message: `'${this.state.entity.subscriptionNames()}' subscription still in use. Ignore dispose request.`, + })); + return; + } + this.handledUpdates.splice(0, this.handledUpdates.length); + super.dispose(); + } + /** + * Invalidate subscription object. + * + * Clean up resources used by a subscription object. + * + * **Note:** An invalidated instance won't call the dispatcher to deliver updates to the listeners. + * + * @param forDestroy - Whether subscription object invalidated as part of PubNub client destroy process or not. + * + * @internal + */ + invalidate(forDestroy = false) { + if (forDestroy) + this.state.entity.decreaseSubscriptionCount(this.state.id); + this.handledUpdates.splice(0, this.handledUpdates.length); + super.invalidate(forDestroy); + } + /** + * Add another {@link SubscriptionSet} into which subscription has been added. + * + * @param parent - {@link SubscriptionSet} which has been modified. + * + * @internal + */ + addParentSet(parent) { + if (!this.parents.includes(parent)) { + this.parents.push(parent); + this.state.client.logger.trace(this.subscriptionType, `Add parent subscription set for ${this.id}: ${parent.id}. Parent subscription set count: ${this.parentSetsCount}`); + } + } + /** + * Remove {@link SubscriptionSet} upon subscription removal from it. + * + * @param parent - {@link SubscriptionSet} which has been modified. + * + * @internal + */ + removeParentSet(parent) { + const parentIndex = this.parents.indexOf(parent); + if (parentIndex !== -1) { + this.parents.splice(parentIndex, 1); + this.state.client.logger.trace(this.subscriptionType, `Remove parent subscription set from ${this.id}: ${parent.id}. Parent subscription set count: ${this.parentSetsCount}`); + } + if (this.parentSetsCount === 0) + this.handledUpdates.splice(0, this.handledUpdates.length); + } + /** + * Merge entities' subscription objects into {@link SubscriptionSet}. + * + * @param subscription - Another entity's subscription object to be merged with receiver. + * + * @return {@link SubscriptionSet} which contains both receiver and other entities' subscription objects. + */ + addSubscription(subscription) { + this.state.client.logger.debug(this.subscriptionType, () => ({ + messageType: 'text', + message: `Create set with subscription: ${subscription}`, + })); + const subscriptionSet = new SubscriptionSet({ + client: this.state.client, + subscriptions: [this, subscription], + options: this.state.options, + }); + // Check whether a source subscription is already subscribed or not. + if (!this.state.isSubscribed && !subscription.state.isSubscribed) + return subscriptionSet; + this.state.client.logger.trace(this.subscriptionType, 'Subscribe resulting set because the receiver is already subscribed.'); + // Subscribing resulting subscription set because source subscription was subscribed. + subscriptionSet.subscribe(); + return subscriptionSet; + } + /** + * Register {@link Subscription} object for real-time events' retrieval. + * + * **Note:** Superclass calls this method only in response to a {@link Subscription.subscribe subscribe} method call. + * + * @param parameters - Object registration parameters. + * @param [parameters.cursor] - Subscription real-time events catch-up cursor. + * @param [parameters.subscriptions] - List of subscription objects which should be registered (in case of partial + * modification). + * + * @internal + */ + register(parameters) { + this.state.entity.increaseSubscriptionCount(this.state.id); + this.state.client.logger.trace(this.subscriptionType, () => ({ + messageType: 'text', + message: `Register subscription for real-time events: ${this}`, + })); + this.state.client.registerEventHandleCapable(this, parameters.cursor); + } + /** + * Unregister {@link Subscription} object from real-time events' retrieval. + * + * **Note:** Superclass calls this method only in response to a {@link Subscription.unsubscribe unsubscribe} method + * call. + * + * @param [_subscriptions] - List of subscription objects which should be unregistered (in case of partial + * modification). + * + * @internal + */ + unregister(_subscriptions) { + this.state.entity.decreaseSubscriptionCount(this.state.id); + this.state.client.logger.trace(this.subscriptionType, () => ({ + messageType: 'text', + message: `Unregister subscription from real-time events: ${this}`, + })); + this.handledUpdates.splice(0, this.handledUpdates.length); + this.state.client.unregisterEventHandleCapable(this); + } + /** + * Stringify subscription object. + * + * @returns Serialized subscription object. + */ + toString() { + const state = this.state; + return `${this.subscriptionType} { id: ${this.id}, stateId: ${state.id}, entity: ${state.entity + .subscriptionNames(false) + .pop()}, clonesCount: ${Object.keys(state.clones).length}, isSubscribed: ${state.isSubscribed}, parentSetsCount: ${this.parentSetsCount}, cursor: ${state.cursor ? state.cursor.timetoken : 'not set'}, referenceTimetoken: ${state.referenceTimetoken ? state.referenceTimetoken : 'not set'} }`; + } + } + + /** + * Get Presence State REST API module. + * + * @internal + */ + // endregion + /** + * Get `uuid` presence state request. + * + * @internal + */ + class GetPresenceStateRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b; + var _c, _d; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = (_c = this.parameters).channels) !== null && _a !== void 0 ? _a : (_c.channels = []); + (_b = (_d = this.parameters).channelGroups) !== null && _b !== void 0 ? _b : (_d.channelGroups = []); + } + operation() { + return RequestOperation$1.PNGetStateOperation; + } + validate() { + const { keySet: { subscribeKey }, channels, channelGroups, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + const serviceResponse = this.deserializeResponse(response); + const { channels = [], channelGroups = [] } = this.parameters; + const state = { channels: {} }; + if (channels.length === 1 && channelGroups.length === 0) + state.channels[channels[0]] = serviceResponse.payload; + else + state.channels = serviceResponse.payload; + return state; + }); + } + get path() { + const { keySet: { subscribeKey }, uuid, channels, } = this.parameters; + return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}/uuid/${encodeString(uuid !== null && uuid !== void 0 ? uuid : '')}`; + } + get queryParameters() { + const { channelGroups } = this.parameters; + if (!channelGroups || channelGroups.length === 0) + return {}; + return { 'channel-group': channelGroups.join(',') }; + } + } + + /** + * Set Presence State REST API module. + * + * @internal + */ + // endregion + /** + * Set `uuid` presence state request. + * + * @internal + */ + class SetPresenceStateRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSetStateOperation; + } + validate() { + const { keySet: { subscribeKey }, state, channels = [], channelGroups = [], } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (state === undefined) + return 'Missing State'; + if ((channels === null || channels === void 0 ? void 0 : channels.length) === 0 && (channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.length) === 0) + return 'Please provide a list of channels and/or channel-groups'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { state: this.deserializeResponse(response).payload }; + }); + } + get path() { + const { keySet: { subscribeKey }, uuid, channels, } = this.parameters; + return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}/uuid/${encodeString(uuid)}/data`; + } + get queryParameters() { + const { channelGroups, state } = this.parameters; + const query = { state: JSON.stringify(state) }; + if (channelGroups && channelGroups.length !== 0) + query['channel-group'] = channelGroups.join(','); + return query; + } + } + + /** + * Announce heartbeat REST API module. + * + * @internal + */ + // endregion + /** + * Announce `uuid` presence request. + * + * @internal + */ + class HeartbeatRequest extends AbstractRequest { + constructor(parameters) { + super({ cancellable: true }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNHeartbeatOperation; + } + validate() { + const { keySet: { subscribeKey }, channels = [], channelGroups = [], } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (channels.length === 0 && channelGroups.length === 0) + return 'Please provide a list of channels and/or channel-groups'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + get path() { + const { keySet: { subscribeKey }, channels, } = this.parameters; + return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}/heartbeat`; + } + get queryParameters() { + const { channelGroups, state, heartbeat } = this.parameters; + const query = { heartbeat: `${heartbeat}` }; + if (channelGroups && channelGroups.length !== 0) + query['channel-group'] = channelGroups.join(','); + if (state !== undefined) + query.state = JSON.stringify(state); + return query; + } + } + + /** + * Announce leave REST API module. + * + * @internal + */ + // endregion + /** + * Announce user leave request. + * + * @internal + */ + class PresenceLeaveRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + if (this.parameters.channelGroups) + this.parameters.channelGroups = Array.from(new Set(this.parameters.channelGroups)); + if (this.parameters.channels) + this.parameters.channels = Array.from(new Set(this.parameters.channels)); + } + operation() { + return RequestOperation$1.PNUnsubscribeOperation; + } + validate() { + const { keySet: { subscribeKey }, channels = [], channelGroups = [], } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (channels.length === 0 && channelGroups.length === 0) + return 'At least one `channel` or `channel group` should be provided.'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + get path() { + var _a; + const { keySet: { subscribeKey }, channels, } = this.parameters; + return `/v2/presence/sub-key/${subscribeKey}/channel/${encodeNames((_a = channels === null || channels === void 0 ? void 0 : channels.sort()) !== null && _a !== void 0 ? _a : [], ',')}/leave`; + } + get queryParameters() { + const { channelGroups } = this.parameters; + if (!channelGroups || channelGroups.length === 0) + return {}; + return { 'channel-group': channelGroups.sort().join(',') }; + } + } + + /** + * `uuid` presence REST API module. + * + * @internal + */ + // endregion + /** + * Get `uuid` presence request. + * + * @internal + */ + class WhereNowRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNWhereNowOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + const serviceResponse = this.deserializeResponse(response); + if (!serviceResponse.payload) + return { channels: [] }; + return { channels: serviceResponse.payload.channels }; + }); + } + get path() { + const { keySet: { subscribeKey }, uuid, } = this.parameters; + return `/v2/presence/sub-key/${subscribeKey}/uuid/${encodeString(uuid)}`; + } + } + + /** + * Channels / channel groups presence REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `uuid` should be included in response or not. + */ + const INCLUDE_UUID$1 = true; + /** + * Whether state associated with `uuid` should be included in response or not. + */ + const INCLUDE_STATE = false; + /** + * Maximum number of participants which can be returned with single response. + */ + const MAXIMUM_COUNT = 1000; + // endregion + /** + * Channel presence request. + * + * @internal + */ + class HereNowRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d; + var _e, _f, _g, _h; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = (_e = this.parameters).queryParameters) !== null && _a !== void 0 ? _a : (_e.queryParameters = {}); + (_b = (_f = this.parameters).includeUUIDs) !== null && _b !== void 0 ? _b : (_f.includeUUIDs = INCLUDE_UUID$1); + (_c = (_g = this.parameters).includeState) !== null && _c !== void 0 ? _c : (_g.includeState = INCLUDE_STATE); + (_d = (_h = this.parameters).limit) !== null && _d !== void 0 ? _d : (_h.limit = MAXIMUM_COUNT); + } + operation() { + const { channels = [], channelGroups = [] } = this.parameters; + return channels.length === 0 && channelGroups.length === 0 + ? RequestOperation$1.PNGlobalHereNowOperation + : RequestOperation$1.PNHereNowOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b; + const serviceResponse = this.deserializeResponse(response); + // Extract general presence information. + const totalChannels = 'occupancy' in serviceResponse ? 1 : serviceResponse.payload.total_channels; + const totalOccupancy = 'occupancy' in serviceResponse ? serviceResponse.occupancy : serviceResponse.payload.total_occupancy; + const channelsPresence = {}; + let channels = {}; + const limit = this.parameters.limit; + let occupancyMatchLimit = false; + // Remap single channel presence to multiple channels presence response. + if ('occupancy' in serviceResponse) { + const channel = this.parameters.channels[0]; + channels[channel] = { uuids: (_a = serviceResponse.uuids) !== null && _a !== void 0 ? _a : [], occupancy: totalOccupancy }; + } + else + channels = (_b = serviceResponse.payload.channels) !== null && _b !== void 0 ? _b : {}; + Object.keys(channels).forEach((channel) => { + const channelEntry = channels[channel]; + channelsPresence[channel] = { + occupants: this.parameters.includeUUIDs + ? channelEntry.uuids.map((uuid) => { + if (typeof uuid === 'string') + return { uuid, state: null }; + return uuid; + }) + : [], + name: channel, + occupancy: channelEntry.occupancy, + }; + if (!occupancyMatchLimit && channelEntry.occupancy === limit) + occupancyMatchLimit = true; + }); + return { + totalChannels, + totalOccupancy, + channels: channelsPresence, + }; + }); + } + get path() { + const { keySet: { subscribeKey }, channels, channelGroups, } = this.parameters; + let path = `/v2/presence/sub-key/${subscribeKey}`; + if ((channels && channels.length > 0) || (channelGroups && channelGroups.length > 0)) + path += `/channel/${encodeNames(channels !== null && channels !== void 0 ? channels : [], ',')}`; + return path; + } + get queryParameters() { + const { channelGroups, includeUUIDs, includeState, limit, offset, queryParameters } = this.parameters; + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (this.operation() === RequestOperation$1.PNHereNowOperation ? { limit } : {})), (this.operation() === RequestOperation$1.PNHereNowOperation && (offset !== null && offset !== void 0 ? offset : 0 > 0) ? { offset } : {})), (!includeUUIDs ? { disable_uuids: '1' } : {})), ((includeState !== null && includeState !== void 0 ? includeState : false) ? { state: '1' } : {})), (channelGroups && channelGroups.length > 0 ? { 'channel-group': channelGroups.join(',') } : {})), queryParameters); + } + } + + /** + * Delete messages REST API module. + * + * @internal + */ + // endregion + /** + * Delete messages from channel history. + * + * @internal + */ + class DeleteMessageRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNDeleteMessagesOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + if (!this.parameters.channel) + return 'Missing channel'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v3/history/sub-key/${subscribeKey}/channel/${encodeString(channel)}`; + } + get queryParameters() { + const { start, end } = this.parameters; + return Object.assign(Object.assign({}, (start ? { start } : {})), (end ? { end } : {})); + } + } + + /** + * Messages count REST API module. + * + * @internal + */ + // endregion + /** + * Count messages request. + * + * @internal + */ + class MessageCountRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNMessageCounts; + } + validate() { + const { keySet: { subscribeKey }, channels, timetoken, channelTimetokens, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channels) + return 'Missing channels'; + if (timetoken && channelTimetokens) + return '`timetoken` and `channelTimetokens` are incompatible together'; + if (!timetoken && !channelTimetokens) + return '`timetoken` or `channelTimetokens` need to be set'; + if (channelTimetokens && channelTimetokens.length > 1 && channelTimetokens.length !== channels.length) + return 'Length of `channelTimetokens` and `channels` do not match'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { channels: this.deserializeResponse(response).channels }; + }); + } + get path() { + return `/v3/history/sub-key/${this.parameters.keySet.subscribeKey}/message-counts/${encodeNames(this.parameters.channels)}`; + } + get queryParameters() { + let { channelTimetokens } = this.parameters; + if (this.parameters.timetoken) + channelTimetokens = [this.parameters.timetoken]; + return Object.assign(Object.assign({}, (channelTimetokens.length === 1 ? { timetoken: channelTimetokens[0] } : {})), (channelTimetokens.length > 1 ? { channelsTimetoken: channelTimetokens.join(',') } : {})); + } + } + + /** + * Get history REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ---------------------- Defaults ------------------------ + // -------------------------------------------------------- + // region Defaults + /** + * Whether verbose logging enabled or not. + */ + const LOG_VERBOSITY$1 = false; + /** + * Whether associated message metadata should be returned or not. + */ + const INCLUDE_METADATA = false; + /** + * Whether timetokens should be returned as strings by default or not. + */ + const STRINGIFY_TIMETOKENS$1 = false; + /** + * Default and maximum number of messages which should be returned. + */ + const MESSAGES_COUNT = 100; + // endregion + /** + * Get single channel messages request. + * + * @internal + */ + class GetHistoryRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c; + super(); + this.parameters = parameters; + // Apply defaults. + if (parameters.count) + parameters.count = Math.min(parameters.count, MESSAGES_COUNT); + else + parameters.count = MESSAGES_COUNT; + (_a = parameters.stringifiedTimeToken) !== null && _a !== void 0 ? _a : (parameters.stringifiedTimeToken = STRINGIFY_TIMETOKENS$1); + (_b = parameters.includeMeta) !== null && _b !== void 0 ? _b : (parameters.includeMeta = INCLUDE_METADATA); + (_c = parameters.logVerbosity) !== null && _c !== void 0 ? _c : (parameters.logVerbosity = LOG_VERBOSITY$1); + } + operation() { + return RequestOperation$1.PNHistoryOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + if (!this.parameters.channel) + return 'Missing channel'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + const serviceResponse = this.deserializeResponse(response); + const messages = serviceResponse[0]; + const startTimeToken = serviceResponse[1]; + const endTimeToken = serviceResponse[2]; + // Handle malformed get history response. + if (!Array.isArray(messages)) + return { messages: [], startTimeToken, endTimeToken }; + return { + messages: messages.map((payload) => { + const processedPayload = this.processPayload(payload.message); + const item = { + entry: processedPayload.payload, + timetoken: payload.timetoken, + }; + if (processedPayload.error) + item.error = processedPayload.error; + if (payload.meta) + item.meta = payload.meta; + return item; + }), + startTimeToken, + endTimeToken, + }; + }); + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v2/history/sub-key/${subscribeKey}/channel/${encodeString(channel)}`; + } + get queryParameters() { + const { start, end, reverse, count, stringifiedTimeToken, includeMeta } = this.parameters; + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: count, include_token: 'true' }, (start ? { start } : {})), (end ? { end } : {})), (stringifiedTimeToken ? { string_message_token: 'true' } : {})), (reverse !== undefined && reverse !== null ? { reverse: reverse.toString() } : {})), (includeMeta ? { include_meta: 'true' } : {})); + } + processPayload(payload) { + const { crypto, logVerbosity } = this.parameters; + if (!crypto || typeof payload !== 'string') + return { payload }; + let decryptedPayload; + let error; + try { + const decryptedData = crypto.decrypt(payload); + decryptedPayload = + decryptedData instanceof ArrayBuffer + ? JSON.parse(GetHistoryRequest.decoder.decode(decryptedData)) + : decryptedData; + } + catch (err) { + if (logVerbosity) + console.log(`decryption error`, err.message); + decryptedPayload = payload; + error = `Error while decrypting message content: ${err.message}`; + } + return { + payload: decryptedPayload, + error, + }; + } + } + + // endregion + // -------------------------------------------------------- + // -------------------- Fetch Messages -------------------- + // -------------------------------------------------------- + // region Fetch Messages + /** + * PubNub-defined message type. + * + * Types of messages which can be retrieved with fetch messages REST API. + */ + var PubNubMessageType; + (function (PubNubMessageType) { + /** + * Regular message. + */ + PubNubMessageType[PubNubMessageType["Message"] = -1] = "Message"; + /** + * File message. + */ + PubNubMessageType[PubNubMessageType["Files"] = 4] = "Files"; + })(PubNubMessageType || (PubNubMessageType = {})); + // endregion + + /** + * Fetch messages REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ---------------------- Defaults ------------------------ + // -------------------------------------------------------- + // region Defaults + /** + * Whether verbose logging enabled or not. + */ + const LOG_VERBOSITY = false; + /** + * Whether message type should be returned or not. + */ + const INCLUDE_MESSAGE_TYPE = true; + /** + * Whether timetokens should be returned as strings by default or not. + */ + const STRINGIFY_TIMETOKENS = false; + /** + * Whether message publisher `uuid` should be returned or not. + */ + const INCLUDE_UUID = true; + /** + * Default number of messages which can be returned for single channel, and it is maximum as well. + */ + const SINGLE_CHANNEL_MESSAGES_COUNT = 100; + /** + * Default number of messages which can be returned for multiple channels or when fetched + * message actions. + */ + const MULTIPLE_CHANNELS_MESSAGES_COUNT = 25; + // endregion + /** + * Fetch messages from channels request. + * + * @internal + */ + class FetchMessagesRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d, _e; + super(); + this.parameters = parameters; + // Apply defaults. + const includeMessageActions = (_a = parameters.includeMessageActions) !== null && _a !== void 0 ? _a : false; + const defaultCount = parameters.channels.length > 1 || includeMessageActions + ? MULTIPLE_CHANNELS_MESSAGES_COUNT + : SINGLE_CHANNEL_MESSAGES_COUNT; + if (!parameters.count) + parameters.count = defaultCount; + else + parameters.count = Math.min(parameters.count, defaultCount); + if (parameters.includeUuid) + parameters.includeUUID = parameters.includeUuid; + else + (_b = parameters.includeUUID) !== null && _b !== void 0 ? _b : (parameters.includeUUID = INCLUDE_UUID); + (_c = parameters.stringifiedTimeToken) !== null && _c !== void 0 ? _c : (parameters.stringifiedTimeToken = STRINGIFY_TIMETOKENS); + (_d = parameters.includeMessageType) !== null && _d !== void 0 ? _d : (parameters.includeMessageType = INCLUDE_MESSAGE_TYPE); + (_e = parameters.logVerbosity) !== null && _e !== void 0 ? _e : (parameters.logVerbosity = LOG_VERBOSITY); + } + operation() { + return RequestOperation$1.PNFetchMessagesOperation; + } + validate() { + const { keySet: { subscribeKey }, channels, includeMessageActions, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channels) + return 'Missing channels'; + if (includeMessageActions !== undefined && includeMessageActions && channels.length > 1) + return ('History can return actions data for a single channel only. Either pass a single channel ' + + 'or disable the includeMessageActions flag.'); + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + const serviceResponse = this.deserializeResponse(response); + const responseChannels = (_a = serviceResponse.channels) !== null && _a !== void 0 ? _a : {}; + const channels = {}; + Object.keys(responseChannels).forEach((channel) => { + // Map service response to expected data object type structure. + channels[channel] = responseChannels[channel].map((payload) => { + // `null` message type means regular message. + if (payload.message_type === null) + payload.message_type = PubNubMessageType.Message; + const processedPayload = this.processPayload(channel, payload); + const item = Object.assign(Object.assign({ channel, timetoken: payload.timetoken, message: processedPayload.payload, messageType: payload.message_type }, (payload.custom_message_type ? { customMessageType: payload.custom_message_type } : {})), { uuid: payload.uuid }); + if (payload.actions) { + const itemWithActions = item; + itemWithActions.actions = payload.actions; + // Backward compatibility for existing users. + // TODO: Remove in next release. + itemWithActions.data = payload.actions; + } + if (payload.meta) + item.meta = payload.meta; + if (processedPayload.error) + item.error = processedPayload.error; + return item; + }); + }); + if (serviceResponse.more) + return { channels, more: serviceResponse.more }; + return { channels }; + }); + } + get path() { + const { keySet: { subscribeKey }, channels, includeMessageActions, } = this.parameters; + const endpoint = !includeMessageActions ? 'history' : 'history-with-actions'; + return `/v3/${endpoint}/sub-key/${subscribeKey}/channel/${encodeNames(channels)}`; + } + get queryParameters() { + const { start, end, count, includeCustomMessageType, includeMessageType, includeMeta, includeUUID, stringifiedTimeToken, } = this.parameters; + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ max: count }, (start ? { start } : {})), (end ? { end } : {})), (stringifiedTimeToken ? { string_message_token: 'true' } : {})), (includeMeta !== undefined && includeMeta ? { include_meta: 'true' } : {})), (includeUUID ? { include_uuid: 'true' } : {})), (includeCustomMessageType !== undefined && includeCustomMessageType !== null + ? { include_custom_message_type: includeCustomMessageType ? 'true' : 'false' } + : {})), (includeMessageType ? { include_message_type: 'true' } : {})); + } + /** + * Parse single channel data entry. + * + * @param channel - Channel for which {@link payload} should be processed. + * @param payload - Source payload which should be processed and parsed to expected type. + * + * @returns + */ + processPayload(channel, payload) { + const { crypto, logVerbosity } = this.parameters; + if (!crypto || typeof payload.message !== 'string') + return { payload: payload.message }; + let decryptedPayload; + let error; + try { + const decryptedData = crypto.decrypt(payload.message); + decryptedPayload = + decryptedData instanceof ArrayBuffer + ? JSON.parse(FetchMessagesRequest.decoder.decode(decryptedData)) + : decryptedData; + } + catch (err) { + if (logVerbosity) + console.log(`decryption error`, err.message); + decryptedPayload = payload.message; + error = `Error while decrypting message content: ${err.message}`; + } + if (!error && + decryptedPayload && + payload.message_type == PubNubMessageType.Files && + typeof decryptedPayload === 'object' && + this.isFileMessage(decryptedPayload)) { + const fileMessage = decryptedPayload; + return { + payload: { + message: fileMessage.message, + file: Object.assign(Object.assign({}, fileMessage.file), { url: this.parameters.getFileUrl({ channel, id: fileMessage.file.id, name: fileMessage.file.name }) }), + }, + error, + }; + } + return { payload: decryptedPayload, error }; + } + /** + * Check whether `payload` potentially represents file message. + * + * @param payload - Fetched message payload. + * + * @returns `true` if payload can be {@link History#FileMessage|FileMessage}. + */ + isFileMessage(payload) { + return payload.file !== undefined; + } + } + + /** + * Get Message Actions REST API module. + * + * @internal + */ + // endregion + /** + * Fetch channel message actions request. + * + * @internal + */ + class GetMessageActionsRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetMessageActionsOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + if (!this.parameters.channel) + return 'Missing message channel'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + const serviceResponse = this.deserializeResponse(response); + let start = null; + let end = null; + if (serviceResponse.data.length > 0) { + start = serviceResponse.data[0].actionTimetoken; + end = serviceResponse.data[serviceResponse.data.length - 1].actionTimetoken; + } + return { + data: serviceResponse.data, + more: serviceResponse.more, + start, + end, + }; + }); + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v1/message-actions/${subscribeKey}/channel/${encodeString(channel)}`; + } + get queryParameters() { + const { limit, start, end } = this.parameters; + return Object.assign(Object.assign(Object.assign({}, (start ? { start } : {})), (end ? { end } : {})), (limit ? { limit } : {})); + } + } + + /** + * Add Message Action REST API module. + * + * @internal + */ + // endregion + /** + * Add Message Reaction request. + * + * @internal + */ + class AddMessageActionRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNAddMessageActionOperation; + } + validate() { + const { keySet: { subscribeKey }, action, channel, messageTimetoken, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channel) + return 'Missing message channel'; + if (!messageTimetoken) + return 'Missing message timetoken'; + if (!action) + return 'Missing Action'; + if (!action.value) + return 'Missing Action.value'; + if (!action.type) + return 'Missing Action.type'; + if (action.type.length > 15) + return 'Action.type value exceed maximum length of 15'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then(({ data }) => ({ data })); + }); + } + get path() { + const { keySet: { subscribeKey }, channel, messageTimetoken, } = this.parameters; + return `/v1/message-actions/${subscribeKey}/channel/${encodeString(channel)}/message/${messageTimetoken}`; + } + get headers() { + var _a; + return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); + } + get body() { + return JSON.stringify(this.parameters.action); + } + } + + /** + * Remove Message Action REST API module. + * + * @internal + */ + // endregion + /** + * Remove specific message action request. + * + * @internal + */ + class RemoveMessageAction extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveMessageActionOperation; + } + validate() { + const { keySet: { subscribeKey }, channel, messageTimetoken, actionTimetoken, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channel) + return 'Missing message action channel'; + if (!messageTimetoken) + return 'Missing message timetoken'; + if (!actionTimetoken) + return 'Missing action timetoken'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then(({ data }) => ({ data })); + }); + } + get path() { + const { keySet: { subscribeKey }, channel, actionTimetoken, messageTimetoken, } = this.parameters; + return `/v1/message-actions/${subscribeKey}/channel/${encodeString(channel)}/message/${messageTimetoken}/action/${actionTimetoken}`; + } + } + + /** + * Publish File Message REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether published file messages should be stored in the channel's history. + */ + const STORE_IN_HISTORY = true; + // endregion + /** + * Publish shared file information request. + * + * @internal + */ + class PublishFileMessageRequest extends AbstractRequest { + constructor(parameters) { + var _a; + var _b; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = (_b = this.parameters).storeInHistory) !== null && _a !== void 0 ? _a : (_b.storeInHistory = STORE_IN_HISTORY); + } + operation() { + return RequestOperation$1.PNPublishFileMessageOperation; + } + validate() { + const { channel, fileId, fileName } = this.parameters; + if (!channel) + return "channel can't be empty"; + if (!fileId) + return "file id can't be empty"; + if (!fileName) + return "file name can't be empty"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { timetoken: this.deserializeResponse(response)[2] }; + }); + } + get path() { + const { message, channel, keySet: { publishKey, subscribeKey }, fileId, fileName, } = this.parameters; + const fileMessage = Object.assign({ file: { + name: fileName, + id: fileId, + } }, (message ? { message } : {})); + return `/v1/files/publish-file/${publishKey}/${subscribeKey}/0/${encodeString(channel)}/0/${encodeString(this.prepareMessagePayload(fileMessage))}`; + } + get queryParameters() { + const { customMessageType, storeInHistory, ttl, meta } = this.parameters; + return Object.assign(Object.assign(Object.assign({ store: storeInHistory ? '1' : '0' }, (customMessageType ? { custom_message_type: customMessageType } : {})), (ttl ? { ttl } : {})), (meta && typeof meta === 'object' ? { meta: JSON.stringify(meta) } : {})); + } + /** + * Pre-process provided data. + * + * Data will be "normalized" and encrypted if `cryptoModule` has been provided. + * + * @param payload - User-provided data which should be pre-processed before use. + * + * @returns Payload which can be used as part of request URL or body. + * + * @throws {Error} in case if provided `payload` or results of `encryption` can't be stringified. + */ + prepareMessagePayload(payload) { + const { crypto } = this.parameters; + if (!crypto) + return JSON.stringify(payload) || ''; + const encrypted = crypto.encrypt(JSON.stringify(payload)); + return JSON.stringify(typeof encrypted === 'string' ? encrypted : encode(encrypted)); + } + } + + /** + * File sharing REST API module. + * + * @internal + */ + // endregion + /** + * File download Url generation request. + * + * Local request which generates Url to download shared file from the specific channel. + * + * @internal + */ + class GetFileDownloadUrlRequest extends AbstractRequest { + /** + * Construct file download Url generation request. + * + * @param parameters - Request configuration. + */ + constructor(parameters) { + super({ method: TransportMethod.LOCAL }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetFileUrlOperation; + } + validate() { + const { channel, id, name } = this.parameters; + if (!channel) + return "channel can't be empty"; + if (!id) + return "file id can't be empty"; + if (!name) + return "file name can't be empty"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return response.url; + }); + } + get path() { + const { channel, id, name, keySet: { subscribeKey }, } = this.parameters; + return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files/${encodeString(id)}/${encodeString(name)}`; + } + } + + /** + * Delete file REST API module. + * + * @internal + */ + // endregion + /** + * Delete File request. + * + * @internal + */ + class DeleteFileRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNDeleteFileOperation; + } + validate() { + const { channel, id, name } = this.parameters; + if (!channel) + return "channel can't be empty"; + if (!id) + return "file id can't be empty"; + if (!name) + return "file name can't be empty"; + } + get path() { + const { keySet: { subscribeKey }, id, channel, name, } = this.parameters; + return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files/${encodeString(id)}/${encodeString(name)}`; + } + } + + /** + * List Files REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Number of files to return in response. + */ + const LIMIT$6 = 100; + // endregion + /** + * Files List request. + * + * @internal + */ + class FilesListRequest extends AbstractRequest { + constructor(parameters) { + var _a; + var _b; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = (_b = this.parameters).limit) !== null && _a !== void 0 ? _a : (_b.limit = LIMIT$6); + } + operation() { + return RequestOperation$1.PNListFilesOperation; + } + validate() { + if (!this.parameters.channel) + return "channel can't be empty"; + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files`; + } + get queryParameters() { + const { limit, next } = this.parameters; + return Object.assign({ limit: limit }, (next ? { next } : {})); + } + } + + /** + * Generate file upload URL REST API request. + * + * @internal + */ + // endregion + /** + * Generate File Upload Url request. + * + * @internal + */ + class GenerateFileUploadUrlRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGenerateUploadUrlOperation; + } + validate() { + if (!this.parameters.channel) + return "channel can't be empty"; + if (!this.parameters.name) + return "'name' can't be empty"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + const serviceResponse = this.deserializeResponse(response); + return { + id: serviceResponse.data.id, + name: serviceResponse.data.name, + url: serviceResponse.file_upload_request.url, + formFields: serviceResponse.file_upload_request.form_fields, + }; + }); + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/generate-upload-url`; + } + get headers() { + var _a; + return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); + } + get body() { + return JSON.stringify({ name: this.parameters.name }); + } + } + + /** + * Upload file REST API request. + * + * @internal + */ + /** + * File Upload request. + * + * @internal + */ + class UploadFileRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + // Use file's actual mime type if available. + const mimeType = parameters.file.mimeType; + if (mimeType) { + parameters.formFields = parameters.formFields.map((entry) => { + if (entry.name === 'Content-Type') + return { name: entry.name, value: mimeType }; + return entry; + }); + } + } + operation() { + return RequestOperation$1.PNPublishFileOperation; + } + validate() { + const { fileId, fileName, file, uploadUrl } = this.parameters; + if (!fileId) + return "Validation failed: file 'id' can't be empty"; + if (!fileName) + return "Validation failed: file 'name' can't be empty"; + if (!file) + return "Validation failed: 'file' can't be empty"; + if (!uploadUrl) + return "Validation failed: file upload 'url' can't be empty"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { + status: response.status, + message: response.body ? UploadFileRequest.decoder.decode(response.body) : 'OK', + }; + }); + } + request() { + return Object.assign(Object.assign({}, super.request()), { origin: new URL(this.parameters.uploadUrl).origin, timeout: 300 }); + } + get path() { + const { pathname, search } = new URL(this.parameters.uploadUrl); + return `${pathname}${search}`; + } + get body() { + return this.parameters.file; + } + get formData() { + return this.parameters.formFields; + } + } + + /** + * Share File API module. + * + * @internal + */ + // endregion + /** + * Send file composed request. + * + * @internal + */ + class SendFileRequest { + constructor(parameters) { + var _a; + this.parameters = parameters; + this.file = (_a = this.parameters.PubNubFile) === null || _a === void 0 ? void 0 : _a.create(parameters.file); + if (!this.file) + throw new Error('File upload error: unable to create File object.'); + } + /** + * Process user-input and upload file. + * + * @returns File upload request response. + */ + process() { + return __awaiter(this, void 0, void 0, function* () { + let fileName; + let fileId; + return this.generateFileUploadUrl() + .then((result) => { + fileName = result.name; + fileId = result.id; + return this.uploadFile(result); + }) + .then((result) => { + if (result.status !== 204) { + throw new PubNubError('Upload to bucket was unsuccessful', { + error: true, + statusCode: result.status, + category: StatusCategory$1.PNUnknownCategory, + operation: RequestOperation$1.PNPublishFileOperation, + errorData: { message: result.message }, + }); + } + }) + .then(() => this.publishFileMessage(fileId, fileName)) + .catch((error) => { + if (error instanceof PubNubError) + throw error; + const apiError = !(error instanceof PubNubAPIError) ? PubNubAPIError.create(error) : error; + throw new PubNubError('File upload error.', apiError.toStatus(RequestOperation$1.PNPublishFileOperation)); + }); + }); + } + /** + * Generate pre-signed file upload Url. + * + * @returns File upload credentials. + */ + generateFileUploadUrl() { + return __awaiter(this, void 0, void 0, function* () { + const request = new GenerateFileUploadUrlRequest(Object.assign(Object.assign({}, this.parameters), { name: this.file.name, keySet: this.parameters.keySet })); + return this.parameters.sendRequest(request); + }); + } + /** + * Prepare and upload {@link PubNub} File object to remote storage. + * + * @param uploadParameters - File upload request parameters. + * + * @returns + */ + uploadFile(uploadParameters) { + return __awaiter(this, void 0, void 0, function* () { + const { cipherKey, PubNubFile, crypto, cryptography } = this.parameters; + const { id, name, url, formFields } = uploadParameters; + // Encrypt file if possible. + if (this.parameters.PubNubFile.supportsEncryptFile) { + if (!cipherKey && crypto) + this.file = (yield crypto.encryptFile(this.file, PubNubFile)); + else if (cipherKey && cryptography) + this.file = (yield cryptography.encryptFile(cipherKey, this.file, PubNubFile)); + } + return this.parameters.sendRequest(new UploadFileRequest({ + fileId: id, + fileName: name, + file: this.file, + uploadUrl: url, + formFields, + })); + }); + } + publishFileMessage(fileId, fileName) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b, _c, _d; + let result = { timetoken: '0' }; + let retries = this.parameters.fileUploadPublishRetryLimit; + let publishError; + let wasSuccessful = false; + do { + try { + result = yield this.parameters.publishFile(Object.assign(Object.assign({}, this.parameters), { fileId, fileName })); + wasSuccessful = true; + } + catch (error) { + if (error instanceof PubNubError) + publishError = error; + retries -= 1; + } + } while (!wasSuccessful && retries > 0); + if (!wasSuccessful) { + throw new PubNubError('Publish failed. You may want to execute that operation manually using pubnub.publishFile', { + error: true, + category: (_b = (_a = publishError.status) === null || _a === void 0 ? void 0 : _a.category) !== null && _b !== void 0 ? _b : StatusCategory$1.PNUnknownCategory, + statusCode: (_d = (_c = publishError.status) === null || _c === void 0 ? void 0 : _c.statusCode) !== null && _d !== void 0 ? _d : 0, + channel: this.parameters.channel, + id: fileId, + name: fileName, + }); + } + else + return { status: 200, timetoken: result.timetoken, id: fileId, name: fileName }; + }); + } + } + + /** + * Common entity interface. + */ + class Entity { + /** + * Create an entity instance. + * + * @param nameOrId - Identifier which will be used with subscription loop. + * @param client - PubNub instance which has been used to create this entity. + * + * @internal + */ + constructor(nameOrId, client) { + /** + * List of subscription state object IDs which are using this entity. + * + * @internal + */ + this.subscriptionStateIds = []; + this.client = client; + this._nameOrId = nameOrId; + } + /** + * Retrieve entity type. + * + * @return One of known {@link EntityType entity types}. + * + * @internal + */ + get entityType() { + return 'Channel'; + } + /** + * Type of subscription entity. + * + * Type defines where it will be used with multiplexed subscribe REST API calls. + * + * @retuerns One of {@link SubscriptionType} enum fields. + * + * @internal + */ + get subscriptionType() { + return SubscriptionType.Channel; + } + /** + * Names for an object to be used in subscription. + * + * Provided strings will be used with multiplexed subscribe REST API calls. + * + * @param receivePresenceEvents - Whether presence events should be observed or not. + * + * @returns List of names with multiplexed subscribe REST API calls (may include additional names to receive presence + * updates). + * + * @internal + */ + subscriptionNames(receivePresenceEvents) { + { + return [ + this._nameOrId, + ...(receivePresenceEvents && !this._nameOrId.endsWith('-pnpres') ? [`${this._nameOrId}-pnpres`] : []), + ]; + } + } + /** + * Create a subscribable's subscription object for real-time updates. + * + * Create a subscription object which can be used to subscribe to the real-time updates sent to the specific data + * stream. + * + * @param [subscriptionOptions] - Subscription object behavior customization options. + * + * @returns Configured and ready to use subscribable's subscription object. + */ + subscription(subscriptionOptions) { + { + return new Subscription({ + client: this.client, + entity: this, + options: subscriptionOptions, + }); + } + } + /** + * How many active subscriptions use this entity. + * + * @internal + */ + get subscriptionsCount() { + return this.subscriptionStateIds.length; + } + /** + * Increase the number of active subscriptions. + * + * @param subscriptionStateId - Unique identifier of the subscription state object which doesn't use entity anymore. + * + * @internal + */ + increaseSubscriptionCount(subscriptionStateId) { + { + if (!this.subscriptionStateIds.includes(subscriptionStateId)) + this.subscriptionStateIds.push(subscriptionStateId); + } + } + /** + * Decrease the number of active subscriptions. + * + * **Note:** As long as the entity is used by at least one subscription, it can't be removed from the subscription. + * + * @param subscriptionStateId - Unique identifier of the subscription state object which doesn't use entity anymore. + * + * @internal + */ + decreaseSubscriptionCount(subscriptionStateId) { + { + const index = this.subscriptionStateIds.indexOf(subscriptionStateId); + if (index >= 0) + this.subscriptionStateIds.splice(index, 1); + } + } + /** + * Stringify entity object. + * + * @returns Serialized entity object. + */ + toString() { + return `${this.entityType} { nameOrId: ${this._nameOrId}, subscriptionsCount: ${this.subscriptionsCount} }`; + } + } + + /** + * Projection names which are observed on the object's base (un-prefixed) data channel. + * + * @internal + */ + const BASE_PROJECTIONS = ['default', '__default__']; + /** + * Key under which the base (un-prefixed) projection is stored in the variants registry. + * + * @internal + */ + const BASE_PROJECTION_KEY = ''; + /** + * Normalize a user-provided DataSync projection name. + * + * **Note:** Only the projection name is normalized. A DataSync object identifier is always used + * verbatim (so wildcard identifiers keep working by construction). + * + * @param [projection] - Projection name as provided by the user. + * + * @returns Trimmed projection name or `undefined` when the base projection is requested. + * + * @internal + */ + const normalizedProjection = (projection) => { + if (!projection) + return undefined; + const trimmed = projection.trim(); + if (trimmed.length === 0 || BASE_PROJECTIONS.includes(trimmed.toLowerCase())) + return undefined; + return trimmed; + }; + /** + * Base class for DataSync objects which can be observed with the subscribe REST API. + * + * A DataSync object is observed on a data channel named after its identifier, optionally prefixed + * with the name of an observed projection: `__{projection}__{id}`. + * + * **Note:** The identifier is used verbatim, so an identifier which already looks prefixed + * (`__admin__u1`) will be prefixed again when a projection is requested (`__admin____admin__u1`). + */ + class DataSyncSubscribable extends Entity { + /** + * Create a DataSync object entity. + * + * @param nameOrId - Unique DataSync object identifier (used verbatim). + * @param client - PubNub instance which has been used to create this entity. + * @param [projection] - Name of the projection which should be observed by this entity. + * + * @internal + */ + constructor(nameOrId, client, projection) { + super(nameOrId, client); + this._projection = normalizedProjection(projection); + } + /** + * Get unique DataSync object identifier. + * + * @returns DataSync object identifier. + */ + get id() { + return this._nameOrId; + } + /** + * Get the name of the projection which is observed by this entity. + * + * **Note:** A projection is chosen per subscription + * ({@link DataSyncSubscriptionOptions#projection}), so an entity created by the PubNub client + * always reports `undefined` here: it is the base-projection entity, and the entities bound to + * other projections are internal to it. + * + * @returns Observed projection name or `undefined` when the object is observed through its base + * projection. + */ + get projection() { + return this._projection; + } + /** + * Name of the data channel which is used with multiplexed subscribe REST API calls. + * + * @returns Name of the observed data channel. + * + * @internal + */ + get subscriptionChannel() { + return this._projection ? `__${this._projection}__${this._nameOrId}` : this._nameOrId; + } + /** + * Names for an object to be used in subscription. + * + * **Note:** A DataSync object is observed on a single data channel; presence events are not + * supported for it and `_receivePresenceEvents` is ignored. + * + * @param _receivePresenceEvents - Whether presence events should be observed or not. + * + * @returns List of names with multiplexed subscribe REST API calls. + * + * @internal + */ + subscriptionNames(_receivePresenceEvents) { + return [this.subscriptionChannel]; + } + /** + * Create a DataSync object's subscription object for real-time updates. + * + * @param [subscriptionOptions] - Subscription object behavior customization options. + * + * @returns Configured and ready to use DataSync object's subscription object. + * + * @example + * ```typescript + * // Observe the object itself. + * pubnub.dataSyncUser('u1').subscription().subscribe(); + * + * // Observe the `admin` projection of the object (the `__admin__u1` data channel). + * pubnub.dataSyncUser('u1').subscription({ projection: 'admin' }).subscribe(); + * ``` + */ + subscription(subscriptionOptions) { + { + const entity = this.entityForProjection(normalizedProjection(subscriptionOptions === null || subscriptionOptions === void 0 ? void 0 : subscriptionOptions.projection)); + // Each projection is observed on its own data channel, so it must be represented by its own + // entity instance (see `variants`). Let the entity which owns the requested projection create + // the subscription object for itself: it resolves that same projection to itself, so this + // delegation is always a single hop. + if (entity !== this) + return entity.subscription(subscriptionOptions); + return super.subscription(subscriptionOptions); + } + } + /** + * Resolve the entity which observes the same DataSync object through `projection`. + * + * @param [projection] - Normalized name of the projection to observe. + * + * @returns Receiver itself, or the memoized sibling entity bound to `projection`. + * + * @internal + */ + entityForProjection(projection) { + var _a, _b, _c; + var _d; + if (projection === this._projection) + return this; + // Register the receiver in the shared registry, so that it can be resolved back from siblings. + // + // Note: the receiver is added with an element assignment and never as part of an object literal + // which is assigned to `variants`. Declaration files for this module are inferred from the + // compiled JavaScript (`allowJs`), where a `this.variants = { ...: this }` statement would make + // the inferred member type reference the inaccessible polymorphic `this` type (TS2527). + const variants = ((_a = this.variants) !== null && _a !== void 0 ? _a : (this.variants = {})); + (_c = variants[_d = (_b = this._projection) !== null && _b !== void 0 ? _b : BASE_PROJECTION_KEY]) !== null && _c !== void 0 ? _c : (variants[_d] = this); + const key = projection !== null && projection !== void 0 ? projection : BASE_PROJECTION_KEY; + let entity = variants[key]; + if (!entity) { + entity = variants[key] = this.withProjection(projection); + entity.variants = variants; + } + return entity; + } + /** + * Stringify entity object. + * + * @returns Serialized entity object. + */ + toString() { + var _a; + return (`${this.entityType} { id: ${this._nameOrId}, projection: ${(_a = this._projection) !== null && _a !== void 0 ? _a : 'none'}, ` + + `channel: ${this.subscriptionChannel}, subscriptionsCount: ${this.subscriptionsCount} }`); + } + } + + /** + * First-class object which provides access to the real-time updates of a DataSync `Relationship` + * object. + * + * **Important:** The service delivers relationship changes on the data channels of **both linked + * entities** (`entityAId` and `entityBId`), and never on the relationship's own identifier. Observe + * `pubnub.dataSyncEntity(...)` for the linked entities to receive relationship updates; this entity + * is only useful if a key set is configured to publish relationship changes on the relationship + * identifier itself. + */ + class DataSyncRelationship extends DataSyncSubscribable { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'DataSyncRelationship'; + } + /** + * Create a copy of the receiver which observes `projection` of the same DataSync `Relationship` + * object. + * + * @param [projection] - Normalized name of the projection to observe. + * + * @returns `DataSyncRelationship` entity bound to `projection`. + * + * @internal + */ + withProjection(projection) { + return new DataSyncRelationship(this._nameOrId, this.client, projection); + } + } + + /** + * First-class object which provides access to the real-time updates of a DataSync `Membership` + * object. + * + * **Note:** A membership identifier is composite (`{userId}:{channelId}`) and is used verbatim as + * the name of the observed data channel. + * + * **Important:** The service delivers membership changes on the data channels of **both linked + * entities** (the user identifier and the channel identifier), and never on the membership's own + * identifier. Observe `pubnub.dataSyncUser(...)` and/or `pubnub.dataSyncChannel(...)` to receive + * membership updates; this entity is only useful if a key set is configured to publish membership + * changes on the membership identifier itself. + */ + class DataSyncMembership extends DataSyncSubscribable { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'DataSyncMembership'; + } + /** + * Create a copy of the receiver which observes `projection` of the same DataSync `Membership` + * object. + * + * @param [projection] - Normalized name of the projection to observe. + * + * @returns `DataSyncMembership` entity bound to `projection`. + * + * @internal + */ + withProjection(projection) { + return new DataSyncMembership(this._nameOrId, this.client, projection); + } + } + + /** + * First-class object which provides access to the real-time updates of a DataSync `Channel` object. + */ + class DataSyncChannel extends DataSyncSubscribable { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'DataSyncChannel'; + } + /** + * Create a copy of the receiver which observes `projection` of the same DataSync `Channel` object. + * + * @param [projection] - Normalized name of the projection to observe. + * + * @returns `DataSyncChannel` entity bound to `projection`. + * + * @internal + */ + withProjection(projection) { + return new DataSyncChannel(this._nameOrId, this.client, projection); + } + } + + /** + * First-class object which provides access to the real-time updates of a DataSync `Entity` object. + */ + class DataSyncEntity extends DataSyncSubscribable { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'DataSyncEntity'; + } + /** + * Create a copy of the receiver which observes `projection` of the same DataSync `Entity` object. + * + * @param [projection] - Normalized name of the projection to observe. + * + * @returns `DataSyncEntity` entity bound to `projection`. + * + * @internal + */ + withProjection(projection) { + return new DataSyncEntity(this._nameOrId, this.client, projection); + } + } + + /** + * First-class objects which provides access to the channel app context object-specific APIs. + */ + class ChannelMetadata extends Entity { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'ChannelMetadata'; + } + /** + * Get unique channel metadata object identifier. + * + * @returns Channel metadata identifier. + */ + get id() { + return this._nameOrId; + } + /** + * Names for an object to be used in subscription. + * + * Provided strings will be used with multiplexed subscribe REST API calls. + * + * @param _receivePresenceEvents - Whether presence events should be observed or not. + * + * @returns List of names with multiplexed subscribe REST API calls (may include additional names to receive presence + * updates). + * + * @internal + */ + subscriptionNames(_receivePresenceEvents) { + return [this.id]; + } + } + + /** + * First-class object which provides access to the real-time updates of a DataSync `User` object. + */ + class DataSyncUser extends DataSyncSubscribable { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'DataSyncUser'; + } + /** + * Create a copy of the receiver which observes `projection` of the same DataSync `User` object. + * + * @param [projection] - Normalized name of the projection to observe. + * + * @returns `DataSyncUser` entity bound to `projection`. + * + * @internal + */ + withProjection(projection) { + return new DataSyncUser(this._nameOrId, this.client, projection); + } + } + + /** + * First-class objects which provides access to the channel group-specific APIs. + */ + class ChannelGroup extends Entity { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'ChannelGroups'; + } + /** + * Get a unique channel group name. + * + * @returns Channel group name. + */ + get name() { + return this._nameOrId; + } + /** + * Type of subscription entity. + * + * Type defines where it will be used with multiplexed subscribe REST API calls. + * + * @retuerns One of {@link SubscriptionType} enum fields. + * + * @internal + */ + get subscriptionType() { + return SubscriptionType.ChannelGroup; + } + } + + /** + * First-class objects which provides access to the user app context object-specific APIs. + */ + class UserMetadata extends Entity { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'UserMetadata'; + } + /** + * Get unique user metadata object identifier. + * + * @returns User metadata identifier. + */ + get id() { + return this._nameOrId; + } + /** + * Names for an object to be used in subscription. + * + * Provided strings will be used with multiplexed subscribe REST API calls. + * + * @param _receivePresenceEvents - Whether presence events should be observed or not. + * + * @returns List of names with multiplexed subscribe REST API calls (may include additional names to receive presence + * updates). + * + * @internal + */ + subscriptionNames(_receivePresenceEvents) { + return [this.id]; + } + } + + /** + * First-class objects which provides access to the channel-specific APIs. + */ + class Channel extends Entity { + /** + * Retrieve entity type. + * + * @return One of known entity types. + * + * @internal + */ + get entityType() { + return 'Channel'; + } + /** + * Get a unique channel name. + * + * @returns Channel name. + */ + get name() { + return this._nameOrId; + } + } + + /** + * Remove channel group channels REST API module. + * + * @internal + */ + // endregion + /** + * Remove channel group channels request. + * + * @internal + */ + // prettier-ignore + class RemoveChannelGroupChannelsRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveChannelsFromGroupOperation; + } + validate() { + const { keySet: { subscribeKey }, channels, channelGroup, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channelGroup) + return 'Missing Channel Group'; + if (!channels) + return 'Missing channels'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + get path() { + const { keySet: { subscribeKey }, channelGroup, } = this.parameters; + return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}`; + } + get queryParameters() { + return { remove: this.parameters.channels.join(',') }; + } + } + + /** + * Add channel group channels REST API module. + * + * @internal + */ + // endregion + /** + * Add channel group channels request. + * + * @internal + */ + class AddChannelGroupChannelsRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNAddChannelsToGroupOperation; + } + validate() { + const { keySet: { subscribeKey }, channels, channelGroup, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!channelGroup) + return 'Missing Channel Group'; + if (!channels) + return 'Missing channels'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + get path() { + const { keySet: { subscribeKey }, channelGroup, } = this.parameters; + return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}`; + } + get queryParameters() { + return { add: this.parameters.channels.join(',') }; + } + } + + /** + * List channel group channels REST API module. + * + * @internal + */ + // endregion + /** + * List Channel Group Channels request. + * + * @internal + */ + class ListChannelGroupChannels extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNChannelsForGroupOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + if (!this.parameters.channelGroup) + return 'Missing Channel Group'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { channels: this.deserializeResponse(response).payload.channels }; + }); + } + get path() { + const { keySet: { subscribeKey }, channelGroup, } = this.parameters; + return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}`; + } + } + + /** + * Delete channel group REST API module. + * + * @internal + */ + // endregion + /** + * Channel group delete request. + * + * @internal + */ + class DeleteChannelGroupRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveGroupOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + if (!this.parameters.channelGroup) + return 'Missing Channel Group'; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + get path() { + const { keySet: { subscribeKey }, channelGroup, } = this.parameters; + return `/v1/channel-registration/sub-key/${subscribeKey}/channel-group/${encodeString(channelGroup)}/remove`; + } + } + + /** + * List All Channel Groups REST API module. + * + * @internal + */ + // endregion + /** + * List all channel groups request. + * + * @internal + */ + class ListChannelGroupsRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNChannelGroupsOperation; + } + validate() { + if (!this.parameters.keySet.subscribeKey) + return 'Missing Subscribe Key'; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { groups: this.deserializeResponse(response).payload.groups }; + }); + } + get path() { + return `/v1/channel-registration/sub-key/${this.parameters.keySet.subscribeKey}/channel-group`; + } + } + + /** + * PubNub Channel Groups API module. + */ + /** + * PubNub Stream / Channel group API interface. + */ + class PubNubChannelGroups { + /** + * Create stream / channel group API access object. + * + * @param logger - Registered loggers' manager. + * @param keySet - PubNub account keys set which should be used for REST API calls. + * @param sendRequest - Function which should be used to send REST API calls. + * + * @internal + */ + constructor(logger, keySet, + /* eslint-disable @typescript-eslint/no-explicit-any */ + sendRequest) { + this.sendRequest = sendRequest; + this.logger = logger; + this.keySet = keySet; + } + /** + * Fetch channel group channels. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get channel group channels response or `void` in case if `callback` + * provided. + */ + listChannels(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'List channel group channels with parameters:', + })); + const request = new ListChannelGroupChannels(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `List channel group channels success. Received ${response.channels.length} channels.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Fetch all channel groups. + * + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all channel groups response or `void` in case if `callback` provided. + * + * @deprecated + */ + listGroups(callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', 'List all channel groups.'); + const request = new ListChannelGroupsRequest({ keySet: this.keySet }); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `List all channel groups success. Received ${response.groups.length} groups.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Add channels to the channel group. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous add channels to the channel group response or `void` in case if + * `callback` provided. + */ + addChannels(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Add channels to the channel group with parameters:', + })); + const request = new AddChannelGroupChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = () => { + this.logger.debug('PubNub', `Add channels to the channel group success.`); + }; + if (callback) + return this.sendRequest(request, (status) => { + if (!status.error) + logResponse(); + callback(status); + }); + return this.sendRequest(request).then((response) => { + logResponse(); + return response; + }); + }); + } + /** + * Remove channels from the channel group. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove channels from the channel group response or `void` in + * case if `callback` provided. + */ + removeChannels(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove channels from the channel group with parameters:', + })); + const request = new RemoveChannelGroupChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = () => { + this.logger.debug('PubNub', `Remove channels from the channel group success.`); + }; + if (callback) + return this.sendRequest(request, (status) => { + if (!status.error) + logResponse(); + callback(status); + }); + return this.sendRequest(request).then((response) => { + logResponse(); + return response; + }); + }); + } + /** + * Remove a channel group. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove channel group response or `void` in case if `callback` provided. + */ + deleteGroup(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove a channel group with parameters:', + })); + const request = new DeleteChannelGroupRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = () => { + this.logger.debug('PubNub', `Remove a channel group success. Removed '${parameters.channelGroup}' channel group.'`); + }; + if (callback) + return this.sendRequest(request, (status) => { + if (!status.error) + logResponse(); + callback(status); + }); + return this.sendRequest(request).then((response) => { + logResponse(); + return response; + }); + }); + } + } + + /** + * Manage channels enabled for device push REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Environment for which APNS2 notifications + */ + const ENVIRONMENT = 'development'; + /** + * Maximum number of channels in `list` response. + */ + const MAX_COUNT = 1000; + // endregion + /** + * Base push notification request. + * + * @internal + */ + class BasePushNotificationChannelsRequest extends AbstractRequest { + constructor(parameters) { + var _a; + var _b; + super(); + this.parameters = parameters; + // Apply request defaults + if (this.parameters.pushGateway === 'apns2') + (_a = (_b = this.parameters).environment) !== null && _a !== void 0 ? _a : (_b.environment = ENVIRONMENT); + if (this.parameters.count && this.parameters.count > MAX_COUNT) + this.parameters.count = MAX_COUNT; + } + operation() { + throw Error('Should be implemented in subclass.'); + } + validate() { + const { keySet: { subscribeKey }, action, device, pushGateway, } = this.parameters; + if (!subscribeKey) + return 'Missing Subscribe Key'; + if (!device) + return 'Missing Device ID (device)'; + if ((action === 'add' || action === 'remove') && + (!('channels' in this.parameters) || this.parameters.channels.length === 0)) + return 'Missing Channels'; + if (!pushGateway) + return 'Missing GW Type (pushGateway: fcm or apns2)'; + if (this.parameters.pushGateway === 'apns2' && !this.parameters.topic) + return 'Missing APNS2 topic'; + } + get path() { + const { keySet: { subscribeKey }, action, device, pushGateway, } = this.parameters; + let path = pushGateway === 'apns2' + ? `/v2/push/sub-key/${subscribeKey}/devices-apns2/${device}` + : `/v1/push/sub-key/${subscribeKey}/devices/${device}`; + if (action === 'remove-device') + path = `${path}/remove`; + return path; + } + get queryParameters() { + const { start, count } = this.parameters; + let query = Object.assign(Object.assign({ type: this.parameters.pushGateway }, (start ? { start } : {})), (count && count > 0 ? { count } : {})); + if ('channels' in this.parameters) + query[this.parameters.action] = this.parameters.channels.join(','); + if (this.parameters.pushGateway === 'apns2') { + const { environment, topic } = this.parameters; + query = Object.assign(Object.assign({}, query), { environment: environment, topic }); + } + return query; + } + } + + /** + * Unregister Channels from Device push REST API module. + * + * @internal + */ + // endregion + /** + * Unregister channels from device push request. + * + * @internal + */ + // prettier-ignore + class RemoveDevicePushNotificationChannelsRequest extends BasePushNotificationChannelsRequest { + constructor(parameters) { + super(Object.assign(Object.assign({}, parameters), { action: 'remove' })); + } + operation() { + return RequestOperation$1.PNRemovePushNotificationEnabledChannelsOperation; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + } + + /** + * List Device push enabled channels REST API module. + * + * @internal + */ + // endregion + /** + * List device push enabled channels request. + * + * @internal + */ + // prettier-ignore + class ListDevicePushNotificationChannelsRequest extends BasePushNotificationChannelsRequest { + constructor(parameters) { + super(Object.assign(Object.assign({}, parameters), { action: 'list' })); + } + operation() { + return RequestOperation$1.PNPushNotificationEnabledChannelsOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { channels: this.deserializeResponse(response) }; + }); + } + } + + /** + * Register Channels with Device push REST API module. + * + * @internal + */ + // endregion + /** + * Register channels with device push request. + * + * @internal + */ + // prettier-ignore + class AddDevicePushNotificationChannelsRequest extends BasePushNotificationChannelsRequest { + constructor(parameters) { + super(Object.assign(Object.assign({}, parameters), { action: 'add' })); + } + operation() { + return RequestOperation$1.PNAddPushNotificationEnabledChannelsOperation; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + } + + /** + * Unregister Device push REST API module. + * + * @internal + */ + // endregion + /** + * Unregister device push notifications request. + * + * @internal + */ + // prettier-ignore + class RemoveDevicePushNotificationRequest extends BasePushNotificationChannelsRequest { + constructor(parameters) { + super(Object.assign(Object.assign({}, parameters), { action: 'remove-device' })); + } + operation() { + return RequestOperation$1.PNRemoveAllPushNotificationsOperation; + } + parse(response) { + const _super = Object.create(null, { + parse: { get: () => super.parse } + }); + return __awaiter(this, void 0, void 0, function* () { + return _super.parse.call(this, response).then((_) => ({})); + }); + } + } + + /** + * PubNub Push Notifications API module. + */ + /** + * PubNub Push Notifications API interface. + */ + class PubNubPushNotifications { + /** + * Create mobile push notifications API access object. + * + * @param logger - Registered loggers' manager. + * @param keySet - PubNub account keys set which should be used for REST API calls. + * @param sendRequest - Function which should be used to send REST API calls. + * + * @internal + */ + constructor(logger, keySet, + /* eslint-disable @typescript-eslint/no-explicit-any */ + sendRequest) { + this.sendRequest = sendRequest; + this.logger = logger; + this.keySet = keySet; + } + /** + * Fetch device's push notification enabled channels. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get device channels response or `void` in case if `callback` provided. + */ + listChannels(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `List push-enabled channels with parameters:`, + })); + const request = new ListDevicePushNotificationChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `List push-enabled channels success. Received ${response.channels.length} channels.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Enable push notifications on channels for device. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + */ + addChannels(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Add push-enabled channels with parameters:`, + })); + const request = new AddDevicePushNotificationChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = () => { + this.logger.debug('PubNub', `Add push-enabled channels success.`); + }; + if (callback) + return this.sendRequest(request, (status) => { + if (!status.error) + logResponse(); + callback(status); + }); + return this.sendRequest(request).then((response) => { + logResponse(); + return response; + }); + }); + } + /** + * Disable push notifications on channels for device. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + */ + removeChannels(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove push-enabled channels with parameters:`, + })); + const request = new RemoveDevicePushNotificationChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = () => { + this.logger.debug('PubNub', `Remove push-enabled channels success.`); + }; + if (callback) + return this.sendRequest(request, (status) => { + if (!status.error) + logResponse(); + callback(status); + }); + return this.sendRequest(request).then((response) => { + logResponse(); + return response; + }); + }); + } + /** + * Disable push notifications for device. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + */ + deleteDevice(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove push notifications for device with parameters:`, + })); + const request = new RemoveDevicePushNotificationRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = () => { + this.logger.debug('PubNub', `Remove push notifications for device success.`); + }; + if (callback) + return this.sendRequest(request, (status) => { + if (!status.error) + logResponse(); + callback(status); + }); + return this.sendRequest(request).then((response) => { + logResponse(); + return response; + }); + }); + } + } + + /** + * Get All Channel Metadata REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Channel` custom fields should be included in response or not. + */ + const INCLUDE_CUSTOM_FIELDS$9 = false; + /** + * Whether total number of channels should be included in response or not. + */ + const INCLUDE_TOTAL_COUNT$4 = false; + /** + * Number of objects to return in response. + */ + const LIMIT$5 = 100; + // endregion + /** + * Get All Channels Metadata request. + * + * @internal + */ + class GetAllChannelsMetadataRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d; + var _e, _f; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_e = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_e.customFields = INCLUDE_CUSTOM_FIELDS$9); + (_c = (_f = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_f.totalCount = INCLUDE_TOTAL_COUNT$4); + (_d = parameters.limit) !== null && _d !== void 0 ? _d : (parameters.limit = LIMIT$5); + } + operation() { + return RequestOperation$1.PNGetAllChannelMetadataOperation; + } + get path() { + return `/v2/objects/${this.parameters.keySet.subscribeKey}/channels`; + } + get queryParameters() { + const { include, page, filter, sort, limit } = this.parameters; + let sorting = ''; + if (typeof sort === 'string') + sorting = sort; + else + sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ include: ['status', 'type', ...(include.customFields ? ['custom'] : [])].join(','), count: `${include.totalCount}` }, (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Remove Channel Metadata REST API module. + * + * @internal + */ + // endregion + /** + * Remove Channel Metadata request. + * + * @internal + */ + class RemoveChannelMetadataRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveChannelMetadataOperation; + } + validate() { + if (!this.parameters.channel) + return 'Channel cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}`; + } + } + + /** + * Get UUID Memberships REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Membership` custom field should be included in response or not. + */ + const INCLUDE_CUSTOM_FIELDS$8 = false; + /** + * Whether membership's `status` field should be included in response or not. + */ + const INCLUDE_STATUS$3 = false; + /** + * Whether membership's `type` field should be included in response or not. + */ + const INCLUDE_TYPE$3 = false; + /** + * Whether total number of memberships should be included in response or not. + */ + const INCLUDE_TOTAL_COUNT$3 = false; + /** + * Whether `Channel` fields should be included in response or not. + */ + const INCLUDE_CHANNEL_FIELDS$1 = false; + /** + * Whether `Channel` status field should be included in response or not. + */ + const INCLUDE_CHANNEL_STATUS_FIELD$1 = false; + /** + * Whether `Channel` type field should be included in response or not. + */ + const INCLUDE_CHANNEL_TYPE_FIELD$1 = false; + /** + * Whether `Channel` custom field should be included in response or not. + */ + const INCLUDE_CHANNEL_CUSTOM_FIELDS$1 = false; + /** + * Number of objects to return in response. + */ + const LIMIT$4 = 100; + // endregion + /** + * Get UUID Memberships request. + * + * @internal + */ + class GetUUIDMembershipsRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + var _l, _m, _o, _p, _q, _r, _s, _t; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$8); + (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT$3); + (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS$3); + (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE$3); + (_f = (_q = parameters.include).channelFields) !== null && _f !== void 0 ? _f : (_q.channelFields = INCLUDE_CHANNEL_FIELDS$1); + (_g = (_r = parameters.include).customChannelFields) !== null && _g !== void 0 ? _g : (_r.customChannelFields = INCLUDE_CHANNEL_CUSTOM_FIELDS$1); + (_h = (_s = parameters.include).channelStatusField) !== null && _h !== void 0 ? _h : (_s.channelStatusField = INCLUDE_CHANNEL_STATUS_FIELD$1); + (_j = (_t = parameters.include).channelTypeField) !== null && _j !== void 0 ? _j : (_t.channelTypeField = INCLUDE_CHANNEL_TYPE_FIELD$1); + (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT$4); + // Remap for backward compatibility. + if (this.parameters.userId) + this.parameters.uuid = this.parameters.userId; + } + operation() { + return RequestOperation$1.PNGetMembershipsOperation; + } + validate() { + if (!this.parameters.uuid) + return "'uuid' cannot be empty"; + } + get path() { + const { keySet: { subscribeKey }, uuid, } = this.parameters; + return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}/channels`; + } + get queryParameters() { + const { include, page, filter, sort, limit } = this.parameters; + let sorting = ''; + if (typeof sort === 'string') + sorting = sort; + else + sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + const includeFlags = []; + if (include.statusField) + includeFlags.push('status'); + if (include.typeField) + includeFlags.push('type'); + if (include.customFields) + includeFlags.push('custom'); + if (include.channelFields) + includeFlags.push('channel'); + if (include.channelStatusField) + includeFlags.push('channel.status'); + if (include.channelTypeField) + includeFlags.push('channel.type'); + if (include.customChannelFields) + includeFlags.push('channel.custom'); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set UUID Memberships REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Membership` custom field should be included in response or not. + */ + const INCLUDE_CUSTOM_FIELDS$7 = false; + /** + * Whether membership's `status` field should be included in response or not. + */ + const INCLUDE_STATUS$2 = false; + /** + * Whether membership's `type` field should be included in response or not. + */ + const INCLUDE_TYPE$2 = false; + /** + * Whether total number of memberships should be included in response or not. + */ + const INCLUDE_TOTAL_COUNT$2 = false; + /** + * Whether `Channel` fields should be included in response or not. + */ + const INCLUDE_CHANNEL_FIELDS = false; + /** + * Whether `Channel` status field should be included in response or not. + */ + const INCLUDE_CHANNEL_STATUS_FIELD = false; + /** + * Whether `Channel` type field should be included in response or not. + */ + const INCLUDE_CHANNEL_TYPE_FIELD = false; + /** + * Whether `Channel` custom field should be included in response or not. + */ + const INCLUDE_CHANNEL_CUSTOM_FIELDS = false; + /** + * Number of objects to return in response. + */ + const LIMIT$3 = 100; + // endregion + /** + * Set UUID Memberships request. + * + * @internal + */ + class SetUUIDMembershipsRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + var _l, _m, _o, _p, _q, _r, _s, _t; + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$7); + (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT$2); + (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS$2); + (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE$2); + (_f = (_q = parameters.include).channelFields) !== null && _f !== void 0 ? _f : (_q.channelFields = INCLUDE_CHANNEL_FIELDS); + (_g = (_r = parameters.include).customChannelFields) !== null && _g !== void 0 ? _g : (_r.customChannelFields = INCLUDE_CHANNEL_CUSTOM_FIELDS); + (_h = (_s = parameters.include).channelStatusField) !== null && _h !== void 0 ? _h : (_s.channelStatusField = INCLUDE_CHANNEL_STATUS_FIELD); + (_j = (_t = parameters.include).channelTypeField) !== null && _j !== void 0 ? _j : (_t.channelTypeField = INCLUDE_CHANNEL_TYPE_FIELD); + (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT$3); + // Remap for backward compatibility. + if (this.parameters.userId) + this.parameters.uuid = this.parameters.userId; + } + operation() { + return RequestOperation$1.PNSetMembershipsOperation; + } + validate() { + const { uuid, channels } = this.parameters; + if (!uuid) + return "'uuid' cannot be empty"; + if (!channels || channels.length === 0) + return 'Channels cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, uuid, } = this.parameters; + return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}/channels`; + } + get queryParameters() { + const { include, page, filter, sort, limit } = this.parameters; + let sorting = ''; + if (typeof sort === 'string') + sorting = sort; + else + sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + const includeFlags = ['channel.status', 'channel.type', 'status']; + if (include.statusField) + includeFlags.push('status'); + if (include.typeField) + includeFlags.push('type'); + if (include.customFields) + includeFlags.push('custom'); + if (include.channelFields) + includeFlags.push('channel'); + if (include.channelStatusField) + includeFlags.push('channel.status'); + if (include.channelTypeField) + includeFlags.push('channel.type'); + if (include.customChannelFields) + includeFlags.push('channel.custom'); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); + } + get headers() { + var _a; + return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); + } + get body() { + const { channels, type } = this.parameters; + return JSON.stringify({ + [`${type}`]: channels.map((channel) => { + if (typeof channel === 'string') { + return { channel: { id: channel } }; + } + else { + return { channel: { id: channel.id }, status: channel.status, type: channel.type, custom: channel.custom }; + } + }), + }); + } + } + + /** + * Get All UUID Metadata REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Channel` custom field should be included by default or not. + */ + const INCLUDE_CUSTOM_FIELDS$6 = false; + /** + * Number of objects to return in response. + */ + const LIMIT$2 = 100; + // endregion + /** + * Get All UUIDs Metadata request. + * + * @internal + */ + class GetAllUUIDMetadataRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c; + var _d; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_d = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_d.customFields = INCLUDE_CUSTOM_FIELDS$6); + (_c = parameters.limit) !== null && _c !== void 0 ? _c : (parameters.limit = LIMIT$2); + } + operation() { + return RequestOperation$1.PNGetAllUUIDMetadataOperation; + } + get path() { + return `/v2/objects/${this.parameters.keySet.subscribeKey}/uuids`; + } + get queryParameters() { + const { include, page, filter, sort, limit } = this.parameters; + let sorting = ''; + if (typeof sort === 'string') + sorting = sort; + else + sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ include: ['status', 'type', ...(include.customFields ? ['custom'] : [])].join(',') }, (include.totalCount !== undefined ? { count: `${include.totalCount}` } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Get Channel Metadata REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Channel` custom field should be included by default or not. + */ + const INCLUDE_CUSTOM_FIELDS$5 = true; + // endregion + /** + * Get Channel Metadata request. + * + * @internal + */ + class GetChannelMetadataRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b; + var _c; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS$5); + } + operation() { + return RequestOperation$1.PNGetChannelMetadataOperation; + } + validate() { + if (!this.parameters.channel) + return 'Channel cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}`; + } + get queryParameters() { + return { + include: ['status', 'type', ...(this.parameters.include.customFields ? ['custom'] : [])].join(','), + }; + } + } + + /** + * Set Channel Metadata REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Channel` custom field should be included by default or not. + */ + const INCLUDE_CUSTOM_FIELDS$4 = true; + // endregion + /** + * Set Channel Metadata request. + * + * @internal + */ + class SetChannelMetadataRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b; + var _c; + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS$4); + } + operation() { + return RequestOperation$1.PNSetChannelMetadataOperation; + } + validate() { + if (!this.parameters.channel) + return 'Channel cannot be empty'; + if (!this.parameters.data) + return 'Data cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json' }); + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}`; + } + get queryParameters() { + return { + include: ['status', 'type', ...(this.parameters.include.customFields ? ['custom'] : [])].join(','), + }; + } + get body() { + return JSON.stringify(this.parameters.data); + } + } + + /** + * Remove UUID Metadata REST API module. + * + * @internal + */ + // endregion + /** + * Remove UUID Metadata request. + * + * @internal + */ + class RemoveUUIDMetadataRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + // Remap for backward compatibility. + if (this.parameters.userId) + this.parameters.uuid = this.parameters.userId; + } + operation() { + return RequestOperation$1.PNRemoveUUIDMetadataOperation; + } + validate() { + if (!this.parameters.uuid) + return "'uuid' cannot be empty"; + } + get path() { + const { keySet: { subscribeKey }, uuid, } = this.parameters; + return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}`; + } + } + + /** + * Get Channel Members REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Member` custom field should be included in response or not. + */ + const INCLUDE_CUSTOM_FIELDS$3 = false; + /** + * Whether member's `status` field should be included in response or not. + */ + const INCLUDE_STATUS$1 = false; + /** + * Whether member's `type` field should be included in response or not. + */ + const INCLUDE_TYPE$1 = false; + /** + * Whether total number of members should be included in response or not. + */ + const INCLUDE_TOTAL_COUNT$1 = false; + /** + * Whether `UUID` fields should be included in response or not. + */ + const INCLUDE_UUID_FIELDS$1 = false; + /** + * Whether `UUID` status field should be included in response or not. + */ + const INCLUDE_UUID_STATUS_FIELD$1 = false; + /** + * Whether `UUID` type field should be included in response or not. + */ + const INCLUDE_UUID_TYPE_FIELD$1 = false; + /** + * Whether `UUID` custom field should be included in response or not. + */ + const INCLUDE_UUID_CUSTOM_FIELDS$1 = false; + /** + * Number of objects to return in response. + */ + const LIMIT$1 = 100; + // endregion + /** + * Get Channel Members request. + * + * @internal + */ + class GetChannelMembersRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + var _l, _m, _o, _p, _q, _r, _s, _t; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$3); + (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT$1); + (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS$1); + (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE$1); + (_f = (_q = parameters.include).UUIDFields) !== null && _f !== void 0 ? _f : (_q.UUIDFields = INCLUDE_UUID_FIELDS$1); + (_g = (_r = parameters.include).customUUIDFields) !== null && _g !== void 0 ? _g : (_r.customUUIDFields = INCLUDE_UUID_CUSTOM_FIELDS$1); + (_h = (_s = parameters.include).UUIDStatusField) !== null && _h !== void 0 ? _h : (_s.UUIDStatusField = INCLUDE_UUID_STATUS_FIELD$1); + (_j = (_t = parameters.include).UUIDTypeField) !== null && _j !== void 0 ? _j : (_t.UUIDTypeField = INCLUDE_UUID_TYPE_FIELD$1); + (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT$1); + } + operation() { + return RequestOperation$1.PNSetMembersOperation; + } + validate() { + if (!this.parameters.channel) + return 'Channel cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}/uuids`; + } + get queryParameters() { + const { include, page, filter, sort, limit } = this.parameters; + let sorting = ''; + if (typeof sort === 'string') + sorting = sort; + else + sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + const includeFlags = []; + if (include.statusField) + includeFlags.push('status'); + if (include.typeField) + includeFlags.push('type'); + if (include.customFields) + includeFlags.push('custom'); + if (include.UUIDFields) + includeFlags.push('uuid'); + if (include.UUIDStatusField) + includeFlags.push('uuid.status'); + if (include.UUIDTypeField) + includeFlags.push('uuid.type'); + if (include.customUUIDFields) + includeFlags.push('uuid.custom'); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set Channel Members REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Member` custom field should be included in response or not. + */ + const INCLUDE_CUSTOM_FIELDS$2 = false; + /** + * Whether member's `status` field should be included in response or not. + */ + const INCLUDE_STATUS = false; + /** + * Whether member's `type` field should be included in response or not. + */ + const INCLUDE_TYPE = false; + /** + * Whether total number of members should be included in response or not. + */ + const INCLUDE_TOTAL_COUNT = false; + /** + * Whether `UUID` fields should be included in response or not. + */ + const INCLUDE_UUID_FIELDS = false; + /** + * Whether `UUID` status field should be included in response or not. + */ + const INCLUDE_UUID_STATUS_FIELD = false; + /** + * Whether `UUID` type field should be included in response or not. + */ + const INCLUDE_UUID_TYPE_FIELD = false; + /** + * Whether `UUID` custom field should be included in response or not. + */ + const INCLUDE_UUID_CUSTOM_FIELDS = false; + /** + * Number of objects to return in response. + */ + const LIMIT = 100; + // endregion + /** + * Set Channel Members request. + * + * @internal + */ + class SetChannelMembersRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + var _l, _m, _o, _p, _q, _r, _s, _t; + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_l = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_l.customFields = INCLUDE_CUSTOM_FIELDS$2); + (_c = (_m = parameters.include).totalCount) !== null && _c !== void 0 ? _c : (_m.totalCount = INCLUDE_TOTAL_COUNT); + (_d = (_o = parameters.include).statusField) !== null && _d !== void 0 ? _d : (_o.statusField = INCLUDE_STATUS); + (_e = (_p = parameters.include).typeField) !== null && _e !== void 0 ? _e : (_p.typeField = INCLUDE_TYPE); + (_f = (_q = parameters.include).UUIDFields) !== null && _f !== void 0 ? _f : (_q.UUIDFields = INCLUDE_UUID_FIELDS); + (_g = (_r = parameters.include).customUUIDFields) !== null && _g !== void 0 ? _g : (_r.customUUIDFields = INCLUDE_UUID_CUSTOM_FIELDS); + (_h = (_s = parameters.include).UUIDStatusField) !== null && _h !== void 0 ? _h : (_s.UUIDStatusField = INCLUDE_UUID_STATUS_FIELD); + (_j = (_t = parameters.include).UUIDTypeField) !== null && _j !== void 0 ? _j : (_t.UUIDTypeField = INCLUDE_UUID_TYPE_FIELD); + (_k = parameters.limit) !== null && _k !== void 0 ? _k : (parameters.limit = LIMIT); + } + operation() { + return RequestOperation$1.PNSetMembersOperation; + } + validate() { + const { channel, uuids } = this.parameters; + if (!channel) + return 'Channel cannot be empty'; + if (!uuids || uuids.length === 0) + return 'UUIDs cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, channel, } = this.parameters; + return `/v2/objects/${subscribeKey}/channels/${encodeString(channel)}/uuids`; + } + get queryParameters() { + const { include, page, filter, sort, limit } = this.parameters; + let sorting = ''; + if (typeof sort === 'string') + sorting = sort; + else + sorting = Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + const includeFlags = ['uuid.status', 'uuid.type', 'type']; + if (include.statusField) + includeFlags.push('status'); + if (include.typeField) + includeFlags.push('type'); + if (include.customFields) + includeFlags.push('custom'); + if (include.UUIDFields) + includeFlags.push('uuid'); + if (include.UUIDStatusField) + includeFlags.push('uuid.status'); + if (include.UUIDTypeField) + includeFlags.push('uuid.type'); + if (include.customUUIDFields) + includeFlags.push('uuid.custom'); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ count: `${include.totalCount}` }, (includeFlags.length > 0 ? { include: includeFlags.join(',') } : {})), (filter ? { filter } : {})), ((page === null || page === void 0 ? void 0 : page.next) ? { start: page.next } : {})), ((page === null || page === void 0 ? void 0 : page.prev) ? { end: page.prev } : {})), (limit ? { limit } : {})), (sorting.length ? { sort: sorting } : {})); + } + get headers() { + var _a; + return Object.assign(Object.assign({}, ((_a = super.headers) !== null && _a !== void 0 ? _a : {})), { 'Content-Type': 'application/json' }); + } + get body() { + const { uuids, type } = this.parameters; + return JSON.stringify({ + [`${type}`]: uuids.map((uuid) => { + if (typeof uuid === 'string') { + return { uuid: { id: uuid } }; + } + else { + return { uuid: { id: uuid.id }, status: uuid.status, type: uuid.type, custom: uuid.custom }; + } + }), + }); + } + } + + /** + * Get UUID Metadata REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether UUID custom field should be included by default or not. + */ + const INCLUDE_CUSTOM_FIELDS$1 = true; + // endregion + /** + * Get UUID Metadata request. + * + * @internal + */ + class GetUUIDMetadataRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b; + var _c; + super(); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS$1); + // Remap for backward compatibility. + if (this.parameters.userId) + this.parameters.uuid = this.parameters.userId; + } + operation() { + return RequestOperation$1.PNGetUUIDMetadataOperation; + } + validate() { + if (!this.parameters.uuid) + return "'uuid' cannot be empty"; + } + get path() { + const { keySet: { subscribeKey }, uuid, } = this.parameters; + return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}`; + } + get queryParameters() { + const { include } = this.parameters; + return { include: ['status', 'type', ...(include.customFields ? ['custom'] : [])].join(',') }; + } + } + + /** + * Set UUID Metadata REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Whether `Channel` custom field should be included by default or not. + */ + const INCLUDE_CUSTOM_FIELDS = true; + // endregion + /** + * Set UUID Metadata request. + * + * @internal + */ + class SetUUIDMetadataRequest extends AbstractRequest { + constructor(parameters) { + var _a, _b; + var _c; + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + // Apply default request parameters. + (_a = parameters.include) !== null && _a !== void 0 ? _a : (parameters.include = {}); + (_b = (_c = parameters.include).customFields) !== null && _b !== void 0 ? _b : (_c.customFields = INCLUDE_CUSTOM_FIELDS); + // Remap for backward compatibility. + if (this.parameters.userId) + this.parameters.uuid = this.parameters.userId; + } + operation() { + return RequestOperation$1.PNSetUUIDMetadataOperation; + } + validate() { + if (!this.parameters.uuid) + return "'uuid' cannot be empty"; + if (!this.parameters.data) + return 'Data cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json' }); + } + get path() { + const { keySet: { subscribeKey }, uuid, } = this.parameters; + return `/v2/objects/${subscribeKey}/uuids/${encodeString(uuid)}`; + } + get queryParameters() { + return { + include: ['status', 'type', ...(this.parameters.include.customFields ? ['custom'] : [])].join(','), + }; + } + get body() { + return JSON.stringify(this.parameters.data); + } + } + + /** + * PubNub Objects API module. + */ + /** + * PubNub App Context API interface. + */ + class PubNubObjects { + /** + * Create app context API access object. + * + * @param configuration - Extended PubNub client configuration object. + * @param sendRequest - Function which should be used to send REST API calls. + * + * @internal + */ + constructor(configuration, + /* eslint-disable @typescript-eslint/no-explicit-any */ + sendRequest) { + this.keySet = configuration.keySet; + this.configuration = configuration; + this.sendRequest = sendRequest; + } + /** + * Get registered loggers' manager. + * + * @returns Registered loggers' manager. + * + * @internal + */ + get logger() { + return this.configuration.logger(); + } + /** + * Fetch a paginated list of UUID Metadata objects. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all UUID metadata response or `void` in case if `callback` provided. + */ + getAllUUIDMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, + details: `Get all UUID metadata objects with parameters:`, + })); + return this._getAllUUIDMetadata(parametersOrCallback, callback); + }); + } + /** + * Fetch a paginated list of UUID Metadata objects. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all UUID metadata response or `void` in case if `callback` provided. + * + * @internal + */ + _getAllUUIDMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + // Get user request parameters. + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + const request = new GetAllUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get all UUID metadata success. Received ${response.totalCount} UUID metadata objects.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Fetch a specific UUID Metadata object. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get UUID metadata response or `void` in case if `callback` provided. + */ + getUUIDMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' + ? { uuid: this.configuration.userId } + : parametersOrCallback, + details: `Get ${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} UUID metadata object with parameters:`, + })); + return this._getUUIDMetadata(parametersOrCallback, callback); + }); + } + /** + * Fetch a specific UUID Metadata object. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get UUID metadata response or `void` in case if `callback` provided. + * + * @internal + */ + _getUUIDMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + // Get user request parameters. + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + if (parameters.userId) { + this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); + parameters.uuid = parameters.userId; + } + (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); + const request = new GetUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get UUID metadata object success. Received '${parameters.uuid}' UUID metadata object.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Update a specific UUID Metadata object. + * + * @param parameters - Request configuration parameters. Will set UUID metadata for currently + * configured PubNub client `uuid` if not set. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set UUID metadata response or `void` in case if `callback` provided. + */ + setUUIDMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Set UUID metadata object with parameters:`, + })); + return this._setUUIDMetadata(parameters, callback); + }); + } + /** + * Update a specific UUID Metadata object. + * + * @internal + * + * @param parameters - Request configuration parameters. Will set UUID metadata for currently + * configured PubNub client `uuid` if not set. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set UUID metadata response or `void` in case if `callback` provided. + */ + _setUUIDMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + if (parameters.userId) { + this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); + parameters.uuid = parameters.userId; + } + (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); + const request = new SetUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Set UUID metadata object success. Updated '${parameters.uuid}' UUID metadata object.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Remove a specific UUID Metadata object. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous UUID metadata remove response or `void` in case if `callback` provided. + */ + removeUUIDMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' + ? { uuid: this.configuration.userId } + : parametersOrCallback, + details: `Remove${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} UUID metadata object with parameters:`, + })); + return this._removeUUIDMetadata(parametersOrCallback, callback); + }); + } + /** + * Remove a specific UUID Metadata object. + * + * @internal + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous UUID metadata remove response or `void` in case if `callback` provided. + */ + _removeUUIDMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + // Get user request parameters. + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + if (parameters.userId) { + this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); + parameters.uuid = parameters.userId; + } + (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); + const request = new RemoveUUIDMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Remove UUID metadata object success. Removed '${parameters.uuid}' UUID metadata object.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Fetch a paginated list of Channel Metadata objects. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all Channel metadata response or `void` in case if `callback` + * provided. + */ + getAllChannelMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, + details: `Get all Channel metadata objects with parameters:`, + })); + return this._getAllChannelMetadata(parametersOrCallback, callback); + }); + } + /** + * Fetch a paginated list of Channel Metadata objects. + * + * @internal + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all Channel metadata response or `void` in case if `callback` + * provided. + */ + _getAllChannelMetadata(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + // Get user request parameters. + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + const request = new GetAllChannelsMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get all Channel metadata objects success. Received ${response.totalCount} Channel metadata objects.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Fetch Channel Metadata object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get Channel metadata response or `void` in case if `callback` provided. + */ + getChannelMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Get Channel metadata object with parameters:`, + })); + return this._getChannelMetadata(parameters, callback); + }); + } + /** + * Fetch Channel Metadata object. + * + * @internal + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get Channel metadata response or `void` in case if `callback` provided. + */ + _getChannelMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + const request = new GetChannelMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get Channel metadata object success. Received '${parameters.channel}' Channel metadata object.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Update specific Channel Metadata object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set Channel metadata response or `void` in case if `callback` provided. + */ + setChannelMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Set Channel metadata object with parameters:`, + })); + return this._setChannelMetadata(parameters, callback); + }); + } + /** + * Update specific Channel Metadata object. + * + * @internal + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set Channel metadata response or `void` in case if `callback` provided. + */ + _setChannelMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + const request = new SetChannelMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Set Channel metadata object success. Updated '${parameters.channel}' Channel metadata object.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Remove a specific Channel Metadata object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous Channel metadata remove response or `void` in case if `callback` + * provided. + */ + removeChannelMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove Channel metadata object with parameters:`, + })); + return this._removeChannelMetadata(parameters, callback); + }); + } + /** + * Remove a specific Channel Metadata object. + * + * @internal + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous Channel metadata remove response or `void` in case if `callback` + * provided. + */ + _removeChannelMetadata(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + const request = new RemoveChannelMetadataRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Remove Channel metadata object success. Removed '${parameters.channel}' Channel metadata object.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Fetch a paginated list of Channel Member objects. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get Channel Members response or `void` in case if `callback` provided. + */ + getChannelMembers(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Get channel members with parameters:`, + })); + const request = new GetChannelMembersRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get channel members success. Received ${response.totalCount} channel members.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Update specific Channel Members list. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update Channel members list response or `void` in case if `callback` + * provided. + */ + setChannelMembers(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Set channel members with parameters:`, + })); + const request = new SetChannelMembersRequest(Object.assign(Object.assign({}, parameters), { type: 'set', keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Set channel members success. There are ${response.totalCount} channel members now.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Remove Members from the Channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous Channel Members remove response or `void` in case if `callback` provided. + */ + removeChannelMembers(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove channel members with parameters:`, + })); + const request = new SetChannelMembersRequest(Object.assign(Object.assign({}, parameters), { type: 'delete', keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Remove channel members success. There are ${response.totalCount} channel members now.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Fetch a specific UUID Memberships list. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get UUID Memberships response or `void` in case if `callback` provided. + */ + getMemberships(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + // Get user request parameters. + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + if (parameters.userId) { + this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); + parameters.uuid = parameters.userId; + } + (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Get memberships with parameters:`, + })); + const request = new GetUUIDMembershipsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get memberships success. Received ${response.totalCount} memberships.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Update specific UUID Memberships list. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update UUID Memberships list response or `void` in case if `callback` + * provided. + */ + setMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + if (parameters.userId) { + this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); + parameters.uuid = parameters.userId; + } + (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Set memberships with parameters:`, + })); + const request = new SetUUIDMembershipsRequest(Object.assign(Object.assign({}, parameters), { type: 'set', keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Set memberships success. There are ${response.totalCount} memberships now.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + /** + * Remove a specific UUID Memberships. + * + * @param parameters - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous UUID Memberships remove response or `void` in case if `callback` + * provided. + */ + removeMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + if (parameters.userId) { + this.logger.warn('PubNub', `'userId' parameter is deprecated. Use 'uuid' instead.`); + parameters.uuid = parameters.userId; + } + (_a = parameters.uuid) !== null && _a !== void 0 ? _a : (parameters.uuid = this.configuration.userId); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove memberships with parameters:`, + })); + const request = new SetUUIDMembershipsRequest(Object.assign(Object.assign({}, parameters), { type: 'delete', keySet: this.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Remove memberships success. There are ${response.totalCount} memberships now.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + // endregion + // endregion + // -------------------------------------------------------- + // --------------------- Deprecated API ------------------- + // -------------------------------------------------------- + // region Deprecated + /** + * Fetch paginated list of specific Space members or specific User memberships. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get specific Space members or specific User memberships response. + * + * @deprecated Use {@link PubNubObjects#getChannelMembers getChannelMembers} or + * {@link PubNubObjects#getMemberships getMemberships} methods instead. + */ + fetchMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b; + this.logger.warn('PubNub', "'fetchMemberships' is deprecated. Use 'pubnub.objects.getChannelMembers' or 'pubnub.objects.getMemberships'" + + ' instead.'); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Fetch memberships with parameters:`, + })); + if ('spaceId' in parameters) { + const spaceParameters = parameters; + const mappedParameters = { + channel: (_a = spaceParameters.spaceId) !== null && _a !== void 0 ? _a : spaceParameters.channel, + filter: spaceParameters.filter, + limit: spaceParameters.limit, + page: spaceParameters.page, + include: Object.assign({}, spaceParameters.include), + sort: spaceParameters.sort + ? Object.fromEntries(Object.entries(spaceParameters.sort).map(([key, value]) => [key.replace('user', 'uuid'), value])) + : undefined, + }; + // Map Members object to the older version. + const mapMembers = (response) => ({ + status: response.status, + data: response.data.map((members) => ({ + user: members.uuid, + custom: members.custom, + updated: members.updated, + eTag: members.eTag, + })), + totalCount: response.totalCount, + next: response.next, + prev: response.prev, + }); + if (callback) + return this.getChannelMembers(mappedParameters, (status, result) => { + callback(status, result ? mapMembers(result) : result); + }); + return this.getChannelMembers(mappedParameters).then(mapMembers); + } + const userParameters = parameters; + const mappedParameters = { + uuid: (_b = userParameters.userId) !== null && _b !== void 0 ? _b : userParameters.uuid, + filter: userParameters.filter, + limit: userParameters.limit, + page: userParameters.page, + include: Object.assign({}, userParameters.include), + sort: userParameters.sort + ? Object.fromEntries(Object.entries(userParameters.sort).map(([key, value]) => [key.replace('space', 'channel'), value])) + : undefined, + }; + // Map Memberships object to the older version. + const mapMemberships = (response) => ({ + status: response.status, + data: response.data.map((membership) => ({ + space: membership.channel, + custom: membership.custom, + updated: membership.updated, + eTag: membership.eTag, + })), + totalCount: response.totalCount, + next: response.next, + prev: response.prev, + }); + if (callback) + return this.getMemberships(mappedParameters, (status, result) => { + callback(status, result ? mapMemberships(result) : result); + }); + return this.getMemberships(mappedParameters).then(mapMemberships); + }); + } + /** + * Add members to specific Space or memberships specific User. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous add members to specific Space or memberships specific User response or + * `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubObjects#setChannelMembers setChannelMembers} or + * {@link PubNubObjects#setMemberships setMemberships} methods instead. + */ + addMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b, _c, _d, _e, _f; + this.logger.warn('PubNub', "'addMemberships' is deprecated. Use 'pubnub.objects.setChannelMembers' or 'pubnub.objects.setMemberships'" + + ' instead.'); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Add memberships with parameters:`, + })); + if ('spaceId' in parameters) { + const spaceParameters = parameters; + const mappedParameters = { + channel: (_a = spaceParameters.spaceId) !== null && _a !== void 0 ? _a : spaceParameters.channel, + uuids: (_c = (_b = spaceParameters.users) === null || _b === void 0 ? void 0 : _b.map((user) => { + if (typeof user === 'string') + return user; + return { id: user.userId, custom: user.custom }; + })) !== null && _c !== void 0 ? _c : spaceParameters.uuids, + limit: 0, + }; + if (callback) + return this.setChannelMembers(mappedParameters, callback); + return this.setChannelMembers(mappedParameters); + } + const userParameters = parameters; + const mappedParameters = { + uuid: (_d = userParameters.userId) !== null && _d !== void 0 ? _d : userParameters.uuid, + channels: (_f = (_e = userParameters.spaces) === null || _e === void 0 ? void 0 : _e.map((space) => { + if (typeof space === 'string') + return space; + return { + id: space.spaceId, + custom: space.custom, + }; + })) !== null && _f !== void 0 ? _f : userParameters.channels, + limit: 0, + }; + if (callback) + return this.setMemberships(mappedParameters, callback); + return this.setMemberships(mappedParameters); + }); + } + } + + /** + * Create User REST API module. + * + * @internal + */ + // endregion + /** + * Create User request. + * + * @internal + */ + class CreateUserRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNCreateDataSyncUserOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.data) + return 'User data cannot be empty'; + if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) + return 'Entity class version cannot be empty'; + } + get headers() { + var _a; + const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.user+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/users`; + } + get body() { + const { id, class: entityClass, classLevel, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), (entityClass !== undefined ? { entityClass } : {})), { entityClassVersion: data.classVersion }), (classLevel !== undefined ? { entityClassLevel: classLevel } : {})), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * PubNub DataSync API type definitions. + * + * Types for Entity Class CRUD operations. + */ + /** + * Serialize a {@link DataSyncSort} into the query value the service expects. + * + * A raw string is passed through unchanged. An object is turned into a list of `field:order` + * entries (a `null` direction emits the bare field name, letting the service apply its default + * ascending order). Mirrors the App Context `getAllChannelMetadata` sort handling. + * + * @internal + */ + function serializeDataSyncSort(sort) { + if (typeof sort === 'string') + return sort; + return Object.entries(sort !== null && sort !== void 0 ? sort : {}).map(([option, order]) => (order !== null ? `${option}:${order}` : option)); + } + /** + * Convert user-friendly patch input to JSON Patch operations (request format). + * + * `path`/`from` are passed through verbatim — callers supply the exact RFC 6901 pointer. Do not + * reintroduce dot-notation translation here: splitting on `.` makes stored field names that + * contain a `.` unaddressable. + * + * - Each key in `add` becomes an "add" operation. + * - Each key in `replace` becomes a "replace" operation. + * - Each entry in `remove` becomes a "remove" operation. + * - Each `{ from, path }` pair in `move` becomes a "move" operation. + * - Each `{ from, path }` pair in `copy` becomes a "copy" operation. + * - Each key in `test` becomes a "test" operation. + * + * @internal + */ + function toJsonPatchOperations(input) { + const { add, replace, remove, move, copy, test } = input; + const ops = []; + if (add) { + for (const [path, value] of Object.entries(add)) { + ops.push({ op: 'add', path, value }); + } + } + if (replace) { + for (const [path, value] of Object.entries(replace)) { + ops.push({ op: 'replace', path, value }); + } + } + if (remove) { + for (const path of remove) { + ops.push({ op: 'remove', path }); + } + } + if (move) { + for (const { from, path } of move) { + ops.push({ op: 'move', from, path }); + } + } + if (copy) { + for (const { from, path } of copy) { + ops.push({ op: 'copy', from, path }); + } + } + if (test) { + for (const [path, value] of Object.entries(test)) { + ops.push({ op: 'test', path, value }); + } + } + return ops; + } + + /** + * Get Users REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Default number of items per page. + */ + const DEFAULT_LIMIT$4 = 20; + // endregion + /** + * Get Users request. + * + * @internal + */ + class GetUsersRequest extends AbstractRequest { + constructor(parameters) { + var _a; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$4); + } + operation() { + return RequestOperation$1.PNGetDataSyncUsersOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + get path() { + return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/users`; + } + get queryParameters() { + const { class: entityClass, classVersion, classLevel, cursor, limit, filter, filterFast, sort } = this.parameters; + const sorting = serializeDataSyncSort(sort); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (entityClass ? { entity_class: entityClass } : {})), (classVersion !== undefined ? { entity_class_version: `${classVersion}` } : {})), (classLevel ? { entity_class_level: classLevel } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set User REST API module. + * + * Full resource replacement via PUT. + * + * @internal + */ + // endregion + /** + * Set User request. + * + * @internal + */ + class SetUserRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PUT }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSetDataSyncUserOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'User id cannot be empty'; + if (!this.parameters.data) + return 'User data cannot be empty'; + if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) + return 'Entity class version cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.user+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; + } + get body() { + const { data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign({ entityClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Remove User REST API module. + * + * @internal + */ + // endregion + /** + * Remove User request. + * + * @internal + */ + class RemoveUserRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveDataSyncUserOperation; + } + validate() { + if (!this.parameters.id) + return 'User id cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.keys(headers).length > 0 ? headers : undefined; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { status: response.status }; + }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; + } + } + + /** + * Update User REST API module. + * + * Partial update via JSON Patch (RFC 6902). + * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` + * (JSON Pointer paths), and `move`/`copy` (JSON Pointer `{ from, path }` pairs) + * and converts them to JSON Patch operations. Paths are sent verbatim. + * + * @internal + */ + // endregion + /** + * Update User request. + * + * @internal + */ + class UpdateUserRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNUpdateDataSyncUserOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'User id cannot be empty'; + const { add, replace, remove, move, copy, test } = this.parameters; + const hasAdd = add && Object.keys(add).length > 0; + const hasReplace = replace && Object.keys(replace).length > 0; + const hasRemove = remove && remove.length > 0; + const hasMove = move && move.length > 0; + const hasCopy = copy && copy.length > 0; + const hasTest = test && Object.keys(test).length > 0; + if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) + return 'At least one of add, replace, remove, move, copy, or test must be provided'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; + } + get body() { + const { add, replace, remove, move, copy, test } = this.parameters; + const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); + return JSON.stringify(jsonPatchOps); + } + } + + /** + * Get User REST API module. + * + * @internal + */ + // endregion + /** + * Get User request. + * + * @internal + */ + class GetUserRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetDataSyncUserOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'User id cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/users/${encodeString(id)}`; + } + } + + /** + * Create Channel REST API module. + * + * @internal + */ + // endregion + /** + * Create Channel request. + * + * @internal + */ + class CreateChannelRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNCreateDataSyncChannelOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.data) + return 'Channel data cannot be empty'; + if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) + return 'Entity class version cannot be empty'; + } + get headers() { + var _a; + const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.channel+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/channels`; + } + get body() { + const { id, class: entityClass, classLevel, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), (entityClass !== undefined ? { entityClass } : {})), { entityClassVersion: data.classVersion }), (classLevel !== undefined ? { entityClassLevel: classLevel } : {})), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Get Channels REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Default number of items per page. + */ + const DEFAULT_LIMIT$3 = 20; + // endregion + /** + * Get Channels request. + * + * @internal + */ + class GetChannelsRequest extends AbstractRequest { + constructor(parameters) { + var _a; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$3); + } + operation() { + return RequestOperation$1.PNGetDataSyncChannelsOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + get path() { + return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/channels`; + } + get queryParameters() { + const { class: entityClass, classVersion, classLevel, cursor, limit, filter, filterFast, sort } = this.parameters; + const sorting = serializeDataSyncSort(sort); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (entityClass ? { entity_class: entityClass } : {})), (classVersion !== undefined ? { entity_class_version: `${classVersion}` } : {})), (classLevel ? { entity_class_level: classLevel } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set Channel REST API module. + * + * Full resource replacement via PUT. + * + * @internal + */ + // endregion + /** + * Set Channel request. + * + * @internal + */ + class SetChannelRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PUT }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSetDataSyncChannelOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Channel id cannot be empty'; + if (!this.parameters.data) + return 'Channel data cannot be empty'; + if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) + return 'Entity class version cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.channel+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; + } + get body() { + const { data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign({ entityClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Remove Channel REST API module. + * + * @internal + */ + // endregion + /** + * Remove Channel request. + * + * @internal + */ + class RemoveChannelRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveDataSyncChannelOperation; + } + validate() { + if (!this.parameters.id) + return 'Channel id cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.keys(headers).length > 0 ? headers : undefined; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { status: response.status }; + }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; + } + } + + /** + * Update Channel REST API module. + * + * Partial update via JSON Patch (RFC 6902). + * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` + * (JSON Pointer paths), and `move`/`copy` (JSON Pointer from → path pairs), + * converting them to JSON Patch operations. Paths are sent verbatim. + * + * @internal + */ + // endregion + /** + * Update Channel request. + * + * @internal + */ + class UpdateChannelRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNUpdateDataSyncChannelOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Channel id cannot be empty'; + const { add, replace, remove, move, copy, test } = this.parameters; + const hasAdd = add && Object.keys(add).length > 0; + const hasReplace = replace && Object.keys(replace).length > 0; + const hasRemove = remove && remove.length > 0; + const hasMove = move && move.length > 0; + const hasCopy = copy && copy.length > 0; + const hasTest = test && Object.keys(test).length > 0; + if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) + return 'At least one of add, replace, remove, move, copy, or test must be provided'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; + } + get body() { + const { add, replace, remove, move, copy, test } = this.parameters; + const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); + return JSON.stringify(jsonPatchOps); + } + } + + /** + * Get Channel REST API module. + * + * @internal + */ + // endregion + /** + * Get Channel request. + * + * @internal + */ + class GetChannelRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetDataSyncChannelOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Channel id cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/channels/${encodeString(id)}`; + } + } + + /** + * Create Membership REST API module. + * + * @internal + */ + // endregion + /** + * Create Membership request. + * + * @internal + */ + class CreateMembershipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNCreateDataSyncMembershipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.userId) + return 'User id cannot be empty'; + if (!this.parameters.channelId) + return 'Channel id cannot be empty'; + if (!this.parameters.data) + return 'Membership data cannot be empty'; + if (!this.parameters.data.classVersion) + return 'Membership class version cannot be empty'; + } + get headers() { + var _a; + const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.membership+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/memberships`; + } + get body() { + const { id, userId, channelId, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), { userId, + channelId, relationshipClassVersion: data.classVersion }), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Get Memberships REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Default number of items per page. + */ + const DEFAULT_LIMIT$2 = 20; + // endregion + /** + * Get Memberships request. + * + * @internal + */ + class GetMembershipsRequest extends AbstractRequest { + constructor(parameters) { + var _a; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$2); + } + operation() { + return RequestOperation$1.PNGetDataSyncMembershipsOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + get path() { + return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/memberships`; + } + get queryParameters() { + const { userId, channelId, classVersion, cursor, limit, filter, filterFast, sort } = this.parameters; + const sorting = serializeDataSyncSort(sort); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (userId ? { user_id: userId } : {})), (channelId ? { channel_id: channelId } : {})), (classVersion !== undefined ? { relationship_class_version: `${classVersion}` } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set Membership REST API module. + * + * Full resource replacement via PUT. + * + * @internal + */ + // endregion + /** + * Set Membership request. + * + * @internal + */ + class SetMembershipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PUT }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSetDataSyncMembershipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Membership id cannot be empty'; + if (!this.parameters.userId) + return 'User id cannot be empty'; + if (!this.parameters.channelId) + return 'Channel id cannot be empty'; + if (!this.parameters.data) + return 'Membership data cannot be empty'; + if (!this.parameters.data.classVersion) + return 'Membership class version cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.membership+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; + } + get body() { + const { userId, channelId, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign({ userId, + channelId, relationshipClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Remove Membership REST API module. + * + * @internal + */ + // endregion + /** + * Remove Membership request. + * + * @internal + */ + class RemoveMembershipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveDataSyncMembershipOperation; + } + validate() { + if (!this.parameters.id) + return 'Membership id cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.keys(headers).length > 0 ? headers : undefined; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { status: response.status }; + }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; + } + } + + /** + * Update Membership REST API module. + * + * Partial update via JSON Patch (RFC 6902). + * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` + * (JSON Pointer paths), and `move`/`copy` (JSON Pointer `{ from, path }` pairs) + * and converts them to JSON Patch operations. Paths are sent verbatim. + * + * @internal + */ + // endregion + /** + * Update Membership request. + * + * @internal + */ + class UpdateMembershipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNUpdateDataSyncMembershipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Membership id cannot be empty'; + const { add, replace, remove, move, copy, test } = this.parameters; + const hasAdd = add && Object.keys(add).length > 0; + const hasReplace = replace && Object.keys(replace).length > 0; + const hasRemove = remove && remove.length > 0; + const hasMove = move && move.length > 0; + const hasCopy = copy && copy.length > 0; + const hasTest = test && Object.keys(test).length > 0; + if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) + return 'At least one of add, replace, remove, move, copy, or test must be provided'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; + } + get body() { + const { add, replace, remove, move, copy, test } = this.parameters; + const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); + return JSON.stringify(jsonPatchOps); + } + } + + /** + * Get Membership REST API module. + * + * @internal + */ + // endregion + /** + * Get Membership request. + * + * @internal + */ + class GetMembershipRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetDataSyncMembershipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Membership id cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/memberships/${encodeString(id)}`; + } + } + + /** + * Create Relationship REST API module. + * + * @internal + */ + // endregion + /** + * Create Relationship request. + * + * @internal + */ + class CreateRelationshipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNCreateDataSyncRelationshipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.entityAId) + return 'Entity A id cannot be empty'; + if (!this.parameters.entityBId) + return 'Entity B id cannot be empty'; + if (!this.parameters.class) + return 'Relationship class cannot be empty'; + if (!this.parameters.data) + return 'Relationship data cannot be empty'; + if (!this.parameters.data.classVersion) + return 'Relationship class version cannot be empty'; + } + get headers() { + var _a; + const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.relationship+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/relationships`; + } + get body() { + const { id, class: relationshipClass, entityAId, entityBId, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), { entityAId, + entityBId, + relationshipClass, relationshipClassVersion: data.classVersion }), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Get Relationships REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Default number of items per page. + */ + const DEFAULT_LIMIT$1 = 20; + // endregion + /** + * Get Relationships request. + * + * @internal + */ + class GetRelationshipsRequest extends AbstractRequest { + constructor(parameters) { + var _a; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT$1); + } + operation() { + return RequestOperation$1.PNGetDataSyncRelationshipsOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.class) + return 'Relationship class cannot be empty'; + } + get path() { + return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/relationships`; + } + get queryParameters() { + const { class: relationshipClass, classVersion, entityAId, entityBId, cursor, limit, filter, filterFast, sort, } = this.parameters; + const sorting = serializeDataSyncSort(sort); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ relationship_class: relationshipClass }, (classVersion !== undefined ? { relationship_class_version: `${classVersion}` } : {})), (entityAId ? { entity_a_id: entityAId } : {})), (entityBId ? { entity_b_id: entityBId } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set Relationship REST API module. + * + * Full resource replacement via PUT. + * + * @internal + */ + // endregion + /** + * Set Relationship request. + * + * @internal + */ + class SetRelationshipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PUT }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSetDataSyncRelationshipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Relationship id cannot be empty'; + if (!this.parameters.entityAId) + return 'Entity A id cannot be empty'; + if (!this.parameters.entityBId) + return 'Entity B id cannot be empty'; + if (!this.parameters.data) + return 'Relationship data cannot be empty'; + if (!this.parameters.data.classVersion) + return 'Relationship class version cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.relationship+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; + } + get body() { + const { entityAId, entityBId, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign({ entityAId, + entityBId, relationshipClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Remove Relationship REST API module. + * + * @internal + */ + // endregion + /** + * Remove Relationship request. + * + * @internal + */ + class RemoveRelationshipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveDataSyncRelationshipOperation; + } + validate() { + if (!this.parameters.id) + return 'Relationship id cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.keys(headers).length > 0 ? headers : undefined; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { status: response.status }; + }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; + } + } + + /** + * Update Relationship REST API module. + * + * Partial update via JSON Patch (RFC 6902). + * Accepts `add` and `replace` (JSON Pointer key-value pairs), `remove` + * (JSON Pointer paths), `move` and `copy` (`{ from, path }` JSON Pointer pairs), + * and `test` (JSON Pointer key-value pairs) and converts them to JSON Patch + * operations. Paths are sent verbatim. + * + * @internal + */ + // endregion + /** + * Update Relationship request. + * + * @internal + */ + class UpdateRelationshipRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNUpdateDataSyncRelationshipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Relationship id cannot be empty'; + const { add, replace, remove, move, copy, test } = this.parameters; + const hasAdd = add && Object.keys(add).length > 0; + const hasReplace = replace && Object.keys(replace).length > 0; + const hasRemove = remove && remove.length > 0; + const hasMove = move && move.length > 0; + const hasCopy = copy && copy.length > 0; + const hasTest = test && Object.keys(test).length > 0; + if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) + return 'At least one of add, replace, remove, move, copy, or test must be provided'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; + } + get body() { + const { add, replace, remove, move, copy, test } = this.parameters; + const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); + return JSON.stringify(jsonPatchOps); + } + } + + /** + * Get Relationship REST API module. + * + * @internal + */ + // endregion + /** + * Get Relationship request. + * + * @internal + */ + class GetRelationshipRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetDataSyncRelationshipOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Relationship id cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/relationships/${encodeString(id)}`; + } + } + + /** + * Create Entity REST API module. + * + * @internal + */ + // endregion + /** + * Create Entity request. + * + * @internal + */ + class CreateEntityRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.POST }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNCreateDataSyncEntityOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.class) + return 'Entity class cannot be empty'; + if (!this.parameters.data) + return 'Entity data cannot be empty'; + if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) + return 'Entity class version cannot be empty'; + } + get headers() { + var _a; + const headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.entity+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/entities`; + } + get body() { + const { id, class: entityClass, classLevel, data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (id !== undefined ? { id } : {})), { entityClass, entityClassVersion: data.classVersion }), (classLevel !== undefined ? { entityClassLevel: classLevel } : {})), (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Get Entities REST API module. + * + * @internal + */ + // -------------------------------------------------------- + // ----------------------- Defaults ----------------------- + // -------------------------------------------------------- + // region Defaults + /** + * Default number of items per page. + */ + const DEFAULT_LIMIT = 20; + // endregion + /** + * Get Entities request. + * + * @internal + */ + class GetEntitiesRequest extends AbstractRequest { + constructor(parameters) { + var _a; + super(); + this.parameters = parameters; + // Apply defaults. + (_a = parameters.limit) !== null && _a !== void 0 ? _a : (parameters.limit = DEFAULT_LIMIT); + } + operation() { + return RequestOperation$1.PNGetDataSyncEntitiesOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.class) + return 'Entity class cannot be empty'; + } + get path() { + return `/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/entities`; + } + get queryParameters() { + const { class: entityClass, classVersion, classLevel, cursor, limit, filter, filterFast, sort } = this.parameters; + const sorting = serializeDataSyncSort(sort); + return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ entity_class: entityClass }, (classVersion !== undefined ? { entity_class_version: `${classVersion}` } : {})), (classLevel ? { entity_class_level: classLevel } : {})), (cursor ? { cursor } : {})), (limit ? { limit: `${limit}` } : {})), (filter ? { filter } : {})), (filterFast ? { filter_fast: filterFast } : {})), (sorting.length ? { sort: sorting } : {})); + } + } + + /** + * Set Entity REST API module. + * + * Full resource replacement via PUT. + * Note: `entityClass` is immutable and cannot be changed via update. + * + * @internal + */ + // endregion + /** + * Set Entity request. + * + * @internal + */ + class SetEntityRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PUT }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNSetDataSyncEntityOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Entity id cannot be empty'; + if (!this.parameters.data) + return 'Entity data cannot be empty'; + if (this.parameters.data.classVersion === undefined || this.parameters.data.classVersion === null) + return 'Entity class version cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/vnd.pubnub.objects.entity+json;version=1' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; + } + get body() { + const { data } = this.parameters; + return JSON.stringify({ + data: Object.assign(Object.assign({ entityClassVersion: data.classVersion }, (data.status !== undefined ? { status: data.status } : {})), (data.payload !== undefined ? { payload: data.payload } : {})), + }); + } + } + + /** + * Remove Entity REST API module. + * + * @internal + */ + // endregion + /** + * Remove Entity request. + * + * @internal + */ + class RemoveEntityRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.DELETE }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNRemoveDataSyncEntityOperation; + } + validate() { + if (!this.parameters.id) + return 'Entity id cannot be empty'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.keys(headers).length > 0 ? headers : undefined; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { status: response.status }; + }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; + } + } + + /** + * Update Entity REST API module. + * + * Partial update via JSON Patch (RFC 6902). + * Accepts `add`/`replace`/`test` (JSON Pointer key-value pairs), `remove` + * (JSON Pointer paths), and `move`/`copy` (JSON Pointer from/path pairs), and + * converts them to JSON Patch operations. Paths are sent verbatim. + * + * @internal + */ + // endregion + /** + * Update Entity request. + * + * @internal + */ + class UpdateEntityRequest extends AbstractRequest { + constructor(parameters) { + super({ method: TransportMethod.PATCH }); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNUpdateDataSyncEntityOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Entity id cannot be empty'; + const { add, replace, remove, move, copy, test } = this.parameters; + const hasAdd = add && Object.keys(add).length > 0; + const hasReplace = replace && Object.keys(replace).length > 0; + const hasRemove = remove && remove.length > 0; + const hasMove = move && move.length > 0; + const hasCopy = copy && copy.length > 0; + const hasTest = test && Object.keys(test).length > 0; + if (!hasAdd && !hasReplace && !hasRemove && !hasMove && !hasCopy && !hasTest) + return 'At least one of add, replace, remove, move, copy, or test must be provided'; + } + get headers() { + var _a; + let headers = (_a = super.headers) !== null && _a !== void 0 ? _a : {}; + if (this.parameters.ifMatchesEtag) + headers = Object.assign(Object.assign({}, headers), { 'If-Match': this.parameters.ifMatchesEtag }); + return Object.assign(Object.assign({}, headers), { 'Content-Type': 'application/json-patch+json' }); + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; + } + get body() { + const { add, replace, remove, move, copy, test } = this.parameters; + const jsonPatchOps = toJsonPatchOperations({ add, replace, remove, move, copy, test }); + return JSON.stringify(jsonPatchOps); + } + } + + /** + * Get Entity REST API module. + * + * @internal + */ + // endregion + /** + * Get Entity request. + * + * @internal + */ + class GetEntityRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNGetDataSyncEntityOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + // The DataSync service returns the object envelope ({ data } or { data, meta }) without a + // top-level HTTP status; surface `response.status` so callers can inspect it (parity with remove). + const parsed = this.deserializeResponse(response); + return Object.assign(Object.assign({}, parsed), { status: response.status }); + }); + } + validate() { + if (!this.parameters.id) + return 'Entity id cannot be empty'; + } + get path() { + const { keySet: { subscribeKey }, id, } = this.parameters; + return `/v1/datasync/subkeys/${subscribeKey}/entities/${encodeString(id)}`; + } + } + + /** + * PubNub DataSync API module. + */ + /** + * PubNub DataSync API interface. + */ + class PubNubDataSync { + /** + * Create DataSync API access object. + * + * @param configuration - Extended PubNub client configuration object. + * @param sendRequest - Function which should be used to send REST API calls. + * + * @internal + */ + constructor(configuration, + /* eslint-disable @typescript-eslint/no-explicit-any */ + sendRequest) { + this.keySet = configuration.keySet; + this.configuration = configuration; + this.sendRequest = sendRequest; + } + /** + * Get registered loggers' manager. + * + * @returns Registered loggers' manager. + * + * @internal + */ + get logger() { + return this.configuration.logger(); + } + /** + * Create a new Entity. + * + * To change a field later with `updateEntity`, address it by its JSON Pointer: `classVersion` is + * patched as `/entityClassVersion`, `status` as `/status`, and payload fields as + * `/payload/`. `class` and `classLevel` are immutable and cannot be patched. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create entity response or `void` in case if `callback` provided. + */ + createEntity(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Create Entity with parameters:', + })); + const request = new CreateEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a specific Entity. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get entity response or `void` in case if `callback` provided. + */ + getEntity(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Entity with parameters:', + })); + const request = new GetEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a paginated list of Entities for a given Entity Class. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get entities response or `void` in case if `callback` provided. + */ + getEntities(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Entities with parameters:', + })); + const request = new GetEntitiesRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Set an Entity (full replacement via PUT). + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set entity response or `void` in case if `callback` provided. + */ + setEntity(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Set Entity with parameters:', + })); + const request = new SetEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Update an Entity (partial update via JSON Patch RFC 6902). + * + * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which + * is the name an entity carries in responses and real-time events: + * + * - `classVersion` → `/entityClassVersion` + * - `status` → `/status` + * - a payload field → `/payload/`; nest deeper with more segments, e.g. + * `/payload/address/city`. A field name that contains a `.` is written as-is + * (`/payload/user.name`). + * + * `entityClass` and `entityClassLevel` are immutable and cannot be patched. + * + * @example + * ```typescript + * await pubnub.dataSync.updateEntity({ + * id, + * replace: { '/status': 'inactive', '/payload/creditScore': 810 }, + * remove: ['/payload/legacyField'], + * }); + * ``` + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update entity response or `void` in case if `callback` provided. + */ + updateEntity(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Update Entity with parameters:', + })); + const request = new UpdateEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Remove an Entity. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove entity response or `void` in case if `callback` provided. + */ + removeEntity(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove Entity with parameters:', + })); + const request = new RemoveEntityRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Create a new Relationship. + * + * To change a field later with `updateRelationship`, address it by its JSON Pointer: + * `classVersion` is patched as `/relationshipClassVersion`, `status` as `/status`, and payload + * fields as `/payload/`. `class`, `entityAId`, and `entityBId` are immutable and + * cannot be patched. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create relationship response or `void` in case if `callback` provided. + */ + createRelationship(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Create Relationship with parameters:', + })); + const request = new CreateRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a specific Relationship. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get relationship response or `void` in case if `callback` provided. + */ + getRelationship(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Relationship with parameters:', + })); + const request = new GetRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a paginated list of Relationships. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get relationships response or `void` in case if `callback` provided. + */ + getRelationships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Relationships with parameters:', + })); + const request = new GetRelationshipsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Set a Relationship (full replacement via PUT). + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set relationship response or `void` in case if `callback` provided. + */ + setRelationship(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Set Relationship with parameters:', + })); + const request = new SetRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Update a Relationship (partial update via JSON Patch RFC 6902). + * + * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which + * is the name a relationship carries in responses and real-time events: + * + * - `classVersion` → `/relationshipClassVersion` + * - `status` → `/status` + * - a payload field → `/payload/`; nest deeper with more segments, e.g. + * `/payload/address/city`. A field name that contains a `.` is written as-is + * (`/payload/user.name`). + * + * `relationshipClass`, `entityAId`, and `entityBId` are immutable and cannot be patched. + * + * @example + * ```typescript + * await pubnub.dataSync.updateRelationship({ + * id, + * replace: { '/status': 'inactive', '/payload/label': 'primary' }, + * remove: ['/payload/legacyField'], + * }); + * ``` + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update relationship response or `void` in case if `callback` provided. + */ + updateRelationship(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Update Relationship with parameters:', + })); + const request = new UpdateRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Remove a Relationship. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove relationship response or `void` in case if `callback` provided. + */ + removeRelationship(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove Relationship with parameters:', + })); + const request = new RemoveRelationshipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Create a new User. + * + * To change a field later with `updateUser`, address it by its JSON Pointer: `classVersion` is + * patched as `/entityClassVersion`, `status` as `/status`, and payload fields as + * `/payload/`. `class` and `classLevel` are immutable and cannot be patched. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create user response or `void` in case if `callback` provided. + */ + createUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Create User with parameters:', + })); + const request = new CreateUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a specific User. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get user response or `void` in case if `callback` provided. + */ + getUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get User with parameters:', + })); + const request = new GetUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a paginated list of Users. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get users response or `void` in case if `callback` provided. + */ + getUsers(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Users with parameters:', + })); + const request = new GetUsersRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Set a User (full replacement via PUT). + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set user response or `void` in case if `callback` provided. + */ + setUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Set User with parameters:', + })); + const request = new SetUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Update a User (partial update via JSON Patch RFC 6902). + * + * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which + * is the name a user carries in responses and real-time events: + * + * - `classVersion` → `/entityClassVersion` + * - `status` → `/status` + * - a payload field → `/payload/`; nest deeper with more segments, e.g. + * `/payload/address/city`. A field name that contains a `.` is written as-is + * (`/payload/user.name`). + * + * `entityClass` and `entityClassLevel` are immutable and cannot be patched. + * + * @example + * ```typescript + * await pubnub.dataSync.updateUser({ + * id, + * replace: { '/status': 'inactive', '/payload/email': 'alice.v@acme.test' }, + * remove: ['/payload/legacyField'], + * }); + * ``` + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update user response or `void` in case if `callback` provided. + */ + updateUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Update User with parameters:', + })); + const request = new UpdateUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Remove a User. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove user response or `void` in case if `callback` provided. + */ + removeUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove User with parameters:', + })); + const request = new RemoveUserRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Create a new Channel. + * + * To change a field later with `updateChannel`, address it by its JSON Pointer: `classVersion` + * is patched as `/entityClassVersion`, `status` as `/status`, and payload fields as + * `/payload/`. `class` and `classLevel` are immutable and cannot be patched. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create channel response or `void` in case if `callback` provided. + */ + createChannel(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Create Channel with parameters:', + })); + const request = new CreateChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a specific Channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get channel response or `void` in case if `callback` provided. + */ + getChannel(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Channel with parameters:', + })); + const request = new GetChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a paginated list of Channels. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get channels response or `void` in case if `callback` provided. + */ + getChannels(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Channels with parameters:', + })); + const request = new GetChannelsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Set a Channel (full replacement via PUT). + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set channel response or `void` in case if `callback` provided. + */ + setChannel(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Set Channel with parameters:', + })); + const request = new SetChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Update a Channel (partial update via JSON Patch RFC 6902). + * + * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which + * is the name a channel carries in responses and real-time events: + * + * - `classVersion` → `/entityClassVersion` + * - `status` → `/status` + * - a payload field → `/payload/`; nest deeper with more segments, e.g. + * `/payload/address/city`. A field name that contains a `.` is written as-is + * (`/payload/user.name`). + * + * `entityClass` and `entityClassLevel` are immutable and cannot be patched. + * + * @example + * ```typescript + * await pubnub.dataSync.updateChannel({ + * id, + * replace: { '/status': 'inactive', '/payload/memberCount': 42 }, + * remove: ['/payload/legacyField'], + * }); + * ``` + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update channel response or `void` in case if `callback` provided. + */ + updateChannel(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Update Channel with parameters:', + })); + const request = new UpdateChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Remove a Channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove channel response or `void` in case if `callback` provided. + */ + removeChannel(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove Channel with parameters:', + })); + const request = new RemoveChannelRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Create a new Membership (associates a User with a Channel). + * + * To change a field later with `updateMembership`, address it by its JSON Pointer: + * `classVersion` is patched as `/relationshipClassVersion`, `status` as `/status`, and payload + * fields as `/payload/`. `userId` and `channelId` are immutable and cannot be patched. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create membership response or `void` in case if `callback` provided. + */ + createMembership(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Create Membership with parameters:', + })); + const request = new CreateMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a specific Membership. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get membership response or `void` in case if `callback` provided. + */ + getMembership(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Membership with parameters:', + })); + const request = new GetMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Get a paginated list of Memberships. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get memberships response or `void` in case if `callback` provided. + */ + getMemberships(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + const parameters = parametersOrCallback && typeof parametersOrCallback !== 'function' ? parametersOrCallback : {}; + callback !== null && callback !== void 0 ? callback : (callback = typeof parametersOrCallback === 'function' ? parametersOrCallback : undefined); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get Memberships with parameters:', + })); + const request = new GetMembershipsRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Set a Membership (full replacement via PUT). + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set membership response or `void` in case if `callback` provided. + */ + setMembership(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Set Membership with parameters:', + })); + const request = new SetMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Update a Membership (partial update via JSON Patch RFC 6902). + * + * Paths are JSON Pointers (RFC 6901). Address each field by its stored property name, which + * is the name a membership carries in responses and real-time events: + * + * - `classVersion` → `/relationshipClassVersion` + * - `status` → `/status` + * - a payload field → `/payload/`; nest deeper with more segments, e.g. + * `/payload/address/city`. A field name that contains a `.` is written as-is + * (`/payload/user.name`). + * + * `userId` and `channelId` are immutable and cannot be patched. + * + * @example + * ```typescript + * await pubnub.dataSync.updateMembership({ + * id, + * replace: { '/status': 'inactive', '/payload/role': 'moderator' }, + * remove: ['/payload/legacyField'], + * }); + * ``` + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update membership response or `void` in case if `callback` provided. + */ + updateMembership(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Update Membership with parameters:', + })); + const request = new UpdateMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + /** + * Remove a Membership. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove membership response or `void` in case if `callback` provided. + */ + removeMembership(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove Membership with parameters:', + })); + const request = new RemoveMembershipRequest(Object.assign(Object.assign({}, parameters), { keySet: this.keySet })); + if (callback) + return this.sendRequest(request, callback); + return this.sendRequest(request); + }); + } + } + + /** + * Time REST API module. + */ + // endregion + /** + * Get current PubNub high-precision time request. + * + * @internal + */ + class TimeRequest extends AbstractRequest { + constructor() { + super(); + } + operation() { + return RequestOperation$1.PNTimeOperation; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + return { timetoken: this.deserializeResponse(response)[0] }; + }); + } + get path() { + return '/time/0'; + } + } + + /** + * Download File REST API module. + * + * @internal + */ + // endregion + /** + * Download File request. + * + * @internal + */ + class DownloadFileRequest extends AbstractRequest { + constructor(parameters) { + super(); + this.parameters = parameters; + } + operation() { + return RequestOperation$1.PNDownloadFileOperation; + } + validate() { + const { channel, id, name } = this.parameters; + if (!channel) + return "channel can't be empty"; + if (!id) + return "file id can't be empty"; + if (!name) + return "file name can't be empty"; + } + parse(response) { + return __awaiter(this, void 0, void 0, function* () { + const { cipherKey, crypto, cryptography, name, PubNubFile } = this.parameters; + const mimeType = response.headers['content-type']; + let decryptedFile; + let body = response.body; + if (PubNubFile.supportsEncryptFile && (cipherKey || crypto)) { + if (cipherKey && cryptography) + body = yield cryptography.decrypt(cipherKey, body); + else if (!cipherKey && crypto) + decryptedFile = yield crypto.decryptFile(PubNubFile.create({ data: body, name: name, mimeType }), PubNubFile); + } + return (decryptedFile + ? decryptedFile + : PubNubFile.create({ + data: body, + name, + mimeType, + })); + }); + } + get path() { + const { keySet: { subscribeKey }, channel, id, name, } = this.parameters; + return `/v1/files/${subscribeKey}/channels/${encodeString(channel)}/files/${encodeString(id)}/${encodeString(name)}`; + } + } + + /** + * Core PubNub API module. + */ + // endregion + /** + * Platform-agnostic PubNub client core. + */ + class PubNubCore { + /** + * Construct notification payload which will trigger push notification. + * + * @param title - Title which will be shown on notification. + * @param body - Payload which will be sent as part of notification. + * + * @returns Pre-formatted message payload which will trigger push notification. + */ + static notificationPayload(title, body) { + { + return new NotificationsPayload(title, body); + } + } + /** + * Generate unique identifier. + * + * @returns Unique identifier. + */ + static generateUUID() { + return uuidGenerator.createUUID(); + } + // endregion + /** + * Create and configure PubNub client core. + * + * @param configuration - PubNub client core configuration. + * @returns Configured and ready to use PubNub client. + * + * @internal + */ + constructor(configuration) { + /** + * List of subscribe capable objects with active subscriptions. + * + * Track list of {@link Subscription} and {@link SubscriptionSet} objects with active + * subscription. + * + * @internal + */ + this.eventHandleCapable = {}; + /** + * Created entities. + * + * Map of entities which have been created to access. + * + * @internal + */ + this.entities = {}; + this._configuration = configuration.configuration; + this.cryptography = configuration.cryptography; + this.tokenManager = configuration.tokenManager; + this.transport = configuration.transport; + this.crypto = configuration.crypto; + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: configuration.configuration, + details: 'Create with configuration:', + ignoredKeys(key, obj) { + return typeof obj[key] === 'function' || key.startsWith('_') || key === 'keySet' || isSensitiveLogKey(key); + }, + })); + // API group entry points initialization. + this._objects = new PubNubObjects(this._configuration, this.sendRequest.bind(this)); + this._dataSync = new PubNubDataSync(this._configuration, this.sendRequest.bind(this)); + this._channelGroups = new PubNubChannelGroups(this._configuration.logger(), this._configuration.keySet, this.sendRequest.bind(this)); + this._push = new PubNubPushNotifications(this._configuration.logger(), this._configuration.keySet, this.sendRequest.bind(this)); + { + // Prepare for a real-time events announcement. + this.eventDispatcher = new EventDispatcher(); + if (this._configuration.enableEventEngine) { + { + this.logger.debug('PubNub', 'Using new subscription loop management.'); + let heartbeatInterval = this._configuration.getHeartbeatInterval(); + this.presenceState = {}; + { + if (heartbeatInterval) { + this.presenceEventEngine = new PresenceEventEngine({ + heartbeat: (parameters, callback) => { + this.logger.trace('PresenceEventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Heartbeat with parameters:', + })); + return this.heartbeat(parameters, callback); + }, + leave: (parameters) => { + this.logger.trace('PresenceEventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Leave with parameters:', + })); + this.makeUnsubscribe(parameters, () => { }); + }, + heartbeatDelay: () => { + let cancelDelay = () => { }; + const promise = new Promise((resolve, reject) => { + heartbeatInterval = this._configuration.getHeartbeatInterval(); + if (!heartbeatInterval) + reject(new PubNubError('Heartbeat interval has been reset.')); + else { + const timeoutId = setTimeout(() => { + resolve(); + }, heartbeatInterval * 1000); + cancelDelay = () => { + clearTimeout(timeoutId); + reject(new PubNubError('Heartbeat interval has been cancelled.')); + }; + } + }); + return { cancelDelay, promise }; + }, + emitStatus: (status) => this.emitStatus(status), + config: this._configuration, + presenceState: this.presenceState, + }); + } + } + this.eventEngine = new EventEngine({ + handshake: (parameters) => { + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Handshake with parameters:', + ignoredKeys: ['abortSignal', 'crypto', 'timeout', 'keySet', 'getFileUrl'], + })); + return this.subscribeHandshake(parameters); + }, + receiveMessages: (parameters) => { + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Receive messages with parameters:', + ignoredKeys: ['abortSignal', 'crypto', 'timeout', 'keySet', 'getFileUrl'], + })); + return this.subscribeReceiveMessages(parameters); + }, + join: (parameters) => { + var _a, _b; + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Join with parameters:', + })); + if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { + this.logger.trace('EventEngine', "Ignoring 'join' announcement request."); + return; + } + this.join(parameters); + }, + leave: (parameters) => { + var _a, _b; + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Leave with parameters:', + })); + if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { + this.logger.trace('EventEngine', "Ignoring 'leave' announcement request."); + return; + } + this.leave(parameters); + }, + leaveAll: (parameters) => { + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Leave all with parameters:', + })); + this.leaveAll(parameters); + }, + presenceReconnect: (parameters) => { + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Reconnect with parameters:', + })); + this.presenceReconnect(parameters); + }, + presenceDisconnect: (parameters) => { + this.logger.trace('EventEngine', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Disconnect with parameters:', + })); + this.presenceDisconnect(parameters); + }, + presenceState: this.presenceState, + config: this._configuration, + emitMessages: (cursor, events) => { + try { + this.logger.debug('EventEngine', () => { + const hashedEvents = events.map((event) => { + const pn_mfp = event.type === PubNubEventType.Message || event.type === PubNubEventType.Signal + ? messageFingerprint(event.data.message) + : undefined; + return pn_mfp ? { type: event.type, data: Object.assign(Object.assign({}, event.data), { pn_mfp }) } : event; + }); + return { messageType: 'object', message: hashedEvents, details: 'Received events:' }; + }); + events.forEach((event) => this.emitEvent(cursor, event)); + } + catch (e) { + const errorStatus = { + error: true, + category: StatusCategory$1.PNUnknownCategory, + errorData: e, + statusCode: 0, + }; + this.emitStatus(errorStatus); + } + }, + emitStatus: (status) => this.emitStatus(status), + }); + } + } + else { + { + this.logger.debug('PubNub', 'Using legacy subscription loop management.'); + this.subscriptionManager = new SubscriptionManager(this._configuration, (cursor, event) => { + try { + this.emitEvent(cursor, event); + } + catch (e) { + const errorStatus = { + error: true, + category: StatusCategory$1.PNUnknownCategory, + errorData: e, + statusCode: 0, + }; + this.emitStatus(errorStatus); + } + }, this.emitStatus.bind(this), (parameters, callback) => { + this.logger.trace('SubscriptionManager', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Subscribe with parameters:', + ignoredKeys: ['crypto', 'timeout', 'keySet', 'getFileUrl'], + })); + this.makeSubscribe(parameters, callback); + }, (parameters, callback) => { + this.logger.trace('SubscriptionManager', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Heartbeat with parameters:', + ignoredKeys: ['crypto', 'timeout', 'keySet', 'getFileUrl'], + })); + return this.heartbeat(parameters, callback); + }, (parameters, callback) => { + this.logger.trace('SubscriptionManager', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Leave with parameters:', + })); + this.makeUnsubscribe(parameters, callback); + }, this.time.bind(this)); + } + } + } + } + // -------------------------------------------------------- + // -------------------- Configuration ---------------------- + // -------------------------------------------------------- + // region Configuration + /** + * PubNub client configuration. + * + * @returns Currently user PubNub client configuration. + */ + get configuration() { + return this._configuration; + } + /** + * Current PubNub client configuration. + * + * @returns Currently user PubNub client configuration. + * + * @deprecated Use {@link configuration} getter instead. + */ + get _config() { + return this.configuration; + } + /** + * REST API endpoint access authorization key. + * + * It is required to have `authorization key` with required permissions to access REST API + * endpoints when `PAM` enabled for user key set. + */ + get authKey() { + var _a; + return (_a = this._configuration.authKey) !== null && _a !== void 0 ? _a : undefined; + } + /** + * REST API endpoint access authorization key. + * + * It is required to have `authorization key` with required permissions to access REST API + * endpoints when `PAM` enabled for user key set. + */ + getAuthKey() { + return this.authKey; + } + /** + * Change REST API endpoint access authorization key. + * + * @param authKey - New authorization key which should be used with new requests. + */ + setAuthKey(authKey) { + this.logger.debug('PubNub', 'Auth key updated.'); + this._configuration.setAuthKey(authKey); + if (this.onAuthenticationChange) + this.onAuthenticationChange(authKey); + } + /** + * Get a PubNub client user identifier. + * + * @returns Current PubNub client user identifier. + */ + get userId() { + return this._configuration.userId; + } + /** + * Change the current PubNub client user identifier. + * + * **Important:** Change won't affect ongoing REST API calls. + * **Warning:** Because ongoing REST API calls won't be canceled there could happen unexpected events like implicit + * `join` event for the previous `userId` after a long-poll subscribe request will receive a response. To avoid this + * it is advised to unsubscribe from all/disconnect before changing `userId`. + * + * @param value - New PubNub client user identifier. + * + * @throws Error empty user identifier has been provided. + */ + set userId(value) { + if (!value || typeof value !== 'string' || value.trim().length === 0) { + const error = new Error('Missing or invalid userId parameter. Provide a valid string userId'); + this.logger.error('PubNub', () => ({ messageType: 'error', message: error })); + throw error; + } + this.logger.debug('PubNub', `Set user ID: ${value}`); + this._configuration.userId = value; + if (this.onUserIdChange) + this.onUserIdChange(this._configuration.userId); + } + /** + * Get a PubNub client user identifier. + * + * @returns Current PubNub client user identifier. + */ + getUserId() { + return this._configuration.userId; + } + /** + * Change the current PubNub client user identifier. + * + * **Important:** Change won't affect ongoing REST API calls. + * + * @param value - New PubNub client user identifier. + * + * @throws Error empty user identifier has been provided. + */ + setUserId(value) { + this.userId = value; + } + /** + * Real-time updates filtering expression. + * + * @returns Filtering expression. + */ + get filterExpression() { + var _a; + return (_a = this._configuration.getFilterExpression()) !== null && _a !== void 0 ? _a : undefined; + } + /** + * Real-time updates filtering expression. + * + * @returns Filtering expression. + */ + getFilterExpression() { + return this.filterExpression; + } + /** + * Update real-time updates filtering expression. + * + * @param expression - New expression which should be used or `undefined` to disable filtering. + */ + set filterExpression(expression) { + this.logger.debug('PubNub', `Set filter expression: ${expression}`); + this._configuration.setFilterExpression(expression); + } + /** + * Update real-time updates filtering expression. + * + * @param expression - New expression which should be used or `undefined` to disable filtering. + */ + setFilterExpression(expression) { + this.logger.debug('PubNub', `Set filter expression: ${expression}`); + this.filterExpression = expression; + } + /** + * Dta encryption / decryption key. + * + * @returns Currently used key for data encryption / decryption. + */ + get cipherKey() { + return this._configuration.getCipherKey(); + } + /** + * Change data encryption / decryption key. + * + * @param key - New key which should be used for data encryption / decryption. + */ + set cipherKey(key) { + this._configuration.setCipherKey(key); + } + /** + * Change data encryption / decryption key. + * + * @param key - New key which should be used for data encryption / decryption. + */ + setCipherKey(key) { + this.logger.debug('PubNub', 'Cipher key updated.'); + this.cipherKey = key; + } + /** + * Change a heartbeat requests interval. + * + * @param interval - New presence request heartbeat intervals. + */ + set heartbeatInterval(interval) { + var _a; + this.logger.debug('PubNub', `Set heartbeat interval: ${interval}`); + this._configuration.setHeartbeatInterval(interval); + if (this.onHeartbeatIntervalChange) + this.onHeartbeatIntervalChange((_a = this._configuration.getHeartbeatInterval()) !== null && _a !== void 0 ? _a : 0); + } + /** + * Change a heartbeat requests interval. + * + * @param interval - New presence request heartbeat intervals. + */ + setHeartbeatInterval(interval) { + this.heartbeatInterval = interval; + } + /** + * Get registered loggers' manager. + * + * @returns Registered loggers' manager. + */ + get logger() { + return this._configuration.logger(); + } + /** + * Get PubNub SDK version. + * + * @returns Current SDK version. + */ + getVersion() { + return this._configuration.getVersion(); + } + /** + * Add framework's prefix. + * + * @param name - Name of the framework which would want to add own data into `pnsdk` suffix. + * @param suffix - Suffix with information about a framework. + */ + _addPnsdkSuffix(name, suffix) { + this.logger.debug('PubNub', `Add '${name}' 'pnsdk' suffix: ${suffix}`); + this._configuration._addPnsdkSuffix(name, suffix); + } + // -------------------------------------------------------- + // ---------------------- Deprecated ---------------------- + // -------------------------------------------------------- + // region Deprecated + /** + * Get a PubNub client user identifier. + * + * @returns Current PubNub client user identifier. + * + * @deprecated Use the {@link getUserId} or {@link userId} getter instead. + */ + getUUID() { + return this.userId; + } + /** + * Change the current PubNub client user identifier. + * + * **Important:** Change won't affect ongoing REST API calls. + * + * @param value - New PubNub client user identifier. + * + * @throws Error empty user identifier has been provided. + * + * @deprecated Use the {@link PubNubCore#setUserId setUserId} or {@link PubNubCore#userId userId} setter instead. + */ + setUUID(value) { + this.logger.warn('PubNub', "'setUserId` is deprecated, please use 'setUserId' or 'userId' setter instead."); + this.logger.debug('PubNub', `Set UUID: ${value}`); + this.userId = value; + } + /** + * Custom data encryption method. + * + * @deprecated Instead use {@link cryptoModule} for data encryption. + */ + get customEncrypt() { + return this._configuration.getCustomEncrypt(); + } + /** + * Custom data decryption method. + * + * @deprecated Instead use {@link cryptoModule} for data decryption. + */ + get customDecrypt() { + return this._configuration.getCustomDecrypt(); + } + // endregion + // endregion + // -------------------------------------------------------- + // ---------------------- Entities ------------------------ + // -------------------------------------------------------- + // region Entities + /** + * Create a `Channel` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param name - Unique channel name. + * @returns `Channel` entity. + */ + channel(name) { + let channel = this.entities[`${name}_ch`]; + if (!channel) + channel = this.entities[`${name}_ch`] = new Channel(name, this); + return channel; + } + /** + * Create a `ChannelGroup` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param name - Unique channel group name. + * @returns `ChannelGroup` entity. + */ + channelGroup(name) { + let channelGroup = this.entities[`${name}_chg`]; + if (!channelGroup) + channelGroup = this.entities[`${name}_chg`] = new ChannelGroup(name, this); + return channelGroup; + } + /** + * Create a `ChannelMetadata` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param id - Unique channel metadata object identifier. + * @returns `ChannelMetadata` entity. + */ + channelMetadata(id) { + let metadata = this.entities[`${id}_chm`]; + if (!metadata) + metadata = this.entities[`${id}_chm`] = new ChannelMetadata(id, this); + return metadata; + } + /** + * Create a `UserMetadata` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param id - Unique user metadata object identifier. + * @returns `UserMetadata` entity. + */ + userMetadata(id) { + let metadata = this.entities[`${id}_um`]; + if (!metadata) + metadata = this.entities[`${id}_um`] = new UserMetadata(id, this); + return metadata; + } + /** + * Create a `DataSyncUser` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param id - Unique DataSync `User` object identifier (used verbatim, so wildcard identifiers + * like `user.*` are supported). + * @returns `DataSyncUser` entity. + */ + dataSyncUser(id) { + let entity = this.entities[`${id}_dsu`]; + if (!entity) + entity = this.entities[`${id}_dsu`] = new DataSyncUser(id, this); + return entity; + } + /** + * Create a `DataSyncChannel` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param id - Unique DataSync `Channel` object identifier (used verbatim, so wildcard identifiers + * like `channel.*` are supported). + * @returns `DataSyncChannel` entity. + */ + dataSyncChannel(id) { + let entity = this.entities[`${id}_dsc`]; + if (!entity) + entity = this.entities[`${id}_dsc`] = new DataSyncChannel(id, this); + return entity; + } + /** + * Create a `DataSyncMembership` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * **Important:** Membership changes are delivered on the data channels of both linked entities + * (the user and the channel identifier), not on the membership identifier — use + * {@link PubNubCore#dataSyncUser dataSyncUser} / {@link PubNubCore#dataSyncChannel + * dataSyncChannel} to observe them. + * + * @param id - Unique DataSync `Membership` object identifier (`{userId}:{channelId}`, used + * verbatim, so wildcard identifiers like `user-123:*` are supported). + * @returns `DataSyncMembership` entity. + */ + dataSyncMembership(id) { + let entity = this.entities[`${id}_dsm`]; + if (!entity) + entity = this.entities[`${id}_dsm`] = new DataSyncMembership(id, this); + return entity; + } + /** + * Create a `DataSyncEntity` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * @param id - Unique DataSync `Entity` object identifier (used verbatim, so wildcard identifiers + * like `customer.*` are supported). + * @returns `DataSyncEntity` entity. + */ + dataSyncEntity(id) { + let entity = this.entities[`${id}_dse`]; + if (!entity) + entity = this.entities[`${id}_dse`] = new DataSyncEntity(id, this); + return entity; + } + /** + * Create a `DataSyncRelationship` entity. + * + * Entity can be used for the interaction with the following API: + * - `subscribe` + * + * **Important:** Relationship changes are delivered on the data channels of both linked entities + * (`entityAId` and `entityBId`), not on the relationship identifier — use + * {@link PubNubCore#dataSyncEntity dataSyncEntity} to observe them. + * + * @param id - Unique DataSync `Relationship` object identifier (used verbatim, so wildcard + * identifiers like `owns.*` are supported). + * @returns `DataSyncRelationship` entity. + */ + dataSyncRelationship(id) { + let entity = this.entities[`${id}_dsr`]; + if (!entity) + entity = this.entities[`${id}_dsr`] = new DataSyncRelationship(id, this); + return entity; + } + /** + * Create subscriptions set object. + * + * @param parameters - Subscriptions set configuration parameters. + */ + subscriptionSet(parameters) { + var _a, _b; + { + // Prepare a list of entities for a set. + const entities = []; + (_a = parameters.channels) === null || _a === void 0 ? void 0 : _a.forEach((name) => entities.push(this.channel(name))); + (_b = parameters.channelGroups) === null || _b === void 0 ? void 0 : _b.forEach((name) => entities.push(this.channelGroup(name))); + return new SubscriptionSet({ client: this, entities, options: parameters.subscriptionOptions }); + } + } + /** + * Schedule request execution. + * + * @internal + * + * @param request - REST API request. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous request execution and response parsing result or `void` in case if + * `callback` provided. + * + * @throws PubNubError in case of request processing error. + */ + sendRequest(request, callback) { + return __awaiter(this, void 0, void 0, function* () { + // Validate user-input. + const validationResult = request.validate(); + if (validationResult) { + const validationError = createValidationError(validationResult); + this.logger.error('PubNub', () => ({ messageType: 'error', message: validationError })); + if (callback) + return callback(validationError, null); + throw new PubNubError('Validation failed, check status for details', validationError); + } + // Complete request configuration. + const transportRequest = request.request(); + const operation = request.operation(); + if ((transportRequest.formData && transportRequest.formData.length > 0) || + operation === RequestOperation$1.PNDownloadFileOperation) { + // Set file upload / download request delay. + transportRequest.timeout = this._configuration.getFileTimeout(); + } + else { + if (operation === RequestOperation$1.PNSubscribeOperation || + operation === RequestOperation$1.PNReceiveMessagesOperation) + transportRequest.timeout = this._configuration.getSubscribeTimeout(); + else + transportRequest.timeout = this._configuration.getTransactionTimeout(); + } + // API request processing status. + const status = { + error: false, + operation, + category: StatusCategory$1.PNAcknowledgmentCategory, + statusCode: 0, + }; + const [sendableRequest, cancellationController] = this.transport.makeSendable(transportRequest); + /** + * **Important:** Because of multiple environments where JS SDK can be used, control over + * cancellation had to be inverted to let the transport provider solve a request cancellation task + * more efficiently. As a result, cancellation controller can be retrieved and used only after + * the request will be scheduled by the transport provider. + */ + request.cancellationController = cancellationController ? cancellationController : null; + return sendableRequest + .then((response) => { + status.statusCode = response.status; + // Handle a special case when request completed but not fully processed by PubNub service. + if (response.status !== 200 && response.status !== 204) { + const responseText = PubNubCore.decoder.decode(response.body); + const contentType = response.headers['content-type']; + if (contentType || contentType.indexOf('javascript') !== -1 || contentType.indexOf('json') !== -1) { + const json = JSON.parse(responseText); + if (typeof json === 'object' && 'error' in json && json.error && typeof json.error === 'object') + status.errorData = json.error; + } + else + status.responseText = responseText; + } + return request.parse(response); + }) + .then((parsed) => { + // Notify callback (if possible). + if (callback) + return callback(status, parsed); + return parsed; + }) + .catch((error) => { + const apiError = !(error instanceof PubNubAPIError) ? PubNubAPIError.create(error) : error; + // Notify callback (if possible). + if (callback) { + if (apiError.category !== StatusCategory$1.PNCancelledCategory) { + this.logger.error('PubNub', () => ({ + messageType: 'error', + message: apiError.toPubNubError(operation, 'REST API request processing error, check status for details'), + })); + } + return callback(apiError.toStatus(operation), null); + } + const pubNubError = apiError.toPubNubError(operation, 'REST API request processing error, check status for details'); + if (apiError.category !== StatusCategory$1.PNCancelledCategory) + this.logger.error('PubNub', () => ({ messageType: 'error', message: pubNubError })); + throw pubNubError; + }); + }); + } + /** + * Unsubscribe from all channels and groups. + * + * @param [isOffline] - Whether `offline` presence should be notified or not. + */ + destroy(isOffline = false) { + this.logger.info('PubNub', 'Destroying PubNub client.'); + { + if (this._globalSubscriptionSet) { + this._globalSubscriptionSet.invalidate(true); + this._globalSubscriptionSet = undefined; + } + Object.values(this.eventHandleCapable).forEach((subscription) => subscription.invalidate(true)); + this.eventHandleCapable = {}; + if (this.subscriptionManager) { + this.subscriptionManager.unsubscribeAll(isOffline); + this.subscriptionManager.disconnect(); + } + else if (this.eventEngine) + this.eventEngine.unsubscribeAll(isOffline); + } + { + if (this.presenceEventEngine) + this.presenceEventEngine.leaveAll(isOffline); + } + } + /** + * Unsubscribe from all channels and groups. + * + * @deprecated Use {@link destroy} method instead. + */ + stop() { + this.logger.warn('PubNub', "'stop' is deprecated, please use 'destroy' instead."); + this.destroy(); + } + /** + * Publish data to a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous publish data response or `void` in case if `callback` provided. + */ + publish(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Publish with parameters:', + })); + const isFireRequest = parameters.replicate === false && parameters.storeInHistory === false; + const request = new PublishRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule() })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `${isFireRequest ? 'Fire' : 'Publish'} success with timetoken: ${response.timetoken}`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Signal data to a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous signal data response or `void` in case if `callback` provided. + */ + signal(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Signal with parameters:', + })); + const request = new SignalRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Publish success with timetoken: ${response.timetoken}`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * `Fire` a data to a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous signal data response or `void` in case if `callback` provided. + * + * @deprecated Use {@link publish} method instead. + */ + fire(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Fire with parameters:', + })); + callback !== null && callback !== void 0 ? callback : (callback = () => { }); + return this.publish(Object.assign(Object.assign({}, parameters), { replicate: false, storeInHistory: false }), callback); + }); + } + // endregion + // -------------------------------------------------------- + // -------------------- Subscribe API --------------------- + // -------------------------------------------------------- + // region Subscribe API + /** + * Global subscription set which supports legacy subscription interface. + * + * @returns Global subscription set. + * + * @internal + */ + get globalSubscriptionSet() { + if (!this._globalSubscriptionSet) + this._globalSubscriptionSet = this.subscriptionSet({}); + return this._globalSubscriptionSet; + } + /** + * Subscription-based current timetoken. + * + * @returns Timetoken based on current timetoken plus diff between current and loop start time. + * + * @internal + */ + get subscriptionTimetoken() { + { + if (this.subscriptionManager) + return this.subscriptionManager.subscriptionTimetoken; + else if (this.eventEngine) + return this.eventEngine.subscriptionTimetoken; + } + return undefined; + } + /** + * Get list of channels on which PubNub client currently subscribed. + * + * @returns List of active channels. + */ + getSubscribedChannels() { + { + if (this.subscriptionManager) + return this.subscriptionManager.subscribedChannels; + else if (this.eventEngine) + return this.eventEngine.getSubscribedChannels(); + } + return []; + } + /** + * Get list of channel groups on which PubNub client currently subscribed. + * + * @returns List of active channel groups. + */ + getSubscribedChannelGroups() { + { + if (this.subscriptionManager) + return this.subscriptionManager.subscribedChannelGroups; + else if (this.eventEngine) + return this.eventEngine.getSubscribedChannelGroups(); + } + return []; + } + /** + * Register an events handler object ({@link Subscription} or {@link SubscriptionSet}) with an active subscription. + * + * @param subscription - {@link Subscription} or {@link SubscriptionSet} object. + * @param [cursor] - Subscription catchup timetoken. + * @param [subscriptions] - List of subscriptions for partial subscription loop update. + * + * @internal + */ + registerEventHandleCapable(subscription, cursor, subscriptions) { + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign(Object.assign({ subscription: subscription }, (cursor ? { cursor } : [])), (subscriptions ? { subscriptions } : {})), + details: `Register event handle capable:`, + })); + if (!this.eventHandleCapable[subscription.state.id]) + this.eventHandleCapable[subscription.state.id] = subscription; + let subscriptionInput; + if (!subscriptions || subscriptions.length === 0) + subscriptionInput = subscription.subscriptionInput(false); + else { + subscriptionInput = new SubscriptionInput({}); + subscriptions.forEach((subscription) => subscriptionInput.add(subscription.subscriptionInput(false))); + } + const parameters = {}; + parameters.channels = subscriptionInput.channels; + parameters.channelGroups = subscriptionInput.channelGroups; + if (cursor) + parameters.timetoken = cursor.timetoken; + if (this.subscriptionManager) + this.subscriptionManager.subscribe(parameters); + else if (this.eventEngine) + this.eventEngine.subscribe(parameters); + } + } + /** + * Unregister an events handler object ({@link Subscription} or {@link SubscriptionSet}) with inactive subscription. + * + * @param subscription - {@link Subscription} or {@link SubscriptionSet} object. + * @param [subscriptions] - List of subscriptions for partial subscription loop update. + * + * @internal + */ + unregisterEventHandleCapable(subscription, subscriptions) { + { + if (!this.eventHandleCapable[subscription.state.id]) + return; + const inUseSubscriptions = []; + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: { subscription: subscription, subscriptions }, + details: `Unregister event handle capable:`, + })); + // Check whether only subscription object has been passed to be unregistered. + let shouldDeleteEventHandler = !subscriptions || subscriptions.length === 0; + // Check whether subscription set is unregistering with all managed Subscription objects, + if (!shouldDeleteEventHandler && + subscription instanceof SubscriptionSet && + subscription.subscriptions.length === (subscriptions === null || subscriptions === void 0 ? void 0 : subscriptions.length)) + shouldDeleteEventHandler = subscription.subscriptions.every((sub) => subscriptions.includes(sub)); + if (shouldDeleteEventHandler) + delete this.eventHandleCapable[subscription.state.id]; + let subscriptionInput; + if (!subscriptions || subscriptions.length === 0) { + subscriptionInput = subscription.subscriptionInput(true); + if (subscriptionInput.isEmpty) + inUseSubscriptions.push(subscription); + } + else { + subscriptionInput = new SubscriptionInput({}); + subscriptions.forEach((subscription) => { + const input = subscription.subscriptionInput(true); + if (input.isEmpty) + inUseSubscriptions.push(subscription); + else + subscriptionInput.add(input); + }); + } + if (inUseSubscriptions.length > 0) { + this.logger.trace('PubNub', () => { + const entities = []; + if (inUseSubscriptions[0] instanceof SubscriptionSet) { + inUseSubscriptions[0].subscriptions.forEach((subscription) => entities.push(subscription.state.entity)); + } + else + inUseSubscriptions.forEach((subscription) => entities.push(subscription.state.entity)); + return { + messageType: 'object', + message: { entities }, + details: `Can't unregister event handle capable because entities still in use:`, + }; + }); + } + if (subscriptionInput.isEmpty) + return; + else { + const _channelGroupsInUse = []; + const _channelsInUse = []; + Object.values(this.eventHandleCapable).forEach((_subscription) => { + const _subscriptionInput = _subscription.subscriptionInput(false); + const _subscriptionChannelGroups = _subscriptionInput.channelGroups; + const _subscriptionChannels = _subscriptionInput.channels; + _channelGroupsInUse.push(...subscriptionInput.channelGroups.filter((channel) => _subscriptionChannelGroups.includes(channel))); + _channelsInUse.push(...subscriptionInput.channels.filter((channel) => _subscriptionChannels.includes(channel))); + }); + if (_channelsInUse.length > 0 || _channelGroupsInUse.length > 0) { + this.logger.trace('PubNub', () => { + const _entitiesInUse = []; + const addEntityIfInUse = (entity) => { + const namesOrIds = entity.subscriptionNames(true); + const checkList = entity.subscriptionType === SubscriptionType.Channel ? _channelsInUse : _channelGroupsInUse; + if (namesOrIds.some((id) => checkList.includes(id))) + _entitiesInUse.push(entity); + }; + Object.values(this.eventHandleCapable).forEach((_subscription) => { + if (_subscription instanceof SubscriptionSet) { + _subscription.subscriptions.forEach((_subscriptionInSet) => { + addEntityIfInUse(_subscriptionInSet.state.entity); + }); + } + else if (_subscription instanceof Subscription) + addEntityIfInUse(_subscription.state.entity); + }); + let details = 'Some entities still in use:'; + if (_channelsInUse.length + _channelGroupsInUse.length === subscriptionInput.length) + details = "Can't unregister event handle capable because entities still in use:"; + return { messageType: 'object', message: { entities: _entitiesInUse }, details }; + }); + subscriptionInput.remove(new SubscriptionInput({ channels: _channelsInUse, channelGroups: _channelGroupsInUse })); + if (subscriptionInput.isEmpty) + return; + } + } + const parameters = {}; + parameters.channels = subscriptionInput.channels; + parameters.channelGroups = subscriptionInput.channelGroups; + if (this.subscriptionManager) + this.subscriptionManager.unsubscribe(parameters); + else if (this.eventEngine) + this.eventEngine.unsubscribe(parameters); + } + } + /** + * Subscribe to specified channels and groups real-time events. + * + * @param parameters - Request configuration parameters. + */ + subscribe(parameters) { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Subscribe with parameters:', + })); + // The addition of a new subscription set into the subscribed global subscription set will update the active + // subscription loop with new channels and groups. + const subscriptionSet = this.subscriptionSet(Object.assign(Object.assign({}, parameters), { subscriptionOptions: { receivePresenceEvents: parameters.withPresence } })); + this.globalSubscriptionSet.addSubscriptionSet(subscriptionSet); + subscriptionSet.dispose(); + const timetoken = typeof parameters.timetoken === 'number' ? `${parameters.timetoken}` : parameters.timetoken; + this.globalSubscriptionSet.subscribe({ timetoken }); + } + } + /** + * Perform subscribe request. + * + * **Note:** Method passed into managers to let them use it when required. + * + * @internal + * + * @param parameters - Request configuration parameters. + * @param callback - Request completion handler callback. + */ + makeSubscribe(parameters, callback) { + { + // `on-demand` query parameter not required for non-SharedWorker environment. + if (!this._configuration.isSharedWorkerEnabled()) + parameters.onDemand = false; + const request = new SubscribeRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); + this.sendRequest(request, (status, result) => { + var _a; + if (this.subscriptionManager && ((_a = this.subscriptionManager.abort) === null || _a === void 0 ? void 0 : _a.identifier) === request.requestIdentifier) + this.subscriptionManager.abort = null; + callback(status, result); + }); + /** + * Allow subscription cancellation. + * + * **Note:** Had to be done after scheduling because the transport provider returns the cancellation + * controller only when schedule new request. + */ + if (this.subscriptionManager) { + // Creating an identifiable abort caller. + const callableAbort = () => request.abort('Cancel long-poll subscribe request'); + callableAbort.identifier = request.requestIdentifier; + this.subscriptionManager.abort = callableAbort; + } + } + } + /** + * Unsubscribe from specified channels and groups real-time events. + * + * @param parameters - Request configuration parameters. + */ + unsubscribe(parameters) { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Unsubscribe with parameters:', + })); + if (!this._globalSubscriptionSet) { + this.logger.debug('PubNub', 'There are no active subscriptions. Ignore.'); + return; + } + const subscriptions = this.globalSubscriptionSet.subscriptions.filter((subscription) => { + var _a, _b; + const subscriptionInput = subscription.subscriptionInput(false); + if (subscriptionInput.isEmpty) + return false; + for (const channel of (_a = parameters.channels) !== null && _a !== void 0 ? _a : []) + if (subscriptionInput.contains(channel)) + return true; + for (const group of (_b = parameters.channelGroups) !== null && _b !== void 0 ? _b : []) + if (subscriptionInput.contains(group)) + return true; + }); + // Removal from the active subscription also will cause `unsubscribe`. + if (subscriptions.length > 0) + this.globalSubscriptionSet.removeSubscriptions(subscriptions); + } + } + /** + * Perform unsubscribe request. + * + * **Note:** Method passed into managers to let them use it when required. + * + * @internal + * + * @param parameters - Request configuration parameters. + * @param callback - Request completion handler callback. + */ + makeUnsubscribe(parameters, callback) { + { + // Filtering out presence channels and groups. + let { channels, channelGroups } = parameters; + // Remove `-pnpres` channels / groups if they not acceptable in the current PubNub client configuration. + if (!this._configuration.getKeepPresenceChannelsInPresenceRequests()) { + if (channelGroups) + channelGroups = channelGroups.filter((channelGroup) => !channelGroup.endsWith('-pnpres')); + if (channels) + channels = channels.filter((channel) => !channel.endsWith('-pnpres')); + } + // Complete immediately request only for presence channels. + if ((channelGroups !== null && channelGroups !== void 0 ? channelGroups : []).length === 0 && (channels !== null && channels !== void 0 ? channels : []).length === 0) { + return callback({ + error: false, + operation: RequestOperation$1.PNUnsubscribeOperation, + category: StatusCategory$1.PNAcknowledgmentCategory, + statusCode: 200, + }); + } + this.sendRequest(new PresenceLeaveRequest({ channels, channelGroups, keySet: this._configuration.keySet }), callback); + } + } + /** + * Unsubscribe from all channels and groups. + */ + unsubscribeAll() { + { + this.logger.debug('PubNub', 'Unsubscribe all channels and groups'); + // Keeping a subscription set instance after invalidation so to make it possible to deliver the expected + // disconnection status. + if (this._globalSubscriptionSet) + this._globalSubscriptionSet.invalidate(false); + Object.values(this.eventHandleCapable).forEach((subscription) => subscription.invalidate(false)); + this.eventHandleCapable = {}; + if (this.subscriptionManager) + this.subscriptionManager.unsubscribeAll(); + else if (this.eventEngine) + this.eventEngine.unsubscribeAll(); + } + } + /** + * Temporarily disconnect from the real-time events stream. + * + * **Note:** `isOffline` is set to `true` only when a client experiences network issues. + * + * @param [isOffline] - Whether `offline` presence should be notified or not. + */ + disconnect(isOffline = false) { + { + this.logger.debug('PubNub', `Disconnect (while offline? ${!!isOffline ? 'yes' : 'no'})`); + if (this.subscriptionManager) + this.subscriptionManager.disconnect(); + else if (this.eventEngine) + this.eventEngine.disconnect(isOffline); + } + } + /** + * Restore connection to the real-time events stream. + * + * @param parameters - Reconnection catch-up configuration. **Note:** available only with the enabled event engine. + */ + reconnect(parameters) { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Reconnect with parameters:', + })); + if (this.subscriptionManager) + this.subscriptionManager.reconnect(); + else if (this.eventEngine) + this.eventEngine.reconnect(parameters !== null && parameters !== void 0 ? parameters : {}); + } + } + /** + * Event engine handshake subscribe. + * + * @internal + * + * @param parameters - Request configuration parameters. + */ + subscribeHandshake(parameters) { + return __awaiter(this, void 0, void 0, function* () { + { + // `on-demand` query parameter not required for non-SharedWorker environment. + if (!this._configuration.isSharedWorkerEnabled()) + parameters.onDemand = false; + if (!parameters.heartbeat) + parameters.heartbeat = this._configuration.getPresenceTimeout(); + const request = new HandshakeSubscribeRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); + const abortUnsubscribe = parameters.abortSignal.subscribe((err) => { + request.abort('Cancel subscribe handshake request'); + }); + /** + * Allow subscription cancellation. + * + * **Note:** Had to be done after scheduling because the transport provider returns the cancellation + * controller only when schedule new request. + */ + const handshakeResponse = this.sendRequest(request); + return handshakeResponse.then((response) => { + abortUnsubscribe(); + return response.cursor; + }); + } + }); + } + /** + * Event engine receive messages subscribe. + * + * @internal + * + * @param parameters - Request configuration parameters. + */ + subscribeReceiveMessages(parameters) { + return __awaiter(this, void 0, void 0, function* () { + { + // `on-demand` query parameter not required for non-SharedWorker environment. + if (!this._configuration.isSharedWorkerEnabled()) + parameters.onDemand = false; + if (!parameters.heartbeat) + parameters.heartbeat = this._configuration.getPresenceTimeout(); + const request = new ReceiveMessagesSubscribeRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); + const abortUnsubscribe = parameters.abortSignal.subscribe((err) => { + request.abort('Cancel long-poll subscribe request'); + }); + /** + * Allow subscription cancellation. + * + * **Note:** Had to be done after scheduling because the transport provider returns the cancellation + * controller only when schedule new request. + */ + const receiveResponse = this.sendRequest(request); + return receiveResponse.then((response) => { + abortUnsubscribe(); + return response; + }); + } + }); + } + /** + * Get reactions to a specific message. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get reactions response or `void` in case if `callback` provided. + */ + getMessageActions(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get message actions with parameters:', + })); + const request = new GetMessageActionsRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get message actions success. Received ${response.data.length} message actions.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Add a reaction to a specific message. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous add a reaction response or `void` in case if `callback` provided. + */ + addMessageAction(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Add message action with parameters:', + })); + const request = new AddMessageActionRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Message action add success. Message action added with timetoken: ${response.data.actionTimetoken}`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Remove a reaction from a specific message. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous remove a reaction response or `void` in case if `callback` provided. + */ + removeMessageAction(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Remove message action with parameters:', + })); + const request = new RemoveMessageAction(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Message action remove success. Removed message action with ${parameters.actionTimetoken} timetoken.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Fetch messages history for channels. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous fetch messages response or `void` in case if `callback` provided. + */ + fetchMessages(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Fetch messages with parameters:', + })); + const request = new FetchMessagesRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule(), getFileUrl: this.getFileUrl.bind(this) })); + const logResponse = (response) => { + if (!response) + return; + const messagesCount = Object.values(response.channels).reduce((acc, message) => acc + message.length, 0); + this.logger.debug('PubNub', `Fetch messages success. Received ${messagesCount} messages.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Delete messages from the channel history. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous delete messages response or `void` in case if `callback` provided. + * + */ + deleteMessages(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Delete messages with parameters:', + })); + const request = new DeleteMessageRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Delete messages success.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Count messages from the channels' history. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous count messages response or `void` in case if `callback` provided. + */ + messageCounts(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get messages count with parameters:', + })); + const request = new MessageCountRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + const messagesCount = Object.values(response.channels).reduce((acc, messagesCount) => acc + messagesCount, 0); + this.logger.debug('PubNub', `Get messages count success. There are ${messagesCount} messages since provided reference timetoken${parameters.channelTimetokens ? parameters.channelTimetokens.join(',') : ''.length > 1 ? 's' : ''}.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Fetch single channel history. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous fetch channel history response or `void` in case if `callback` provided. + * + * @deprecated + */ + history(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Fetch history with parameters:', + })); + const request = new GetHistoryRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule() })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Fetch history success. Received ${response.messages.length} messages.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Get channel's presence information. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get channel's presence response or `void` in case if `callback` provided. + */ + hereNow(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Here now with parameters:', + })); + const request = new HereNowRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Here now success. There are ${response.totalOccupancy} participants in ${response.totalChannels} channels.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Get user's presence information. + * + * Get list of channels to which `uuid` currently subscribed. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get user's presence response or `void` in case if `callback` provided. + */ + whereNow(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Where now with parameters:', + })); + const request = new WhereNowRequest({ + uuid: (_a = parameters.uuid) !== null && _a !== void 0 ? _a : this._configuration.userId, + keySet: this._configuration.keySet, + }); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Where now success. Currently present in ${response.channels.length} channels.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Get associated user's data for channels and groups. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get user's data response or `void` in case if `callback` provided. + */ + getState(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Get presence state with parameters:', + })); + const request = new GetPresenceStateRequest(Object.assign(Object.assign({}, parameters), { uuid: (_a = parameters.uuid) !== null && _a !== void 0 ? _a : this._configuration.userId, keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get presence state success. Received presence state for ${Object.keys(response.channels).length} channels.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Set associated user's data for channels and groups. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous set user's data response or `void` in case if `callback` provided. + */ + setState(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b; + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Set presence state with parameters:', + })); + const { keySet, userId: userId } = this._configuration; + const heartbeat = this._configuration.getPresenceTimeout(); + let request; + // Maintain presence information (if required). + if (this._configuration.enableEventEngine && this.presenceState) { + const presenceState = this.presenceState; + (_a = parameters.channels) === null || _a === void 0 ? void 0 : _a.forEach((channel) => (presenceState[channel] = parameters.state)); + if ('channelGroups' in parameters) { + (_b = parameters.channelGroups) === null || _b === void 0 ? void 0 : _b.forEach((group) => (presenceState[group] = parameters.state)); + } + if (this.onPresenceStateChange) + this.onPresenceStateChange(this.presenceState); + } + // Check whether the state should be set with heartbeat or not. + if ('withHeartbeat' in parameters && parameters.withHeartbeat) { + request = new HeartbeatRequest(Object.assign(Object.assign({}, parameters), { keySet, heartbeat })); + } + else { + request = new SetPresenceStateRequest(Object.assign(Object.assign({}, parameters), { keySet, uuid: userId })); + } + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Set presence state success.${request instanceof HeartbeatRequest ? ' Presence state has been set using heartbeat endpoint.' : ''}`); + }; + // Update state used by subscription manager. + if (this.subscriptionManager) { + this.subscriptionManager.setState(parameters); + if (this.onPresenceStateChange) + this.onPresenceStateChange(this.subscriptionManager.presenceState); + } + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + // endregion + // region Change presence state + /** + * Manual presence management. + * + * @param parameters - Desired presence state for a provided list of channels and groups. + */ + presence(parameters) { + var _a; + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Change presence with parameters:', + })); + (_a = this.subscriptionManager) === null || _a === void 0 ? void 0 : _a.changePresence(parameters); + } + } + // endregion + // region Heartbeat + /** + * Announce user presence + * + * @internal + * + * @param parameters - Desired presence state for provided list of channels and groups. + * @param callback - Request completion handler callback. + */ + heartbeat(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Heartbeat with parameters:', + })); + // Filtering out presence channels and groups. + let { channels, channelGroups } = parameters; + // Remove `-pnpres` channels / groups if they not acceptable in the current PubNub client configuration. + if (channelGroups) + channelGroups = channelGroups.filter((channelGroup) => !channelGroup.endsWith('-pnpres')); + if (channels) + channels = channels.filter((channel) => !channel.endsWith('-pnpres')); + // Complete immediately request only for presence channels. + if ((channelGroups !== null && channelGroups !== void 0 ? channelGroups : []).length === 0 && (channels !== null && channels !== void 0 ? channels : []).length === 0) { + const responseStatus = { + error: false, + operation: RequestOperation$1.PNHeartbeatOperation, + category: StatusCategory$1.PNAcknowledgmentCategory, + statusCode: 200, + }; + this.logger.trace('PubNub', 'There are no active subscriptions. Ignore.'); + if (callback) + return callback(responseStatus, {}); + return Promise.resolve(responseStatus); + } + const request = new HeartbeatRequest(Object.assign(Object.assign({}, parameters), { channels: [...new Set(channels)], channelGroups: [...new Set(channelGroups)], keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.trace('PubNub', 'Heartbeat success.'); + }; + const abortUnsubscribe = (_a = parameters.abortSignal) === null || _a === void 0 ? void 0 : _a.subscribe((err) => { + request.abort('Cancel long-poll subscribe request'); + }); + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + if (abortUnsubscribe) + abortUnsubscribe(); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + if (abortUnsubscribe) + abortUnsubscribe(); + return response; + }); + } + }); + } + // endregion + // region Join + /** + * Announce user `join` on specified list of channels and groups. + * + * @internal + * + * @param parameters - List of channels and groups where `join` event should be sent. + */ + join(parameters) { + var _a, _b; + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Join with parameters:', + })); + if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { + this.logger.trace('PubNub', "Ignoring 'join' announcement request."); + return; + } + if (this.presenceEventEngine) + this.presenceEventEngine.join(parameters); + else { + this.heartbeat(Object.assign(Object.assign({ channels: parameters.channels, channelGroups: parameters.groups }, (this._configuration.maintainPresenceState && + this.presenceState && + Object.keys(this.presenceState).length > 0 && { state: this.presenceState })), { heartbeat: this._configuration.getPresenceTimeout() }), () => { }); + } + } + } + /** + * Reconnect presence event engine after network issues. + * + * @param parameters - List of channels and groups where `join` event should be sent. + * + * @internal + */ + presenceReconnect(parameters) { + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Presence reconnect with parameters:', + })); + if (this.presenceEventEngine) + this.presenceEventEngine.reconnect(); + else { + this.heartbeat(Object.assign(Object.assign({ channels: parameters.channels, channelGroups: parameters.groups }, (this._configuration.maintainPresenceState && { state: this.presenceState })), { heartbeat: this._configuration.getPresenceTimeout() }), () => { }); + } + } + } + // endregion + // region Leave + /** + * Announce user `leave` on specified list of channels and groups. + * + * @internal + * + * @param parameters - List of channels and groups where `leave` event should be sent. + */ + leave(parameters) { + var _a, _b, _c; + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Leave with parameters:', + })); + if (parameters && ((_a = parameters.channels) !== null && _a !== void 0 ? _a : []).length === 0 && ((_b = parameters.groups) !== null && _b !== void 0 ? _b : []).length === 0) { + this.logger.trace('PubNub', "Ignoring 'leave' announcement request."); + return; + } + if (this.presenceEventEngine) + (_c = this.presenceEventEngine) === null || _c === void 0 ? void 0 : _c.leave(parameters); + else + this.makeUnsubscribe({ channels: parameters.channels, channelGroups: parameters.groups }, () => { }); + } + } + /** + * Announce user `leave` on all subscribed channels. + * + * @internal + * + * @param parameters - List of channels and groups where `leave` event should be sent. + */ + leaveAll(parameters = {}) { + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Leave all with parameters:', + })); + if (this.presenceEventEngine) + this.presenceEventEngine.leaveAll(!!parameters.isOffline); + else if (!parameters.isOffline) + this.makeUnsubscribe({ channels: parameters.channels, channelGroups: parameters.groups }, () => { }); + } + } + /** + * Announce user `leave` on disconnection. + * + * @internal + * + * @param parameters - List of channels and groups where `leave` event should be sent. + */ + presenceDisconnect(parameters) { + { + this.logger.trace('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: 'Presence disconnect parameters:', + })); + if (this.presenceEventEngine) + this.presenceEventEngine.disconnect(!!parameters.isOffline); + else if (!parameters.isOffline) + this.makeUnsubscribe({ channels: parameters.channels, channelGroups: parameters.groups }, () => { }); + } + } + /** + * Grant token permission. + * + * Generate an access token with requested permissions. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous grant token response or `void` in case if `callback` provided. + */ + grantToken(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('Grant Token error: PAM module disabled'); + }); + } + /** + * Revoke token permission. + * + * @param token - Access token for which permissions should be revoked. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous revoke token response or `void` in case if `callback` provided. + */ + revokeToken(token, callback) { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('Revoke Token error: PAM module disabled'); + }); + } + // endregion + // region Token Manipulation + /** + * Get a current access token. + * + * @returns Previously configured access token using {@link setToken} method. + */ + get token() { + return this.tokenManager && this.tokenManager.getToken(); + } + /** + * Get a current access token. + * + * @returns Previously configured access token using {@link setToken} method. + */ + getToken() { + return this.token; + } + /** + * Set current access token. + * + * @param token - New access token which should be used with next REST API endpoint calls. + */ + set token(token) { + if (this.tokenManager) + this.tokenManager.setToken(token); + if (this.onAuthenticationChange) + this.onAuthenticationChange(token); + } + /** + * Set current access token. + * + * @param token - New access token which should be used with next REST API endpoint calls. + */ + setToken(token) { + this.logger.debug('PubNub', 'Access token updated.'); + this.token = token; + } + /** + * Parse access token. + * + * Parse token to see what permissions token owner has. + * + * @param token - Token which should be parsed. + * + * @returns Token's permissions information for the resources. + */ + parseToken(token) { + this.logger.debug('PubNub', 'Parse access token.'); + return this.tokenManager && this.tokenManager.parseToken(token); + } + /** + * Grant auth key(s) permission. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous grant auth key(s) permissions or `void` in case if `callback` provided. + * + * @deprecated Use {@link grantToken} and {@link setToken} methods instead. + */ + grant(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('Grant error: PAM module disabled'); + }); + } + /** + * Audit auth key(s) permission. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @deprecated + * + * @deprecated Use {@link grantToken} and {@link setToken} methods instead. + */ + audit(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('Grant Permissions error: PAM module disabled'); + }); + } + // endregion + // endregion + // endregion + // -------------------------------------------------------- + // ------------------- App Context API -------------------- + // -------------------------------------------------------- + // region App Context API + /** + * PubNub App Context API group. + */ + get objects() { + return this._objects; + } + // -------------------------------------------------------- + // -------------------- DataSync API --------------------- + // -------------------------------------------------------- + // region DataSync API + /** + * PubNub DataSync API group. + */ + get dataSync() { + return this._dataSync; + } + /** + Fetch a paginated list of User objects. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all User objects response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.getAllUUIDMetadata getAllUUIDMetadata} method instead. + */ + fetchUsers(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'fetchUsers' is deprecated. Use 'pubnub.objects.getAllUUIDMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, + details: `Fetch all User objects with parameters:`, + })); + return this.objects._getAllUUIDMetadata(parametersOrCallback, callback); + } + }); + } + /** + * Fetch User object for a currently configured PubNub client `uuid`. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get User object response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.getUUIDMetadata getUUIDMetadata} method instead. + */ + fetchUser(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'fetchUser' is deprecated. Use 'pubnub.objects.getUUIDMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' + ? { uuid: this.userId } + : parametersOrCallback, + details: `Fetch${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} User object with parameters:`, + })); + return this.objects._getUUIDMetadata(parametersOrCallback, callback); + } + }); + } + /** + * Create a User object. + * + * @param parameters - Request configuration parameters. Will create a User object for a currently + * configured PubNub client `uuid` if not set. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create User object response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.setUUIDMetadata setUUIDMetadata} method instead. + */ + createUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'createUser' is deprecated. Use 'pubnub.objects.setUUIDMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Create User object with parameters:`, + })); + return this.objects._setUUIDMetadata(parameters, callback); + } + }); + } + /** + * Update a User object. + * + * @param parameters - Request configuration parameters. Will update a User object for a currently + * configured PubNub client `uuid` if not set. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update User object response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.setUUIDMetadata setUUIDMetadata} method instead. + */ + updateUser(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.warn('PubNub', "'updateUser' is deprecated. Use 'pubnub.objects.setUUIDMetadata' instead."); + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Update User object with parameters:`, + })); + return this.objects._setUUIDMetadata(parameters, callback); + } + }); + } + /** + * Remove a specific User object. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous User object removes response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.removeUUIDMetadata removeUUIDMetadata} method instead. + */ + removeUser(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'removeUser' is deprecated. Use 'pubnub.objects.removeUUIDMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' + ? { uuid: this.userId } + : parametersOrCallback, + details: `Remove${!parametersOrCallback || typeof parametersOrCallback === 'function' ? ' current' : ''} User object with parameters:`, + })); + return this.objects._removeUUIDMetadata(parametersOrCallback, callback); + } + }); + } + /** + * Fetch a paginated list of Space objects. + * + * @param [parametersOrCallback] - Request configuration parameters or callback from overload. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get all Space objects response or `void` in case if `callback` + * provided. + * + * @deprecated Use {@link PubNubCore#objects.getAllChannelMetadata getAllChannelMetadata} method instead. + */ + fetchSpaces(parametersOrCallback, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'fetchSpaces' is deprecated. Use 'pubnub.objects.getAllChannelMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: !parametersOrCallback || typeof parametersOrCallback === 'function' ? {} : parametersOrCallback, + details: `Fetch all Space objects with parameters:`, + })); + return this.objects._getAllChannelMetadata(parametersOrCallback, callback); + } + }); + } + /** + * Fetch a specific Space object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get Space object response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.getChannelMetadata getChannelMetadata} method instead. + */ + fetchSpace(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'fetchSpace' is deprecated. Use 'pubnub.objects.getChannelMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Fetch Space object with parameters:`, + })); + return this.objects._getChannelMetadata(parameters, callback); + } + }); + } + /** + * Create specific Space object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous create Space object response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.setChannelMetadata setChannelMetadata} method instead. + */ + createSpace(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'createSpace' is deprecated. Use 'pubnub.objects.setChannelMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Create Space object with parameters:`, + })); + return this.objects._setChannelMetadata(parameters, callback); + } + }); + } + /** + * Update specific Space object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update Space object response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.setChannelMetadata setChannelMetadata} method instead. + */ + updateSpace(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'updateSpace' is deprecated. Use 'pubnub.objects.setChannelMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Update Space object with parameters:`, + })); + return this.objects._setChannelMetadata(parameters, callback); + } + }); + } + /** + * Remove a specific Space object. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous Space object remove response or `void` in case if `callback` + * provided. + * + * @deprecated Use {@link PubNubCore#objects.removeChannelMetadata removeChannelMetadata} method instead. + */ + removeSpace(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'removeSpace' is deprecated. Use 'pubnub.objects.removeChannelMetadata' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove Space object with parameters:`, + })); + return this.objects._removeChannelMetadata(parameters, callback); + } + }); + } + /** + * Fetch a paginated list of specific Space members or specific User memberships. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get specific Space members or specific User memberships response or + * `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.getChannelMembers getChannelMembers} or + * {@link PubNubCore#objects.getMemberships getMemberships} methods instead. + */ + fetchMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + return this.objects.fetchMemberships(parameters, callback); + }); + } + /** + * Add members to specific Space or memberships specific User. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous add members to specific Space or memberships specific User response or + * `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.setChannelMembers setChannelMembers} or + * {@link PubNubCore#objects.setMemberships setMemberships} methods instead. + */ + addMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + return this.objects.addMemberships(parameters, callback); + }); + } + /** + * Update specific Space members or User memberships. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous update Space members or User memberships response or `void` in case + * if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.setChannelMembers setChannelMembers} or + * {@link PubNubCore#objects.setMemberships setMemberships} methods instead. + */ + updateMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.warn('PubNub', "'addMemberships' is deprecated. Use 'pubnub.objects.setChannelMembers' or 'pubnub.objects.setMemberships'" + + ' instead.'); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Update memberships with parameters:`, + })); + return this.objects.addMemberships(parameters, callback); + } + }); + } + /** + * Remove User membership. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous memberships modification response or `void` in case if `callback` provided. + * + * @deprecated Use {@link PubNubCore#objects.removeMemberships removeMemberships} or + * {@link PubNubCore#objects.removeChannelMembers removeChannelMembers} methods instead from `objects` API group. + */ + removeMemberships(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + var _a, _b, _c; + { + this.logger.warn('PubNub', "'removeMemberships' is deprecated. Use 'pubnub.objects.removeMemberships' or" + + " 'pubnub.objects.removeChannelMembers' instead."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Remove memberships with parameters:`, + })); + if ('spaceId' in parameters) { + const spaceParameters = parameters; + const requestParameters = { + channel: (_a = spaceParameters.spaceId) !== null && _a !== void 0 ? _a : spaceParameters.channel, + uuids: (_b = spaceParameters.userIds) !== null && _b !== void 0 ? _b : spaceParameters.uuids, + limit: 0, + }; + if (callback) + return this.objects.removeChannelMembers(requestParameters, callback); + return this.objects.removeChannelMembers(requestParameters); + } + const userParameters = parameters; + const requestParameters = { + uuid: userParameters.userId, + channels: (_c = userParameters.spaceIds) !== null && _c !== void 0 ? _c : userParameters.channels, + limit: 0, + }; + if (callback) + return this.objects.removeMemberships(requestParameters, callback); + return this.objects.removeMemberships(requestParameters); + } + }); + } + // endregion + // endregion + // -------------------------------------------------------- + // ----------------- Channel Groups API ------------------- + // -------------------------------------------------------- + // region Channel Groups API + /** + * PubNub Channel Groups API group. + */ + get channelGroups() { + return this._channelGroups; + } + // endregion + // -------------------------------------------------------- + // ---------------- Push Notifications API ----------------- + // -------------------------------------------------------- + // region Push Notifications API + /** + * PubNub Push Notifications API group. + */ + get push() { + return this._push; + } + /** + * Share file to a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous file sharing response or `void` in case if `callback` provided. + */ + sendFile(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + if (!this._configuration.PubNubFile) + throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Send file with parameters:`, + })); + const sendFileRequest = new SendFileRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, PubNubFile: this._configuration.PubNubFile, fileUploadPublishRetryLimit: this._configuration.fileUploadPublishRetryLimit, file: parameters.file, sendRequest: this.sendRequest.bind(this), publishFile: this.publishFile.bind(this), crypto: this._configuration.getCryptoModule(), cryptography: this.cryptography ? this.cryptography : undefined })); + const status = { + error: false, + operation: RequestOperation$1.PNPublishFileOperation, + category: StatusCategory$1.PNAcknowledgmentCategory, + statusCode: 0, + }; + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Send file success. File shared with ${response.id} ID.`); + }; + return sendFileRequest + .process() + .then((response) => { + status.statusCode = response.status; + logResponse(response); + if (callback) + return callback(status, response); + return response; + }) + .catch((error) => { + let errorStatus; + if (error instanceof PubNubError) + errorStatus = error.status; + else if (error instanceof PubNubAPIError) + errorStatus = error.toStatus(status.operation); + this.logger.error('PubNub', () => ({ + messageType: 'error', + message: new PubNubError('File sending error. Check status for details', errorStatus), + })); + // Notify callback (if possible). + if (callback && errorStatus) + callback(errorStatus, null); + throw new PubNubError('REST API request processing error. Check status for details', errorStatus); + }); + } + }); + } + /** + * Publish file message to a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous publish file message response or `void` in case if `callback` provided. + */ + publishFile(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + if (!this._configuration.PubNubFile) + throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Publish file message with parameters:`, + })); + const request = new PublishFileMessageRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, crypto: this._configuration.getCryptoModule() })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Publish file message success. File message published with timetoken: ${response.timetoken}`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + * Retrieve list of shared files in specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous shared files list response or `void` in case if `callback` provided. + */ + listFiles(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `List files with parameters:`, + })); + const request = new FilesListRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `List files success. There are ${response.count} uploaded files.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + // endregion + // region Get Download Url + /** + * Get file download Url. + * + * @param parameters - Request configuration parameters. + * + * @returns File download Url. + */ + getFileUrl(parameters) { + var _a; + { + const request = this.transport.request(new GetFileDownloadUrlRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })).request()); + const query = (_a = request.queryParameters) !== null && _a !== void 0 ? _a : {}; + const queryString = Object.keys(query) + .map((key) => { + const queryValue = query[key]; + if (!Array.isArray(queryValue)) + return `${key}=${encodeString(queryValue)}`; + return queryValue.map((value) => `${key}=${encodeString(value)}`).join('&'); + }) + .join('&'); + return `${request.origin}${request.path}?${queryString}`; + } + } + /** + * Download a shared file from a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous download shared file response or `void` in case if `callback` provided. + */ + downloadFile(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + if (!this._configuration.PubNubFile) + throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform."); + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Download file with parameters:`, + })); + const request = new DownloadFileRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet, PubNubFile: this._configuration.PubNubFile, cryptography: this.cryptography ? this.cryptography : undefined, crypto: this._configuration.getCryptoModule() })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Download file success.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return (yield this.sendRequest(request).then((response) => { + logResponse(response); + return response; + })); + } + }); + } + /** + * Delete a shared file from a specific channel. + * + * @param parameters - Request configuration parameters. + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous delete shared file response or `void` in case if `callback` provided. + */ + deleteFile(parameters, callback) { + return __awaiter(this, void 0, void 0, function* () { + { + this.logger.debug('PubNub', () => ({ + messageType: 'object', + message: Object.assign({}, parameters), + details: `Delete file with parameters:`, + })); + const request = new DeleteFileRequest(Object.assign(Object.assign({}, parameters), { keySet: this._configuration.keySet })); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Delete file success. Deleted file with ${parameters.id} ID.`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + } + }); + } + /** + Get current high-precision timetoken. + * + * @param [callback] - Request completion handler callback. + * + * @returns Asynchronous get current timetoken response or `void` in case if `callback` provided. + */ + time(callback) { + return __awaiter(this, void 0, void 0, function* () { + this.logger.debug('PubNub', 'Get service time.'); + const request = new TimeRequest(); + const logResponse = (response) => { + if (!response) + return; + this.logger.debug('PubNub', `Get service time success. Current timetoken: ${response.timetoken}`); + }; + if (callback) + return this.sendRequest(request, (status, response) => { + logResponse(response); + callback(status, response); + }); + return this.sendRequest(request).then((response) => { + logResponse(response); + return response; + }); + }); + } + // endregion + // -------------------------------------------------------- + // -------------------- Event emitter --------------------- + // -------------------------------------------------------- + // region Event emitter + /** + * Emit received a status update. + * + * Use global and local event dispatchers to deliver a status object. + * + * @param status - Status object which should be emitted through the listeners. + * + * @internal + */ + emitStatus(status) { + var _a; + (_a = this.eventDispatcher) === null || _a === void 0 ? void 0 : _a.handleStatus(status); + } + /** + * Emit receiver real-time event. + * + * Use global and local event dispatchers to deliver an event object. + * + * @param cursor - Next subscription loop timetoken. + * @param event - Event object which should be emitted through the listeners. + * + * @internal + */ + emitEvent(cursor, event) { + var _a; + { + if (this._globalSubscriptionSet) + this._globalSubscriptionSet.handleEvent(cursor, event); + (_a = this.eventDispatcher) === null || _a === void 0 ? void 0 : _a.handleEvent(event); + Object.values(this.eventHandleCapable).forEach((eventHandleCapable) => { + if (eventHandleCapable !== this._globalSubscriptionSet) + eventHandleCapable.handleEvent(cursor, event); + }); + } + } + /** + * Set a connection status change event handler. + * + * @param listener - Listener function, which will be called each time when the connection status changes. + */ + set onStatus(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onStatus = listener; + } + } + /** + * Set a new message handler. + * + * @param listener - Listener function, which will be called each time when a new message + * is received from the real-time network. + */ + set onMessage(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onMessage = listener; + } + } + /** + * Set a new presence events handler. + * + * @param listener - Listener function, which will be called each time when a new + * presence event is received from the real-time network. + */ + set onPresence(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onPresence = listener; + } + } + /** + * Set a new signal handler. + * + * @param listener - Listener function, which will be called each time when a new signal + * is received from the real-time network. + */ + set onSignal(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onSignal = listener; + } + } + /** + * Set a new app context event handler. + * + * @param listener - Listener function, which will be called each time when a new + * app context event is received from the real-time network. + */ + set onObjects(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onObjects = listener; + } + } + /** + * Set a new message reaction event handler. + * + * @param listener - Listener function, which will be called each time when a + * new message reaction event is received from the real-time network. + */ + set onMessageAction(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onMessageAction = listener; + } + } + /** + * Set a new file handler. + * + * @param listener - Listener function, which will be called each time when a new file + * is received from the real-time network. + */ + set onFile(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onFile = listener; + } + } + /** + * Set a new DataSync event handler. + * + * @param listener - Listener function, which will be called each time when a new + * DataSync event is received from the real-time network. + */ + set onDataSync(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.onDataSync = listener; + } + } + /** + * Set events handler. + * + * @param listener - Events listener configuration object, which lets specify handlers for multiple + * types of events. + */ + addListener(listener) { + { + if (this.eventDispatcher) { + this.eventDispatcher.addListener(listener); + } + } + } + /** + * Remove real-time event listener. + * + * @param listener - Event listener configuration, which should be removed from the list of notified + * listeners. **Important:** Should be the same object which has been passed to the + * {@link addListener}. + */ + removeListener(listener) { + { + if (this.eventDispatcher) + this.eventDispatcher.removeListener(listener); + } + } + /** + * Clear all real-time event listeners. + */ + removeAllListeners() { + { + if (this.eventDispatcher) + this.eventDispatcher.removeAllListeners(); + } + } + // endregion + // -------------------------------------------------------- + // ------------------ Cryptography API -------------------- + // -------------------------------------------------------- + // region Cryptography + // region Common + /** + * Encrypt data. + * + * @param data - Stringified data which should be encrypted using `CryptoModule`. + * @param [customCipherKey] - Cipher key which should be used to encrypt data. **Deprecated:** + * use {@link Configuration#cryptoModule|cryptoModule} instead. + * + * @returns Data encryption result as a string. + * + * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. + */ + encrypt(data, customCipherKey) { + this.logger.warn('PubNub', "'encrypt' is deprecated. Use cryptoModule instead."); + const cryptoModule = this._configuration.getCryptoModule(); + if (!customCipherKey && cryptoModule && typeof data === 'string') { + const encrypted = cryptoModule.encrypt(data); + return typeof encrypted === 'string' ? encrypted : encode(encrypted); + } + if (!this.crypto) + throw new Error('Encryption error: cypher key not set'); + { + return this.crypto.encrypt(data, customCipherKey); + } + } + /** + * Decrypt data. + * + * @param data - Stringified data which should be encrypted using `CryptoModule`. + * @param [customCipherKey] - Cipher key which should be used to decrypt data. **Deprecated:** + * use {@link Configuration#cryptoModule|cryptoModule} instead. + * + * @returns Data decryption result as an object. + * + * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. + */ + decrypt(data, customCipherKey) { + this.logger.warn('PubNub', "'decrypt' is deprecated. Use cryptoModule instead."); + const cryptoModule = this._configuration.getCryptoModule(); + if (!customCipherKey && cryptoModule) { + const decrypted = cryptoModule.decrypt(data); + return decrypted instanceof ArrayBuffer ? JSON.parse(new TextDecoder().decode(decrypted)) : decrypted; + } + if (!this.crypto) + throw new Error('Decryption error: cypher key not set'); + { + return this.crypto.decrypt(data, customCipherKey); + } + } + /** + * Encrypt file content. + * + * @param keyOrFile - Cipher key which should be used to encrypt data or file which should be + * encrypted using `CryptoModule`. + * @param [file] - File which should be encrypted using legacy cryptography. + * + * @returns Asynchronous file encryption result. + * + * @throws Error if a source file isn't provided. + * @throws File constructor not provided. + * @throws Crypto module is missing (if non-legacy flow used). + * + * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. + */ + encryptFile(keyOrFile, file) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + if (typeof keyOrFile !== 'string') + file = keyOrFile; + if (!file) + throw new Error('File encryption error. Source file is missing.'); + if (!this._configuration.PubNubFile) + throw new Error('File encryption error. File constructor not configured.'); + if (typeof keyOrFile !== 'string' && !this._configuration.getCryptoModule()) + throw new Error('File encryption error. Crypto module not configured.'); + if (typeof keyOrFile === 'string') { + if (!this.cryptography) + throw new Error('File encryption error. File encryption not available'); + return this.cryptography.encryptFile(keyOrFile, file, this._configuration.PubNubFile); + } + return (_a = this._configuration.getCryptoModule()) === null || _a === void 0 ? void 0 : _a.encryptFile(file, this._configuration.PubNubFile); + }); + } + /** + * Decrypt file content. + * + * @param keyOrFile - Cipher key which should be used to decrypt data or file which should be + * decrypted using `CryptoModule`. + * @param [file] - File which should be decrypted using legacy cryptography. + * + * @returns Asynchronous file decryption result. + * + * @throws Error if source file isn't provided. + * @throws File constructor not provided. + * @throws Crypto module is missing (if non-legacy flow used). + * + * @deprecated Use {@link Configuration#cryptoModule|cryptoModule} instead. + */ + decryptFile(keyOrFile, file) { + return __awaiter(this, void 0, void 0, function* () { + var _a; + if (typeof keyOrFile !== 'string') + file = keyOrFile; + if (!file) + throw new Error('File encryption error. Source file is missing.'); + if (!this._configuration.PubNubFile) + throw new Error('File decryption error. File constructor' + ' not configured.'); + if (typeof keyOrFile === 'string' && !this._configuration.getCryptoModule()) + throw new Error('File decryption error. Crypto module not configured.'); + if (typeof keyOrFile === 'string') { + if (!this.cryptography) + throw new Error('File decryption error. File decryption not available'); + return this.cryptography.decryptFile(keyOrFile, file, this._configuration.PubNubFile); + } + return (_a = this._configuration.getCryptoModule()) === null || _a === void 0 ? void 0 : _a.decryptFile(file, this._configuration.PubNubFile); + }); + } + } + /** + * {@link ArrayBuffer} to {@link string} decoder. + * + * @internal + */ + PubNubCore.decoder = new TextDecoder(); + // -------------------------------------------------------- + // ----------------------- Static ------------------------- + // -------------------------------------------------------- + // region Static + /** + * Type of REST API endpoint which reported status. + */ + PubNubCore.OPERATIONS = RequestOperation$1; + /** + * API call status category. + */ + PubNubCore.CATEGORIES = StatusCategory$1; + /** + * Enum with API endpoint groups which can be used with retry policy to set up exclusions (which shouldn't be + * retried). + */ + PubNubCore.Endpoint = Endpoint; + /** + * Exponential retry policy constructor. + */ + PubNubCore.ExponentialRetryPolicy = RetryPolicy.ExponentialRetryPolicy; + /** + * Linear retry policy constructor. + */ + PubNubCore.LinearRetryPolicy = RetryPolicy.LinearRetryPolicy; + /** + * Disabled / inactive retry policy. + * + * **Note:** By default `ExponentialRetryPolicy` is set for subscribe requests and this one can be used to disable + * retry policy for all requests (setting `undefined` for retry configuration will set default policy). + */ + PubNubCore.NoneRetryPolicy = RetryPolicy.None; + /** + * Available minimum log levels. + */ + PubNubCore.LogLevel = LogLevel; + + /** + * Cbor decoder module. + * + * @internal + */ + /** + * CBOR data decoder. + * + * @internal + */ + class Cbor { + constructor(decode, base64ToBinary) { + this.decode = decode; + this.base64ToBinary = base64ToBinary; + } + /** + * Decode CBOR base64-encoded object. + * + * @param tokenString - Base64-encoded token. + * + * @returns Token object decoded from CBOR. + */ + decodeToken(tokenString) { + let padding = ''; + if (tokenString.length % 4 === 3) + padding = '='; + else if (tokenString.length % 4 === 2) + padding = '=='; + const cleaned = tokenString.replace(/-/gi, '+').replace(/_/gi, '/') + padding; + const result = this.decode(this.base64ToBinary(cleaned)); + return typeof result === 'object' ? result : undefined; + } + } + + /* eslint no-bitwise: ["error", { "allow": ["~", "&", ">>"] }] */ + /* global navigator */ + /** + * PubNub client for browser platform. + */ + class PubNub extends PubNubCore { + /** + * Create and configure the PubNub client core. + * + * @param configuration - User-provided PubNub client configuration. + * + * @returns Configured and ready to use PubNub client. + */ + constructor(configuration) { + var _a; + const sharedWorkerRequested = configuration.subscriptionWorkerUrl !== undefined; + const configurationCopy = setDefaults(configuration); + const platformConfiguration = Object.assign(Object.assign({}, configurationCopy), { sdkFamily: 'Web' }); + platformConfiguration.PubNubFile = PubNubFile; + // Prepare full client configuration. + const clientConfiguration = makeConfiguration(platformConfiguration, (cryptoConfiguration) => { + if (!cryptoConfiguration.cipherKey) + return undefined; + { + const cryptoModule = new WebCryptoModule({ + default: new LegacyCryptor(Object.assign(Object.assign({}, cryptoConfiguration), (!cryptoConfiguration.logger ? { logger: clientConfiguration.logger() } : {}))), + cryptors: [new AesCbcCryptor({ cipherKey: cryptoConfiguration.cipherKey })], + }); + return cryptoModule; + } + }); + if (configuration.subscriptionWorkerLogVerbosity) + configuration.subscriptionWorkerLogLevel = LogLevel.Debug; + else if (configuration.subscriptionWorkerLogLevel === undefined) + configuration.subscriptionWorkerLogLevel = LogLevel.None; + if (configuration.subscriptionWorkerLogVerbosity !== undefined) { + clientConfiguration + .logger() + .warn('Configuration', "'subscriptionWorkerLogVerbosity' is deprecated. Use 'subscriptionWorkerLogLevel' instead."); + } + { + // Ensure that the logger has been passed to the user-provided crypto module. + if (clientConfiguration.getCryptoModule()) + clientConfiguration.getCryptoModule().logger = clientConfiguration.logger(); + } + // Prepare Token manager. + let tokenManager; + { + tokenManager = new TokenManager(new Cbor((arrayBuffer) => stringifyBufferKeys(CborReader.decode(arrayBuffer)), decode)); + } + // Legacy crypto (legacy data encryption / decryption and request signature support). + let crypto; + { + if (clientConfiguration.getCipherKey() || clientConfiguration.secretKey) { + crypto = new Crypto({ + secretKey: clientConfiguration.secretKey, + cipherKey: clientConfiguration.getCipherKey(), + useRandomIVs: clientConfiguration.getUseRandomIVs(), + customEncrypt: clientConfiguration.getCustomEncrypt(), + customDecrypt: clientConfiguration.getCustomDecrypt(), + logger: clientConfiguration.logger(), + }); + } + } + // Settings change handlers + let heartbeatIntervalChangeHandler = () => { }; + let presenceStateChangeHandler = () => { }; + let authenticationChangeHandler = () => { }; + let userIdChangeHandler = () => { }; + let cryptography; + cryptography = new WebCryptography(); + // Setup transport provider. + let transport = new WebTransport(clientConfiguration.logger(), platformConfiguration.transport); + { + if (configurationCopy.subscriptionWorkerUrl) { + try { + // Inject subscription worker into the transport provider stack. + const middleware = new SubscriptionWorkerMiddleware({ + clientIdentifier: clientConfiguration._instanceId, + subscriptionKey: clientConfiguration.subscribeKey, + userId: clientConfiguration.getUserId(), + workerUrl: configurationCopy.subscriptionWorkerUrl, + sdkVersion: clientConfiguration.getVersion(), + heartbeatInterval: clientConfiguration.getHeartbeatInterval(), + announceSuccessfulHeartbeats: clientConfiguration.announceSuccessfulHeartbeats, + announceFailedHeartbeats: clientConfiguration.announceFailedHeartbeats, + workerOfflineClientsCheckInterval: platformConfiguration.subscriptionWorkerOfflineClientsCheckInterval, + workerUnsubscribeOfflineClients: platformConfiguration.subscriptionWorkerUnsubscribeOfflineClients, + workerLogLevel: platformConfiguration.subscriptionWorkerLogLevel, + tokenManager, + transport, + logger: clientConfiguration.logger(), + }); + presenceStateChangeHandler = (state) => middleware.onPresenceStateChange(state); + heartbeatIntervalChangeHandler = (interval) => middleware.onHeartbeatIntervalChange(interval); + authenticationChangeHandler = (auth) => middleware.onTokenChange(auth); + userIdChangeHandler = (userId) => middleware.onUserIdChange(userId); + transport = middleware; + if (configurationCopy.subscriptionWorkerUnsubscribeOfflineClients && + typeof window !== 'undefined' && + window.addEventListener) { + window.addEventListener('pagehide', (event) => { + if (!event.persisted) + middleware.terminate(); + }, { once: true }); + } + } + catch (e) { + clientConfiguration.logger().error('PubNub', () => ({ + messageType: 'error', + message: e, + })); + } + } + else if (sharedWorkerRequested) { + clientConfiguration + .logger() + .warn('PubNub', 'SharedWorker not supported in this browser. Fallback to the original transport.'); + } + } + const transportMiddleware = new PubNubMiddleware({ + clientConfiguration, + tokenManager, + transport, + }); + super({ + configuration: clientConfiguration, + transport: transportMiddleware, + cryptography, + tokenManager, + crypto, + }); + /** + * PubNub File constructor. + */ + this.File = PubNubFile; + this.onHeartbeatIntervalChange = heartbeatIntervalChangeHandler; + this.onAuthenticationChange = authenticationChangeHandler; + this.onPresenceStateChange = presenceStateChangeHandler; + this.onUserIdChange = userIdChangeHandler; + { + if (transport instanceof SubscriptionWorkerMiddleware) { + transport.emitStatus = this.emitStatus.bind(this); + const disconnect = this.disconnect.bind(this); + this.disconnect = (isOffline) => { + transport.disconnect(); + disconnect(); + }; + } + } + // `window` is unavailable in DOM-less contexts (e.g. MV3 service workers); only attach network + // listeners when a `window` with event support actually exists. + if (((_a = configuration.listenToBrowserNetworkEvents) !== null && _a !== void 0 ? _a : true) && + typeof window !== 'undefined' && + window.addEventListener) { + window.addEventListener('offline', () => { + this.networkDownDetected(); + }); + window.addEventListener('online', () => { + this.networkUpDetected(); + }); + } + } + networkDownDetected() { + this.logger.debug('PubNub', 'Network down detected'); + this.emitStatus({ category: PubNub.CATEGORIES.PNNetworkDownCategory }); + if (this._configuration.restore) + this.disconnect(true); + else + this.destroy(true); + } + networkUpDetected() { + this.logger.debug('PubNub', 'Network up detected'); + this.emitStatus({ category: PubNub.CATEGORIES.PNNetworkUpCategory }); + this.reconnect(); + } + } + /** + * Data encryption / decryption module constructor. + */ + PubNub.CryptoModule = WebCryptoModule ; + + return PubNub; + +})); diff --git a/dist/web/pubnub.min.js b/dist/web/pubnub.min.js index cddf60b6f..2fca410b4 100644 --- a/dist/web/pubnub.min.js +++ b/dist/web/pubnub.min.js @@ -1,2 +1,2 @@ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).PubNub=t()}(this,(function(){"use strict";var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function t(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var s={exports:{}};!function(t){!function(e,s){var n=Math.pow(2,-24),i=Math.pow(2,32),r=Math.pow(2,53);var a={encode:function(e){var t,n=new ArrayBuffer(256),a=new DataView(n),o=0;function c(e){for(var s=n.byteLength,i=o+e;s>2,u=0;u>6),i.push(128|63&a)):a<55296?(i.push(224|a>>12),i.push(128|a>>6&63),i.push(128|63&a)):(a=(1023&a)<<10,a|=1023&t.charCodeAt(++n),a+=65536,i.push(240|a>>18),i.push(128|a>>12&63),i.push(128|a>>6&63),i.push(128|63&a))}return d(3,i.length),h(i);default:var p;if(Array.isArray(t))for(d(4,p=t.length),n=0;n>5!==e)throw"Invalid indefinite length element";return s}function y(e,t){for(var s=0;s>10),e.push(56320|1023&n))}}"function"!=typeof t&&(t=function(e){return e}),"function"!=typeof r&&(r=function(){return s});var m=function e(){var i,d,m=l(),f=m>>5,v=31&m;if(7===f)switch(v){case 25:return function(){var e=new ArrayBuffer(4),t=new DataView(e),s=h(),i=32768&s,r=31744&s,a=1023&s;if(31744===r)r=261120;else if(0!==r)r+=114688;else if(0!==a)return a*n;return t.setUint32(0,i<<16|r<<13|a<<13),t.getFloat32(0)}();case 26:return c(a.getFloat32(o),4);case 27:return c(a.getFloat64(o),8)}if((d=g(v))<0&&(f<2||6=0;)S+=d,O.push(u(d));var j=new Uint8Array(S),w=0;for(i=0;i=0;)y(k,d);else y(k,d);return String.fromCharCode.apply(null,k);case 4:var C;if(d<0)for(C=[];!p();)C.push(e());else for(C=new Array(d),i=0;ie.toString())).join(", ")}]}`}}a.encoder=new TextEncoder,a.decoder=new TextDecoder;class o{static create(e){return new o(e)}constructor(e){let t,s,n,i;if(e instanceof File)i=e,n=e.name,s=e.type,t=e.size;else if("data"in e){const r=e.data;s=e.mimeType,n=e.name,i=new File([r],n,{type:s}),t=i.size}if(void 0===i)throw new Error("Couldn't construct a file out of supplied options.");if(void 0===n)throw new Error("Couldn't guess filename out of the options. Please provide one.");t&&(this.contentLength=t),this.mimeType=s,this.data=i,this.name=n}toBuffer(){return r(this,void 0,void 0,(function*(){throw new Error("This feature is only supported in Node.js environments.")}))}toArrayBuffer(){return r(this,void 0,void 0,(function*(){return new Promise(((e,t)=>{const s=new FileReader;s.addEventListener("load",(()=>{if(s.result instanceof ArrayBuffer)return e(s.result)})),s.addEventListener("error",(()=>t(s.error))),s.readAsArrayBuffer(this.data)}))}))}toString(){return r(this,void 0,void 0,(function*(){return new Promise(((e,t)=>{const s=new FileReader;s.addEventListener("load",(()=>{if("string"==typeof s.result)return e(s.result)})),s.addEventListener("error",(()=>{t(s.error)})),s.readAsBinaryString(this.data)}))}))}toStream(){return r(this,void 0,void 0,(function*(){throw new Error("This feature is only supported in Node.js environments.")}))}toFile(){return r(this,void 0,void 0,(function*(){return this.data}))}toFileUri(){return r(this,void 0,void 0,(function*(){throw new Error("This feature is only supported in React Native environments.")}))}toBlob(){return r(this,void 0,void 0,(function*(){return this.data}))}}o.supportsBlob="undefined"!=typeof Blob,o.supportsFile="undefined"!=typeof File,o.supportsBuffer=!1,o.supportsStream=!1,o.supportsString=!0,o.supportsArrayBuffer=!0,o.supportsEncryptFile=!0,o.supportsFileUri=!1;function c(e){const t=e.replace(/==?$/,""),s=Math.floor(t.length/4*3),n=new ArrayBuffer(s),i=new Uint8Array(n);let r=0;function a(){const e=t.charAt(r++),s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(e);if(-1===s)throw new Error(`Illegal character at ${r}: ${t.charAt(r-1)}`);return s}for(let e=0;e>4,c=(15&s)<<4|n>>2,u=(3&n)<<6|r;i[e]=o,64!=n&&(i[e+1]=c),64!=r&&(i[e+2]=u)}return n}function u(e){let t="";const s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",n=new Uint8Array(e),i=n.byteLength,r=i%3,a=i-r;let o,c,u,l,h;for(let e=0;e>18,c=(258048&h)>>12,u=(4032&h)>>6,l=63&h,t+=s[o]+s[c]+s[u]+s[l];return 1==r?(h=n[a],o=(252&h)>>2,c=(3&h)<<4,t+=s[o]+s[c]+"=="):2==r&&(h=n[a]<<8|n[a+1],o=(64512&h)>>10,c=(1008&h)>>4,u=(15&h)<<2,t+=s[o]+s[c]+s[u]+"="),t}var l;!function(e){e.PNNetworkIssuesCategory="PNNetworkIssuesCategory",e.PNTimeoutCategory="PNTimeoutCategory",e.PNCancelledCategory="PNCancelledCategory",e.PNBadRequestCategory="PNBadRequestCategory",e.PNAccessDeniedCategory="PNAccessDeniedCategory",e.PNValidationErrorCategory="PNValidationErrorCategory",e.PNAcknowledgmentCategory="PNAcknowledgmentCategory",e.PNMalformedResponseCategory="PNMalformedResponseCategory",e.PNServerErrorCategory="PNServerErrorCategory",e.PNUnknownCategory="PNUnknownCategory",e.PNNetworkUpCategory="PNNetworkUpCategory",e.PNNetworkDownCategory="PNNetworkDownCategory",e.PNReconnectedCategory="PNReconnectedCategory",e.PNConnectedCategory="PNConnectedCategory",e.PNSubscriptionChangedCategory="PNSubscriptionChangedCategory",e.PNRequestMessageCountExceededCategory="PNRequestMessageCountExceededCategory",e.PNDisconnectedCategory="PNDisconnectedCategory",e.PNConnectionErrorCategory="PNConnectionErrorCategory",e.PNDisconnectedUnexpectedlyCategory="PNDisconnectedUnexpectedlyCategory",e.PNSharedWorkerUpdatedCategory="PNSharedWorkerUpdatedCategory"}(l||(l={}));var h=l;class d extends Error{constructor(e,t){super(e),this.status=t,this.name="PubNubError",this.message=e,Object.setPrototypeOf(this,new.target.prototype)}}function p(e,t){var s;return null!==(s=e.statusCode)&&void 0!==s||(e.statusCode=0),Object.assign(Object.assign({},e),{statusCode:e.statusCode,category:t,error:!0})}function g(e,t){return p(Object.assign(Object.assign({message:"Unable to deserialize service response"},void 0!==e?{responseText:e}:{}),void 0!==t?{statusCode:t}:{}),h.PNMalformedResponseCategory)}var b,y,m,f,v,O=O||function(e){var t={},s=t.lib={},n=function(){},i=s.Base={extend:function(e){n.prototype=this;var t=new n;return e&&t.mixIn(e),t.hasOwnProperty("init")||(t.init=function(){t.$super.init.apply(this,arguments)}),t.init.prototype=t,t.$super=this,t},create:function(){var e=this.extend();return e.init.apply(e,arguments),e},init:function(){},mixIn:function(e){for(var t in e)e.hasOwnProperty(t)&&(this[t]=e[t]);e.hasOwnProperty("toString")&&(this.toString=e.toString)},clone:function(){return this.init.prototype.extend(this)}},r=s.WordArray=i.extend({init:function(e,t){e=this.words=e||[],this.sigBytes=null!=t?t:4*e.length},toString:function(e){return(e||o).stringify(this)},concat:function(e){var t=this.words,s=e.words,n=this.sigBytes;if(e=e.sigBytes,this.clamp(),n%4)for(var i=0;i>>2]|=(s[i>>>2]>>>24-i%4*8&255)<<24-(n+i)%4*8;else if(65535>>2]=s[i>>>2];else t.push.apply(t,s);return this.sigBytes+=e,this},clamp:function(){var t=this.words,s=this.sigBytes;t[s>>>2]&=4294967295<<32-s%4*8,t.length=e.ceil(s/4)},clone:function(){var e=i.clone.call(this);return e.words=this.words.slice(0),e},random:function(t){for(var s=[],n=0;n>>2]>>>24-n%4*8&255;s.push((i>>>4).toString(16)),s.push((15&i).toString(16))}return s.join("")},parse:function(e){for(var t=e.length,s=[],n=0;n>>3]|=parseInt(e.substr(n,2),16)<<24-n%8*4;return new r.init(s,t/2)}},c=a.Latin1={stringify:function(e){var t=e.words;e=e.sigBytes;for(var s=[],n=0;n>>2]>>>24-n%4*8&255));return s.join("")},parse:function(e){for(var t=e.length,s=[],n=0;n>>2]|=(255&e.charCodeAt(n))<<24-n%4*8;return new r.init(s,t)}},u=a.Utf8={stringify:function(e){try{return decodeURIComponent(escape(c.stringify(e)))}catch(e){throw Error("Malformed UTF-8 data")}},parse:function(e){return c.parse(unescape(encodeURIComponent(e)))}},l=s.BufferedBlockAlgorithm=i.extend({reset:function(){this._data=new r.init,this._nDataBytes=0},_append:function(e){"string"==typeof e&&(e=u.parse(e)),this._data.concat(e),this._nDataBytes+=e.sigBytes},_process:function(t){var s=this._data,n=s.words,i=s.sigBytes,a=this.blockSize,o=i/(4*a);if(t=(o=t?e.ceil(o):e.max((0|o)-this._minBufferSize,0))*a,i=e.min(4*t,i),t){for(var c=0;cu;){var l;e:{l=c;for(var h=e.sqrt(l),d=2;d<=h;d++)if(!(l%d)){l=!1;break e}l=!0}l&&(8>u&&(r[u]=o(e.pow(c,.5))),a[u]=o(e.pow(c,1/3)),u++),c++}var p=[];i=i.SHA256=n.extend({_doReset:function(){this._hash=new s.init(r.slice(0))},_doProcessBlock:function(e,t){for(var s=this._hash.words,n=s[0],i=s[1],r=s[2],o=s[3],c=s[4],u=s[5],l=s[6],h=s[7],d=0;64>d;d++){if(16>d)p[d]=0|e[t+d];else{var g=p[d-15],b=p[d-2];p[d]=((g<<25|g>>>7)^(g<<14|g>>>18)^g>>>3)+p[d-7]+((b<<15|b>>>17)^(b<<13|b>>>19)^b>>>10)+p[d-16]}g=h+((c<<26|c>>>6)^(c<<21|c>>>11)^(c<<7|c>>>25))+(c&u^~c&l)+a[d]+p[d],b=((n<<30|n>>>2)^(n<<19|n>>>13)^(n<<10|n>>>22))+(n&i^n&r^i&r),h=l,l=u,u=c,c=o+g|0,o=r,r=i,i=n,n=g+b|0}s[0]=s[0]+n|0,s[1]=s[1]+i|0,s[2]=s[2]+r|0,s[3]=s[3]+o|0,s[4]=s[4]+c|0,s[5]=s[5]+u|0,s[6]=s[6]+l|0,s[7]=s[7]+h|0},_doFinalize:function(){var t=this._data,s=t.words,n=8*this._nDataBytes,i=8*t.sigBytes;return s[i>>>5]|=128<<24-i%32,s[14+(i+64>>>9<<4)]=e.floor(n/4294967296),s[15+(i+64>>>9<<4)]=n,t.sigBytes=4*s.length,this._process(),this._hash},clone:function(){var e=n.clone.call(this);return e._hash=this._hash.clone(),e}});t.SHA256=n._createHelper(i),t.HmacSHA256=n._createHmacHelper(i)}(Math),y=(b=O).enc.Utf8,b.algo.HMAC=b.lib.Base.extend({init:function(e,t){e=this._hasher=new e.init,"string"==typeof t&&(t=y.parse(t));var s=e.blockSize,n=4*s;t.sigBytes>n&&(t=e.finalize(t)),t.clamp();for(var i=this._oKey=t.clone(),r=this._iKey=t.clone(),a=i.words,o=r.words,c=0;c>>2]>>>24-i%4*8&255)<<16|(t[i+1>>>2]>>>24-(i+1)%4*8&255)<<8|t[i+2>>>2]>>>24-(i+2)%4*8&255,a=0;4>a&&i+.75*a>>6*(3-a)&63));if(t=n.charAt(64))for(;e.length%4;)e.push(t);return e.join("")},parse:function(e){var t=e.length,s=this._map;(n=s.charAt(64))&&-1!=(n=e.indexOf(n))&&(t=n);for(var n=[],i=0,r=0;r>>6-r%4*2;n[i>>>2]|=(a|o)<<24-i%4*8,i++}return f.create(n,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},function(e){function t(e,t,s,n,i,r,a){return((e=e+(t&s|~t&n)+i+a)<>>32-r)+t}function s(e,t,s,n,i,r,a){return((e=e+(t&n|s&~n)+i+a)<>>32-r)+t}function n(e,t,s,n,i,r,a){return((e=e+(t^s^n)+i+a)<>>32-r)+t}function i(e,t,s,n,i,r,a){return((e=e+(s^(t|~n))+i+a)<>>32-r)+t}for(var r=O,a=(c=r.lib).WordArray,o=c.Hasher,c=r.algo,u=[],l=0;64>l;l++)u[l]=4294967296*e.abs(e.sin(l+1))|0;c=c.MD5=o.extend({_doReset:function(){this._hash=new a.init([1732584193,4023233417,2562383102,271733878])},_doProcessBlock:function(e,r){for(var a=0;16>a;a++){var o=e[c=r+a];e[c]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8)}a=this._hash.words;var c=e[r+0],l=(o=e[r+1],e[r+2]),h=e[r+3],d=e[r+4],p=e[r+5],g=e[r+6],b=e[r+7],y=e[r+8],m=e[r+9],f=e[r+10],v=e[r+11],O=e[r+12],S=e[r+13],j=e[r+14],w=e[r+15],k=t(k=a[0],N=a[1],P=a[2],C=a[3],c,7,u[0]),C=t(C,k,N,P,o,12,u[1]),P=t(P,C,k,N,l,17,u[2]),N=t(N,P,C,k,h,22,u[3]);k=t(k,N,P,C,d,7,u[4]),C=t(C,k,N,P,p,12,u[5]),P=t(P,C,k,N,g,17,u[6]),N=t(N,P,C,k,b,22,u[7]),k=t(k,N,P,C,y,7,u[8]),C=t(C,k,N,P,m,12,u[9]),P=t(P,C,k,N,f,17,u[10]),N=t(N,P,C,k,v,22,u[11]),k=t(k,N,P,C,O,7,u[12]),C=t(C,k,N,P,S,12,u[13]),P=t(P,C,k,N,j,17,u[14]),k=s(k,N=t(N,P,C,k,w,22,u[15]),P,C,o,5,u[16]),C=s(C,k,N,P,g,9,u[17]),P=s(P,C,k,N,v,14,u[18]),N=s(N,P,C,k,c,20,u[19]),k=s(k,N,P,C,p,5,u[20]),C=s(C,k,N,P,f,9,u[21]),P=s(P,C,k,N,w,14,u[22]),N=s(N,P,C,k,d,20,u[23]),k=s(k,N,P,C,m,5,u[24]),C=s(C,k,N,P,j,9,u[25]),P=s(P,C,k,N,h,14,u[26]),N=s(N,P,C,k,y,20,u[27]),k=s(k,N,P,C,S,5,u[28]),C=s(C,k,N,P,l,9,u[29]),P=s(P,C,k,N,b,14,u[30]),k=n(k,N=s(N,P,C,k,O,20,u[31]),P,C,p,4,u[32]),C=n(C,k,N,P,y,11,u[33]),P=n(P,C,k,N,v,16,u[34]),N=n(N,P,C,k,j,23,u[35]),k=n(k,N,P,C,o,4,u[36]),C=n(C,k,N,P,d,11,u[37]),P=n(P,C,k,N,b,16,u[38]),N=n(N,P,C,k,f,23,u[39]),k=n(k,N,P,C,S,4,u[40]),C=n(C,k,N,P,c,11,u[41]),P=n(P,C,k,N,h,16,u[42]),N=n(N,P,C,k,g,23,u[43]),k=n(k,N,P,C,m,4,u[44]),C=n(C,k,N,P,O,11,u[45]),P=n(P,C,k,N,w,16,u[46]),k=i(k,N=n(N,P,C,k,l,23,u[47]),P,C,c,6,u[48]),C=i(C,k,N,P,b,10,u[49]),P=i(P,C,k,N,j,15,u[50]),N=i(N,P,C,k,p,21,u[51]),k=i(k,N,P,C,O,6,u[52]),C=i(C,k,N,P,h,10,u[53]),P=i(P,C,k,N,f,15,u[54]),N=i(N,P,C,k,o,21,u[55]),k=i(k,N,P,C,y,6,u[56]),C=i(C,k,N,P,w,10,u[57]),P=i(P,C,k,N,g,15,u[58]),N=i(N,P,C,k,S,21,u[59]),k=i(k,N,P,C,d,6,u[60]),C=i(C,k,N,P,v,10,u[61]),P=i(P,C,k,N,l,15,u[62]),N=i(N,P,C,k,m,21,u[63]);a[0]=a[0]+k|0,a[1]=a[1]+N|0,a[2]=a[2]+P|0,a[3]=a[3]+C|0},_doFinalize:function(){var t=this._data,s=t.words,n=8*this._nDataBytes,i=8*t.sigBytes;s[i>>>5]|=128<<24-i%32;var r=e.floor(n/4294967296);for(s[15+(i+64>>>9<<4)]=16711935&(r<<8|r>>>24)|4278255360&(r<<24|r>>>8),s[14+(i+64>>>9<<4)]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8),t.sigBytes=4*(s.length+1),this._process(),s=(t=this._hash).words,n=0;4>n;n++)i=s[n],s[n]=16711935&(i<<8|i>>>24)|4278255360&(i<<24|i>>>8);return t},clone:function(){var e=o.clone.call(this);return e._hash=this._hash.clone(),e}}),r.MD5=o._createHelper(c),r.HmacMD5=o._createHmacHelper(c)}(Math),function(){var e,t=O,s=(e=t.lib).Base,n=e.WordArray,i=(e=t.algo).EvpKDF=s.extend({cfg:s.extend({keySize:4,hasher:e.MD5,iterations:1}),init:function(e){this.cfg=this.cfg.extend(e)},compute:function(e,t){for(var s=(o=this.cfg).hasher.create(),i=n.create(),r=i.words,a=o.keySize,o=o.iterations;r.length>>2]}},e.BlockCipher=a.extend({cfg:a.cfg.extend({mode:o,padding:u}),reset:function(){a.reset.call(this);var e=(t=this.cfg).iv,t=t.mode;if(this._xformMode==this._ENC_XFORM_MODE)var s=t.createEncryptor;else s=t.createDecryptor,this._minBufferSize=1;this._mode=s.call(t,this,e&&e.words)},_doProcessBlock:function(e,t){this._mode.processBlock(e,t)},_doFinalize:function(){var e=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){e.pad(this._data,this.blockSize);var t=this._process(!0)}else t=this._process(!0),e.unpad(t);return t},blockSize:4});var l=e.CipherParams=t.extend({init:function(e){this.mixIn(e)},toString:function(e){return(e||this.formatter).stringify(this)}}),h=(o=(d.format={}).OpenSSL={stringify:function(e){var t=e.ciphertext;return((e=e.salt)?s.create([1398893684,1701076831]).concat(e).concat(t):t).toString(i)},parse:function(e){var t=(e=i.parse(e)).words;if(1398893684==t[0]&&1701076831==t[1]){var n=s.create(t.slice(2,4));t.splice(0,4),e.sigBytes-=16}return l.create({ciphertext:e,salt:n})}},e.SerializableCipher=t.extend({cfg:t.extend({format:o}),encrypt:function(e,t,s,n){n=this.cfg.extend(n);var i=e.createEncryptor(s,n);return t=i.finalize(t),i=i.cfg,l.create({ciphertext:t,key:s,iv:i.iv,algorithm:e,mode:i.mode,padding:i.padding,blockSize:e.blockSize,formatter:n.format})},decrypt:function(e,t,s,n){return n=this.cfg.extend(n),t=this._parse(t,n.format),e.createDecryptor(s,n).finalize(t.ciphertext)},_parse:function(e,t){return"string"==typeof e?t.parse(e,this):e}})),d=(d.kdf={}).OpenSSL={execute:function(e,t,n,i){return i||(i=s.random(8)),e=r.create({keySize:t+n}).compute(e,i),n=s.create(e.words.slice(t),4*n),e.sigBytes=4*t,l.create({key:e,iv:n,salt:i})}},p=e.PasswordBasedCipher=h.extend({cfg:h.cfg.extend({kdf:d}),encrypt:function(e,t,s,n){return s=(n=this.cfg.extend(n)).kdf.execute(s,e.keySize,e.ivSize),n.iv=s.iv,(e=h.encrypt.call(this,e,t,s.key,n)).mixIn(s),e},decrypt:function(e,t,s,n){return n=this.cfg.extend(n),t=this._parse(t,n.format),s=n.kdf.execute(s,e.keySize,e.ivSize,t.salt),n.iv=s.iv,h.decrypt.call(this,e,t,s.key,n)}})}(),function(){for(var e=O,t=e.lib.BlockCipher,s=e.algo,n=[],i=[],r=[],a=[],o=[],c=[],u=[],l=[],h=[],d=[],p=[],g=0;256>g;g++)p[g]=128>g?g<<1:g<<1^283;var b=0,y=0;for(g=0;256>g;g++){var m=(m=y^y<<1^y<<2^y<<3^y<<4)>>>8^255&m^99;n[b]=m,i[m]=b;var f=p[b],v=p[f],S=p[v],j=257*p[m]^16843008*m;r[b]=j<<24|j>>>8,a[b]=j<<16|j>>>16,o[b]=j<<8|j>>>24,c[b]=j,j=16843009*S^65537*v^257*f^16843008*b,u[m]=j<<24|j>>>8,l[m]=j<<16|j>>>16,h[m]=j<<8|j>>>24,d[m]=j,b?(b=f^p[p[p[S^f]]],y^=p[p[y]]):b=y=1}var w=[0,1,2,4,8,16,32,64,128,27,54];s=s.AES=t.extend({_doReset:function(){for(var e=(s=this._key).words,t=s.sigBytes/4,s=4*((this._nRounds=t+6)+1),i=this._keySchedule=[],r=0;r>>24]<<24|n[a>>>16&255]<<16|n[a>>>8&255]<<8|n[255&a]):(a=n[(a=a<<8|a>>>24)>>>24]<<24|n[a>>>16&255]<<16|n[a>>>8&255]<<8|n[255&a],a^=w[r/t|0]<<24),i[r]=i[r-t]^a}for(e=this._invKeySchedule=[],t=0;tt||4>=r?a:u[n[a>>>24]]^l[n[a>>>16&255]]^h[n[a>>>8&255]]^d[n[255&a]]},encryptBlock:function(e,t){this._doCryptBlock(e,t,this._keySchedule,r,a,o,c,n)},decryptBlock:function(e,t){var s=e[t+1];e[t+1]=e[t+3],e[t+3]=s,this._doCryptBlock(e,t,this._invKeySchedule,u,l,h,d,i),s=e[t+1],e[t+1]=e[t+3],e[t+3]=s},_doCryptBlock:function(e,t,s,n,i,r,a,o){for(var c=this._nRounds,u=e[t]^s[0],l=e[t+1]^s[1],h=e[t+2]^s[2],d=e[t+3]^s[3],p=4,g=1;g>>24]^i[l>>>16&255]^r[h>>>8&255]^a[255&d]^s[p++],y=n[l>>>24]^i[h>>>16&255]^r[d>>>8&255]^a[255&u]^s[p++],m=n[h>>>24]^i[d>>>16&255]^r[u>>>8&255]^a[255&l]^s[p++];d=n[d>>>24]^i[u>>>16&255]^r[l>>>8&255]^a[255&h]^s[p++],u=b,l=y,h=m}b=(o[u>>>24]<<24|o[l>>>16&255]<<16|o[h>>>8&255]<<8|o[255&d])^s[p++],y=(o[l>>>24]<<24|o[h>>>16&255]<<16|o[d>>>8&255]<<8|o[255&u])^s[p++],m=(o[h>>>24]<<24|o[d>>>16&255]<<16|o[u>>>8&255]<<8|o[255&l])^s[p++],d=(o[d>>>24]<<24|o[u>>>16&255]<<16|o[l>>>8&255]<<8|o[255&h])^s[p++],e[t]=b,e[t+1]=y,e[t+2]=m,e[t+3]=d},keySize:8});e.AES=t._createHelper(s)}(),O.mode.ECB=((v=O.lib.BlockCipherMode.extend()).Encryptor=v.extend({processBlock:function(e,t){this._cipher.encryptBlock(e,t)}}),v.Decryptor=v.extend({processBlock:function(e,t){this._cipher.decryptBlock(e,t)}}),v);var S=t(O);class j{constructor({cipherKey:e}){this.cipherKey=e,this.CryptoJS=S,this.encryptedKey=this.CryptoJS.SHA256(e)}encrypt(e){if(0===("string"==typeof e?e:j.decoder.decode(e)).length)throw new Error("encryption error. empty content");const t=this.getIv();return{metadata:t,data:c(this.CryptoJS.AES.encrypt(e,this.encryptedKey,{iv:this.bufferToWordArray(t),mode:this.CryptoJS.mode.CBC}).ciphertext.toString(this.CryptoJS.enc.Base64))}}encryptFileData(e){return r(this,void 0,void 0,(function*(){const t=yield this.getKey(),s=this.getIv();return{data:yield crypto.subtle.encrypt({name:this.algo,iv:s},t,e),metadata:s}}))}decrypt(e){if("string"==typeof e.data)throw new Error("Decryption error: data for decryption should be ArrayBuffed.");const t=this.bufferToWordArray(new Uint8ClampedArray(e.metadata)),s=this.bufferToWordArray(new Uint8ClampedArray(e.data));return j.encoder.encode(this.CryptoJS.AES.decrypt({ciphertext:s},this.encryptedKey,{iv:t,mode:this.CryptoJS.mode.CBC}).toString(this.CryptoJS.enc.Utf8)).buffer}decryptFileData(e){return r(this,void 0,void 0,(function*(){if("string"==typeof e.data)throw new Error("Decryption error: data for decryption should be ArrayBuffed.");const t=yield this.getKey();return crypto.subtle.decrypt({name:this.algo,iv:e.metadata},t,e.data)}))}get identifier(){return"ACRH"}get algo(){return"AES-CBC"}getIv(){return crypto.getRandomValues(new Uint8Array(j.BLOCK_SIZE))}getKey(){return r(this,void 0,void 0,(function*(){const e=j.encoder.encode(this.cipherKey),t=yield crypto.subtle.digest("SHA-256",e.buffer);return crypto.subtle.importKey("raw",t,this.algo,!0,["encrypt","decrypt"])}))}bufferToWordArray(e){const t=[];let s;for(s=0;sw.has(e),C=e=>encodeURIComponent(e).replace(/[!~*'()]/g,(e=>`%${e.charCodeAt(0).toString(16).toUpperCase()}`)),P=(e,t)=>{const s=e.map((e=>C(e)));return s.length?s.join(","):null!=t?t:""},N=(e,t)=>{const s=Object.fromEntries(t.map((e=>[e,!1])));return e.filter((e=>!(t.includes(e)&&!s[e])||(s[e]=!0,!1)))},E=(e,t)=>[...e].filter((s=>t.includes(s)&&e.indexOf(s)===e.lastIndexOf(s)&&t.indexOf(s)===t.lastIndexOf(s))),T=e=>Object.keys(e).map((t=>{const s=e[t];return Array.isArray(s)?s.map((e=>`${t}=${C(e)}`)).join("&"):`${t}=${C(s)}`})).join("&"),_=(e,t)=>{if("0"===t||"0"===e)return;const s=M(`${Date.now()}0000`,t,!1);return M(e,s,!0)},I=(e,t,s)=>{if(e&&0!==e.length){if(t&&t.length>0&&"0"!==t){const n=M(e,t,!1);return M(null!=s?s:`${Date.now()}0000`,n.replace("-",""),Number(n)<0)}return s&&s.length>0&&"0"!==s?s:`${Date.now()}0000`}},M=(e,t,s)=>{t.startsWith("-")&&(t=t.replace("-",""),s=!1),t=t.padStart(17,"0");const n=e.slice(0,10),i=e.slice(10,17),r=t.slice(0,10),a=t.slice(10,17);let o=Number(n),c=Number(i);return o+=Number(r)*(s?1:-1),c+=Number(a)*(s?1:-1),c>=1e7?(o+=Math.floor(c/1e7),c%=1e7):c<0?o>0?(o-=1,c+=1e7):o<0&&(c*=-1):o<0&&c>0&&(o+=1,c=1e7-c),0!==o?`${o}${`${c}`.padStart(7,"0")}`:`${c}`},R=e=>{const t="string"!=typeof e?JSON.stringify(e):e,s=new Uint32Array(1);let n=0,i=t.length;for(;i-- >0;)s[0]=(s[0]<<5)-s[0]+t.charCodeAt(n++);return s[0].toString(16).padStart(8,"0")};function D(e){const t=[];let s;for(s=0;s({messageType:"object",message:this.configuration,details:"Create with configuration:",ignoredKeys:(e,t)=>"function"==typeof t[e]||"logger"===e||k(e)})))}get logger(){return this._logger}HMACSHA256(e){return S.HmacSHA256(e,this.configuration.secretKey).toString(S.enc.Base64)}SHA256(e){return S.SHA256(e).toString(S.enc.Hex)}encrypt(e,t,s){return this.configuration.customEncrypt?(this.logger&&this.logger.warn("Crypto","'customEncrypt' is deprecated. Consult docs for better alternative."),this.configuration.customEncrypt(e)):this.pnEncrypt(e,t,s)}decrypt(e,t,s){return this.configuration.customDecrypt?(this.logger&&this.logger.warn("Crypto","'customDecrypt' is deprecated. Consult docs for better alternative."),this.configuration.customDecrypt(e)):this.pnDecrypt(e,t,s)}pnEncrypt(e,t,s){const n=null!=t?t:this.configuration.cipherKey;if(!n)return e;this.logger&&this.logger.debug("Crypto",(()=>({messageType:"object",message:Object.assign({data:e},null!=s?s:{}),details:"Encrypt with parameters:",ignoredKeys:k}))),s=this.parseOptions(s);const i=this.getMode(s),r=this.getPaddedKey(n,s);if(this.configuration.useRandomIVs){const t=this.getRandomIV(),s=S.AES.encrypt(e,r,{iv:t,mode:i}).ciphertext;return t.clone().concat(s.clone()).toString(S.enc.Base64)}const a=this.getIV(s);return S.AES.encrypt(e,r,{iv:a,mode:i}).ciphertext.toString(S.enc.Base64)||e}pnDecrypt(e,t,s){const n=null!=t?t:this.configuration.cipherKey;if(!n)return e;this.logger&&this.logger.debug("Crypto",(()=>({messageType:"object",message:Object.assign({data:e},null!=s?s:{}),details:"Decrypt with parameters:",ignoredKeys:k}))),s=this.parseOptions(s);const i=this.getMode(s),r=this.getPaddedKey(n,s);if(this.configuration.useRandomIVs){const t=new Uint8ClampedArray(c(e)),s=D(t.slice(0,16)),n=D(t.slice(16));try{const e=S.AES.decrypt({ciphertext:n},r,{iv:s,mode:i}).toString(S.enc.Utf8);return JSON.parse(e)}catch(e){return this.logger&&this.logger.error("Crypto",(()=>({messageType:"error",message:e}))),null}}else{const t=this.getIV(s);try{const s=S.enc.Base64.parse(e),n=S.AES.decrypt({ciphertext:s},r,{iv:t,mode:i}).toString(S.enc.Utf8);return JSON.parse(n)}catch(e){return this.logger&&this.logger.error("Crypto",(()=>({messageType:"error",message:e}))),null}}}parseOptions(e){var t,s,n,i;if(!e)return this.defaultOptions;const r={encryptKey:null!==(t=e.encryptKey)&&void 0!==t?t:this.defaultOptions.encryptKey,keyEncoding:null!==(s=e.keyEncoding)&&void 0!==s?s:this.defaultOptions.keyEncoding,keyLength:null!==(n=e.keyLength)&&void 0!==n?n:this.defaultOptions.keyLength,mode:null!==(i=e.mode)&&void 0!==i?i:this.defaultOptions.mode};return-1===this.allowedKeyEncodings.indexOf(r.keyEncoding.toLowerCase())&&(r.keyEncoding=this.defaultOptions.keyEncoding),-1===this.allowedKeyLengths.indexOf(r.keyLength)&&(r.keyLength=this.defaultOptions.keyLength),-1===this.allowedModes.indexOf(r.mode.toLowerCase())&&(r.mode=this.defaultOptions.mode),r}decodeKey(e,t){return"base64"===t.keyEncoding?S.enc.Base64.parse(e):"hex"===t.keyEncoding?S.enc.Hex.parse(e):e}getPaddedKey(e,t){return e=this.decodeKey(e,t),t.encryptKey?S.enc.Utf8.parse(this.SHA256(e).slice(0,32)):e}getMode(e){return"ecb"===e.mode?S.mode.ECB:S.mode.CBC}getIV(e){return"cbc"===e.mode?S.enc.Utf8.parse(this.iv):null}getRandomIV(){return S.lib.WordArray.random(16)}}class A{encrypt(e,t){return r(this,void 0,void 0,(function*(){if(!(t instanceof ArrayBuffer)&&"string"!=typeof t)throw new Error("Cannot encrypt this file. In browsers file encryption supports only string or ArrayBuffer");const s=yield this.getKey(e);return t instanceof ArrayBuffer?this.encryptArrayBuffer(s,t):this.encryptString(s,t)}))}encryptArrayBuffer(e,t){return r(this,void 0,void 0,(function*(){const s=crypto.getRandomValues(new Uint8Array(16));return this.concatArrayBuffer(s.buffer,yield crypto.subtle.encrypt({name:"AES-CBC",iv:s},e,t))}))}encryptString(e,t){return r(this,void 0,void 0,(function*(){const s=crypto.getRandomValues(new Uint8Array(16)),n=A.encoder.encode(t).buffer,i=yield crypto.subtle.encrypt({name:"AES-CBC",iv:s},e,n),r=this.concatArrayBuffer(s.buffer,i);return A.decoder.decode(r)}))}encryptFile(e,t,s){return r(this,void 0,void 0,(function*(){var n,i;if((null!==(n=t.contentLength)&&void 0!==n?n:0)<=0)throw new Error("encryption error. empty content");const r=yield this.getKey(e),a=yield t.toArrayBuffer(),o=yield this.encryptArrayBuffer(r,a);return s.create({name:t.name,mimeType:null!==(i=t.mimeType)&&void 0!==i?i:"application/octet-stream",data:o})}))}decrypt(e,t){return r(this,void 0,void 0,(function*(){if(!(t instanceof ArrayBuffer)&&"string"!=typeof t)throw new Error("Cannot decrypt this file. In browsers file decryption supports only string or ArrayBuffer");const s=yield this.getKey(e);return t instanceof ArrayBuffer?this.decryptArrayBuffer(s,t):this.decryptString(s,t)}))}decryptArrayBuffer(e,t){return r(this,void 0,void 0,(function*(){const s=t.slice(0,16);if(t.slice(A.IV_LENGTH).byteLength<=0)throw new Error("decryption error: empty content");return yield crypto.subtle.decrypt({name:"AES-CBC",iv:s},e,t.slice(A.IV_LENGTH))}))}decryptString(e,t){return r(this,void 0,void 0,(function*(){const s=A.encoder.encode(t).buffer,n=s.slice(0,16),i=s.slice(16),r=yield crypto.subtle.decrypt({name:"AES-CBC",iv:n},e,i);return A.decoder.decode(r)}))}decryptFile(e,t,s){return r(this,void 0,void 0,(function*(){const n=yield this.getKey(e),i=yield t.toArrayBuffer(),r=yield this.decryptArrayBuffer(n,i);return s.create({name:t.name,mimeType:t.mimeType,data:r})}))}getKey(e){return r(this,void 0,void 0,(function*(){const t=yield crypto.subtle.digest("SHA-256",A.encoder.encode(e)),s=Array.from(new Uint8Array(t)).map((e=>e.toString(16).padStart(2,"0"))).join(""),n=A.encoder.encode(s.slice(0,32)).buffer;return crypto.subtle.importKey("raw",n,"AES-CBC",!0,["encrypt","decrypt"])}))}concatArrayBuffer(e,t){const s=new Uint8Array(e.byteLength+t.byteLength);return s.set(new Uint8Array(e),0),s.set(new Uint8Array(t),e.byteLength),s.buffer}}A.IV_LENGTH=16,A.encoder=new TextEncoder,A.decoder=new TextDecoder;class ${constructor(e){this.config=e,this.cryptor=new U(Object.assign({},e)),this.fileCryptor=new A}set logger(e){this.cryptor.logger=e,!1===this.config.useRandomIVs&&e.warn("LegacyCryptor","Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients.\n Do not disable random IVs in new applications.")}encrypt(e){const t="string"==typeof e?e:$.decoder.decode(e);return{data:this.cryptor.encrypt(t),metadata:null}}encryptFile(e,t){return r(this,void 0,void 0,(function*(){var s;if(!this.config.cipherKey)throw new d("File encryption error: cipher key not set.");return this.fileCryptor.encryptFile(null===(s=this.config)||void 0===s?void 0:s.cipherKey,e,t)}))}decrypt(e){const t="string"==typeof e.data?e.data:u(e.data);return this.cryptor.decrypt(t)}decryptFile(e,t){return r(this,void 0,void 0,(function*(){if(!this.config.cipherKey)throw new d("File encryption error: cipher key not set.");return this.fileCryptor.decryptFile(this.config.cipherKey,e,t)}))}get identifier(){return""}toString(){return`LegacyCryptor { ${Object.entries(this.config).reduce(((e,[t,s])=>("logger"===t||k(t)||e.push(`${t}: ${"function"==typeof s?"":s}`),e)),[]).join(", ")} }`}}$.encoder=new TextEncoder,$.decoder=new TextDecoder;class F extends a{set logger(e){if(this.defaultCryptor.identifier===F.LEGACY_IDENTIFIER)e.warn("CryptoModule","'legacyCryptoModule' is deprecated. Use 'aesCbcCryptoModule' instead for new applications."),this.defaultCryptor.logger=e;else{const t=this.cryptors.find((e=>e.identifier===F.LEGACY_IDENTIFIER));t&&(t.logger=e)}}static legacyCryptoModule(e){var t;if(!e.cipherKey)throw new d("Crypto module error: cipher key not set.");return e.logger&&(e.logger.warn("CryptoModule","'legacyCryptoModule' is deprecated. Use 'aesCbcCryptoModule' instead for new applications."),!1===e.useRandomIVs&&e.logger.warn("CryptoModule","Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients.\n Do not disable random IVs in new applications.")),new F({default:new $(Object.assign(Object.assign({},e),{useRandomIVs:null===(t=e.useRandomIVs)||void 0===t||t})),cryptors:[new j({cipherKey:e.cipherKey})]})}static aesCbcCryptoModule(e){var t;if(!e.cipherKey)throw new d("Crypto module error: cipher key not set.");return new F({default:new j({cipherKey:e.cipherKey}),cryptors:[new $(Object.assign(Object.assign({},e),{useRandomIVs:null===(t=e.useRandomIVs)||void 0===t||t}))]})}static withDefaultCryptor(e){return new this({default:e})}encrypt(e){const t=e instanceof ArrayBuffer&&this.defaultCryptor.identifier===F.LEGACY_IDENTIFIER?this.defaultCryptor.encrypt(F.decoder.decode(e)):this.defaultCryptor.encrypt(e);if(!t.metadata)return t.data;if("string"==typeof t.data)throw new Error("Encryption error: encrypted data should be ArrayBuffed.");const s=this.getHeaderData(t);return this.concatArrayBuffer(s,t.data)}encryptFile(e,t){return r(this,void 0,void 0,(function*(){if(this.defaultCryptor.identifier===x.LEGACY_IDENTIFIER)return this.defaultCryptor.encryptFile(e,t);const s=yield this.getFileData(e),n=yield this.defaultCryptor.encryptFileData(s);if("string"==typeof n.data)throw new Error("Encryption error: encrypted data should be ArrayBuffed.");return t.create({name:e.name,mimeType:"application/octet-stream",data:this.concatArrayBuffer(this.getHeaderData(n),n.data)})}))}decrypt(e){const t="string"==typeof e?c(e):e,s=x.tryParse(t),n=this.getCryptor(s),i=s.length>0?t.slice(s.length-s.metadataLength,s.length):null;if(t.slice(s.length).byteLength<=0)throw new Error("Decryption error: empty content");return n.decrypt({data:t.slice(s.length),metadata:i})}decryptFile(e,t){return r(this,void 0,void 0,(function*(){const s=yield e.data.arrayBuffer(),n=x.tryParse(s),i=this.getCryptor(n);if((null==i?void 0:i.identifier)===x.LEGACY_IDENTIFIER)return i.decryptFile(e,t);const r=(yield this.getFileData(s)).slice(n.length-n.metadataLength,n.length);return t.create({name:e.name,data:yield this.defaultCryptor.decryptFileData({data:s.slice(n.length),metadata:r})})}))}getCryptorFromId(e){const t=this.getAllCryptors().find((t=>e===t.identifier));if(t)return t;throw Error("Unknown cryptor error")}getCryptor(e){if("string"==typeof e){const t=this.getAllCryptors().find((t=>t.identifier===e));if(t)return t;throw new Error("Unknown cryptor error")}if(e instanceof q)return this.getCryptorFromId(e.identifier)}getHeaderData(e){if(!e.metadata)return;const t=x.from(this.defaultCryptor.identifier,e.metadata),s=new Uint8Array(t.length);let n=0;return s.set(t.data,n),n+=t.length-e.metadata.byteLength,s.set(new Uint8Array(e.metadata),n),s.buffer}concatArrayBuffer(e,t){const s=new Uint8Array(e.byteLength+t.byteLength);return s.set(new Uint8Array(e),0),s.set(new Uint8Array(t),e.byteLength),s.buffer}getFileData(e){return r(this,void 0,void 0,(function*(){if(e instanceof ArrayBuffer)return e;if(e instanceof o)return e.toArrayBuffer();throw new Error("Cannot decrypt/encrypt file. In browsers file encrypt/decrypt supported for string, ArrayBuffer or Blob")}))}}F.LEGACY_IDENTIFIER="";class x{static from(e,t){if(e!==x.LEGACY_IDENTIFIER)return new q(e,t.byteLength)}static tryParse(e){const t=new Uint8Array(e);let s,n,i=null;if(t.byteLength>=4&&(s=t.slice(0,4),this.decoder.decode(s)!==x.SENTINEL))return F.LEGACY_IDENTIFIER;if(!(t.byteLength>=5))throw new Error("Decryption error: invalid header version");if(i=t[4],i>x.MAX_VERSION)throw new Error("Decryption error: Unknown cryptor error");let r=5+x.IDENTIFIER_LENGTH;if(!(t.byteLength>=r))throw new Error("Decryption error: invalid crypto identifier");n=t.slice(5,r);let a=null;if(!(t.byteLength>=r+1))throw new Error("Decryption error: invalid metadata length");return a=t[r],r+=1,255===a&&t.byteLength>=r+2&&(a=new Uint16Array(t.slice(r,r+2)).reduce(((e,t)=>(e<<8)+t),0)),new q(this.decoder.decode(n),a)}}x.SENTINEL="PNED",x.LEGACY_IDENTIFIER="",x.IDENTIFIER_LENGTH=4,x.VERSION=1,x.MAX_VERSION=1,x.decoder=new TextDecoder;class q{constructor(e,t){this._identifier=e,this._metadataLength=t}get identifier(){return this._identifier}set identifier(e){this._identifier=e}get metadataLength(){return this._metadataLength}set metadataLength(e){this._metadataLength=e}get version(){return x.VERSION}get length(){return x.SENTINEL.length+1+x.IDENTIFIER_LENGTH+(this.metadataLength<255?1:3)+this.metadataLength}get data(){let e=0;const t=new Uint8Array(this.length),s=new TextEncoder;t.set(s.encode(x.SENTINEL)),e+=x.SENTINEL.length,t[e]=this.version,e++,this.identifier&&t.set(s.encode(this.identifier),e);const n=this.metadataLength;return e+=x.IDENTIFIER_LENGTH,n<255?t[e]=n:t.set([255,n>>8,255&n],e),t}}q.IDENTIFIER_LENGTH=4,q.SENTINEL="PNED";class G extends Error{static create(e,t){return G.isErrorObject(e)?G.createFromError(e):G.createFromServiceResponse(e,t)}static createFromError(e){let t=h.PNUnknownCategory,s="Unknown error",n="Error";if(!e)return new G(s,t,0);if(e instanceof G)return e;if(G.isErrorObject(e)&&(s=e.message,n=e.name),"AbortError"===n||-1!==s.indexOf("Aborted"))t=h.PNCancelledCategory,s="Request cancelled";else if(-1!==s.toLowerCase().indexOf("timeout"))t=h.PNTimeoutCategory,s="Request timeout";else if(-1!==s.toLowerCase().indexOf("network"))t=h.PNNetworkIssuesCategory,s="Network issues";else if("TypeError"===n)t=-1!==s.indexOf("Load failed")||-1!=s.indexOf("Failed to fetch")?h.PNNetworkIssuesCategory:h.PNBadRequestCategory;else if("FetchError"===n){const n=e.code;["ECONNREFUSED","ENETUNREACH","ENOTFOUND","ECONNRESET","EAI_AGAIN"].includes(n)&&(t=h.PNNetworkIssuesCategory),"ECONNREFUSED"===n?s="Connection refused":"ENETUNREACH"===n?s="Network not reachable":"ENOTFOUND"===n?s="Server not found":"ECONNRESET"===n?s="Connection reset by peer":"EAI_AGAIN"===n?s="Name resolution error":"ETIMEDOUT"===n?(t=h.PNTimeoutCategory,s="Request timeout"):s=`Unknown system error: ${e}`}else"Request timeout"===s&&(t=h.PNTimeoutCategory);return new G(s,t,0,e)}static createFromServiceResponse(e,t){let s,n=h.PNUnknownCategory,i="Unknown error",{status:r}=e;if(null!=t||(t=e.body),402===r?i="Not available for used key set. Contact support@pubnub.com":404===r?i="Resource not found":400===r?(n=h.PNBadRequestCategory,i="Bad request"):403===r?(n=h.PNAccessDeniedCategory,i="Access denied"):r>=500&&(n=h.PNServerErrorCategory,i="Internal server error"),"object"==typeof e&&0===Object.keys(e).length&&(n=h.PNMalformedResponseCategory,i="Malformed response (network issues)",r=400),t&&t.byteLength>0){const n=(new TextDecoder).decode(t);if(-1!==e.headers["content-type"].indexOf("text/javascript")||-1!==e.headers["content-type"].indexOf("application/json"))try{const e=JSON.parse(n);"object"==typeof e&&(Array.isArray(e)?"number"==typeof e[0]&&0===e[0]&&e.length>1&&"string"==typeof e[1]&&(s=e[1]):("error"in e&&(1===e.error||!0===e.error)&&"status"in e&&"number"==typeof e.status&&"message"in e&&"service"in e?(s=e,r=e.status):s=e,"error"in e&&e.error instanceof Error&&(s=e.error)))}catch(e){s=n}else if(-1!==e.headers["content-type"].indexOf("xml")){const e=/(.*)<\/Message>/gi.exec(n);i=e?`Upload to bucket failed: ${e[1]}`:"Upload to bucket failed."}else s=n}return new G(i,n,r,s)}constructor(e,t,s,n){super(e),this.category=t,this.statusCode=s,this.errorData=n,this.name="PubNubAPIError"}toStatus(e){return{error:!0,category:this.category,operation:e,statusCode:this.statusCode,errorData:this.errorData,toJSON:function(){let e;const t=this.errorData;if(t)try{if("object"==typeof t){const s=Object.assign(Object.assign(Object.assign(Object.assign({},"name"in t?{name:t.name}:{}),"message"in t?{message:t.message}:{}),"stack"in t?{stack:t.stack}:{}),t);e=JSON.parse(JSON.stringify(s,G.circularReplacer()))}else e=t}catch(t){e={error:"Could not serialize the error object"}}const s=i(this,["toJSON"]);return JSON.stringify(Object.assign(Object.assign({},s),{errorData:e}))}}}toPubNubError(e,t){return new d(null!=t?t:this.message,this.toStatus(e))}static circularReplacer(){const e=new WeakSet;return function(t,s){if("object"==typeof s&&null!==s){if(e.has(s))return"[Circular]";e.add(s)}return s}}static isErrorObject(e){return!(!e||"object"!=typeof e)&&(e instanceof Error||("name"in e&&"message"in e&&"string"==typeof e.name&&"string"==typeof e.message||"[object Error]"===Object.prototype.toString.call(e)))}}var L;!function(e){e.PNPublishOperation="PNPublishOperation",e.PNSignalOperation="PNSignalOperation",e.PNSubscribeOperation="PNSubscribeOperation",e.PNUnsubscribeOperation="PNUnsubscribeOperation",e.PNWhereNowOperation="PNWhereNowOperation",e.PNHereNowOperation="PNHereNowOperation",e.PNGlobalHereNowOperation="PNGlobalHereNowOperation",e.PNSetStateOperation="PNSetStateOperation",e.PNGetStateOperation="PNGetStateOperation",e.PNHeartbeatOperation="PNHeartbeatOperation",e.PNAddMessageActionOperation="PNAddActionOperation",e.PNRemoveMessageActionOperation="PNRemoveMessageActionOperation",e.PNGetMessageActionsOperation="PNGetMessageActionsOperation",e.PNTimeOperation="PNTimeOperation",e.PNHistoryOperation="PNHistoryOperation",e.PNDeleteMessagesOperation="PNDeleteMessagesOperation",e.PNFetchMessagesOperation="PNFetchMessagesOperation",e.PNMessageCounts="PNMessageCountsOperation",e.PNGetAllUUIDMetadataOperation="PNGetAllUUIDMetadataOperation",e.PNGetUUIDMetadataOperation="PNGetUUIDMetadataOperation",e.PNSetUUIDMetadataOperation="PNSetUUIDMetadataOperation",e.PNRemoveUUIDMetadataOperation="PNRemoveUUIDMetadataOperation",e.PNGetAllChannelMetadataOperation="PNGetAllChannelMetadataOperation",e.PNGetChannelMetadataOperation="PNGetChannelMetadataOperation",e.PNSetChannelMetadataOperation="PNSetChannelMetadataOperation",e.PNRemoveChannelMetadataOperation="PNRemoveChannelMetadataOperation",e.PNGetMembersOperation="PNGetMembersOperation",e.PNSetMembersOperation="PNSetMembersOperation",e.PNGetMembershipsOperation="PNGetMembershipsOperation",e.PNSetMembershipsOperation="PNSetMembershipsOperation",e.PNCreateDataSyncEntityOperation="PNCreateDataSyncEntityOperation",e.PNGetDataSyncEntityOperation="PNGetDataSyncEntityOperation",e.PNGetDataSyncEntitiesOperation="PNGetDataSyncEntitiesOperation",e.PNSetDataSyncEntityOperation="PNSetDataSyncEntityOperation",e.PNUpdateDataSyncEntityOperation="PNUpdateDataSyncEntityOperation",e.PNRemoveDataSyncEntityOperation="PNRemoveDataSyncEntityOperation",e.PNCreateDataSyncRelationshipOperation="PNCreateDataSyncRelationshipOperation",e.PNGetDataSyncRelationshipOperation="PNGetDataSyncRelationshipOperation",e.PNGetDataSyncRelationshipsOperation="PNGetDataSyncRelationshipsOperation",e.PNSetDataSyncRelationshipOperation="PNSetDataSyncRelationshipOperation",e.PNUpdateDataSyncRelationshipOperation="PNUpdateDataSyncRelationshipOperation",e.PNRemoveDataSyncRelationshipOperation="PNRemoveDataSyncRelationshipOperation",e.PNCreateDataSyncUserOperation="PNCreateDataSyncUserOperation",e.PNGetDataSyncUserOperation="PNGetDataSyncUserOperation",e.PNGetDataSyncUsersOperation="PNGetDataSyncUsersOperation",e.PNSetDataSyncUserOperation="PNSetDataSyncUserOperation",e.PNUpdateDataSyncUserOperation="PNUpdateDataSyncUserOperation",e.PNRemoveDataSyncUserOperation="PNRemoveDataSyncUserOperation",e.PNCreateDataSyncChannelOperation="PNCreateDataSyncChannelOperation",e.PNGetDataSyncChannelOperation="PNGetDataSyncChannelOperation",e.PNGetDataSyncChannelsOperation="PNGetDataSyncChannelsOperation",e.PNSetDataSyncChannelOperation="PNSetDataSyncChannelOperation",e.PNUpdateDataSyncChannelOperation="PNUpdateDataSyncChannelOperation",e.PNRemoveDataSyncChannelOperation="PNRemoveDataSyncChannelOperation",e.PNCreateDataSyncMembershipOperation="PNCreateDataSyncMembershipOperation",e.PNGetDataSyncMembershipOperation="PNGetDataSyncMembershipOperation",e.PNGetDataSyncMembershipsOperation="PNGetDataSyncMembershipsOperation",e.PNSetDataSyncMembershipOperation="PNSetDataSyncMembershipOperation",e.PNUpdateDataSyncMembershipOperation="PNUpdateDataSyncMembershipOperation",e.PNRemoveDataSyncMembershipOperation="PNRemoveDataSyncMembershipOperation",e.PNListFilesOperation="PNListFilesOperation",e.PNGenerateUploadUrlOperation="PNGenerateUploadUrlOperation",e.PNPublishFileOperation="PNPublishFileOperation",e.PNPublishFileMessageOperation="PNPublishFileMessageOperation",e.PNGetFileUrlOperation="PNGetFileUrlOperation",e.PNDownloadFileOperation="PNDownloadFileOperation",e.PNDeleteFileOperation="PNDeleteFileOperation",e.PNAddPushNotificationEnabledChannelsOperation="PNAddPushNotificationEnabledChannelsOperation",e.PNRemovePushNotificationEnabledChannelsOperation="PNRemovePushNotificationEnabledChannelsOperation",e.PNPushNotificationEnabledChannelsOperation="PNPushNotificationEnabledChannelsOperation",e.PNRemoveAllPushNotificationsOperation="PNRemoveAllPushNotificationsOperation",e.PNChannelGroupsOperation="PNChannelGroupsOperation",e.PNRemoveGroupOperation="PNRemoveGroupOperation",e.PNChannelsForGroupOperation="PNChannelsForGroupOperation",e.PNAddChannelsToGroupOperation="PNAddChannelsToGroupOperation",e.PNRemoveChannelsFromGroupOperation="PNRemoveChannelsFromGroupOperation",e.PNAccessManagerGrant="PNAccessManagerGrant",e.PNAccessManagerGrantToken="PNAccessManagerGrantToken",e.PNAccessManagerAudit="PNAccessManagerAudit",e.PNAccessManagerRevokeToken="PNAccessManagerRevokeToken",e.PNHandshakeOperation="PNHandshakeOperation",e.PNReceiveMessagesOperation="PNReceiveMessagesOperation"}(L||(L={}));var K=L;class H{constructor(e){this.configuration=e,this.subscriptionWorkerReady=!1,this.accessTokensMap={},this.workerEventsQueue=[],this.callbacks=new Map,this.setupSubscriptionWorker()}set emitStatus(e){this._emitStatus=e}onUserIdChange(e){this.configuration.userId=e,this.scheduleEventPost({type:"client-update",heartbeatInterval:this.configuration.heartbeatInterval,clientIdentifier:this.configuration.clientIdentifier,subscriptionKey:this.configuration.subscriptionKey,userId:this.configuration.userId,workerLogLevel:this.configuration.workerLogLevel})}onPresenceStateChange(e){this.scheduleEventPost({type:"client-presence-state-update",clientIdentifier:this.configuration.clientIdentifier,subscriptionKey:this.configuration.subscriptionKey,workerLogLevel:this.configuration.workerLogLevel,state:e})}onHeartbeatIntervalChange(e){this.configuration.heartbeatInterval=e,this.scheduleEventPost({type:"client-update",heartbeatInterval:this.configuration.heartbeatInterval,clientIdentifier:this.configuration.clientIdentifier,subscriptionKey:this.configuration.subscriptionKey,userId:this.configuration.userId,workerLogLevel:this.configuration.workerLogLevel})}onTokenChange(e){const t={type:"client-update",heartbeatInterval:this.configuration.heartbeatInterval,clientIdentifier:this.configuration.clientIdentifier,subscriptionKey:this.configuration.subscriptionKey,userId:this.configuration.userId,workerLogLevel:this.configuration.workerLogLevel};this.parsedAccessToken(e).then((s=>{t.preProcessedToken=s,t.accessToken=e})).then((()=>this.scheduleEventPost(t)))}disconnect(){this.scheduleEventPost({type:"client-disconnect",clientIdentifier:this.configuration.clientIdentifier,subscriptionKey:this.configuration.subscriptionKey,workerLogLevel:this.configuration.workerLogLevel})}terminate(){this.scheduleEventPost({type:"client-unregister",clientIdentifier:this.configuration.clientIdentifier,subscriptionKey:this.configuration.subscriptionKey,workerLogLevel:this.configuration.workerLogLevel})}makeSendable(e){if(!e.path.startsWith("/v2/subscribe")&&!e.path.endsWith("/heartbeat")&&!e.path.endsWith("/leave"))return this.configuration.transport.makeSendable(e);let t;this.configuration.logger.debug("SubscriptionWorkerMiddleware","Process request with SharedWorker transport.");const s={type:"send-request",clientIdentifier:this.configuration.clientIdentifier,subscriptionKey:this.configuration.subscriptionKey,request:e,workerLogLevel:this.configuration.workerLogLevel};return e.cancellable&&(t={abort:()=>{const t={type:"cancel-request",clientIdentifier:this.configuration.clientIdentifier,subscriptionKey:this.configuration.subscriptionKey,identifier:e.identifier,workerLogLevel:this.configuration.workerLogLevel};this.scheduleEventPost(t)}}),[new Promise(((t,n)=>{this.callbacks.set(e.identifier,{resolve:t,reject:n}),this.parsedAccessTokenForRequest(e).then((e=>s.preProcessedToken=e)).then((()=>this.scheduleEventPost(s)))})),t]}request(e){return e}scheduleEventPost(e,t=!1){const s=this.sharedSubscriptionWorker;s?s.port.postMessage(e):t?this.workerEventsQueue.splice(0,0,e):this.workerEventsQueue.push(e)}flushScheduledEvents(){const e=this.sharedSubscriptionWorker;if(!e||0===this.workerEventsQueue.length)return;const t=[];for(let e=0;e!t.includes(e))),this.workerEventsQueue.forEach((t=>e.port.postMessage(t))),this.workerEventsQueue=[]}get sharedSubscriptionWorker(){return this.subscriptionWorkerReady?this.subscriptionWorker:null}setupSubscriptionWorker(){if("undefined"!=typeof SharedWorker){try{this.subscriptionWorker=new SharedWorker(this.configuration.workerUrl,`/pubnub-${this.configuration.sdkVersion}`)}catch(e){throw this.configuration.logger.error("SubscriptionWorkerMiddleware",(()=>({messageType:"error",message:e}))),e}this.subscriptionWorker.port.start(),this.scheduleEventPost({type:"client-register",clientIdentifier:this.configuration.clientIdentifier,subscriptionKey:this.configuration.subscriptionKey,userId:this.configuration.userId,heartbeatInterval:this.configuration.heartbeatInterval,workerOfflineClientsCheckInterval:this.configuration.workerOfflineClientsCheckInterval,workerUnsubscribeOfflineClients:this.configuration.workerUnsubscribeOfflineClients,workerLogLevel:this.configuration.workerLogLevel},!0),this.subscriptionWorker.port.onmessage=e=>this.handleWorkerEvent(e),this.shouldAnnounceNewerSharedWorkerVersionAvailability()&&localStorage.setItem("PNSubscriptionSharedWorkerVersion",this.configuration.sdkVersion),window.addEventListener("storage",(e=>{"PNSubscriptionSharedWorkerVersion"===e.key&&e.newValue&&this._emitStatus&&this.isNewerSharedWorkerVersion(e.newValue)&&this._emitStatus({error:!1,category:h.PNSharedWorkerUpdatedCategory})}))}}handleWorkerEvent(e){const{data:t}=e;if("shared-worker-ping"===t.type||"shared-worker-connected"===t.type||"shared-worker-console-log"===t.type||"shared-worker-console-dir"===t.type||t.clientIdentifier===this.configuration.clientIdentifier)if("shared-worker-connected"===t.type)this.configuration.logger.trace("SharedWorker","Ready for events processing."),this.subscriptionWorkerReady=!0,this.flushScheduledEvents();else if("shared-worker-console-log"===t.type)this.configuration.logger.debug("SharedWorker",(()=>"string"==typeof t.message||"number"==typeof t.message||"boolean"==typeof t.message?{messageType:"text",message:t.message}:t.message));else if("shared-worker-console-dir"===t.type)this.configuration.logger.debug("SharedWorker",(()=>({messageType:"object",message:t.data,details:t.message?t.message:void 0})));else if("shared-worker-ping"===t.type){const{subscriptionKey:e,clientIdentifier:t}=this.configuration;this.scheduleEventPost({type:"client-pong",subscriptionKey:e,clientIdentifier:t,workerLogLevel:this.configuration.workerLogLevel})}else if("request-process-success"===t.type||"request-process-error"===t.type)if(this.callbacks.has(t.identifier)){const{resolve:e,reject:s}=this.callbacks.get(t.identifier);this.callbacks.delete(t.identifier),"request-process-success"===t.type?e({status:t.response.status,url:t.url,headers:t.response.headers,body:t.response.body}):s(this.errorFromRequestSendingError(t))}else this._emitStatus&&t.url.indexOf("/v2/presence")>=0&&t.url.indexOf("/heartbeat")>=0&&("request-process-success"===t.type&&this.configuration.announceSuccessfulHeartbeats?this._emitStatus({statusCode:t.response.status,error:!1,operation:K.PNHeartbeatOperation,category:h.PNAcknowledgmentCategory}):"request-process-error"===t.type&&this.configuration.announceFailedHeartbeats&&this._emitStatus(this.errorFromRequestSendingError(t).toStatus(K.PNHeartbeatOperation)))}parsedAccessTokenForRequest(e){return r(this,void 0,void 0,(function*(){var t;return this.parsedAccessToken(e.queryParameters?null!==(t=e.queryParameters.auth)&&void 0!==t?t:"":void 0)}))}parsedAccessToken(e){return r(this,void 0,void 0,(function*(){if(e)return this.accessTokensMap[e]?this.accessTokensMap[e]:this.stringifyAccessToken(e).then((([t,s])=>{if(t&&s)return(this.accessTokensMap={[e]:{token:s,expiration:t.timestamp+60*t.ttl}})[e]}))}))}stringifyAccessToken(e){return r(this,void 0,void 0,(function*(){if(!this.configuration.tokenManager)return[void 0,void 0];const t=this.configuration.tokenManager.parseToken(e);if(!t)return[void 0,void 0];const s=e=>e?Object.entries(e).sort((([e],[t])=>e.localeCompare(t))).map((([e,t])=>Object.entries(t||{}).sort((([e],[t])=>e.localeCompare(t))).map((([t,s])=>{return`${e}:${t}=${s?(n=s,Object.entries(n).filter((([e,t])=>t)).map((([e])=>e[0])).sort().join("")):""}`;var n})).join(","))).join(";"):"";let n=[s(t.resources),s(t.patterns),t.authorized_uuid].filter(Boolean).join("|");if("undefined"!=typeof crypto&&crypto.subtle){const e=yield crypto.subtle.digest("SHA-256",(new TextEncoder).encode(n));n=String.fromCharCode(...Array.from(new Uint8Array(e)))}return[t,"undefined"!=typeof btoa?btoa(n):n]}))}errorFromRequestSendingError(e){let t=h.PNUnknownCategory,s="Unknown error";if(e.error)"NETWORK_ISSUE"===e.error.type?t=h.PNNetworkIssuesCategory:"TIMEOUT"===e.error.type?t=h.PNTimeoutCategory:"ABORTED"===e.error.type&&(t=h.PNCancelledCategory),s=`${e.error.message} (${e.identifier})`;else if(e.response){const{url:t,response:s}=e;return G.create({url:t,headers:s.headers,body:s.body,status:s.status},s.body)}return new G(s,t,0,new Error(s))}shouldAnnounceNewerSharedWorkerVersionAvailability(){const e=localStorage.getItem("PNSubscriptionSharedWorkerVersion");return!e||!this.isNewerSharedWorkerVersion(e)}isNewerSharedWorkerVersion(e){const[t,s,n]=this.configuration.sdkVersion.split(".").map(Number),[i,r,a]=e.split(".").map(Number);return i>t||r>s||a>n}}function B(e,t=0){const s=e=>"object"==typeof e&&null!==e&&e.constructor===Object,n=e=>"number"==typeof e&&isFinite(e);if(!s(e))return e;const i={};return Object.keys(e).forEach((r=>{const a=(e=>"string"==typeof e||e instanceof String)(r);let o=r;const c=e[r];if(t<2)if(a&&r.indexOf(",")>=0){o=r.split(",").map(Number).reduce(((e,t)=>e+String.fromCharCode(t)),"")}else(n(r)||a&&!isNaN(Number(r)))&&(o=String.fromCharCode(n(r)?r:parseInt(r,10)));i[o]=s(c)?B(c,t+1):c})),i}const W=e=>{var t,s,n,i,r,a;return e.subscriptionWorkerUrl&&"undefined"==typeof SharedWorker&&(e.subscriptionWorkerUrl=null),Object.assign(Object.assign({},(e=>{var t,s,n,i,r,a,o,c,u,l,h,p,g,b,y;const m=Object.assign({},e);if(null!==(t=m.ssl)&&void 0!==t||(m.ssl=!0),null!==(s=m.transactionalRequestTimeout)&&void 0!==s||(m.transactionalRequestTimeout=15),null!==(n=m.subscribeRequestTimeout)&&void 0!==n||(m.subscribeRequestTimeout=310),null!==(i=m.fileRequestTimeout)&&void 0!==i||(m.fileRequestTimeout=300),null!==(r=m.restore)&&void 0!==r||(m.restore=!0),null!==(a=m.useInstanceId)&&void 0!==a||(m.useInstanceId=!1),null!==(o=m.suppressLeaveEvents)&&void 0!==o||(m.suppressLeaveEvents=!1),null!==(c=m.requestMessageCountThreshold)&&void 0!==c||(m.requestMessageCountThreshold=100),null!==(u=m.autoNetworkDetection)&&void 0!==u||(m.autoNetworkDetection=!1),null!==(l=m.enableEventEngine)&&void 0!==l||(m.enableEventEngine=!0),null!==(h=m.maintainPresenceState)&&void 0!==h||(m.maintainPresenceState=!0),null!==(p=m.useSmartHeartbeat)&&void 0!==p||(m.useSmartHeartbeat=!1),null!==(g=m.keepAlive)&&void 0!==g||(m.keepAlive=!1),m.userId&&m.uuid)throw new d("PubNub client configuration error: use only 'userId'");if(null!==(b=m.userId)&&void 0!==b||(m.userId=m.uuid),!m.userId)throw new d("PubNub client configuration error: 'userId' not set");if(0===(null===(y=m.userId)||void 0===y?void 0:y.trim().length))throw new d("PubNub client configuration error: 'userId' is empty");m.origin||(m.origin=Array.from({length:20},((e,t)=>`ps${t+1}.pndsn.com`)));const f={subscribeKey:m.subscribeKey,publishKey:m.publishKey,secretKey:m.secretKey};void 0!==m.presenceTimeout&&(m.presenceTimeout>320?(m.presenceTimeout=320,console.warn("WARNING: Presence timeout is larger than the maximum. Using maximum value: ",320)):m.presenceTimeout<=0&&(console.warn("WARNING: Presence timeout should be larger than zero."),delete m.presenceTimeout)),void 0!==m.presenceTimeout?m.heartbeatInterval=m.presenceTimeout/2-1:m.presenceTimeout=300;let v=!1,O=!0,S=5,j=!1,w=100,k=!0;return void 0!==m.dedupeOnSubscribe&&"boolean"==typeof m.dedupeOnSubscribe&&(j=m.dedupeOnSubscribe),void 0!==m.maximumCacheSize&&"number"==typeof m.maximumCacheSize&&(w=m.maximumCacheSize),void 0!==m.useRequestId&&"boolean"==typeof m.useRequestId&&(k=m.useRequestId),void 0!==m.announceSuccessfulHeartbeats&&"boolean"==typeof m.announceSuccessfulHeartbeats&&(v=m.announceSuccessfulHeartbeats),void 0!==m.announceFailedHeartbeats&&"boolean"==typeof m.announceFailedHeartbeats&&(O=m.announceFailedHeartbeats),void 0!==m.fileUploadPublishRetryLimit&&"number"==typeof m.fileUploadPublishRetryLimit&&(S=m.fileUploadPublishRetryLimit),Object.assign(Object.assign({},m),{keySet:f,dedupeOnSubscribe:j,maximumCacheSize:w,useRequestId:k,announceSuccessfulHeartbeats:v,announceFailedHeartbeats:O,fileUploadPublishRetryLimit:S})})(e)),{listenToBrowserNetworkEvents:null===(t=e.listenToBrowserNetworkEvents)||void 0===t||t,subscriptionWorkerUrl:e.subscriptionWorkerUrl,subscriptionWorkerOfflineClientsCheckInterval:null!==(s=e.subscriptionWorkerOfflineClientsCheckInterval)&&void 0!==s?s:10,subscriptionWorkerUnsubscribeOfflineClients:null!==(n=e.subscriptionWorkerUnsubscribeOfflineClients)&&void 0!==n&&n,subscriptionWorkerLogVerbosity:null!==(i=e.subscriptionWorkerLogVerbosity)&&void 0!==i&&i,transport:null!==(r=e.transport)&&void 0!==r?r:"fetch",keepAlive:null===(a=e.keepAlive)||void 0===a||a})};var V;!function(e){e[e.Trace=0]="Trace",e[e.Debug=1]="Debug",e[e.Info=2]="Info",e[e.Warn=3]="Warn",e[e.Error=4]="Error",e[e.None=5]="None"}(V||(V={}));class z{debug(e){this.log(e)}error(e){this.log(e)}info(e){this.log(e)}trace(e){this.log(e)}warn(e){this.log(e)}toString(){return"ConsoleLogger {}"}log(e){const t=V[e.level],s=t.toLowerCase();console["trace"===s?"debug":s](`${e.timestamp.toISOString()} PubNub-${e.pubNubId} ${t.padEnd(5," ")}${e.location?` ${e.location}`:""} ${this.logMessage(e)}`)}logMessage(e){if("text"===e.messageType)return e.message;if("object"===e.messageType)return`${e.details?`${e.details}\n`:""}${this.formattedObject(e)}`;if("network-request"===e.messageType){const t=!!e.canceled||!!e.failed,s=e.minimumLevel!==V.Trace||t?void 0:this.formattedHeaders(e),n=e.message,i=n.queryParameters&&Object.keys(n.queryParameters).length>0?T(n.queryParameters):void 0,r=`${n.origin}${n.path}${i?`?${i}`:""}`,a=t?void 0:this.formattedBody(e);let o="Sending";t&&(o=`${e.canceled?"Canceled":"Failed"}${e.details?` (${e.details})`:""}`);const c=((null==a?void 0:a.formData)?"FormData":"Method").length;return`${o} HTTP request:\n ${this.paddedString("Method",c)}: ${n.method}\n ${this.paddedString("URL",c)}: ${r}${s?`\n ${this.paddedString("Headers",c)}:\n${s}`:""}${(null==a?void 0:a.formData)?`\n ${this.paddedString("FormData",c)}:\n${a.formData}`:""}${(null==a?void 0:a.body)?`\n ${this.paddedString("Body",c)}:\n${a.body}`:""}`}if("network-response"===e.messageType){const t=e.minimumLevel===V.Trace?this.formattedHeaders(e):void 0,s=this.formattedBody(e),n=((null==s?void 0:s.formData)?"Headers":"Status").length,i=e.message;return`Received HTTP response:\n ${this.paddedString("URL",n)}: ${i.url}\n ${this.paddedString("Status",n)}: ${i.status}${e.details?`\n ${this.paddedString("Details",n)}: ${e.details}`:""}${t?`\n ${this.paddedString("Headers",n)}:\n${t}`:""}${(null==s?void 0:s.body)?`\n ${this.paddedString("Body",n)}:\n${s.body}`:""}`}if("error"===e.messageType){const t=this.formattedErrorStatus(e),s=e.message;return`${s.name}: ${s.message}${t?`\n${t}`:""}`}return""}formattedObject(e){const t=(s,n=1,i=!1)=>{const r=10===n,a=" ".repeat(2*n),o=[],c=(t,s)=>!!e.ignoredKeys&&("function"==typeof e.ignoredKeys?e.ignoredKeys(t,s):e.ignoredKeys.includes(t));if("string"==typeof s)o.push(`${a}- ${s}`);else if("number"==typeof s)o.push(`${a}- ${s}`);else if("boolean"==typeof s)o.push(`${a}- ${s}`);else if(null===s)o.push(`${a}- null`);else if(void 0===s)o.push(`${a}- undefined`);else if("function"==typeof s)o.push(`${a}- `);else if("object"==typeof s)if(Array.isArray(s)||"function"!=typeof s.toString||0===s.toString().indexOf("[object"))if(Array.isArray(s))for(const e of s){const s=i?"":a;if(null===e)o.push(`${s}- null`);else if(void 0===e)o.push(`${s}- undefined`);else if("function"==typeof e)o.push(`${s}- `);else if("object"==typeof e){const i=Array.isArray(e),a=r?"...":t(e,n+1,!i);o.push(`${s}-${i&&!r?"\n":" "}${a}`)}else o.push(`${s}- ${e}`);i=!1}else{const e=s,u=Object.keys(e),l=u.reduce(((t,s)=>Math.max(t,c(s,e)?t:s.length)),0);for(const s of u){if(c(s,e))continue;const u=i?"":a,h=e[s],d=s.padEnd(l," ");if(null===h)o.push(`${u}${d}: null`);else if(void 0===h)o.push(`${u}${d}: undefined`);else if("function"==typeof h)o.push(`${u}${d}: `);else if("object"==typeof h){const e=Array.isArray(h),s=e&&0===h.length,i=!(e||h instanceof String||0!==Object.keys(h).length),a=!e&&"function"==typeof h.toString&&0!==h.toString().indexOf("[object"),c=r?"...":s?"[]":i?"{}":t(h,n+1,a);o.push(`${u}${d}:${r||a||s||i?" ":"\n"}${c}`)}else o.push(`${u}${d}: ${h}`);i=!1}}else o.push(`${i?"":a}${s.toString()}`),i=!1;return o.join("\n")};return t(e.message)}formattedHeaders(e){if(!e.message.headers)return;const t=e.message.headers,s=Object.keys(t).reduce(((e,t)=>Math.max(e,t.length)),0);return Object.keys(t).map((e=>` - ${e.toLowerCase().padEnd(s," ")}: ${t[e]}`)).join("\n")}formattedBody(e){var t;if(!e.message.headers)return;let s,n;const i=e.message.headers,r=null!==(t=i["content-type"])&&void 0!==t?t:i["Content-Type"],a="formData"in e.message?e.message.formData:void 0,o=e.message.body;if(a){const e=a.reduce(((e,{key:t})=>Math.max(e,t.length)),0);s=a.map((({key:t,value:s})=>` - ${t.padEnd(e," ")}: ${s}`)).join("\n")}return o?(n="string"==typeof o?` ${o}`:o instanceof ArrayBuffer||"[object ArrayBuffer]"===Object.prototype.toString.call(o)?!r||-1===r.indexOf("javascript")&&-1===r.indexOf("json")?` ArrayBuffer { byteLength: ${o.byteLength} }`:` ${z.decoder.decode(o)}`:` File { name: ${o.name}${o.contentLength?`, contentLength: ${o.contentLength}`:""}${o.mimeType?`, mimeType: ${o.mimeType}`:""} }`,{body:n,formData:s}):{formData:s}}formattedErrorStatus(e){if(!e.message.status)return;const t=e.message.status,s=t.errorData;let n;if(z.isError(s))n=` ${s.name}: ${s.message}`,s.stack&&(n+=`\n${s.stack.split("\n").map((e=>` ${e}`)).join("\n")}`);else if(s)try{n=` ${JSON.stringify(s)}`}catch(e){n=` ${s}`}return` Category : ${t.category}\n Operation : ${t.operation}\n Status : ${t.statusCode}${n?`\n Error data:\n${n}`:""}`}paddedString(e,t){return e.padEnd(t-e.length," ")}static isError(e){return!!e&&(e instanceof Error||"[object Error]"===Object.prototype.toString.call(e))}}z.decoder=new TextDecoder;const J=[404,409];var X;!function(e){e.Unknown="UnknownEndpoint",e.MessageSend="MessageSendEndpoint",e.Subscribe="SubscribeEndpoint",e.Presence="PresenceEndpoint",e.Files="FilesEndpoint",e.MessageStorage="MessageStorageEndpoint",e.ChannelGroups="ChannelGroupsEndpoint",e.DevicePushNotifications="DevicePushNotificationsEndpoint",e.AppContext="AppContextEndpoint",e.MessageReactions="MessageReactionsEndpoint"}(X||(X={}));class Q{static None(){return{shouldRetry:(e,t,s,n,i)=>!1,getDelay:(e,t)=>-1,validate:()=>!0}}static LinearRetryPolicy(e){var t;return{delay:e.delay,maximumRetry:e.maximumRetry,excluded:null!==(t=e.excluded)&&void 0!==t?t:[],shouldRetry(e,t,s,n,i){return Y(e,t,s,null!=n?n:0,this.maximumRetry,this.excluded,i)},getDelay(e,t){let s=-1;return t&&void 0!==t.headers["retry-after"]&&(s=parseInt(t.headers["retry-after"],10)),-1===s&&(s=this.delay),1e3*(s+Math.random())},validate(){if(this.delay<2)throw new Error("Delay can not be set less than 2 seconds for retry")}}}static ExponentialRetryPolicy(e){var t;return{minimumDelay:e.minimumDelay,maximumDelay:e.maximumDelay,maximumRetry:e.maximumRetry,excluded:null!==(t=e.excluded)&&void 0!==t?t:[],shouldRetry(e,t,s,n,i){return Y(e,t,s,null!=n?n:0,this.maximumRetry,this.excluded,i)},getDelay(e,t){let s=-1;return t&&void 0!==t.headers["retry-after"]&&(s=parseInt(t.headers["retry-after"],10)),-1===s&&(s=Math.min(this.minimumDelay*Math.pow(2,e),this.maximumDelay)),1e3*(s+Math.random())},validate(){if(this.minimumDelay<2)throw new Error("Minimum delay can not be set less than 2 seconds for retry")}}}}const Y=(e,t,s,n,i,r,a)=>{var o;if(s&&(s===h.PNCancelledCategory||s===h.PNBadRequestCategory||s===h.PNAccessDeniedCategory))return!1;if(Z(e,r))return!1;if(n>i)return!1;const c=null!==(o=null==t?void 0:t.status)&&void 0!==o?o:a;return(void 0===c||!J.includes(c))&&(!t||(429===t.status||t.status>=500))},Z=(e,t)=>!!(t&&t.length>0)&&t.includes(ee(e)),ee=e=>{let t=X.Unknown;return e.path.startsWith("/v2/subscribe")?t=X.Subscribe:e.path.startsWith("/publish/")||e.path.startsWith("/signal/")?t=X.MessageSend:e.path.startsWith("/v2/presence")?t=X.Presence:e.path.startsWith("/v2/history")||e.path.startsWith("/v3/history")?t=X.MessageStorage:e.path.startsWith("/v1/message-actions/")?t=X.MessageReactions:e.path.startsWith("/v1/channel-registration/")||e.path.startsWith("/v2/objects/")?t=X.ChannelGroups:e.path.startsWith("/v1/push/")||e.path.startsWith("/v2/push/")?t=X.DevicePushNotifications:e.path.startsWith("/v1/files/")&&(t=X.Files),t};class te{constructor(e,t,s){this.previousEntryTimestamp=0,this.pubNubId=e,this.minLogLevel=t,this.loggers=s}get logLevel(){return this.minLogLevel}trace(e,t){this.log(V.Trace,e,t)}debug(e,t){this.log(V.Debug,e,t)}info(e,t){this.log(V.Info,e,t)}warn(e,t){this.log(V.Warn,e,t)}error(e,t){this.log(V.Error,e,t)}log(e,t,s){if(ee[i](r)))}}var se={exports:{}}; -/*! lil-uuid - v0.1 - MIT License - https://github.com/lil-js/uuid */!function(e,t){!function(e){var t="0.1.0",s={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i};function n(){var e,t,s="";for(e=0;e<32;e++)t=16*Math.random()|0,8!==e&&12!==e&&16!==e&&20!==e||(s+="-"),s+=(12===e?4:16===e?3&t|8:t).toString(16);return s}function i(e,t){var n=s[t||"all"];return n&&n.test(e)||!1}n.isUUID=i,n.VERSION=t,e.uuid=n,e.isUUID=i}(t),null!==e&&(e.exports=t.uuid)}(se,se.exports);var ne=t(se.exports),ie={createUUID:()=>ne.uuid?ne.uuid():ne()};const re=(e,t)=>{var s,n,i,r;!e.retryConfiguration&&e.enableEventEngine&&(e.retryConfiguration=Q.ExponentialRetryPolicy({minimumDelay:2,maximumDelay:150,maximumRetry:6,excluded:[X.MessageSend,X.Presence,X.Files,X.MessageStorage,X.ChannelGroups,X.DevicePushNotifications,X.AppContext,X.MessageReactions]}));const a=`pn-${ie.createUUID()}`;e.logVerbosity?e.logLevel=V.Debug:void 0===e.logLevel&&(e.logLevel=V.None);const o=new te(oe(a),e.logLevel,[...null!==(s=e.loggers)&&void 0!==s?s:[],new z]);void 0!==e.logVerbosity&&o.warn("Configuration","'logVerbosity' is deprecated. Use 'logLevel' instead."),null===(n=e.retryConfiguration)||void 0===n||n.validate();const c=e.useRandomIVs;null!==(i=e.useRandomIVs)&&void 0!==i||(e.useRandomIVs=true),void 0!==c&&(o.warn("Configuration","'useRandomIVs' is deprecated. Pass it to 'cryptoModule' instead."),!1===c&&o.warn("Configuration","Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients.\n Do not disable random IVs in new applications.")),e.origin=ae(null!==(r=e.ssl)&&void 0!==r&&r,e.origin);const u=e.cryptoModule;u&&delete e.cryptoModule;const l=Object.assign(Object.assign({},e),{_pnsdkSuffix:{},_loggerManager:o,_instanceId:a,_cryptoModule:void 0,_cipherKey:void 0,_setupCryptoModule:t,get instanceId(){if(e.useInstanceId)return this._instanceId},getInstanceId(){if(e.useInstanceId)return this._instanceId},getUserId(){return this.userId},setUserId(e){if(!e||"string"!=typeof e||0===e.trim().length)throw new Error("Missing or invalid userId parameter. Provide a valid string userId");this.userId=e},logger(){return this._loggerManager},getAuthKey(){return this.authKey},setAuthKey(e){this.authKey=e},getFilterExpression(){return this.filterExpression},setFilterExpression(e){this.filterExpression=e},getCipherKey(){return this._cipherKey},setCipherKey(t){this._cipherKey=t,t||!this._cryptoModule?t&&this._setupCryptoModule&&(this._cryptoModule=this._setupCryptoModule({cipherKey:t,useRandomIVs:e.useRandomIVs,customEncrypt:this.getCustomEncrypt(),customDecrypt:this.getCustomDecrypt(),logger:this.logger()})):this._cryptoModule=void 0},getCryptoModule(){return this._cryptoModule},getUseRandomIVs:()=>e.useRandomIVs,isSharedWorkerEnabled:()=>"Web"===e.sdkFamily&&e.subscriptionWorkerUrl,getKeepPresenceChannelsInPresenceRequests:()=>"Web"===e.sdkFamily&&e.subscriptionWorkerUrl,setPresenceTimeout(e){this.heartbeatInterval=e/2-1,this.presenceTimeout=e},getPresenceTimeout(){return this.presenceTimeout},getHeartbeatInterval(){return this.heartbeatInterval},setHeartbeatInterval(e){this.heartbeatInterval=e},getTransactionTimeout(){return this.transactionalRequestTimeout},getSubscribeTimeout(){return this.subscribeRequestTimeout},getFileTimeout(){return this.fileRequestTimeout},get PubNubFile(){return e.PubNubFile},get version(){return"13.1.2"},getVersion(){return this.version},_addPnsdkSuffix(e,t){this._pnsdkSuffix[e]=`${t}`},_getPnsdkSuffix(e){const t=Object.values(this._pnsdkSuffix).join(e);return t.length>0?e+t:""},getUUID(){return this.getUserId()},setUUID(e){this.setUserId(e)},getCustomEncrypt:()=>e.customEncrypt,getCustomDecrypt:()=>e.customDecrypt});return e.cipherKey?(o.warn("Configuration","'cipherKey' is deprecated. Use 'cryptoModule' instead."),l.setCipherKey(e.cipherKey)):u&&(l._cryptoModule=u),l},ae=(e,t)=>{const s=e?"https://":"http://";return"string"==typeof t?`${s}${t}`:`${s}${t[Math.floor(Math.random()*t.length)]}`},oe=e=>{let t=2166136261;for(let s=0;s>>0;return t.toString(16).padStart(8,"0")};class ce{constructor(e){this.cbor=e}setToken(e){e&&e.length>0?this.token=e:this.token=void 0}getToken(){return this.token}parseToken(e){var t,s;const n=this.cbor.decodeToken(e);if(void 0!==n){const e=n.res.uuid?Object.keys(n.res.uuid):[],i=n.res.usr?Object.keys(n.res.usr):[],r=Object.keys(n.res.chan),a=Object.keys(n.res.grp),o=n.pat.uuid?Object.keys(n.pat.uuid):[],c=n.pat.usr?Object.keys(n.pat.usr):[],u=Object.keys(n.pat.chan),l=Object.keys(n.pat.grp),h={version:n.v,timestamp:n.t,ttl:n.ttl,authorized_uuid:n.uuid,signature:n.sig},d=e.length>0,p=i.length>0,g=r.length>0,b=a.length>0;if(d||p||g||b){if(h.resources={},d){const t=h.resources.uuids={};e.forEach((e=>t[e]=this.extractPermissions(n.res.uuid[e])))}if(p){const e=h.resources.users={};i.forEach((t=>e[t]=this.extractCrudPermissions(n.res.usr[t])))}if(g){const e=h.resources.channels={};r.forEach((t=>e[t]=this.extractPermissions(n.res.chan[t])))}if(b){const e=h.resources.groups={};a.forEach((t=>e[t]=this.extractPermissions(n.res.grp[t])))}}const y=this.extractDataSyncScopes(n.res);y&&((null!==(t=h.resources)&&void 0!==t?t:h.resources={}).dataSync=y);const m=o.length>0,f=c.length>0,v=u.length>0,O=l.length>0;if(m||f||v||O){if(h.patterns={},m){const e=h.patterns.uuids={};o.forEach((t=>e[t]=this.extractPermissions(n.pat.uuid[t])))}if(f){const e=h.patterns.users={};c.forEach((t=>e[t]=this.extractCrudPermissions(n.pat.usr[t])))}if(v){const e=h.patterns.channels={};u.forEach((t=>e[t]=this.extractPermissions(n.pat.chan[t])))}if(O){const e=h.patterns.groups={};l.forEach((t=>e[t]=this.extractPermissions(n.pat.grp[t])))}}const S=this.extractDataSyncScopes(n.pat);S&&((null!==(s=h.patterns)&&void 0!==s?s:h.patterns={}).dataSync=S);const j=this.extractCategories(n.cat);return j&&(h.categories=j),n.meta&&Object.keys(n.meta).length>0&&(h.meta=n.meta),h}}extractPermissions(e){const t={read:!1,write:!1,manage:!1,delete:!1,get:!1,update:!1,join:!1};return 128&~e||(t.join=!0),64&~e||(t.update=!0),32&~e||(t.get=!0),8&~e||(t.delete=!0),4&~e||(t.manage=!0),2&~e||(t.write=!0),1&~e||(t.read=!0),t}extractCategories(e){if(!e)return;const t={};return"number"==typeof e.chan&&(t.channels={get:!(32&~e.chan)}),"number"==typeof e.uuid&&(t.uuids={get:!(32&~e.uuid)}),Object.keys(t).length>0?t:void 0}extractDataSyncScopes(e){let t;return[["entities","datasync:entities"],["relationships","datasync:relationships"],["memberships","datasync:memberships"]].forEach((([s,n])=>{const i=e[n];if(!i)return;const r=Object.keys(i);if(0===r.length)return;const a=(null!=t?t:t={})[s]={};r.forEach((e=>a[e]=this.extractCrudPermissions(i[e])))})),t}extractCrudPermissions(e){return{create:!(16&~e),get:!(32&~e),update:!(64&~e),delete:!(8&~e)}}}var ue;!function(e){e.GET="GET",e.POST="POST",e.PATCH="PATCH",e.PUT="PUT",e.DELETE="DELETE",e.LOCAL="LOCAL"}(ue||(ue={}));class le{constructor(e,t,s,n){this.publishKey=e,this.secretKey=t,this.hasher=s,this.logger=n}signature(e){const t=e.path.startsWith("/publish")?ue.GET:e.method;let s=`${t}\n${this.publishKey}\n${e.path}\n${this.queryParameters(e.queryParameters)}\n`;if(t===ue.POST||t===ue.PATCH||t===ue.PUT){const t=e.body;let n;t&&t instanceof ArrayBuffer?n=le.textDecoder.decode(t):t&&"object"!=typeof t&&(n=t),n&&(s+=n)}return this.logger.trace("RequestSignature",(()=>({messageType:"text",message:`Request signature input:\n${s}`}))),`v2.${this.hasher(s,this.secretKey)}`.replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}queryParameters(e){return Object.keys(e).sort().map((t=>{const s=e[t];return Array.isArray(s)?s.sort().map((e=>`${t}=${C(e)}`)).join("&"):`${t}=${C(s)}`})).join("&")}}le.textDecoder=new TextDecoder("utf-8");class he{constructor(e){this.configuration=e;const{clientConfiguration:{keySet:t},shaHMAC:s}=e;t.secretKey&&s&&(this.signatureGenerator=new le(t.publishKey,t.secretKey,s,this.logger))}get logger(){return this.configuration.clientConfiguration.logger()}makeSendable(e){const t=this.configuration.clientConfiguration.retryConfiguration,s=this.configuration.transport;if(void 0!==t){let n,i,r=!1,a=0;const o={abort:e=>{r=!0,n&&clearTimeout(n),i&&i.abort(e)}};return[new Promise(((o,c)=>{const u=()=>{if(r)return;const[l,h]=s.makeSendable(this.request(e));i=h;const d=(s,i)=>{let r=-1;t.shouldRetry(e,s,null==i?void 0:i.category,a+1,null==i?void 0:i.statusCode)&&(r=t.getDelay(a,s)),r>0?(a++,this.logger.warn("PubNubMiddleware",`HTTP request retry #${a} in ${r}ms.`),n=setTimeout((()=>u()),r)):s?o(s):i&&c(i)};l.then((e=>d(e))).catch((e=>d(void 0,e)))};u()})),i?o:void 0]}return s.makeSendable(this.request(e))}request(e){var t;const{clientConfiguration:s}=this.configuration;return(e=this.configuration.transport.request(e)).queryParameters||(e.queryParameters={}),s.useInstanceId&&(e.queryParameters.instanceid=s.getInstanceId()),e.queryParameters.uuid||(e.queryParameters.uuid=s.userId),s.useRequestId&&(e.queryParameters.requestid=e.identifier),e.queryParameters.pnsdk=this.generatePNSDK(),null!==(t=e.origin)&&void 0!==t||(e.origin=s.origin),this.authenticateRequest(e),this.signRequest(e),e}authenticateRequest(e){var t;if(e.path.startsWith("/v2/auth/")||e.path.startsWith("/v3/pam/")||e.path.startsWith("/time"))return;const{clientConfiguration:s,tokenManager:n}=this.configuration,i=null!==(t=n&&n.getToken())&&void 0!==t?t:s.authKey;i&&(e.queryParameters.auth=i)}signRequest(e){this.signatureGenerator&&!e.path.startsWith("/time")&&(e.queryParameters.timestamp=String(Math.floor((new Date).getTime()/1e3)),e.queryParameters.signature=this.signatureGenerator.signature(e))}generatePNSDK(){const{clientConfiguration:e}=this.configuration;if(e.sdkName)return e.sdkName;let t=`PubNub-JS-${e.sdkFamily}`;e.partnerId&&(t+=`-${e.partnerId}`),t+=`/${e.getVersion()}`;const s=e._getPnsdkSuffix(" ");return s.length>0&&(t+=s),t}}class de{constructor(e,t="fetch"){this.logger=e,this.transport=t,e.debug("WebTransport",`Create with configuration:\n - transport: ${t}`),"fetch"===t&&"undefined"==typeof fetch&&(e.warn("WebTransport",`'${t}' not supported in this browser. Fallback to the 'xhr' transport.`),this.transport="xhr"),"fetch"===this.transport&&(de.originalFetch=de.getOriginalFetch(),this.isFetchMonkeyPatched()&&e.warn("WebTransport","Native Web Fetch API 'fetch' function monkey patched."))}makeSendable(e){const t=new AbortController,s={abortController:t,abort:e=>{t.signal.aborted||(this.logger.trace("WebTransport",`On-demand request aborting: ${e}`),t.abort(e))}};return[this.webTransportRequestFromTransportRequest(e).then((t=>(this.logger.debug("WebTransport",(()=>({messageType:"network-request",message:e}))),this.sendRequest(t,s).then((e=>e.arrayBuffer().then((t=>[e,t])))).then((e=>{const s=e[1].byteLength>0?e[1]:void 0,{status:n,headers:i}=e[0],r={};i.forEach(((e,t)=>r[t]=e.toLowerCase()));const a={status:n,url:t.url,headers:r,body:s};if(this.logger.debug("WebTransport",(()=>({messageType:"network-response",message:a}))),n>=400)throw G.create(a);return a})).catch((t=>{const s=("string"==typeof t?t:t.message).toLowerCase();let n="string"==typeof t?new Error(t):t;throw s.includes("timeout")?this.logger.warn("WebTransport",(()=>({messageType:"network-request",message:e,details:"Timeout",canceled:!0}))):s.includes("cancel")||s.includes("abort")?(this.logger.debug("WebTransport",(()=>({messageType:"network-request",message:e,details:"Aborted",canceled:!0}))),n=new Error("Aborted"),n.name="AbortError"):s.includes("network")?this.logger.warn("WebTransport",(()=>({messageType:"network-request",message:e,details:"Network error",failed:!0}))):this.logger.warn("WebTransport",(()=>({messageType:"network-request",message:e,details:G.create(n).message,failed:!0}))),G.create(n)}))))),s]}request(e){return e}sendRequest(e,t){return r(this,void 0,void 0,(function*(){return"fetch"===this.transport?this.sendFetchRequest(e,t):this.sendXHRRequest(e,t)}))}sendFetchRequest(e,t){return r(this,void 0,void 0,(function*(){let s;const n=new Promise(((n,i)=>{s=setTimeout((()=>{clearTimeout(s),i(new Error("Request timeout")),t.abort("Cancel because of timeout")}),1e3*e.timeout)})),i=new Request(e.url,{method:e.method,headers:e.headers,redirect:"follow",body:e.body});return Promise.race([de.originalFetch(i,{signal:t.abortController.signal,credentials:"omit",cache:"no-cache"}).then((e=>(s&&clearTimeout(s),e))),n])}))}sendXHRRequest(e,t){return r(this,void 0,void 0,(function*(){return new Promise(((s,n)=>{var i;const r=new XMLHttpRequest;r.open(e.method,e.url,!0);let a=!1;r.responseType="arraybuffer",r.timeout=1e3*e.timeout,t.abortController.signal.onabort=()=>{r.readyState!=XMLHttpRequest.DONE&&r.readyState!=XMLHttpRequest.UNSENT&&(a=!0,r.abort())},Object.entries(null!==(i=e.headers)&&void 0!==i?i:{}).forEach((([e,t])=>r.setRequestHeader(e,t))),r.onabort=()=>{n(new Error("Aborted"))},r.ontimeout=()=>{n(new Error("Request timeout"))},r.onerror=()=>{if(!a){const t=this.transportResponseFromXHR(e.url,r);n(new Error(G.create(t).message))}},r.onload=()=>{const e=new Headers;r.getAllResponseHeaders().split("\r\n").forEach((t=>{const[s,n]=t.split(": ");s.length>1&&n.length>1&&e.append(s,n)})),s(new Response(r.response,{status:r.status,headers:e,statusText:r.statusText}))},r.send(e.body)}))}))}webTransportRequestFromTransportRequest(e){return r(this,void 0,void 0,(function*(){let t,s=e.path;if(e.formData&&e.formData.length>0){e.queryParameters={};const s=e.body,n=new FormData;for(const{key:t,value:s}of e.formData)n.append(t,s);try{const e=yield s.toArrayBuffer();n.append("file",new Blob([e],{type:"application/octet-stream"}),s.name)}catch(e){this.logger.warn("WebTransport",(()=>({messageType:"error",message:e})));try{const e=yield s.toFileUri();n.append("file",e,s.name)}catch(e){this.logger.error("WebTransport",(()=>({messageType:"error",message:e})))}}t=n}else if(e.body&&("string"==typeof e.body||e.body instanceof ArrayBuffer))if(e.compressible&&"undefined"!=typeof CompressionStream){const s="string"==typeof e.body?de.encoder.encode(e.body):e.body,n=s.byteLength,i=new ReadableStream({start(e){e.enqueue(s),e.close()}});t=yield new Response(i.pipeThrough(new CompressionStream("deflate"))).arrayBuffer(),this.logger.trace("WebTransport",(()=>{const e=t.byteLength,s=(e/n).toFixed(2);return{messageType:"text",message:`Body of ${n} bytes, compressed by ${s}x to ${e} bytes.`}}))}else t=e.body;return e.queryParameters&&0!==Object.keys(e.queryParameters).length&&(s=`${s}?${T(e.queryParameters)}`),{url:`${e.origin}${s}`,method:e.method,headers:e.headers,timeout:e.timeout,body:t}}))}isFetchMonkeyPatched(e){return!(null!=e?e:fetch).toString().includes("[native code]")&&"fetch"!==fetch.name}transportResponseFromXHR(e,t){const s=t.getAllResponseHeaders().split("\n"),n={};for(const e of s){const[t,s]=e.trim().split(":");t&&s&&(n[t.toLowerCase()]=s.trim())}return{status:t.status,url:e,headers:n,body:t.response}}static getOriginalFetch(){if("undefined"==typeof document||!document.body)return fetch.bind(globalThis);let e=document.querySelector('iframe[name="pubnub-context-unpatched-fetch"]');return e||(e=document.createElement("iframe"),e.style.display="none",e.name="pubnub-context-unpatched-fetch",e.src="about:blank",document.body.appendChild(e)),e.contentWindow?e.contentWindow.fetch.bind(e.contentWindow):fetch.bind(globalThis)}}de.encoder=new TextEncoder,de.decoder=new TextDecoder;class pe{constructor(e){this.params=e,this.requestIdentifier=ie.createUUID(),this._cancellationController=null}get cancellationController(){return this._cancellationController}set cancellationController(e){this._cancellationController=e}abort(e){this&&this.cancellationController&&this.cancellationController.abort(e)}operation(){throw Error("Should be implemented by subclass.")}validate(){}parse(e){return r(this,void 0,void 0,(function*(){return this.deserializeResponse(e)}))}request(){var e,t,s,n,i,r;const a={method:null!==(t=null===(e=this.params)||void 0===e?void 0:e.method)&&void 0!==t?t:ue.GET,path:this.path,queryParameters:this.queryParameters,cancellable:null!==(n=null===(s=this.params)||void 0===s?void 0:s.cancellable)&&void 0!==n&&n,compressible:null!==(r=null===(i=this.params)||void 0===i?void 0:i.compressible)&&void 0!==r&&r,timeout:10,identifier:this.requestIdentifier},o=this.headers;if(o&&(a.headers=o),a.method===ue.POST||a.method===ue.PATCH||a.method===ue.PUT){const[e,t]=[this.body,this.formData];t&&(a.formData=t),e&&(a.body=e)}return a}get headers(){var e,t;return Object.assign({"Accept-Encoding":"gzip, deflate"},null!==(t=null===(e=this.params)||void 0===e?void 0:e.compressible)&&void 0!==t&&t?{"Content-Encoding":"deflate"}:{})}get path(){throw Error("`path` getter should be implemented by subclass.")}get queryParameters(){return{}}get formData(){}get body(){}deserializeResponse(e){const t=pe.decoder.decode(e.body),s=e.headers["content-type"];let n;if(!s||-1===s.indexOf("javascript")&&-1===s.indexOf("json"))throw new d("Service response error, check status for details",g(t,e.status));try{n=JSON.parse(t)}catch(s){throw console.error("Error parsing JSON response:",s),new d("Service response error, check status for details",g(t,e.status))}if("status"in n&&"number"==typeof n.status&&n.status>=400)throw G.create(e);return n}}pe.decoder=new TextDecoder;var ge;!function(e){e[e.Presence=-2]="Presence",e[e.Message=-1]="Message",e[e.Signal=1]="Signal",e[e.AppContext=2]="AppContext",e[e.MessageAction=3]="MessageAction",e[e.Files=4]="Files",e[e.DataSync=5]="DataSync"}(ge||(ge={}));const be=new Set([ge.Presence,ge.Message,ge.Signal,ge.AppContext,ge.MessageAction,ge.Files,ge.DataSync]),ye={user:"user",channel:"channel",membership:"membership"};class me extends pe{constructor(e){var t,s,n,i,r,a;super({cancellable:!0}),this.parameters=e,null!==(t=(i=this.parameters).withPresence)&&void 0!==t||(i.withPresence=false),null!==(s=(r=this.parameters).channelGroups)&&void 0!==s||(r.channelGroups=[]),null!==(n=(a=this.parameters).channels)&&void 0!==n||(a.channels=[])}operation(){return K.PNSubscribeOperation}validate(){const{keySet:{subscribeKey:e},channels:t,channelGroups:s}=this.parameters;return e?t||s?void 0:"`channels` and `channelGroups` both should not be empty":"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){let t,s;try{s=pe.decoder.decode(e.body);t=JSON.parse(s)}catch(e){console.error("Error parsing JSON response:",e)}if(!t)throw new d("Service response error, check status for details",g(s,e.status));const n=t.m.filter((e=>{const t=void 0===e.b?e.c:e.b;return this.parameters.channels&&this.parameters.channels.includes(t)||this.parameters.channelGroups&&this.parameters.channelGroups.includes(t)})).map((e=>{let{e:t}=e;if(e.c.endsWith("-pnpres")?t=ge.Presence:null!=t||(t=ge.Message),!be.has(t))return;const s=R(e.d);if(t!=ge.Presence&&t!=ge.Signal&&"string"==typeof e.d)return t==ge.Message?{type:ge.Message,data:this.messageFromEnvelope(e),pn_mfp:s}:{type:ge.Files,data:this.fileFromEnvelope(e),pn_mfp:s};if(t==ge.Message)return{type:ge.Message,data:this.messageFromEnvelope(e),pn_mfp:s};if(t===ge.Presence)return{type:ge.Presence,data:this.presenceEventFromEnvelope(e),pn_mfp:s};if(t==ge.Signal)return{type:ge.Signal,data:this.signalFromEnvelope(e),pn_mfp:s};if(t===ge.AppContext)return{type:ge.AppContext,data:this.appContextFromEnvelope(e),pn_mfp:s};if(t===ge.MessageAction)return{type:ge.MessageAction,data:this.messageActionFromEnvelope(e),pn_mfp:s};if(t===ge.DataSync){const t=this.dataSyncFromEnvelope(e);return t?{type:ge.DataSync,data:t,pn_mfp:s}:{type:ge.Message,data:this.messageFromEnvelope(e),pn_mfp:s}}return{type:ge.Files,data:this.fileFromEnvelope(e),pn_mfp:s}})).filter((e=>void 0!==e));return{cursor:{timetoken:t.t.t,region:t.t.r},messages:n}}))}get headers(){var e;return Object.assign(Object.assign({},null!==(e=super.headers)&&void 0!==e?e:{}),{accept:"text/javascript"})}presenceEventFromEnvelope(e){var t;const{d:s}=e,[n,i]=this.subscriptionChannelFromEnvelope(e),r=n.replace("-pnpres",""),a=null!==i?r:null,o=null!==i?i:r;let c;if("string"==typeof s)try{const e=JSON.parse(s);null===e||"object"!=typeof e||Array.isArray(e)||(c=e)}catch(e){}else c=s;return c&&("data"in c?(c.state=c.data,delete c.data):"action"in c&&"interval"===c.action&&(c.hereNowRefresh=null!==(t=c.here_now_refresh)&&void 0!==t&&t,delete c.here_now_refresh)),Object.assign({channel:r,subscription:i,actualChannel:a,subscribedChannel:o,timetoken:e.p.t},null!=c?c:{})}messageFromEnvelope(e){const[t,s]=this.subscriptionChannelFromEnvelope(e),[n,i]=this.decryptedData(e.d),r={channel:t,subscription:s,actualChannel:null!==s?t:null,subscribedChannel:null!==s?s:t,timetoken:e.p.t,publisher:e.i,message:n};return e.u&&(r.userMetadata=e.u),e.cmt&&(r.customMessageType=e.cmt),i&&(r.error=i),r}signalFromEnvelope(e){const[t,s]=this.subscriptionChannelFromEnvelope(e),n={channel:t,subscription:s,timetoken:e.p.t,publisher:e.i,message:e.d};return e.u&&(n.userMetadata=e.u),e.cmt&&(n.customMessageType=e.cmt),n}messageActionFromEnvelope(e){const[t,s]=this.subscriptionChannelFromEnvelope(e),n=e.d;return{channel:t,subscription:s,timetoken:e.p.t,publisher:e.i,event:n.event,data:Object.assign(Object.assign({},n.data),{uuid:e.i})}}appContextFromEnvelope(e){const[t,s]=this.subscriptionChannelFromEnvelope(e),n=e.d;return{channel:t,subscription:s,timetoken:e.p.t,message:n}}dataSyncFromEnvelope(e){var t;const[s,n]=this.subscriptionChannelFromEnvelope(e),i=e.d,r=null==i?void 0:i.metadata;if(!r||"data-sync"!==r.source||!r.event||!r.type)return;const a=r.className?r.className.split(":"):[],o=a.filter((e=>e.length>0)),c=o.length>0?o[o.length-1]:void 0,u=r.classLevel,l=void 0===u?a[0]:"Global"===u?c:void 0,h=("entity"===r.type||"relationship"===r.type)&&l&&ye[l.toLowerCase()]||r.type,d=void 0!==r.classVersion?Number.parseInt(`${r.classVersion}`,10):NaN,p=Number.isNaN(d)?void 0:d,g=null!==(t=i.data)&&void 0!==t?t:{},b={version:i.version,source:r.source,type:r.type,className:c,classLevel:u,classVersion:p};let y;return y="delete"===r.event?Object.assign(Object.assign({},b),{event:r.event,objectType:h,data:{id:g.id,deletedAt:g.deletedAt}}):Object.assign(Object.assign({},b),{event:r.event,objectType:h,data:Object.assign({},g)}),{channel:s,subscription:n,timetoken:e.p.t,message:y}}fileFromEnvelope(e){const[t,s]=this.subscriptionChannelFromEnvelope(e),[n,i]=this.decryptedData(e.d);let r=i;const a={channel:t,subscription:s,timetoken:e.p.t,publisher:e.i};return e.u&&(a.userMetadata=e.u),n?"string"==typeof n?null!=r||(r="Unexpected file information payload data type."):(a.message=n.message,n.file&&(a.file={id:n.file.id,name:n.file.name,url:this.parameters.getFileUrl({id:n.file.id,name:n.file.name,channel:t})})):null!=r||(r="File information payload is missing."),e.cmt&&(a.customMessageType=e.cmt),r&&(a.error=r),a}subscriptionChannelFromEnvelope(e){return[e.c,void 0===e.b?e.c:e.b]}decryptedData(e){if(!this.parameters.crypto||"string"!=typeof e)return[e,void 0];let t,s;try{const s=this.parameters.crypto.decrypt(e);t=s instanceof ArrayBuffer?JSON.parse(fe.decoder.decode(s)):s}catch(e){t=null,s=`Error while decrypting message content: ${e.message}`}return[null!=t?t:e,s]}}class fe extends me{get path(){var e;const{keySet:{subscribeKey:t},channels:s}=this.parameters;return`/v2/subscribe/${t}/${P(null!==(e=null==s?void 0:s.sort())&&void 0!==e?e:[],",")}/0`}get queryParameters(){const{channelGroups:e,filterExpression:t,heartbeat:s,state:n,timetoken:i,region:r,onDemand:a}=this.parameters,o={};return a&&(o["on-demand"]=1),e&&e.length>0&&(o["channel-group"]=e.sort().join(",")),t&&t.length>0&&(o["filter-expr"]=t),s&&(o.heartbeat=s),n&&Object.keys(n).length>0&&(o.state=JSON.stringify(n)),void 0!==i&&"string"==typeof i?i.length>0&&"0"!==i&&(o.tt=i):void 0!==i&&i>0&&(o.tt=i),r&&(o.tr=r),o}}class ve{constructor(){this.hasListeners=!1,this.listeners=[{count:-1,listener:{}}]}set onStatus(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"status"})}set onMessage(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"message"})}set onPresence(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"presence"})}set onSignal(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"signal"})}set onObjects(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"objects"})}set onMessageAction(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"messageAction"})}set onFile(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"file"})}set onDataSync(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"dataSync"})}handleEvent(e){if(this.hasListeners)if(e.type===ge.Message)this.announce("message",e.data);else if(e.type===ge.Signal)this.announce("signal",e.data);else if(e.type===ge.Presence)this.announce("presence",e.data);else if(e.type===ge.AppContext){const{data:t}=e,{message:s}=t;if(this.announce("objects",t),"uuid"===s.type){const{message:e,channel:n}=t,r=i(t,["message","channel"]),{event:a,type:o}=s,c=i(s,["event","type"]),u=Object.assign(Object.assign({},r),{spaceId:n,message:Object.assign(Object.assign({},c),{event:"set"===a?"updated":"removed",type:"user"})});this.announce("user",u)}else if("channel"===s.type){const{message:e,channel:n}=t,r=i(t,["message","channel"]),{event:a,type:o}=s,c=i(s,["event","type"]),u=Object.assign(Object.assign({},r),{spaceId:n,message:Object.assign(Object.assign({},c),{event:"set"===a?"updated":"removed",type:"space"})});this.announce("space",u)}else if("membership"===s.type){const{message:e,channel:n}=t,r=i(t,["message","channel"]),{event:a,data:o}=s,c=i(s,["event","data"]),{uuid:u,channel:l}=o,h=i(o,["uuid","channel"]),d=Object.assign(Object.assign({},r),{spaceId:n,message:Object.assign(Object.assign({},c),{event:"set"===a?"updated":"removed",data:Object.assign(Object.assign({},h),{user:u,space:l})})});this.announce("membership",d)}}else e.type===ge.MessageAction?this.announce("messageAction",e.data):e.type===ge.Files?this.announce("file",e.data):e.type===ge.DataSync&&this.announce("dataSync",e.data)}handleStatus(e){this.hasListeners&&this.announce("status",e)}addListener(e){this.updateTypeOrObjectListener({add:!0,listener:e})}removeListener(e){this.updateTypeOrObjectListener({add:!1,listener:e})}removeAllListeners(){this.listeners=[{count:-1,listener:{}}],this.hasListeners=!1}updateTypeOrObjectListener(e){if(e.type)"function"==typeof e.listener?this.listeners[0].listener[e.type]=e.listener:delete this.listeners[0].listener[e.type];else if(e.listener&&"function"!=typeof e.listener){let t,s=!1;for(t of this.listeners)if(t.listener===e.listener){e.add?(t.count++,s=!0):(t.count--,0===t.count&&this.listeners.splice(this.listeners.indexOf(t),1));break}e.add&&!s&&this.listeners.push({count:1,listener:e.listener})}this.hasListeners=this.listeners.length>1||Object.keys(this.listeners[0]).length>0}announce(e,t){this.listeners.forEach((({listener:s})=>{const n=s[e];n&&n(t)}))}}class Oe{constructor(e){this.time=e}onReconnect(e){this.callback=e}startPolling(){this.timeTimer=setInterval((()=>this.callTime()),3e3)}stopPolling(){this.timeTimer&&clearInterval(this.timeTimer),this.timeTimer=null}callTime(){this.time((e=>{e.error||(this.stopPolling(),this.callback&&this.callback())}))}}class Se{constructor(e){this.config=e,e.logger().debug("DedupingManager",(()=>({messageType:"object",message:{maximumCacheSize:e.maximumCacheSize},details:"Create with configuration:"}))),this.maximumCacheSize=e.maximumCacheSize,this.hashHistory=[]}getKey(e){var t;return`${e.timetoken}-${this.hashCode(JSON.stringify(null!==(t=e.message)&&void 0!==t?t:"")).toString()}`}isDuplicate(e){return this.hashHistory.includes(this.getKey(e))}addEntry(e){this.hashHistory.length>=this.maximumCacheSize&&this.hashHistory.shift(),this.hashHistory.push(this.getKey(e))}clearHistory(){this.hashHistory=[]}hashCode(e){let t=0;if(0===e.length)return t;for(let s=0;s{this.pendingChannelSubscriptions.add(e),this.channels[e]={},i&&(this.presenceChannels[e]={}),(r||this.configuration.getHeartbeatInterval())&&(this.heartbeatChannels[e]={})})),null==s||s.forEach((e=>{this.pendingChannelGroupSubscriptions.add(e),this.channelGroups[e]={},i&&(this.presenceChannelGroups[e]={}),(r||this.configuration.getHeartbeatInterval())&&(this.heartbeatChannelGroups[e]={})})),this.subscriptionStatusAnnounced=!1,this.reconnect()}unsubscribe(e,t=!1){let{channels:s,channelGroups:n}=e;const r=new Set,a=new Set;if(null==s||s.forEach((e=>{e in this.channels&&(delete this.channels[e],a.add(e),e in this.heartbeatChannels&&delete this.heartbeatChannels[e]),e in this.presenceState&&delete this.presenceState[e],e in this.presenceChannels&&(delete this.presenceChannels[e],a.add(e))})),null==n||n.forEach((e=>{e in this.channelGroups&&(delete this.channelGroups[e],r.add(e),e in this.heartbeatChannelGroups&&delete this.heartbeatChannelGroups[e]),e in this.presenceState&&delete this.presenceState[e],e in this.presenceChannelGroups&&(delete this.presenceChannelGroups[e],r.add(e))})),0===a.size&&0===r.size)return;const o=this.lastTimetoken,c=this.currentTimetoken;0===Object.keys(this.channels).length&&0===Object.keys(this.presenceChannels).length&&0===Object.keys(this.channelGroups).length&&0===Object.keys(this.presenceChannelGroups).length&&(this.lastTimetoken="0",this.currentTimetoken="0",this.referenceTimetoken=null,this.storedTimetoken=null,this.region=null,this.reconnectionManager.stopPolling()),this.reconnect(!0),!1!==this.configuration.suppressLeaveEvents||t||(n=Array.from(r),s=Array.from(a),this.leaveCall({channels:s,channelGroups:n},(e=>{const{error:t}=e,r=i(e,["error"]);let a;t&&(e.errorData&&"object"==typeof e.errorData&&"message"in e.errorData&&"string"==typeof e.errorData.message?a=e.errorData.message:"message"in e&&"string"==typeof e.message&&(a=e.message)),this.emitStatus(Object.assign(Object.assign({},r),{error:null!=a&&a,affectedChannels:s,affectedChannelGroups:n,currentTimetoken:c,lastTimetoken:o}))})))}unsubscribeAll(e=!1){this.disconnectedWhileHandledEvent=!0,this.unsubscribe({channels:this.subscribedChannels,channelGroups:this.subscribedChannelGroups},e)}startSubscribeLoop(e=!1){this.disconnectedWhileHandledEvent=!1,this.stopSubscribeLoop();const t=[...Object.keys(this.channelGroups)],s=[...Object.keys(this.channels)];Object.keys(this.presenceChannelGroups).forEach((e=>t.push(`${e}-pnpres`))),Object.keys(this.presenceChannels).forEach((e=>s.push(`${e}-pnpres`))),0===s.length&&0===t.length||(this.subscribeCall(Object.assign(Object.assign(Object.assign({channels:s,channelGroups:t,state:this.presenceState,heartbeat:this.configuration.getPresenceTimeout(),timetoken:this.currentTimetoken},null!==this.region?{region:this.region}:{}),this.configuration.filterExpression?{filterExpression:this.configuration.filterExpression}:{}),{onDemand:!this.subscriptionStatusAnnounced||e}),((e,t)=>{this.processSubscribeResponse(e,t)})),!e&&this.configuration.useSmartHeartbeat&&this.startHeartbeatTimer())}stopSubscribeLoop(){this._subscribeAbort&&(this._subscribeAbort(),this._subscribeAbort=null)}processSubscribeResponse(e,t){if(e.error){if("object"==typeof e.errorData&&"name"in e.errorData&&"AbortError"===e.errorData.name||e.category===h.PNCancelledCategory)return;return void(e.category===h.PNTimeoutCategory?this.startSubscribeLoop():e.category===h.PNNetworkIssuesCategory||e.category===h.PNMalformedResponseCategory?(this.disconnect(),e.error&&this.configuration.autoNetworkDetection&&this.isOnline&&(this.isOnline=!1,this.emitStatus({category:h.PNNetworkDownCategory})),this.reconnectionManager.onReconnect((()=>{this.configuration.autoNetworkDetection&&!this.isOnline&&(this.isOnline=!0,this.emitStatus({category:h.PNNetworkUpCategory})),this.reconnect(),this.subscriptionStatusAnnounced=!0;const t={category:h.PNReconnectedCategory,operation:e.operation,lastTimetoken:this.lastTimetoken,currentTimetoken:this.currentTimetoken};this.emitStatus(t)})),this.reconnectionManager.startPolling(),this.emitStatus(Object.assign(Object.assign({},e),{category:h.PNNetworkIssuesCategory}))):e.category===h.PNBadRequestCategory?(this.stopHeartbeatTimer(),this.emitStatus(e)):this.emitStatus(e))}if(this.referenceTimetoken=I(t.cursor.timetoken,this.storedTimetoken),this.storedTimetoken?(this.currentTimetoken=this.storedTimetoken,this.storedTimetoken=null):(this.lastTimetoken=this.currentTimetoken,this.currentTimetoken=t.cursor.timetoken),!this.subscriptionStatusAnnounced){const t={category:h.PNConnectedCategory,operation:e.operation,affectedChannels:Array.from(this.pendingChannelSubscriptions),subscribedChannels:this.subscribedChannels,affectedChannelGroups:Array.from(this.pendingChannelGroupSubscriptions),lastTimetoken:this.lastTimetoken,currentTimetoken:this.currentTimetoken};this.subscriptionStatusAnnounced=!0,this.emitStatus(t),this.pendingChannelGroupSubscriptions.clear(),this.pendingChannelSubscriptions.clear()}const{messages:s}=t,{requestMessageCountThreshold:n,dedupeOnSubscribe:i}=this.configuration;n&&s.length>=n&&this.emitStatus({category:h.PNRequestMessageCountExceededCategory,operation:e.operation});try{const e={timetoken:this.currentTimetoken,region:this.region?this.region:void 0};this.configuration.logger().debug("SubscriptionManager",(()=>({messageType:"object",message:s.map((e=>({type:e.type,data:Object.assign(Object.assign({},e.data),{pn_mfp:e.pn_mfp})}))),details:"Received events:"}))),s.forEach((t=>{if(i&&"message"in t.data&&"timetoken"in t.data){if(this.dedupingManager.isDuplicate(t.data))return void this.configuration.logger().warn("SubscriptionManager",(()=>({messageType:"object",message:t.data,details:"Duplicate message detected (skipped):"})));this.dedupingManager.addEntry(t.data)}this.emitEvent(e,t)}))}catch(e){const t={error:!0,category:h.PNUnknownCategory,errorData:e,statusCode:0};this.emitStatus(t)}this.region=t.cursor.region,this.disconnectedWhileHandledEvent?this.disconnectedWhileHandledEvent=!1:this.startSubscribeLoop()}setState(e){const{state:t,channels:s,channelGroups:n}=e;null==s||s.forEach((e=>e in this.channels&&(this.presenceState[e]=t))),null==n||n.forEach((e=>e in this.channelGroups&&(this.presenceState[e]=t)))}changePresence(e){const{connected:t,channels:s,channelGroups:n}=e;t?(null==s||s.forEach((e=>this.heartbeatChannels[e]={})),null==n||n.forEach((e=>this.heartbeatChannelGroups[e]={}))):(null==s||s.forEach((e=>{e in this.heartbeatChannels&&delete this.heartbeatChannels[e]})),null==n||n.forEach((e=>{e in this.heartbeatChannelGroups&&delete this.heartbeatChannelGroups[e]})),!1===this.configuration.suppressLeaveEvents&&this.leaveCall({channels:s,channelGroups:n},(e=>this.emitStatus(e)))),this.reconnect()}startHeartbeatTimer(){this.stopHeartbeatTimer();const e=this.configuration.getHeartbeatInterval();e&&0!==e&&(this.configuration.useSmartHeartbeat||this.sendHeartbeat(),this.heartbeatTimer=setInterval((()=>this.sendHeartbeat()),1e3*e))}stopHeartbeatTimer(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null)}sendHeartbeat(){const e=Object.keys(this.heartbeatChannelGroups),t=Object.keys(this.heartbeatChannels);0===t.length&&0===e.length||this.heartbeatCall({channels:t,channelGroups:e,heartbeat:this.configuration.getPresenceTimeout(),state:this.presenceState},(e=>{e.error&&this.configuration.announceFailedHeartbeats&&this.emitStatus(e),e.error&&this.configuration.autoNetworkDetection&&this.isOnline&&(this.isOnline=!1,this.disconnect(),this.emitStatus({category:h.PNNetworkDownCategory}),this.reconnect()),!e.error&&this.configuration.announceSuccessfulHeartbeats&&this.emitStatus(e)}))}}class we{constructor(e,t,s){this._payload=e,this.setDefaultPayloadStructure(),this.title=t,this.body=s}get payload(){return this._payload}set title(e){this._title=e}set subtitle(e){this._subtitle=e}set body(e){this._body=e}set badge(e){this._badge=e}set sound(e){this._sound=e}setDefaultPayloadStructure(){}toObject(){return{}}}class ke extends we{constructor(){super(...arguments),this._apnsPushType="apns",this._isSilent=!1}get payload(){return this._payload}set configurations(e){e&&e.length&&(this._configurations=e)}get notification(){return this.payload.aps}get title(){return this._title}set title(e){e&&e.length&&(this.payload.aps.alert.title=e,this._title=e)}get subtitle(){return this._subtitle}set subtitle(e){e&&e.length&&(this.payload.aps.alert.subtitle=e,this._subtitle=e)}get body(){return this._body}set body(e){e&&e.length&&(this.payload.aps.alert.body=e,this._body=e)}get badge(){return this._badge}set badge(e){null!=e&&(this.payload.aps.badge=e,this._badge=e)}get sound(){return this._sound}set sound(e){e&&e.length&&(this.payload.aps.sound=e,this._sound=e)}set silent(e){this._isSilent=e}setDefaultPayloadStructure(){this.payload.aps={alert:{}}}toObject(){const e=Object.assign({},this.payload),{aps:t}=e;let{alert:s}=t;if(this._isSilent&&(t["content-available"]=1),"apns2"===this._apnsPushType){if(!this._configurations||!this._configurations.length)throw new ReferenceError("APNS2 configuration is missing");const t=[];this._configurations.forEach((e=>{t.push(this.objectFromAPNS2Configuration(e))})),t.length&&(e.pn_push=t)}return s&&Object.keys(s).length||delete t.alert,this._isSilent&&(delete t.alert,delete t.badge,delete t.sound,s={}),this._isSilent||s&&Object.keys(s).length?e:null}objectFromAPNS2Configuration(e){if(!e.targets||!e.targets.length)throw new ReferenceError("At least one APNS2 target should be provided");const{collapseId:t,expirationDate:s}=e,n={auth_method:"token",targets:e.targets.map((e=>this.objectFromAPNSTarget(e))),version:"v2"};return t&&t.length&&(n.collapse_id=t),s&&(n.expiration=s.toISOString()),n}objectFromAPNSTarget(e){if(!e.topic||!e.topic.length)throw new TypeError("Target 'topic' undefined.");const{topic:t,environment:s="development",excludedDevices:n=[]}=e,i={topic:t,environment:s};return n.length&&(i.excluded_devices=n),i}}class Ce extends we{get payload(){return this._payload}get notification(){return this.payload.notification}get data(){return this.payload.data}get androidNotification(){var e;return null===(e=this.payload.android)||void 0===e?void 0:e.notification}get title(){return this._title}set title(e){e&&e.length&&(this.payload.notification.title=e,this.androidNotification.title=e,this._title=e)}get body(){return this._body}set body(e){e&&e.length&&(this.payload.notification.body=e,this.androidNotification.body=e,this._body=e)}get badge(){return this._badge}set badge(e){null!=e&&(this.androidNotification.notification_count=e,this._badge=e)}get sound(){return this._sound}set sound(e){e&&e.length&&(this.androidNotification.sound=e,this._sound=e)}get icon(){return this._icon}set icon(e){e&&e.length&&(this.androidNotification.icon=e,this._icon=e)}get tag(){return this._tag}set tag(e){e&&e.length&&(this.androidNotification.tag=e,this._tag=e)}set silent(e){this._isSilent=e}setDefaultPayloadStructure(){this.payload.notification={},this.payload.data={},this.payload.android={notification:{}}}toObject(){var e,t;const s={},n=Object.assign({},this.payload.notification),r=Object.assign({},this.payload.android),a=i(Object.assign({},null!==(e=r.notification)&&void 0!==e?e:{}),["title","body"]);if(this._isSilent){const e={};this._title&&(e.title=this._title),this._body&&(e.body=this._body);for(const[t,s]of Object.entries(a))null!=s&&(e[t]=String(s));this.payload.data&&Object.assign(e,this.payload.data),Object.keys(e).length&&(s.data=e),delete r.notification,Object.keys(r).length&&(s.android=r)}else if(Object.keys(n).length&&(s.notification=n),this.payload.data&&Object.keys(this.payload.data).length&&(s.data=Object.assign({},this.payload.data)),Object.keys(a).length){const e=i(r,["notification"]);s.android=Object.assign(Object.assign({},e),{notification:a})}else{const e=i(r,["notification"]);Object.keys(e).length&&(s.android=e)}const o=i(this.payload,["notification","android","data","pn_exceptions"]);return Object.assign(s,o),(null===(t=this.payload.pn_exceptions)||void 0===t?void 0:t.length)&&(s.pn_exceptions=this.payload.pn_exceptions),Object.keys(s).length?s:null}}class Pe{constructor(e,t){this._payload={apns:{},fcm:{}},this._title=e,this._body=t,this.apns=new ke(this._payload.apns,e,t),this.fcm=new Ce(this._payload.fcm,e,t)}set debugging(e){this._debugging=e}get title(){return this._title}get subtitle(){return this._subtitle}set subtitle(e){this._subtitle=e,this.apns.subtitle=e,this.fcm.subtitle=e}get body(){return this._body}get badge(){return this._badge}set badge(e){this._badge=e,this.apns.badge=e,this.fcm.badge=e}get sound(){return this._sound}set sound(e){this._sound=e,this.apns.sound=e,this.fcm.sound=e}buildPayload(e){const t={};if(e.includes("apns")||e.includes("apns2")){this.apns._apnsPushType=e.includes("apns")?"apns":"apns2";const s=this.apns.toObject();s&&Object.keys(s).length&&(t.pn_apns=s)}if(e.includes("fcm")){const e=this.fcm.toObject();e&&Object.keys(e).length&&(t.pn_fcm=e)}return Object.keys(t).length&&this._debugging&&(t.pn_debug=!0),t}}class Ne{constructor(e=!1){this.sync=e,this.listeners=new Set}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}notify(e){const t=()=>{this.listeners.forEach((t=>{t(e)}))};this.sync?t():setTimeout(t,0)}}class Ee{transition(e,t){var s;if(this.transitionMap.has(t.type))return null===(s=this.transitionMap.get(t.type))||void 0===s?void 0:s(e,t)}constructor(e){this.label=e,this.transitionMap=new Map,this.enterEffects=[],this.exitEffects=[]}on(e,t){return this.transitionMap.set(e,t),this}with(e,t){return[this,e,null!=t?t:[]]}onEnter(e){return this.enterEffects.push(e),this}onExit(e){return this.exitEffects.push(e),this}}class Te extends Ne{constructor(e){super(!0),this.logger=e,this._pendingEvents=[],this._inTransition=!1}get currentState(){return this._currentState}get currentContext(){return this._currentContext}describe(e){return new Ee(e)}start(e,t){this._currentState=e,this._currentContext=t,this.notify({type:"engineStarted",state:e,context:t})}transition(e){if(!this._currentState)throw this.logger.error("Engine","Finite state machine is not started"),new Error("Start the engine first");if(this._inTransition)return this.logger.trace("Engine",(()=>({messageType:"object",message:e,details:"Event engine in transition. Enqueue received event:"}))),void this._pendingEvents.push(e);this._inTransition=!0,this.logger.trace("Engine",(()=>({messageType:"object",message:e,details:"Event engine received event:"}))),this.notify({type:"eventReceived",event:e});const t=this._currentState.transition(this._currentContext,e);if(t){const[s,n,i]=t;this.logger.trace("Engine",`Exiting state: ${this._currentState.label}`);for(const e of this._currentState.exitEffects)this.notify({type:"invocationDispatched",invocation:e(this._currentContext)});this.logger.trace("Engine",(()=>({messageType:"object",details:`Entering '${s.label}' state with context:`,message:n})));const r=this._currentState;this._currentState=s;const a=this._currentContext;this._currentContext=n,this.notify({type:"transitionDone",fromState:r,fromContext:a,toState:s,toContext:n,event:e});for(const e of i)this.notify({type:"invocationDispatched",invocation:e});for(const e of this._currentState.enterEffects)this.notify({type:"invocationDispatched",invocation:e(this._currentContext)})}else this.logger.warn("Engine",`No transition from '${this._currentState.label}' found for event: ${e.type}`);if(this._inTransition=!1,this._pendingEvents.length>0){const e=this._pendingEvents.shift();e&&(this.logger.trace("Engine",(()=>({messageType:"object",message:e,details:"De-queueing pending event:"}))),this.transition(e))}}}class _e{constructor(e,t){this.dependencies=e,this.logger=t,this.instances=new Map,this.handlers=new Map}on(e,t){this.handlers.set(e,t)}dispatch(e){if(this.logger.trace("Dispatcher",`Process invocation: ${e.type}`),"CANCEL"===e.type){if(this.instances.has(e.payload)){const t=this.instances.get(e.payload);null==t||t.cancel(),this.instances.delete(e.payload)}return}const t=this.handlers.get(e.type);if(!t)throw this.logger.error("Dispatcher",`Unhandled invocation '${e.type}'`),new Error(`Unhandled invocation '${e.type}'`);const s=t(e.payload,this.dependencies);this.logger.trace("Dispatcher",(()=>({messageType:"object",details:"Call invocation handler with parameters:",message:e.payload,ignoredKeys:["abortSignal"]}))),e.managed&&this.instances.set(e.type,s),s.start()}dispose(){for(const[e,t]of this.instances.entries())t.cancel(),this.instances.delete(e)}}function Ie(e,t){const s=function(...s){return{type:e,payload:null==t?void 0:t(...s)}};return s.type=e,s}function Me(e,t){const s=(...s)=>({type:e,payload:t(...s),managed:!1});return s.type=e,s}function Re(e,t){const s=(...s)=>({type:e,payload:t(...s),managed:!0});return s.type=e,s.cancel={type:"CANCEL",payload:e,managed:!1},s}class De extends Error{constructor(){super("The operation was aborted."),this.name="AbortError",Object.setPrototypeOf(this,new.target.prototype)}}class Ue extends Ne{constructor(){super(...arguments),this._aborted=!1}get aborted(){return this._aborted}throwIfAborted(){if(this._aborted)throw new De}abort(){this._aborted=!0,this.notify(new De)}}class Ae{constructor(e,t){this.payload=e,this.dependencies=t}}class $e extends Ae{constructor(e,t,s){super(e,t),this.asyncFunction=s,this.abortSignal=new Ue}start(){this.asyncFunction(this.payload,this.abortSignal,this.dependencies).catch((e=>{}))}cancel(){this.abortSignal.abort()}}const Fe=e=>(t,s)=>new $e(t,s,e),xe=Re("HEARTBEAT",((e,t)=>({channels:e,groups:t}))),qe=Me("LEAVE",((e,t)=>({channels:e,groups:t}))),Ge=Me("EMIT_STATUS",(e=>e)),Le=Re("WAIT",(()=>({}))),Ke=Ie("RECONNECT",(()=>({}))),He=Ie("DISCONNECT",((e=!1)=>({isOffline:e}))),Be=Ie("JOINED",((e,t)=>({channels:e,groups:t}))),We=Ie("LEFT",((e,t)=>({channels:e,groups:t}))),Ve=Ie("LEFT_ALL",((e=!1)=>({isOffline:e}))),ze=Ie("HEARTBEAT_SUCCESS",(e=>({statusCode:e}))),Je=Ie("HEARTBEAT_FAILURE",(e=>e)),Xe=Ie("TIMES_UP",(()=>({})));class Qe extends _e{constructor(e,t){super(t,t.config.logger()),this.on(xe.type,Fe(((t,s,n)=>r(this,[t,s,n],void 0,(function*(t,s,{heartbeat:n,presenceState:i,config:r}){s.throwIfAborted();try{yield n(Object.assign(Object.assign({abortSignal:s,channels:t.channels,channelGroups:t.groups},r.maintainPresenceState&&{state:i}),{heartbeat:r.presenceTimeout}));e.transition(ze(200))}catch(t){if(t instanceof d){if(t.status&&t.status.category==h.PNCancelledCategory)return;e.transition(Je(t))}}}))))),this.on(qe.type,Fe(((e,t,s)=>r(this,[e,t,s],void 0,(function*(e,t,{leave:s,config:n}){if(!n.suppressLeaveEvents)try{s({channels:e.channels,channelGroups:e.groups})}catch(e){}}))))),this.on(Le.type,Fe(((t,s,n)=>r(this,[t,s,n],void 0,(function*(t,s,{heartbeatDelay:n}){const{cancelDelay:i,promise:r}=n();s.throwIfAborted();const a=s.subscribe((()=>i()));return yield r,a(),s.throwIfAborted(),e.transition(Xe())}))))),this.on(Ge.type,Fe(((e,t,s)=>r(this,[e,t,s],void 0,(function*(e,t,{emitStatus:s,config:n}){n.announceFailedHeartbeats&&!0===(null==e?void 0:e.error)?s(Object.assign(Object.assign({},e),{operation:K.PNHeartbeatOperation})):n.announceSuccessfulHeartbeats&&200===e.statusCode&&s(Object.assign(Object.assign({},e),{error:!1,operation:K.PNHeartbeatOperation,category:h.PNAcknowledgmentCategory}))})))))}}const Ye=new Ee("HEARTBEAT_INACTIVE"),Ze=new Ee("HEARTBEATING"),et=new Ee("HEARTBEAT_COOLDOWN"),tt=new Ee("HEARTBEAT_STOPPED"),st=new Ee("HEARTBEAT_FAILED");Ye.on(Be.type,((e,t)=>Ze.with({channels:t.payload.channels,groups:t.payload.groups}))),Ze.onEnter((e=>xe(e.channels,e.groups))),Ze.onExit((()=>xe.cancel)),Ze.on(ze.type,((e,t)=>et.with({channels:e.channels,groups:e.groups},[Ge(Object.assign({},t.payload))]))),Ze.on(Be.type,((e,t)=>Ze.with({channels:[...e.channels,...t.payload.channels.filter((t=>!e.channels.includes(t)))],groups:[...e.groups,...t.payload.groups.filter((t=>!e.groups.includes(t)))]}))),Ze.on(We.type,((e,t)=>Ze.with({channels:e.channels.filter((e=>!t.payload.channels.includes(e))),groups:e.groups.filter((e=>!t.payload.groups.includes(e)))},[qe(t.payload.channels,t.payload.groups)]))),Ze.on(Je.type,((e,t)=>st.with(Object.assign({},e),[...t.payload.status?[Ge(Object.assign({},t.payload.status))]:[]]))),Ze.on(He.type,((e,t)=>tt.with({channels:e.channels,groups:e.groups},[...t.payload.isOffline?[]:[qe(e.channels,e.groups)]]))),Ze.on(Ve.type,((e,t)=>Ye.with(void 0,[...t.payload.isOffline?[]:[qe(e.channels,e.groups)]]))),et.onEnter((()=>Le())),et.onExit((()=>Le.cancel)),et.on(Xe.type,((e,t)=>Ze.with({channels:e.channels,groups:e.groups}))),et.on(Be.type,((e,t)=>Ze.with({channels:[...e.channels,...t.payload.channels.filter((t=>!e.channels.includes(t)))],groups:[...e.groups,...t.payload.groups.filter((t=>!e.groups.includes(t)))]}))),et.on(We.type,((e,t)=>Ze.with({channels:e.channels.filter((e=>!t.payload.channels.includes(e))),groups:e.groups.filter((e=>!t.payload.groups.includes(e)))},[qe(t.payload.channels,t.payload.groups)]))),et.on(He.type,((e,t)=>tt.with({channels:e.channels,groups:e.groups},[...t.payload.isOffline?[]:[qe(e.channels,e.groups)]]))),et.on(Ve.type,((e,t)=>Ye.with(void 0,[...t.payload.isOffline?[]:[qe(e.channels,e.groups)]]))),tt.on(Be.type,((e,t)=>tt.with({channels:[...e.channels,...t.payload.channels.filter((t=>!e.channels.includes(t)))],groups:[...e.groups,...t.payload.groups.filter((t=>!e.groups.includes(t)))]}))),tt.on(We.type,((e,t)=>tt.with({channels:e.channels.filter((e=>!t.payload.channels.includes(e))),groups:e.groups.filter((e=>!t.payload.groups.includes(e)))}))),tt.on(Ke.type,((e,t)=>Ze.with({channels:e.channels,groups:e.groups}))),tt.on(Ve.type,((e,t)=>Ye.with(void 0))),st.on(Be.type,((e,t)=>Ze.with({channels:[...e.channels,...t.payload.channels.filter((t=>!e.channels.includes(t)))],groups:[...e.groups,...t.payload.groups.filter((t=>!e.groups.includes(t)))]}))),st.on(We.type,((e,t)=>Ze.with({channels:e.channels.filter((e=>!t.payload.channels.includes(e))),groups:e.groups.filter((e=>!t.payload.groups.includes(e)))},[qe(t.payload.channels,t.payload.groups)]))),st.on(Ke.type,((e,t)=>Ze.with({channels:e.channels,groups:e.groups}))),st.on(He.type,((e,t)=>tt.with({channels:e.channels,groups:e.groups},[...t.payload.isOffline?[]:[qe(e.channels,e.groups)]]))),st.on(Ve.type,((e,t)=>Ye.with(void 0,[...t.payload.isOffline?[]:[qe(e.channels,e.groups)]])));class nt{get _engine(){return this.engine}constructor(e){this.dependencies=e,this.channels=[],this.groups=[],this.engine=new Te(e.config.logger()),this.dispatcher=new Qe(this.engine,e),e.config.logger().debug("PresenceEventEngine","Create presence event engine."),this._unsubscribeEngine=this.engine.subscribe((e=>{"invocationDispatched"===e.type&&this.dispatcher.dispatch(e.invocation)})),this.engine.start(Ye,void 0)}join({channels:e,groups:t}){this.channels=[...this.channels,...(null!=e?e:[]).filter((e=>!this.channels.includes(e)))],this.groups=[...this.groups,...(null!=t?t:[]).filter((e=>!this.groups.includes(e)))],0===this.channels.length&&0===this.groups.length||this.engine.transition(Be(this.channels.slice(0),this.groups.slice(0)))}leave({channels:e,groups:t}){e&&(this.channels=this.channels.filter((t=>!e.includes(t)))),t&&(this.groups=this.groups.filter((e=>!t.includes(e)))),this.dependencies.presenceState&&(null==e||e.forEach((e=>delete this.dependencies.presenceState[e])),null==t||t.forEach((e=>delete this.dependencies.presenceState[e]))),this.engine.transition(We(null!=e?e:[],null!=t?t:[]))}leaveAll(e=!1){this.dependencies.presenceState&&(this.channels.forEach((e=>delete this.dependencies.presenceState[e])),this.groups.forEach((e=>delete this.dependencies.presenceState[e]))),this.channels=[],this.groups=[],this.engine.transition(Ve(e))}reconnect(){this.engine.transition(Ke())}disconnect(e=!1){this.engine.transition(He(e))}dispose(){this.disconnect(!0),this._unsubscribeEngine(),this.dispatcher.dispose()}}const it=Ie("SUBSCRIPTION_CHANGED",((e,t,s=!1)=>({channels:e,groups:t,isOffline:s}))),rt=Ie("SUBSCRIPTION_RESTORED",((e,t,s,n)=>({channels:e,groups:t,cursor:{timetoken:s,region:null!=n?n:0}}))),at=Ie("HANDSHAKE_SUCCESS",(e=>e)),ot=Ie("HANDSHAKE_FAILURE",(e=>e)),ct=Ie("RECEIVE_SUCCESS",((e,t)=>({cursor:e,events:t}))),ut=Ie("RECEIVE_FAILURE",(e=>e)),lt=Ie("DISCONNECT",((e=!1)=>({isOffline:e}))),ht=Ie("RECONNECT",((e,t)=>({cursor:{timetoken:null!=e?e:"",region:null!=t?t:0}}))),dt=Ie("UNSUBSCRIBE_ALL",(()=>({}))),pt=new Ee("UNSUBSCRIBED"),gt=new Ee("HANDSHAKING"),bt=new Ee("HANDSHAKE_STOPPED"),yt=new Ee("HANDSHAKE_FAILED"),mt=new Ee("RECEIVING"),ft=new Ee("RECEIVE_STOPPED"),vt=new Ee("RECEIVE_FAILED");pt.on(it.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,onDemand:!0}))),pt.on(rt.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region},onDemand:!0})));const Ot=Re("HANDSHAKE",((e,t,s)=>({channels:e,groups:t,onDemand:s}))),St=Re("RECEIVE_MESSAGES",((e,t,s,n)=>({channels:e,groups:t,cursor:s,onDemand:n}))),jt=Me("EMIT_MESSAGES",((e,t)=>({cursor:e,events:t}))),wt=Me("EMIT_STATUS",(e=>e));gt.onEnter((e=>{var t;return Ot(e.channels,e.groups,null!==(t=e.onDemand)&&void 0!==t&&t)})),gt.onExit((()=>Ot.cancel)),gt.on(it.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:e.cursor,onDemand:!0}))),gt.on(at.type,((e,{payload:t})=>{var s,n,i,r,a;return mt.with({channels:e.channels,groups:e.groups,cursor:{timetoken:(null===(s=e.cursor)||void 0===s?void 0:s.timetoken)?null===(n=e.cursor)||void 0===n?void 0:n.timetoken:t.timetoken,region:t.region},referenceTimetoken:I(t.timetoken,null===(i=e.cursor)||void 0===i?void 0:i.timetoken)},[wt({category:h.PNConnectedCategory,affectedChannels:e.channels.slice(0),affectedChannelGroups:e.groups.slice(0),operation:K.PNSubscribeOperation,currentTimetoken:(null===(r=e.cursor)||void 0===r?void 0:r.timetoken)?null===(a=e.cursor)||void 0===a?void 0:a.timetoken:t.timetoken})])})),gt.on(ot.type,((e,t)=>{var s;return yt.with(Object.assign(Object.assign({},e),{reason:t.payload}),[wt({category:h.PNConnectionErrorCategory,error:null===(s=t.payload.status)||void 0===s?void 0:s.category})])})),gt.on(lt.type,((e,t)=>{var s;if(t.payload.isOffline){const t=G.create(new Error("Network connection error")).toPubNubError(K.PNSubscribeOperation);return yt.with(Object.assign(Object.assign({},e),{reason:t}),[wt({category:h.PNConnectionErrorCategory,error:null===(s=t.status)||void 0===s?void 0:s.category})])}return bt.with(Object.assign({},e))})),gt.on(rt.type,((e,{payload:t})=>{var s;return 0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region||(null===(s=null==e?void 0:e.cursor)||void 0===s?void 0:s.region)||0},onDemand:!0})})),gt.on(dt.type,(e=>pt.with())),bt.on(it.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):bt.with({channels:t.channels,groups:t.groups,cursor:e.cursor}))),bt.on(ht.type,((e,{payload:t})=>gt.with(Object.assign(Object.assign({},e),{cursor:t.cursor||e.cursor,onDemand:!0})))),bt.on(rt.type,((e,{payload:t})=>{var s;return 0===t.channels.length&&0===t.groups.length?pt.with(void 0):bt.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region||(null===(s=e.cursor)||void 0===s?void 0:s.region)||0}})})),bt.on(dt.type,(e=>pt.with())),yt.on(it.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:e.cursor,onDemand:!0}))),yt.on(ht.type,((e,{payload:t})=>gt.with(Object.assign(Object.assign({},e),{cursor:t.cursor||e.cursor,onDemand:!0})))),yt.on(rt.type,((e,{payload:t})=>{var s,n;return 0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region?t.cursor.region:null!==(n=null===(s=null==e?void 0:e.cursor)||void 0===s?void 0:s.region)&&void 0!==n?n:0},onDemand:!0})})),yt.on(dt.type,(e=>pt.with())),mt.onEnter((e=>{var t;return St(e.channels,e.groups,e.cursor,null!==(t=e.onDemand)&&void 0!==t&&t)})),mt.onExit((()=>St.cancel)),mt.on(ct.type,((e,{payload:t})=>mt.with({channels:e.channels,groups:e.groups,cursor:t.cursor,referenceTimetoken:I(t.cursor.timetoken)},[jt(e.cursor,t.events)]))),mt.on(it.type,((e,{payload:t})=>{var s;if(0===t.channels.length&&0===t.groups.length){let e;return t.isOffline&&(e=null===(s=G.create(new Error("Network connection error")).toPubNubError(K.PNSubscribeOperation).status)||void 0===s?void 0:s.category),pt.with(void 0,[wt(Object.assign({category:t.isOffline?h.PNDisconnectedUnexpectedlyCategory:h.PNDisconnectedCategory,operation:K.PNUnsubscribeOperation},e?{error:e}:{}))])}return mt.with({channels:t.channels,groups:t.groups,cursor:e.cursor,referenceTimetoken:e.referenceTimetoken,onDemand:!0},[wt({category:h.PNSubscriptionChangedCategory,affectedChannels:t.channels.slice(0),affectedChannelGroups:t.groups.slice(0),currentTimetoken:e.cursor.timetoken})])})),mt.on(rt.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0,[wt({category:h.PNDisconnectedCategory})]):mt.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region||e.cursor.region},referenceTimetoken:I(e.cursor.timetoken,`${t.cursor.timetoken}`,e.referenceTimetoken),onDemand:!0},[wt({category:h.PNSubscriptionChangedCategory,affectedChannels:t.channels.slice(0),affectedChannelGroups:t.groups.slice(0),currentTimetoken:t.cursor.timetoken})]))),mt.on(ut.type,((e,{payload:t})=>{var s;return vt.with(Object.assign(Object.assign({},e),{reason:t}),[wt({category:h.PNDisconnectedUnexpectedlyCategory,error:null===(s=t.status)||void 0===s?void 0:s.category})])})),mt.on(lt.type,((e,t)=>{var s;if(t.payload.isOffline){const t=G.create(new Error("Network connection error")).toPubNubError(K.PNSubscribeOperation);return vt.with(Object.assign(Object.assign({},e),{reason:t}),[wt({category:h.PNDisconnectedUnexpectedlyCategory,operation:K.PNSubscribeOperation,error:null===(s=t.status)||void 0===s?void 0:s.category})])}return ft.with(Object.assign({},e),[wt({category:h.PNDisconnectedCategory,operation:K.PNSubscribeOperation})])})),mt.on(dt.type,(e=>pt.with(void 0,[wt({category:h.PNDisconnectedCategory,operation:K.PNUnsubscribeOperation})]))),ft.on(it.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):ft.with({channels:t.channels,groups:t.groups,cursor:e.cursor}))),ft.on(rt.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):ft.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region||e.cursor.region}}))),ft.on(ht.type,((e,{payload:t})=>{var s;return gt.with({channels:e.channels,groups:e.groups,cursor:{timetoken:t.cursor.timetoken?null===(s=t.cursor)||void 0===s?void 0:s.timetoken:e.cursor.timetoken,region:t.cursor.region||e.cursor.region},onDemand:!0})})),ft.on(dt.type,(()=>pt.with(void 0))),vt.on(ht.type,((e,{payload:t})=>{var s;return gt.with({channels:e.channels,groups:e.groups,cursor:{timetoken:t.cursor.timetoken?null===(s=t.cursor)||void 0===s?void 0:s.timetoken:e.cursor.timetoken,region:t.cursor.region||e.cursor.region},onDemand:!0})})),vt.on(it.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:e.cursor,onDemand:!0}))),vt.on(rt.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region||e.cursor.region},onDemand:!0}))),vt.on(dt.type,(e=>pt.with(void 0)));class kt extends _e{constructor(e,t){super(t,t.config.logger()),this.on(Ot.type,Fe(((t,s,n)=>r(this,[t,s,n],void 0,(function*(t,s,{handshake:n,presenceState:i,config:r}){s.throwIfAborted();try{const a=yield n(Object.assign(Object.assign({abortSignal:s,channels:t.channels,channelGroups:t.groups,filterExpression:r.filterExpression},r.maintainPresenceState&&{state:i}),{onDemand:t.onDemand}));return e.transition(at(a))}catch(t){if(t instanceof d){if(t.status&&t.status.category==h.PNCancelledCategory)return;return e.transition(ot(t))}}}))))),this.on(St.type,Fe(((t,s,n)=>r(this,[t,s,n],void 0,(function*(t,s,{receiveMessages:n,config:i}){s.throwIfAborted();try{const r=yield n({abortSignal:s,channels:t.channels,channelGroups:t.groups,timetoken:t.cursor.timetoken,region:t.cursor.region,filterExpression:i.filterExpression,onDemand:t.onDemand});e.transition(ct(r.cursor,r.messages))}catch(t){if(t instanceof d){if(t.status&&t.status.category==h.PNCancelledCategory)return;if(!s.aborted)return e.transition(ut(t))}}}))))),this.on(jt.type,Fe(((e,t,s)=>r(this,[e,t,s],void 0,(function*({cursor:e,events:t},s,{emitMessages:n}){t.length>0&&n(e,t)}))))),this.on(wt.type,Fe(((e,t,s)=>r(this,[e,t,s],void 0,(function*(e,t,{emitStatus:s}){return s(e)})))))}}class Ct{get _engine(){return this.engine}constructor(e){this.channels=[],this.groups=[],this.dependencies=e,this.engine=new Te(e.config.logger()),this.dispatcher=new kt(this.engine,e),e.config.logger().debug("EventEngine","Create subscribe event engine."),this._unsubscribeEngine=this.engine.subscribe((e=>{"invocationDispatched"===e.type&&this.dispatcher.dispatch(e.invocation)})),this.engine.start(pt,void 0)}get subscriptionTimetoken(){const e=this.engine.currentState;if(!e)return;let t,s="0";if(e.label===mt.label){const e=this.engine.currentContext;s=e.cursor.timetoken,t=e.referenceTimetoken}return _(s,null!=t?t:"0")}subscribe({channels:e,channelGroups:t,timetoken:s,withPresence:n}){var i;const r=null==e?void 0:e.some((e=>!this.channels.includes(e))),a=null==t?void 0:t.some((e=>!this.groups.includes(e))),o=r||a;if(this.channels=[...this.channels,...null!=e?e:[]],this.groups=[...this.groups,...null!=t?t:[]],n&&(this.channels.map((e=>this.channels.push(`${e}-pnpres`))),this.groups.map((e=>this.groups.push(`${e}-pnpres`)))),s)this.engine.transition(rt(Array.from(new Set([...this.channels,...null!=e?e:[]])),Array.from(new Set([...this.groups,...null!=t?t:[]])),s));else if(o)this.engine.transition(it(Array.from(new Set([...this.channels,...null!=e?e:[]])),Array.from(new Set([...this.groups,...null!=t?t:[]]))));else{this.dependencies.config.logger().debug("EventEngine","Skipping state transition - all channels/groups already subscribed. Emitting SubscriptionChanged event.");const e=this.engine.currentState,t=this.engine.currentContext;let s="0";if((null==e?void 0:e.label)===mt.label&&t){s=null===(i=t.cursor)||void 0===i?void 0:i.timetoken}this.dependencies.emitStatus({category:h.PNSubscriptionChangedCategory,affectedChannels:Array.from(new Set(this.channels)),affectedChannelGroups:Array.from(new Set(this.groups)),currentTimetoken:s})}this.dependencies.join&&this.dependencies.join({channels:Array.from(new Set(this.channels.filter((e=>!e.endsWith("-pnpres"))))),groups:Array.from(new Set(this.groups.filter((e=>!e.endsWith("-pnpres")))))})}unsubscribe({channels:e=[],channelGroups:t=[]}){const s=N(this.channels,[...e,...e.map((e=>`${e}-pnpres`))]),n=N(this.groups,[...t,...t.map((e=>`${e}-pnpres`))]);if(new Set(this.channels).size!==new Set(s).size||new Set(this.groups).size!==new Set(n).size){const i=E(this.channels,e),r=E(this.groups,t);this.dependencies.presenceState&&(null==i||i.forEach((e=>delete this.dependencies.presenceState[e])),null==r||r.forEach((e=>delete this.dependencies.presenceState[e]))),this.channels=s,this.groups=n,this.engine.transition(it(Array.from(new Set(this.channels.slice(0))),Array.from(new Set(this.groups.slice(0))))),this.dependencies.leave&&this.dependencies.leave({channels:i.slice(0),groups:r.slice(0)})}}unsubscribeAll(e=!1){const t=this.getSubscribedChannelGroups(),s=this.getSubscribedChannels();this.channels=[],this.groups=[],this.dependencies.presenceState&&Object.keys(this.dependencies.presenceState).forEach((e=>{delete this.dependencies.presenceState[e]})),this.engine.transition(it(this.channels.slice(0),this.groups.slice(0),e)),this.dependencies.leaveAll&&this.dependencies.leaveAll({channels:s,groups:t,isOffline:e})}reconnect({timetoken:e,region:t}){const s=this.getSubscribedChannels(),n=this.getSubscribedChannels();this.engine.transition(ht(e,t)),this.dependencies.presenceReconnect&&this.dependencies.presenceReconnect({channels:n,groups:s})}disconnect(e=!1){const t=this.getSubscribedChannels(),s=this.getSubscribedChannels();this.engine.transition(lt(e)),this.dependencies.presenceDisconnect&&this.dependencies.presenceDisconnect({channels:s,groups:t,isOffline:e})}getSubscribedChannels(){return Array.from(new Set(this.channels.slice(0)))}getSubscribedChannelGroups(){return Array.from(new Set(this.groups.slice(0)))}dispose(){this.disconnect(!0),this._unsubscribeEngine(),this.dispatcher.dispose()}}class Pt extends pe{constructor(e){var t;const s=null!==(t=e.sendByPost)&&void 0!==t&&t;super({method:s?ue.POST:ue.GET,compressible:s}),this.parameters=e,this.parameters.sendByPost=s}operation(){return K.PNPublishOperation}validate(){const{message:e,channel:t,keySet:{publishKey:s}}=this.parameters;return t?e?s?void 0:"Missing 'publishKey'":"Missing 'message'":"Missing 'channel'"}parse(e){return r(this,void 0,void 0,(function*(){return{timetoken:this.deserializeResponse(e)[2]}}))}get path(){const{message:e,channel:t,keySet:s}=this.parameters,n=this.prepareMessagePayload(e);return`/publish/${s.publishKey}/${s.subscribeKey}/0/${C(t)}/0${this.parameters.sendByPost?"":`/${C(n)}`}`}get queryParameters(){const{customMessageType:e,meta:t,replicate:s,storeInHistory:n,ttl:i}=this.parameters,r={};return e&&(r.custom_message_type=e),void 0!==n&&(r.store=n?"1":"0"),void 0!==i&&(r.ttl=i),void 0===s||s||(r.norep="true"),t&&"object"==typeof t&&(r.meta=JSON.stringify(t)),r}get headers(){var e;return this.parameters.sendByPost?Object.assign(Object.assign({},null!==(e=super.headers)&&void 0!==e?e:{}),{"Content-Type":"application/json"}):super.headers}get body(){return this.prepareMessagePayload(this.parameters.message)}prepareMessagePayload(e){const{crypto:t}=this.parameters;if(!t)return JSON.stringify(e)||"";const s=t.encrypt(JSON.stringify(e));return JSON.stringify("string"==typeof s?s:u(s))}}class Nt extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNSignalOperation}validate(){const{message:e,channel:t,keySet:{publishKey:s}}=this.parameters;return t?e?s?void 0:"Missing 'publishKey'":"Missing 'message'":"Missing 'channel'"}parse(e){return r(this,void 0,void 0,(function*(){return{timetoken:this.deserializeResponse(e)[2]}}))}get path(){const{keySet:{publishKey:e,subscribeKey:t},channel:s,message:n}=this.parameters,i=JSON.stringify(n);return`/signal/${e}/${t}/0/${C(s)}/0/${C(i)}`}get queryParameters(){const{customMessageType:e}=this.parameters,t={};return e&&(t.custom_message_type=e),t}}class Et extends me{operation(){return K.PNReceiveMessagesOperation}validate(){const e=super.validate();return e||(this.parameters.timetoken?this.parameters.region?void 0:"region can not be empty":"timetoken can not be empty")}get path(){const{keySet:{subscribeKey:e},channels:t=[]}=this.parameters;return`/v2/subscribe/${e}/${P(t.sort(),",")}/0`}get queryParameters(){const{channelGroups:e,filterExpression:t,timetoken:s,region:n,heartbeat:i,onDemand:r}=this.parameters,a={ee:""};return r&&(a["on-demand"]=1),e&&e.length>0&&(a["channel-group"]=e.sort().join(",")),t&&t.length>0&&(a["filter-expr"]=t),"string"==typeof s?s&&"0"!==s&&s.length>0&&(a.tt=s):s&&s>0&&(a.tt=s),n&&(a.tr=n),i&&(a.heartbeat=i),a}}class Tt extends me{operation(){return K.PNHandshakeOperation}get path(){const{keySet:{subscribeKey:e},channels:t=[]}=this.parameters;return`/v2/subscribe/${e}/${P(t.sort(),",")}/0`}get queryParameters(){const{channelGroups:e,heartbeat:t,filterExpression:s,state:n,onDemand:i}=this.parameters,r={ee:""};return i&&(r["on-demand"]=1),e&&e.length>0&&(r["channel-group"]=e.sort().join(",")),s&&s.length>0&&(r["filter-expr"]=s),n&&Object.keys(n).length>0&&(r.state=JSON.stringify(n)),t&&(r.heartbeat=t),r}}var _t;!function(e){e[e.Channel=0]="Channel",e[e.ChannelGroup=1]="ChannelGroup"}(_t||(_t={}));class It{constructor({channels:e,channelGroups:t}){this.isEmpty=!0,this._channelGroups=new Set((null!=t?t:[]).filter((e=>e.length>0))),this._channels=new Set((null!=e?e:[]).filter((e=>e.length>0))),this.isEmpty=0===this._channels.size&&0===this._channelGroups.size}get length(){return this.isEmpty?0:this._channels.size+this._channelGroups.size}get channels(){return this.isEmpty?[]:Array.from(this._channels)}get channelGroups(){return this.isEmpty?[]:Array.from(this._channelGroups)}contains(e){return!this.isEmpty&&(this._channels.has(e)||this._channelGroups.has(e))}with(e){return new It({channels:[...this._channels,...e._channels],channelGroups:[...this._channelGroups,...e._channelGroups]})}without(e){return new It({channels:[...this._channels].filter((t=>!e._channels.has(t))),channelGroups:[...this._channelGroups].filter((t=>!e._channelGroups.has(t)))})}add(e){return e._channelGroups.size>0&&(this._channelGroups=new Set([...this._channelGroups,...e._channelGroups])),e._channels.size>0&&(this._channels=new Set([...this._channels,...e._channels])),this.isEmpty=0===this._channels.size&&0===this._channelGroups.size,this}remove(e){return e._channelGroups.size>0&&(this._channelGroups=new Set([...this._channelGroups].filter((t=>!e._channelGroups.has(t))))),e._channels.size>0&&(this._channels=new Set([...this._channels].filter((t=>!e._channels.has(t))))),this}removeAll(){return this._channels.clear(),this._channelGroups.clear(),this.isEmpty=!0,this}toString(){return`SubscriptionInput { channels: [${this.channels.join(", ")}], channelGroups: [${this.channelGroups.join(", ")}], is empty: ${this.isEmpty?"true":"false"}} }`}}class Mt{constructor(e,t,s,n){this._isSubscribed=!1,this.clones={},this.parents=[],this._id=ie.createUUID(),this.referenceTimetoken=n,this.subscriptionInput=t,this.options=s,this.client=e}get id(){return this._id}get isLastClone(){return 1===Object.keys(this.clones).length}get isSubscribed(){return!!this._isSubscribed||this.parents.length>0&&this.parents.some((e=>e.isSubscribed))}set isSubscribed(e){this.isSubscribed!==e&&(this._isSubscribed=e)}addParentState(e){this.parents.includes(e)||this.parents.push(e)}removeParentState(e){const t=this.parents.indexOf(e);-1!==t&&this.parents.splice(t,1)}storeClone(e,t){this.clones[e]||(this.clones[e]=t)}}class Rt{constructor(e,t="Subscription"){this.subscriptionType=t,this.id=ie.createUUID(),this.eventDispatcher=new ve,this._state=e}get state(){return this._state}get channels(){return this.state.subscriptionInput.channels.slice(0)}get channelGroups(){return this.state.subscriptionInput.channelGroups.slice(0)}set onMessage(e){this.eventDispatcher.onMessage=e}set onPresence(e){this.eventDispatcher.onPresence=e}set onSignal(e){this.eventDispatcher.onSignal=e}set onObjects(e){this.eventDispatcher.onObjects=e}set onMessageAction(e){this.eventDispatcher.onMessageAction=e}set onFile(e){this.eventDispatcher.onFile=e}set onDataSync(e){this.eventDispatcher.onDataSync=e}addListener(e){this.eventDispatcher.addListener(e)}removeListener(e){this.eventDispatcher.removeListener(e)}removeAllListeners(){this.eventDispatcher.removeAllListeners()}handleEvent(e,t){var s;if((!this.state.cursor||e>this.state.cursor)&&(this.state.cursor=e),this.state.referenceTimetoken&&t.data.timetoken({messageType:"text",message:`Event timetoken (${t.data.timetoken}) is older than reference timetoken (${this.state.referenceTimetoken}) for ${this.id} subscription object. Ignoring event.`})));if((null===(s=this.state.options)||void 0===s?void 0:s.filter)&&!this.state.options.filter(t))return void this.state.client.logger.trace(this.subscriptionType,`Event filtered out by filter function for ${this.id} subscription object. Ignoring event.`);const n=Object.values(this.state.clones);n.length>0&&this.state.client.logger.trace(this.subscriptionType,`Notify ${this.id} subscription object clones (count: ${n.length}) about received event.`),n.forEach((e=>e.eventDispatcher.handleEvent(t)))}dispose(){const e=Object.keys(this.state.clones);e.length>1?(this.state.client.logger.debug(this.subscriptionType,`Remove subscription object clone on dispose: ${this.id}`),delete this.state.clones[this.id]):1===e.length&&this.state.clones[this.id]&&(this.state.client.logger.debug(this.subscriptionType,`Unsubscribe subscription object on dispose: ${this.id}`),this.unsubscribe())}invalidate(e=!1){this.state._isSubscribed=!1,e&&(delete this.state.clones[this.id],0===Object.keys(this.state.clones).length&&(this.state.client.logger.trace(this.subscriptionType,"Last clone removed. Reset shared subscription state."),this.state.subscriptionInput.removeAll(),this.state.parents=[]))}subscribe(e){this.state.isSubscribed?this.state.client.logger.trace(this.subscriptionType,"Already subscribed. Ignoring subscribe request."):(this.state.client.logger.debug(this.subscriptionType,(()=>e?{messageType:"object",message:e,details:"Subscribe with parameters:"}:{messageType:"text",message:"Subscribe"})),this.state.isSubscribed=!0,this.updateSubscription({subscribing:!0,timetoken:null==e?void 0:e.timetoken}))}unsubscribe(){if(!this.state._isSubscribed||this.state.isSubscribed){if(!this.state._isSubscribed&&this.state.parents.length>0&&this.state.isSubscribed)return void this.state.client.logger.warn(this.subscriptionType,(()=>({messageType:"object",details:"Subscription is subscribed as part of a subscription set. Remove from active sets to unsubscribe:",message:this.state.parents.filter((e=>e.isSubscribed))})));if(!this.state._isSubscribed)return void this.state.client.logger.trace(this.subscriptionType,"Not subscribed. Ignoring unsubscribe request.")}this.state.client.logger.debug(this.subscriptionType,"Unsubscribe"),this.state.isSubscribed=!1,delete this.state.cursor,this.updateSubscription({subscribing:!1})}updateSubscription(e){var t,s;(null==e?void 0:e.timetoken)&&((null===(t=this.state.cursor)||void 0===t?void 0:t.timetoken)&&"0"!==(null===(s=this.state.cursor)||void 0===s?void 0:s.timetoken)?"0"!==e.timetoken&&e.timetoken>this.state.cursor.timetoken&&(this.state.cursor.timetoken=e.timetoken):this.state.cursor={timetoken:e.timetoken});const n=e.subscriptions&&e.subscriptions.length>0?e.subscriptions:void 0;e.subscribing?this.register(Object.assign(Object.assign({},e.timetoken?{cursor:this.state.cursor}:{}),n?{subscriptions:n}:{})):this.unregister(n)}}class Dt extends Mt{constructor(e){const t=new It({});e.subscriptions.forEach((e=>t.add(e.state.subscriptionInput))),super(e.client,t,e.options,e.client.subscriptionTimetoken),this.subscriptions=e.subscriptions}addSubscription(e){this.subscriptions.includes(e)||(e.state.addParentState(this),this.subscriptions.push(e),this.subscriptionInput.add(e.state.subscriptionInput))}removeSubscription(e,t){const s=this.subscriptions.indexOf(e);-1!==s&&(this.subscriptions.splice(s,1),t||e.state.removeParentState(this),this.subscriptionInput.remove(e.state.subscriptionInput))}removeAllSubscriptions(){this.subscriptions.forEach((e=>e.state.removeParentState(this))),this.subscriptions.splice(0,this.subscriptions.length),this.subscriptionInput.removeAll()}}class Ut extends Rt{constructor(e){let t;if("client"in e){let s=[];!e.subscriptions&&e.entities?e.entities.forEach((t=>s.push(t.subscription(e.options)))):e.subscriptions&&(s=e.subscriptions),t=new Dt({client:e.client,subscriptions:s,options:e.options}),s.forEach((e=>e.state.addParentState(t))),t.client.logger.debug("SubscriptionSet",(()=>({messageType:"object",details:"Create subscription set with parameters:",message:Object.assign({subscriptions:t.subscriptions},e.options?e.options:{})})))}else t=e.state,t.client.logger.debug("SubscriptionSet","Create subscription set clone");super(t,"SubscriptionSet"),this.state.storeClone(this.id,this),t.subscriptions.forEach((e=>e.addParentSet(this)))}get state(){return super.state}get subscriptions(){return this.state.subscriptions.slice(0)}handleEvent(e,t){var s;this.state.subscriptionInput.contains(null!==(s=t.data.subscription)&&void 0!==s?s:t.data.channel)&&(this.state._isSubscribed?(super.handleEvent(e,t),this.state.subscriptions.length>0&&this.state.client.logger.trace(this.subscriptionType,`Notify ${this.id} subscription set subscriptions (count: ${this.state.subscriptions.length}) about received event.`),this.state.subscriptions.forEach((s=>s.handleEvent(e,t)))):this.state.client.logger.trace(this.subscriptionType,`Subscription set ${this.id} is not subscribed. Ignoring event.`))}subscriptionInput(e=!1){let t=this.state.subscriptionInput;return this.state.subscriptions.forEach((s=>{e&&s.state.entity.subscriptionsCount>0&&(t=t.without(s.state.subscriptionInput))})),t}cloneEmpty(){return new Ut({state:this.state})}dispose(){const e=this.state.isLastClone;this.state.subscriptions.forEach((t=>{t.removeParentSet(this),e&&t.state.removeParentState(this.state)})),super.dispose()}invalidate(e=!1){(e?this.state.subscriptions.slice(0):this.state.subscriptions).forEach((t=>{e&&(t.state.entity.decreaseSubscriptionCount(this.state.id),t.removeParentSet(this)),t.invalidate(e)})),e&&this.state.removeAllSubscriptions(),super.invalidate()}addSubscription(e){this.addSubscriptions([e])}addSubscriptions(e){const t=[],s=[];this.state.client.logger.debug(this.subscriptionType,(()=>{const t=[],s=[];return e.forEach((e=>{this.state.subscriptions.includes(e)?t.push(e):s.push(e)})),{messageType:"object",details:`Add subscriptions to ${this.id} (subscriptions count: ${this.state.subscriptions.length+s.length}):`,message:{addedSubscriptions:s,ignoredSubscriptions:t}}})),e.filter((e=>!this.state.subscriptions.includes(e))).forEach((e=>{e.state.isSubscribed?s.push(e):t.push(e),e.addParentSet(this),this.state.addSubscription(e)})),0===s.length&&0===t.length||!this.state.isSubscribed||(s.forEach((({state:e})=>e.entity.increaseSubscriptionCount(this.state.id))),t.length>0&&this.updateSubscription({subscribing:!0,subscriptions:t}))}removeSubscription(e){this.removeSubscriptions([e])}removeSubscriptions(e){const t=[];this.state.client.logger.debug(this.subscriptionType,(()=>{const t=[],s=[];return e.forEach((e=>{this.state.subscriptions.includes(e)?s.push(e):t.push(e)})),{messageType:"object",details:`Remove subscriptions from ${this.id} (subscriptions count: ${this.state.subscriptions.length}):`,message:{removedSubscriptions:s,ignoredSubscriptions:t}}})),e.filter((e=>this.state.subscriptions.includes(e))).forEach((e=>{e.state.isSubscribed&&t.push(e),e.removeParentSet(this),this.state.removeSubscription(e,e.parentSetsCount>1)})),0!==t.length&&this.state.isSubscribed&&this.updateSubscription({subscribing:!1,subscriptions:t})}addSubscriptionSet(e){this.addSubscriptions(e.subscriptions)}removeSubscriptionSet(e){this.removeSubscriptions(e.subscriptions)}register(e){var t;const s=null!==(t=e.subscriptions)&&void 0!==t?t:this.state.subscriptions;s.forEach((({state:e})=>e.entity.increaseSubscriptionCount(this.state.id))),this.state.client.logger.trace(this.subscriptionType,(()=>({messageType:"text",message:`Register subscription for real-time events: ${this}`}))),this.state.client.registerEventHandleCapable(this,e.cursor,s)}unregister(e){const t=null!=e?e:this.state.subscriptions;t.forEach((({state:e})=>e.entity.decreaseSubscriptionCount(this.state.id))),this.state.client.logger.trace(this.subscriptionType,(()=>e?{messageType:"object",message:{subscription:this,subscriptions:e},details:"Unregister subscriptions of subscription set from real-time events:"}:{messageType:"text",message:`Unregister subscription from real-time events: ${this}`})),this.state.client.unregisterEventHandleCapable(this,t)}toString(){const e=this.state;return`${this.subscriptionType} { id: ${this.id}, stateId: ${e.id}, clonesCount: ${Object.keys(this.state.clones).length}, isSubscribed: ${e.isSubscribed}, subscriptions: [${e.subscriptions.map((e=>e.toString())).join(", ")}] }`}}class At extends Mt{constructor(e){var t,s;const n=e.entity.subscriptionNames(null!==(s=null===(t=e.options)||void 0===t?void 0:t.receivePresenceEvents)&&void 0!==s&&s),i=new It({[e.entity.subscriptionType==_t.Channel?"channels":"channelGroups"]:n});super(e.client,i,e.options,e.client.subscriptionTimetoken),this.entity=e.entity}}class $t extends Rt{constructor(e){"client"in e?e.client.logger.debug("Subscription",(()=>({messageType:"object",details:"Create subscription with parameters:",message:Object.assign({entity:e.entity},e.options?e.options:{})}))):e.state.client.logger.debug("Subscription","Create subscription clone"),super("state"in e?e.state:new At(e)),this.parents=[],this.handledUpdates=[],this.state.storeClone(this.id,this)}get state(){return super.state}get parentSetsCount(){return this.parents.length}handleEvent(e,t){var s,n;if(this.state.isSubscribed&&this.state.subscriptionInput.contains(null!==(s=t.data.subscription)&&void 0!==s?s:t.data.channel)){if(this.parentSetsCount>0){const e=R(t.data);if(this.handledUpdates.includes(e))return void this.state.client.logger.trace(this.subscriptionType,`Event (${e}) already handled by ${this.id}. Ignoring.`);this.handledUpdates.push(e),this.handledUpdates.length>10&&this.handledUpdates.shift()}this.state.subscriptionInput.contains(null!==(n=t.data.subscription)&&void 0!==n?n:t.data.channel)&&super.handleEvent(e,t)}}subscriptionInput(e=!1){return e&&this.state.entity.subscriptionsCount>0?new It({}):this.state.subscriptionInput}cloneEmpty(){return new $t({state:this.state})}dispose(){this.parentSetsCount>0?this.state.client.logger.debug(this.subscriptionType,(()=>({messageType:"text",message:`'${this.state.entity.subscriptionNames()}' subscription still in use. Ignore dispose request.`}))):(this.handledUpdates.splice(0,this.handledUpdates.length),super.dispose())}invalidate(e=!1){e&&this.state.entity.decreaseSubscriptionCount(this.state.id),this.handledUpdates.splice(0,this.handledUpdates.length),super.invalidate(e)}addParentSet(e){this.parents.includes(e)||(this.parents.push(e),this.state.client.logger.trace(this.subscriptionType,`Add parent subscription set for ${this.id}: ${e.id}. Parent subscription set count: ${this.parentSetsCount}`))}removeParentSet(e){const t=this.parents.indexOf(e);-1!==t&&(this.parents.splice(t,1),this.state.client.logger.trace(this.subscriptionType,`Remove parent subscription set from ${this.id}: ${e.id}. Parent subscription set count: ${this.parentSetsCount}`)),0===this.parentSetsCount&&this.handledUpdates.splice(0,this.handledUpdates.length)}addSubscription(e){this.state.client.logger.debug(this.subscriptionType,(()=>({messageType:"text",message:`Create set with subscription: ${e}`})));const t=new Ut({client:this.state.client,subscriptions:[this,e],options:this.state.options});return this.state.isSubscribed||e.state.isSubscribed?(this.state.client.logger.trace(this.subscriptionType,"Subscribe resulting set because the receiver is already subscribed."),t.subscribe(),t):t}register(e){this.state.entity.increaseSubscriptionCount(this.state.id),this.state.client.logger.trace(this.subscriptionType,(()=>({messageType:"text",message:`Register subscription for real-time events: ${this}`}))),this.state.client.registerEventHandleCapable(this,e.cursor)}unregister(e){this.state.entity.decreaseSubscriptionCount(this.state.id),this.state.client.logger.trace(this.subscriptionType,(()=>({messageType:"text",message:`Unregister subscription from real-time events: ${this}`}))),this.handledUpdates.splice(0,this.handledUpdates.length),this.state.client.unregisterEventHandleCapable(this)}toString(){const e=this.state;return`${this.subscriptionType} { id: ${this.id}, stateId: ${e.id}, entity: ${e.entity.subscriptionNames(!1).pop()}, clonesCount: ${Object.keys(e.clones).length}, isSubscribed: ${e.isSubscribed}, parentSetsCount: ${this.parentSetsCount}, cursor: ${e.cursor?e.cursor.timetoken:"not set"}, referenceTimetoken: ${e.referenceTimetoken?e.referenceTimetoken:"not set"} }`}}class Ft extends pe{constructor(e){var t,s,n,i;super(),this.parameters=e,null!==(t=(n=this.parameters).channels)&&void 0!==t||(n.channels=[]),null!==(s=(i=this.parameters).channelGroups)&&void 0!==s||(i.channelGroups=[])}operation(){return K.PNGetStateOperation}validate(){const{keySet:{subscribeKey:e},channels:t,channelGroups:s}=this.parameters;if(!e)return"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e),{channels:s=[],channelGroups:n=[]}=this.parameters,i={channels:{}};return 1===s.length&&0===n.length?i.channels[s[0]]=t.payload:i.channels=t.payload,i}))}get path(){const{keySet:{subscribeKey:e},uuid:t,channels:s}=this.parameters;return`/v2/presence/sub-key/${e}/channel/${P(null!=s?s:[],",")}/uuid/${C(null!=t?t:"")}`}get queryParameters(){const{channelGroups:e}=this.parameters;return e&&0!==e.length?{"channel-group":e.join(",")}:{}}}class xt extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNSetStateOperation}validate(){const{keySet:{subscribeKey:e},state:t,channels:s=[],channelGroups:n=[]}=this.parameters;return e?void 0===t?"Missing State":0===(null==s?void 0:s.length)&&0===(null==n?void 0:n.length)?"Please provide a list of channels and/or channel-groups":void 0:"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){return{state:this.deserializeResponse(e).payload}}))}get path(){const{keySet:{subscribeKey:e},uuid:t,channels:s}=this.parameters;return`/v2/presence/sub-key/${e}/channel/${P(null!=s?s:[],",")}/uuid/${C(t)}/data`}get queryParameters(){const{channelGroups:e,state:t}=this.parameters,s={state:JSON.stringify(t)};return e&&0!==e.length&&(s["channel-group"]=e.join(",")),s}}class qt extends pe{constructor(e){super({cancellable:!0}),this.parameters=e}operation(){return K.PNHeartbeatOperation}validate(){const{keySet:{subscribeKey:e},channels:t=[],channelGroups:s=[]}=this.parameters;return e?0===t.length&&0===s.length?"Please provide a list of channels and/or channel-groups":void 0:"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}get path(){const{keySet:{subscribeKey:e},channels:t}=this.parameters;return`/v2/presence/sub-key/${e}/channel/${P(null!=t?t:[],",")}/heartbeat`}get queryParameters(){const{channelGroups:e,state:t,heartbeat:s}=this.parameters,n={heartbeat:`${s}`};return e&&0!==e.length&&(n["channel-group"]=e.join(",")),void 0!==t&&(n.state=JSON.stringify(t)),n}}class Gt extends pe{constructor(e){super(),this.parameters=e,this.parameters.channelGroups&&(this.parameters.channelGroups=Array.from(new Set(this.parameters.channelGroups))),this.parameters.channels&&(this.parameters.channels=Array.from(new Set(this.parameters.channels)))}operation(){return K.PNUnsubscribeOperation}validate(){const{keySet:{subscribeKey:e},channels:t=[],channelGroups:s=[]}=this.parameters;return e?0===t.length&&0===s.length?"At least one `channel` or `channel group` should be provided.":void 0:"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}get path(){var e;const{keySet:{subscribeKey:t},channels:s}=this.parameters;return`/v2/presence/sub-key/${t}/channel/${P(null!==(e=null==s?void 0:s.sort())&&void 0!==e?e:[],",")}/leave`}get queryParameters(){const{channelGroups:e}=this.parameters;return e&&0!==e.length?{"channel-group":e.sort().join(",")}:{}}}class Lt extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNWhereNowOperation}validate(){if(!this.parameters.keySet.subscribeKey)return"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return t.payload?{channels:t.payload.channels}:{channels:[]}}))}get path(){const{keySet:{subscribeKey:e},uuid:t}=this.parameters;return`/v2/presence/sub-key/${e}/uuid/${C(t)}`}}class Kt extends pe{constructor(e){var t,s,n,i,r,a,o,c;super(),this.parameters=e,null!==(t=(r=this.parameters).queryParameters)&&void 0!==t||(r.queryParameters={}),null!==(s=(a=this.parameters).includeUUIDs)&&void 0!==s||(a.includeUUIDs=true),null!==(n=(o=this.parameters).includeState)&&void 0!==n||(o.includeState=false),null!==(i=(c=this.parameters).limit)&&void 0!==i||(c.limit=1e3)}operation(){const{channels:e=[],channelGroups:t=[]}=this.parameters;return 0===e.length&&0===t.length?K.PNGlobalHereNowOperation:K.PNHereNowOperation}validate(){if(!this.parameters.keySet.subscribeKey)return"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){var t,s;const n=this.deserializeResponse(e),i="occupancy"in n?1:n.payload.total_channels,r="occupancy"in n?n.occupancy:n.payload.total_occupancy,a={};let o={};const c=this.parameters.limit;let u=!1;if("occupancy"in n){const e=this.parameters.channels[0];o[e]={uuids:null!==(t=n.uuids)&&void 0!==t?t:[],occupancy:r}}else o=null!==(s=n.payload.channels)&&void 0!==s?s:{};return Object.keys(o).forEach((e=>{const t=o[e];a[e]={occupants:this.parameters.includeUUIDs?t.uuids.map((e=>"string"==typeof e?{uuid:e,state:null}:e)):[],name:e,occupancy:t.occupancy},u||t.occupancy!==c||(u=!0)})),{totalChannels:i,totalOccupancy:r,channels:a}}))}get path(){const{keySet:{subscribeKey:e},channels:t,channelGroups:s}=this.parameters;let n=`/v2/presence/sub-key/${e}`;return(t&&t.length>0||s&&s.length>0)&&(n+=`/channel/${P(null!=t?t:[],",")}`),n}get queryParameters(){const{channelGroups:e,includeUUIDs:t,includeState:s,limit:n,offset:i,queryParameters:r}=this.parameters;return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},this.operation()===K.PNHereNowOperation?{limit:n}:{}),this.operation()===K.PNHereNowOperation&&null!=i&&i?{offset:i}:{}),t?{}:{disable_uuids:"1"}),null!=s&&s?{state:"1"}:{}),e&&e.length>0?{"channel-group":e.join(",")}:{}),r)}}class Ht extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNDeleteMessagesOperation}validate(){return this.parameters.keySet.subscribeKey?this.parameters.channel?void 0:"Missing channel":"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v3/history/sub-key/${e}/channel/${C(t)}`}get queryParameters(){const{start:e,end:t}=this.parameters;return Object.assign(Object.assign({},e?{start:e}:{}),t?{end:t}:{})}}class Bt extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNMessageCounts}validate(){const{keySet:{subscribeKey:e},channels:t,timetoken:s,channelTimetokens:n}=this.parameters;return e?t?s&&n?"`timetoken` and `channelTimetokens` are incompatible together":s||n?n&&n.length>1&&n.length!==t.length?"Length of `channelTimetokens` and `channels` do not match":void 0:"`timetoken` or `channelTimetokens` need to be set":"Missing channels":"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){return{channels:this.deserializeResponse(e).channels}}))}get path(){return`/v3/history/sub-key/${this.parameters.keySet.subscribeKey}/message-counts/${P(this.parameters.channels)}`}get queryParameters(){let{channelTimetokens:e}=this.parameters;return this.parameters.timetoken&&(e=[this.parameters.timetoken]),Object.assign(Object.assign({},1===e.length?{timetoken:e[0]}:{}),e.length>1?{channelsTimetoken:e.join(",")}:{})}}class Wt extends pe{constructor(e){var t,s,n;super(),this.parameters=e,e.count?e.count=Math.min(e.count,100):e.count=100,null!==(t=e.stringifiedTimeToken)&&void 0!==t||(e.stringifiedTimeToken=false),null!==(s=e.includeMeta)&&void 0!==s||(e.includeMeta=false),null!==(n=e.logVerbosity)&&void 0!==n||(e.logVerbosity=false)}operation(){return K.PNHistoryOperation}validate(){return this.parameters.keySet.subscribeKey?this.parameters.channel?void 0:"Missing channel":"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e),s=t[0],n=t[1],i=t[2];return Array.isArray(s)?{messages:s.map((e=>{const t=this.processPayload(e.message),s={entry:t.payload,timetoken:e.timetoken};return t.error&&(s.error=t.error),e.meta&&(s.meta=e.meta),s})),startTimeToken:n,endTimeToken:i}:{messages:[],startTimeToken:n,endTimeToken:i}}))}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v2/history/sub-key/${e}/channel/${C(t)}`}get queryParameters(){const{start:e,end:t,reverse:s,count:n,stringifiedTimeToken:i,includeMeta:r}=this.parameters;return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({count:n,include_token:"true"},e?{start:e}:{}),t?{end:t}:{}),i?{string_message_token:"true"}:{}),null!=s?{reverse:s.toString()}:{}),r?{include_meta:"true"}:{})}processPayload(e){const{crypto:t,logVerbosity:s}=this.parameters;if(!t||"string"!=typeof e)return{payload:e};let n,i;try{const s=t.decrypt(e);n=s instanceof ArrayBuffer?JSON.parse(Wt.decoder.decode(s)):s}catch(t){s&&console.log("decryption error",t.message),n=e,i=`Error while decrypting message content: ${t.message}`}return{payload:n,error:i}}}var Vt;!function(e){e[e.Message=-1]="Message",e[e.Files=4]="Files"}(Vt||(Vt={}));class zt extends pe{constructor(e){var t,s,n,i,r;super(),this.parameters=e;const a=null!==(t=e.includeMessageActions)&&void 0!==t&&t,o=e.channels.length>1||a?25:100;e.count?e.count=Math.min(e.count,o):e.count=o,e.includeUuid?e.includeUUID=e.includeUuid:null!==(s=e.includeUUID)&&void 0!==s||(e.includeUUID=true),null!==(n=e.stringifiedTimeToken)&&void 0!==n||(e.stringifiedTimeToken=false),null!==(i=e.includeMessageType)&&void 0!==i||(e.includeMessageType=true),null!==(r=e.logVerbosity)&&void 0!==r||(e.logVerbosity=false)}operation(){return K.PNFetchMessagesOperation}validate(){const{keySet:{subscribeKey:e},channels:t,includeMessageActions:s}=this.parameters;return e?t?void 0!==s&&s&&t.length>1?"History can return actions data for a single channel only. Either pass a single channel or disable the includeMessageActions flag.":void 0:"Missing channels":"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){var t;const s=this.deserializeResponse(e),n=null!==(t=s.channels)&&void 0!==t?t:{},i={};return Object.keys(n).forEach((e=>{i[e]=n[e].map((t=>{null===t.message_type&&(t.message_type=Vt.Message);const s=this.processPayload(e,t),n=Object.assign(Object.assign({channel:e,timetoken:t.timetoken,message:s.payload,messageType:t.message_type},t.custom_message_type?{customMessageType:t.custom_message_type}:{}),{uuid:t.uuid});if(t.actions){const e=n;e.actions=t.actions,e.data=t.actions}return t.meta&&(n.meta=t.meta),s.error&&(n.error=s.error),n}))})),s.more?{channels:i,more:s.more}:{channels:i}}))}get path(){const{keySet:{subscribeKey:e},channels:t,includeMessageActions:s}=this.parameters;return`/v3/${s?"history-with-actions":"history"}/sub-key/${e}/channel/${P(t)}`}get queryParameters(){const{start:e,end:t,count:s,includeCustomMessageType:n,includeMessageType:i,includeMeta:r,includeUUID:a,stringifiedTimeToken:o}=this.parameters;return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({max:s},e?{start:e}:{}),t?{end:t}:{}),o?{string_message_token:"true"}:{}),void 0!==r&&r?{include_meta:"true"}:{}),a?{include_uuid:"true"}:{}),null!=n?{include_custom_message_type:n?"true":"false"}:{}),i?{include_message_type:"true"}:{})}processPayload(e,t){const{crypto:s,logVerbosity:n}=this.parameters;if(!s||"string"!=typeof t.message)return{payload:t.message};let i,r;try{const e=s.decrypt(t.message);i=e instanceof ArrayBuffer?JSON.parse(zt.decoder.decode(e)):e}catch(e){n&&console.log("decryption error",e.message),i=t.message,r=`Error while decrypting message content: ${e.message}`}if(!r&&i&&t.message_type==Vt.Files&&"object"==typeof i&&this.isFileMessage(i)){const t=i;return{payload:{message:t.message,file:Object.assign(Object.assign({},t.file),{url:this.parameters.getFileUrl({channel:e,id:t.file.id,name:t.file.name})})},error:r}}return{payload:i,error:r}}isFileMessage(e){return void 0!==e.file}}class Jt extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNGetMessageActionsOperation}validate(){return this.parameters.keySet.subscribeKey?this.parameters.channel?void 0:"Missing message channel":"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);let s=null,n=null;return t.data.length>0&&(s=t.data[0].actionTimetoken,n=t.data[t.data.length-1].actionTimetoken),{data:t.data,more:t.more,start:s,end:n}}))}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v1/message-actions/${e}/channel/${C(t)}`}get queryParameters(){const{limit:e,start:t,end:s}=this.parameters;return Object.assign(Object.assign(Object.assign({},t?{start:t}:{}),s?{end:s}:{}),e?{limit:e}:{})}}class Xt extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNAddMessageActionOperation}validate(){const{keySet:{subscribeKey:e},action:t,channel:s,messageTimetoken:n}=this.parameters;return e?s?n?t?t.value?t.type?t.type.length>15?"Action.type value exceed maximum length of 15":void 0:"Missing Action.type":"Missing Action.value":"Missing Action":"Missing message timetoken":"Missing message channel":"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((({data:e})=>({data:e})))}))}get path(){const{keySet:{subscribeKey:e},channel:t,messageTimetoken:s}=this.parameters;return`/v1/message-actions/${e}/channel/${C(t)}/message/${s}`}get headers(){var e;return Object.assign(Object.assign({},null!==(e=super.headers)&&void 0!==e?e:{}),{"Content-Type":"application/json"})}get body(){return JSON.stringify(this.parameters.action)}}class Qt extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveMessageActionOperation}validate(){const{keySet:{subscribeKey:e},channel:t,messageTimetoken:s,actionTimetoken:n}=this.parameters;return e?t?s?n?void 0:"Missing action timetoken":"Missing message timetoken":"Missing message action channel":"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((({data:e})=>({data:e})))}))}get path(){const{keySet:{subscribeKey:e},channel:t,actionTimetoken:s,messageTimetoken:n}=this.parameters;return`/v1/message-actions/${e}/channel/${C(t)}/message/${n}/action/${s}`}}class Yt extends pe{constructor(e){var t,s;super(),this.parameters=e,null!==(t=(s=this.parameters).storeInHistory)&&void 0!==t||(s.storeInHistory=true)}operation(){return K.PNPublishFileMessageOperation}validate(){const{channel:e,fileId:t,fileName:s}=this.parameters;return e?t?s?void 0:"file name can't be empty":"file id can't be empty":"channel can't be empty"}parse(e){return r(this,void 0,void 0,(function*(){return{timetoken:this.deserializeResponse(e)[2]}}))}get path(){const{message:e,channel:t,keySet:{publishKey:s,subscribeKey:n},fileId:i,fileName:r}=this.parameters,a=Object.assign({file:{name:r,id:i}},e?{message:e}:{});return`/v1/files/publish-file/${s}/${n}/0/${C(t)}/0/${C(this.prepareMessagePayload(a))}`}get queryParameters(){const{customMessageType:e,storeInHistory:t,ttl:s,meta:n}=this.parameters;return Object.assign(Object.assign(Object.assign({store:t?"1":"0"},e?{custom_message_type:e}:{}),s?{ttl:s}:{}),n&&"object"==typeof n?{meta:JSON.stringify(n)}:{})}prepareMessagePayload(e){const{crypto:t}=this.parameters;if(!t)return JSON.stringify(e)||"";const s=t.encrypt(JSON.stringify(e));return JSON.stringify("string"==typeof s?s:u(s))}}class Zt extends pe{constructor(e){super({method:ue.LOCAL}),this.parameters=e}operation(){return K.PNGetFileUrlOperation}validate(){const{channel:e,id:t,name:s}=this.parameters;return e?t?s?void 0:"file name can't be empty":"file id can't be empty":"channel can't be empty"}parse(e){return r(this,void 0,void 0,(function*(){return e.url}))}get path(){const{channel:e,id:t,name:s,keySet:{subscribeKey:n}}=this.parameters;return`/v1/files/${n}/channels/${C(e)}/files/${C(t)}/${C(s)}`}}class es extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNDeleteFileOperation}validate(){const{channel:e,id:t,name:s}=this.parameters;return e?t?s?void 0:"file name can't be empty":"file id can't be empty":"channel can't be empty"}get path(){const{keySet:{subscribeKey:e},id:t,channel:s,name:n}=this.parameters;return`/v1/files/${e}/channels/${C(s)}/files/${C(t)}/${C(n)}`}}class ts extends pe{constructor(e){var t,s;super(),this.parameters=e,null!==(t=(s=this.parameters).limit)&&void 0!==t||(s.limit=100)}operation(){return K.PNListFilesOperation}validate(){if(!this.parameters.channel)return"channel can't be empty"}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v1/files/${e}/channels/${C(t)}/files`}get queryParameters(){const{limit:e,next:t}=this.parameters;return Object.assign({limit:e},t?{next:t}:{})}}class ss extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNGenerateUploadUrlOperation}validate(){return this.parameters.channel?this.parameters.name?void 0:"'name' can't be empty":"channel can't be empty"}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return{id:t.data.id,name:t.data.name,url:t.file_upload_request.url,formFields:t.file_upload_request.form_fields}}))}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v1/files/${e}/channels/${C(t)}/generate-upload-url`}get headers(){var e;return Object.assign(Object.assign({},null!==(e=super.headers)&&void 0!==e?e:{}),{"Content-Type":"application/json"})}get body(){return JSON.stringify({name:this.parameters.name})}}class ns extends pe{constructor(e){super({method:ue.POST}),this.parameters=e;const t=e.file.mimeType;t&&(e.formFields=e.formFields.map((e=>"Content-Type"===e.name?{name:e.name,value:t}:e)))}operation(){return K.PNPublishFileOperation}validate(){const{fileId:e,fileName:t,file:s,uploadUrl:n}=this.parameters;return e?t?s?n?void 0:"Validation failed: file upload 'url' can't be empty":"Validation failed: 'file' can't be empty":"Validation failed: file 'name' can't be empty":"Validation failed: file 'id' can't be empty"}parse(e){return r(this,void 0,void 0,(function*(){return{status:e.status,message:e.body?ns.decoder.decode(e.body):"OK"}}))}request(){return Object.assign(Object.assign({},super.request()),{origin:new URL(this.parameters.uploadUrl).origin,timeout:300})}get path(){const{pathname:e,search:t}=new URL(this.parameters.uploadUrl);return`${e}${t}`}get body(){return this.parameters.file}get formData(){return this.parameters.formFields}}class is{constructor(e){var t;if(this.parameters=e,this.file=null===(t=this.parameters.PubNubFile)||void 0===t?void 0:t.create(e.file),!this.file)throw new Error("File upload error: unable to create File object.")}process(){return r(this,void 0,void 0,(function*(){let e,t;return this.generateFileUploadUrl().then((s=>(e=s.name,t=s.id,this.uploadFile(s)))).then((e=>{if(204!==e.status)throw new d("Upload to bucket was unsuccessful",{error:!0,statusCode:e.status,category:h.PNUnknownCategory,operation:K.PNPublishFileOperation,errorData:{message:e.message}})})).then((()=>this.publishFileMessage(t,e))).catch((e=>{if(e instanceof d)throw e;const t=e instanceof G?e:G.create(e);throw new d("File upload error.",t.toStatus(K.PNPublishFileOperation))}))}))}generateFileUploadUrl(){return r(this,void 0,void 0,(function*(){const e=new ss(Object.assign(Object.assign({},this.parameters),{name:this.file.name,keySet:this.parameters.keySet}));return this.parameters.sendRequest(e)}))}uploadFile(e){return r(this,void 0,void 0,(function*(){const{cipherKey:t,PubNubFile:s,crypto:n,cryptography:i}=this.parameters,{id:r,name:a,url:o,formFields:c}=e;return this.parameters.PubNubFile.supportsEncryptFile&&(!t&&n?this.file=yield n.encryptFile(this.file,s):t&&i&&(this.file=yield i.encryptFile(t,this.file,s))),this.parameters.sendRequest(new ns({fileId:r,fileName:a,file:this.file,uploadUrl:o,formFields:c}))}))}publishFileMessage(e,t){return r(this,void 0,void 0,(function*(){var s,n,i,r;let a,o={timetoken:"0"},c=this.parameters.fileUploadPublishRetryLimit,u=!1;do{try{o=yield this.parameters.publishFile(Object.assign(Object.assign({},this.parameters),{fileId:e,fileName:t})),u=!0}catch(e){e instanceof d&&(a=e),c-=1}}while(!u&&c>0);if(u)return{status:200,timetoken:o.timetoken,id:e,name:t};throw new d("Publish failed. You may want to execute that operation manually using pubnub.publishFile",{error:!0,category:null!==(n=null===(s=a.status)||void 0===s?void 0:s.category)&&void 0!==n?n:h.PNUnknownCategory,statusCode:null!==(r=null===(i=a.status)||void 0===i?void 0:i.statusCode)&&void 0!==r?r:0,channel:this.parameters.channel,id:e,name:t})}))}}class rs{constructor(e,t){this.subscriptionStateIds=[],this.client=t,this._nameOrId=e}get entityType(){return"Channel"}get subscriptionType(){return _t.Channel}subscriptionNames(e){return[this._nameOrId,...e&&!this._nameOrId.endsWith("-pnpres")?[`${this._nameOrId}-pnpres`]:[]]}subscription(e){return new $t({client:this.client,entity:this,options:e})}get subscriptionsCount(){return this.subscriptionStateIds.length}increaseSubscriptionCount(e){this.subscriptionStateIds.includes(e)||this.subscriptionStateIds.push(e)}decreaseSubscriptionCount(e){{const t=this.subscriptionStateIds.indexOf(e);t>=0&&this.subscriptionStateIds.splice(t,1)}}toString(){return`${this.entityType} { nameOrId: ${this._nameOrId}, subscriptionsCount: ${this.subscriptionsCount} }`}}const as=["default","__default__"],os=e=>{if(!e)return;const t=e.trim();return 0===t.length||as.includes(t.toLowerCase())?void 0:t};class cs extends rs{constructor(e,t,s){super(e,t),this._projection=os(s)}get id(){return this._nameOrId}get projection(){return this._projection}get subscriptionChannel(){return this._projection?`__${this._projection}__${this._nameOrId}`:this._nameOrId}subscriptionNames(e){return[this.subscriptionChannel]}subscription(e){{const t=this.entityForProjection(os(null==e?void 0:e.projection));return t!==this?t.subscription(e):super.subscription(e)}}entityForProjection(e){var t,s,n,i;if(e===this._projection)return this;const r=null!==(t=this.variants)&&void 0!==t?t:this.variants={};null!==(n=r[i=null!==(s=this._projection)&&void 0!==s?s:""])&&void 0!==n||(r[i]=this);const a=null!=e?e:"";let o=r[a];return o||(o=r[a]=this.withProjection(e),o.variants=r),o}toString(){var e;return`${this.entityType} { id: ${this._nameOrId}, projection: ${null!==(e=this._projection)&&void 0!==e?e:"none"}, channel: ${this.subscriptionChannel}, subscriptionsCount: ${this.subscriptionsCount} }`}}class us extends cs{get entityType(){return"DataSyncRelationship"}withProjection(e){return new us(this._nameOrId,this.client,e)}}class ls extends cs{get entityType(){return"DataSyncMembership"}withProjection(e){return new ls(this._nameOrId,this.client,e)}}class hs extends cs{get entityType(){return"DataSyncChannel"}withProjection(e){return new hs(this._nameOrId,this.client,e)}}class ds extends cs{get entityType(){return"DataSyncEntity"}withProjection(e){return new ds(this._nameOrId,this.client,e)}}class ps extends rs{get entityType(){return"ChannelMetadata"}get id(){return this._nameOrId}subscriptionNames(e){return[this.id]}}class gs extends cs{get entityType(){return"DataSyncUser"}withProjection(e){return new gs(this._nameOrId,this.client,e)}}class bs extends rs{get entityType(){return"ChannelGroups"}get name(){return this._nameOrId}get subscriptionType(){return _t.ChannelGroup}}class ys extends rs{get entityType(){return"UserMetadata"}get id(){return this._nameOrId}subscriptionNames(e){return[this.id]}}class ms extends rs{get entityType(){return"Channel"}get name(){return this._nameOrId}}class fs extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNRemoveChannelsFromGroupOperation}validate(){const{keySet:{subscribeKey:e},channels:t,channelGroup:s}=this.parameters;return e?s?t?void 0:"Missing channels":"Missing Channel Group":"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}get path(){const{keySet:{subscribeKey:e},channelGroup:t}=this.parameters;return`/v1/channel-registration/sub-key/${e}/channel-group/${C(t)}`}get queryParameters(){return{remove:this.parameters.channels.join(",")}}}class vs extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNAddChannelsToGroupOperation}validate(){const{keySet:{subscribeKey:e},channels:t,channelGroup:s}=this.parameters;return e?s?t?void 0:"Missing channels":"Missing Channel Group":"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}get path(){const{keySet:{subscribeKey:e},channelGroup:t}=this.parameters;return`/v1/channel-registration/sub-key/${e}/channel-group/${C(t)}`}get queryParameters(){return{add:this.parameters.channels.join(",")}}}class Os extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNChannelsForGroupOperation}validate(){return this.parameters.keySet.subscribeKey?this.parameters.channelGroup?void 0:"Missing Channel Group":"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){return{channels:this.deserializeResponse(e).payload.channels}}))}get path(){const{keySet:{subscribeKey:e},channelGroup:t}=this.parameters;return`/v1/channel-registration/sub-key/${e}/channel-group/${C(t)}`}}class Ss extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNRemoveGroupOperation}validate(){return this.parameters.keySet.subscribeKey?this.parameters.channelGroup?void 0:"Missing Channel Group":"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}get path(){const{keySet:{subscribeKey:e},channelGroup:t}=this.parameters;return`/v1/channel-registration/sub-key/${e}/channel-group/${C(t)}/remove`}}class js extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNChannelGroupsOperation}validate(){if(!this.parameters.keySet.subscribeKey)return"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){return{groups:this.deserializeResponse(e).payload.groups}}))}get path(){return`/v1/channel-registration/sub-key/${this.parameters.keySet.subscribeKey}/channel-group`}}class ws{constructor(e,t,s){this.sendRequest=s,this.logger=e,this.keySet=t}listChannels(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"List channel group channels with parameters:"})));const s=new Os(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=e=>{e&&this.logger.debug("PubNub",`List channel group channels success. Received ${e.channels.length} channels.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}listGroups(e){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub","List all channel groups.");const t=new js({keySet:this.keySet}),s=e=>{e&&this.logger.debug("PubNub",`List all channel groups success. Received ${e.groups.length} groups.`)};return e?this.sendRequest(t,((t,n)=>{s(n),e(t,n)})):this.sendRequest(t).then((e=>(s(e),e)))}))}addChannels(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Add channels to the channel group with parameters:"})));const s=new vs(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=()=>{this.logger.debug("PubNub","Add channels to the channel group success.")};return t?this.sendRequest(s,(e=>{e.error||n(),t(e)})):this.sendRequest(s).then((e=>(n(),e)))}))}removeChannels(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove channels from the channel group with parameters:"})));const s=new fs(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=()=>{this.logger.debug("PubNub","Remove channels from the channel group success.")};return t?this.sendRequest(s,(e=>{e.error||n(),t(e)})):this.sendRequest(s).then((e=>(n(),e)))}))}deleteGroup(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove a channel group with parameters:"})));const s=new Ss(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=()=>{this.logger.debug("PubNub",`Remove a channel group success. Removed '${e.channelGroup}' channel group.'`)};return t?this.sendRequest(s,(e=>{e.error||n(),t(e)})):this.sendRequest(s).then((e=>(n(),e)))}))}}class ks extends pe{constructor(e){var t,s;super(),this.parameters=e,"apns2"===this.parameters.pushGateway&&(null!==(t=(s=this.parameters).environment)&&void 0!==t||(s.environment="development")),this.parameters.count&&this.parameters.count>1e3&&(this.parameters.count=1e3)}operation(){throw Error("Should be implemented in subclass.")}validate(){const{keySet:{subscribeKey:e},action:t,device:s,pushGateway:n}=this.parameters;return e?s?"add"!==t&&"remove"!==t||"channels"in this.parameters&&0!==this.parameters.channels.length?n?"apns2"!==this.parameters.pushGateway||this.parameters.topic?void 0:"Missing APNS2 topic":"Missing GW Type (pushGateway: fcm or apns2)":"Missing Channels":"Missing Device ID (device)":"Missing Subscribe Key"}get path(){const{keySet:{subscribeKey:e},action:t,device:s,pushGateway:n}=this.parameters;let i="apns2"===n?`/v2/push/sub-key/${e}/devices-apns2/${s}`:`/v1/push/sub-key/${e}/devices/${s}`;return"remove-device"===t&&(i=`${i}/remove`),i}get queryParameters(){const{start:e,count:t}=this.parameters;let s=Object.assign(Object.assign({type:this.parameters.pushGateway},e?{start:e}:{}),t&&t>0?{count:t}:{});if("channels"in this.parameters&&(s[this.parameters.action]=this.parameters.channels.join(",")),"apns2"===this.parameters.pushGateway){const{environment:e,topic:t}=this.parameters;s=Object.assign(Object.assign({},s),{environment:e,topic:t})}return s}}class Cs extends ks{constructor(e){super(Object.assign(Object.assign({},e),{action:"remove"}))}operation(){return K.PNRemovePushNotificationEnabledChannelsOperation}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}}class Ps extends ks{constructor(e){super(Object.assign(Object.assign({},e),{action:"list"}))}operation(){return K.PNPushNotificationEnabledChannelsOperation}parse(e){return r(this,void 0,void 0,(function*(){return{channels:this.deserializeResponse(e)}}))}}class Ns extends ks{constructor(e){super(Object.assign(Object.assign({},e),{action:"add"}))}operation(){return K.PNAddPushNotificationEnabledChannelsOperation}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}}class Es extends ks{constructor(e){super(Object.assign(Object.assign({},e),{action:"remove-device"}))}operation(){return K.PNRemoveAllPushNotificationsOperation}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}}class Ts{constructor(e,t,s){this.sendRequest=s,this.logger=e,this.keySet=t}listChannels(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"List push-enabled channels with parameters:"})));const s=new Ps(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=e=>{e&&this.logger.debug("PubNub",`List push-enabled channels success. Received ${e.channels.length} channels.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}addChannels(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Add push-enabled channels with parameters:"})));const s=new Ns(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=()=>{this.logger.debug("PubNub","Add push-enabled channels success.")};return t?this.sendRequest(s,(e=>{e.error||n(),t(e)})):this.sendRequest(s).then((e=>(n(),e)))}))}removeChannels(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove push-enabled channels with parameters:"})));const s=new Cs(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=()=>{this.logger.debug("PubNub","Remove push-enabled channels success.")};return t?this.sendRequest(s,(e=>{e.error||n(),t(e)})):this.sendRequest(s).then((e=>(n(),e)))}))}deleteDevice(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove push notifications for device with parameters:"})));const s=new Es(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=()=>{this.logger.debug("PubNub","Remove push notifications for device success.")};return t?this.sendRequest(s,(e=>{e.error||n(),t(e)})):this.sendRequest(s).then((e=>(n(),e)))}))}}class _s extends pe{constructor(e){var t,s,n,i,r,a;super(),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(r=e.include).customFields)&&void 0!==s||(r.customFields=false),null!==(n=(a=e.include).totalCount)&&void 0!==n||(a.totalCount=false),null!==(i=e.limit)&&void 0!==i||(e.limit=100)}operation(){return K.PNGetAllChannelMetadataOperation}get path(){return`/v2/objects/${this.parameters.keySet.subscribeKey}/channels`}get queryParameters(){const{include:e,page:t,filter:s,sort:n,limit:i}=this.parameters;let r="";return r="string"==typeof n?n:Object.entries(null!=n?n:{}).map((([e,t])=>null!==t?`${e}:${t}`:e)),Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({include:["status","type",...e.customFields?["custom"]:[]].join(","),count:`${e.totalCount}`},s?{filter:s}:{}),(null==t?void 0:t.next)?{start:t.next}:{}),(null==t?void 0:t.prev)?{end:t.prev}:{}),i?{limit:i}:{}),r.length?{sort:r}:{})}}class Is extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveChannelMetadataOperation}validate(){if(!this.parameters.channel)return"Channel cannot be empty"}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v2/objects/${e}/channels/${C(t)}`}}class Ms extends pe{constructor(e){var t,s,n,i,r,a,o,c,u,l,h,d,p,g,b,y,m,f;super(),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(h=e.include).customFields)&&void 0!==s||(h.customFields=false),null!==(n=(d=e.include).totalCount)&&void 0!==n||(d.totalCount=false),null!==(i=(p=e.include).statusField)&&void 0!==i||(p.statusField=false),null!==(r=(g=e.include).typeField)&&void 0!==r||(g.typeField=false),null!==(a=(b=e.include).channelFields)&&void 0!==a||(b.channelFields=false),null!==(o=(y=e.include).customChannelFields)&&void 0!==o||(y.customChannelFields=false),null!==(c=(m=e.include).channelStatusField)&&void 0!==c||(m.channelStatusField=false),null!==(u=(f=e.include).channelTypeField)&&void 0!==u||(f.channelTypeField=false),null!==(l=e.limit)&&void 0!==l||(e.limit=100),this.parameters.userId&&(this.parameters.uuid=this.parameters.userId)}operation(){return K.PNGetMembershipsOperation}validate(){if(!this.parameters.uuid)return"'uuid' cannot be empty"}get path(){const{keySet:{subscribeKey:e},uuid:t}=this.parameters;return`/v2/objects/${e}/uuids/${C(t)}/channels`}get queryParameters(){const{include:e,page:t,filter:s,sort:n,limit:i}=this.parameters;let r="";r="string"==typeof n?n:Object.entries(null!=n?n:{}).map((([e,t])=>null!==t?`${e}:${t}`:e));const a=[];return e.statusField&&a.push("status"),e.typeField&&a.push("type"),e.customFields&&a.push("custom"),e.channelFields&&a.push("channel"),e.channelStatusField&&a.push("channel.status"),e.channelTypeField&&a.push("channel.type"),e.customChannelFields&&a.push("channel.custom"),Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({count:`${e.totalCount}`},a.length>0?{include:a.join(",")}:{}),s?{filter:s}:{}),(null==t?void 0:t.next)?{start:t.next}:{}),(null==t?void 0:t.prev)?{end:t.prev}:{}),i?{limit:i}:{}),r.length?{sort:r}:{})}}class Rs extends pe{constructor(e){var t,s,n,i,r,a,o,c,u,l,h,d,p,g,b,y,m,f;super({method:ue.PATCH}),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(h=e.include).customFields)&&void 0!==s||(h.customFields=false),null!==(n=(d=e.include).totalCount)&&void 0!==n||(d.totalCount=false),null!==(i=(p=e.include).statusField)&&void 0!==i||(p.statusField=false),null!==(r=(g=e.include).typeField)&&void 0!==r||(g.typeField=false),null!==(a=(b=e.include).channelFields)&&void 0!==a||(b.channelFields=false),null!==(o=(y=e.include).customChannelFields)&&void 0!==o||(y.customChannelFields=false),null!==(c=(m=e.include).channelStatusField)&&void 0!==c||(m.channelStatusField=false),null!==(u=(f=e.include).channelTypeField)&&void 0!==u||(f.channelTypeField=false),null!==(l=e.limit)&&void 0!==l||(e.limit=100),this.parameters.userId&&(this.parameters.uuid=this.parameters.userId)}operation(){return K.PNSetMembershipsOperation}validate(){const{uuid:e,channels:t}=this.parameters;return e?t&&0!==t.length?void 0:"Channels cannot be empty":"'uuid' cannot be empty"}get path(){const{keySet:{subscribeKey:e},uuid:t}=this.parameters;return`/v2/objects/${e}/uuids/${C(t)}/channels`}get queryParameters(){const{include:e,page:t,filter:s,sort:n,limit:i}=this.parameters;let r="";r="string"==typeof n?n:Object.entries(null!=n?n:{}).map((([e,t])=>null!==t?`${e}:${t}`:e));const a=["channel.status","channel.type","status"];return e.statusField&&a.push("status"),e.typeField&&a.push("type"),e.customFields&&a.push("custom"),e.channelFields&&a.push("channel"),e.channelStatusField&&a.push("channel.status"),e.channelTypeField&&a.push("channel.type"),e.customChannelFields&&a.push("channel.custom"),Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({count:`${e.totalCount}`},a.length>0?{include:a.join(",")}:{}),s?{filter:s}:{}),(null==t?void 0:t.next)?{start:t.next}:{}),(null==t?void 0:t.prev)?{end:t.prev}:{}),i?{limit:i}:{}),r.length?{sort:r}:{})}get headers(){var e;return Object.assign(Object.assign({},null!==(e=super.headers)&&void 0!==e?e:{}),{"Content-Type":"application/json"})}get body(){const{channels:e,type:t}=this.parameters;return JSON.stringify({[`${t}`]:e.map((e=>"string"==typeof e?{channel:{id:e}}:{channel:{id:e.id},status:e.status,type:e.type,custom:e.custom}))})}}class Ds extends pe{constructor(e){var t,s,n,i;super(),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(i=e.include).customFields)&&void 0!==s||(i.customFields=false),null!==(n=e.limit)&&void 0!==n||(e.limit=100)}operation(){return K.PNGetAllUUIDMetadataOperation}get path(){return`/v2/objects/${this.parameters.keySet.subscribeKey}/uuids`}get queryParameters(){const{include:e,page:t,filter:s,sort:n,limit:i}=this.parameters;let r="";return r="string"==typeof n?n:Object.entries(null!=n?n:{}).map((([e,t])=>null!==t?`${e}:${t}`:e)),Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({include:["status","type",...e.customFields?["custom"]:[]].join(",")},void 0!==e.totalCount?{count:`${e.totalCount}`}:{}),s?{filter:s}:{}),(null==t?void 0:t.next)?{start:t.next}:{}),(null==t?void 0:t.prev)?{end:t.prev}:{}),i?{limit:i}:{}),r.length?{sort:r}:{})}}class Us extends pe{constructor(e){var t,s,n;super(),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(n=e.include).customFields)&&void 0!==s||(n.customFields=true)}operation(){return K.PNGetChannelMetadataOperation}validate(){if(!this.parameters.channel)return"Channel cannot be empty"}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v2/objects/${e}/channels/${C(t)}`}get queryParameters(){return{include:["status","type",...this.parameters.include.customFields?["custom"]:[]].join(",")}}}class As extends pe{constructor(e){var t,s,n;super({method:ue.PATCH}),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(n=e.include).customFields)&&void 0!==s||(n.customFields=true)}operation(){return K.PNSetChannelMetadataOperation}validate(){return this.parameters.channel?this.parameters.data?void 0:"Data cannot be empty":"Channel cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json"})}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v2/objects/${e}/channels/${C(t)}`}get queryParameters(){return{include:["status","type",...this.parameters.include.customFields?["custom"]:[]].join(",")}}get body(){return JSON.stringify(this.parameters.data)}}class $s extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e,this.parameters.userId&&(this.parameters.uuid=this.parameters.userId)}operation(){return K.PNRemoveUUIDMetadataOperation}validate(){if(!this.parameters.uuid)return"'uuid' cannot be empty"}get path(){const{keySet:{subscribeKey:e},uuid:t}=this.parameters;return`/v2/objects/${e}/uuids/${C(t)}`}}class Fs extends pe{constructor(e){var t,s,n,i,r,a,o,c,u,l,h,d,p,g,b,y,m,f;super(),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(h=e.include).customFields)&&void 0!==s||(h.customFields=false),null!==(n=(d=e.include).totalCount)&&void 0!==n||(d.totalCount=false),null!==(i=(p=e.include).statusField)&&void 0!==i||(p.statusField=false),null!==(r=(g=e.include).typeField)&&void 0!==r||(g.typeField=false),null!==(a=(b=e.include).UUIDFields)&&void 0!==a||(b.UUIDFields=false),null!==(o=(y=e.include).customUUIDFields)&&void 0!==o||(y.customUUIDFields=false),null!==(c=(m=e.include).UUIDStatusField)&&void 0!==c||(m.UUIDStatusField=false),null!==(u=(f=e.include).UUIDTypeField)&&void 0!==u||(f.UUIDTypeField=false),null!==(l=e.limit)&&void 0!==l||(e.limit=100)}operation(){return K.PNSetMembersOperation}validate(){if(!this.parameters.channel)return"Channel cannot be empty"}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v2/objects/${e}/channels/${C(t)}/uuids`}get queryParameters(){const{include:e,page:t,filter:s,sort:n,limit:i}=this.parameters;let r="";r="string"==typeof n?n:Object.entries(null!=n?n:{}).map((([e,t])=>null!==t?`${e}:${t}`:e));const a=[];return e.statusField&&a.push("status"),e.typeField&&a.push("type"),e.customFields&&a.push("custom"),e.UUIDFields&&a.push("uuid"),e.UUIDStatusField&&a.push("uuid.status"),e.UUIDTypeField&&a.push("uuid.type"),e.customUUIDFields&&a.push("uuid.custom"),Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({count:`${e.totalCount}`},a.length>0?{include:a.join(",")}:{}),s?{filter:s}:{}),(null==t?void 0:t.next)?{start:t.next}:{}),(null==t?void 0:t.prev)?{end:t.prev}:{}),i?{limit:i}:{}),r.length?{sort:r}:{})}}class xs extends pe{constructor(e){var t,s,n,i,r,a,o,c,u,l,h,d,p,g,b,y,m,f;super({method:ue.PATCH}),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(h=e.include).customFields)&&void 0!==s||(h.customFields=false),null!==(n=(d=e.include).totalCount)&&void 0!==n||(d.totalCount=false),null!==(i=(p=e.include).statusField)&&void 0!==i||(p.statusField=false),null!==(r=(g=e.include).typeField)&&void 0!==r||(g.typeField=false),null!==(a=(b=e.include).UUIDFields)&&void 0!==a||(b.UUIDFields=false),null!==(o=(y=e.include).customUUIDFields)&&void 0!==o||(y.customUUIDFields=false),null!==(c=(m=e.include).UUIDStatusField)&&void 0!==c||(m.UUIDStatusField=false),null!==(u=(f=e.include).UUIDTypeField)&&void 0!==u||(f.UUIDTypeField=false),null!==(l=e.limit)&&void 0!==l||(e.limit=100)}operation(){return K.PNSetMembersOperation}validate(){const{channel:e,uuids:t}=this.parameters;return e?t&&0!==t.length?void 0:"UUIDs cannot be empty":"Channel cannot be empty"}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v2/objects/${e}/channels/${C(t)}/uuids`}get queryParameters(){const{include:e,page:t,filter:s,sort:n,limit:i}=this.parameters;let r="";r="string"==typeof n?n:Object.entries(null!=n?n:{}).map((([e,t])=>null!==t?`${e}:${t}`:e));const a=["uuid.status","uuid.type","type"];return e.statusField&&a.push("status"),e.typeField&&a.push("type"),e.customFields&&a.push("custom"),e.UUIDFields&&a.push("uuid"),e.UUIDStatusField&&a.push("uuid.status"),e.UUIDTypeField&&a.push("uuid.type"),e.customUUIDFields&&a.push("uuid.custom"),Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({count:`${e.totalCount}`},a.length>0?{include:a.join(",")}:{}),s?{filter:s}:{}),(null==t?void 0:t.next)?{start:t.next}:{}),(null==t?void 0:t.prev)?{end:t.prev}:{}),i?{limit:i}:{}),r.length?{sort:r}:{})}get headers(){var e;return Object.assign(Object.assign({},null!==(e=super.headers)&&void 0!==e?e:{}),{"Content-Type":"application/json"})}get body(){const{uuids:e,type:t}=this.parameters;return JSON.stringify({[`${t}`]:e.map((e=>"string"==typeof e?{uuid:{id:e}}:{uuid:{id:e.id},status:e.status,type:e.type,custom:e.custom}))})}}class qs extends pe{constructor(e){var t,s,n;super(),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(n=e.include).customFields)&&void 0!==s||(n.customFields=true),this.parameters.userId&&(this.parameters.uuid=this.parameters.userId)}operation(){return K.PNGetUUIDMetadataOperation}validate(){if(!this.parameters.uuid)return"'uuid' cannot be empty"}get path(){const{keySet:{subscribeKey:e},uuid:t}=this.parameters;return`/v2/objects/${e}/uuids/${C(t)}`}get queryParameters(){const{include:e}=this.parameters;return{include:["status","type",...e.customFields?["custom"]:[]].join(",")}}}class Gs extends pe{constructor(e){var t,s,n;super({method:ue.PATCH}),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(n=e.include).customFields)&&void 0!==s||(n.customFields=true),this.parameters.userId&&(this.parameters.uuid=this.parameters.userId)}operation(){return K.PNSetUUIDMetadataOperation}validate(){return this.parameters.uuid?this.parameters.data?void 0:"Data cannot be empty":"'uuid' cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json"})}get path(){const{keySet:{subscribeKey:e},uuid:t}=this.parameters;return`/v2/objects/${e}/uuids/${C(t)}`}get queryParameters(){return{include:["status","type",...this.parameters.include.customFields?["custom"]:[]].join(",")}}get body(){return JSON.stringify(this.parameters.data)}}class Ls{constructor(e,t){this.keySet=e.keySet,this.configuration=e,this.sendRequest=t}get logger(){return this.configuration.logger()}getAllUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{},details:"Get all UUID metadata objects with parameters:"}))),this._getAllUUIDMetadata(e,t)}))}_getAllUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){const s=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0);const n=new Ds(Object.assign(Object.assign({},s),{keySet:this.keySet})),i=e=>{e&&this.logger.debug("PubNub",`Get all UUID metadata success. Received ${e.totalCount} UUID metadata objects.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}))}getUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{uuid:this.configuration.userId},details:`Get ${e&&"function"!=typeof e?"":" current"} UUID metadata object with parameters:`}))),this._getUUIDMetadata(e,t)}))}_getUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){var s;const n=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0),n.userId&&(this.logger.warn("PubNub","'userId' parameter is deprecated. Use 'uuid' instead."),n.uuid=n.userId),null!==(s=n.uuid)&&void 0!==s||(n.uuid=this.configuration.userId);const i=new qs(Object.assign(Object.assign({},n),{keySet:this.keySet})),r=e=>{e&&this.logger.debug("PubNub",`Get UUID metadata object success. Received '${n.uuid}' UUID metadata object.`)};return t?this.sendRequest(i,((e,s)=>{r(s),t(e,s)})):this.sendRequest(i).then((e=>(r(e),e)))}))}setUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set UUID metadata object with parameters:"}))),this._setUUIDMetadata(e,t)}))}_setUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){var s;e.userId&&(this.logger.warn("PubNub","'userId' parameter is deprecated. Use 'uuid' instead."),e.uuid=e.userId),null!==(s=e.uuid)&&void 0!==s||(e.uuid=this.configuration.userId);const n=new Gs(Object.assign(Object.assign({},e),{keySet:this.keySet})),i=t=>{t&&this.logger.debug("PubNub",`Set UUID metadata object success. Updated '${e.uuid}' UUID metadata object.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}))}removeUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{uuid:this.configuration.userId},details:`Remove${e&&"function"!=typeof e?"":" current"} UUID metadata object with parameters:`}))),this._removeUUIDMetadata(e,t)}))}_removeUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){var s;const n=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0),n.userId&&(this.logger.warn("PubNub","'userId' parameter is deprecated. Use 'uuid' instead."),n.uuid=n.userId),null!==(s=n.uuid)&&void 0!==s||(n.uuid=this.configuration.userId);const i=new $s(Object.assign(Object.assign({},n),{keySet:this.keySet})),r=e=>{e&&this.logger.debug("PubNub",`Remove UUID metadata object success. Removed '${n.uuid}' UUID metadata object.`)};return t?this.sendRequest(i,((e,s)=>{r(s),t(e,s)})):this.sendRequest(i).then((e=>(r(e),e)))}))}getAllChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{},details:"Get all Channel metadata objects with parameters:"}))),this._getAllChannelMetadata(e,t)}))}_getAllChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){const s=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0);const n=new _s(Object.assign(Object.assign({},s),{keySet:this.keySet})),i=e=>{e&&this.logger.debug("PubNub",`Get all Channel metadata objects success. Received ${e.totalCount} Channel metadata objects.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}))}getChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Channel metadata object with parameters:"}))),this._getChannelMetadata(e,t)}))}_getChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){const s=new Us(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=t=>{t&&this.logger.debug("PubNub",`Get Channel metadata object success. Received '${e.channel}' Channel metadata object.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}setChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set Channel metadata object with parameters:"}))),this._setChannelMetadata(e,t)}))}_setChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){const s=new As(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=t=>{t&&this.logger.debug("PubNub",`Set Channel metadata object success. Updated '${e.channel}' Channel metadata object.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}removeChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove Channel metadata object with parameters:"}))),this._removeChannelMetadata(e,t)}))}_removeChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){const s=new Is(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=t=>{t&&this.logger.debug("PubNub",`Remove Channel metadata object success. Removed '${e.channel}' Channel metadata object.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}getChannelMembers(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get channel members with parameters:"})));const s=new Fs(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Get channel members success. Received ${e.totalCount} channel members.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}setChannelMembers(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set channel members with parameters:"})));const s=new xs(Object.assign(Object.assign({},e),{type:"set",keySet:this.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Set channel members success. There are ${e.totalCount} channel members now.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}removeChannelMembers(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove channel members with parameters:"})));const s=new xs(Object.assign(Object.assign({},e),{type:"delete",keySet:this.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Remove channel members success. There are ${e.totalCount} channel members now.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}getMemberships(e,t){return r(this,void 0,void 0,(function*(){var s;const n=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0),n.userId&&(this.logger.warn("PubNub","'userId' parameter is deprecated. Use 'uuid' instead."),n.uuid=n.userId),null!==(s=n.uuid)&&void 0!==s||(n.uuid=this.configuration.userId),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},n),details:"Get memberships with parameters:"})));const i=new Ms(Object.assign(Object.assign({},n),{keySet:this.keySet})),r=e=>{e&&this.logger.debug("PubNub",`Get memberships success. Received ${e.totalCount} memberships.`)};return t?this.sendRequest(i,((e,s)=>{r(s),t(e,s)})):this.sendRequest(i).then((e=>(r(e),e)))}))}setMemberships(e,t){return r(this,void 0,void 0,(function*(){var s;e.userId&&(this.logger.warn("PubNub","'userId' parameter is deprecated. Use 'uuid' instead."),e.uuid=e.userId),null!==(s=e.uuid)&&void 0!==s||(e.uuid=this.configuration.userId),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set memberships with parameters:"})));const n=new Rs(Object.assign(Object.assign({},e),{type:"set",keySet:this.keySet})),i=e=>{e&&this.logger.debug("PubNub",`Set memberships success. There are ${e.totalCount} memberships now.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}))}removeMemberships(e,t){return r(this,void 0,void 0,(function*(){var s;e.userId&&(this.logger.warn("PubNub","'userId' parameter is deprecated. Use 'uuid' instead."),e.uuid=e.userId),null!==(s=e.uuid)&&void 0!==s||(e.uuid=this.configuration.userId),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove memberships with parameters:"})));const n=new Rs(Object.assign(Object.assign({},e),{type:"delete",keySet:this.keySet})),i=e=>{e&&this.logger.debug("PubNub",`Remove memberships success. There are ${e.totalCount} memberships now.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}))}fetchMemberships(e,t){return r(this,void 0,void 0,(function*(){var s,n;if(this.logger.warn("PubNub","'fetchMemberships' is deprecated. Use 'pubnub.objects.getChannelMembers' or 'pubnub.objects.getMemberships' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Fetch memberships with parameters:"}))),"spaceId"in e){const n=e,i={channel:null!==(s=n.spaceId)&&void 0!==s?s:n.channel,filter:n.filter,limit:n.limit,page:n.page,include:Object.assign({},n.include),sort:n.sort?Object.fromEntries(Object.entries(n.sort).map((([e,t])=>[e.replace("user","uuid"),t]))):void 0},r=e=>({status:e.status,data:e.data.map((e=>({user:e.uuid,custom:e.custom,updated:e.updated,eTag:e.eTag}))),totalCount:e.totalCount,next:e.next,prev:e.prev});return t?this.getChannelMembers(i,((e,s)=>{t(e,s?r(s):s)})):this.getChannelMembers(i).then(r)}const i=e,r={uuid:null!==(n=i.userId)&&void 0!==n?n:i.uuid,filter:i.filter,limit:i.limit,page:i.page,include:Object.assign({},i.include),sort:i.sort?Object.fromEntries(Object.entries(i.sort).map((([e,t])=>[e.replace("space","channel"),t]))):void 0},a=e=>({status:e.status,data:e.data.map((e=>({space:e.channel,custom:e.custom,updated:e.updated,eTag:e.eTag}))),totalCount:e.totalCount,next:e.next,prev:e.prev});return t?this.getMemberships(r,((e,s)=>{t(e,s?a(s):s)})):this.getMemberships(r).then(a)}))}addMemberships(e,t){return r(this,void 0,void 0,(function*(){var s,n,i,r,a,o;if(this.logger.warn("PubNub","'addMemberships' is deprecated. Use 'pubnub.objects.setChannelMembers' or 'pubnub.objects.setMemberships' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Add memberships with parameters:"}))),"spaceId"in e){const r=e,a={channel:null!==(s=r.spaceId)&&void 0!==s?s:r.channel,uuids:null!==(i=null===(n=r.users)||void 0===n?void 0:n.map((e=>"string"==typeof e?e:{id:e.userId,custom:e.custom})))&&void 0!==i?i:r.uuids,limit:0};return t?this.setChannelMembers(a,t):this.setChannelMembers(a)}const c=e,u={uuid:null!==(r=c.userId)&&void 0!==r?r:c.uuid,channels:null!==(o=null===(a=c.spaces)||void 0===a?void 0:a.map((e=>"string"==typeof e?e:{id:e.spaceId,custom:e.custom})))&&void 0!==o?o:c.channels,limit:0};return t?this.setMemberships(u,t):this.setMemberships(u)}))}}class Ks extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNCreateDataSyncUserOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.data?void 0===this.parameters.data.classVersion||null===this.parameters.data.classVersion?"Entity class version cannot be empty":void 0:"User data cannot be empty"}get headers(){var e;const t=null!==(e=super.headers)&&void 0!==e?e:{};return Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.user+json;version=1"})}get path(){const{keySet:{subscribeKey:e}}=this.parameters;return`/v1/datasync/subkeys/${e}/users`}get body(){const{id:e,class:t,classLevel:s,data:n}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},void 0!==e?{id:e}:{}),void 0!==t?{entityClass:t}:{}),{entityClassVersion:n.classVersion}),void 0!==s?{entityClassLevel:s}:{}),void 0!==n.status?{status:n.status}:{}),void 0!==n.payload?{payload:n.payload}:{})})}}function Hs(e){return"string"==typeof e?e:Object.entries(null!=e?e:{}).map((([e,t])=>null!==t?`${e}:${t}`:e))}function Bs(e){const{add:t,replace:s,remove:n,move:i,copy:r,test:a}=e,o=[];if(t)for(const[e,s]of Object.entries(t))o.push({op:"add",path:e,value:s});if(s)for(const[e,t]of Object.entries(s))o.push({op:"replace",path:e,value:t});if(n)for(const e of n)o.push({op:"remove",path:e});if(i)for(const{from:e,path:t}of i)o.push({op:"move",from:e,path:t});if(r)for(const{from:e,path:t}of r)o.push({op:"copy",from:e,path:t});if(a)for(const[e,t]of Object.entries(a))o.push({op:"test",path:e,value:t});return o}class Ws extends pe{constructor(e){var t;super(),this.parameters=e,null!==(t=e.limit)&&void 0!==t||(e.limit=20)}operation(){return K.PNGetDataSyncUsersOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}get path(){return`/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/users`}get queryParameters(){const{class:e,classVersion:t,classLevel:s,cursor:n,limit:i,filter:r,filterFast:a,sort:o}=this.parameters,c=Hs(o);return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},e?{entity_class:e}:{}),void 0!==t?{entity_class_version:`${t}`}:{}),s?{entity_class_level:s}:{}),n?{cursor:n}:{}),i?{limit:`${i}`}:{}),r?{filter:r}:{}),a?{filter_fast:a}:{}),c.length?{sort:c}:{})}}class Vs extends pe{constructor(e){super({method:ue.PUT}),this.parameters=e}operation(){return K.PNSetDataSyncUserOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.id?this.parameters.data?void 0===this.parameters.data.classVersion||null===this.parameters.data.classVersion?"Entity class version cannot be empty":void 0:"User data cannot be empty":"User id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.user+json;version=1"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/users/${C(t)}`}get body(){const{data:e}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign({entityClassVersion:e.classVersion},void 0!==e.status?{status:e.status}:{}),void 0!==e.payload?{payload:e.payload}:{})})}}class zs extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveDataSyncUserOperation}validate(){if(!this.parameters.id)return"User id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.keys(t).length>0?t:void 0}parse(e){return r(this,void 0,void 0,(function*(){return{status:e.status}}))}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/users/${C(t)}`}}class Js extends pe{constructor(e){super({method:ue.PATCH}),this.parameters=e}operation(){return K.PNUpdateDataSyncUserOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"User id cannot be empty";const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=e&&Object.keys(e).length>0,o=t&&Object.keys(t).length>0,c=s&&s.length>0,u=n&&n.length>0,l=i&&i.length>0,h=r&&Object.keys(r).length>0;return a||o||c||u||l||h?void 0:"At least one of add, replace, remove, move, copy, or test must be provided"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json-patch+json"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/users/${C(t)}`}get body(){const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=Bs({add:e,replace:t,remove:s,move:n,copy:i,test:r});return JSON.stringify(a)}}class Xs extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNGetDataSyncUserOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"User id cannot be empty"}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/users/${C(t)}`}}class Qs extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNCreateDataSyncChannelOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.data?void 0===this.parameters.data.classVersion||null===this.parameters.data.classVersion?"Entity class version cannot be empty":void 0:"Channel data cannot be empty"}get headers(){var e;const t=null!==(e=super.headers)&&void 0!==e?e:{};return Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.channel+json;version=1"})}get path(){const{keySet:{subscribeKey:e}}=this.parameters;return`/v1/datasync/subkeys/${e}/channels`}get body(){const{id:e,class:t,classLevel:s,data:n}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},void 0!==e?{id:e}:{}),void 0!==t?{entityClass:t}:{}),{entityClassVersion:n.classVersion}),void 0!==s?{entityClassLevel:s}:{}),void 0!==n.status?{status:n.status}:{}),void 0!==n.payload?{payload:n.payload}:{})})}}class Ys extends pe{constructor(e){var t;super(),this.parameters=e,null!==(t=e.limit)&&void 0!==t||(e.limit=20)}operation(){return K.PNGetDataSyncChannelsOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}get path(){return`/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/channels`}get queryParameters(){const{class:e,classVersion:t,classLevel:s,cursor:n,limit:i,filter:r,filterFast:a,sort:o}=this.parameters,c=Hs(o);return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},e?{entity_class:e}:{}),void 0!==t?{entity_class_version:`${t}`}:{}),s?{entity_class_level:s}:{}),n?{cursor:n}:{}),i?{limit:`${i}`}:{}),r?{filter:r}:{}),a?{filter_fast:a}:{}),c.length?{sort:c}:{})}}class Zs extends pe{constructor(e){super({method:ue.PUT}),this.parameters=e}operation(){return K.PNSetDataSyncChannelOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.id?this.parameters.data?void 0===this.parameters.data.classVersion||null===this.parameters.data.classVersion?"Entity class version cannot be empty":void 0:"Channel data cannot be empty":"Channel id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.channel+json;version=1"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/channels/${C(t)}`}get body(){const{data:e}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign({entityClassVersion:e.classVersion},void 0!==e.status?{status:e.status}:{}),void 0!==e.payload?{payload:e.payload}:{})})}}class en extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveDataSyncChannelOperation}validate(){if(!this.parameters.id)return"Channel id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.keys(t).length>0?t:void 0}parse(e){return r(this,void 0,void 0,(function*(){return{status:e.status}}))}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/channels/${C(t)}`}}class tn extends pe{constructor(e){super({method:ue.PATCH}),this.parameters=e}operation(){return K.PNUpdateDataSyncChannelOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Channel id cannot be empty";const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=e&&Object.keys(e).length>0,o=t&&Object.keys(t).length>0,c=s&&s.length>0,u=n&&n.length>0,l=i&&i.length>0,h=r&&Object.keys(r).length>0;return a||o||c||u||l||h?void 0:"At least one of add, replace, remove, move, copy, or test must be provided"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json-patch+json"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/channels/${C(t)}`}get body(){const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=Bs({add:e,replace:t,remove:s,move:n,copy:i,test:r});return JSON.stringify(a)}}class sn extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNGetDataSyncChannelOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Channel id cannot be empty"}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/channels/${C(t)}`}}class nn extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNCreateDataSyncMembershipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.userId?this.parameters.channelId?this.parameters.data?this.parameters.data.classVersion?void 0:"Membership class version cannot be empty":"Membership data cannot be empty":"Channel id cannot be empty":"User id cannot be empty"}get headers(){var e;const t=null!==(e=super.headers)&&void 0!==e?e:{};return Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.membership+json;version=1"})}get path(){const{keySet:{subscribeKey:e}}=this.parameters;return`/v1/datasync/subkeys/${e}/memberships`}get body(){const{id:e,userId:t,channelId:s,data:n}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign(Object.assign(Object.assign({},void 0!==e?{id:e}:{}),{userId:t,channelId:s,relationshipClassVersion:n.classVersion}),void 0!==n.status?{status:n.status}:{}),void 0!==n.payload?{payload:n.payload}:{})})}}class rn extends pe{constructor(e){var t;super(),this.parameters=e,null!==(t=e.limit)&&void 0!==t||(e.limit=20)}operation(){return K.PNGetDataSyncMembershipsOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}get path(){return`/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/memberships`}get queryParameters(){const{userId:e,channelId:t,classVersion:s,cursor:n,limit:i,filter:r,filterFast:a,sort:o}=this.parameters,c=Hs(o);return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},e?{user_id:e}:{}),t?{channel_id:t}:{}),void 0!==s?{relationship_class_version:`${s}`}:{}),n?{cursor:n}:{}),i?{limit:`${i}`}:{}),r?{filter:r}:{}),a?{filter_fast:a}:{}),c.length?{sort:c}:{})}}class an extends pe{constructor(e){super({method:ue.PUT}),this.parameters=e}operation(){return K.PNSetDataSyncMembershipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.id?this.parameters.userId?this.parameters.channelId?this.parameters.data?this.parameters.data.classVersion?void 0:"Membership class version cannot be empty":"Membership data cannot be empty":"Channel id cannot be empty":"User id cannot be empty":"Membership id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.membership+json;version=1"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/memberships/${C(t)}`}get body(){const{userId:e,channelId:t,data:s}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign({userId:e,channelId:t,relationshipClassVersion:s.classVersion},void 0!==s.status?{status:s.status}:{}),void 0!==s.payload?{payload:s.payload}:{})})}}class on extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveDataSyncMembershipOperation}validate(){if(!this.parameters.id)return"Membership id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.keys(t).length>0?t:void 0}parse(e){return r(this,void 0,void 0,(function*(){return{status:e.status}}))}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/memberships/${C(t)}`}}class cn extends pe{constructor(e){super({method:ue.PATCH}),this.parameters=e}operation(){return K.PNUpdateDataSyncMembershipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Membership id cannot be empty";const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=e&&Object.keys(e).length>0,o=t&&Object.keys(t).length>0,c=s&&s.length>0,u=n&&n.length>0,l=i&&i.length>0,h=r&&Object.keys(r).length>0;return a||o||c||u||l||h?void 0:"At least one of add, replace, remove, move, copy, or test must be provided"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json-patch+json"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/memberships/${C(t)}`}get body(){const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=Bs({add:e,replace:t,remove:s,move:n,copy:i,test:r});return JSON.stringify(a)}}class un extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNGetDataSyncMembershipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Membership id cannot be empty"}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/memberships/${C(t)}`}}class ln extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNCreateDataSyncRelationshipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.entityAId?this.parameters.entityBId?this.parameters.class?this.parameters.data?this.parameters.data.classVersion?void 0:"Relationship class version cannot be empty":"Relationship data cannot be empty":"Relationship class cannot be empty":"Entity B id cannot be empty":"Entity A id cannot be empty"}get headers(){var e;const t=null!==(e=super.headers)&&void 0!==e?e:{};return Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.relationship+json;version=1"})}get path(){const{keySet:{subscribeKey:e}}=this.parameters;return`/v1/datasync/subkeys/${e}/relationships`}get body(){const{id:e,class:t,entityAId:s,entityBId:n,data:i}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign(Object.assign(Object.assign({},void 0!==e?{id:e}:{}),{entityAId:s,entityBId:n,relationshipClass:t,relationshipClassVersion:i.classVersion}),void 0!==i.status?{status:i.status}:{}),void 0!==i.payload?{payload:i.payload}:{})})}}class hn extends pe{constructor(e){var t;super(),this.parameters=e,null!==(t=e.limit)&&void 0!==t||(e.limit=20)}operation(){return K.PNGetDataSyncRelationshipsOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.class)return"Relationship class cannot be empty"}get path(){return`/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/relationships`}get queryParameters(){const{class:e,classVersion:t,entityAId:s,entityBId:n,cursor:i,limit:r,filter:a,filterFast:o,sort:c}=this.parameters,u=Hs(c);return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({relationship_class:e},void 0!==t?{relationship_class_version:`${t}`}:{}),s?{entity_a_id:s}:{}),n?{entity_b_id:n}:{}),i?{cursor:i}:{}),r?{limit:`${r}`}:{}),a?{filter:a}:{}),o?{filter_fast:o}:{}),u.length?{sort:u}:{})}}class dn extends pe{constructor(e){super({method:ue.PUT}),this.parameters=e}operation(){return K.PNSetDataSyncRelationshipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.id?this.parameters.entityAId?this.parameters.entityBId?this.parameters.data?this.parameters.data.classVersion?void 0:"Relationship class version cannot be empty":"Relationship data cannot be empty":"Entity B id cannot be empty":"Entity A id cannot be empty":"Relationship id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.relationship+json;version=1"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/relationships/${C(t)}`}get body(){const{entityAId:e,entityBId:t,data:s}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign({entityAId:e,entityBId:t,relationshipClassVersion:s.classVersion},void 0!==s.status?{status:s.status}:{}),void 0!==s.payload?{payload:s.payload}:{})})}}class pn extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveDataSyncRelationshipOperation}validate(){if(!this.parameters.id)return"Relationship id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.keys(t).length>0?t:void 0}parse(e){return r(this,void 0,void 0,(function*(){return{status:e.status}}))}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/relationships/${C(t)}`}}class gn extends pe{constructor(e){super({method:ue.PATCH}),this.parameters=e}operation(){return K.PNUpdateDataSyncRelationshipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Relationship id cannot be empty";const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=e&&Object.keys(e).length>0,o=t&&Object.keys(t).length>0,c=s&&s.length>0,u=n&&n.length>0,l=i&&i.length>0,h=r&&Object.keys(r).length>0;return a||o||c||u||l||h?void 0:"At least one of add, replace, remove, move, copy, or test must be provided"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json-patch+json"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/relationships/${C(t)}`}get body(){const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=Bs({add:e,replace:t,remove:s,move:n,copy:i,test:r});return JSON.stringify(a)}}class bn extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNGetDataSyncRelationshipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Relationship id cannot be empty"}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/relationships/${C(t)}`}}class yn extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNCreateDataSyncEntityOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.class?this.parameters.data?void 0===this.parameters.data.classVersion||null===this.parameters.data.classVersion?"Entity class version cannot be empty":void 0:"Entity data cannot be empty":"Entity class cannot be empty"}get headers(){var e;const t=null!==(e=super.headers)&&void 0!==e?e:{};return Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.entity+json;version=1"})}get path(){const{keySet:{subscribeKey:e}}=this.parameters;return`/v1/datasync/subkeys/${e}/entities`}get body(){const{id:e,class:t,classLevel:s,data:n}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},void 0!==e?{id:e}:{}),{entityClass:t,entityClassVersion:n.classVersion}),void 0!==s?{entityClassLevel:s}:{}),void 0!==n.status?{status:n.status}:{}),void 0!==n.payload?{payload:n.payload}:{})})}}class mn extends pe{constructor(e){var t;super(),this.parameters=e,null!==(t=e.limit)&&void 0!==t||(e.limit=20)}operation(){return K.PNGetDataSyncEntitiesOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.class)return"Entity class cannot be empty"}get path(){return`/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/entities`}get queryParameters(){const{class:e,classVersion:t,classLevel:s,cursor:n,limit:i,filter:r,filterFast:a,sort:o}=this.parameters,c=Hs(o);return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({entity_class:e},void 0!==t?{entity_class_version:`${t}`}:{}),s?{entity_class_level:s}:{}),n?{cursor:n}:{}),i?{limit:`${i}`}:{}),r?{filter:r}:{}),a?{filter_fast:a}:{}),c.length?{sort:c}:{})}}class fn extends pe{constructor(e){super({method:ue.PUT}),this.parameters=e}operation(){return K.PNSetDataSyncEntityOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.id?this.parameters.data?void 0===this.parameters.data.classVersion||null===this.parameters.data.classVersion?"Entity class version cannot be empty":void 0:"Entity data cannot be empty":"Entity id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.entity+json;version=1"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/entities/${C(t)}`}get body(){const{data:e}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign({entityClassVersion:e.classVersion},void 0!==e.status?{status:e.status}:{}),void 0!==e.payload?{payload:e.payload}:{})})}}class vn extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveDataSyncEntityOperation}validate(){if(!this.parameters.id)return"Entity id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.keys(t).length>0?t:void 0}parse(e){return r(this,void 0,void 0,(function*(){return{status:e.status}}))}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/entities/${C(t)}`}}class On extends pe{constructor(e){super({method:ue.PATCH}),this.parameters=e}operation(){return K.PNUpdateDataSyncEntityOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Entity id cannot be empty";const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=e&&Object.keys(e).length>0,o=t&&Object.keys(t).length>0,c=s&&s.length>0,u=n&&n.length>0,l=i&&i.length>0,h=r&&Object.keys(r).length>0;return a||o||c||u||l||h?void 0:"At least one of add, replace, remove, move, copy, or test must be provided"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json-patch+json"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/entities/${C(t)}`}get body(){const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=Bs({add:e,replace:t,remove:s,move:n,copy:i,test:r});return JSON.stringify(a)}}class Sn extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNGetDataSyncEntityOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Entity id cannot be empty"}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/entities/${C(t)}`}}class jn{constructor(e,t){this.keySet=e.keySet,this.configuration=e,this.sendRequest=t}get logger(){return this.configuration.logger()}createEntity(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create Entity with parameters:"})));const s=new yn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getEntity(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Entity with parameters:"})));const s=new Sn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getEntities(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Entities with parameters:"})));const s=new mn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}setEntity(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set Entity with parameters:"})));const s=new fn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}updateEntity(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update Entity with parameters:"})));const s=new On(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}removeEntity(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove Entity with parameters:"})));const s=new vn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}createRelationship(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create Relationship with parameters:"})));const s=new ln(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getRelationship(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Relationship with parameters:"})));const s=new bn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getRelationships(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Relationships with parameters:"})));const s=new hn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}setRelationship(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set Relationship with parameters:"})));const s=new dn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}updateRelationship(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update Relationship with parameters:"})));const s=new gn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}removeRelationship(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove Relationship with parameters:"})));const s=new pn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}createUser(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create User with parameters:"})));const s=new Ks(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getUser(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get User with parameters:"})));const s=new Xs(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getUsers(e,t){return r(this,void 0,void 0,(function*(){const s=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},s),details:"Get Users with parameters:"})));const n=new Ws(Object.assign(Object.assign({},s),{keySet:this.keySet}));return t?this.sendRequest(n,t):this.sendRequest(n)}))}setUser(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set User with parameters:"})));const s=new Vs(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}updateUser(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update User with parameters:"})));const s=new Js(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}removeUser(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove User with parameters:"})));const s=new zs(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}createChannel(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create Channel with parameters:"})));const s=new Qs(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getChannel(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Channel with parameters:"})));const s=new sn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getChannels(e,t){return r(this,void 0,void 0,(function*(){const s=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},s),details:"Get Channels with parameters:"})));const n=new Ys(Object.assign(Object.assign({},s),{keySet:this.keySet}));return t?this.sendRequest(n,t):this.sendRequest(n)}))}setChannel(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set Channel with parameters:"})));const s=new Zs(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}updateChannel(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update Channel with parameters:"})));const s=new tn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}removeChannel(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove Channel with parameters:"})));const s=new en(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}createMembership(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create Membership with parameters:"})));const s=new nn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getMembership(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Membership with parameters:"})));const s=new un(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getMemberships(e,t){return r(this,void 0,void 0,(function*(){const s=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},s),details:"Get Memberships with parameters:"})));const n=new rn(Object.assign(Object.assign({},s),{keySet:this.keySet}));return t?this.sendRequest(n,t):this.sendRequest(n)}))}setMembership(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set Membership with parameters:"})));const s=new an(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}updateMembership(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update Membership with parameters:"})));const s=new cn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}removeMembership(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove Membership with parameters:"})));const s=new on(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}}class wn extends pe{constructor(){super()}operation(){return K.PNTimeOperation}parse(e){return r(this,void 0,void 0,(function*(){return{timetoken:this.deserializeResponse(e)[0]}}))}get path(){return"/time/0"}}class kn extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNDownloadFileOperation}validate(){const{channel:e,id:t,name:s}=this.parameters;return e?t?s?void 0:"file name can't be empty":"file id can't be empty":"channel can't be empty"}parse(e){return r(this,void 0,void 0,(function*(){const{cipherKey:t,crypto:s,cryptography:n,name:i,PubNubFile:r}=this.parameters,a=e.headers["content-type"];let o,c=e.body;return r.supportsEncryptFile&&(t||s)&&(t&&n?c=yield n.decrypt(t,c):!t&&s&&(o=yield s.decryptFile(r.create({data:c,name:i,mimeType:a}),r))),o||r.create({data:c,name:i,mimeType:a})}))}get path(){const{keySet:{subscribeKey:e},channel:t,id:s,name:n}=this.parameters;return`/v1/files/${e}/channels/${C(t)}/files/${C(s)}/${C(n)}`}}class Cn{static notificationPayload(e,t){return new Pe(e,t)}static generateUUID(){return ie.createUUID()}constructor(e){if(this.eventHandleCapable={},this.entities={},this._configuration=e.configuration,this.cryptography=e.cryptography,this.tokenManager=e.tokenManager,this.transport=e.transport,this.crypto=e.crypto,this.logger.debug("PubNub",(()=>({messageType:"object",message:e.configuration,details:"Create with configuration:",ignoredKeys:(e,t)=>"function"==typeof t[e]||e.startsWith("_")||"keySet"===e||k(e)}))),this._objects=new Ls(this._configuration,this.sendRequest.bind(this)),this._dataSync=new jn(this._configuration,this.sendRequest.bind(this)),this._channelGroups=new ws(this._configuration.logger(),this._configuration.keySet,this.sendRequest.bind(this)),this._push=new Ts(this._configuration.logger(),this._configuration.keySet,this.sendRequest.bind(this)),this.eventDispatcher=new ve,this._configuration.enableEventEngine){this.logger.debug("PubNub","Using new subscription loop management.");let e=this._configuration.getHeartbeatInterval();this.presenceState={},e&&(this.presenceEventEngine=new nt({heartbeat:(e,t)=>(this.logger.trace("PresenceEventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Heartbeat with parameters:"}))),this.heartbeat(e,t)),leave:e=>{this.logger.trace("PresenceEventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Leave with parameters:"}))),this.makeUnsubscribe(e,(()=>{}))},heartbeatDelay:()=>{let t=()=>{};const s=new Promise(((s,n)=>{if(e=this._configuration.getHeartbeatInterval(),e){const i=setTimeout((()=>{s()}),1e3*e);t=()=>{clearTimeout(i),n(new d("Heartbeat interval has been cancelled."))}}else n(new d("Heartbeat interval has been reset."))}));return{cancelDelay:t,promise:s}},emitStatus:e=>this.emitStatus(e),config:this._configuration,presenceState:this.presenceState})),this.eventEngine=new Ct({handshake:e=>(this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Handshake with parameters:",ignoredKeys:["abortSignal","crypto","timeout","keySet","getFileUrl"]}))),this.subscribeHandshake(e)),receiveMessages:e=>(this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Receive messages with parameters:",ignoredKeys:["abortSignal","crypto","timeout","keySet","getFileUrl"]}))),this.subscribeReceiveMessages(e)),join:e=>{var t,s;this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Join with parameters:"}))),e&&0===(null!==(t=e.channels)&&void 0!==t?t:[]).length&&0===(null!==(s=e.groups)&&void 0!==s?s:[]).length?this.logger.trace("EventEngine","Ignoring 'join' announcement request."):this.join(e)},leave:e=>{var t,s;this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Leave with parameters:"}))),e&&0===(null!==(t=e.channels)&&void 0!==t?t:[]).length&&0===(null!==(s=e.groups)&&void 0!==s?s:[]).length?this.logger.trace("EventEngine","Ignoring 'leave' announcement request."):this.leave(e)},leaveAll:e=>{this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Leave all with parameters:"}))),this.leaveAll(e)},presenceReconnect:e=>{this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Reconnect with parameters:"}))),this.presenceReconnect(e)},presenceDisconnect:e=>{this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Disconnect with parameters:"}))),this.presenceDisconnect(e)},presenceState:this.presenceState,config:this._configuration,emitMessages:(e,t)=>{try{this.logger.debug("EventEngine",(()=>({messageType:"object",message:t.map((e=>{const t=e.type===ge.Message||e.type===ge.Signal?R(e.data.message):void 0;return t?{type:e.type,data:Object.assign(Object.assign({},e.data),{pn_mfp:t})}:e})),details:"Received events:"}))),t.forEach((t=>this.emitEvent(e,t)))}catch(e){const t={error:!0,category:h.PNUnknownCategory,errorData:e,statusCode:0};this.emitStatus(t)}},emitStatus:e=>this.emitStatus(e)})}else this.logger.debug("PubNub","Using legacy subscription loop management."),this.subscriptionManager=new je(this._configuration,((e,t)=>{try{this.emitEvent(e,t)}catch(e){const t={error:!0,category:h.PNUnknownCategory,errorData:e,statusCode:0};this.emitStatus(t)}}),this.emitStatus.bind(this),((e,t)=>{this.logger.trace("SubscriptionManager",(()=>({messageType:"object",message:Object.assign({},e),details:"Subscribe with parameters:",ignoredKeys:["crypto","timeout","keySet","getFileUrl"]}))),this.makeSubscribe(e,t)}),((e,t)=>(this.logger.trace("SubscriptionManager",(()=>({messageType:"object",message:Object.assign({},e),details:"Heartbeat with parameters:",ignoredKeys:["crypto","timeout","keySet","getFileUrl"]}))),this.heartbeat(e,t))),((e,t)=>{this.logger.trace("SubscriptionManager",(()=>({messageType:"object",message:Object.assign({},e),details:"Leave with parameters:"}))),this.makeUnsubscribe(e,t)}),this.time.bind(this))}get configuration(){return this._configuration}get _config(){return this.configuration}get authKey(){var e;return null!==(e=this._configuration.authKey)&&void 0!==e?e:void 0}getAuthKey(){return this.authKey}setAuthKey(e){this.logger.debug("PubNub","Auth key updated."),this._configuration.setAuthKey(e),this.onAuthenticationChange&&this.onAuthenticationChange(e)}get userId(){return this._configuration.userId}set userId(e){if(!e||"string"!=typeof e||0===e.trim().length){const e=new Error("Missing or invalid userId parameter. Provide a valid string userId");throw this.logger.error("PubNub",(()=>({messageType:"error",message:e}))),e}this.logger.debug("PubNub",`Set user ID: ${e}`),this._configuration.userId=e,this.onUserIdChange&&this.onUserIdChange(this._configuration.userId)}getUserId(){return this._configuration.userId}setUserId(e){this.userId=e}get filterExpression(){var e;return null!==(e=this._configuration.getFilterExpression())&&void 0!==e?e:void 0}getFilterExpression(){return this.filterExpression}set filterExpression(e){this.logger.debug("PubNub",`Set filter expression: ${e}`),this._configuration.setFilterExpression(e)}setFilterExpression(e){this.logger.debug("PubNub",`Set filter expression: ${e}`),this.filterExpression=e}get cipherKey(){return this._configuration.getCipherKey()}set cipherKey(e){this._configuration.setCipherKey(e)}setCipherKey(e){this.logger.debug("PubNub","Cipher key updated."),this.cipherKey=e}set heartbeatInterval(e){var t;this.logger.debug("PubNub",`Set heartbeat interval: ${e}`),this._configuration.setHeartbeatInterval(e),this.onHeartbeatIntervalChange&&this.onHeartbeatIntervalChange(null!==(t=this._configuration.getHeartbeatInterval())&&void 0!==t?t:0)}setHeartbeatInterval(e){this.heartbeatInterval=e}get logger(){return this._configuration.logger()}getVersion(){return this._configuration.getVersion()}_addPnsdkSuffix(e,t){this.logger.debug("PubNub",`Add '${e}' 'pnsdk' suffix: ${t}`),this._configuration._addPnsdkSuffix(e,t)}getUUID(){return this.userId}setUUID(e){this.logger.warn("PubNub","'setUserId` is deprecated, please use 'setUserId' or 'userId' setter instead."),this.logger.debug("PubNub",`Set UUID: ${e}`),this.userId=e}get customEncrypt(){return this._configuration.getCustomEncrypt()}get customDecrypt(){return this._configuration.getCustomDecrypt()}channel(e){let t=this.entities[`${e}_ch`];return t||(t=this.entities[`${e}_ch`]=new ms(e,this)),t}channelGroup(e){let t=this.entities[`${e}_chg`];return t||(t=this.entities[`${e}_chg`]=new bs(e,this)),t}channelMetadata(e){let t=this.entities[`${e}_chm`];return t||(t=this.entities[`${e}_chm`]=new ps(e,this)),t}userMetadata(e){let t=this.entities[`${e}_um`];return t||(t=this.entities[`${e}_um`]=new ys(e,this)),t}dataSyncUser(e){let t=this.entities[`${e}_dsu`];return t||(t=this.entities[`${e}_dsu`]=new gs(e,this)),t}dataSyncChannel(e){let t=this.entities[`${e}_dsc`];return t||(t=this.entities[`${e}_dsc`]=new hs(e,this)),t}dataSyncMembership(e){let t=this.entities[`${e}_dsm`];return t||(t=this.entities[`${e}_dsm`]=new ls(e,this)),t}dataSyncEntity(e){let t=this.entities[`${e}_dse`];return t||(t=this.entities[`${e}_dse`]=new ds(e,this)),t}dataSyncRelationship(e){let t=this.entities[`${e}_dsr`];return t||(t=this.entities[`${e}_dsr`]=new us(e,this)),t}subscriptionSet(e){var t,s;{const n=[];return null===(t=e.channels)||void 0===t||t.forEach((e=>n.push(this.channel(e)))),null===(s=e.channelGroups)||void 0===s||s.forEach((e=>n.push(this.channelGroup(e)))),new Ut({client:this,entities:n,options:e.subscriptionOptions})}}sendRequest(e,t){return r(this,void 0,void 0,(function*(){const s=e.validate();if(s){const e=(n=s,p(Object.assign({message:n},{}),h.PNValidationErrorCategory));if(this.logger.error("PubNub",(()=>({messageType:"error",message:e}))),t)return t(e,null);throw new d("Validation failed, check status for details",e)}var n;const i=e.request(),r=e.operation();i.formData&&i.formData.length>0||r===K.PNDownloadFileOperation?i.timeout=this._configuration.getFileTimeout():r===K.PNSubscribeOperation||r===K.PNReceiveMessagesOperation?i.timeout=this._configuration.getSubscribeTimeout():i.timeout=this._configuration.getTransactionTimeout();const a={error:!1,operation:r,category:h.PNAcknowledgmentCategory,statusCode:0},[o,c]=this.transport.makeSendable(i);return e.cancellationController=c||null,o.then((t=>{if(a.statusCode=t.status,200!==t.status&&204!==t.status){const e=Cn.decoder.decode(t.body),s=t.headers["content-type"];if(s||-1!==s.indexOf("javascript")||-1!==s.indexOf("json")){const t=JSON.parse(e);"object"==typeof t&&"error"in t&&t.error&&"object"==typeof t.error&&(a.errorData=t.error)}else a.responseText=e}return e.parse(t)})).then((e=>t?t(a,e):e)).catch((e=>{const s=e instanceof G?e:G.create(e);if(t)return s.category!==h.PNCancelledCategory&&this.logger.error("PubNub",(()=>({messageType:"error",message:s.toPubNubError(r,"REST API request processing error, check status for details")}))),t(s.toStatus(r),null);const n=s.toPubNubError(r,"REST API request processing error, check status for details");throw s.category!==h.PNCancelledCategory&&this.logger.error("PubNub",(()=>({messageType:"error",message:n}))),n}))}))}destroy(e=!1){this.logger.info("PubNub","Destroying PubNub client."),this._globalSubscriptionSet&&(this._globalSubscriptionSet.invalidate(!0),this._globalSubscriptionSet=void 0),Object.values(this.eventHandleCapable).forEach((e=>e.invalidate(!0))),this.eventHandleCapable={},this.subscriptionManager?(this.subscriptionManager.unsubscribeAll(e),this.subscriptionManager.disconnect()):this.eventEngine&&this.eventEngine.unsubscribeAll(e),this.presenceEventEngine&&this.presenceEventEngine.leaveAll(e)}stop(){this.logger.warn("PubNub","'stop' is deprecated, please use 'destroy' instead."),this.destroy()}publish(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Publish with parameters:"})));const s=!1===e.replicate&&!1===e.storeInHistory,n=new Pt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule()})),i=e=>{e&&this.logger.debug("PubNub",`${s?"Fire":"Publish"} success with timetoken: ${e.timetoken}`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}}))}signal(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Signal with parameters:"})));const s=new Nt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Publish success with timetoken: ${e.timetoken}`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}fire(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Fire with parameters:"}))),null!=t||(t=()=>{}),this.publish(Object.assign(Object.assign({},e),{replicate:!1,storeInHistory:!1}),t)}))}get globalSubscriptionSet(){return this._globalSubscriptionSet||(this._globalSubscriptionSet=this.subscriptionSet({})),this._globalSubscriptionSet}get subscriptionTimetoken(){return this.subscriptionManager?this.subscriptionManager.subscriptionTimetoken:this.eventEngine?this.eventEngine.subscriptionTimetoken:void 0}getSubscribedChannels(){return this.subscriptionManager?this.subscriptionManager.subscribedChannels:this.eventEngine?this.eventEngine.getSubscribedChannels():[]}getSubscribedChannelGroups(){return this.subscriptionManager?this.subscriptionManager.subscribedChannelGroups:this.eventEngine?this.eventEngine.getSubscribedChannelGroups():[]}registerEventHandleCapable(e,t,s){{let n;this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign(Object.assign({subscription:e},t?{cursor:t}:[]),s?{subscriptions:s}:{}),details:"Register event handle capable:"}))),this.eventHandleCapable[e.state.id]||(this.eventHandleCapable[e.state.id]=e),s&&0!==s.length?(n=new It({}),s.forEach((e=>n.add(e.subscriptionInput(!1))))):n=e.subscriptionInput(!1);const i={};i.channels=n.channels,i.channelGroups=n.channelGroups,t&&(i.timetoken=t.timetoken),this.subscriptionManager?this.subscriptionManager.subscribe(i):this.eventEngine&&this.eventEngine.subscribe(i)}}unregisterEventHandleCapable(e,t){{if(!this.eventHandleCapable[e.state.id])return;const s=[];this.logger.trace("PubNub",(()=>({messageType:"object",message:{subscription:e,subscriptions:t},details:"Unregister event handle capable:"})));let n,i=!t||0===t.length;if(!i&&e instanceof Ut&&e.subscriptions.length===(null==t?void 0:t.length)&&(i=e.subscriptions.every((e=>t.includes(e)))),i&&delete this.eventHandleCapable[e.state.id],t&&0!==t.length?(n=new It({}),t.forEach((e=>{const t=e.subscriptionInput(!0);t.isEmpty?s.push(e):n.add(t)}))):(n=e.subscriptionInput(!0),n.isEmpty&&s.push(e)),s.length>0&&this.logger.trace("PubNub",(()=>{const e=[];return s[0]instanceof Ut?s[0].subscriptions.forEach((t=>e.push(t.state.entity))):s.forEach((t=>e.push(t.state.entity))),{messageType:"object",message:{entities:e},details:"Can't unregister event handle capable because entities still in use:"}})),n.isEmpty)return;{const e=[],t=[];if(Object.values(this.eventHandleCapable).forEach((s=>{const i=s.subscriptionInput(!1),r=i.channelGroups,a=i.channels;e.push(...n.channelGroups.filter((e=>r.includes(e)))),t.push(...n.channels.filter((e=>a.includes(e))))})),(t.length>0||e.length>0)&&(this.logger.trace("PubNub",(()=>{const s=[],i=n=>{const i=n.subscriptionNames(!0),r=n.subscriptionType===_t.Channel?t:e;i.some((e=>r.includes(e)))&&s.push(n)};Object.values(this.eventHandleCapable).forEach((e=>{e instanceof Ut?e.subscriptions.forEach((e=>{i(e.state.entity)})):e instanceof $t&&i(e.state.entity)}));let r="Some entities still in use:";return t.length+e.length===n.length&&(r="Can't unregister event handle capable because entities still in use:"),{messageType:"object",message:{entities:s},details:r}})),n.remove(new It({channels:t,channelGroups:e})),n.isEmpty))return}const r={};r.channels=n.channels,r.channelGroups=n.channelGroups,this.subscriptionManager?this.subscriptionManager.unsubscribe(r):this.eventEngine&&this.eventEngine.unsubscribe(r)}}subscribe(e){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Subscribe with parameters:"})));const t=this.subscriptionSet(Object.assign(Object.assign({},e),{subscriptionOptions:{receivePresenceEvents:e.withPresence}}));this.globalSubscriptionSet.addSubscriptionSet(t),t.dispose();const s="number"==typeof e.timetoken?`${e.timetoken}`:e.timetoken;this.globalSubscriptionSet.subscribe({timetoken:s})}}makeSubscribe(e,t){{this._configuration.isSharedWorkerEnabled()||(e.onDemand=!1);const s=new fe(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule(),getFileUrl:this.getFileUrl.bind(this)}));if(this.sendRequest(s,((e,n)=>{var i;this.subscriptionManager&&(null===(i=this.subscriptionManager.abort)||void 0===i?void 0:i.identifier)===s.requestIdentifier&&(this.subscriptionManager.abort=null),t(e,n)})),this.subscriptionManager){const e=()=>s.abort("Cancel long-poll subscribe request");e.identifier=s.requestIdentifier,this.subscriptionManager.abort=e}}}unsubscribe(e){{if(this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Unsubscribe with parameters:"}))),!this._globalSubscriptionSet)return void this.logger.debug("PubNub","There are no active subscriptions. Ignore.");const t=this.globalSubscriptionSet.subscriptions.filter((t=>{var s,n;const i=t.subscriptionInput(!1);if(i.isEmpty)return!1;for(const t of null!==(s=e.channels)&&void 0!==s?s:[])if(i.contains(t))return!0;for(const t of null!==(n=e.channelGroups)&&void 0!==n?n:[])if(i.contains(t))return!0}));t.length>0&&this.globalSubscriptionSet.removeSubscriptions(t)}}makeUnsubscribe(e,t){{let{channels:s,channelGroups:n}=e;if(this._configuration.getKeepPresenceChannelsInPresenceRequests()||(n&&(n=n.filter((e=>!e.endsWith("-pnpres")))),s&&(s=s.filter((e=>!e.endsWith("-pnpres"))))),0===(null!=n?n:[]).length&&0===(null!=s?s:[]).length)return t({error:!1,operation:K.PNUnsubscribeOperation,category:h.PNAcknowledgmentCategory,statusCode:200});this.sendRequest(new Gt({channels:s,channelGroups:n,keySet:this._configuration.keySet}),t)}}unsubscribeAll(){this.logger.debug("PubNub","Unsubscribe all channels and groups"),this._globalSubscriptionSet&&this._globalSubscriptionSet.invalidate(!1),Object.values(this.eventHandleCapable).forEach((e=>e.invalidate(!1))),this.eventHandleCapable={},this.subscriptionManager?this.subscriptionManager.unsubscribeAll():this.eventEngine&&this.eventEngine.unsubscribeAll()}disconnect(e=!1){this.logger.debug("PubNub",`Disconnect (while offline? ${e?"yes":"no"})`),this.subscriptionManager?this.subscriptionManager.disconnect():this.eventEngine&&this.eventEngine.disconnect(e)}reconnect(e){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Reconnect with parameters:"}))),this.subscriptionManager?this.subscriptionManager.reconnect():this.eventEngine&&this.eventEngine.reconnect(null!=e?e:{})}subscribeHandshake(e){return r(this,void 0,void 0,(function*(){{this._configuration.isSharedWorkerEnabled()||(e.onDemand=!1),e.heartbeat||(e.heartbeat=this._configuration.getPresenceTimeout());const t=new Tt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule(),getFileUrl:this.getFileUrl.bind(this)})),s=e.abortSignal.subscribe((e=>{t.abort("Cancel subscribe handshake request")}));return this.sendRequest(t).then((e=>(s(),e.cursor)))}}))}subscribeReceiveMessages(e){return r(this,void 0,void 0,(function*(){{this._configuration.isSharedWorkerEnabled()||(e.onDemand=!1),e.heartbeat||(e.heartbeat=this._configuration.getPresenceTimeout());const t=new Et(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule(),getFileUrl:this.getFileUrl.bind(this)})),s=e.abortSignal.subscribe((e=>{t.abort("Cancel long-poll subscribe request")}));return this.sendRequest(t).then((e=>(s(),e)))}}))}getMessageActions(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get message actions with parameters:"})));const s=new Jt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Get message actions success. Received ${e.data.length} message actions.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}addMessageAction(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Add message action with parameters:"})));const s=new Xt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Message action add success. Message action added with timetoken: ${e.data.actionTimetoken}`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}removeMessageAction(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove message action with parameters:"})));const s=new Qt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=t=>{t&&this.logger.debug("PubNub",`Message action remove success. Removed message action with ${e.actionTimetoken} timetoken.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}fetchMessages(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Fetch messages with parameters:"})));const s=new zt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule(),getFileUrl:this.getFileUrl.bind(this)})),n=e=>{if(!e)return;const t=Object.values(e.channels).reduce(((e,t)=>e+t.length),0);this.logger.debug("PubNub",`Fetch messages success. Received ${t} messages.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}deleteMessages(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Delete messages with parameters:"})));const s=new Ht(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=e=>{e&&this.logger.debug("PubNub","Delete messages success.")};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}messageCounts(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get messages count with parameters:"})));const s=new Bt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=t=>{if(!t)return;const s=Object.values(t.channels).reduce(((e,t)=>e+t),0);this.logger.debug("PubNub",`Get messages count success. There are ${s} messages since provided reference timetoken${e.channelTimetokens?e.channelTimetokens.join(","):""}.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}history(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Fetch history with parameters:"})));const s=new Wt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule()})),n=e=>{e&&this.logger.debug("PubNub",`Fetch history success. Received ${e.messages.length} messages.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}hereNow(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Here now with parameters:"})));const s=new Kt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Here now success. There are ${e.totalOccupancy} participants in ${e.totalChannels} channels.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}whereNow(e,t){return r(this,void 0,void 0,(function*(){var s;{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Where now with parameters:"})));const n=new Lt({uuid:null!==(s=e.uuid)&&void 0!==s?s:this._configuration.userId,keySet:this._configuration.keySet}),i=e=>{e&&this.logger.debug("PubNub",`Where now success. Currently present in ${e.channels.length} channels.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}}))}getState(e,t){return r(this,void 0,void 0,(function*(){var s;{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get presence state with parameters:"})));const n=new Ft(Object.assign(Object.assign({},e),{uuid:null!==(s=e.uuid)&&void 0!==s?s:this._configuration.userId,keySet:this._configuration.keySet})),i=e=>{e&&this.logger.debug("PubNub",`Get presence state success. Received presence state for ${Object.keys(e.channels).length} channels.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}}))}setState(e,t){return r(this,void 0,void 0,(function*(){var s,n;{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set presence state with parameters:"})));const{keySet:i,userId:r}=this._configuration,a=this._configuration.getPresenceTimeout();let o;if(this._configuration.enableEventEngine&&this.presenceState){const t=this.presenceState;null===(s=e.channels)||void 0===s||s.forEach((s=>t[s]=e.state)),"channelGroups"in e&&(null===(n=e.channelGroups)||void 0===n||n.forEach((s=>t[s]=e.state))),this.onPresenceStateChange&&this.onPresenceStateChange(this.presenceState)}o="withHeartbeat"in e&&e.withHeartbeat?new qt(Object.assign(Object.assign({},e),{keySet:i,heartbeat:a})):new xt(Object.assign(Object.assign({},e),{keySet:i,uuid:r}));const c=e=>{e&&this.logger.debug("PubNub","Set presence state success."+(o instanceof qt?" Presence state has been set using heartbeat endpoint.":""))};return this.subscriptionManager&&(this.subscriptionManager.setState(e),this.onPresenceStateChange&&this.onPresenceStateChange(this.subscriptionManager.presenceState)),t?this.sendRequest(o,((e,s)=>{c(s),t(e,s)})):this.sendRequest(o).then((e=>(c(e),e)))}}))}presence(e){var t;this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Change presence with parameters:"}))),null===(t=this.subscriptionManager)||void 0===t||t.changePresence(e)}heartbeat(e,t){return r(this,void 0,void 0,(function*(){var s;{this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Heartbeat with parameters:"})));let{channels:n,channelGroups:i}=e;if(i&&(i=i.filter((e=>!e.endsWith("-pnpres")))),n&&(n=n.filter((e=>!e.endsWith("-pnpres")))),0===(null!=i?i:[]).length&&0===(null!=n?n:[]).length){const e={error:!1,operation:K.PNHeartbeatOperation,category:h.PNAcknowledgmentCategory,statusCode:200};return this.logger.trace("PubNub","There are no active subscriptions. Ignore."),t?t(e,{}):Promise.resolve(e)}const r=new qt(Object.assign(Object.assign({},e),{channels:[...new Set(n)],channelGroups:[...new Set(i)],keySet:this._configuration.keySet})),a=e=>{e&&this.logger.trace("PubNub","Heartbeat success.")},o=null===(s=e.abortSignal)||void 0===s?void 0:s.subscribe((e=>{r.abort("Cancel long-poll subscribe request")}));return t?this.sendRequest(r,((e,s)=>{a(s),o&&o(),t(e,s)})):this.sendRequest(r).then((e=>(a(e),o&&o(),e)))}}))}join(e){var t,s;this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Join with parameters:"}))),e&&0===(null!==(t=e.channels)&&void 0!==t?t:[]).length&&0===(null!==(s=e.groups)&&void 0!==s?s:[]).length?this.logger.trace("PubNub","Ignoring 'join' announcement request."):this.presenceEventEngine?this.presenceEventEngine.join(e):this.heartbeat(Object.assign(Object.assign({channels:e.channels,channelGroups:e.groups},this._configuration.maintainPresenceState&&this.presenceState&&Object.keys(this.presenceState).length>0&&{state:this.presenceState}),{heartbeat:this._configuration.getPresenceTimeout()}),(()=>{}))}presenceReconnect(e){this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Presence reconnect with parameters:"}))),this.presenceEventEngine?this.presenceEventEngine.reconnect():this.heartbeat(Object.assign(Object.assign({channels:e.channels,channelGroups:e.groups},this._configuration.maintainPresenceState&&{state:this.presenceState}),{heartbeat:this._configuration.getPresenceTimeout()}),(()=>{}))}leave(e){var t,s,n;this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Leave with parameters:"}))),e&&0===(null!==(t=e.channels)&&void 0!==t?t:[]).length&&0===(null!==(s=e.groups)&&void 0!==s?s:[]).length?this.logger.trace("PubNub","Ignoring 'leave' announcement request."):this.presenceEventEngine?null===(n=this.presenceEventEngine)||void 0===n||n.leave(e):this.makeUnsubscribe({channels:e.channels,channelGroups:e.groups},(()=>{}))}leaveAll(e={}){this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Leave all with parameters:"}))),this.presenceEventEngine?this.presenceEventEngine.leaveAll(!!e.isOffline):e.isOffline||this.makeUnsubscribe({channels:e.channels,channelGroups:e.groups},(()=>{}))}presenceDisconnect(e){this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Presence disconnect parameters:"}))),this.presenceEventEngine?this.presenceEventEngine.disconnect(!!e.isOffline):e.isOffline||this.makeUnsubscribe({channels:e.channels,channelGroups:e.groups},(()=>{}))}grantToken(e,t){return r(this,void 0,void 0,(function*(){throw new Error("Grant Token error: PAM module disabled")}))}revokeToken(e,t){return r(this,void 0,void 0,(function*(){throw new Error("Revoke Token error: PAM module disabled")}))}get token(){return this.tokenManager&&this.tokenManager.getToken()}getToken(){return this.token}set token(e){this.tokenManager&&this.tokenManager.setToken(e),this.onAuthenticationChange&&this.onAuthenticationChange(e)}setToken(e){this.logger.debug("PubNub","Access token updated."),this.token=e}parseToken(e){return this.logger.debug("PubNub","Parse access token."),this.tokenManager&&this.tokenManager.parseToken(e)}grant(e,t){return r(this,void 0,void 0,(function*(){throw new Error("Grant error: PAM module disabled")}))}audit(e,t){return r(this,void 0,void 0,(function*(){throw new Error("Grant Permissions error: PAM module disabled")}))}get objects(){return this._objects}get dataSync(){return this._dataSync}fetchUsers(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'fetchUsers' is deprecated. Use 'pubnub.objects.getAllUUIDMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{},details:"Fetch all User objects with parameters:"}))),this.objects._getAllUUIDMetadata(e,t)}))}fetchUser(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'fetchUser' is deprecated. Use 'pubnub.objects.getUUIDMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{uuid:this.userId},details:`Fetch${e&&"function"!=typeof e?"":" current"} User object with parameters:`}))),this.objects._getUUIDMetadata(e,t)}))}createUser(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'createUser' is deprecated. Use 'pubnub.objects.setUUIDMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create User object with parameters:"}))),this.objects._setUUIDMetadata(e,t)}))}updateUser(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'updateUser' is deprecated. Use 'pubnub.objects.setUUIDMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update User object with parameters:"}))),this.objects._setUUIDMetadata(e,t)}))}removeUser(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'removeUser' is deprecated. Use 'pubnub.objects.removeUUIDMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{uuid:this.userId},details:`Remove${e&&"function"!=typeof e?"":" current"} User object with parameters:`}))),this.objects._removeUUIDMetadata(e,t)}))}fetchSpaces(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'fetchSpaces' is deprecated. Use 'pubnub.objects.getAllChannelMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{},details:"Fetch all Space objects with parameters:"}))),this.objects._getAllChannelMetadata(e,t)}))}fetchSpace(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'fetchSpace' is deprecated. Use 'pubnub.objects.getChannelMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Fetch Space object with parameters:"}))),this.objects._getChannelMetadata(e,t)}))}createSpace(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'createSpace' is deprecated. Use 'pubnub.objects.setChannelMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create Space object with parameters:"}))),this.objects._setChannelMetadata(e,t)}))}updateSpace(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'updateSpace' is deprecated. Use 'pubnub.objects.setChannelMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update Space object with parameters:"}))),this.objects._setChannelMetadata(e,t)}))}removeSpace(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'removeSpace' is deprecated. Use 'pubnub.objects.removeChannelMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove Space object with parameters:"}))),this.objects._removeChannelMetadata(e,t)}))}fetchMemberships(e,t){return r(this,void 0,void 0,(function*(){return this.objects.fetchMemberships(e,t)}))}addMemberships(e,t){return r(this,void 0,void 0,(function*(){return this.objects.addMemberships(e,t)}))}updateMemberships(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'addMemberships' is deprecated. Use 'pubnub.objects.setChannelMembers' or 'pubnub.objects.setMemberships' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update memberships with parameters:"}))),this.objects.addMemberships(e,t)}))}removeMemberships(e,t){return r(this,void 0,void 0,(function*(){var s,n,i;{if(this.logger.warn("PubNub","'removeMemberships' is deprecated. Use 'pubnub.objects.removeMemberships' or 'pubnub.objects.removeChannelMembers' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove memberships with parameters:"}))),"spaceId"in e){const i=e,r={channel:null!==(s=i.spaceId)&&void 0!==s?s:i.channel,uuids:null!==(n=i.userIds)&&void 0!==n?n:i.uuids,limit:0};return t?this.objects.removeChannelMembers(r,t):this.objects.removeChannelMembers(r)}const r=e,a={uuid:r.userId,channels:null!==(i=r.spaceIds)&&void 0!==i?i:r.channels,limit:0};return t?this.objects.removeMemberships(a,t):this.objects.removeMemberships(a)}}))}get channelGroups(){return this._channelGroups}get push(){return this._push}sendFile(e,t){return r(this,void 0,void 0,(function*(){{if(!this._configuration.PubNubFile)throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform.");this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Send file with parameters:"})));const s=new is(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,PubNubFile:this._configuration.PubNubFile,fileUploadPublishRetryLimit:this._configuration.fileUploadPublishRetryLimit,file:e.file,sendRequest:this.sendRequest.bind(this),publishFile:this.publishFile.bind(this),crypto:this._configuration.getCryptoModule(),cryptography:this.cryptography?this.cryptography:void 0})),n={error:!1,operation:K.PNPublishFileOperation,category:h.PNAcknowledgmentCategory,statusCode:0},i=e=>{e&&this.logger.debug("PubNub",`Send file success. File shared with ${e.id} ID.`)};return s.process().then((e=>(n.statusCode=e.status,i(e),t?t(n,e):e))).catch((e=>{let s;throw e instanceof d?s=e.status:e instanceof G&&(s=e.toStatus(n.operation)),this.logger.error("PubNub",(()=>({messageType:"error",message:new d("File sending error. Check status for details",s)}))),t&&s&&t(s,null),new d("REST API request processing error. Check status for details",s)}))}}))}publishFile(e,t){return r(this,void 0,void 0,(function*(){{if(!this._configuration.PubNubFile)throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform.");this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Publish file message with parameters:"})));const s=new Yt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule()})),n=e=>{e&&this.logger.debug("PubNub",`Publish file message success. File message published with timetoken: ${e.timetoken}`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}listFiles(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"List files with parameters:"})));const s=new ts(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=e=>{e&&this.logger.debug("PubNub",`List files success. There are ${e.count} uploaded files.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}getFileUrl(e){var t;{const s=this.transport.request(new Zt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})).request()),n=null!==(t=s.queryParameters)&&void 0!==t?t:{},i=Object.keys(n).map((e=>{const t=n[e];return Array.isArray(t)?t.map((t=>`${e}=${C(t)}`)).join("&"):`${e}=${C(t)}`})).join("&");return`${s.origin}${s.path}?${i}`}}downloadFile(e,t){return r(this,void 0,void 0,(function*(){{if(!this._configuration.PubNubFile)throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform.");this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Download file with parameters:"})));const s=new kn(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,PubNubFile:this._configuration.PubNubFile,cryptography:this.cryptography?this.cryptography:void 0,crypto:this._configuration.getCryptoModule()})),n=e=>{e&&this.logger.debug("PubNub","Download file success.")};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):yield this.sendRequest(s).then((e=>(n(e),e)))}}))}deleteFile(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Delete file with parameters:"})));const s=new es(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=t=>{t&&this.logger.debug("PubNub",`Delete file success. Deleted file with ${e.id} ID.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}time(e){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub","Get service time.");const t=new wn,s=e=>{e&&this.logger.debug("PubNub",`Get service time success. Current timetoken: ${e.timetoken}`)};return e?this.sendRequest(t,((t,n)=>{s(n),e(t,n)})):this.sendRequest(t).then((e=>(s(e),e)))}))}emitStatus(e){var t;null===(t=this.eventDispatcher)||void 0===t||t.handleStatus(e)}emitEvent(e,t){var s;this._globalSubscriptionSet&&this._globalSubscriptionSet.handleEvent(e,t),null===(s=this.eventDispatcher)||void 0===s||s.handleEvent(t),Object.values(this.eventHandleCapable).forEach((s=>{s!==this._globalSubscriptionSet&&s.handleEvent(e,t)}))}set onStatus(e){this.eventDispatcher&&(this.eventDispatcher.onStatus=e)}set onMessage(e){this.eventDispatcher&&(this.eventDispatcher.onMessage=e)}set onPresence(e){this.eventDispatcher&&(this.eventDispatcher.onPresence=e)}set onSignal(e){this.eventDispatcher&&(this.eventDispatcher.onSignal=e)}set onObjects(e){this.eventDispatcher&&(this.eventDispatcher.onObjects=e)}set onMessageAction(e){this.eventDispatcher&&(this.eventDispatcher.onMessageAction=e)}set onFile(e){this.eventDispatcher&&(this.eventDispatcher.onFile=e)}set onDataSync(e){this.eventDispatcher&&(this.eventDispatcher.onDataSync=e)}addListener(e){this.eventDispatcher&&this.eventDispatcher.addListener(e)}removeListener(e){this.eventDispatcher&&this.eventDispatcher.removeListener(e)}removeAllListeners(){this.eventDispatcher&&this.eventDispatcher.removeAllListeners()}encrypt(e,t){this.logger.warn("PubNub","'encrypt' is deprecated. Use cryptoModule instead.");const s=this._configuration.getCryptoModule();if(!t&&s&&"string"==typeof e){const t=s.encrypt(e);return"string"==typeof t?t:u(t)}if(!this.crypto)throw new Error("Encryption error: cypher key not set");return this.crypto.encrypt(e,t)}decrypt(e,t){this.logger.warn("PubNub","'decrypt' is deprecated. Use cryptoModule instead.");const s=this._configuration.getCryptoModule();if(!t&&s){const t=s.decrypt(e);return t instanceof ArrayBuffer?JSON.parse((new TextDecoder).decode(t)):t}if(!this.crypto)throw new Error("Decryption error: cypher key not set");return this.crypto.decrypt(e,t)}encryptFile(e,t){return r(this,void 0,void 0,(function*(){var s;if("string"!=typeof e&&(t=e),!t)throw new Error("File encryption error. Source file is missing.");if(!this._configuration.PubNubFile)throw new Error("File encryption error. File constructor not configured.");if("string"!=typeof e&&!this._configuration.getCryptoModule())throw new Error("File encryption error. Crypto module not configured.");if("string"==typeof e){if(!this.cryptography)throw new Error("File encryption error. File encryption not available");return this.cryptography.encryptFile(e,t,this._configuration.PubNubFile)}return null===(s=this._configuration.getCryptoModule())||void 0===s?void 0:s.encryptFile(t,this._configuration.PubNubFile)}))}decryptFile(e,t){return r(this,void 0,void 0,(function*(){var s;if("string"!=typeof e&&(t=e),!t)throw new Error("File encryption error. Source file is missing.");if(!this._configuration.PubNubFile)throw new Error("File decryption error. File constructor not configured.");if("string"==typeof e&&!this._configuration.getCryptoModule())throw new Error("File decryption error. Crypto module not configured.");if("string"==typeof e){if(!this.cryptography)throw new Error("File decryption error. File decryption not available");return this.cryptography.decryptFile(e,t,this._configuration.PubNubFile)}return null===(s=this._configuration.getCryptoModule())||void 0===s?void 0:s.decryptFile(t,this._configuration.PubNubFile)}))}}Cn.decoder=new TextDecoder,Cn.OPERATIONS=K,Cn.CATEGORIES=h,Cn.Endpoint=X,Cn.ExponentialRetryPolicy=Q.ExponentialRetryPolicy,Cn.LinearRetryPolicy=Q.LinearRetryPolicy,Cn.NoneRetryPolicy=Q.None,Cn.LogLevel=V;class Pn{constructor(e,t){this.decode=e,this.base64ToBinary=t}decodeToken(e){let t="";e.length%4==3?t="=":e.length%4==2&&(t="==");const s=e.replace(/-/gi,"+").replace(/_/gi,"/")+t,n=this.decode(this.base64ToBinary(s));return"object"==typeof n?n:void 0}}class Nn extends Cn{constructor(e){var t;const s=void 0!==e.subscriptionWorkerUrl,i=W(e),r=Object.assign(Object.assign({},i),{sdkFamily:"Web"});r.PubNubFile=o;const a=re(r,(e=>{if(e.cipherKey){return new F({default:new $(Object.assign(Object.assign({},e),e.logger?{}:{logger:a.logger()})),cryptors:[new j({cipherKey:e.cipherKey})]})}}));let u,l;e.subscriptionWorkerLogVerbosity?e.subscriptionWorkerLogLevel=V.Debug:void 0===e.subscriptionWorkerLogLevel&&(e.subscriptionWorkerLogLevel=V.None),void 0!==e.subscriptionWorkerLogVerbosity&&a.logger().warn("Configuration","'subscriptionWorkerLogVerbosity' is deprecated. Use 'subscriptionWorkerLogLevel' instead."),a.getCryptoModule()&&(a.getCryptoModule().logger=a.logger()),u=new ce(new Pn((e=>B(n.decode(e))),c)),(a.getCipherKey()||a.secretKey)&&(l=new U({secretKey:a.secretKey,cipherKey:a.getCipherKey(),useRandomIVs:a.getUseRandomIVs(),customEncrypt:a.getCustomEncrypt(),customDecrypt:a.getCustomDecrypt(),logger:a.logger()}));let h,d=()=>{},p=()=>{},g=()=>{},b=()=>{};h=new A;let y=new de(a.logger(),r.transport);if(i.subscriptionWorkerUrl)try{const e=new H({clientIdentifier:a._instanceId,subscriptionKey:a.subscribeKey,userId:a.getUserId(),workerUrl:i.subscriptionWorkerUrl,sdkVersion:a.getVersion(),heartbeatInterval:a.getHeartbeatInterval(),announceSuccessfulHeartbeats:a.announceSuccessfulHeartbeats,announceFailedHeartbeats:a.announceFailedHeartbeats,workerOfflineClientsCheckInterval:r.subscriptionWorkerOfflineClientsCheckInterval,workerUnsubscribeOfflineClients:r.subscriptionWorkerUnsubscribeOfflineClients,workerLogLevel:r.subscriptionWorkerLogLevel,tokenManager:u,transport:y,logger:a.logger()});p=t=>e.onPresenceStateChange(t),d=t=>e.onHeartbeatIntervalChange(t),g=t=>e.onTokenChange(t),b=t=>e.onUserIdChange(t),y=e,i.subscriptionWorkerUnsubscribeOfflineClients&&"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("pagehide",(t=>{t.persisted||e.terminate()}),{once:!0})}catch(e){a.logger().error("PubNub",(()=>({messageType:"error",message:e})))}else s&&a.logger().warn("PubNub","SharedWorker not supported in this browser. Fallback to the original transport.");const m=new he({clientConfiguration:a,tokenManager:u,transport:y});if(super({configuration:a,transport:m,cryptography:h,tokenManager:u,crypto:l}),this.File=o,this.onHeartbeatIntervalChange=d,this.onAuthenticationChange=g,this.onPresenceStateChange=p,this.onUserIdChange=b,y instanceof H){y.emitStatus=this.emitStatus.bind(this);const e=this.disconnect.bind(this);this.disconnect=t=>{y.disconnect(),e()}}(null===(t=e.listenToBrowserNetworkEvents)||void 0===t||t)&&"undefined"!=typeof window&&window.addEventListener&&(window.addEventListener("offline",(()=>{this.networkDownDetected()})),window.addEventListener("online",(()=>{this.networkUpDetected()})))}networkDownDetected(){this.logger.debug("PubNub","Network down detected"),this.emitStatus({category:Nn.CATEGORIES.PNNetworkDownCategory}),this._configuration.restore?this.disconnect(!0):this.destroy(!0)}networkUpDetected(){this.logger.debug("PubNub","Network up detected"),this.emitStatus({category:Nn.CATEGORIES.PNNetworkUpCategory}),this.reconnect()}}return Nn.CryptoModule=F,Nn})); +/*! lil-uuid - v0.1 - MIT License - https://github.com/lil-js/uuid */!function(e,t){!function(e){var t="0.1.0",s={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i};function n(){var e,t,s="";for(e=0;e<32;e++)t=16*Math.random()|0,8!==e&&12!==e&&16!==e&&20!==e||(s+="-"),s+=(12===e?4:16===e?3&t|8:t).toString(16);return s}function i(e,t){var n=s[t||"all"];return n&&n.test(e)||!1}n.isUUID=i,n.VERSION=t,e.uuid=n,e.isUUID=i}(t),null!==e&&(e.exports=t.uuid)}(se,se.exports);var ne=t(se.exports),ie={createUUID:()=>ne.uuid?ne.uuid():ne()};const re=(e,t)=>{var s,n,i,r;!e.retryConfiguration&&e.enableEventEngine&&(e.retryConfiguration=Q.ExponentialRetryPolicy({minimumDelay:2,maximumDelay:150,maximumRetry:6,excluded:[X.MessageSend,X.Presence,X.Files,X.MessageStorage,X.ChannelGroups,X.DevicePushNotifications,X.AppContext,X.MessageReactions]}));const a=`pn-${ie.createUUID()}`;e.logVerbosity?e.logLevel=V.Debug:void 0===e.logLevel&&(e.logLevel=V.None);const o=new te(oe(a),e.logLevel,[...null!==(s=e.loggers)&&void 0!==s?s:[],new z]);void 0!==e.logVerbosity&&o.warn("Configuration","'logVerbosity' is deprecated. Use 'logLevel' instead."),null===(n=e.retryConfiguration)||void 0===n||n.validate();const c=e.useRandomIVs;null!==(i=e.useRandomIVs)&&void 0!==i||(e.useRandomIVs=true),void 0!==c&&(o.warn("Configuration","'useRandomIVs' is deprecated. Pass it to 'cryptoModule' instead."),!1===c&&o.warn("Configuration","Setting 'useRandomIVs' to false is insecure and should only be used to support legacy clients.\n Do not disable random IVs in new applications.")),e.origin=ae(null!==(r=e.ssl)&&void 0!==r&&r,e.origin);const u=e.cryptoModule;u&&delete e.cryptoModule;const l=Object.assign(Object.assign({},e),{_pnsdkSuffix:{},_loggerManager:o,_instanceId:a,_cryptoModule:void 0,_cipherKey:void 0,_setupCryptoModule:t,get instanceId(){if(e.useInstanceId)return this._instanceId},getInstanceId(){if(e.useInstanceId)return this._instanceId},getUserId(){return this.userId},setUserId(e){if(!e||"string"!=typeof e||0===e.trim().length)throw new Error("Missing or invalid userId parameter. Provide a valid string userId");this.userId=e},logger(){return this._loggerManager},getAuthKey(){return this.authKey},setAuthKey(e){this.authKey=e},getFilterExpression(){return this.filterExpression},setFilterExpression(e){this.filterExpression=e},getCipherKey(){return this._cipherKey},setCipherKey(t){this._cipherKey=t,t||!this._cryptoModule?t&&this._setupCryptoModule&&(this._cryptoModule=this._setupCryptoModule({cipherKey:t,useRandomIVs:e.useRandomIVs,customEncrypt:this.getCustomEncrypt(),customDecrypt:this.getCustomDecrypt(),logger:this.logger()})):this._cryptoModule=void 0},getCryptoModule(){return this._cryptoModule},getUseRandomIVs:()=>e.useRandomIVs,isSharedWorkerEnabled:()=>"Web"===e.sdkFamily&&e.subscriptionWorkerUrl,getKeepPresenceChannelsInPresenceRequests:()=>"Web"===e.sdkFamily&&e.subscriptionWorkerUrl,setPresenceTimeout(e){this.heartbeatInterval=e/2-1,this.presenceTimeout=e},getPresenceTimeout(){return this.presenceTimeout},getHeartbeatInterval(){return this.heartbeatInterval},setHeartbeatInterval(e){this.heartbeatInterval=e},getTransactionTimeout(){return this.transactionalRequestTimeout},getSubscribeTimeout(){return this.subscribeRequestTimeout},getFileTimeout(){return this.fileRequestTimeout},get PubNubFile(){return e.PubNubFile},get version(){return"13.1.3"},getVersion(){return this.version},_addPnsdkSuffix(e,t){this._pnsdkSuffix[e]=`${t}`},_getPnsdkSuffix(e){const t=Object.values(this._pnsdkSuffix).join(e);return t.length>0?e+t:""},getUUID(){return this.getUserId()},setUUID(e){this.setUserId(e)},getCustomEncrypt:()=>e.customEncrypt,getCustomDecrypt:()=>e.customDecrypt});return e.cipherKey?(o.warn("Configuration","'cipherKey' is deprecated. Use 'cryptoModule' instead."),l.setCipherKey(e.cipherKey)):u&&(l._cryptoModule=u),l},ae=(e,t)=>{const s=e?"https://":"http://";return"string"==typeof t?`${s}${t}`:`${s}${t[Math.floor(Math.random()*t.length)]}`},oe=e=>{let t=2166136261;for(let s=0;s>>0;return t.toString(16).padStart(8,"0")};class ce{constructor(e){this.cbor=e}setToken(e){e&&e.length>0?this.token=e:this.token=void 0}getToken(){return this.token}parseToken(e){var t,s;const n=this.cbor.decodeToken(e);if(void 0!==n){const e=n.res.uuid?Object.keys(n.res.uuid):[],i=n.res.usr?Object.keys(n.res.usr):[],r=Object.keys(n.res.chan),a=Object.keys(n.res.grp),o=n.pat.uuid?Object.keys(n.pat.uuid):[],c=n.pat.usr?Object.keys(n.pat.usr):[],u=Object.keys(n.pat.chan),l=Object.keys(n.pat.grp),h={version:n.v,timestamp:n.t,ttl:n.ttl,authorized_uuid:n.uuid,signature:n.sig},d=e.length>0,p=i.length>0,g=r.length>0,b=a.length>0;if(d||p||g||b){if(h.resources={},d){const t=h.resources.uuids={};e.forEach((e=>t[e]=this.extractPermissions(n.res.uuid[e])))}if(p){const e=h.resources.users={};i.forEach((t=>e[t]=this.extractCrudPermissions(n.res.usr[t])))}if(g){const e=h.resources.channels={};r.forEach((t=>e[t]=this.extractPermissions(n.res.chan[t])))}if(b){const e=h.resources.groups={};a.forEach((t=>e[t]=this.extractPermissions(n.res.grp[t])))}}const y=this.extractDataSyncScopes(n.res);y&&((null!==(t=h.resources)&&void 0!==t?t:h.resources={}).dataSync=y);const m=o.length>0,f=c.length>0,v=u.length>0,O=l.length>0;if(m||f||v||O){if(h.patterns={},m){const e=h.patterns.uuids={};o.forEach((t=>e[t]=this.extractPermissions(n.pat.uuid[t])))}if(f){const e=h.patterns.users={};c.forEach((t=>e[t]=this.extractCrudPermissions(n.pat.usr[t])))}if(v){const e=h.patterns.channels={};u.forEach((t=>e[t]=this.extractPermissions(n.pat.chan[t])))}if(O){const e=h.patterns.groups={};l.forEach((t=>e[t]=this.extractPermissions(n.pat.grp[t])))}}const S=this.extractDataSyncScopes(n.pat);S&&((null!==(s=h.patterns)&&void 0!==s?s:h.patterns={}).dataSync=S);const j=this.extractCategories(n.cat);return j&&(h.categories=j),n.meta&&Object.keys(n.meta).length>0&&(h.meta=n.meta),h}}extractPermissions(e){const t={read:!1,write:!1,manage:!1,delete:!1,get:!1,update:!1,join:!1};return 128&~e||(t.join=!0),64&~e||(t.update=!0),32&~e||(t.get=!0),8&~e||(t.delete=!0),4&~e||(t.manage=!0),2&~e||(t.write=!0),1&~e||(t.read=!0),t}extractCategories(e){if(!e)return;const t={};return"number"==typeof e.chan&&(t.channels={get:!(32&~e.chan)}),"number"==typeof e.uuid&&(t.uuids={get:!(32&~e.uuid)}),Object.keys(t).length>0?t:void 0}extractDataSyncScopes(e){let t;return[["entities","datasync:entities"],["relationships","datasync:relationships"],["memberships","datasync:memberships"]].forEach((([s,n])=>{const i=e[n];if(!i)return;const r=Object.keys(i);if(0===r.length)return;const a=(null!=t?t:t={})[s]={};r.forEach((e=>a[e]=this.extractCrudPermissions(i[e])))})),t}extractCrudPermissions(e){return{create:!(16&~e),get:!(32&~e),update:!(64&~e),delete:!(8&~e)}}}var ue;!function(e){e.GET="GET",e.POST="POST",e.PATCH="PATCH",e.PUT="PUT",e.DELETE="DELETE",e.LOCAL="LOCAL"}(ue||(ue={}));class le{constructor(e,t,s,n){this.publishKey=e,this.secretKey=t,this.hasher=s,this.logger=n}signature(e){const t=e.path.startsWith("/publish")?ue.GET:e.method;let s=`${t}\n${this.publishKey}\n${e.path}\n${this.queryParameters(e.queryParameters)}\n`;if(t===ue.POST||t===ue.PATCH||t===ue.PUT){const t=e.body;let n;t&&t instanceof ArrayBuffer?n=le.textDecoder.decode(t):t&&"object"!=typeof t&&(n=t),n&&(s+=n)}return this.logger.trace("RequestSignature",(()=>({messageType:"text",message:`Request signature input:\n${s}`}))),`v2.${this.hasher(s,this.secretKey)}`.replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}queryParameters(e){return Object.keys(e).sort().map((t=>{const s=e[t];return Array.isArray(s)?s.sort().map((e=>`${t}=${C(e)}`)).join("&"):`${t}=${C(s)}`})).join("&")}}le.textDecoder=new TextDecoder("utf-8");class he{constructor(e){this.configuration=e;const{clientConfiguration:{keySet:t},shaHMAC:s}=e;t.secretKey&&s&&(this.signatureGenerator=new le(t.publishKey,t.secretKey,s,this.logger))}get logger(){return this.configuration.clientConfiguration.logger()}makeSendable(e){const t=this.configuration.clientConfiguration.retryConfiguration,s=this.configuration.transport;if(void 0!==t){let n,i,r=!1,a=0;const o={abort:e=>{r=!0,n&&clearTimeout(n),i&&i.abort(e)}};return[new Promise(((o,c)=>{const u=()=>{if(r)return;const[l,h]=s.makeSendable(this.request(e));i=h;const d=(s,i)=>{let r=-1;t.shouldRetry(e,s,null==i?void 0:i.category,a+1,null==i?void 0:i.statusCode)&&(r=t.getDelay(a,s)),r>0?(a++,this.logger.warn("PubNubMiddleware",`HTTP request retry #${a} in ${r}ms.`),n=setTimeout((()=>u()),r)):s?o(s):i&&c(i)};l.then((e=>d(e))).catch((e=>d(void 0,e)))};u()})),i?o:void 0]}return s.makeSendable(this.request(e))}request(e){var t;const{clientConfiguration:s}=this.configuration;return(e=this.configuration.transport.request(e)).queryParameters||(e.queryParameters={}),s.useInstanceId&&(e.queryParameters.instanceid=s.getInstanceId()),e.queryParameters.uuid||(e.queryParameters.uuid=s.userId),s.useRequestId&&(e.queryParameters.requestid=e.identifier),e.queryParameters.pnsdk=this.generatePNSDK(),null!==(t=e.origin)&&void 0!==t||(e.origin=s.origin),this.authenticateRequest(e),this.signRequest(e),e}authenticateRequest(e){var t;if(e.path.startsWith("/v2/auth/")||e.path.startsWith("/v3/pam/")||e.path.startsWith("/time"))return;const{clientConfiguration:s,tokenManager:n}=this.configuration,i=null!==(t=n&&n.getToken())&&void 0!==t?t:s.authKey;i&&(e.queryParameters.auth=i)}signRequest(e){this.signatureGenerator&&!e.path.startsWith("/time")&&(e.queryParameters.timestamp=String(Math.floor((new Date).getTime()/1e3)),e.queryParameters.signature=this.signatureGenerator.signature(e))}generatePNSDK(){const{clientConfiguration:e}=this.configuration;if(e.sdkName)return e.sdkName;let t=`PubNub-JS-${e.sdkFamily}`;e.partnerId&&(t+=`-${e.partnerId}`),t+=`/${e.getVersion()}`;const s=e._getPnsdkSuffix(" ");return s.length>0&&(t+=s),t}}class de{constructor(e,t="fetch"){this.logger=e,this.transport=t,e.debug("WebTransport",`Create with configuration:\n - transport: ${t}`),"fetch"===t&&"undefined"==typeof fetch&&(e.warn("WebTransport",`'${t}' not supported in this browser. Fallback to the 'xhr' transport.`),this.transport="xhr"),"fetch"===this.transport&&(de.originalFetch=de.getOriginalFetch(),this.isFetchMonkeyPatched()&&e.warn("WebTransport","Native Web Fetch API 'fetch' function monkey patched."))}makeSendable(e){const t=new AbortController,s={abortController:t,abort:e=>{t.signal.aborted||(this.logger.trace("WebTransport",`On-demand request aborting: ${e}`),t.abort(e))}};return[this.webTransportRequestFromTransportRequest(e).then((t=>(this.logger.debug("WebTransport",(()=>({messageType:"network-request",message:e}))),this.sendRequest(t,s).then((e=>e.arrayBuffer().then((t=>[e,t])))).then((e=>{const s=e[1].byteLength>0?e[1]:void 0,{status:n,headers:i}=e[0],r={};i.forEach(((e,t)=>r[t]=e.toLowerCase()));const a={status:n,url:t.url,headers:r,body:s};if(this.logger.debug("WebTransport",(()=>({messageType:"network-response",message:a}))),n>=400)throw G.create(a);return a})).catch((t=>{const s=("string"==typeof t?t:t.message).toLowerCase();let n="string"==typeof t?new Error(t):t;throw s.includes("timeout")?this.logger.warn("WebTransport",(()=>({messageType:"network-request",message:e,details:"Timeout",canceled:!0}))):s.includes("cancel")||s.includes("abort")?(this.logger.debug("WebTransport",(()=>({messageType:"network-request",message:e,details:"Aborted",canceled:!0}))),n=new Error("Aborted"),n.name="AbortError"):s.includes("network")?this.logger.warn("WebTransport",(()=>({messageType:"network-request",message:e,details:"Network error",failed:!0}))):this.logger.warn("WebTransport",(()=>({messageType:"network-request",message:e,details:G.create(n).message,failed:!0}))),G.create(n)}))))),s]}request(e){return e}sendRequest(e,t){return r(this,void 0,void 0,(function*(){return"fetch"===this.transport?this.sendFetchRequest(e,t):this.sendXHRRequest(e,t)}))}sendFetchRequest(e,t){return r(this,void 0,void 0,(function*(){let s;const n=new Promise(((n,i)=>{s=setTimeout((()=>{clearTimeout(s),i(new Error("Request timeout")),t.abort("Cancel because of timeout")}),1e3*e.timeout)})),i=new Request(e.url,{method:e.method,headers:e.headers,redirect:"follow",body:e.body});return Promise.race([de.originalFetch(i,{signal:t.abortController.signal,credentials:"omit",cache:"no-cache"}).then((e=>(s&&clearTimeout(s),e))),n])}))}sendXHRRequest(e,t){return r(this,void 0,void 0,(function*(){return new Promise(((s,n)=>{var i;const r=new XMLHttpRequest;r.open(e.method,e.url,!0);let a=!1;r.responseType="arraybuffer",r.timeout=1e3*e.timeout,t.abortController.signal.onabort=()=>{r.readyState!=XMLHttpRequest.DONE&&r.readyState!=XMLHttpRequest.UNSENT&&(a=!0,r.abort())},Object.entries(null!==(i=e.headers)&&void 0!==i?i:{}).forEach((([e,t])=>r.setRequestHeader(e,t))),r.onabort=()=>{n(new Error("Aborted"))},r.ontimeout=()=>{n(new Error("Request timeout"))},r.onerror=()=>{if(!a){const t=this.transportResponseFromXHR(e.url,r);n(new Error(G.create(t).message))}},r.onload=()=>{const e=new Headers;r.getAllResponseHeaders().split("\r\n").forEach((t=>{const[s,n]=t.split(": ");s.length>1&&n.length>1&&e.append(s,n)})),s(new Response(r.response,{status:r.status,headers:e,statusText:r.statusText}))},r.send(e.body)}))}))}webTransportRequestFromTransportRequest(e){return r(this,void 0,void 0,(function*(){let t,s=e.path;if(e.formData&&e.formData.length>0){e.queryParameters={};const s=e.body,n=new FormData;for(const{key:t,value:s}of e.formData)n.append(t,s);try{const e=yield s.toArrayBuffer();n.append("file",new Blob([e],{type:"application/octet-stream"}),s.name)}catch(e){this.logger.warn("WebTransport",(()=>({messageType:"error",message:e})));try{const e=yield s.toFileUri();n.append("file",e,s.name)}catch(e){this.logger.error("WebTransport",(()=>({messageType:"error",message:e})))}}t=n}else if(e.body&&("string"==typeof e.body||e.body instanceof ArrayBuffer))if(e.compressible&&"undefined"!=typeof CompressionStream){const s="string"==typeof e.body?de.encoder.encode(e.body):e.body,n=s.byteLength,i=new ReadableStream({start(e){e.enqueue(s),e.close()}});t=yield new Response(i.pipeThrough(new CompressionStream("deflate"))).arrayBuffer(),this.logger.trace("WebTransport",(()=>{const e=t.byteLength,s=(e/n).toFixed(2);return{messageType:"text",message:`Body of ${n} bytes, compressed by ${s}x to ${e} bytes.`}}))}else t=e.body;return e.queryParameters&&0!==Object.keys(e.queryParameters).length&&(s=`${s}?${T(e.queryParameters)}`),{url:`${e.origin}${s}`,method:e.method,headers:e.headers,timeout:e.timeout,body:t}}))}isFetchMonkeyPatched(e){return!(null!=e?e:fetch).toString().includes("[native code]")&&"fetch"!==fetch.name}transportResponseFromXHR(e,t){const s=t.getAllResponseHeaders().split("\n"),n={};for(const e of s){const[t,s]=e.trim().split(":");t&&s&&(n[t.toLowerCase()]=s.trim())}return{status:t.status,url:e,headers:n,body:t.response}}static getOriginalFetch(){if("undefined"==typeof document||!document.body)return fetch.bind(globalThis);let e=document.querySelector('iframe[name="pubnub-context-unpatched-fetch"]');return e||(e=document.createElement("iframe"),e.style.display="none",e.name="pubnub-context-unpatched-fetch",e.src="about:blank",document.body.appendChild(e)),e.contentWindow?e.contentWindow.fetch.bind(e.contentWindow):fetch.bind(globalThis)}}de.encoder=new TextEncoder,de.decoder=new TextDecoder;class pe{constructor(e){this.params=e,this.requestIdentifier=ie.createUUID(),this._cancellationController=null}get cancellationController(){return this._cancellationController}set cancellationController(e){this._cancellationController=e}abort(e){this&&this.cancellationController&&this.cancellationController.abort(e)}operation(){throw Error("Should be implemented by subclass.")}validate(){}parse(e){return r(this,void 0,void 0,(function*(){return this.deserializeResponse(e)}))}request(){var e,t,s,n,i,r;const a={method:null!==(t=null===(e=this.params)||void 0===e?void 0:e.method)&&void 0!==t?t:ue.GET,path:this.path,queryParameters:this.queryParameters,cancellable:null!==(n=null===(s=this.params)||void 0===s?void 0:s.cancellable)&&void 0!==n&&n,compressible:null!==(r=null===(i=this.params)||void 0===i?void 0:i.compressible)&&void 0!==r&&r,timeout:10,identifier:this.requestIdentifier},o=this.headers;if(o&&(a.headers=o),a.method===ue.POST||a.method===ue.PATCH||a.method===ue.PUT){const[e,t]=[this.body,this.formData];t&&(a.formData=t),e&&(a.body=e)}return a}get headers(){var e,t;return Object.assign({"Accept-Encoding":"gzip, deflate"},null!==(t=null===(e=this.params)||void 0===e?void 0:e.compressible)&&void 0!==t&&t?{"Content-Encoding":"deflate"}:{})}get path(){throw Error("`path` getter should be implemented by subclass.")}get queryParameters(){return{}}get formData(){}get body(){}deserializeResponse(e){const t=pe.decoder.decode(e.body),s=e.headers["content-type"];let n;if(!s||-1===s.indexOf("javascript")&&-1===s.indexOf("json"))throw new d("Service response error, check status for details",g(t,e.status));try{n=JSON.parse(t)}catch(s){throw console.error("Error parsing JSON response:",s),new d("Service response error, check status for details",g(t,e.status))}if("status"in n&&"number"==typeof n.status&&n.status>=400)throw G.create(e);return n}}pe.decoder=new TextDecoder;var ge;!function(e){e[e.Presence=-2]="Presence",e[e.Message=-1]="Message",e[e.Signal=1]="Signal",e[e.AppContext=2]="AppContext",e[e.MessageAction=3]="MessageAction",e[e.Files=4]="Files",e[e.DataSync=5]="DataSync"}(ge||(ge={}));const be=new Set([ge.Presence,ge.Message,ge.Signal,ge.AppContext,ge.MessageAction,ge.Files,ge.DataSync]),ye={user:"user",channel:"channel",membership:"membership"};class me extends pe{constructor(e){var t,s,n,i,r,a;super({cancellable:!0}),this.parameters=e,null!==(t=(i=this.parameters).withPresence)&&void 0!==t||(i.withPresence=false),null!==(s=(r=this.parameters).channelGroups)&&void 0!==s||(r.channelGroups=[]),null!==(n=(a=this.parameters).channels)&&void 0!==n||(a.channels=[])}operation(){return K.PNSubscribeOperation}validate(){const{keySet:{subscribeKey:e},channels:t,channelGroups:s}=this.parameters;return e?t||s?void 0:"`channels` and `channelGroups` both should not be empty":"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){let t,s;try{s=pe.decoder.decode(e.body);t=JSON.parse(s)}catch(e){console.error("Error parsing JSON response:",e)}if(!t)throw new d("Service response error, check status for details",g(s,e.status));const n=t.m.filter((e=>{const t=void 0===e.b?e.c:e.b;return this.parameters.channels&&this.parameters.channels.includes(t)||this.parameters.channelGroups&&this.parameters.channelGroups.includes(t)})).map((e=>{let{e:t}=e;if(e.c.endsWith("-pnpres")?t=ge.Presence:null!=t||(t=ge.Message),!be.has(t))return;const s=R(e.d);if(t!=ge.Presence&&t!=ge.Signal&&"string"==typeof e.d)return t==ge.Message?{type:ge.Message,data:this.messageFromEnvelope(e),pn_mfp:s}:{type:ge.Files,data:this.fileFromEnvelope(e),pn_mfp:s};if(t==ge.Message)return{type:ge.Message,data:this.messageFromEnvelope(e),pn_mfp:s};if(t===ge.Presence)return{type:ge.Presence,data:this.presenceEventFromEnvelope(e),pn_mfp:s};if(t==ge.Signal)return{type:ge.Signal,data:this.signalFromEnvelope(e),pn_mfp:s};if(t===ge.AppContext)return{type:ge.AppContext,data:this.appContextFromEnvelope(e),pn_mfp:s};if(t===ge.MessageAction)return{type:ge.MessageAction,data:this.messageActionFromEnvelope(e),pn_mfp:s};if(t===ge.DataSync){const t=this.dataSyncFromEnvelope(e);return t?{type:ge.DataSync,data:t,pn_mfp:s}:{type:ge.Message,data:this.messageFromEnvelope(e),pn_mfp:s}}return{type:ge.Files,data:this.fileFromEnvelope(e),pn_mfp:s}})).filter((e=>void 0!==e));return{cursor:{timetoken:t.t.t,region:t.t.r},messages:n}}))}get headers(){var e;return Object.assign(Object.assign({},null!==(e=super.headers)&&void 0!==e?e:{}),{accept:"text/javascript"})}presenceEventFromEnvelope(e){var t;const{d:s}=e,[n,i]=this.subscriptionChannelFromEnvelope(e),r=n.replace("-pnpres",""),a=null!==i?r:null,o=null!==i?i:r;let c;if("string"==typeof s)try{const e=JSON.parse(s);null===e||"object"!=typeof e||Array.isArray(e)||(c=e)}catch(e){}else c=s;return c&&("data"in c?(c.state=c.data,delete c.data):"action"in c&&"interval"===c.action&&(c.hereNowRefresh=null!==(t=c.here_now_refresh)&&void 0!==t&&t,delete c.here_now_refresh)),Object.assign({channel:r,subscription:i,actualChannel:a,subscribedChannel:o,timetoken:e.p.t},null!=c?c:{})}messageFromEnvelope(e){const[t,s]=this.subscriptionChannelFromEnvelope(e),[n,i]=this.decryptedData(e.d),r={channel:t,subscription:s,actualChannel:null!==s?t:null,subscribedChannel:null!==s?s:t,timetoken:e.p.t,publisher:e.i,message:n};return e.u&&(r.userMetadata=e.u),e.cmt&&(r.customMessageType=e.cmt),i&&(r.error=i),r}signalFromEnvelope(e){const[t,s]=this.subscriptionChannelFromEnvelope(e),n={channel:t,subscription:s,timetoken:e.p.t,publisher:e.i,message:e.d};return e.u&&(n.userMetadata=e.u),e.cmt&&(n.customMessageType=e.cmt),n}messageActionFromEnvelope(e){const[t,s]=this.subscriptionChannelFromEnvelope(e),n=e.d;return{channel:t,subscription:s,timetoken:e.p.t,publisher:e.i,event:n.event,data:Object.assign(Object.assign({},n.data),{uuid:e.i})}}appContextFromEnvelope(e){const[t,s]=this.subscriptionChannelFromEnvelope(e),n=e.d;return{channel:t,subscription:s,timetoken:e.p.t,message:n}}dataSyncFromEnvelope(e){var t;const[s,n]=this.subscriptionChannelFromEnvelope(e),i=e.d,r=null==i?void 0:i.metadata;if(!r||"data-sync"!==r.source||!r.event||!r.type)return;const a=r.className?r.className.split(":"):[],o=a.filter((e=>e.length>0)),c=o.length>0?o[o.length-1]:void 0,u=r.classLevel,l=void 0===u?a[0]:"Global"===u?c:void 0,h=("entity"===r.type||"relationship"===r.type)&&l&&ye[l.toLowerCase()]||r.type,d=void 0!==r.classVersion?Number.parseInt(`${r.classVersion}`,10):NaN,p=Number.isNaN(d)?void 0:d,g=null!==(t=i.data)&&void 0!==t?t:{},b={version:i.version,source:r.source,type:r.type,className:c,classLevel:u,classVersion:p};let y;if("delete"===r.event&&"membership"===h){const e={id:g.id,deletedAt:g.deletedAt};"string"==typeof g.channelId&&(e.channelId=g.channelId),"string"==typeof g.userId&&(e.userId=g.userId),y=Object.assign(Object.assign({},b),{event:r.event,objectType:h,data:e})}else if("delete"===r.event&&"relationship"===h){const e={id:g.id,deletedAt:g.deletedAt};"string"==typeof g.entityAId&&(e.entityAId=g.entityAId),"string"==typeof g.entityBId&&(e.entityBId=g.entityBId),y=Object.assign(Object.assign({},b),{event:r.event,objectType:h,data:e})}else y="delete"===r.event?Object.assign(Object.assign({},b),{event:r.event,objectType:h,data:{id:g.id,deletedAt:g.deletedAt}}):Object.assign(Object.assign({},b),{event:r.event,objectType:h,data:Object.assign({},g)});return{channel:s,subscription:n,timetoken:e.p.t,message:y}}fileFromEnvelope(e){const[t,s]=this.subscriptionChannelFromEnvelope(e),[n,i]=this.decryptedData(e.d);let r=i;const a={channel:t,subscription:s,timetoken:e.p.t,publisher:e.i};return e.u&&(a.userMetadata=e.u),n?"string"==typeof n?null!=r||(r="Unexpected file information payload data type."):(a.message=n.message,n.file&&(a.file={id:n.file.id,name:n.file.name,url:this.parameters.getFileUrl({id:n.file.id,name:n.file.name,channel:t})})):null!=r||(r="File information payload is missing."),e.cmt&&(a.customMessageType=e.cmt),r&&(a.error=r),a}subscriptionChannelFromEnvelope(e){return[e.c,void 0===e.b?e.c:e.b]}decryptedData(e){if(!this.parameters.crypto||"string"!=typeof e)return[e,void 0];let t,s;try{const s=this.parameters.crypto.decrypt(e);t=s instanceof ArrayBuffer?JSON.parse(fe.decoder.decode(s)):s}catch(e){t=null,s=`Error while decrypting message content: ${e.message}`}return[null!=t?t:e,s]}}class fe extends me{get path(){var e;const{keySet:{subscribeKey:t},channels:s}=this.parameters;return`/v2/subscribe/${t}/${P(null!==(e=null==s?void 0:s.sort())&&void 0!==e?e:[],",")}/0`}get queryParameters(){const{channelGroups:e,filterExpression:t,heartbeat:s,state:n,timetoken:i,region:r,onDemand:a}=this.parameters,o={};return a&&(o["on-demand"]=1),e&&e.length>0&&(o["channel-group"]=e.sort().join(",")),t&&t.length>0&&(o["filter-expr"]=t),s&&(o.heartbeat=s),n&&Object.keys(n).length>0&&(o.state=JSON.stringify(n)),void 0!==i&&"string"==typeof i?i.length>0&&"0"!==i&&(o.tt=i):void 0!==i&&i>0&&(o.tt=i),r&&(o.tr=r),o}}class ve{constructor(){this.hasListeners=!1,this.listeners=[{count:-1,listener:{}}]}set onStatus(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"status"})}set onMessage(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"message"})}set onPresence(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"presence"})}set onSignal(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"signal"})}set onObjects(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"objects"})}set onMessageAction(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"messageAction"})}set onFile(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"file"})}set onDataSync(e){this.updateTypeOrObjectListener({add:!!e,listener:e,type:"dataSync"})}handleEvent(e){if(this.hasListeners)if(e.type===ge.Message)this.announce("message",e.data);else if(e.type===ge.Signal)this.announce("signal",e.data);else if(e.type===ge.Presence)this.announce("presence",e.data);else if(e.type===ge.AppContext){const{data:t}=e,{message:s}=t;if(this.announce("objects",t),"uuid"===s.type){const{message:e,channel:n}=t,r=i(t,["message","channel"]),{event:a,type:o}=s,c=i(s,["event","type"]),u=Object.assign(Object.assign({},r),{spaceId:n,message:Object.assign(Object.assign({},c),{event:"set"===a?"updated":"removed",type:"user"})});this.announce("user",u)}else if("channel"===s.type){const{message:e,channel:n}=t,r=i(t,["message","channel"]),{event:a,type:o}=s,c=i(s,["event","type"]),u=Object.assign(Object.assign({},r),{spaceId:n,message:Object.assign(Object.assign({},c),{event:"set"===a?"updated":"removed",type:"space"})});this.announce("space",u)}else if("membership"===s.type){const{message:e,channel:n}=t,r=i(t,["message","channel"]),{event:a,data:o}=s,c=i(s,["event","data"]),{uuid:u,channel:l}=o,h=i(o,["uuid","channel"]),d=Object.assign(Object.assign({},r),{spaceId:n,message:Object.assign(Object.assign({},c),{event:"set"===a?"updated":"removed",data:Object.assign(Object.assign({},h),{user:u,space:l})})});this.announce("membership",d)}}else e.type===ge.MessageAction?this.announce("messageAction",e.data):e.type===ge.Files?this.announce("file",e.data):e.type===ge.DataSync&&this.announce("dataSync",e.data)}handleStatus(e){this.hasListeners&&this.announce("status",e)}addListener(e){this.updateTypeOrObjectListener({add:!0,listener:e})}removeListener(e){this.updateTypeOrObjectListener({add:!1,listener:e})}removeAllListeners(){this.listeners=[{count:-1,listener:{}}],this.hasListeners=!1}updateTypeOrObjectListener(e){if(e.type)"function"==typeof e.listener?this.listeners[0].listener[e.type]=e.listener:delete this.listeners[0].listener[e.type];else if(e.listener&&"function"!=typeof e.listener){let t,s=!1;for(t of this.listeners)if(t.listener===e.listener){e.add?(t.count++,s=!0):(t.count--,0===t.count&&this.listeners.splice(this.listeners.indexOf(t),1));break}e.add&&!s&&this.listeners.push({count:1,listener:e.listener})}this.hasListeners=this.listeners.length>1||Object.keys(this.listeners[0]).length>0}announce(e,t){this.listeners.forEach((({listener:s})=>{const n=s[e];n&&n(t)}))}}class Oe{constructor(e){this.time=e}onReconnect(e){this.callback=e}startPolling(){this.timeTimer=setInterval((()=>this.callTime()),3e3)}stopPolling(){this.timeTimer&&clearInterval(this.timeTimer),this.timeTimer=null}callTime(){this.time((e=>{e.error||(this.stopPolling(),this.callback&&this.callback())}))}}class Se{constructor(e){this.config=e,e.logger().debug("DedupingManager",(()=>({messageType:"object",message:{maximumCacheSize:e.maximumCacheSize},details:"Create with configuration:"}))),this.maximumCacheSize=e.maximumCacheSize,this.hashHistory=[]}getKey(e){var t;return`${e.timetoken}-${this.hashCode(JSON.stringify(null!==(t=e.message)&&void 0!==t?t:"")).toString()}`}isDuplicate(e){return this.hashHistory.includes(this.getKey(e))}addEntry(e){this.hashHistory.length>=this.maximumCacheSize&&this.hashHistory.shift(),this.hashHistory.push(this.getKey(e))}clearHistory(){this.hashHistory=[]}hashCode(e){let t=0;if(0===e.length)return t;for(let s=0;s{this.pendingChannelSubscriptions.add(e),this.channels[e]={},i&&(this.presenceChannels[e]={}),(r||this.configuration.getHeartbeatInterval())&&(this.heartbeatChannels[e]={})})),null==s||s.forEach((e=>{this.pendingChannelGroupSubscriptions.add(e),this.channelGroups[e]={},i&&(this.presenceChannelGroups[e]={}),(r||this.configuration.getHeartbeatInterval())&&(this.heartbeatChannelGroups[e]={})})),this.subscriptionStatusAnnounced=!1,this.reconnect()}unsubscribe(e,t=!1){let{channels:s,channelGroups:n}=e;const r=new Set,a=new Set;if(null==s||s.forEach((e=>{e in this.channels&&(delete this.channels[e],a.add(e),e in this.heartbeatChannels&&delete this.heartbeatChannels[e]),e in this.presenceState&&delete this.presenceState[e],e in this.presenceChannels&&(delete this.presenceChannels[e],a.add(e))})),null==n||n.forEach((e=>{e in this.channelGroups&&(delete this.channelGroups[e],r.add(e),e in this.heartbeatChannelGroups&&delete this.heartbeatChannelGroups[e]),e in this.presenceState&&delete this.presenceState[e],e in this.presenceChannelGroups&&(delete this.presenceChannelGroups[e],r.add(e))})),0===a.size&&0===r.size)return;const o=this.lastTimetoken,c=this.currentTimetoken;0===Object.keys(this.channels).length&&0===Object.keys(this.presenceChannels).length&&0===Object.keys(this.channelGroups).length&&0===Object.keys(this.presenceChannelGroups).length&&(this.lastTimetoken="0",this.currentTimetoken="0",this.referenceTimetoken=null,this.storedTimetoken=null,this.region=null,this.reconnectionManager.stopPolling()),this.reconnect(!0),!1!==this.configuration.suppressLeaveEvents||t||(n=Array.from(r),s=Array.from(a),this.leaveCall({channels:s,channelGroups:n},(e=>{const{error:t}=e,r=i(e,["error"]);let a;t&&(e.errorData&&"object"==typeof e.errorData&&"message"in e.errorData&&"string"==typeof e.errorData.message?a=e.errorData.message:"message"in e&&"string"==typeof e.message&&(a=e.message)),this.emitStatus(Object.assign(Object.assign({},r),{error:null!=a&&a,affectedChannels:s,affectedChannelGroups:n,currentTimetoken:c,lastTimetoken:o}))})))}unsubscribeAll(e=!1){this.disconnectedWhileHandledEvent=!0,this.unsubscribe({channels:this.subscribedChannels,channelGroups:this.subscribedChannelGroups},e)}startSubscribeLoop(e=!1){this.disconnectedWhileHandledEvent=!1,this.stopSubscribeLoop();const t=[...Object.keys(this.channelGroups)],s=[...Object.keys(this.channels)];Object.keys(this.presenceChannelGroups).forEach((e=>t.push(`${e}-pnpres`))),Object.keys(this.presenceChannels).forEach((e=>s.push(`${e}-pnpres`))),0===s.length&&0===t.length||(this.subscribeCall(Object.assign(Object.assign(Object.assign({channels:s,channelGroups:t,state:this.presenceState,heartbeat:this.configuration.getPresenceTimeout(),timetoken:this.currentTimetoken},null!==this.region?{region:this.region}:{}),this.configuration.filterExpression?{filterExpression:this.configuration.filterExpression}:{}),{onDemand:!this.subscriptionStatusAnnounced||e}),((e,t)=>{this.processSubscribeResponse(e,t)})),!e&&this.configuration.useSmartHeartbeat&&this.startHeartbeatTimer())}stopSubscribeLoop(){this._subscribeAbort&&(this._subscribeAbort(),this._subscribeAbort=null)}processSubscribeResponse(e,t){if(e.error){if("object"==typeof e.errorData&&"name"in e.errorData&&"AbortError"===e.errorData.name||e.category===h.PNCancelledCategory)return;return void(e.category===h.PNTimeoutCategory?this.startSubscribeLoop():e.category===h.PNNetworkIssuesCategory||e.category===h.PNMalformedResponseCategory?(this.disconnect(),e.error&&this.configuration.autoNetworkDetection&&this.isOnline&&(this.isOnline=!1,this.emitStatus({category:h.PNNetworkDownCategory})),this.reconnectionManager.onReconnect((()=>{this.configuration.autoNetworkDetection&&!this.isOnline&&(this.isOnline=!0,this.emitStatus({category:h.PNNetworkUpCategory})),this.reconnect(),this.subscriptionStatusAnnounced=!0;const t={category:h.PNReconnectedCategory,operation:e.operation,lastTimetoken:this.lastTimetoken,currentTimetoken:this.currentTimetoken};this.emitStatus(t)})),this.reconnectionManager.startPolling(),this.emitStatus(Object.assign(Object.assign({},e),{category:h.PNNetworkIssuesCategory}))):e.category===h.PNBadRequestCategory?(this.stopHeartbeatTimer(),this.emitStatus(e)):this.emitStatus(e))}if(this.referenceTimetoken=I(t.cursor.timetoken,this.storedTimetoken),this.storedTimetoken?(this.currentTimetoken=this.storedTimetoken,this.storedTimetoken=null):(this.lastTimetoken=this.currentTimetoken,this.currentTimetoken=t.cursor.timetoken),!this.subscriptionStatusAnnounced){const t={category:h.PNConnectedCategory,operation:e.operation,affectedChannels:Array.from(this.pendingChannelSubscriptions),subscribedChannels:this.subscribedChannels,affectedChannelGroups:Array.from(this.pendingChannelGroupSubscriptions),lastTimetoken:this.lastTimetoken,currentTimetoken:this.currentTimetoken};this.subscriptionStatusAnnounced=!0,this.emitStatus(t),this.pendingChannelGroupSubscriptions.clear(),this.pendingChannelSubscriptions.clear()}const{messages:s}=t,{requestMessageCountThreshold:n,dedupeOnSubscribe:i}=this.configuration;n&&s.length>=n&&this.emitStatus({category:h.PNRequestMessageCountExceededCategory,operation:e.operation});try{const e={timetoken:this.currentTimetoken,region:this.region?this.region:void 0};this.configuration.logger().debug("SubscriptionManager",(()=>({messageType:"object",message:s.map((e=>({type:e.type,data:Object.assign(Object.assign({},e.data),{pn_mfp:e.pn_mfp})}))),details:"Received events:"}))),s.forEach((t=>{if(i&&"message"in t.data&&"timetoken"in t.data){if(this.dedupingManager.isDuplicate(t.data))return void this.configuration.logger().warn("SubscriptionManager",(()=>({messageType:"object",message:t.data,details:"Duplicate message detected (skipped):"})));this.dedupingManager.addEntry(t.data)}this.emitEvent(e,t)}))}catch(e){const t={error:!0,category:h.PNUnknownCategory,errorData:e,statusCode:0};this.emitStatus(t)}this.region=t.cursor.region,this.disconnectedWhileHandledEvent?this.disconnectedWhileHandledEvent=!1:this.startSubscribeLoop()}setState(e){const{state:t,channels:s,channelGroups:n}=e;null==s||s.forEach((e=>e in this.channels&&(this.presenceState[e]=t))),null==n||n.forEach((e=>e in this.channelGroups&&(this.presenceState[e]=t)))}changePresence(e){const{connected:t,channels:s,channelGroups:n}=e;t?(null==s||s.forEach((e=>this.heartbeatChannels[e]={})),null==n||n.forEach((e=>this.heartbeatChannelGroups[e]={}))):(null==s||s.forEach((e=>{e in this.heartbeatChannels&&delete this.heartbeatChannels[e]})),null==n||n.forEach((e=>{e in this.heartbeatChannelGroups&&delete this.heartbeatChannelGroups[e]})),!1===this.configuration.suppressLeaveEvents&&this.leaveCall({channels:s,channelGroups:n},(e=>this.emitStatus(e)))),this.reconnect()}startHeartbeatTimer(){this.stopHeartbeatTimer();const e=this.configuration.getHeartbeatInterval();e&&0!==e&&(this.configuration.useSmartHeartbeat||this.sendHeartbeat(),this.heartbeatTimer=setInterval((()=>this.sendHeartbeat()),1e3*e))}stopHeartbeatTimer(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null)}sendHeartbeat(){const e=Object.keys(this.heartbeatChannelGroups),t=Object.keys(this.heartbeatChannels);0===t.length&&0===e.length||this.heartbeatCall({channels:t,channelGroups:e,heartbeat:this.configuration.getPresenceTimeout(),state:this.presenceState},(e=>{e.error&&this.configuration.announceFailedHeartbeats&&this.emitStatus(e),e.error&&this.configuration.autoNetworkDetection&&this.isOnline&&(this.isOnline=!1,this.disconnect(),this.emitStatus({category:h.PNNetworkDownCategory}),this.reconnect()),!e.error&&this.configuration.announceSuccessfulHeartbeats&&this.emitStatus(e)}))}}class we{constructor(e,t,s){this._payload=e,this.setDefaultPayloadStructure(),this.title=t,this.body=s}get payload(){return this._payload}set title(e){this._title=e}set subtitle(e){this._subtitle=e}set body(e){this._body=e}set badge(e){this._badge=e}set sound(e){this._sound=e}setDefaultPayloadStructure(){}toObject(){return{}}}class ke extends we{constructor(){super(...arguments),this._apnsPushType="apns",this._isSilent=!1}get payload(){return this._payload}set configurations(e){e&&e.length&&(this._configurations=e)}get notification(){return this.payload.aps}get title(){return this._title}set title(e){e&&e.length&&(this.payload.aps.alert.title=e,this._title=e)}get subtitle(){return this._subtitle}set subtitle(e){e&&e.length&&(this.payload.aps.alert.subtitle=e,this._subtitle=e)}get body(){return this._body}set body(e){e&&e.length&&(this.payload.aps.alert.body=e,this._body=e)}get badge(){return this._badge}set badge(e){null!=e&&(this.payload.aps.badge=e,this._badge=e)}get sound(){return this._sound}set sound(e){e&&e.length&&(this.payload.aps.sound=e,this._sound=e)}set silent(e){this._isSilent=e}setDefaultPayloadStructure(){this.payload.aps={alert:{}}}toObject(){const e=Object.assign({},this.payload),{aps:t}=e;let{alert:s}=t;if(this._isSilent&&(t["content-available"]=1),"apns2"===this._apnsPushType){if(!this._configurations||!this._configurations.length)throw new ReferenceError("APNS2 configuration is missing");const t=[];this._configurations.forEach((e=>{t.push(this.objectFromAPNS2Configuration(e))})),t.length&&(e.pn_push=t)}return s&&Object.keys(s).length||delete t.alert,this._isSilent&&(delete t.alert,delete t.badge,delete t.sound,s={}),this._isSilent||s&&Object.keys(s).length?e:null}objectFromAPNS2Configuration(e){if(!e.targets||!e.targets.length)throw new ReferenceError("At least one APNS2 target should be provided");const{collapseId:t,expirationDate:s}=e,n={auth_method:"token",targets:e.targets.map((e=>this.objectFromAPNSTarget(e))),version:"v2"};return t&&t.length&&(n.collapse_id=t),s&&(n.expiration=s.toISOString()),n}objectFromAPNSTarget(e){if(!e.topic||!e.topic.length)throw new TypeError("Target 'topic' undefined.");const{topic:t,environment:s="development",excludedDevices:n=[]}=e,i={topic:t,environment:s};return n.length&&(i.excluded_devices=n),i}}class Ce extends we{get payload(){return this._payload}get notification(){return this.payload.notification}get data(){return this.payload.data}get androidNotification(){var e;return null===(e=this.payload.android)||void 0===e?void 0:e.notification}get title(){return this._title}set title(e){e&&e.length&&(this.payload.notification.title=e,this.androidNotification.title=e,this._title=e)}get body(){return this._body}set body(e){e&&e.length&&(this.payload.notification.body=e,this.androidNotification.body=e,this._body=e)}get badge(){return this._badge}set badge(e){null!=e&&(this.androidNotification.notification_count=e,this._badge=e)}get sound(){return this._sound}set sound(e){e&&e.length&&(this.androidNotification.sound=e,this._sound=e)}get icon(){return this._icon}set icon(e){e&&e.length&&(this.androidNotification.icon=e,this._icon=e)}get tag(){return this._tag}set tag(e){e&&e.length&&(this.androidNotification.tag=e,this._tag=e)}set silent(e){this._isSilent=e}setDefaultPayloadStructure(){this.payload.notification={},this.payload.data={},this.payload.android={notification:{}}}toObject(){var e,t;const s={},n=Object.assign({},this.payload.notification),r=Object.assign({},this.payload.android),a=i(Object.assign({},null!==(e=r.notification)&&void 0!==e?e:{}),["title","body"]);if(this._isSilent){const e={};this._title&&(e.title=this._title),this._body&&(e.body=this._body);for(const[t,s]of Object.entries(a))null!=s&&(e[t]=String(s));this.payload.data&&Object.assign(e,this.payload.data),Object.keys(e).length&&(s.data=e),delete r.notification,Object.keys(r).length&&(s.android=r)}else if(Object.keys(n).length&&(s.notification=n),this.payload.data&&Object.keys(this.payload.data).length&&(s.data=Object.assign({},this.payload.data)),Object.keys(a).length){const e=i(r,["notification"]);s.android=Object.assign(Object.assign({},e),{notification:a})}else{const e=i(r,["notification"]);Object.keys(e).length&&(s.android=e)}const o=i(this.payload,["notification","android","data","pn_exceptions"]);return Object.assign(s,o),(null===(t=this.payload.pn_exceptions)||void 0===t?void 0:t.length)&&(s.pn_exceptions=this.payload.pn_exceptions),Object.keys(s).length?s:null}}class Pe{constructor(e,t){this._payload={apns:{},fcm:{}},this._title=e,this._body=t,this.apns=new ke(this._payload.apns,e,t),this.fcm=new Ce(this._payload.fcm,e,t)}set debugging(e){this._debugging=e}get title(){return this._title}get subtitle(){return this._subtitle}set subtitle(e){this._subtitle=e,this.apns.subtitle=e,this.fcm.subtitle=e}get body(){return this._body}get badge(){return this._badge}set badge(e){this._badge=e,this.apns.badge=e,this.fcm.badge=e}get sound(){return this._sound}set sound(e){this._sound=e,this.apns.sound=e,this.fcm.sound=e}buildPayload(e){const t={};if(e.includes("apns")||e.includes("apns2")){this.apns._apnsPushType=e.includes("apns")?"apns":"apns2";const s=this.apns.toObject();s&&Object.keys(s).length&&(t.pn_apns=s)}if(e.includes("fcm")){const e=this.fcm.toObject();e&&Object.keys(e).length&&(t.pn_fcm=e)}return Object.keys(t).length&&this._debugging&&(t.pn_debug=!0),t}}class Ne{constructor(e=!1){this.sync=e,this.listeners=new Set}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}notify(e){const t=()=>{this.listeners.forEach((t=>{t(e)}))};this.sync?t():setTimeout(t,0)}}class Ee{transition(e,t){var s;if(this.transitionMap.has(t.type))return null===(s=this.transitionMap.get(t.type))||void 0===s?void 0:s(e,t)}constructor(e){this.label=e,this.transitionMap=new Map,this.enterEffects=[],this.exitEffects=[]}on(e,t){return this.transitionMap.set(e,t),this}with(e,t){return[this,e,null!=t?t:[]]}onEnter(e){return this.enterEffects.push(e),this}onExit(e){return this.exitEffects.push(e),this}}class Te extends Ne{constructor(e){super(!0),this.logger=e,this._pendingEvents=[],this._inTransition=!1}get currentState(){return this._currentState}get currentContext(){return this._currentContext}describe(e){return new Ee(e)}start(e,t){this._currentState=e,this._currentContext=t,this.notify({type:"engineStarted",state:e,context:t})}transition(e){if(!this._currentState)throw this.logger.error("Engine","Finite state machine is not started"),new Error("Start the engine first");if(this._inTransition)return this.logger.trace("Engine",(()=>({messageType:"object",message:e,details:"Event engine in transition. Enqueue received event:"}))),void this._pendingEvents.push(e);this._inTransition=!0,this.logger.trace("Engine",(()=>({messageType:"object",message:e,details:"Event engine received event:"}))),this.notify({type:"eventReceived",event:e});const t=this._currentState.transition(this._currentContext,e);if(t){const[s,n,i]=t;this.logger.trace("Engine",`Exiting state: ${this._currentState.label}`);for(const e of this._currentState.exitEffects)this.notify({type:"invocationDispatched",invocation:e(this._currentContext)});this.logger.trace("Engine",(()=>({messageType:"object",details:`Entering '${s.label}' state with context:`,message:n})));const r=this._currentState;this._currentState=s;const a=this._currentContext;this._currentContext=n,this.notify({type:"transitionDone",fromState:r,fromContext:a,toState:s,toContext:n,event:e});for(const e of i)this.notify({type:"invocationDispatched",invocation:e});for(const e of this._currentState.enterEffects)this.notify({type:"invocationDispatched",invocation:e(this._currentContext)})}else this.logger.warn("Engine",`No transition from '${this._currentState.label}' found for event: ${e.type}`);if(this._inTransition=!1,this._pendingEvents.length>0){const e=this._pendingEvents.shift();e&&(this.logger.trace("Engine",(()=>({messageType:"object",message:e,details:"De-queueing pending event:"}))),this.transition(e))}}}class _e{constructor(e,t){this.dependencies=e,this.logger=t,this.instances=new Map,this.handlers=new Map}on(e,t){this.handlers.set(e,t)}dispatch(e){if(this.logger.trace("Dispatcher",`Process invocation: ${e.type}`),"CANCEL"===e.type){if(this.instances.has(e.payload)){const t=this.instances.get(e.payload);null==t||t.cancel(),this.instances.delete(e.payload)}return}const t=this.handlers.get(e.type);if(!t)throw this.logger.error("Dispatcher",`Unhandled invocation '${e.type}'`),new Error(`Unhandled invocation '${e.type}'`);const s=t(e.payload,this.dependencies);this.logger.trace("Dispatcher",(()=>({messageType:"object",details:"Call invocation handler with parameters:",message:e.payload,ignoredKeys:["abortSignal"]}))),e.managed&&this.instances.set(e.type,s),s.start()}dispose(){for(const[e,t]of this.instances.entries())t.cancel(),this.instances.delete(e)}}function Ie(e,t){const s=function(...s){return{type:e,payload:null==t?void 0:t(...s)}};return s.type=e,s}function Me(e,t){const s=(...s)=>({type:e,payload:t(...s),managed:!1});return s.type=e,s}function Re(e,t){const s=(...s)=>({type:e,payload:t(...s),managed:!0});return s.type=e,s.cancel={type:"CANCEL",payload:e,managed:!1},s}class De extends Error{constructor(){super("The operation was aborted."),this.name="AbortError",Object.setPrototypeOf(this,new.target.prototype)}}class Ue extends Ne{constructor(){super(...arguments),this._aborted=!1}get aborted(){return this._aborted}throwIfAborted(){if(this._aborted)throw new De}abort(){this._aborted=!0,this.notify(new De)}}class Ae{constructor(e,t){this.payload=e,this.dependencies=t}}class $e extends Ae{constructor(e,t,s){super(e,t),this.asyncFunction=s,this.abortSignal=new Ue}start(){this.asyncFunction(this.payload,this.abortSignal,this.dependencies).catch((e=>{}))}cancel(){this.abortSignal.abort()}}const Fe=e=>(t,s)=>new $e(t,s,e),xe=Re("HEARTBEAT",((e,t)=>({channels:e,groups:t}))),qe=Me("LEAVE",((e,t)=>({channels:e,groups:t}))),Ge=Me("EMIT_STATUS",(e=>e)),Le=Re("WAIT",(()=>({}))),Ke=Ie("RECONNECT",(()=>({}))),He=Ie("DISCONNECT",((e=!1)=>({isOffline:e}))),Be=Ie("JOINED",((e,t)=>({channels:e,groups:t}))),We=Ie("LEFT",((e,t)=>({channels:e,groups:t}))),Ve=Ie("LEFT_ALL",((e=!1)=>({isOffline:e}))),ze=Ie("HEARTBEAT_SUCCESS",(e=>({statusCode:e}))),Je=Ie("HEARTBEAT_FAILURE",(e=>e)),Xe=Ie("TIMES_UP",(()=>({})));class Qe extends _e{constructor(e,t){super(t,t.config.logger()),this.on(xe.type,Fe(((t,s,n)=>r(this,[t,s,n],void 0,(function*(t,s,{heartbeat:n,presenceState:i,config:r}){s.throwIfAborted();try{yield n(Object.assign(Object.assign({abortSignal:s,channels:t.channels,channelGroups:t.groups},r.maintainPresenceState&&{state:i}),{heartbeat:r.presenceTimeout}));e.transition(ze(200))}catch(t){if(t instanceof d){if(t.status&&t.status.category==h.PNCancelledCategory)return;e.transition(Je(t))}}}))))),this.on(qe.type,Fe(((e,t,s)=>r(this,[e,t,s],void 0,(function*(e,t,{leave:s,config:n}){if(!n.suppressLeaveEvents)try{s({channels:e.channels,channelGroups:e.groups})}catch(e){}}))))),this.on(Le.type,Fe(((t,s,n)=>r(this,[t,s,n],void 0,(function*(t,s,{heartbeatDelay:n}){const{cancelDelay:i,promise:r}=n();s.throwIfAborted();const a=s.subscribe((()=>i()));return yield r,a(),s.throwIfAborted(),e.transition(Xe())}))))),this.on(Ge.type,Fe(((e,t,s)=>r(this,[e,t,s],void 0,(function*(e,t,{emitStatus:s,config:n}){n.announceFailedHeartbeats&&!0===(null==e?void 0:e.error)?s(Object.assign(Object.assign({},e),{operation:K.PNHeartbeatOperation})):n.announceSuccessfulHeartbeats&&200===e.statusCode&&s(Object.assign(Object.assign({},e),{error:!1,operation:K.PNHeartbeatOperation,category:h.PNAcknowledgmentCategory}))})))))}}const Ye=new Ee("HEARTBEAT_INACTIVE"),Ze=new Ee("HEARTBEATING"),et=new Ee("HEARTBEAT_COOLDOWN"),tt=new Ee("HEARTBEAT_STOPPED"),st=new Ee("HEARTBEAT_FAILED");Ye.on(Be.type,((e,t)=>Ze.with({channels:t.payload.channels,groups:t.payload.groups}))),Ze.onEnter((e=>xe(e.channels,e.groups))),Ze.onExit((()=>xe.cancel)),Ze.on(ze.type,((e,t)=>et.with({channels:e.channels,groups:e.groups},[Ge(Object.assign({},t.payload))]))),Ze.on(Be.type,((e,t)=>Ze.with({channels:[...e.channels,...t.payload.channels.filter((t=>!e.channels.includes(t)))],groups:[...e.groups,...t.payload.groups.filter((t=>!e.groups.includes(t)))]}))),Ze.on(We.type,((e,t)=>Ze.with({channels:e.channels.filter((e=>!t.payload.channels.includes(e))),groups:e.groups.filter((e=>!t.payload.groups.includes(e)))},[qe(t.payload.channels,t.payload.groups)]))),Ze.on(Je.type,((e,t)=>st.with(Object.assign({},e),[...t.payload.status?[Ge(Object.assign({},t.payload.status))]:[]]))),Ze.on(He.type,((e,t)=>tt.with({channels:e.channels,groups:e.groups},[...t.payload.isOffline?[]:[qe(e.channels,e.groups)]]))),Ze.on(Ve.type,((e,t)=>Ye.with(void 0,[...t.payload.isOffline?[]:[qe(e.channels,e.groups)]]))),et.onEnter((()=>Le())),et.onExit((()=>Le.cancel)),et.on(Xe.type,((e,t)=>Ze.with({channels:e.channels,groups:e.groups}))),et.on(Be.type,((e,t)=>Ze.with({channels:[...e.channels,...t.payload.channels.filter((t=>!e.channels.includes(t)))],groups:[...e.groups,...t.payload.groups.filter((t=>!e.groups.includes(t)))]}))),et.on(We.type,((e,t)=>Ze.with({channels:e.channels.filter((e=>!t.payload.channels.includes(e))),groups:e.groups.filter((e=>!t.payload.groups.includes(e)))},[qe(t.payload.channels,t.payload.groups)]))),et.on(He.type,((e,t)=>tt.with({channels:e.channels,groups:e.groups},[...t.payload.isOffline?[]:[qe(e.channels,e.groups)]]))),et.on(Ve.type,((e,t)=>Ye.with(void 0,[...t.payload.isOffline?[]:[qe(e.channels,e.groups)]]))),tt.on(Be.type,((e,t)=>tt.with({channels:[...e.channels,...t.payload.channels.filter((t=>!e.channels.includes(t)))],groups:[...e.groups,...t.payload.groups.filter((t=>!e.groups.includes(t)))]}))),tt.on(We.type,((e,t)=>tt.with({channels:e.channels.filter((e=>!t.payload.channels.includes(e))),groups:e.groups.filter((e=>!t.payload.groups.includes(e)))}))),tt.on(Ke.type,((e,t)=>Ze.with({channels:e.channels,groups:e.groups}))),tt.on(Ve.type,((e,t)=>Ye.with(void 0))),st.on(Be.type,((e,t)=>Ze.with({channels:[...e.channels,...t.payload.channels.filter((t=>!e.channels.includes(t)))],groups:[...e.groups,...t.payload.groups.filter((t=>!e.groups.includes(t)))]}))),st.on(We.type,((e,t)=>Ze.with({channels:e.channels.filter((e=>!t.payload.channels.includes(e))),groups:e.groups.filter((e=>!t.payload.groups.includes(e)))},[qe(t.payload.channels,t.payload.groups)]))),st.on(Ke.type,((e,t)=>Ze.with({channels:e.channels,groups:e.groups}))),st.on(He.type,((e,t)=>tt.with({channels:e.channels,groups:e.groups},[...t.payload.isOffline?[]:[qe(e.channels,e.groups)]]))),st.on(Ve.type,((e,t)=>Ye.with(void 0,[...t.payload.isOffline?[]:[qe(e.channels,e.groups)]])));class nt{get _engine(){return this.engine}constructor(e){this.dependencies=e,this.channels=[],this.groups=[],this.engine=new Te(e.config.logger()),this.dispatcher=new Qe(this.engine,e),e.config.logger().debug("PresenceEventEngine","Create presence event engine."),this._unsubscribeEngine=this.engine.subscribe((e=>{"invocationDispatched"===e.type&&this.dispatcher.dispatch(e.invocation)})),this.engine.start(Ye,void 0)}join({channels:e,groups:t}){this.channels=[...this.channels,...(null!=e?e:[]).filter((e=>!this.channels.includes(e)))],this.groups=[...this.groups,...(null!=t?t:[]).filter((e=>!this.groups.includes(e)))],0===this.channels.length&&0===this.groups.length||this.engine.transition(Be(this.channels.slice(0),this.groups.slice(0)))}leave({channels:e,groups:t}){e&&(this.channels=this.channels.filter((t=>!e.includes(t)))),t&&(this.groups=this.groups.filter((e=>!t.includes(e)))),this.dependencies.presenceState&&(null==e||e.forEach((e=>delete this.dependencies.presenceState[e])),null==t||t.forEach((e=>delete this.dependencies.presenceState[e]))),this.engine.transition(We(null!=e?e:[],null!=t?t:[]))}leaveAll(e=!1){this.dependencies.presenceState&&(this.channels.forEach((e=>delete this.dependencies.presenceState[e])),this.groups.forEach((e=>delete this.dependencies.presenceState[e]))),this.channels=[],this.groups=[],this.engine.transition(Ve(e))}reconnect(){this.engine.transition(Ke())}disconnect(e=!1){this.engine.transition(He(e))}dispose(){this.disconnect(!0),this._unsubscribeEngine(),this.dispatcher.dispose()}}const it=Ie("SUBSCRIPTION_CHANGED",((e,t,s=!1)=>({channels:e,groups:t,isOffline:s}))),rt=Ie("SUBSCRIPTION_RESTORED",((e,t,s,n)=>({channels:e,groups:t,cursor:{timetoken:s,region:null!=n?n:0}}))),at=Ie("HANDSHAKE_SUCCESS",(e=>e)),ot=Ie("HANDSHAKE_FAILURE",(e=>e)),ct=Ie("RECEIVE_SUCCESS",((e,t)=>({cursor:e,events:t}))),ut=Ie("RECEIVE_FAILURE",(e=>e)),lt=Ie("DISCONNECT",((e=!1)=>({isOffline:e}))),ht=Ie("RECONNECT",((e,t)=>({cursor:{timetoken:null!=e?e:"",region:null!=t?t:0}}))),dt=Ie("UNSUBSCRIBE_ALL",(()=>({}))),pt=new Ee("UNSUBSCRIBED"),gt=new Ee("HANDSHAKING"),bt=new Ee("HANDSHAKE_STOPPED"),yt=new Ee("HANDSHAKE_FAILED"),mt=new Ee("RECEIVING"),ft=new Ee("RECEIVE_STOPPED"),vt=new Ee("RECEIVE_FAILED");pt.on(it.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,onDemand:!0}))),pt.on(rt.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region},onDemand:!0})));const Ot=Re("HANDSHAKE",((e,t,s)=>({channels:e,groups:t,onDemand:s}))),St=Re("RECEIVE_MESSAGES",((e,t,s,n)=>({channels:e,groups:t,cursor:s,onDemand:n}))),jt=Me("EMIT_MESSAGES",((e,t)=>({cursor:e,events:t}))),wt=Me("EMIT_STATUS",(e=>e));gt.onEnter((e=>{var t;return Ot(e.channels,e.groups,null!==(t=e.onDemand)&&void 0!==t&&t)})),gt.onExit((()=>Ot.cancel)),gt.on(it.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:e.cursor,onDemand:!0}))),gt.on(at.type,((e,{payload:t})=>{var s,n,i,r,a;return mt.with({channels:e.channels,groups:e.groups,cursor:{timetoken:(null===(s=e.cursor)||void 0===s?void 0:s.timetoken)?null===(n=e.cursor)||void 0===n?void 0:n.timetoken:t.timetoken,region:t.region},referenceTimetoken:I(t.timetoken,null===(i=e.cursor)||void 0===i?void 0:i.timetoken)},[wt({category:h.PNConnectedCategory,affectedChannels:e.channels.slice(0),affectedChannelGroups:e.groups.slice(0),operation:K.PNSubscribeOperation,currentTimetoken:(null===(r=e.cursor)||void 0===r?void 0:r.timetoken)?null===(a=e.cursor)||void 0===a?void 0:a.timetoken:t.timetoken})])})),gt.on(ot.type,((e,t)=>{var s;return yt.with(Object.assign(Object.assign({},e),{reason:t.payload}),[wt({category:h.PNConnectionErrorCategory,error:null===(s=t.payload.status)||void 0===s?void 0:s.category})])})),gt.on(lt.type,((e,t)=>{var s;if(t.payload.isOffline){const t=G.create(new Error("Network connection error")).toPubNubError(K.PNSubscribeOperation);return yt.with(Object.assign(Object.assign({},e),{reason:t}),[wt({category:h.PNConnectionErrorCategory,error:null===(s=t.status)||void 0===s?void 0:s.category})])}return bt.with(Object.assign({},e))})),gt.on(rt.type,((e,{payload:t})=>{var s;return 0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region||(null===(s=null==e?void 0:e.cursor)||void 0===s?void 0:s.region)||0},onDemand:!0})})),gt.on(dt.type,(e=>pt.with())),bt.on(it.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):bt.with({channels:t.channels,groups:t.groups,cursor:e.cursor}))),bt.on(ht.type,((e,{payload:t})=>gt.with(Object.assign(Object.assign({},e),{cursor:t.cursor||e.cursor,onDemand:!0})))),bt.on(rt.type,((e,{payload:t})=>{var s;return 0===t.channels.length&&0===t.groups.length?pt.with(void 0):bt.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region||(null===(s=e.cursor)||void 0===s?void 0:s.region)||0}})})),bt.on(dt.type,(e=>pt.with())),yt.on(it.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:e.cursor,onDemand:!0}))),yt.on(ht.type,((e,{payload:t})=>gt.with(Object.assign(Object.assign({},e),{cursor:t.cursor||e.cursor,onDemand:!0})))),yt.on(rt.type,((e,{payload:t})=>{var s,n;return 0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region?t.cursor.region:null!==(n=null===(s=null==e?void 0:e.cursor)||void 0===s?void 0:s.region)&&void 0!==n?n:0},onDemand:!0})})),yt.on(dt.type,(e=>pt.with())),mt.onEnter((e=>{var t;return St(e.channels,e.groups,e.cursor,null!==(t=e.onDemand)&&void 0!==t&&t)})),mt.onExit((()=>St.cancel)),mt.on(ct.type,((e,{payload:t})=>mt.with({channels:e.channels,groups:e.groups,cursor:t.cursor,referenceTimetoken:I(t.cursor.timetoken)},[jt(e.cursor,t.events)]))),mt.on(it.type,((e,{payload:t})=>{var s;if(0===t.channels.length&&0===t.groups.length){let e;return t.isOffline&&(e=null===(s=G.create(new Error("Network connection error")).toPubNubError(K.PNSubscribeOperation).status)||void 0===s?void 0:s.category),pt.with(void 0,[wt(Object.assign({category:t.isOffline?h.PNDisconnectedUnexpectedlyCategory:h.PNDisconnectedCategory,operation:K.PNUnsubscribeOperation},e?{error:e}:{}))])}return mt.with({channels:t.channels,groups:t.groups,cursor:e.cursor,referenceTimetoken:e.referenceTimetoken,onDemand:!0},[wt({category:h.PNSubscriptionChangedCategory,affectedChannels:t.channels.slice(0),affectedChannelGroups:t.groups.slice(0),currentTimetoken:e.cursor.timetoken})])})),mt.on(rt.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0,[wt({category:h.PNDisconnectedCategory})]):mt.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region||e.cursor.region},referenceTimetoken:I(e.cursor.timetoken,`${t.cursor.timetoken}`,e.referenceTimetoken),onDemand:!0},[wt({category:h.PNSubscriptionChangedCategory,affectedChannels:t.channels.slice(0),affectedChannelGroups:t.groups.slice(0),currentTimetoken:t.cursor.timetoken})]))),mt.on(ut.type,((e,{payload:t})=>{var s;return vt.with(Object.assign(Object.assign({},e),{reason:t}),[wt({category:h.PNDisconnectedUnexpectedlyCategory,error:null===(s=t.status)||void 0===s?void 0:s.category})])})),mt.on(lt.type,((e,t)=>{var s;if(t.payload.isOffline){const t=G.create(new Error("Network connection error")).toPubNubError(K.PNSubscribeOperation);return vt.with(Object.assign(Object.assign({},e),{reason:t}),[wt({category:h.PNDisconnectedUnexpectedlyCategory,operation:K.PNSubscribeOperation,error:null===(s=t.status)||void 0===s?void 0:s.category})])}return ft.with(Object.assign({},e),[wt({category:h.PNDisconnectedCategory,operation:K.PNSubscribeOperation})])})),mt.on(dt.type,(e=>pt.with(void 0,[wt({category:h.PNDisconnectedCategory,operation:K.PNUnsubscribeOperation})]))),ft.on(it.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):ft.with({channels:t.channels,groups:t.groups,cursor:e.cursor}))),ft.on(rt.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):ft.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region||e.cursor.region}}))),ft.on(ht.type,((e,{payload:t})=>{var s;return gt.with({channels:e.channels,groups:e.groups,cursor:{timetoken:t.cursor.timetoken?null===(s=t.cursor)||void 0===s?void 0:s.timetoken:e.cursor.timetoken,region:t.cursor.region||e.cursor.region},onDemand:!0})})),ft.on(dt.type,(()=>pt.with(void 0))),vt.on(ht.type,((e,{payload:t})=>{var s;return gt.with({channels:e.channels,groups:e.groups,cursor:{timetoken:t.cursor.timetoken?null===(s=t.cursor)||void 0===s?void 0:s.timetoken:e.cursor.timetoken,region:t.cursor.region||e.cursor.region},onDemand:!0})})),vt.on(it.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:e.cursor,onDemand:!0}))),vt.on(rt.type,((e,{payload:t})=>0===t.channels.length&&0===t.groups.length?pt.with(void 0):gt.with({channels:t.channels,groups:t.groups,cursor:{timetoken:`${t.cursor.timetoken}`,region:t.cursor.region||e.cursor.region},onDemand:!0}))),vt.on(dt.type,(e=>pt.with(void 0)));class kt extends _e{constructor(e,t){super(t,t.config.logger()),this.on(Ot.type,Fe(((t,s,n)=>r(this,[t,s,n],void 0,(function*(t,s,{handshake:n,presenceState:i,config:r}){s.throwIfAborted();try{const a=yield n(Object.assign(Object.assign({abortSignal:s,channels:t.channels,channelGroups:t.groups,filterExpression:r.filterExpression},r.maintainPresenceState&&{state:i}),{onDemand:t.onDemand}));return e.transition(at(a))}catch(t){if(t instanceof d){if(t.status&&t.status.category==h.PNCancelledCategory)return;return e.transition(ot(t))}}}))))),this.on(St.type,Fe(((t,s,n)=>r(this,[t,s,n],void 0,(function*(t,s,{receiveMessages:n,config:i}){s.throwIfAborted();try{const r=yield n({abortSignal:s,channels:t.channels,channelGroups:t.groups,timetoken:t.cursor.timetoken,region:t.cursor.region,filterExpression:i.filterExpression,onDemand:t.onDemand});e.transition(ct(r.cursor,r.messages))}catch(t){if(t instanceof d){if(t.status&&t.status.category==h.PNCancelledCategory)return;if(!s.aborted)return e.transition(ut(t))}}}))))),this.on(jt.type,Fe(((e,t,s)=>r(this,[e,t,s],void 0,(function*({cursor:e,events:t},s,{emitMessages:n}){t.length>0&&n(e,t)}))))),this.on(wt.type,Fe(((e,t,s)=>r(this,[e,t,s],void 0,(function*(e,t,{emitStatus:s}){return s(e)})))))}}class Ct{get _engine(){return this.engine}constructor(e){this.channels=[],this.groups=[],this.dependencies=e,this.engine=new Te(e.config.logger()),this.dispatcher=new kt(this.engine,e),e.config.logger().debug("EventEngine","Create subscribe event engine."),this._unsubscribeEngine=this.engine.subscribe((e=>{"invocationDispatched"===e.type&&this.dispatcher.dispatch(e.invocation)})),this.engine.start(pt,void 0)}get subscriptionTimetoken(){const e=this.engine.currentState;if(!e)return;let t,s="0";if(e.label===mt.label){const e=this.engine.currentContext;s=e.cursor.timetoken,t=e.referenceTimetoken}return _(s,null!=t?t:"0")}subscribe({channels:e,channelGroups:t,timetoken:s,withPresence:n}){var i;const r=null==e?void 0:e.some((e=>!this.channels.includes(e))),a=null==t?void 0:t.some((e=>!this.groups.includes(e))),o=r||a;if(this.channels=[...this.channels,...null!=e?e:[]],this.groups=[...this.groups,...null!=t?t:[]],n&&(this.channels.map((e=>this.channels.push(`${e}-pnpres`))),this.groups.map((e=>this.groups.push(`${e}-pnpres`)))),s)this.engine.transition(rt(Array.from(new Set([...this.channels,...null!=e?e:[]])),Array.from(new Set([...this.groups,...null!=t?t:[]])),s));else if(o)this.engine.transition(it(Array.from(new Set([...this.channels,...null!=e?e:[]])),Array.from(new Set([...this.groups,...null!=t?t:[]]))));else{this.dependencies.config.logger().debug("EventEngine","Skipping state transition - all channels/groups already subscribed. Emitting SubscriptionChanged event.");const e=this.engine.currentState,t=this.engine.currentContext;let s="0";if((null==e?void 0:e.label)===mt.label&&t){s=null===(i=t.cursor)||void 0===i?void 0:i.timetoken}this.dependencies.emitStatus({category:h.PNSubscriptionChangedCategory,affectedChannels:Array.from(new Set(this.channels)),affectedChannelGroups:Array.from(new Set(this.groups)),currentTimetoken:s})}this.dependencies.join&&this.dependencies.join({channels:Array.from(new Set(this.channels.filter((e=>!e.endsWith("-pnpres"))))),groups:Array.from(new Set(this.groups.filter((e=>!e.endsWith("-pnpres")))))})}unsubscribe({channels:e=[],channelGroups:t=[]}){const s=N(this.channels,[...e,...e.map((e=>`${e}-pnpres`))]),n=N(this.groups,[...t,...t.map((e=>`${e}-pnpres`))]);if(new Set(this.channels).size!==new Set(s).size||new Set(this.groups).size!==new Set(n).size){const i=E(this.channels,e),r=E(this.groups,t);this.dependencies.presenceState&&(null==i||i.forEach((e=>delete this.dependencies.presenceState[e])),null==r||r.forEach((e=>delete this.dependencies.presenceState[e]))),this.channels=s,this.groups=n,this.engine.transition(it(Array.from(new Set(this.channels.slice(0))),Array.from(new Set(this.groups.slice(0))))),this.dependencies.leave&&this.dependencies.leave({channels:i.slice(0),groups:r.slice(0)})}}unsubscribeAll(e=!1){const t=this.getSubscribedChannelGroups(),s=this.getSubscribedChannels();this.channels=[],this.groups=[],this.dependencies.presenceState&&Object.keys(this.dependencies.presenceState).forEach((e=>{delete this.dependencies.presenceState[e]})),this.engine.transition(it(this.channels.slice(0),this.groups.slice(0),e)),this.dependencies.leaveAll&&this.dependencies.leaveAll({channels:s,groups:t,isOffline:e})}reconnect({timetoken:e,region:t}){const s=this.getSubscribedChannels(),n=this.getSubscribedChannels();this.engine.transition(ht(e,t)),this.dependencies.presenceReconnect&&this.dependencies.presenceReconnect({channels:n,groups:s})}disconnect(e=!1){const t=this.getSubscribedChannels(),s=this.getSubscribedChannels();this.engine.transition(lt(e)),this.dependencies.presenceDisconnect&&this.dependencies.presenceDisconnect({channels:s,groups:t,isOffline:e})}getSubscribedChannels(){return Array.from(new Set(this.channels.slice(0)))}getSubscribedChannelGroups(){return Array.from(new Set(this.groups.slice(0)))}dispose(){this.disconnect(!0),this._unsubscribeEngine(),this.dispatcher.dispose()}}class Pt extends pe{constructor(e){var t;const s=null!==(t=e.sendByPost)&&void 0!==t&&t;super({method:s?ue.POST:ue.GET,compressible:s}),this.parameters=e,this.parameters.sendByPost=s}operation(){return K.PNPublishOperation}validate(){const{message:e,channel:t,keySet:{publishKey:s}}=this.parameters;return t?e?s?void 0:"Missing 'publishKey'":"Missing 'message'":"Missing 'channel'"}parse(e){return r(this,void 0,void 0,(function*(){return{timetoken:this.deserializeResponse(e)[2]}}))}get path(){const{message:e,channel:t,keySet:s}=this.parameters,n=this.prepareMessagePayload(e);return`/publish/${s.publishKey}/${s.subscribeKey}/0/${C(t)}/0${this.parameters.sendByPost?"":`/${C(n)}`}`}get queryParameters(){const{customMessageType:e,meta:t,replicate:s,storeInHistory:n,ttl:i}=this.parameters,r={};return e&&(r.custom_message_type=e),void 0!==n&&(r.store=n?"1":"0"),void 0!==i&&(r.ttl=i),void 0===s||s||(r.norep="true"),t&&"object"==typeof t&&(r.meta=JSON.stringify(t)),r}get headers(){var e;return this.parameters.sendByPost?Object.assign(Object.assign({},null!==(e=super.headers)&&void 0!==e?e:{}),{"Content-Type":"application/json"}):super.headers}get body(){return this.prepareMessagePayload(this.parameters.message)}prepareMessagePayload(e){const{crypto:t}=this.parameters;if(!t)return JSON.stringify(e)||"";const s=t.encrypt(JSON.stringify(e));return JSON.stringify("string"==typeof s?s:u(s))}}class Nt extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNSignalOperation}validate(){const{message:e,channel:t,keySet:{publishKey:s}}=this.parameters;return t?e?s?void 0:"Missing 'publishKey'":"Missing 'message'":"Missing 'channel'"}parse(e){return r(this,void 0,void 0,(function*(){return{timetoken:this.deserializeResponse(e)[2]}}))}get path(){const{keySet:{publishKey:e,subscribeKey:t},channel:s,message:n}=this.parameters,i=JSON.stringify(n);return`/signal/${e}/${t}/0/${C(s)}/0/${C(i)}`}get queryParameters(){const{customMessageType:e}=this.parameters,t={};return e&&(t.custom_message_type=e),t}}class Et extends me{operation(){return K.PNReceiveMessagesOperation}validate(){const e=super.validate();return e||(this.parameters.timetoken?this.parameters.region?void 0:"region can not be empty":"timetoken can not be empty")}get path(){const{keySet:{subscribeKey:e},channels:t=[]}=this.parameters;return`/v2/subscribe/${e}/${P(t.sort(),",")}/0`}get queryParameters(){const{channelGroups:e,filterExpression:t,timetoken:s,region:n,heartbeat:i,onDemand:r}=this.parameters,a={ee:""};return r&&(a["on-demand"]=1),e&&e.length>0&&(a["channel-group"]=e.sort().join(",")),t&&t.length>0&&(a["filter-expr"]=t),"string"==typeof s?s&&"0"!==s&&s.length>0&&(a.tt=s):s&&s>0&&(a.tt=s),n&&(a.tr=n),i&&(a.heartbeat=i),a}}class Tt extends me{operation(){return K.PNHandshakeOperation}get path(){const{keySet:{subscribeKey:e},channels:t=[]}=this.parameters;return`/v2/subscribe/${e}/${P(t.sort(),",")}/0`}get queryParameters(){const{channelGroups:e,heartbeat:t,filterExpression:s,state:n,onDemand:i}=this.parameters,r={ee:""};return i&&(r["on-demand"]=1),e&&e.length>0&&(r["channel-group"]=e.sort().join(",")),s&&s.length>0&&(r["filter-expr"]=s),n&&Object.keys(n).length>0&&(r.state=JSON.stringify(n)),t&&(r.heartbeat=t),r}}var _t;!function(e){e[e.Channel=0]="Channel",e[e.ChannelGroup=1]="ChannelGroup"}(_t||(_t={}));class It{constructor({channels:e,channelGroups:t}){this.isEmpty=!0,this._channelGroups=new Set((null!=t?t:[]).filter((e=>e.length>0))),this._channels=new Set((null!=e?e:[]).filter((e=>e.length>0))),this.isEmpty=0===this._channels.size&&0===this._channelGroups.size}get length(){return this.isEmpty?0:this._channels.size+this._channelGroups.size}get channels(){return this.isEmpty?[]:Array.from(this._channels)}get channelGroups(){return this.isEmpty?[]:Array.from(this._channelGroups)}contains(e){return!this.isEmpty&&(this._channels.has(e)||this._channelGroups.has(e))}with(e){return new It({channels:[...this._channels,...e._channels],channelGroups:[...this._channelGroups,...e._channelGroups]})}without(e){return new It({channels:[...this._channels].filter((t=>!e._channels.has(t))),channelGroups:[...this._channelGroups].filter((t=>!e._channelGroups.has(t)))})}add(e){return e._channelGroups.size>0&&(this._channelGroups=new Set([...this._channelGroups,...e._channelGroups])),e._channels.size>0&&(this._channels=new Set([...this._channels,...e._channels])),this.isEmpty=0===this._channels.size&&0===this._channelGroups.size,this}remove(e){return e._channelGroups.size>0&&(this._channelGroups=new Set([...this._channelGroups].filter((t=>!e._channelGroups.has(t))))),e._channels.size>0&&(this._channels=new Set([...this._channels].filter((t=>!e._channels.has(t))))),this}removeAll(){return this._channels.clear(),this._channelGroups.clear(),this.isEmpty=!0,this}toString(){return`SubscriptionInput { channels: [${this.channels.join(", ")}], channelGroups: [${this.channelGroups.join(", ")}], is empty: ${this.isEmpty?"true":"false"}} }`}}class Mt{constructor(e,t,s,n){this._isSubscribed=!1,this.clones={},this.parents=[],this._id=ie.createUUID(),this.referenceTimetoken=n,this.subscriptionInput=t,this.options=s,this.client=e}get id(){return this._id}get isLastClone(){return 1===Object.keys(this.clones).length}get isSubscribed(){return!!this._isSubscribed||this.parents.length>0&&this.parents.some((e=>e.isSubscribed))}set isSubscribed(e){this.isSubscribed!==e&&(this._isSubscribed=e)}addParentState(e){this.parents.includes(e)||this.parents.push(e)}removeParentState(e){const t=this.parents.indexOf(e);-1!==t&&this.parents.splice(t,1)}storeClone(e,t){this.clones[e]||(this.clones[e]=t)}}class Rt{constructor(e,t="Subscription"){this.subscriptionType=t,this.id=ie.createUUID(),this.eventDispatcher=new ve,this._state=e}get state(){return this._state}get channels(){return this.state.subscriptionInput.channels.slice(0)}get channelGroups(){return this.state.subscriptionInput.channelGroups.slice(0)}set onMessage(e){this.eventDispatcher.onMessage=e}set onPresence(e){this.eventDispatcher.onPresence=e}set onSignal(e){this.eventDispatcher.onSignal=e}set onObjects(e){this.eventDispatcher.onObjects=e}set onMessageAction(e){this.eventDispatcher.onMessageAction=e}set onFile(e){this.eventDispatcher.onFile=e}set onDataSync(e){this.eventDispatcher.onDataSync=e}addListener(e){this.eventDispatcher.addListener(e)}removeListener(e){this.eventDispatcher.removeListener(e)}removeAllListeners(){this.eventDispatcher.removeAllListeners()}handleEvent(e,t){var s;if((!this.state.cursor||e>this.state.cursor)&&(this.state.cursor=e),this.state.referenceTimetoken&&t.data.timetoken({messageType:"text",message:`Event timetoken (${t.data.timetoken}) is older than reference timetoken (${this.state.referenceTimetoken}) for ${this.id} subscription object. Ignoring event.`})));if((null===(s=this.state.options)||void 0===s?void 0:s.filter)&&!this.state.options.filter(t))return void this.state.client.logger.trace(this.subscriptionType,`Event filtered out by filter function for ${this.id} subscription object. Ignoring event.`);const n=Object.values(this.state.clones);n.length>0&&this.state.client.logger.trace(this.subscriptionType,`Notify ${this.id} subscription object clones (count: ${n.length}) about received event.`),n.forEach((e=>e.eventDispatcher.handleEvent(t)))}dispose(){const e=Object.keys(this.state.clones);e.length>1?(this.state.client.logger.debug(this.subscriptionType,`Remove subscription object clone on dispose: ${this.id}`),delete this.state.clones[this.id]):1===e.length&&this.state.clones[this.id]&&(this.state.client.logger.debug(this.subscriptionType,`Unsubscribe subscription object on dispose: ${this.id}`),this.unsubscribe())}invalidate(e=!1){this.state._isSubscribed=!1,e&&(delete this.state.clones[this.id],0===Object.keys(this.state.clones).length&&(this.state.client.logger.trace(this.subscriptionType,"Last clone removed. Reset shared subscription state."),this.state.subscriptionInput.removeAll(),this.state.parents=[]))}subscribe(e){this.state.isSubscribed?this.state.client.logger.trace(this.subscriptionType,"Already subscribed. Ignoring subscribe request."):(this.state.client.logger.debug(this.subscriptionType,(()=>e?{messageType:"object",message:e,details:"Subscribe with parameters:"}:{messageType:"text",message:"Subscribe"})),this.state.isSubscribed=!0,this.updateSubscription({subscribing:!0,timetoken:null==e?void 0:e.timetoken}))}unsubscribe(){if(!this.state._isSubscribed||this.state.isSubscribed){if(!this.state._isSubscribed&&this.state.parents.length>0&&this.state.isSubscribed)return void this.state.client.logger.warn(this.subscriptionType,(()=>({messageType:"object",details:"Subscription is subscribed as part of a subscription set. Remove from active sets to unsubscribe:",message:this.state.parents.filter((e=>e.isSubscribed))})));if(!this.state._isSubscribed)return void this.state.client.logger.trace(this.subscriptionType,"Not subscribed. Ignoring unsubscribe request.")}this.state.client.logger.debug(this.subscriptionType,"Unsubscribe"),this.state.isSubscribed=!1,delete this.state.cursor,this.updateSubscription({subscribing:!1})}updateSubscription(e){var t,s;(null==e?void 0:e.timetoken)&&((null===(t=this.state.cursor)||void 0===t?void 0:t.timetoken)&&"0"!==(null===(s=this.state.cursor)||void 0===s?void 0:s.timetoken)?"0"!==e.timetoken&&e.timetoken>this.state.cursor.timetoken&&(this.state.cursor.timetoken=e.timetoken):this.state.cursor={timetoken:e.timetoken});const n=e.subscriptions&&e.subscriptions.length>0?e.subscriptions:void 0;e.subscribing?this.register(Object.assign(Object.assign({},e.timetoken?{cursor:this.state.cursor}:{}),n?{subscriptions:n}:{})):this.unregister(n)}}class Dt extends Mt{constructor(e){const t=new It({});e.subscriptions.forEach((e=>t.add(e.state.subscriptionInput))),super(e.client,t,e.options,e.client.subscriptionTimetoken),this.subscriptions=e.subscriptions}addSubscription(e){this.subscriptions.includes(e)||(e.state.addParentState(this),this.subscriptions.push(e),this.subscriptionInput.add(e.state.subscriptionInput))}removeSubscription(e,t){const s=this.subscriptions.indexOf(e);-1!==s&&(this.subscriptions.splice(s,1),t||e.state.removeParentState(this),this.subscriptionInput.remove(e.state.subscriptionInput))}removeAllSubscriptions(){this.subscriptions.forEach((e=>e.state.removeParentState(this))),this.subscriptions.splice(0,this.subscriptions.length),this.subscriptionInput.removeAll()}}class Ut extends Rt{constructor(e){let t;if("client"in e){let s=[];!e.subscriptions&&e.entities?e.entities.forEach((t=>s.push(t.subscription(e.options)))):e.subscriptions&&(s=e.subscriptions),t=new Dt({client:e.client,subscriptions:s,options:e.options}),s.forEach((e=>e.state.addParentState(t))),t.client.logger.debug("SubscriptionSet",(()=>({messageType:"object",details:"Create subscription set with parameters:",message:Object.assign({subscriptions:t.subscriptions},e.options?e.options:{})})))}else t=e.state,t.client.logger.debug("SubscriptionSet","Create subscription set clone");super(t,"SubscriptionSet"),this.state.storeClone(this.id,this),t.subscriptions.forEach((e=>e.addParentSet(this)))}get state(){return super.state}get subscriptions(){return this.state.subscriptions.slice(0)}handleEvent(e,t){var s;this.state.subscriptionInput.contains(null!==(s=t.data.subscription)&&void 0!==s?s:t.data.channel)&&(this.state._isSubscribed?(super.handleEvent(e,t),this.state.subscriptions.length>0&&this.state.client.logger.trace(this.subscriptionType,`Notify ${this.id} subscription set subscriptions (count: ${this.state.subscriptions.length}) about received event.`),this.state.subscriptions.forEach((s=>s.handleEvent(e,t)))):this.state.client.logger.trace(this.subscriptionType,`Subscription set ${this.id} is not subscribed. Ignoring event.`))}subscriptionInput(e=!1){let t=this.state.subscriptionInput;return this.state.subscriptions.forEach((s=>{e&&s.state.entity.subscriptionsCount>0&&(t=t.without(s.state.subscriptionInput))})),t}cloneEmpty(){return new Ut({state:this.state})}dispose(){const e=this.state.isLastClone;this.state.subscriptions.forEach((t=>{t.removeParentSet(this),e&&t.state.removeParentState(this.state)})),super.dispose()}invalidate(e=!1){(e?this.state.subscriptions.slice(0):this.state.subscriptions).forEach((t=>{e&&(t.state.entity.decreaseSubscriptionCount(this.state.id),t.removeParentSet(this)),t.invalidate(e)})),e&&this.state.removeAllSubscriptions(),super.invalidate()}addSubscription(e){this.addSubscriptions([e])}addSubscriptions(e){const t=[],s=[];this.state.client.logger.debug(this.subscriptionType,(()=>{const t=[],s=[];return e.forEach((e=>{this.state.subscriptions.includes(e)?t.push(e):s.push(e)})),{messageType:"object",details:`Add subscriptions to ${this.id} (subscriptions count: ${this.state.subscriptions.length+s.length}):`,message:{addedSubscriptions:s,ignoredSubscriptions:t}}})),e.filter((e=>!this.state.subscriptions.includes(e))).forEach((e=>{e.state.isSubscribed?s.push(e):t.push(e),e.addParentSet(this),this.state.addSubscription(e)})),0===s.length&&0===t.length||!this.state.isSubscribed||(s.forEach((({state:e})=>e.entity.increaseSubscriptionCount(this.state.id))),t.length>0&&this.updateSubscription({subscribing:!0,subscriptions:t}))}removeSubscription(e){this.removeSubscriptions([e])}removeSubscriptions(e){const t=[];this.state.client.logger.debug(this.subscriptionType,(()=>{const t=[],s=[];return e.forEach((e=>{this.state.subscriptions.includes(e)?s.push(e):t.push(e)})),{messageType:"object",details:`Remove subscriptions from ${this.id} (subscriptions count: ${this.state.subscriptions.length}):`,message:{removedSubscriptions:s,ignoredSubscriptions:t}}})),e.filter((e=>this.state.subscriptions.includes(e))).forEach((e=>{e.state.isSubscribed&&t.push(e),e.removeParentSet(this),this.state.removeSubscription(e,e.parentSetsCount>1)})),0!==t.length&&this.state.isSubscribed&&this.updateSubscription({subscribing:!1,subscriptions:t})}addSubscriptionSet(e){this.addSubscriptions(e.subscriptions)}removeSubscriptionSet(e){this.removeSubscriptions(e.subscriptions)}register(e){var t;const s=null!==(t=e.subscriptions)&&void 0!==t?t:this.state.subscriptions;s.forEach((({state:e})=>e.entity.increaseSubscriptionCount(this.state.id))),this.state.client.logger.trace(this.subscriptionType,(()=>({messageType:"text",message:`Register subscription for real-time events: ${this}`}))),this.state.client.registerEventHandleCapable(this,e.cursor,s)}unregister(e){const t=null!=e?e:this.state.subscriptions;t.forEach((({state:e})=>e.entity.decreaseSubscriptionCount(this.state.id))),this.state.client.logger.trace(this.subscriptionType,(()=>e?{messageType:"object",message:{subscription:this,subscriptions:e},details:"Unregister subscriptions of subscription set from real-time events:"}:{messageType:"text",message:`Unregister subscription from real-time events: ${this}`})),this.state.client.unregisterEventHandleCapable(this,t)}toString(){const e=this.state;return`${this.subscriptionType} { id: ${this.id}, stateId: ${e.id}, clonesCount: ${Object.keys(this.state.clones).length}, isSubscribed: ${e.isSubscribed}, subscriptions: [${e.subscriptions.map((e=>e.toString())).join(", ")}] }`}}class At extends Mt{constructor(e){var t,s;const n=e.entity.subscriptionNames(null!==(s=null===(t=e.options)||void 0===t?void 0:t.receivePresenceEvents)&&void 0!==s&&s),i=new It({[e.entity.subscriptionType==_t.Channel?"channels":"channelGroups"]:n});super(e.client,i,e.options,e.client.subscriptionTimetoken),this.entity=e.entity}}class $t extends Rt{constructor(e){"client"in e?e.client.logger.debug("Subscription",(()=>({messageType:"object",details:"Create subscription with parameters:",message:Object.assign({entity:e.entity},e.options?e.options:{})}))):e.state.client.logger.debug("Subscription","Create subscription clone"),super("state"in e?e.state:new At(e)),this.parents=[],this.handledUpdates=[],this.state.storeClone(this.id,this)}get state(){return super.state}get parentSetsCount(){return this.parents.length}handleEvent(e,t){var s,n;if(this.state.isSubscribed&&this.state.subscriptionInput.contains(null!==(s=t.data.subscription)&&void 0!==s?s:t.data.channel)){if(this.parentSetsCount>0){const e=R(t.data);if(this.handledUpdates.includes(e))return void this.state.client.logger.trace(this.subscriptionType,`Event (${e}) already handled by ${this.id}. Ignoring.`);this.handledUpdates.push(e),this.handledUpdates.length>10&&this.handledUpdates.shift()}this.state.subscriptionInput.contains(null!==(n=t.data.subscription)&&void 0!==n?n:t.data.channel)&&super.handleEvent(e,t)}}subscriptionInput(e=!1){return e&&this.state.entity.subscriptionsCount>0?new It({}):this.state.subscriptionInput}cloneEmpty(){return new $t({state:this.state})}dispose(){this.parentSetsCount>0?this.state.client.logger.debug(this.subscriptionType,(()=>({messageType:"text",message:`'${this.state.entity.subscriptionNames()}' subscription still in use. Ignore dispose request.`}))):(this.handledUpdates.splice(0,this.handledUpdates.length),super.dispose())}invalidate(e=!1){e&&this.state.entity.decreaseSubscriptionCount(this.state.id),this.handledUpdates.splice(0,this.handledUpdates.length),super.invalidate(e)}addParentSet(e){this.parents.includes(e)||(this.parents.push(e),this.state.client.logger.trace(this.subscriptionType,`Add parent subscription set for ${this.id}: ${e.id}. Parent subscription set count: ${this.parentSetsCount}`))}removeParentSet(e){const t=this.parents.indexOf(e);-1!==t&&(this.parents.splice(t,1),this.state.client.logger.trace(this.subscriptionType,`Remove parent subscription set from ${this.id}: ${e.id}. Parent subscription set count: ${this.parentSetsCount}`)),0===this.parentSetsCount&&this.handledUpdates.splice(0,this.handledUpdates.length)}addSubscription(e){this.state.client.logger.debug(this.subscriptionType,(()=>({messageType:"text",message:`Create set with subscription: ${e}`})));const t=new Ut({client:this.state.client,subscriptions:[this,e],options:this.state.options});return this.state.isSubscribed||e.state.isSubscribed?(this.state.client.logger.trace(this.subscriptionType,"Subscribe resulting set because the receiver is already subscribed."),t.subscribe(),t):t}register(e){this.state.entity.increaseSubscriptionCount(this.state.id),this.state.client.logger.trace(this.subscriptionType,(()=>({messageType:"text",message:`Register subscription for real-time events: ${this}`}))),this.state.client.registerEventHandleCapable(this,e.cursor)}unregister(e){this.state.entity.decreaseSubscriptionCount(this.state.id),this.state.client.logger.trace(this.subscriptionType,(()=>({messageType:"text",message:`Unregister subscription from real-time events: ${this}`}))),this.handledUpdates.splice(0,this.handledUpdates.length),this.state.client.unregisterEventHandleCapable(this)}toString(){const e=this.state;return`${this.subscriptionType} { id: ${this.id}, stateId: ${e.id}, entity: ${e.entity.subscriptionNames(!1).pop()}, clonesCount: ${Object.keys(e.clones).length}, isSubscribed: ${e.isSubscribed}, parentSetsCount: ${this.parentSetsCount}, cursor: ${e.cursor?e.cursor.timetoken:"not set"}, referenceTimetoken: ${e.referenceTimetoken?e.referenceTimetoken:"not set"} }`}}class Ft extends pe{constructor(e){var t,s,n,i;super(),this.parameters=e,null!==(t=(n=this.parameters).channels)&&void 0!==t||(n.channels=[]),null!==(s=(i=this.parameters).channelGroups)&&void 0!==s||(i.channelGroups=[])}operation(){return K.PNGetStateOperation}validate(){const{keySet:{subscribeKey:e},channels:t,channelGroups:s}=this.parameters;if(!e)return"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e),{channels:s=[],channelGroups:n=[]}=this.parameters,i={channels:{}};return 1===s.length&&0===n.length?i.channels[s[0]]=t.payload:i.channels=t.payload,i}))}get path(){const{keySet:{subscribeKey:e},uuid:t,channels:s}=this.parameters;return`/v2/presence/sub-key/${e}/channel/${P(null!=s?s:[],",")}/uuid/${C(null!=t?t:"")}`}get queryParameters(){const{channelGroups:e}=this.parameters;return e&&0!==e.length?{"channel-group":e.join(",")}:{}}}class xt extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNSetStateOperation}validate(){const{keySet:{subscribeKey:e},state:t,channels:s=[],channelGroups:n=[]}=this.parameters;return e?void 0===t?"Missing State":0===(null==s?void 0:s.length)&&0===(null==n?void 0:n.length)?"Please provide a list of channels and/or channel-groups":void 0:"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){return{state:this.deserializeResponse(e).payload}}))}get path(){const{keySet:{subscribeKey:e},uuid:t,channels:s}=this.parameters;return`/v2/presence/sub-key/${e}/channel/${P(null!=s?s:[],",")}/uuid/${C(t)}/data`}get queryParameters(){const{channelGroups:e,state:t}=this.parameters,s={state:JSON.stringify(t)};return e&&0!==e.length&&(s["channel-group"]=e.join(",")),s}}class qt extends pe{constructor(e){super({cancellable:!0}),this.parameters=e}operation(){return K.PNHeartbeatOperation}validate(){const{keySet:{subscribeKey:e},channels:t=[],channelGroups:s=[]}=this.parameters;return e?0===t.length&&0===s.length?"Please provide a list of channels and/or channel-groups":void 0:"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}get path(){const{keySet:{subscribeKey:e},channels:t}=this.parameters;return`/v2/presence/sub-key/${e}/channel/${P(null!=t?t:[],",")}/heartbeat`}get queryParameters(){const{channelGroups:e,state:t,heartbeat:s}=this.parameters,n={heartbeat:`${s}`};return e&&0!==e.length&&(n["channel-group"]=e.join(",")),void 0!==t&&(n.state=JSON.stringify(t)),n}}class Gt extends pe{constructor(e){super(),this.parameters=e,this.parameters.channelGroups&&(this.parameters.channelGroups=Array.from(new Set(this.parameters.channelGroups))),this.parameters.channels&&(this.parameters.channels=Array.from(new Set(this.parameters.channels)))}operation(){return K.PNUnsubscribeOperation}validate(){const{keySet:{subscribeKey:e},channels:t=[],channelGroups:s=[]}=this.parameters;return e?0===t.length&&0===s.length?"At least one `channel` or `channel group` should be provided.":void 0:"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}get path(){var e;const{keySet:{subscribeKey:t},channels:s}=this.parameters;return`/v2/presence/sub-key/${t}/channel/${P(null!==(e=null==s?void 0:s.sort())&&void 0!==e?e:[],",")}/leave`}get queryParameters(){const{channelGroups:e}=this.parameters;return e&&0!==e.length?{"channel-group":e.sort().join(",")}:{}}}class Lt extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNWhereNowOperation}validate(){if(!this.parameters.keySet.subscribeKey)return"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return t.payload?{channels:t.payload.channels}:{channels:[]}}))}get path(){const{keySet:{subscribeKey:e},uuid:t}=this.parameters;return`/v2/presence/sub-key/${e}/uuid/${C(t)}`}}class Kt extends pe{constructor(e){var t,s,n,i,r,a,o,c;super(),this.parameters=e,null!==(t=(r=this.parameters).queryParameters)&&void 0!==t||(r.queryParameters={}),null!==(s=(a=this.parameters).includeUUIDs)&&void 0!==s||(a.includeUUIDs=true),null!==(n=(o=this.parameters).includeState)&&void 0!==n||(o.includeState=false),null!==(i=(c=this.parameters).limit)&&void 0!==i||(c.limit=1e3)}operation(){const{channels:e=[],channelGroups:t=[]}=this.parameters;return 0===e.length&&0===t.length?K.PNGlobalHereNowOperation:K.PNHereNowOperation}validate(){if(!this.parameters.keySet.subscribeKey)return"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){var t,s;const n=this.deserializeResponse(e),i="occupancy"in n?1:n.payload.total_channels,r="occupancy"in n?n.occupancy:n.payload.total_occupancy,a={};let o={};const c=this.parameters.limit;let u=!1;if("occupancy"in n){const e=this.parameters.channels[0];o[e]={uuids:null!==(t=n.uuids)&&void 0!==t?t:[],occupancy:r}}else o=null!==(s=n.payload.channels)&&void 0!==s?s:{};return Object.keys(o).forEach((e=>{const t=o[e];a[e]={occupants:this.parameters.includeUUIDs?t.uuids.map((e=>"string"==typeof e?{uuid:e,state:null}:e)):[],name:e,occupancy:t.occupancy},u||t.occupancy!==c||(u=!0)})),{totalChannels:i,totalOccupancy:r,channels:a}}))}get path(){const{keySet:{subscribeKey:e},channels:t,channelGroups:s}=this.parameters;let n=`/v2/presence/sub-key/${e}`;return(t&&t.length>0||s&&s.length>0)&&(n+=`/channel/${P(null!=t?t:[],",")}`),n}get queryParameters(){const{channelGroups:e,includeUUIDs:t,includeState:s,limit:n,offset:i,queryParameters:r}=this.parameters;return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},this.operation()===K.PNHereNowOperation?{limit:n}:{}),this.operation()===K.PNHereNowOperation&&null!=i&&i?{offset:i}:{}),t?{}:{disable_uuids:"1"}),null!=s&&s?{state:"1"}:{}),e&&e.length>0?{"channel-group":e.join(",")}:{}),r)}}class Ht extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNDeleteMessagesOperation}validate(){return this.parameters.keySet.subscribeKey?this.parameters.channel?void 0:"Missing channel":"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v3/history/sub-key/${e}/channel/${C(t)}`}get queryParameters(){const{start:e,end:t}=this.parameters;return Object.assign(Object.assign({},e?{start:e}:{}),t?{end:t}:{})}}class Bt extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNMessageCounts}validate(){const{keySet:{subscribeKey:e},channels:t,timetoken:s,channelTimetokens:n}=this.parameters;return e?t?s&&n?"`timetoken` and `channelTimetokens` are incompatible together":s||n?n&&n.length>1&&n.length!==t.length?"Length of `channelTimetokens` and `channels` do not match":void 0:"`timetoken` or `channelTimetokens` need to be set":"Missing channels":"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){return{channels:this.deserializeResponse(e).channels}}))}get path(){return`/v3/history/sub-key/${this.parameters.keySet.subscribeKey}/message-counts/${P(this.parameters.channels)}`}get queryParameters(){let{channelTimetokens:e}=this.parameters;return this.parameters.timetoken&&(e=[this.parameters.timetoken]),Object.assign(Object.assign({},1===e.length?{timetoken:e[0]}:{}),e.length>1?{channelsTimetoken:e.join(",")}:{})}}class Wt extends pe{constructor(e){var t,s,n;super(),this.parameters=e,e.count?e.count=Math.min(e.count,100):e.count=100,null!==(t=e.stringifiedTimeToken)&&void 0!==t||(e.stringifiedTimeToken=false),null!==(s=e.includeMeta)&&void 0!==s||(e.includeMeta=false),null!==(n=e.logVerbosity)&&void 0!==n||(e.logVerbosity=false)}operation(){return K.PNHistoryOperation}validate(){return this.parameters.keySet.subscribeKey?this.parameters.channel?void 0:"Missing channel":"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e),s=t[0],n=t[1],i=t[2];return Array.isArray(s)?{messages:s.map((e=>{const t=this.processPayload(e.message),s={entry:t.payload,timetoken:e.timetoken};return t.error&&(s.error=t.error),e.meta&&(s.meta=e.meta),s})),startTimeToken:n,endTimeToken:i}:{messages:[],startTimeToken:n,endTimeToken:i}}))}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v2/history/sub-key/${e}/channel/${C(t)}`}get queryParameters(){const{start:e,end:t,reverse:s,count:n,stringifiedTimeToken:i,includeMeta:r}=this.parameters;return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({count:n,include_token:"true"},e?{start:e}:{}),t?{end:t}:{}),i?{string_message_token:"true"}:{}),null!=s?{reverse:s.toString()}:{}),r?{include_meta:"true"}:{})}processPayload(e){const{crypto:t,logVerbosity:s}=this.parameters;if(!t||"string"!=typeof e)return{payload:e};let n,i;try{const s=t.decrypt(e);n=s instanceof ArrayBuffer?JSON.parse(Wt.decoder.decode(s)):s}catch(t){s&&console.log("decryption error",t.message),n=e,i=`Error while decrypting message content: ${t.message}`}return{payload:n,error:i}}}var Vt;!function(e){e[e.Message=-1]="Message",e[e.Files=4]="Files"}(Vt||(Vt={}));class zt extends pe{constructor(e){var t,s,n,i,r;super(),this.parameters=e;const a=null!==(t=e.includeMessageActions)&&void 0!==t&&t,o=e.channels.length>1||a?25:100;e.count?e.count=Math.min(e.count,o):e.count=o,e.includeUuid?e.includeUUID=e.includeUuid:null!==(s=e.includeUUID)&&void 0!==s||(e.includeUUID=true),null!==(n=e.stringifiedTimeToken)&&void 0!==n||(e.stringifiedTimeToken=false),null!==(i=e.includeMessageType)&&void 0!==i||(e.includeMessageType=true),null!==(r=e.logVerbosity)&&void 0!==r||(e.logVerbosity=false)}operation(){return K.PNFetchMessagesOperation}validate(){const{keySet:{subscribeKey:e},channels:t,includeMessageActions:s}=this.parameters;return e?t?void 0!==s&&s&&t.length>1?"History can return actions data for a single channel only. Either pass a single channel or disable the includeMessageActions flag.":void 0:"Missing channels":"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){var t;const s=this.deserializeResponse(e),n=null!==(t=s.channels)&&void 0!==t?t:{},i={};return Object.keys(n).forEach((e=>{i[e]=n[e].map((t=>{null===t.message_type&&(t.message_type=Vt.Message);const s=this.processPayload(e,t),n=Object.assign(Object.assign({channel:e,timetoken:t.timetoken,message:s.payload,messageType:t.message_type},t.custom_message_type?{customMessageType:t.custom_message_type}:{}),{uuid:t.uuid});if(t.actions){const e=n;e.actions=t.actions,e.data=t.actions}return t.meta&&(n.meta=t.meta),s.error&&(n.error=s.error),n}))})),s.more?{channels:i,more:s.more}:{channels:i}}))}get path(){const{keySet:{subscribeKey:e},channels:t,includeMessageActions:s}=this.parameters;return`/v3/${s?"history-with-actions":"history"}/sub-key/${e}/channel/${P(t)}`}get queryParameters(){const{start:e,end:t,count:s,includeCustomMessageType:n,includeMessageType:i,includeMeta:r,includeUUID:a,stringifiedTimeToken:o}=this.parameters;return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({max:s},e?{start:e}:{}),t?{end:t}:{}),o?{string_message_token:"true"}:{}),void 0!==r&&r?{include_meta:"true"}:{}),a?{include_uuid:"true"}:{}),null!=n?{include_custom_message_type:n?"true":"false"}:{}),i?{include_message_type:"true"}:{})}processPayload(e,t){const{crypto:s,logVerbosity:n}=this.parameters;if(!s||"string"!=typeof t.message)return{payload:t.message};let i,r;try{const e=s.decrypt(t.message);i=e instanceof ArrayBuffer?JSON.parse(zt.decoder.decode(e)):e}catch(e){n&&console.log("decryption error",e.message),i=t.message,r=`Error while decrypting message content: ${e.message}`}if(!r&&i&&t.message_type==Vt.Files&&"object"==typeof i&&this.isFileMessage(i)){const t=i;return{payload:{message:t.message,file:Object.assign(Object.assign({},t.file),{url:this.parameters.getFileUrl({channel:e,id:t.file.id,name:t.file.name})})},error:r}}return{payload:i,error:r}}isFileMessage(e){return void 0!==e.file}}class Jt extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNGetMessageActionsOperation}validate(){return this.parameters.keySet.subscribeKey?this.parameters.channel?void 0:"Missing message channel":"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);let s=null,n=null;return t.data.length>0&&(s=t.data[0].actionTimetoken,n=t.data[t.data.length-1].actionTimetoken),{data:t.data,more:t.more,start:s,end:n}}))}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v1/message-actions/${e}/channel/${C(t)}`}get queryParameters(){const{limit:e,start:t,end:s}=this.parameters;return Object.assign(Object.assign(Object.assign({},t?{start:t}:{}),s?{end:s}:{}),e?{limit:e}:{})}}class Xt extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNAddMessageActionOperation}validate(){const{keySet:{subscribeKey:e},action:t,channel:s,messageTimetoken:n}=this.parameters;return e?s?n?t?t.value?t.type?t.type.length>15?"Action.type value exceed maximum length of 15":void 0:"Missing Action.type":"Missing Action.value":"Missing Action":"Missing message timetoken":"Missing message channel":"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((({data:e})=>({data:e})))}))}get path(){const{keySet:{subscribeKey:e},channel:t,messageTimetoken:s}=this.parameters;return`/v1/message-actions/${e}/channel/${C(t)}/message/${s}`}get headers(){var e;return Object.assign(Object.assign({},null!==(e=super.headers)&&void 0!==e?e:{}),{"Content-Type":"application/json"})}get body(){return JSON.stringify(this.parameters.action)}}class Qt extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveMessageActionOperation}validate(){const{keySet:{subscribeKey:e},channel:t,messageTimetoken:s,actionTimetoken:n}=this.parameters;return e?t?s?n?void 0:"Missing action timetoken":"Missing message timetoken":"Missing message action channel":"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((({data:e})=>({data:e})))}))}get path(){const{keySet:{subscribeKey:e},channel:t,actionTimetoken:s,messageTimetoken:n}=this.parameters;return`/v1/message-actions/${e}/channel/${C(t)}/message/${n}/action/${s}`}}class Yt extends pe{constructor(e){var t,s;super(),this.parameters=e,null!==(t=(s=this.parameters).storeInHistory)&&void 0!==t||(s.storeInHistory=true)}operation(){return K.PNPublishFileMessageOperation}validate(){const{channel:e,fileId:t,fileName:s}=this.parameters;return e?t?s?void 0:"file name can't be empty":"file id can't be empty":"channel can't be empty"}parse(e){return r(this,void 0,void 0,(function*(){return{timetoken:this.deserializeResponse(e)[2]}}))}get path(){const{message:e,channel:t,keySet:{publishKey:s,subscribeKey:n},fileId:i,fileName:r}=this.parameters,a=Object.assign({file:{name:r,id:i}},e?{message:e}:{});return`/v1/files/publish-file/${s}/${n}/0/${C(t)}/0/${C(this.prepareMessagePayload(a))}`}get queryParameters(){const{customMessageType:e,storeInHistory:t,ttl:s,meta:n}=this.parameters;return Object.assign(Object.assign(Object.assign({store:t?"1":"0"},e?{custom_message_type:e}:{}),s?{ttl:s}:{}),n&&"object"==typeof n?{meta:JSON.stringify(n)}:{})}prepareMessagePayload(e){const{crypto:t}=this.parameters;if(!t)return JSON.stringify(e)||"";const s=t.encrypt(JSON.stringify(e));return JSON.stringify("string"==typeof s?s:u(s))}}class Zt extends pe{constructor(e){super({method:ue.LOCAL}),this.parameters=e}operation(){return K.PNGetFileUrlOperation}validate(){const{channel:e,id:t,name:s}=this.parameters;return e?t?s?void 0:"file name can't be empty":"file id can't be empty":"channel can't be empty"}parse(e){return r(this,void 0,void 0,(function*(){return e.url}))}get path(){const{channel:e,id:t,name:s,keySet:{subscribeKey:n}}=this.parameters;return`/v1/files/${n}/channels/${C(e)}/files/${C(t)}/${C(s)}`}}class es extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNDeleteFileOperation}validate(){const{channel:e,id:t,name:s}=this.parameters;return e?t?s?void 0:"file name can't be empty":"file id can't be empty":"channel can't be empty"}get path(){const{keySet:{subscribeKey:e},id:t,channel:s,name:n}=this.parameters;return`/v1/files/${e}/channels/${C(s)}/files/${C(t)}/${C(n)}`}}class ts extends pe{constructor(e){var t,s;super(),this.parameters=e,null!==(t=(s=this.parameters).limit)&&void 0!==t||(s.limit=100)}operation(){return K.PNListFilesOperation}validate(){if(!this.parameters.channel)return"channel can't be empty"}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v1/files/${e}/channels/${C(t)}/files`}get queryParameters(){const{limit:e,next:t}=this.parameters;return Object.assign({limit:e},t?{next:t}:{})}}class ss extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNGenerateUploadUrlOperation}validate(){return this.parameters.channel?this.parameters.name?void 0:"'name' can't be empty":"channel can't be empty"}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return{id:t.data.id,name:t.data.name,url:t.file_upload_request.url,formFields:t.file_upload_request.form_fields}}))}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v1/files/${e}/channels/${C(t)}/generate-upload-url`}get headers(){var e;return Object.assign(Object.assign({},null!==(e=super.headers)&&void 0!==e?e:{}),{"Content-Type":"application/json"})}get body(){return JSON.stringify({name:this.parameters.name})}}class ns extends pe{constructor(e){super({method:ue.POST}),this.parameters=e;const t=e.file.mimeType;t&&(e.formFields=e.formFields.map((e=>"Content-Type"===e.name?{name:e.name,value:t}:e)))}operation(){return K.PNPublishFileOperation}validate(){const{fileId:e,fileName:t,file:s,uploadUrl:n}=this.parameters;return e?t?s?n?void 0:"Validation failed: file upload 'url' can't be empty":"Validation failed: 'file' can't be empty":"Validation failed: file 'name' can't be empty":"Validation failed: file 'id' can't be empty"}parse(e){return r(this,void 0,void 0,(function*(){return{status:e.status,message:e.body?ns.decoder.decode(e.body):"OK"}}))}request(){return Object.assign(Object.assign({},super.request()),{origin:new URL(this.parameters.uploadUrl).origin,timeout:300})}get path(){const{pathname:e,search:t}=new URL(this.parameters.uploadUrl);return`${e}${t}`}get body(){return this.parameters.file}get formData(){return this.parameters.formFields}}class is{constructor(e){var t;if(this.parameters=e,this.file=null===(t=this.parameters.PubNubFile)||void 0===t?void 0:t.create(e.file),!this.file)throw new Error("File upload error: unable to create File object.")}process(){return r(this,void 0,void 0,(function*(){let e,t;return this.generateFileUploadUrl().then((s=>(e=s.name,t=s.id,this.uploadFile(s)))).then((e=>{if(204!==e.status)throw new d("Upload to bucket was unsuccessful",{error:!0,statusCode:e.status,category:h.PNUnknownCategory,operation:K.PNPublishFileOperation,errorData:{message:e.message}})})).then((()=>this.publishFileMessage(t,e))).catch((e=>{if(e instanceof d)throw e;const t=e instanceof G?e:G.create(e);throw new d("File upload error.",t.toStatus(K.PNPublishFileOperation))}))}))}generateFileUploadUrl(){return r(this,void 0,void 0,(function*(){const e=new ss(Object.assign(Object.assign({},this.parameters),{name:this.file.name,keySet:this.parameters.keySet}));return this.parameters.sendRequest(e)}))}uploadFile(e){return r(this,void 0,void 0,(function*(){const{cipherKey:t,PubNubFile:s,crypto:n,cryptography:i}=this.parameters,{id:r,name:a,url:o,formFields:c}=e;return this.parameters.PubNubFile.supportsEncryptFile&&(!t&&n?this.file=yield n.encryptFile(this.file,s):t&&i&&(this.file=yield i.encryptFile(t,this.file,s))),this.parameters.sendRequest(new ns({fileId:r,fileName:a,file:this.file,uploadUrl:o,formFields:c}))}))}publishFileMessage(e,t){return r(this,void 0,void 0,(function*(){var s,n,i,r;let a,o={timetoken:"0"},c=this.parameters.fileUploadPublishRetryLimit,u=!1;do{try{o=yield this.parameters.publishFile(Object.assign(Object.assign({},this.parameters),{fileId:e,fileName:t})),u=!0}catch(e){e instanceof d&&(a=e),c-=1}}while(!u&&c>0);if(u)return{status:200,timetoken:o.timetoken,id:e,name:t};throw new d("Publish failed. You may want to execute that operation manually using pubnub.publishFile",{error:!0,category:null!==(n=null===(s=a.status)||void 0===s?void 0:s.category)&&void 0!==n?n:h.PNUnknownCategory,statusCode:null!==(r=null===(i=a.status)||void 0===i?void 0:i.statusCode)&&void 0!==r?r:0,channel:this.parameters.channel,id:e,name:t})}))}}class rs{constructor(e,t){this.subscriptionStateIds=[],this.client=t,this._nameOrId=e}get entityType(){return"Channel"}get subscriptionType(){return _t.Channel}subscriptionNames(e){return[this._nameOrId,...e&&!this._nameOrId.endsWith("-pnpres")?[`${this._nameOrId}-pnpres`]:[]]}subscription(e){return new $t({client:this.client,entity:this,options:e})}get subscriptionsCount(){return this.subscriptionStateIds.length}increaseSubscriptionCount(e){this.subscriptionStateIds.includes(e)||this.subscriptionStateIds.push(e)}decreaseSubscriptionCount(e){{const t=this.subscriptionStateIds.indexOf(e);t>=0&&this.subscriptionStateIds.splice(t,1)}}toString(){return`${this.entityType} { nameOrId: ${this._nameOrId}, subscriptionsCount: ${this.subscriptionsCount} }`}}const as=["default","__default__"],os=e=>{if(!e)return;const t=e.trim();return 0===t.length||as.includes(t.toLowerCase())?void 0:t};class cs extends rs{constructor(e,t,s){super(e,t),this._projection=os(s)}get id(){return this._nameOrId}get projection(){return this._projection}get subscriptionChannel(){return this._projection?`__${this._projection}__${this._nameOrId}`:this._nameOrId}subscriptionNames(e){return[this.subscriptionChannel]}subscription(e){{const t=this.entityForProjection(os(null==e?void 0:e.projection));return t!==this?t.subscription(e):super.subscription(e)}}entityForProjection(e){var t,s,n,i;if(e===this._projection)return this;const r=null!==(t=this.variants)&&void 0!==t?t:this.variants={};null!==(n=r[i=null!==(s=this._projection)&&void 0!==s?s:""])&&void 0!==n||(r[i]=this);const a=null!=e?e:"";let o=r[a];return o||(o=r[a]=this.withProjection(e),o.variants=r),o}toString(){var e;return`${this.entityType} { id: ${this._nameOrId}, projection: ${null!==(e=this._projection)&&void 0!==e?e:"none"}, channel: ${this.subscriptionChannel}, subscriptionsCount: ${this.subscriptionsCount} }`}}class us extends cs{get entityType(){return"DataSyncRelationship"}withProjection(e){return new us(this._nameOrId,this.client,e)}}class ls extends cs{get entityType(){return"DataSyncMembership"}withProjection(e){return new ls(this._nameOrId,this.client,e)}}class hs extends cs{get entityType(){return"DataSyncChannel"}withProjection(e){return new hs(this._nameOrId,this.client,e)}}class ds extends cs{get entityType(){return"DataSyncEntity"}withProjection(e){return new ds(this._nameOrId,this.client,e)}}class ps extends rs{get entityType(){return"ChannelMetadata"}get id(){return this._nameOrId}subscriptionNames(e){return[this.id]}}class gs extends cs{get entityType(){return"DataSyncUser"}withProjection(e){return new gs(this._nameOrId,this.client,e)}}class bs extends rs{get entityType(){return"ChannelGroups"}get name(){return this._nameOrId}get subscriptionType(){return _t.ChannelGroup}}class ys extends rs{get entityType(){return"UserMetadata"}get id(){return this._nameOrId}subscriptionNames(e){return[this.id]}}class ms extends rs{get entityType(){return"Channel"}get name(){return this._nameOrId}}class fs extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNRemoveChannelsFromGroupOperation}validate(){const{keySet:{subscribeKey:e},channels:t,channelGroup:s}=this.parameters;return e?s?t?void 0:"Missing channels":"Missing Channel Group":"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}get path(){const{keySet:{subscribeKey:e},channelGroup:t}=this.parameters;return`/v1/channel-registration/sub-key/${e}/channel-group/${C(t)}`}get queryParameters(){return{remove:this.parameters.channels.join(",")}}}class vs extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNAddChannelsToGroupOperation}validate(){const{keySet:{subscribeKey:e},channels:t,channelGroup:s}=this.parameters;return e?s?t?void 0:"Missing channels":"Missing Channel Group":"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}get path(){const{keySet:{subscribeKey:e},channelGroup:t}=this.parameters;return`/v1/channel-registration/sub-key/${e}/channel-group/${C(t)}`}get queryParameters(){return{add:this.parameters.channels.join(",")}}}class Os extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNChannelsForGroupOperation}validate(){return this.parameters.keySet.subscribeKey?this.parameters.channelGroup?void 0:"Missing Channel Group":"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){return{channels:this.deserializeResponse(e).payload.channels}}))}get path(){const{keySet:{subscribeKey:e},channelGroup:t}=this.parameters;return`/v1/channel-registration/sub-key/${e}/channel-group/${C(t)}`}}class Ss extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNRemoveGroupOperation}validate(){return this.parameters.keySet.subscribeKey?this.parameters.channelGroup?void 0:"Missing Channel Group":"Missing Subscribe Key"}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}get path(){const{keySet:{subscribeKey:e},channelGroup:t}=this.parameters;return`/v1/channel-registration/sub-key/${e}/channel-group/${C(t)}/remove`}}class js extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNChannelGroupsOperation}validate(){if(!this.parameters.keySet.subscribeKey)return"Missing Subscribe Key"}parse(e){return r(this,void 0,void 0,(function*(){return{groups:this.deserializeResponse(e).payload.groups}}))}get path(){return`/v1/channel-registration/sub-key/${this.parameters.keySet.subscribeKey}/channel-group`}}class ws{constructor(e,t,s){this.sendRequest=s,this.logger=e,this.keySet=t}listChannels(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"List channel group channels with parameters:"})));const s=new Os(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=e=>{e&&this.logger.debug("PubNub",`List channel group channels success. Received ${e.channels.length} channels.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}listGroups(e){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub","List all channel groups.");const t=new js({keySet:this.keySet}),s=e=>{e&&this.logger.debug("PubNub",`List all channel groups success. Received ${e.groups.length} groups.`)};return e?this.sendRequest(t,((t,n)=>{s(n),e(t,n)})):this.sendRequest(t).then((e=>(s(e),e)))}))}addChannels(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Add channels to the channel group with parameters:"})));const s=new vs(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=()=>{this.logger.debug("PubNub","Add channels to the channel group success.")};return t?this.sendRequest(s,(e=>{e.error||n(),t(e)})):this.sendRequest(s).then((e=>(n(),e)))}))}removeChannels(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove channels from the channel group with parameters:"})));const s=new fs(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=()=>{this.logger.debug("PubNub","Remove channels from the channel group success.")};return t?this.sendRequest(s,(e=>{e.error||n(),t(e)})):this.sendRequest(s).then((e=>(n(),e)))}))}deleteGroup(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove a channel group with parameters:"})));const s=new Ss(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=()=>{this.logger.debug("PubNub",`Remove a channel group success. Removed '${e.channelGroup}' channel group.'`)};return t?this.sendRequest(s,(e=>{e.error||n(),t(e)})):this.sendRequest(s).then((e=>(n(),e)))}))}}class ks extends pe{constructor(e){var t,s;super(),this.parameters=e,"apns2"===this.parameters.pushGateway&&(null!==(t=(s=this.parameters).environment)&&void 0!==t||(s.environment="development")),this.parameters.count&&this.parameters.count>1e3&&(this.parameters.count=1e3)}operation(){throw Error("Should be implemented in subclass.")}validate(){const{keySet:{subscribeKey:e},action:t,device:s,pushGateway:n}=this.parameters;return e?s?"add"!==t&&"remove"!==t||"channels"in this.parameters&&0!==this.parameters.channels.length?n?"apns2"!==this.parameters.pushGateway||this.parameters.topic?void 0:"Missing APNS2 topic":"Missing GW Type (pushGateway: fcm or apns2)":"Missing Channels":"Missing Device ID (device)":"Missing Subscribe Key"}get path(){const{keySet:{subscribeKey:e},action:t,device:s,pushGateway:n}=this.parameters;let i="apns2"===n?`/v2/push/sub-key/${e}/devices-apns2/${s}`:`/v1/push/sub-key/${e}/devices/${s}`;return"remove-device"===t&&(i=`${i}/remove`),i}get queryParameters(){const{start:e,count:t}=this.parameters;let s=Object.assign(Object.assign({type:this.parameters.pushGateway},e?{start:e}:{}),t&&t>0?{count:t}:{});if("channels"in this.parameters&&(s[this.parameters.action]=this.parameters.channels.join(",")),"apns2"===this.parameters.pushGateway){const{environment:e,topic:t}=this.parameters;s=Object.assign(Object.assign({},s),{environment:e,topic:t})}return s}}class Cs extends ks{constructor(e){super(Object.assign(Object.assign({},e),{action:"remove"}))}operation(){return K.PNRemovePushNotificationEnabledChannelsOperation}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}}class Ps extends ks{constructor(e){super(Object.assign(Object.assign({},e),{action:"list"}))}operation(){return K.PNPushNotificationEnabledChannelsOperation}parse(e){return r(this,void 0,void 0,(function*(){return{channels:this.deserializeResponse(e)}}))}}class Ns extends ks{constructor(e){super(Object.assign(Object.assign({},e),{action:"add"}))}operation(){return K.PNAddPushNotificationEnabledChannelsOperation}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}}class Es extends ks{constructor(e){super(Object.assign(Object.assign({},e),{action:"remove-device"}))}operation(){return K.PNRemoveAllPushNotificationsOperation}parse(e){const t=Object.create(null,{parse:{get:()=>super.parse}});return r(this,void 0,void 0,(function*(){return t.parse.call(this,e).then((e=>({})))}))}}class Ts{constructor(e,t,s){this.sendRequest=s,this.logger=e,this.keySet=t}listChannels(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"List push-enabled channels with parameters:"})));const s=new Ps(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=e=>{e&&this.logger.debug("PubNub",`List push-enabled channels success. Received ${e.channels.length} channels.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}addChannels(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Add push-enabled channels with parameters:"})));const s=new Ns(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=()=>{this.logger.debug("PubNub","Add push-enabled channels success.")};return t?this.sendRequest(s,(e=>{e.error||n(),t(e)})):this.sendRequest(s).then((e=>(n(),e)))}))}removeChannels(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove push-enabled channels with parameters:"})));const s=new Cs(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=()=>{this.logger.debug("PubNub","Remove push-enabled channels success.")};return t?this.sendRequest(s,(e=>{e.error||n(),t(e)})):this.sendRequest(s).then((e=>(n(),e)))}))}deleteDevice(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove push notifications for device with parameters:"})));const s=new Es(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=()=>{this.logger.debug("PubNub","Remove push notifications for device success.")};return t?this.sendRequest(s,(e=>{e.error||n(),t(e)})):this.sendRequest(s).then((e=>(n(),e)))}))}}class _s extends pe{constructor(e){var t,s,n,i,r,a;super(),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(r=e.include).customFields)&&void 0!==s||(r.customFields=false),null!==(n=(a=e.include).totalCount)&&void 0!==n||(a.totalCount=false),null!==(i=e.limit)&&void 0!==i||(e.limit=100)}operation(){return K.PNGetAllChannelMetadataOperation}get path(){return`/v2/objects/${this.parameters.keySet.subscribeKey}/channels`}get queryParameters(){const{include:e,page:t,filter:s,sort:n,limit:i}=this.parameters;let r="";return r="string"==typeof n?n:Object.entries(null!=n?n:{}).map((([e,t])=>null!==t?`${e}:${t}`:e)),Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({include:["status","type",...e.customFields?["custom"]:[]].join(","),count:`${e.totalCount}`},s?{filter:s}:{}),(null==t?void 0:t.next)?{start:t.next}:{}),(null==t?void 0:t.prev)?{end:t.prev}:{}),i?{limit:i}:{}),r.length?{sort:r}:{})}}class Is extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveChannelMetadataOperation}validate(){if(!this.parameters.channel)return"Channel cannot be empty"}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v2/objects/${e}/channels/${C(t)}`}}class Ms extends pe{constructor(e){var t,s,n,i,r,a,o,c,u,l,h,d,p,g,b,y,m,f;super(),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(h=e.include).customFields)&&void 0!==s||(h.customFields=false),null!==(n=(d=e.include).totalCount)&&void 0!==n||(d.totalCount=false),null!==(i=(p=e.include).statusField)&&void 0!==i||(p.statusField=false),null!==(r=(g=e.include).typeField)&&void 0!==r||(g.typeField=false),null!==(a=(b=e.include).channelFields)&&void 0!==a||(b.channelFields=false),null!==(o=(y=e.include).customChannelFields)&&void 0!==o||(y.customChannelFields=false),null!==(c=(m=e.include).channelStatusField)&&void 0!==c||(m.channelStatusField=false),null!==(u=(f=e.include).channelTypeField)&&void 0!==u||(f.channelTypeField=false),null!==(l=e.limit)&&void 0!==l||(e.limit=100),this.parameters.userId&&(this.parameters.uuid=this.parameters.userId)}operation(){return K.PNGetMembershipsOperation}validate(){if(!this.parameters.uuid)return"'uuid' cannot be empty"}get path(){const{keySet:{subscribeKey:e},uuid:t}=this.parameters;return`/v2/objects/${e}/uuids/${C(t)}/channels`}get queryParameters(){const{include:e,page:t,filter:s,sort:n,limit:i}=this.parameters;let r="";r="string"==typeof n?n:Object.entries(null!=n?n:{}).map((([e,t])=>null!==t?`${e}:${t}`:e));const a=[];return e.statusField&&a.push("status"),e.typeField&&a.push("type"),e.customFields&&a.push("custom"),e.channelFields&&a.push("channel"),e.channelStatusField&&a.push("channel.status"),e.channelTypeField&&a.push("channel.type"),e.customChannelFields&&a.push("channel.custom"),Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({count:`${e.totalCount}`},a.length>0?{include:a.join(",")}:{}),s?{filter:s}:{}),(null==t?void 0:t.next)?{start:t.next}:{}),(null==t?void 0:t.prev)?{end:t.prev}:{}),i?{limit:i}:{}),r.length?{sort:r}:{})}}class Rs extends pe{constructor(e){var t,s,n,i,r,a,o,c,u,l,h,d,p,g,b,y,m,f;super({method:ue.PATCH}),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(h=e.include).customFields)&&void 0!==s||(h.customFields=false),null!==(n=(d=e.include).totalCount)&&void 0!==n||(d.totalCount=false),null!==(i=(p=e.include).statusField)&&void 0!==i||(p.statusField=false),null!==(r=(g=e.include).typeField)&&void 0!==r||(g.typeField=false),null!==(a=(b=e.include).channelFields)&&void 0!==a||(b.channelFields=false),null!==(o=(y=e.include).customChannelFields)&&void 0!==o||(y.customChannelFields=false),null!==(c=(m=e.include).channelStatusField)&&void 0!==c||(m.channelStatusField=false),null!==(u=(f=e.include).channelTypeField)&&void 0!==u||(f.channelTypeField=false),null!==(l=e.limit)&&void 0!==l||(e.limit=100),this.parameters.userId&&(this.parameters.uuid=this.parameters.userId)}operation(){return K.PNSetMembershipsOperation}validate(){const{uuid:e,channels:t}=this.parameters;return e?t&&0!==t.length?void 0:"Channels cannot be empty":"'uuid' cannot be empty"}get path(){const{keySet:{subscribeKey:e},uuid:t}=this.parameters;return`/v2/objects/${e}/uuids/${C(t)}/channels`}get queryParameters(){const{include:e,page:t,filter:s,sort:n,limit:i}=this.parameters;let r="";r="string"==typeof n?n:Object.entries(null!=n?n:{}).map((([e,t])=>null!==t?`${e}:${t}`:e));const a=["channel.status","channel.type","status"];return e.statusField&&a.push("status"),e.typeField&&a.push("type"),e.customFields&&a.push("custom"),e.channelFields&&a.push("channel"),e.channelStatusField&&a.push("channel.status"),e.channelTypeField&&a.push("channel.type"),e.customChannelFields&&a.push("channel.custom"),Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({count:`${e.totalCount}`},a.length>0?{include:a.join(",")}:{}),s?{filter:s}:{}),(null==t?void 0:t.next)?{start:t.next}:{}),(null==t?void 0:t.prev)?{end:t.prev}:{}),i?{limit:i}:{}),r.length?{sort:r}:{})}get headers(){var e;return Object.assign(Object.assign({},null!==(e=super.headers)&&void 0!==e?e:{}),{"Content-Type":"application/json"})}get body(){const{channels:e,type:t}=this.parameters;return JSON.stringify({[`${t}`]:e.map((e=>"string"==typeof e?{channel:{id:e}}:{channel:{id:e.id},status:e.status,type:e.type,custom:e.custom}))})}}class Ds extends pe{constructor(e){var t,s,n,i;super(),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(i=e.include).customFields)&&void 0!==s||(i.customFields=false),null!==(n=e.limit)&&void 0!==n||(e.limit=100)}operation(){return K.PNGetAllUUIDMetadataOperation}get path(){return`/v2/objects/${this.parameters.keySet.subscribeKey}/uuids`}get queryParameters(){const{include:e,page:t,filter:s,sort:n,limit:i}=this.parameters;let r="";return r="string"==typeof n?n:Object.entries(null!=n?n:{}).map((([e,t])=>null!==t?`${e}:${t}`:e)),Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({include:["status","type",...e.customFields?["custom"]:[]].join(",")},void 0!==e.totalCount?{count:`${e.totalCount}`}:{}),s?{filter:s}:{}),(null==t?void 0:t.next)?{start:t.next}:{}),(null==t?void 0:t.prev)?{end:t.prev}:{}),i?{limit:i}:{}),r.length?{sort:r}:{})}}class Us extends pe{constructor(e){var t,s,n;super(),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(n=e.include).customFields)&&void 0!==s||(n.customFields=true)}operation(){return K.PNGetChannelMetadataOperation}validate(){if(!this.parameters.channel)return"Channel cannot be empty"}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v2/objects/${e}/channels/${C(t)}`}get queryParameters(){return{include:["status","type",...this.parameters.include.customFields?["custom"]:[]].join(",")}}}class As extends pe{constructor(e){var t,s,n;super({method:ue.PATCH}),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(n=e.include).customFields)&&void 0!==s||(n.customFields=true)}operation(){return K.PNSetChannelMetadataOperation}validate(){return this.parameters.channel?this.parameters.data?void 0:"Data cannot be empty":"Channel cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json"})}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v2/objects/${e}/channels/${C(t)}`}get queryParameters(){return{include:["status","type",...this.parameters.include.customFields?["custom"]:[]].join(",")}}get body(){return JSON.stringify(this.parameters.data)}}class $s extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e,this.parameters.userId&&(this.parameters.uuid=this.parameters.userId)}operation(){return K.PNRemoveUUIDMetadataOperation}validate(){if(!this.parameters.uuid)return"'uuid' cannot be empty"}get path(){const{keySet:{subscribeKey:e},uuid:t}=this.parameters;return`/v2/objects/${e}/uuids/${C(t)}`}}class Fs extends pe{constructor(e){var t,s,n,i,r,a,o,c,u,l,h,d,p,g,b,y,m,f;super(),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(h=e.include).customFields)&&void 0!==s||(h.customFields=false),null!==(n=(d=e.include).totalCount)&&void 0!==n||(d.totalCount=false),null!==(i=(p=e.include).statusField)&&void 0!==i||(p.statusField=false),null!==(r=(g=e.include).typeField)&&void 0!==r||(g.typeField=false),null!==(a=(b=e.include).UUIDFields)&&void 0!==a||(b.UUIDFields=false),null!==(o=(y=e.include).customUUIDFields)&&void 0!==o||(y.customUUIDFields=false),null!==(c=(m=e.include).UUIDStatusField)&&void 0!==c||(m.UUIDStatusField=false),null!==(u=(f=e.include).UUIDTypeField)&&void 0!==u||(f.UUIDTypeField=false),null!==(l=e.limit)&&void 0!==l||(e.limit=100)}operation(){return K.PNSetMembersOperation}validate(){if(!this.parameters.channel)return"Channel cannot be empty"}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v2/objects/${e}/channels/${C(t)}/uuids`}get queryParameters(){const{include:e,page:t,filter:s,sort:n,limit:i}=this.parameters;let r="";r="string"==typeof n?n:Object.entries(null!=n?n:{}).map((([e,t])=>null!==t?`${e}:${t}`:e));const a=[];return e.statusField&&a.push("status"),e.typeField&&a.push("type"),e.customFields&&a.push("custom"),e.UUIDFields&&a.push("uuid"),e.UUIDStatusField&&a.push("uuid.status"),e.UUIDTypeField&&a.push("uuid.type"),e.customUUIDFields&&a.push("uuid.custom"),Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({count:`${e.totalCount}`},a.length>0?{include:a.join(",")}:{}),s?{filter:s}:{}),(null==t?void 0:t.next)?{start:t.next}:{}),(null==t?void 0:t.prev)?{end:t.prev}:{}),i?{limit:i}:{}),r.length?{sort:r}:{})}}class xs extends pe{constructor(e){var t,s,n,i,r,a,o,c,u,l,h,d,p,g,b,y,m,f;super({method:ue.PATCH}),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(h=e.include).customFields)&&void 0!==s||(h.customFields=false),null!==(n=(d=e.include).totalCount)&&void 0!==n||(d.totalCount=false),null!==(i=(p=e.include).statusField)&&void 0!==i||(p.statusField=false),null!==(r=(g=e.include).typeField)&&void 0!==r||(g.typeField=false),null!==(a=(b=e.include).UUIDFields)&&void 0!==a||(b.UUIDFields=false),null!==(o=(y=e.include).customUUIDFields)&&void 0!==o||(y.customUUIDFields=false),null!==(c=(m=e.include).UUIDStatusField)&&void 0!==c||(m.UUIDStatusField=false),null!==(u=(f=e.include).UUIDTypeField)&&void 0!==u||(f.UUIDTypeField=false),null!==(l=e.limit)&&void 0!==l||(e.limit=100)}operation(){return K.PNSetMembersOperation}validate(){const{channel:e,uuids:t}=this.parameters;return e?t&&0!==t.length?void 0:"UUIDs cannot be empty":"Channel cannot be empty"}get path(){const{keySet:{subscribeKey:e},channel:t}=this.parameters;return`/v2/objects/${e}/channels/${C(t)}/uuids`}get queryParameters(){const{include:e,page:t,filter:s,sort:n,limit:i}=this.parameters;let r="";r="string"==typeof n?n:Object.entries(null!=n?n:{}).map((([e,t])=>null!==t?`${e}:${t}`:e));const a=["uuid.status","uuid.type","type"];return e.statusField&&a.push("status"),e.typeField&&a.push("type"),e.customFields&&a.push("custom"),e.UUIDFields&&a.push("uuid"),e.UUIDStatusField&&a.push("uuid.status"),e.UUIDTypeField&&a.push("uuid.type"),e.customUUIDFields&&a.push("uuid.custom"),Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({count:`${e.totalCount}`},a.length>0?{include:a.join(",")}:{}),s?{filter:s}:{}),(null==t?void 0:t.next)?{start:t.next}:{}),(null==t?void 0:t.prev)?{end:t.prev}:{}),i?{limit:i}:{}),r.length?{sort:r}:{})}get headers(){var e;return Object.assign(Object.assign({},null!==(e=super.headers)&&void 0!==e?e:{}),{"Content-Type":"application/json"})}get body(){const{uuids:e,type:t}=this.parameters;return JSON.stringify({[`${t}`]:e.map((e=>"string"==typeof e?{uuid:{id:e}}:{uuid:{id:e.id},status:e.status,type:e.type,custom:e.custom}))})}}class qs extends pe{constructor(e){var t,s,n;super(),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(n=e.include).customFields)&&void 0!==s||(n.customFields=true),this.parameters.userId&&(this.parameters.uuid=this.parameters.userId)}operation(){return K.PNGetUUIDMetadataOperation}validate(){if(!this.parameters.uuid)return"'uuid' cannot be empty"}get path(){const{keySet:{subscribeKey:e},uuid:t}=this.parameters;return`/v2/objects/${e}/uuids/${C(t)}`}get queryParameters(){const{include:e}=this.parameters;return{include:["status","type",...e.customFields?["custom"]:[]].join(",")}}}class Gs extends pe{constructor(e){var t,s,n;super({method:ue.PATCH}),this.parameters=e,null!==(t=e.include)&&void 0!==t||(e.include={}),null!==(s=(n=e.include).customFields)&&void 0!==s||(n.customFields=true),this.parameters.userId&&(this.parameters.uuid=this.parameters.userId)}operation(){return K.PNSetUUIDMetadataOperation}validate(){return this.parameters.uuid?this.parameters.data?void 0:"Data cannot be empty":"'uuid' cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json"})}get path(){const{keySet:{subscribeKey:e},uuid:t}=this.parameters;return`/v2/objects/${e}/uuids/${C(t)}`}get queryParameters(){return{include:["status","type",...this.parameters.include.customFields?["custom"]:[]].join(",")}}get body(){return JSON.stringify(this.parameters.data)}}class Ls{constructor(e,t){this.keySet=e.keySet,this.configuration=e,this.sendRequest=t}get logger(){return this.configuration.logger()}getAllUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{},details:"Get all UUID metadata objects with parameters:"}))),this._getAllUUIDMetadata(e,t)}))}_getAllUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){const s=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0);const n=new Ds(Object.assign(Object.assign({},s),{keySet:this.keySet})),i=e=>{e&&this.logger.debug("PubNub",`Get all UUID metadata success. Received ${e.totalCount} UUID metadata objects.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}))}getUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{uuid:this.configuration.userId},details:`Get ${e&&"function"!=typeof e?"":" current"} UUID metadata object with parameters:`}))),this._getUUIDMetadata(e,t)}))}_getUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){var s;const n=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0),n.userId&&(this.logger.warn("PubNub","'userId' parameter is deprecated. Use 'uuid' instead."),n.uuid=n.userId),null!==(s=n.uuid)&&void 0!==s||(n.uuid=this.configuration.userId);const i=new qs(Object.assign(Object.assign({},n),{keySet:this.keySet})),r=e=>{e&&this.logger.debug("PubNub",`Get UUID metadata object success. Received '${n.uuid}' UUID metadata object.`)};return t?this.sendRequest(i,((e,s)=>{r(s),t(e,s)})):this.sendRequest(i).then((e=>(r(e),e)))}))}setUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set UUID metadata object with parameters:"}))),this._setUUIDMetadata(e,t)}))}_setUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){var s;e.userId&&(this.logger.warn("PubNub","'userId' parameter is deprecated. Use 'uuid' instead."),e.uuid=e.userId),null!==(s=e.uuid)&&void 0!==s||(e.uuid=this.configuration.userId);const n=new Gs(Object.assign(Object.assign({},e),{keySet:this.keySet})),i=t=>{t&&this.logger.debug("PubNub",`Set UUID metadata object success. Updated '${e.uuid}' UUID metadata object.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}))}removeUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{uuid:this.configuration.userId},details:`Remove${e&&"function"!=typeof e?"":" current"} UUID metadata object with parameters:`}))),this._removeUUIDMetadata(e,t)}))}_removeUUIDMetadata(e,t){return r(this,void 0,void 0,(function*(){var s;const n=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0),n.userId&&(this.logger.warn("PubNub","'userId' parameter is deprecated. Use 'uuid' instead."),n.uuid=n.userId),null!==(s=n.uuid)&&void 0!==s||(n.uuid=this.configuration.userId);const i=new $s(Object.assign(Object.assign({},n),{keySet:this.keySet})),r=e=>{e&&this.logger.debug("PubNub",`Remove UUID metadata object success. Removed '${n.uuid}' UUID metadata object.`)};return t?this.sendRequest(i,((e,s)=>{r(s),t(e,s)})):this.sendRequest(i).then((e=>(r(e),e)))}))}getAllChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{},details:"Get all Channel metadata objects with parameters:"}))),this._getAllChannelMetadata(e,t)}))}_getAllChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){const s=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0);const n=new _s(Object.assign(Object.assign({},s),{keySet:this.keySet})),i=e=>{e&&this.logger.debug("PubNub",`Get all Channel metadata objects success. Received ${e.totalCount} Channel metadata objects.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}))}getChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Channel metadata object with parameters:"}))),this._getChannelMetadata(e,t)}))}_getChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){const s=new Us(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=t=>{t&&this.logger.debug("PubNub",`Get Channel metadata object success. Received '${e.channel}' Channel metadata object.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}setChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set Channel metadata object with parameters:"}))),this._setChannelMetadata(e,t)}))}_setChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){const s=new As(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=t=>{t&&this.logger.debug("PubNub",`Set Channel metadata object success. Updated '${e.channel}' Channel metadata object.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}removeChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove Channel metadata object with parameters:"}))),this._removeChannelMetadata(e,t)}))}_removeChannelMetadata(e,t){return r(this,void 0,void 0,(function*(){const s=new Is(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=t=>{t&&this.logger.debug("PubNub",`Remove Channel metadata object success. Removed '${e.channel}' Channel metadata object.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}getChannelMembers(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get channel members with parameters:"})));const s=new Fs(Object.assign(Object.assign({},e),{keySet:this.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Get channel members success. Received ${e.totalCount} channel members.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}setChannelMembers(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set channel members with parameters:"})));const s=new xs(Object.assign(Object.assign({},e),{type:"set",keySet:this.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Set channel members success. There are ${e.totalCount} channel members now.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}removeChannelMembers(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove channel members with parameters:"})));const s=new xs(Object.assign(Object.assign({},e),{type:"delete",keySet:this.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Remove channel members success. There are ${e.totalCount} channel members now.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}))}getMemberships(e,t){return r(this,void 0,void 0,(function*(){var s;const n=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0),n.userId&&(this.logger.warn("PubNub","'userId' parameter is deprecated. Use 'uuid' instead."),n.uuid=n.userId),null!==(s=n.uuid)&&void 0!==s||(n.uuid=this.configuration.userId),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},n),details:"Get memberships with parameters:"})));const i=new Ms(Object.assign(Object.assign({},n),{keySet:this.keySet})),r=e=>{e&&this.logger.debug("PubNub",`Get memberships success. Received ${e.totalCount} memberships.`)};return t?this.sendRequest(i,((e,s)=>{r(s),t(e,s)})):this.sendRequest(i).then((e=>(r(e),e)))}))}setMemberships(e,t){return r(this,void 0,void 0,(function*(){var s;e.userId&&(this.logger.warn("PubNub","'userId' parameter is deprecated. Use 'uuid' instead."),e.uuid=e.userId),null!==(s=e.uuid)&&void 0!==s||(e.uuid=this.configuration.userId),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set memberships with parameters:"})));const n=new Rs(Object.assign(Object.assign({},e),{type:"set",keySet:this.keySet})),i=e=>{e&&this.logger.debug("PubNub",`Set memberships success. There are ${e.totalCount} memberships now.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}))}removeMemberships(e,t){return r(this,void 0,void 0,(function*(){var s;e.userId&&(this.logger.warn("PubNub","'userId' parameter is deprecated. Use 'uuid' instead."),e.uuid=e.userId),null!==(s=e.uuid)&&void 0!==s||(e.uuid=this.configuration.userId),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove memberships with parameters:"})));const n=new Rs(Object.assign(Object.assign({},e),{type:"delete",keySet:this.keySet})),i=e=>{e&&this.logger.debug("PubNub",`Remove memberships success. There are ${e.totalCount} memberships now.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}))}fetchMemberships(e,t){return r(this,void 0,void 0,(function*(){var s,n;if(this.logger.warn("PubNub","'fetchMemberships' is deprecated. Use 'pubnub.objects.getChannelMembers' or 'pubnub.objects.getMemberships' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Fetch memberships with parameters:"}))),"spaceId"in e){const n=e,i={channel:null!==(s=n.spaceId)&&void 0!==s?s:n.channel,filter:n.filter,limit:n.limit,page:n.page,include:Object.assign({},n.include),sort:n.sort?Object.fromEntries(Object.entries(n.sort).map((([e,t])=>[e.replace("user","uuid"),t]))):void 0},r=e=>({status:e.status,data:e.data.map((e=>({user:e.uuid,custom:e.custom,updated:e.updated,eTag:e.eTag}))),totalCount:e.totalCount,next:e.next,prev:e.prev});return t?this.getChannelMembers(i,((e,s)=>{t(e,s?r(s):s)})):this.getChannelMembers(i).then(r)}const i=e,r={uuid:null!==(n=i.userId)&&void 0!==n?n:i.uuid,filter:i.filter,limit:i.limit,page:i.page,include:Object.assign({},i.include),sort:i.sort?Object.fromEntries(Object.entries(i.sort).map((([e,t])=>[e.replace("space","channel"),t]))):void 0},a=e=>({status:e.status,data:e.data.map((e=>({space:e.channel,custom:e.custom,updated:e.updated,eTag:e.eTag}))),totalCount:e.totalCount,next:e.next,prev:e.prev});return t?this.getMemberships(r,((e,s)=>{t(e,s?a(s):s)})):this.getMemberships(r).then(a)}))}addMemberships(e,t){return r(this,void 0,void 0,(function*(){var s,n,i,r,a,o;if(this.logger.warn("PubNub","'addMemberships' is deprecated. Use 'pubnub.objects.setChannelMembers' or 'pubnub.objects.setMemberships' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Add memberships with parameters:"}))),"spaceId"in e){const r=e,a={channel:null!==(s=r.spaceId)&&void 0!==s?s:r.channel,uuids:null!==(i=null===(n=r.users)||void 0===n?void 0:n.map((e=>"string"==typeof e?e:{id:e.userId,custom:e.custom})))&&void 0!==i?i:r.uuids,limit:0};return t?this.setChannelMembers(a,t):this.setChannelMembers(a)}const c=e,u={uuid:null!==(r=c.userId)&&void 0!==r?r:c.uuid,channels:null!==(o=null===(a=c.spaces)||void 0===a?void 0:a.map((e=>"string"==typeof e?e:{id:e.spaceId,custom:e.custom})))&&void 0!==o?o:c.channels,limit:0};return t?this.setMemberships(u,t):this.setMemberships(u)}))}}class Ks extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNCreateDataSyncUserOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.data?void 0===this.parameters.data.classVersion||null===this.parameters.data.classVersion?"Entity class version cannot be empty":void 0:"User data cannot be empty"}get headers(){var e;const t=null!==(e=super.headers)&&void 0!==e?e:{};return Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.user+json;version=1"})}get path(){const{keySet:{subscribeKey:e}}=this.parameters;return`/v1/datasync/subkeys/${e}/users`}get body(){const{id:e,class:t,classLevel:s,data:n}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},void 0!==e?{id:e}:{}),void 0!==t?{entityClass:t}:{}),{entityClassVersion:n.classVersion}),void 0!==s?{entityClassLevel:s}:{}),void 0!==n.status?{status:n.status}:{}),void 0!==n.payload?{payload:n.payload}:{})})}}function Hs(e){return"string"==typeof e?e:Object.entries(null!=e?e:{}).map((([e,t])=>null!==t?`${e}:${t}`:e))}function Bs(e){const{add:t,replace:s,remove:n,move:i,copy:r,test:a}=e,o=[];if(t)for(const[e,s]of Object.entries(t))o.push({op:"add",path:e,value:s});if(s)for(const[e,t]of Object.entries(s))o.push({op:"replace",path:e,value:t});if(n)for(const e of n)o.push({op:"remove",path:e});if(i)for(const{from:e,path:t}of i)o.push({op:"move",from:e,path:t});if(r)for(const{from:e,path:t}of r)o.push({op:"copy",from:e,path:t});if(a)for(const[e,t]of Object.entries(a))o.push({op:"test",path:e,value:t});return o}class Ws extends pe{constructor(e){var t;super(),this.parameters=e,null!==(t=e.limit)&&void 0!==t||(e.limit=20)}operation(){return K.PNGetDataSyncUsersOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}get path(){return`/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/users`}get queryParameters(){const{class:e,classVersion:t,classLevel:s,cursor:n,limit:i,filter:r,filterFast:a,sort:o}=this.parameters,c=Hs(o);return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},e?{entity_class:e}:{}),void 0!==t?{entity_class_version:`${t}`}:{}),s?{entity_class_level:s}:{}),n?{cursor:n}:{}),i?{limit:`${i}`}:{}),r?{filter:r}:{}),a?{filter_fast:a}:{}),c.length?{sort:c}:{})}}class Vs extends pe{constructor(e){super({method:ue.PUT}),this.parameters=e}operation(){return K.PNSetDataSyncUserOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.id?this.parameters.data?void 0===this.parameters.data.classVersion||null===this.parameters.data.classVersion?"Entity class version cannot be empty":void 0:"User data cannot be empty":"User id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.user+json;version=1"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/users/${C(t)}`}get body(){const{data:e}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign({entityClassVersion:e.classVersion},void 0!==e.status?{status:e.status}:{}),void 0!==e.payload?{payload:e.payload}:{})})}}class zs extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveDataSyncUserOperation}validate(){if(!this.parameters.id)return"User id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.keys(t).length>0?t:void 0}parse(e){return r(this,void 0,void 0,(function*(){return{status:e.status}}))}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/users/${C(t)}`}}class Js extends pe{constructor(e){super({method:ue.PATCH}),this.parameters=e}operation(){return K.PNUpdateDataSyncUserOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"User id cannot be empty";const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=e&&Object.keys(e).length>0,o=t&&Object.keys(t).length>0,c=s&&s.length>0,u=n&&n.length>0,l=i&&i.length>0,h=r&&Object.keys(r).length>0;return a||o||c||u||l||h?void 0:"At least one of add, replace, remove, move, copy, or test must be provided"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json-patch+json"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/users/${C(t)}`}get body(){const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=Bs({add:e,replace:t,remove:s,move:n,copy:i,test:r});return JSON.stringify(a)}}class Xs extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNGetDataSyncUserOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"User id cannot be empty"}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/users/${C(t)}`}}class Qs extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNCreateDataSyncChannelOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.data?void 0===this.parameters.data.classVersion||null===this.parameters.data.classVersion?"Entity class version cannot be empty":void 0:"Channel data cannot be empty"}get headers(){var e;const t=null!==(e=super.headers)&&void 0!==e?e:{};return Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.channel+json;version=1"})}get path(){const{keySet:{subscribeKey:e}}=this.parameters;return`/v1/datasync/subkeys/${e}/channels`}get body(){const{id:e,class:t,classLevel:s,data:n}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},void 0!==e?{id:e}:{}),void 0!==t?{entityClass:t}:{}),{entityClassVersion:n.classVersion}),void 0!==s?{entityClassLevel:s}:{}),void 0!==n.status?{status:n.status}:{}),void 0!==n.payload?{payload:n.payload}:{})})}}class Ys extends pe{constructor(e){var t;super(),this.parameters=e,null!==(t=e.limit)&&void 0!==t||(e.limit=20)}operation(){return K.PNGetDataSyncChannelsOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}get path(){return`/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/channels`}get queryParameters(){const{class:e,classVersion:t,classLevel:s,cursor:n,limit:i,filter:r,filterFast:a,sort:o}=this.parameters,c=Hs(o);return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},e?{entity_class:e}:{}),void 0!==t?{entity_class_version:`${t}`}:{}),s?{entity_class_level:s}:{}),n?{cursor:n}:{}),i?{limit:`${i}`}:{}),r?{filter:r}:{}),a?{filter_fast:a}:{}),c.length?{sort:c}:{})}}class Zs extends pe{constructor(e){super({method:ue.PUT}),this.parameters=e}operation(){return K.PNSetDataSyncChannelOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.id?this.parameters.data?void 0===this.parameters.data.classVersion||null===this.parameters.data.classVersion?"Entity class version cannot be empty":void 0:"Channel data cannot be empty":"Channel id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.channel+json;version=1"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/channels/${C(t)}`}get body(){const{data:e}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign({entityClassVersion:e.classVersion},void 0!==e.status?{status:e.status}:{}),void 0!==e.payload?{payload:e.payload}:{})})}}class en extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveDataSyncChannelOperation}validate(){if(!this.parameters.id)return"Channel id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.keys(t).length>0?t:void 0}parse(e){return r(this,void 0,void 0,(function*(){return{status:e.status}}))}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/channels/${C(t)}`}}class tn extends pe{constructor(e){super({method:ue.PATCH}),this.parameters=e}operation(){return K.PNUpdateDataSyncChannelOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Channel id cannot be empty";const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=e&&Object.keys(e).length>0,o=t&&Object.keys(t).length>0,c=s&&s.length>0,u=n&&n.length>0,l=i&&i.length>0,h=r&&Object.keys(r).length>0;return a||o||c||u||l||h?void 0:"At least one of add, replace, remove, move, copy, or test must be provided"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json-patch+json"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/channels/${C(t)}`}get body(){const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=Bs({add:e,replace:t,remove:s,move:n,copy:i,test:r});return JSON.stringify(a)}}class sn extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNGetDataSyncChannelOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Channel id cannot be empty"}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/channels/${C(t)}`}}class nn extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNCreateDataSyncMembershipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.userId?this.parameters.channelId?this.parameters.data?this.parameters.data.classVersion?void 0:"Membership class version cannot be empty":"Membership data cannot be empty":"Channel id cannot be empty":"User id cannot be empty"}get headers(){var e;const t=null!==(e=super.headers)&&void 0!==e?e:{};return Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.membership+json;version=1"})}get path(){const{keySet:{subscribeKey:e}}=this.parameters;return`/v1/datasync/subkeys/${e}/memberships`}get body(){const{id:e,userId:t,channelId:s,data:n}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign(Object.assign(Object.assign({},void 0!==e?{id:e}:{}),{userId:t,channelId:s,relationshipClassVersion:n.classVersion}),void 0!==n.status?{status:n.status}:{}),void 0!==n.payload?{payload:n.payload}:{})})}}class rn extends pe{constructor(e){var t;super(),this.parameters=e,null!==(t=e.limit)&&void 0!==t||(e.limit=20)}operation(){return K.PNGetDataSyncMembershipsOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}get path(){return`/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/memberships`}get queryParameters(){const{userId:e,channelId:t,classVersion:s,cursor:n,limit:i,filter:r,filterFast:a,sort:o}=this.parameters,c=Hs(o);return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},e?{user_id:e}:{}),t?{channel_id:t}:{}),void 0!==s?{relationship_class_version:`${s}`}:{}),n?{cursor:n}:{}),i?{limit:`${i}`}:{}),r?{filter:r}:{}),a?{filter_fast:a}:{}),c.length?{sort:c}:{})}}class an extends pe{constructor(e){super({method:ue.PUT}),this.parameters=e}operation(){return K.PNSetDataSyncMembershipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.id?this.parameters.userId?this.parameters.channelId?this.parameters.data?this.parameters.data.classVersion?void 0:"Membership class version cannot be empty":"Membership data cannot be empty":"Channel id cannot be empty":"User id cannot be empty":"Membership id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.membership+json;version=1"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/memberships/${C(t)}`}get body(){const{userId:e,channelId:t,data:s}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign({userId:e,channelId:t,relationshipClassVersion:s.classVersion},void 0!==s.status?{status:s.status}:{}),void 0!==s.payload?{payload:s.payload}:{})})}}class on extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveDataSyncMembershipOperation}validate(){if(!this.parameters.id)return"Membership id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.keys(t).length>0?t:void 0}parse(e){return r(this,void 0,void 0,(function*(){return{status:e.status}}))}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/memberships/${C(t)}`}}class cn extends pe{constructor(e){super({method:ue.PATCH}),this.parameters=e}operation(){return K.PNUpdateDataSyncMembershipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Membership id cannot be empty";const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=e&&Object.keys(e).length>0,o=t&&Object.keys(t).length>0,c=s&&s.length>0,u=n&&n.length>0,l=i&&i.length>0,h=r&&Object.keys(r).length>0;return a||o||c||u||l||h?void 0:"At least one of add, replace, remove, move, copy, or test must be provided"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json-patch+json"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/memberships/${C(t)}`}get body(){const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=Bs({add:e,replace:t,remove:s,move:n,copy:i,test:r});return JSON.stringify(a)}}class un extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNGetDataSyncMembershipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Membership id cannot be empty"}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/memberships/${C(t)}`}}class ln extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNCreateDataSyncRelationshipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.entityAId?this.parameters.entityBId?this.parameters.class?this.parameters.data?this.parameters.data.classVersion?void 0:"Relationship class version cannot be empty":"Relationship data cannot be empty":"Relationship class cannot be empty":"Entity B id cannot be empty":"Entity A id cannot be empty"}get headers(){var e;const t=null!==(e=super.headers)&&void 0!==e?e:{};return Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.relationship+json;version=1"})}get path(){const{keySet:{subscribeKey:e}}=this.parameters;return`/v1/datasync/subkeys/${e}/relationships`}get body(){const{id:e,class:t,entityAId:s,entityBId:n,data:i}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign(Object.assign(Object.assign({},void 0!==e?{id:e}:{}),{entityAId:s,entityBId:n,relationshipClass:t,relationshipClassVersion:i.classVersion}),void 0!==i.status?{status:i.status}:{}),void 0!==i.payload?{payload:i.payload}:{})})}}class hn extends pe{constructor(e){var t;super(),this.parameters=e,null!==(t=e.limit)&&void 0!==t||(e.limit=20)}operation(){return K.PNGetDataSyncRelationshipsOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.class)return"Relationship class cannot be empty"}get path(){return`/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/relationships`}get queryParameters(){const{class:e,classVersion:t,entityAId:s,entityBId:n,cursor:i,limit:r,filter:a,filterFast:o,sort:c}=this.parameters,u=Hs(c);return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({relationship_class:e},void 0!==t?{relationship_class_version:`${t}`}:{}),s?{entity_a_id:s}:{}),n?{entity_b_id:n}:{}),i?{cursor:i}:{}),r?{limit:`${r}`}:{}),a?{filter:a}:{}),o?{filter_fast:o}:{}),u.length?{sort:u}:{})}}class dn extends pe{constructor(e){super({method:ue.PUT}),this.parameters=e}operation(){return K.PNSetDataSyncRelationshipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.id?this.parameters.entityAId?this.parameters.entityBId?this.parameters.data?this.parameters.data.classVersion?void 0:"Relationship class version cannot be empty":"Relationship data cannot be empty":"Entity B id cannot be empty":"Entity A id cannot be empty":"Relationship id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.relationship+json;version=1"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/relationships/${C(t)}`}get body(){const{entityAId:e,entityBId:t,data:s}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign({entityAId:e,entityBId:t,relationshipClassVersion:s.classVersion},void 0!==s.status?{status:s.status}:{}),void 0!==s.payload?{payload:s.payload}:{})})}}class pn extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveDataSyncRelationshipOperation}validate(){if(!this.parameters.id)return"Relationship id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.keys(t).length>0?t:void 0}parse(e){return r(this,void 0,void 0,(function*(){return{status:e.status}}))}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/relationships/${C(t)}`}}class gn extends pe{constructor(e){super({method:ue.PATCH}),this.parameters=e}operation(){return K.PNUpdateDataSyncRelationshipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Relationship id cannot be empty";const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=e&&Object.keys(e).length>0,o=t&&Object.keys(t).length>0,c=s&&s.length>0,u=n&&n.length>0,l=i&&i.length>0,h=r&&Object.keys(r).length>0;return a||o||c||u||l||h?void 0:"At least one of add, replace, remove, move, copy, or test must be provided"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json-patch+json"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/relationships/${C(t)}`}get body(){const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=Bs({add:e,replace:t,remove:s,move:n,copy:i,test:r});return JSON.stringify(a)}}class bn extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNGetDataSyncRelationshipOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Relationship id cannot be empty"}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/relationships/${C(t)}`}}class yn extends pe{constructor(e){super({method:ue.POST}),this.parameters=e}operation(){return K.PNCreateDataSyncEntityOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.class?this.parameters.data?void 0===this.parameters.data.classVersion||null===this.parameters.data.classVersion?"Entity class version cannot be empty":void 0:"Entity data cannot be empty":"Entity class cannot be empty"}get headers(){var e;const t=null!==(e=super.headers)&&void 0!==e?e:{};return Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.entity+json;version=1"})}get path(){const{keySet:{subscribeKey:e}}=this.parameters;return`/v1/datasync/subkeys/${e}/entities`}get body(){const{id:e,class:t,classLevel:s,data:n}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},void 0!==e?{id:e}:{}),{entityClass:t,entityClassVersion:n.classVersion}),void 0!==s?{entityClassLevel:s}:{}),void 0!==n.status?{status:n.status}:{}),void 0!==n.payload?{payload:n.payload}:{})})}}class mn extends pe{constructor(e){var t;super(),this.parameters=e,null!==(t=e.limit)&&void 0!==t||(e.limit=20)}operation(){return K.PNGetDataSyncEntitiesOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.class)return"Entity class cannot be empty"}get path(){return`/v1/datasync/subkeys/${this.parameters.keySet.subscribeKey}/entities`}get queryParameters(){const{class:e,classVersion:t,classLevel:s,cursor:n,limit:i,filter:r,filterFast:a,sort:o}=this.parameters,c=Hs(o);return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({entity_class:e},void 0!==t?{entity_class_version:`${t}`}:{}),s?{entity_class_level:s}:{}),n?{cursor:n}:{}),i?{limit:`${i}`}:{}),r?{filter:r}:{}),a?{filter_fast:a}:{}),c.length?{sort:c}:{})}}class fn extends pe{constructor(e){super({method:ue.PUT}),this.parameters=e}operation(){return K.PNSetDataSyncEntityOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){return this.parameters.id?this.parameters.data?void 0===this.parameters.data.classVersion||null===this.parameters.data.classVersion?"Entity class version cannot be empty":void 0:"Entity data cannot be empty":"Entity id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/vnd.pubnub.objects.entity+json;version=1"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/entities/${C(t)}`}get body(){const{data:e}=this.parameters;return JSON.stringify({data:Object.assign(Object.assign({entityClassVersion:e.classVersion},void 0!==e.status?{status:e.status}:{}),void 0!==e.payload?{payload:e.payload}:{})})}}class vn extends pe{constructor(e){super({method:ue.DELETE}),this.parameters=e}operation(){return K.PNRemoveDataSyncEntityOperation}validate(){if(!this.parameters.id)return"Entity id cannot be empty"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.keys(t).length>0?t:void 0}parse(e){return r(this,void 0,void 0,(function*(){return{status:e.status}}))}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/entities/${C(t)}`}}class On extends pe{constructor(e){super({method:ue.PATCH}),this.parameters=e}operation(){return K.PNUpdateDataSyncEntityOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Entity id cannot be empty";const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=e&&Object.keys(e).length>0,o=t&&Object.keys(t).length>0,c=s&&s.length>0,u=n&&n.length>0,l=i&&i.length>0,h=r&&Object.keys(r).length>0;return a||o||c||u||l||h?void 0:"At least one of add, replace, remove, move, copy, or test must be provided"}get headers(){var e;let t=null!==(e=super.headers)&&void 0!==e?e:{};return this.parameters.ifMatchesEtag&&(t=Object.assign(Object.assign({},t),{"If-Match":this.parameters.ifMatchesEtag})),Object.assign(Object.assign({},t),{"Content-Type":"application/json-patch+json"})}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/entities/${C(t)}`}get body(){const{add:e,replace:t,remove:s,move:n,copy:i,test:r}=this.parameters,a=Bs({add:e,replace:t,remove:s,move:n,copy:i,test:r});return JSON.stringify(a)}}class Sn extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNGetDataSyncEntityOperation}parse(e){return r(this,void 0,void 0,(function*(){const t=this.deserializeResponse(e);return Object.assign(Object.assign({},t),{status:e.status})}))}validate(){if(!this.parameters.id)return"Entity id cannot be empty"}get path(){const{keySet:{subscribeKey:e},id:t}=this.parameters;return`/v1/datasync/subkeys/${e}/entities/${C(t)}`}}class jn{constructor(e,t){this.keySet=e.keySet,this.configuration=e,this.sendRequest=t}get logger(){return this.configuration.logger()}createEntity(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create Entity with parameters:"})));const s=new yn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getEntity(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Entity with parameters:"})));const s=new Sn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getEntities(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Entities with parameters:"})));const s=new mn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}setEntity(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set Entity with parameters:"})));const s=new fn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}updateEntity(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update Entity with parameters:"})));const s=new On(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}removeEntity(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove Entity with parameters:"})));const s=new vn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}createRelationship(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create Relationship with parameters:"})));const s=new ln(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getRelationship(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Relationship with parameters:"})));const s=new bn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getRelationships(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Relationships with parameters:"})));const s=new hn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}setRelationship(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set Relationship with parameters:"})));const s=new dn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}updateRelationship(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update Relationship with parameters:"})));const s=new gn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}removeRelationship(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove Relationship with parameters:"})));const s=new pn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}createUser(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create User with parameters:"})));const s=new Ks(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getUser(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get User with parameters:"})));const s=new Xs(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getUsers(e,t){return r(this,void 0,void 0,(function*(){const s=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},s),details:"Get Users with parameters:"})));const n=new Ws(Object.assign(Object.assign({},s),{keySet:this.keySet}));return t?this.sendRequest(n,t):this.sendRequest(n)}))}setUser(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set User with parameters:"})));const s=new Vs(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}updateUser(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update User with parameters:"})));const s=new Js(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}removeUser(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove User with parameters:"})));const s=new zs(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}createChannel(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create Channel with parameters:"})));const s=new Qs(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getChannel(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Channel with parameters:"})));const s=new sn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getChannels(e,t){return r(this,void 0,void 0,(function*(){const s=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},s),details:"Get Channels with parameters:"})));const n=new Ys(Object.assign(Object.assign({},s),{keySet:this.keySet}));return t?this.sendRequest(n,t):this.sendRequest(n)}))}setChannel(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set Channel with parameters:"})));const s=new Zs(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}updateChannel(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update Channel with parameters:"})));const s=new tn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}removeChannel(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove Channel with parameters:"})));const s=new en(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}createMembership(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create Membership with parameters:"})));const s=new nn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getMembership(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get Membership with parameters:"})));const s=new un(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}getMemberships(e,t){return r(this,void 0,void 0,(function*(){const s=e&&"function"!=typeof e?e:{};null!=t||(t="function"==typeof e?e:void 0),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},s),details:"Get Memberships with parameters:"})));const n=new rn(Object.assign(Object.assign({},s),{keySet:this.keySet}));return t?this.sendRequest(n,t):this.sendRequest(n)}))}setMembership(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set Membership with parameters:"})));const s=new an(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}updateMembership(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update Membership with parameters:"})));const s=new cn(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}removeMembership(e,t){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove Membership with parameters:"})));const s=new on(Object.assign(Object.assign({},e),{keySet:this.keySet}));return t?this.sendRequest(s,t):this.sendRequest(s)}))}}class wn extends pe{constructor(){super()}operation(){return K.PNTimeOperation}parse(e){return r(this,void 0,void 0,(function*(){return{timetoken:this.deserializeResponse(e)[0]}}))}get path(){return"/time/0"}}class kn extends pe{constructor(e){super(),this.parameters=e}operation(){return K.PNDownloadFileOperation}validate(){const{channel:e,id:t,name:s}=this.parameters;return e?t?s?void 0:"file name can't be empty":"file id can't be empty":"channel can't be empty"}parse(e){return r(this,void 0,void 0,(function*(){const{cipherKey:t,crypto:s,cryptography:n,name:i,PubNubFile:r}=this.parameters,a=e.headers["content-type"];let o,c=e.body;return r.supportsEncryptFile&&(t||s)&&(t&&n?c=yield n.decrypt(t,c):!t&&s&&(o=yield s.decryptFile(r.create({data:c,name:i,mimeType:a}),r))),o||r.create({data:c,name:i,mimeType:a})}))}get path(){const{keySet:{subscribeKey:e},channel:t,id:s,name:n}=this.parameters;return`/v1/files/${e}/channels/${C(t)}/files/${C(s)}/${C(n)}`}}class Cn{static notificationPayload(e,t){return new Pe(e,t)}static generateUUID(){return ie.createUUID()}constructor(e){if(this.eventHandleCapable={},this.entities={},this._configuration=e.configuration,this.cryptography=e.cryptography,this.tokenManager=e.tokenManager,this.transport=e.transport,this.crypto=e.crypto,this.logger.debug("PubNub",(()=>({messageType:"object",message:e.configuration,details:"Create with configuration:",ignoredKeys:(e,t)=>"function"==typeof t[e]||e.startsWith("_")||"keySet"===e||k(e)}))),this._objects=new Ls(this._configuration,this.sendRequest.bind(this)),this._dataSync=new jn(this._configuration,this.sendRequest.bind(this)),this._channelGroups=new ws(this._configuration.logger(),this._configuration.keySet,this.sendRequest.bind(this)),this._push=new Ts(this._configuration.logger(),this._configuration.keySet,this.sendRequest.bind(this)),this.eventDispatcher=new ve,this._configuration.enableEventEngine){this.logger.debug("PubNub","Using new subscription loop management.");let e=this._configuration.getHeartbeatInterval();this.presenceState={},e&&(this.presenceEventEngine=new nt({heartbeat:(e,t)=>(this.logger.trace("PresenceEventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Heartbeat with parameters:"}))),this.heartbeat(e,t)),leave:e=>{this.logger.trace("PresenceEventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Leave with parameters:"}))),this.makeUnsubscribe(e,(()=>{}))},heartbeatDelay:()=>{let t=()=>{};const s=new Promise(((s,n)=>{if(e=this._configuration.getHeartbeatInterval(),e){const i=setTimeout((()=>{s()}),1e3*e);t=()=>{clearTimeout(i),n(new d("Heartbeat interval has been cancelled."))}}else n(new d("Heartbeat interval has been reset."))}));return{cancelDelay:t,promise:s}},emitStatus:e=>this.emitStatus(e),config:this._configuration,presenceState:this.presenceState})),this.eventEngine=new Ct({handshake:e=>(this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Handshake with parameters:",ignoredKeys:["abortSignal","crypto","timeout","keySet","getFileUrl"]}))),this.subscribeHandshake(e)),receiveMessages:e=>(this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Receive messages with parameters:",ignoredKeys:["abortSignal","crypto","timeout","keySet","getFileUrl"]}))),this.subscribeReceiveMessages(e)),join:e=>{var t,s;this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Join with parameters:"}))),e&&0===(null!==(t=e.channels)&&void 0!==t?t:[]).length&&0===(null!==(s=e.groups)&&void 0!==s?s:[]).length?this.logger.trace("EventEngine","Ignoring 'join' announcement request."):this.join(e)},leave:e=>{var t,s;this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Leave with parameters:"}))),e&&0===(null!==(t=e.channels)&&void 0!==t?t:[]).length&&0===(null!==(s=e.groups)&&void 0!==s?s:[]).length?this.logger.trace("EventEngine","Ignoring 'leave' announcement request."):this.leave(e)},leaveAll:e=>{this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Leave all with parameters:"}))),this.leaveAll(e)},presenceReconnect:e=>{this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Reconnect with parameters:"}))),this.presenceReconnect(e)},presenceDisconnect:e=>{this.logger.trace("EventEngine",(()=>({messageType:"object",message:Object.assign({},e),details:"Disconnect with parameters:"}))),this.presenceDisconnect(e)},presenceState:this.presenceState,config:this._configuration,emitMessages:(e,t)=>{try{this.logger.debug("EventEngine",(()=>({messageType:"object",message:t.map((e=>{const t=e.type===ge.Message||e.type===ge.Signal?R(e.data.message):void 0;return t?{type:e.type,data:Object.assign(Object.assign({},e.data),{pn_mfp:t})}:e})),details:"Received events:"}))),t.forEach((t=>this.emitEvent(e,t)))}catch(e){const t={error:!0,category:h.PNUnknownCategory,errorData:e,statusCode:0};this.emitStatus(t)}},emitStatus:e=>this.emitStatus(e)})}else this.logger.debug("PubNub","Using legacy subscription loop management."),this.subscriptionManager=new je(this._configuration,((e,t)=>{try{this.emitEvent(e,t)}catch(e){const t={error:!0,category:h.PNUnknownCategory,errorData:e,statusCode:0};this.emitStatus(t)}}),this.emitStatus.bind(this),((e,t)=>{this.logger.trace("SubscriptionManager",(()=>({messageType:"object",message:Object.assign({},e),details:"Subscribe with parameters:",ignoredKeys:["crypto","timeout","keySet","getFileUrl"]}))),this.makeSubscribe(e,t)}),((e,t)=>(this.logger.trace("SubscriptionManager",(()=>({messageType:"object",message:Object.assign({},e),details:"Heartbeat with parameters:",ignoredKeys:["crypto","timeout","keySet","getFileUrl"]}))),this.heartbeat(e,t))),((e,t)=>{this.logger.trace("SubscriptionManager",(()=>({messageType:"object",message:Object.assign({},e),details:"Leave with parameters:"}))),this.makeUnsubscribe(e,t)}),this.time.bind(this))}get configuration(){return this._configuration}get _config(){return this.configuration}get authKey(){var e;return null!==(e=this._configuration.authKey)&&void 0!==e?e:void 0}getAuthKey(){return this.authKey}setAuthKey(e){this.logger.debug("PubNub","Auth key updated."),this._configuration.setAuthKey(e),this.onAuthenticationChange&&this.onAuthenticationChange(e)}get userId(){return this._configuration.userId}set userId(e){if(!e||"string"!=typeof e||0===e.trim().length){const e=new Error("Missing or invalid userId parameter. Provide a valid string userId");throw this.logger.error("PubNub",(()=>({messageType:"error",message:e}))),e}this.logger.debug("PubNub",`Set user ID: ${e}`),this._configuration.userId=e,this.onUserIdChange&&this.onUserIdChange(this._configuration.userId)}getUserId(){return this._configuration.userId}setUserId(e){this.userId=e}get filterExpression(){var e;return null!==(e=this._configuration.getFilterExpression())&&void 0!==e?e:void 0}getFilterExpression(){return this.filterExpression}set filterExpression(e){this.logger.debug("PubNub",`Set filter expression: ${e}`),this._configuration.setFilterExpression(e)}setFilterExpression(e){this.logger.debug("PubNub",`Set filter expression: ${e}`),this.filterExpression=e}get cipherKey(){return this._configuration.getCipherKey()}set cipherKey(e){this._configuration.setCipherKey(e)}setCipherKey(e){this.logger.debug("PubNub","Cipher key updated."),this.cipherKey=e}set heartbeatInterval(e){var t;this.logger.debug("PubNub",`Set heartbeat interval: ${e}`),this._configuration.setHeartbeatInterval(e),this.onHeartbeatIntervalChange&&this.onHeartbeatIntervalChange(null!==(t=this._configuration.getHeartbeatInterval())&&void 0!==t?t:0)}setHeartbeatInterval(e){this.heartbeatInterval=e}get logger(){return this._configuration.logger()}getVersion(){return this._configuration.getVersion()}_addPnsdkSuffix(e,t){this.logger.debug("PubNub",`Add '${e}' 'pnsdk' suffix: ${t}`),this._configuration._addPnsdkSuffix(e,t)}getUUID(){return this.userId}setUUID(e){this.logger.warn("PubNub","'setUserId` is deprecated, please use 'setUserId' or 'userId' setter instead."),this.logger.debug("PubNub",`Set UUID: ${e}`),this.userId=e}get customEncrypt(){return this._configuration.getCustomEncrypt()}get customDecrypt(){return this._configuration.getCustomDecrypt()}channel(e){let t=this.entities[`${e}_ch`];return t||(t=this.entities[`${e}_ch`]=new ms(e,this)),t}channelGroup(e){let t=this.entities[`${e}_chg`];return t||(t=this.entities[`${e}_chg`]=new bs(e,this)),t}channelMetadata(e){let t=this.entities[`${e}_chm`];return t||(t=this.entities[`${e}_chm`]=new ps(e,this)),t}userMetadata(e){let t=this.entities[`${e}_um`];return t||(t=this.entities[`${e}_um`]=new ys(e,this)),t}dataSyncUser(e){let t=this.entities[`${e}_dsu`];return t||(t=this.entities[`${e}_dsu`]=new gs(e,this)),t}dataSyncChannel(e){let t=this.entities[`${e}_dsc`];return t||(t=this.entities[`${e}_dsc`]=new hs(e,this)),t}dataSyncMembership(e){let t=this.entities[`${e}_dsm`];return t||(t=this.entities[`${e}_dsm`]=new ls(e,this)),t}dataSyncEntity(e){let t=this.entities[`${e}_dse`];return t||(t=this.entities[`${e}_dse`]=new ds(e,this)),t}dataSyncRelationship(e){let t=this.entities[`${e}_dsr`];return t||(t=this.entities[`${e}_dsr`]=new us(e,this)),t}subscriptionSet(e){var t,s;{const n=[];return null===(t=e.channels)||void 0===t||t.forEach((e=>n.push(this.channel(e)))),null===(s=e.channelGroups)||void 0===s||s.forEach((e=>n.push(this.channelGroup(e)))),new Ut({client:this,entities:n,options:e.subscriptionOptions})}}sendRequest(e,t){return r(this,void 0,void 0,(function*(){const s=e.validate();if(s){const e=(n=s,p(Object.assign({message:n},{}),h.PNValidationErrorCategory));if(this.logger.error("PubNub",(()=>({messageType:"error",message:e}))),t)return t(e,null);throw new d("Validation failed, check status for details",e)}var n;const i=e.request(),r=e.operation();i.formData&&i.formData.length>0||r===K.PNDownloadFileOperation?i.timeout=this._configuration.getFileTimeout():r===K.PNSubscribeOperation||r===K.PNReceiveMessagesOperation?i.timeout=this._configuration.getSubscribeTimeout():i.timeout=this._configuration.getTransactionTimeout();const a={error:!1,operation:r,category:h.PNAcknowledgmentCategory,statusCode:0},[o,c]=this.transport.makeSendable(i);return e.cancellationController=c||null,o.then((t=>{if(a.statusCode=t.status,200!==t.status&&204!==t.status){const e=Cn.decoder.decode(t.body),s=t.headers["content-type"];if(s||-1!==s.indexOf("javascript")||-1!==s.indexOf("json")){const t=JSON.parse(e);"object"==typeof t&&"error"in t&&t.error&&"object"==typeof t.error&&(a.errorData=t.error)}else a.responseText=e}return e.parse(t)})).then((e=>t?t(a,e):e)).catch((e=>{const s=e instanceof G?e:G.create(e);if(t)return s.category!==h.PNCancelledCategory&&this.logger.error("PubNub",(()=>({messageType:"error",message:s.toPubNubError(r,"REST API request processing error, check status for details")}))),t(s.toStatus(r),null);const n=s.toPubNubError(r,"REST API request processing error, check status for details");throw s.category!==h.PNCancelledCategory&&this.logger.error("PubNub",(()=>({messageType:"error",message:n}))),n}))}))}destroy(e=!1){this.logger.info("PubNub","Destroying PubNub client."),this._globalSubscriptionSet&&(this._globalSubscriptionSet.invalidate(!0),this._globalSubscriptionSet=void 0),Object.values(this.eventHandleCapable).forEach((e=>e.invalidate(!0))),this.eventHandleCapable={},this.subscriptionManager?(this.subscriptionManager.unsubscribeAll(e),this.subscriptionManager.disconnect()):this.eventEngine&&this.eventEngine.unsubscribeAll(e),this.presenceEventEngine&&this.presenceEventEngine.leaveAll(e)}stop(){this.logger.warn("PubNub","'stop' is deprecated, please use 'destroy' instead."),this.destroy()}publish(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Publish with parameters:"})));const s=!1===e.replicate&&!1===e.storeInHistory,n=new Pt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule()})),i=e=>{e&&this.logger.debug("PubNub",`${s?"Fire":"Publish"} success with timetoken: ${e.timetoken}`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}}))}signal(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Signal with parameters:"})));const s=new Nt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Publish success with timetoken: ${e.timetoken}`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}fire(e,t){return r(this,void 0,void 0,(function*(){return this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Fire with parameters:"}))),null!=t||(t=()=>{}),this.publish(Object.assign(Object.assign({},e),{replicate:!1,storeInHistory:!1}),t)}))}get globalSubscriptionSet(){return this._globalSubscriptionSet||(this._globalSubscriptionSet=this.subscriptionSet({})),this._globalSubscriptionSet}get subscriptionTimetoken(){return this.subscriptionManager?this.subscriptionManager.subscriptionTimetoken:this.eventEngine?this.eventEngine.subscriptionTimetoken:void 0}getSubscribedChannels(){return this.subscriptionManager?this.subscriptionManager.subscribedChannels:this.eventEngine?this.eventEngine.getSubscribedChannels():[]}getSubscribedChannelGroups(){return this.subscriptionManager?this.subscriptionManager.subscribedChannelGroups:this.eventEngine?this.eventEngine.getSubscribedChannelGroups():[]}registerEventHandleCapable(e,t,s){{let n;this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign(Object.assign({subscription:e},t?{cursor:t}:[]),s?{subscriptions:s}:{}),details:"Register event handle capable:"}))),this.eventHandleCapable[e.state.id]||(this.eventHandleCapable[e.state.id]=e),s&&0!==s.length?(n=new It({}),s.forEach((e=>n.add(e.subscriptionInput(!1))))):n=e.subscriptionInput(!1);const i={};i.channels=n.channels,i.channelGroups=n.channelGroups,t&&(i.timetoken=t.timetoken),this.subscriptionManager?this.subscriptionManager.subscribe(i):this.eventEngine&&this.eventEngine.subscribe(i)}}unregisterEventHandleCapable(e,t){{if(!this.eventHandleCapable[e.state.id])return;const s=[];this.logger.trace("PubNub",(()=>({messageType:"object",message:{subscription:e,subscriptions:t},details:"Unregister event handle capable:"})));let n,i=!t||0===t.length;if(!i&&e instanceof Ut&&e.subscriptions.length===(null==t?void 0:t.length)&&(i=e.subscriptions.every((e=>t.includes(e)))),i&&delete this.eventHandleCapable[e.state.id],t&&0!==t.length?(n=new It({}),t.forEach((e=>{const t=e.subscriptionInput(!0);t.isEmpty?s.push(e):n.add(t)}))):(n=e.subscriptionInput(!0),n.isEmpty&&s.push(e)),s.length>0&&this.logger.trace("PubNub",(()=>{const e=[];return s[0]instanceof Ut?s[0].subscriptions.forEach((t=>e.push(t.state.entity))):s.forEach((t=>e.push(t.state.entity))),{messageType:"object",message:{entities:e},details:"Can't unregister event handle capable because entities still in use:"}})),n.isEmpty)return;{const e=[],t=[];if(Object.values(this.eventHandleCapable).forEach((s=>{const i=s.subscriptionInput(!1),r=i.channelGroups,a=i.channels;e.push(...n.channelGroups.filter((e=>r.includes(e)))),t.push(...n.channels.filter((e=>a.includes(e))))})),(t.length>0||e.length>0)&&(this.logger.trace("PubNub",(()=>{const s=[],i=n=>{const i=n.subscriptionNames(!0),r=n.subscriptionType===_t.Channel?t:e;i.some((e=>r.includes(e)))&&s.push(n)};Object.values(this.eventHandleCapable).forEach((e=>{e instanceof Ut?e.subscriptions.forEach((e=>{i(e.state.entity)})):e instanceof $t&&i(e.state.entity)}));let r="Some entities still in use:";return t.length+e.length===n.length&&(r="Can't unregister event handle capable because entities still in use:"),{messageType:"object",message:{entities:s},details:r}})),n.remove(new It({channels:t,channelGroups:e})),n.isEmpty))return}const r={};r.channels=n.channels,r.channelGroups=n.channelGroups,this.subscriptionManager?this.subscriptionManager.unsubscribe(r):this.eventEngine&&this.eventEngine.unsubscribe(r)}}subscribe(e){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Subscribe with parameters:"})));const t=this.subscriptionSet(Object.assign(Object.assign({},e),{subscriptionOptions:{receivePresenceEvents:e.withPresence}}));this.globalSubscriptionSet.addSubscriptionSet(t),t.dispose();const s="number"==typeof e.timetoken?`${e.timetoken}`:e.timetoken;this.globalSubscriptionSet.subscribe({timetoken:s})}}makeSubscribe(e,t){{this._configuration.isSharedWorkerEnabled()||(e.onDemand=!1);const s=new fe(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule(),getFileUrl:this.getFileUrl.bind(this)}));if(this.sendRequest(s,((e,n)=>{var i;this.subscriptionManager&&(null===(i=this.subscriptionManager.abort)||void 0===i?void 0:i.identifier)===s.requestIdentifier&&(this.subscriptionManager.abort=null),t(e,n)})),this.subscriptionManager){const e=()=>s.abort("Cancel long-poll subscribe request");e.identifier=s.requestIdentifier,this.subscriptionManager.abort=e}}}unsubscribe(e){{if(this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Unsubscribe with parameters:"}))),!this._globalSubscriptionSet)return void this.logger.debug("PubNub","There are no active subscriptions. Ignore.");const t=this.globalSubscriptionSet.subscriptions.filter((t=>{var s,n;const i=t.subscriptionInput(!1);if(i.isEmpty)return!1;for(const t of null!==(s=e.channels)&&void 0!==s?s:[])if(i.contains(t))return!0;for(const t of null!==(n=e.channelGroups)&&void 0!==n?n:[])if(i.contains(t))return!0}));t.length>0&&this.globalSubscriptionSet.removeSubscriptions(t)}}makeUnsubscribe(e,t){{let{channels:s,channelGroups:n}=e;if(this._configuration.getKeepPresenceChannelsInPresenceRequests()||(n&&(n=n.filter((e=>!e.endsWith("-pnpres")))),s&&(s=s.filter((e=>!e.endsWith("-pnpres"))))),0===(null!=n?n:[]).length&&0===(null!=s?s:[]).length)return t({error:!1,operation:K.PNUnsubscribeOperation,category:h.PNAcknowledgmentCategory,statusCode:200});this.sendRequest(new Gt({channels:s,channelGroups:n,keySet:this._configuration.keySet}),t)}}unsubscribeAll(){this.logger.debug("PubNub","Unsubscribe all channels and groups"),this._globalSubscriptionSet&&this._globalSubscriptionSet.invalidate(!1),Object.values(this.eventHandleCapable).forEach((e=>e.invalidate(!1))),this.eventHandleCapable={},this.subscriptionManager?this.subscriptionManager.unsubscribeAll():this.eventEngine&&this.eventEngine.unsubscribeAll()}disconnect(e=!1){this.logger.debug("PubNub",`Disconnect (while offline? ${e?"yes":"no"})`),this.subscriptionManager?this.subscriptionManager.disconnect():this.eventEngine&&this.eventEngine.disconnect(e)}reconnect(e){this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Reconnect with parameters:"}))),this.subscriptionManager?this.subscriptionManager.reconnect():this.eventEngine&&this.eventEngine.reconnect(null!=e?e:{})}subscribeHandshake(e){return r(this,void 0,void 0,(function*(){{this._configuration.isSharedWorkerEnabled()||(e.onDemand=!1),e.heartbeat||(e.heartbeat=this._configuration.getPresenceTimeout());const t=new Tt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule(),getFileUrl:this.getFileUrl.bind(this)})),s=e.abortSignal.subscribe((e=>{t.abort("Cancel subscribe handshake request")}));return this.sendRequest(t).then((e=>(s(),e.cursor)))}}))}subscribeReceiveMessages(e){return r(this,void 0,void 0,(function*(){{this._configuration.isSharedWorkerEnabled()||(e.onDemand=!1),e.heartbeat||(e.heartbeat=this._configuration.getPresenceTimeout());const t=new Et(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule(),getFileUrl:this.getFileUrl.bind(this)})),s=e.abortSignal.subscribe((e=>{t.abort("Cancel long-poll subscribe request")}));return this.sendRequest(t).then((e=>(s(),e)))}}))}getMessageActions(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get message actions with parameters:"})));const s=new Jt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Get message actions success. Received ${e.data.length} message actions.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}addMessageAction(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Add message action with parameters:"})));const s=new Xt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Message action add success. Message action added with timetoken: ${e.data.actionTimetoken}`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}removeMessageAction(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove message action with parameters:"})));const s=new Qt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=t=>{t&&this.logger.debug("PubNub",`Message action remove success. Removed message action with ${e.actionTimetoken} timetoken.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}fetchMessages(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Fetch messages with parameters:"})));const s=new zt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule(),getFileUrl:this.getFileUrl.bind(this)})),n=e=>{if(!e)return;const t=Object.values(e.channels).reduce(((e,t)=>e+t.length),0);this.logger.debug("PubNub",`Fetch messages success. Received ${t} messages.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}deleteMessages(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Delete messages with parameters:"})));const s=new Ht(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=e=>{e&&this.logger.debug("PubNub","Delete messages success.")};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}messageCounts(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get messages count with parameters:"})));const s=new Bt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=t=>{if(!t)return;const s=Object.values(t.channels).reduce(((e,t)=>e+t),0);this.logger.debug("PubNub",`Get messages count success. There are ${s} messages since provided reference timetoken${e.channelTimetokens?e.channelTimetokens.join(","):""}.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}history(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Fetch history with parameters:"})));const s=new Wt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule()})),n=e=>{e&&this.logger.debug("PubNub",`Fetch history success. Received ${e.messages.length} messages.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}hereNow(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Here now with parameters:"})));const s=new Kt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=e=>{e&&this.logger.debug("PubNub",`Here now success. There are ${e.totalOccupancy} participants in ${e.totalChannels} channels.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}whereNow(e,t){return r(this,void 0,void 0,(function*(){var s;{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Where now with parameters:"})));const n=new Lt({uuid:null!==(s=e.uuid)&&void 0!==s?s:this._configuration.userId,keySet:this._configuration.keySet}),i=e=>{e&&this.logger.debug("PubNub",`Where now success. Currently present in ${e.channels.length} channels.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}}))}getState(e,t){return r(this,void 0,void 0,(function*(){var s;{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Get presence state with parameters:"})));const n=new Ft(Object.assign(Object.assign({},e),{uuid:null!==(s=e.uuid)&&void 0!==s?s:this._configuration.userId,keySet:this._configuration.keySet})),i=e=>{e&&this.logger.debug("PubNub",`Get presence state success. Received presence state for ${Object.keys(e.channels).length} channels.`)};return t?this.sendRequest(n,((e,s)=>{i(s),t(e,s)})):this.sendRequest(n).then((e=>(i(e),e)))}}))}setState(e,t){return r(this,void 0,void 0,(function*(){var s,n;{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Set presence state with parameters:"})));const{keySet:i,userId:r}=this._configuration,a=this._configuration.getPresenceTimeout();let o;if(this._configuration.enableEventEngine&&this.presenceState){const t=this.presenceState;null===(s=e.channels)||void 0===s||s.forEach((s=>t[s]=e.state)),"channelGroups"in e&&(null===(n=e.channelGroups)||void 0===n||n.forEach((s=>t[s]=e.state))),this.onPresenceStateChange&&this.onPresenceStateChange(this.presenceState)}o="withHeartbeat"in e&&e.withHeartbeat?new qt(Object.assign(Object.assign({},e),{keySet:i,heartbeat:a})):new xt(Object.assign(Object.assign({},e),{keySet:i,uuid:r}));const c=e=>{e&&this.logger.debug("PubNub","Set presence state success."+(o instanceof qt?" Presence state has been set using heartbeat endpoint.":""))};return this.subscriptionManager&&(this.subscriptionManager.setState(e),this.onPresenceStateChange&&this.onPresenceStateChange(this.subscriptionManager.presenceState)),t?this.sendRequest(o,((e,s)=>{c(s),t(e,s)})):this.sendRequest(o).then((e=>(c(e),e)))}}))}presence(e){var t;this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Change presence with parameters:"}))),null===(t=this.subscriptionManager)||void 0===t||t.changePresence(e)}heartbeat(e,t){return r(this,void 0,void 0,(function*(){var s;{this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Heartbeat with parameters:"})));let{channels:n,channelGroups:i}=e;if(i&&(i=i.filter((e=>!e.endsWith("-pnpres")))),n&&(n=n.filter((e=>!e.endsWith("-pnpres")))),0===(null!=i?i:[]).length&&0===(null!=n?n:[]).length){const e={error:!1,operation:K.PNHeartbeatOperation,category:h.PNAcknowledgmentCategory,statusCode:200};return this.logger.trace("PubNub","There are no active subscriptions. Ignore."),t?t(e,{}):Promise.resolve(e)}const r=new qt(Object.assign(Object.assign({},e),{channels:[...new Set(n)],channelGroups:[...new Set(i)],keySet:this._configuration.keySet})),a=e=>{e&&this.logger.trace("PubNub","Heartbeat success.")},o=null===(s=e.abortSignal)||void 0===s?void 0:s.subscribe((e=>{r.abort("Cancel long-poll subscribe request")}));return t?this.sendRequest(r,((e,s)=>{a(s),o&&o(),t(e,s)})):this.sendRequest(r).then((e=>(a(e),o&&o(),e)))}}))}join(e){var t,s;this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Join with parameters:"}))),e&&0===(null!==(t=e.channels)&&void 0!==t?t:[]).length&&0===(null!==(s=e.groups)&&void 0!==s?s:[]).length?this.logger.trace("PubNub","Ignoring 'join' announcement request."):this.presenceEventEngine?this.presenceEventEngine.join(e):this.heartbeat(Object.assign(Object.assign({channels:e.channels,channelGroups:e.groups},this._configuration.maintainPresenceState&&this.presenceState&&Object.keys(this.presenceState).length>0&&{state:this.presenceState}),{heartbeat:this._configuration.getPresenceTimeout()}),(()=>{}))}presenceReconnect(e){this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Presence reconnect with parameters:"}))),this.presenceEventEngine?this.presenceEventEngine.reconnect():this.heartbeat(Object.assign(Object.assign({channels:e.channels,channelGroups:e.groups},this._configuration.maintainPresenceState&&{state:this.presenceState}),{heartbeat:this._configuration.getPresenceTimeout()}),(()=>{}))}leave(e){var t,s,n;this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Leave with parameters:"}))),e&&0===(null!==(t=e.channels)&&void 0!==t?t:[]).length&&0===(null!==(s=e.groups)&&void 0!==s?s:[]).length?this.logger.trace("PubNub","Ignoring 'leave' announcement request."):this.presenceEventEngine?null===(n=this.presenceEventEngine)||void 0===n||n.leave(e):this.makeUnsubscribe({channels:e.channels,channelGroups:e.groups},(()=>{}))}leaveAll(e={}){this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Leave all with parameters:"}))),this.presenceEventEngine?this.presenceEventEngine.leaveAll(!!e.isOffline):e.isOffline||this.makeUnsubscribe({channels:e.channels,channelGroups:e.groups},(()=>{}))}presenceDisconnect(e){this.logger.trace("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Presence disconnect parameters:"}))),this.presenceEventEngine?this.presenceEventEngine.disconnect(!!e.isOffline):e.isOffline||this.makeUnsubscribe({channels:e.channels,channelGroups:e.groups},(()=>{}))}grantToken(e,t){return r(this,void 0,void 0,(function*(){throw new Error("Grant Token error: PAM module disabled")}))}revokeToken(e,t){return r(this,void 0,void 0,(function*(){throw new Error("Revoke Token error: PAM module disabled")}))}get token(){return this.tokenManager&&this.tokenManager.getToken()}getToken(){return this.token}set token(e){this.tokenManager&&this.tokenManager.setToken(e),this.onAuthenticationChange&&this.onAuthenticationChange(e)}setToken(e){this.logger.debug("PubNub","Access token updated."),this.token=e}parseToken(e){return this.logger.debug("PubNub","Parse access token."),this.tokenManager&&this.tokenManager.parseToken(e)}grant(e,t){return r(this,void 0,void 0,(function*(){throw new Error("Grant error: PAM module disabled")}))}audit(e,t){return r(this,void 0,void 0,(function*(){throw new Error("Grant Permissions error: PAM module disabled")}))}get objects(){return this._objects}get dataSync(){return this._dataSync}fetchUsers(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'fetchUsers' is deprecated. Use 'pubnub.objects.getAllUUIDMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{},details:"Fetch all User objects with parameters:"}))),this.objects._getAllUUIDMetadata(e,t)}))}fetchUser(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'fetchUser' is deprecated. Use 'pubnub.objects.getUUIDMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{uuid:this.userId},details:`Fetch${e&&"function"!=typeof e?"":" current"} User object with parameters:`}))),this.objects._getUUIDMetadata(e,t)}))}createUser(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'createUser' is deprecated. Use 'pubnub.objects.setUUIDMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create User object with parameters:"}))),this.objects._setUUIDMetadata(e,t)}))}updateUser(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'updateUser' is deprecated. Use 'pubnub.objects.setUUIDMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update User object with parameters:"}))),this.objects._setUUIDMetadata(e,t)}))}removeUser(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'removeUser' is deprecated. Use 'pubnub.objects.removeUUIDMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{uuid:this.userId},details:`Remove${e&&"function"!=typeof e?"":" current"} User object with parameters:`}))),this.objects._removeUUIDMetadata(e,t)}))}fetchSpaces(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'fetchSpaces' is deprecated. Use 'pubnub.objects.getAllChannelMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:e&&"function"!=typeof e?e:{},details:"Fetch all Space objects with parameters:"}))),this.objects._getAllChannelMetadata(e,t)}))}fetchSpace(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'fetchSpace' is deprecated. Use 'pubnub.objects.getChannelMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Fetch Space object with parameters:"}))),this.objects._getChannelMetadata(e,t)}))}createSpace(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'createSpace' is deprecated. Use 'pubnub.objects.setChannelMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Create Space object with parameters:"}))),this.objects._setChannelMetadata(e,t)}))}updateSpace(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'updateSpace' is deprecated. Use 'pubnub.objects.setChannelMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update Space object with parameters:"}))),this.objects._setChannelMetadata(e,t)}))}removeSpace(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'removeSpace' is deprecated. Use 'pubnub.objects.removeChannelMetadata' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove Space object with parameters:"}))),this.objects._removeChannelMetadata(e,t)}))}fetchMemberships(e,t){return r(this,void 0,void 0,(function*(){return this.objects.fetchMemberships(e,t)}))}addMemberships(e,t){return r(this,void 0,void 0,(function*(){return this.objects.addMemberships(e,t)}))}updateMemberships(e,t){return r(this,void 0,void 0,(function*(){return this.logger.warn("PubNub","'addMemberships' is deprecated. Use 'pubnub.objects.setChannelMembers' or 'pubnub.objects.setMemberships' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Update memberships with parameters:"}))),this.objects.addMemberships(e,t)}))}removeMemberships(e,t){return r(this,void 0,void 0,(function*(){var s,n,i;{if(this.logger.warn("PubNub","'removeMemberships' is deprecated. Use 'pubnub.objects.removeMemberships' or 'pubnub.objects.removeChannelMembers' instead."),this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Remove memberships with parameters:"}))),"spaceId"in e){const i=e,r={channel:null!==(s=i.spaceId)&&void 0!==s?s:i.channel,uuids:null!==(n=i.userIds)&&void 0!==n?n:i.uuids,limit:0};return t?this.objects.removeChannelMembers(r,t):this.objects.removeChannelMembers(r)}const r=e,a={uuid:r.userId,channels:null!==(i=r.spaceIds)&&void 0!==i?i:r.channels,limit:0};return t?this.objects.removeMemberships(a,t):this.objects.removeMemberships(a)}}))}get channelGroups(){return this._channelGroups}get push(){return this._push}sendFile(e,t){return r(this,void 0,void 0,(function*(){{if(!this._configuration.PubNubFile)throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform.");this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Send file with parameters:"})));const s=new is(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,PubNubFile:this._configuration.PubNubFile,fileUploadPublishRetryLimit:this._configuration.fileUploadPublishRetryLimit,file:e.file,sendRequest:this.sendRequest.bind(this),publishFile:this.publishFile.bind(this),crypto:this._configuration.getCryptoModule(),cryptography:this.cryptography?this.cryptography:void 0})),n={error:!1,operation:K.PNPublishFileOperation,category:h.PNAcknowledgmentCategory,statusCode:0},i=e=>{e&&this.logger.debug("PubNub",`Send file success. File shared with ${e.id} ID.`)};return s.process().then((e=>(n.statusCode=e.status,i(e),t?t(n,e):e))).catch((e=>{let s;throw e instanceof d?s=e.status:e instanceof G&&(s=e.toStatus(n.operation)),this.logger.error("PubNub",(()=>({messageType:"error",message:new d("File sending error. Check status for details",s)}))),t&&s&&t(s,null),new d("REST API request processing error. Check status for details",s)}))}}))}publishFile(e,t){return r(this,void 0,void 0,(function*(){{if(!this._configuration.PubNubFile)throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform.");this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Publish file message with parameters:"})));const s=new Yt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,crypto:this._configuration.getCryptoModule()})),n=e=>{e&&this.logger.debug("PubNub",`Publish file message success. File message published with timetoken: ${e.timetoken}`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}listFiles(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"List files with parameters:"})));const s=new ts(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=e=>{e&&this.logger.debug("PubNub",`List files success. There are ${e.count} uploaded files.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}getFileUrl(e){var t;{const s=this.transport.request(new Zt(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})).request()),n=null!==(t=s.queryParameters)&&void 0!==t?t:{},i=Object.keys(n).map((e=>{const t=n[e];return Array.isArray(t)?t.map((t=>`${e}=${C(t)}`)).join("&"):`${e}=${C(t)}`})).join("&");return`${s.origin}${s.path}?${i}`}}downloadFile(e,t){return r(this,void 0,void 0,(function*(){{if(!this._configuration.PubNubFile)throw new Error("Validation failed: 'PubNubFile' not configured or file upload not supported by the platform.");this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Download file with parameters:"})));const s=new kn(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet,PubNubFile:this._configuration.PubNubFile,cryptography:this.cryptography?this.cryptography:void 0,crypto:this._configuration.getCryptoModule()})),n=e=>{e&&this.logger.debug("PubNub","Download file success.")};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):yield this.sendRequest(s).then((e=>(n(e),e)))}}))}deleteFile(e,t){return r(this,void 0,void 0,(function*(){{this.logger.debug("PubNub",(()=>({messageType:"object",message:Object.assign({},e),details:"Delete file with parameters:"})));const s=new es(Object.assign(Object.assign({},e),{keySet:this._configuration.keySet})),n=t=>{t&&this.logger.debug("PubNub",`Delete file success. Deleted file with ${e.id} ID.`)};return t?this.sendRequest(s,((e,s)=>{n(s),t(e,s)})):this.sendRequest(s).then((e=>(n(e),e)))}}))}time(e){return r(this,void 0,void 0,(function*(){this.logger.debug("PubNub","Get service time.");const t=new wn,s=e=>{e&&this.logger.debug("PubNub",`Get service time success. Current timetoken: ${e.timetoken}`)};return e?this.sendRequest(t,((t,n)=>{s(n),e(t,n)})):this.sendRequest(t).then((e=>(s(e),e)))}))}emitStatus(e){var t;null===(t=this.eventDispatcher)||void 0===t||t.handleStatus(e)}emitEvent(e,t){var s;this._globalSubscriptionSet&&this._globalSubscriptionSet.handleEvent(e,t),null===(s=this.eventDispatcher)||void 0===s||s.handleEvent(t),Object.values(this.eventHandleCapable).forEach((s=>{s!==this._globalSubscriptionSet&&s.handleEvent(e,t)}))}set onStatus(e){this.eventDispatcher&&(this.eventDispatcher.onStatus=e)}set onMessage(e){this.eventDispatcher&&(this.eventDispatcher.onMessage=e)}set onPresence(e){this.eventDispatcher&&(this.eventDispatcher.onPresence=e)}set onSignal(e){this.eventDispatcher&&(this.eventDispatcher.onSignal=e)}set onObjects(e){this.eventDispatcher&&(this.eventDispatcher.onObjects=e)}set onMessageAction(e){this.eventDispatcher&&(this.eventDispatcher.onMessageAction=e)}set onFile(e){this.eventDispatcher&&(this.eventDispatcher.onFile=e)}set onDataSync(e){this.eventDispatcher&&(this.eventDispatcher.onDataSync=e)}addListener(e){this.eventDispatcher&&this.eventDispatcher.addListener(e)}removeListener(e){this.eventDispatcher&&this.eventDispatcher.removeListener(e)}removeAllListeners(){this.eventDispatcher&&this.eventDispatcher.removeAllListeners()}encrypt(e,t){this.logger.warn("PubNub","'encrypt' is deprecated. Use cryptoModule instead.");const s=this._configuration.getCryptoModule();if(!t&&s&&"string"==typeof e){const t=s.encrypt(e);return"string"==typeof t?t:u(t)}if(!this.crypto)throw new Error("Encryption error: cypher key not set");return this.crypto.encrypt(e,t)}decrypt(e,t){this.logger.warn("PubNub","'decrypt' is deprecated. Use cryptoModule instead.");const s=this._configuration.getCryptoModule();if(!t&&s){const t=s.decrypt(e);return t instanceof ArrayBuffer?JSON.parse((new TextDecoder).decode(t)):t}if(!this.crypto)throw new Error("Decryption error: cypher key not set");return this.crypto.decrypt(e,t)}encryptFile(e,t){return r(this,void 0,void 0,(function*(){var s;if("string"!=typeof e&&(t=e),!t)throw new Error("File encryption error. Source file is missing.");if(!this._configuration.PubNubFile)throw new Error("File encryption error. File constructor not configured.");if("string"!=typeof e&&!this._configuration.getCryptoModule())throw new Error("File encryption error. Crypto module not configured.");if("string"==typeof e){if(!this.cryptography)throw new Error("File encryption error. File encryption not available");return this.cryptography.encryptFile(e,t,this._configuration.PubNubFile)}return null===(s=this._configuration.getCryptoModule())||void 0===s?void 0:s.encryptFile(t,this._configuration.PubNubFile)}))}decryptFile(e,t){return r(this,void 0,void 0,(function*(){var s;if("string"!=typeof e&&(t=e),!t)throw new Error("File encryption error. Source file is missing.");if(!this._configuration.PubNubFile)throw new Error("File decryption error. File constructor not configured.");if("string"==typeof e&&!this._configuration.getCryptoModule())throw new Error("File decryption error. Crypto module not configured.");if("string"==typeof e){if(!this.cryptography)throw new Error("File decryption error. File decryption not available");return this.cryptography.decryptFile(e,t,this._configuration.PubNubFile)}return null===(s=this._configuration.getCryptoModule())||void 0===s?void 0:s.decryptFile(t,this._configuration.PubNubFile)}))}}Cn.decoder=new TextDecoder,Cn.OPERATIONS=K,Cn.CATEGORIES=h,Cn.Endpoint=X,Cn.ExponentialRetryPolicy=Q.ExponentialRetryPolicy,Cn.LinearRetryPolicy=Q.LinearRetryPolicy,Cn.NoneRetryPolicy=Q.None,Cn.LogLevel=V;class Pn{constructor(e,t){this.decode=e,this.base64ToBinary=t}decodeToken(e){let t="";e.length%4==3?t="=":e.length%4==2&&(t="==");const s=e.replace(/-/gi,"+").replace(/_/gi,"/")+t,n=this.decode(this.base64ToBinary(s));return"object"==typeof n?n:void 0}}class Nn extends Cn{constructor(e){var t;const s=void 0!==e.subscriptionWorkerUrl,i=W(e),r=Object.assign(Object.assign({},i),{sdkFamily:"Web"});r.PubNubFile=o;const a=re(r,(e=>{if(e.cipherKey){return new F({default:new $(Object.assign(Object.assign({},e),e.logger?{}:{logger:a.logger()})),cryptors:[new j({cipherKey:e.cipherKey})]})}}));let u,l;e.subscriptionWorkerLogVerbosity?e.subscriptionWorkerLogLevel=V.Debug:void 0===e.subscriptionWorkerLogLevel&&(e.subscriptionWorkerLogLevel=V.None),void 0!==e.subscriptionWorkerLogVerbosity&&a.logger().warn("Configuration","'subscriptionWorkerLogVerbosity' is deprecated. Use 'subscriptionWorkerLogLevel' instead."),a.getCryptoModule()&&(a.getCryptoModule().logger=a.logger()),u=new ce(new Pn((e=>B(n.decode(e))),c)),(a.getCipherKey()||a.secretKey)&&(l=new U({secretKey:a.secretKey,cipherKey:a.getCipherKey(),useRandomIVs:a.getUseRandomIVs(),customEncrypt:a.getCustomEncrypt(),customDecrypt:a.getCustomDecrypt(),logger:a.logger()}));let h,d=()=>{},p=()=>{},g=()=>{},b=()=>{};h=new A;let y=new de(a.logger(),r.transport);if(i.subscriptionWorkerUrl)try{const e=new H({clientIdentifier:a._instanceId,subscriptionKey:a.subscribeKey,userId:a.getUserId(),workerUrl:i.subscriptionWorkerUrl,sdkVersion:a.getVersion(),heartbeatInterval:a.getHeartbeatInterval(),announceSuccessfulHeartbeats:a.announceSuccessfulHeartbeats,announceFailedHeartbeats:a.announceFailedHeartbeats,workerOfflineClientsCheckInterval:r.subscriptionWorkerOfflineClientsCheckInterval,workerUnsubscribeOfflineClients:r.subscriptionWorkerUnsubscribeOfflineClients,workerLogLevel:r.subscriptionWorkerLogLevel,tokenManager:u,transport:y,logger:a.logger()});p=t=>e.onPresenceStateChange(t),d=t=>e.onHeartbeatIntervalChange(t),g=t=>e.onTokenChange(t),b=t=>e.onUserIdChange(t),y=e,i.subscriptionWorkerUnsubscribeOfflineClients&&"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("pagehide",(t=>{t.persisted||e.terminate()}),{once:!0})}catch(e){a.logger().error("PubNub",(()=>({messageType:"error",message:e})))}else s&&a.logger().warn("PubNub","SharedWorker not supported in this browser. Fallback to the original transport.");const m=new he({clientConfiguration:a,tokenManager:u,transport:y});if(super({configuration:a,transport:m,cryptography:h,tokenManager:u,crypto:l}),this.File=o,this.onHeartbeatIntervalChange=d,this.onAuthenticationChange=g,this.onPresenceStateChange=p,this.onUserIdChange=b,y instanceof H){y.emitStatus=this.emitStatus.bind(this);const e=this.disconnect.bind(this);this.disconnect=t=>{y.disconnect(),e()}}(null===(t=e.listenToBrowserNetworkEvents)||void 0===t||t)&&"undefined"!=typeof window&&window.addEventListener&&(window.addEventListener("offline",(()=>{this.networkDownDetected()})),window.addEventListener("online",(()=>{this.networkUpDetected()})))}networkDownDetected(){this.logger.debug("PubNub","Network down detected"),this.emitStatus({category:Nn.CATEGORIES.PNNetworkDownCategory}),this._configuration.restore?this.disconnect(!0):this.destroy(!0)}networkUpDetected(){this.logger.debug("PubNub","Network up detected"),this.emitStatus({category:Nn.CATEGORIES.PNNetworkUpCategory}),this.reconnect()}}return Nn.CryptoModule=F,Nn})); diff --git a/lib/core/components/configuration.js b/lib/core/components/configuration.js index 8d960ee2a..bc46aaf36 100644 --- a/lib/core/components/configuration.js +++ b/lib/core/components/configuration.js @@ -174,7 +174,7 @@ const makeConfiguration = (base, setupCryptoModule) => { return base.PubNubFile; }, get version() { - return '13.1.2'; + return '13.1.3'; }, getVersion() { return this.version; diff --git a/lib/types/index.d.ts b/lib/types/index.d.ts index 57a983989..3c45e86a4 100644 --- a/lib/types/index.d.ts +++ b/lib/types/index.d.ts @@ -4224,6 +4224,7 @@ declare namespace PubNub { */ deletedAt?: string; }; + /** * DataSync membership delete payload. * @@ -4240,6 +4241,7 @@ declare namespace PubNub { */ userId?: string; }; + /** * DataSync relationship delete payload. * diff --git a/package.json b/package.json index dcb03ce7a..40e5b5112 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pubnub", - "version": "13.1.2", + "version": "13.1.3", "author": "PubNub ", "description": "PubNub SDK for JavaScript. Publish/subscribe messaging over HTTP long-poll with server-assigned message ordering, channel occupancy via Here Now, and message history through Message Persistence.", "scripts": { diff --git a/src/core/components/configuration.ts b/src/core/components/configuration.ts index cd47b76cb..7b75d4d22 100644 --- a/src/core/components/configuration.ts +++ b/src/core/components/configuration.ts @@ -245,7 +245,7 @@ export const makeConfiguration = ( return base.PubNubFile; }, get version(): string { - return '13.1.2'; + return '13.1.3'; }, getVersion(): string { return this.version;