snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Code scanning - action / CodeQL-Build (push) Failing after 2s
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-16 01:21:02 +05:00
commit 30810eecd7
10161 changed files with 987110 additions and 0 deletions

61
packages/apps-engine/.gitignore vendored Normal file
View File

@@ -0,0 +1,61 @@
# Created by https://www.gitignore.io/api/node
### Node ###
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
.deno
.deno-cache
# Optional REPL history
.node_repl_history
### Typings ###
## Ignore downloaded typings
/typings
## dev environment stuff
/examples/
/dev-dist/
/data/
/tests/test-data/dbs
/client
/definition
/server
/lib
.DS_Store
.idea/

View File

@@ -0,0 +1,635 @@
# @rocket.chat/apps-engine
## 1.66.0
### Minor Changes
- ([#41765](https://github.com/RocketChat/Rocket.Chat/pull/41765)) Accepts a role name in the `when.hasOneRole` and `when.hasAllRoles` filters of an app action button
## 1.66.0-rc.0
### Minor Changes
- ([#41765](https://github.com/RocketChat/Rocket.Chat/pull/41765)) Accepts a role name in the `when.hasOneRole` and `when.hasAllRoles` filters of an app action button
## 1.65.1
### Patch Changes
- ([#41304](https://github.com/RocketChat/Rocket.Chat/pull/41304)) Fixes wrong FederationLookup type assigned to IUser in apps. The correct data is there, but the type does not represent it.
## 1.64.1-rc.0
### Patch Changes
- ([#41304](https://github.com/RocketChat/Rocket.Chat/pull/41304)) Fixes wrong FederationLookup type assigned to IUser in apps. The correct data is there, but the type does not represent it.
## 1.64.1
### Patch Changes
- ([#41308](https://github.com/RocketChat/Rocket.Chat/pull/41308) by [@dionisio-bot](https://github.com/dionisio-bot)) Fixes wrong FederationLookup type assigned to IUser in apps. The correct data is there, but the type does not represent it.
## 1.64.0
### Minor Changes
- ([#40791](https://github.com/RocketChat/Rocket.Chat/pull/40791)) Exposes the `isFederated` and `federation` fields for room and user objects in apps
## 1.64.0-rc.0
### Minor Changes
- ([#40791](https://github.com/RocketChat/Rocket.Chat/pull/40791)) Exposes the `isFederated` and `federation` fields for room and user objects in apps
## 1.63.0
### Minor Changes
- ([#40343](https://github.com/RocketChat/Rocket.Chat/pull/40343)) Remove files that weren't accessible to apps at development time
- ([#40463](https://github.com/RocketChat/Rocket.Chat/pull/40463)) Allows apps with the right permission to read room's ABAC attributes.
- ([#40604](https://github.com/RocketChat/Rocket.Chat/pull/40604)) Adds the capability for fetching a user by their sip extension to the apps
## 1.63.0-rc.0
### Minor Changes
- ([#40343](https://github.com/RocketChat/Rocket.Chat/pull/40343)) Remove files that weren't accessible to apps at development time
- ([#40463](https://github.com/RocketChat/Rocket.Chat/pull/40463)) Allows apps with the right permission to read room's ABAC attributes.
- ([#40604](https://github.com/RocketChat/Rocket.Chat/pull/40604)) Adds the capability for fetching a user by their sip extension to the apps
## 1.62.0
### Minor Changes
- ([#39535](https://github.com/RocketChat/Rocket.Chat/pull/39535)) Adds externalIds field to livechat visitors for external platform identification.
- ([#40093](https://github.com/RocketChat/Rocket.Chat/pull/40093)) Adds new API endpoints to load the user's current voice call state from the server
### Patch Changes
- ([#40125](https://github.com/RocketChat/Rocket.Chat/pull/40125)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates)
- ([#39883](https://github.com/RocketChat/Rocket.Chat/pull/39883)) Fixes the issue of the lacking MessageUpdater not being available to apps during runtime
## 1.61.1
### Patch Changes
- ([#40130](https://github.com/RocketChat/Rocket.Chat/pull/40130) by [@dionisio-bot](https://github.com/dionisio-bot)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates)
## 1.62.0-rc.0
### Minor Changes
- ([#39535](https://github.com/RocketChat/Rocket.Chat/pull/39535)) Adds externalIds field to livechat visitors for external platform identification.
- ([#40093](https://github.com/RocketChat/Rocket.Chat/pull/40093)) Adds new API endpoints to load the user's current voice call state from the server
### Patch Changes
- ([#40125](https://github.com/RocketChat/Rocket.Chat/pull/40125)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates)
- ([#39883](https://github.com/RocketChat/Rocket.Chat/pull/39883)) Fixes the issue of the lacking MessageUpdater not being available to apps during runtime
## 1.61.0
### Minor Changes
- ([#39268](https://github.com/RocketChat/Rocket.Chat/pull/39268)) refactor(ui-kit): Remove UiKit deprecations
### Patch Changes
- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration
## 1.61.0-rc.0
### Minor Changes
- ([#39268](https://github.com/RocketChat/Rocket.Chat/pull/39268)) refactor(ui-kit): Remove UiKit deprecations
### Patch Changes
- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration
## 1.60.0
### Minor Changes
- ([#38099](https://github.com/RocketChat/Rocket.Chat/pull/38099)) Adds file metadata to the Apps.Engine for messages with multiple files
### Patch Changes
- ([#38374](https://github.com/RocketChat/Rocket.Chat/pull/38374)) Fixes an issue where apps logs were being lost in nested requests
- ([#38513](https://github.com/RocketChat/Rocket.Chat/pull/38513)) Fixes an issue where app-defined API endpoints with dynamic paths could fail to receive requests when using path parameters like `:param`.
## 1.60.0-rc.0
### Minor Changes
- ([#38099](https://github.com/RocketChat/Rocket.Chat/pull/38099)) Adds file metadata to the Apps.Engine for messages with multiple files
### Patch Changes
- ([#38374](https://github.com/RocketChat/Rocket.Chat/pull/38374)) Fixes an issue where apps logs were being lost in nested requests
- ([#38513](https://github.com/RocketChat/Rocket.Chat/pull/38513)) Fixes an issue where app-defined API endpoints with dynamic paths could fail to receive requests when using path parameters like `:param`.
## 1.59.1
### Patch Changes
- ([#38068](https://github.com/RocketChat/Rocket.Chat/pull/38068)) Fixes an issue that caused a spike in memory usage when apps handled the IPreFileUpload event
## 1.59.1-rc.0
### Patch Changes
- ([#38068](https://github.com/RocketChat/Rocket.Chat/pull/38068)) Fixes an issue that caused a spike in memory usage when apps handled the IPreFileUpload event
## 1.59.0
### Minor Changes
- ([#37719](https://github.com/RocketChat/Rocket.Chat/pull/37719)) Adds a new method to the Apps-Engine that allows apps to retrieve multiple rooms from database
- ([#37672](https://github.com/RocketChat/Rocket.Chat/pull/37672)) Removes deprecated VoIP from Omnichannel
- ([#37091](https://github.com/RocketChat/Rocket.Chat/pull/37091)) Adds Attribute Based Access Control (ABAC) for private channels & private teams.
### Patch Changes
- ([#37730](https://github.com/RocketChat/Rocket.Chat/pull/37730)) Adds an execution flag to apps-engine runtime that helps prevent the publishing of faulty builds
## 1.59.0-rc.0
### Minor Changes
- ([#37719](https://github.com/RocketChat/Rocket.Chat/pull/37719)) Adds a new method to the Apps-Engine that allows apps to retrieve multiple rooms from database
- ([#37672](https://github.com/RocketChat/Rocket.Chat/pull/37672)) Removes deprecated VoIP from Omnichannel
- ([#37091](https://github.com/RocketChat/Rocket.Chat/pull/37091)) Adds Attribute Based Access Control (ABAC) for private channels & private teams.
### Patch Changes
- ([#37730](https://github.com/RocketChat/Rocket.Chat/pull/37730)) Adds an execution flag to apps-engine runtime that helps prevent the publishing of faulty builds
## 1.58.0
### Minor Changes
- ([#37547](https://github.com/RocketChat/Rocket.Chat/pull/37547)) Adds the `getUserRoomIds` method to the `UserRead` accessor in the Apps-Engine, graduating it from the experimental bridge to the stable user bridge.
- ([#37167](https://github.com/RocketChat/Rocket.Chat/pull/37167)) Changes a behavior that would store the result of every status transition that happened to apps
This caused intermediate status to be saved to the database, which could prevent apps from being restored to the desired status when restarted or during server startup.
### Patch Changes
- ([#37496](https://github.com/RocketChat/Rocket.Chat/pull/37496)) Fixes the ping behavior so it only triggers when the app becomes idle, preventing unnecessary restarts
- ([#37380](https://github.com/RocketChat/Rocket.Chat/pull/37380)) Fixes an issue where apps would never get the bio of a user even though the type has the field defined
- ([#37384](https://github.com/RocketChat/Rocket.Chat/pull/37384)) Fixes a problem in apps-engine debug logs where only 2 depth levels were displayed for objects, which is often not enough for debugging purposes
- ([#37152](https://github.com/RocketChat/Rocket.Chat/pull/37152)) Fixes a bug that would cause apps to go into `invalid_installation_disabled` in some cases
## 1.58.0-rc.0
### Minor Changes
- ([#37547](https://github.com/RocketChat/Rocket.Chat/pull/37547)) Adds the `getUserRoomIds` method to the `UserRead` accessor in the Apps-Engine, graduating it from the experimental bridge to the stable user bridge.
- ([#37167](https://github.com/RocketChat/Rocket.Chat/pull/37167)) Changes a behavior that would store the result of every status transition that happened to apps
This caused intermediate status to be saved to the database, which could prevent apps from being restored to the desired status when restarted or during server startup.
### Patch Changes
- ([#37496](https://github.com/RocketChat/Rocket.Chat/pull/37496)) Fixes the ping behavior so it only triggers when the app becomes idle, preventing unnecessary restarts
- ([#37380](https://github.com/RocketChat/Rocket.Chat/pull/37380)) Fixes an issue where apps would never get the bio of a user even though the type has the field defined
- ([#37384](https://github.com/RocketChat/Rocket.Chat/pull/37384)) Fixes a problem in apps-engine debug logs where only 2 depth levels were displayed for objects, which is often not enough for debugging purposes
- ([#37152](https://github.com/RocketChat/Rocket.Chat/pull/37152)) Fixes a bug that would cause apps to go into `invalid_installation_disabled` in some cases
## 1.57.1
### Patch Changes
- ([#37440](https://github.com/RocketChat/Rocket.Chat/pull/37440) by [@dionisio-bot](https://github.com/dionisio-bot)) Fixes a problem in apps-engine debug logs where only 2 depth levels were displayed for objects, which is often not enough for debugging purposes
## 1.57.0
### Minor Changes
- ([#37057](https://github.com/RocketChat/Rocket.Chat/pull/37057)) Adds an experimental API to the apps-engine that retrieves the ids of rooms the user is a member of
### Patch Changes
- ([#36990](https://github.com/RocketChat/Rocket.Chat/pull/36990)) Change app update strategies to prevent unwanted data changes in database
## 1.57.0-rc.0
### Minor Changes
- ([#37057](https://github.com/RocketChat/Rocket.Chat/pull/37057)) Adds an experimental API to the apps-engine that retrieves the ids of rooms the user is a member of
### Patch Changes
- ([#36990](https://github.com/RocketChat/Rocket.Chat/pull/36990)) Change app update strategies to prevent unwanted data changes in database
## 1.56.0
### Minor Changes
- ([#36207](https://github.com/RocketChat/Rocket.Chat/pull/36207)) Introduces the Outbound Message feature to Omnichannel, allowing organizations to initiate proactive communication with contacts through their preferred messaging channel directly from Rocket.Chat
### Patch Changes
- ([#36967](https://github.com/RocketChat/Rocket.Chat/pull/36967)) Fixes an issue where apps that import node native modules with the optional `node:` specifier would fail to construct
- ([#36855](https://github.com/RocketChat/Rocket.Chat/pull/36855)) Changes a strict behavior on reporting slash commands provided by apps
- ([#36943](https://github.com/RocketChat/Rocket.Chat/pull/36943)) Fixes an issue where an object reference leak would cause invalid data to be stored in the database during app installation
## 1.56.0-rc.0
### Minor Changes
- ([#36207](https://github.com/RocketChat/Rocket.Chat/pull/36207)) Introduces the Outbound Message feature to Omnichannel, allowing organizations to initiate proactive communication with contacts through their preferred messaging channel directly from Rocket.Chat
### Patch Changes
- ([#36967](https://github.com/RocketChat/Rocket.Chat/pull/36967)) Fixes an issue where apps that import node native modules with the optional `node:` specifier would fail to construct
- ([#36855](https://github.com/RocketChat/Rocket.Chat/pull/36855)) Changes a strict behavior on reporting slash commands provided by apps
- ([#36943](https://github.com/RocketChat/Rocket.Chat/pull/36943)) Fixes an issue where an object reference leak would cause invalid data to be stored in the database during app installation
## 1.55.1
### Patch Changes
- ([#37028](https://github.com/RocketChat/Rocket.Chat/pull/37028) by [@dionisio-bot](https://github.com/dionisio-bot)) Changes a strict behavior on reporting slash commands provided by apps
## 1.55.0
### Minor Changes
- ([#36553](https://github.com/RocketChat/Rocket.Chat/pull/36553)) Creates a new endpoint that allows agents to send an outbound message from a registered app provider
### Patch Changes
- ([#36625](https://github.com/RocketChat/Rocket.Chat/pull/36625)) Fixes an issue where app installation would fail if the app package contained JS syntax newer than 2017
- ([#36802](https://github.com/RocketChat/Rocket.Chat/pull/36802)) Fixes an error on apps loading that would cause an unhandled promise rejection crash during startup in some cases
- ([#36670](https://github.com/RocketChat/Rocket.Chat/pull/36670)) Fixes an issue that would cause the chat server to crash with an unhandled rejection in some cases
## 1.55.0-rc.1
### Patch Changes
- ([#36802](https://github.com/RocketChat/Rocket.Chat/pull/36802)) Fixes an error on apps loading that would cause an unhandled promise rejection crash during startup in some cases
## 1.55.0-rc.0
### Minor Changes
- ([#36553](https://github.com/RocketChat/Rocket.Chat/pull/36553)) Creates a new endpoint that allows agents to send an outbound message from a registered app provider
### Patch Changes
- ([#36625](https://github.com/RocketChat/Rocket.Chat/pull/36625)) Fixes an issue where app installation would fail if the app package contained JS syntax newer than 2017
- ([#36670](https://github.com/RocketChat/Rocket.Chat/pull/36670)) Fixes an issue that would cause the chat server to crash with an unhandled rejection in some cases
## 1.54.0
### Minor Changes
- ([#36377](https://github.com/RocketChat/Rocket.Chat/pull/36377)) Adds new endpoints for outbound communications
- ([#36403](https://github.com/RocketChat/Rocket.Chat/pull/36403)) Adds a button to the apps logs UI that exports logs as a downloadable file
### Patch Changes
- ([#36504](https://github.com/RocketChat/Rocket.Chat/pull/36504)) Fixes an issue that would leave an app in an unrecoverable state if the installation failed during the construction of the runtime
- ([#36346](https://github.com/RocketChat/Rocket.Chat/pull/36346)) Fixes an issue where some error objects sent to apps' method calls would only contain the message '[object Object]'
## 1.54.0-rc.1
### Patch Changes
- ([#36504](https://github.com/RocketChat/Rocket.Chat/pull/36504)) Fixes an issue that would leave an app in an unrecoverable state if the installation failed during the construction of the runtime
## 1.54.0-rc.0
### Minor Changes
- ([#36377](https://github.com/RocketChat/Rocket.Chat/pull/36377)) Adds new endpoints for outbound communications
- ([#36403](https://github.com/RocketChat/Rocket.Chat/pull/36403)) Adds a button to the apps logs UI that exports logs as a downloadable file
### Patch Changes
- ([#36346](https://github.com/RocketChat/Rocket.Chat/pull/36346)) Fixes an issue where some error objects sent to apps' method calls would only contain the message '[object Object]'
## 1.53.1
### Patch Changes
- ([#36543](https://github.com/RocketChat/Rocket.Chat/pull/36543)) Fixes an issue that would leave an app in an unrecoverable state if the installation failed during the construction of the runtime
## 1.53.0
### Minor Changes
- ([#36169](https://github.com/RocketChat/Rocket.Chat/pull/36169)) Fix an issue where action buttons registered by apps would be displayed even if their apps were disabled
### Patch Changes
- ([#36346](https://github.com/RocketChat/Rocket.Chat/pull/36346)) Fixes an issue where some error objects sent to apps' method calls would only contain the message '[object Object]'
## 1.53.0-rc.1
### Patch Changes
- ([#36346](https://github.com/RocketChat/Rocket.Chat/pull/36346)) Fixes an issue where some error objects sent to apps' method calls would only contain the message '[object Object]'
## 1.53.0-rc.0
### Minor Changes
- ([#36169](https://github.com/RocketChat/Rocket.Chat/pull/36169)) Fix an issue where action buttons registered by apps would be displayed even if their apps were disabled
## 1.52.1
### Patch Changes
- ([#36360](https://github.com/RocketChat/Rocket.Chat/pull/36360) by [@dionisio-bot](https://github.com/dionisio-bot)) Fixes an issue where some error objects sent to apps' method calls would only contain the message '[object Object]'
## 1.52.0
### Minor Changes
- ([#35416](https://github.com/RocketChat/Rocket.Chat/pull/35416)) Improve the `/api/apps/:id/logs` endpoint to accept filters
- ([#35416](https://github.com/RocketChat/Rocket.Chat/pull/35416)) Add a new endpoint `/api/apps/logs` that allows for fetching logs without a filter for app id
### Patch Changes
- ([#36007](https://github.com/RocketChat/Rocket.Chat/pull/36007)) Fixes the Apps-Engine package installation, removing the dependency on an internal package
## 1.52.0-rc.0
### Minor Changes
- ([#35416](https://github.com/RocketChat/Rocket.Chat/pull/35416)) Improve the `/api/apps/:id/logs` endpoint to accept filters
- ([#35416](https://github.com/RocketChat/Rocket.Chat/pull/35416)) Add a new endpoint `/api/apps/logs` that allows for fetching logs without a filter for app id
### Patch Changes
- ([#36007](https://github.com/RocketChat/Rocket.Chat/pull/36007)) Fixes the Apps-Engine package installation, removing the dependency on an internal package
## 1.51.1
### Patch Changes
- ([#36033](https://github.com/RocketChat/Rocket.Chat/pull/36033) by [@dionisio-bot](https://github.com/dionisio-bot)) Fixes the Apps-Engine package installation, removing the dependency on an internal package
## 1.51.0
### Minor Changes
- ([#35280](https://github.com/RocketChat/Rocket.Chat/pull/35280)) Allows apps to react to department status changes.
- ([#35644](https://github.com/RocketChat/Rocket.Chat/pull/35644)) Adds the ability to dynamically add and remove options from select/multi-select settings in the Apps Engine to support more flexible configuration scenarios by exposing two new methods on the settings API.
## 1.51.0-rc.0
### Minor Changes
- ([#35280](https://github.com/RocketChat/Rocket.Chat/pull/35280)) Allows apps to react to department status changes.
- ([#35644](https://github.com/RocketChat/Rocket.Chat/pull/35644)) Adds the ability to dynamically add and remove options from select/multi-select settings in the Apps Engine to support more flexible configuration scenarios by exposing two new methods on the settings API.
## 1.50.0
### Minor Changes
- ([#35486](https://github.com/RocketChat/Rocket.Chat/pull/35486)) Adds the executeLivechatRoomCreatePrevent hook to the Rocket.Chat Apps-Engine to prevent the creation of live chat rooms.
### Patch Changes
- ([#35479](https://github.com/RocketChat/Rocket.Chat/pull/35479)) Fixes deno dependency caching for the docker image builds
- ([#35426](https://github.com/RocketChat/Rocket.Chat/pull/35426)) Improves overall performance on dealing with apps, by reducing the number of getStatus calls through the pipe.
- ([#35667](https://github.com/RocketChat/Rocket.Chat/pull/35667)) Fixes an issue with error handling where errors were not properly propagated to integrated apps.
- ([#35342](https://github.com/RocketChat/Rocket.Chat/pull/35342)) Fixes an issue that prevents modifications from being persisted in the IPreRoomCreateModify
- ([#35603](https://github.com/RocketChat/Rocket.Chat/pull/35603)) Fixes an issue where apps where not able to update messages using the BlockBuilder.
## 1.50.0-rc.1
### Patch Changes
- ([#35667](https://github.com/RocketChat/Rocket.Chat/pull/35667)) Fixes an issue with error handling where errors were not properly propagated to integrated apps.
- ([#35603](https://github.com/RocketChat/Rocket.Chat/pull/35603)) Fixes an issue where apps where not able to update messages using the BlockBuilder.
## 1.50.0-rc.0
### Minor Changes
- ([#35486](https://github.com/RocketChat/Rocket.Chat/pull/35486)) Adds the executeLivechatRoomCreatePrevent hook to the Rocket.Chat Apps-Engine to prevent the creation of live chat rooms.
### Patch Changes
- ([#35479](https://github.com/RocketChat/Rocket.Chat/pull/35479)) Fixes deno dependency caching for the docker image builds
- ([#35426](https://github.com/RocketChat/Rocket.Chat/pull/35426)) Improves overall performance on dealing with apps, by reducing the number of getStatus calls through the pipe.
- ([#35342](https://github.com/RocketChat/Rocket.Chat/pull/35342)) Fixes an issue that prevents modifications from being persisted in the IPreRoomCreateModify
## 1.49.0
### Minor Changes
- ([#35177](https://github.com/RocketChat/Rocket.Chat/pull/35177)) Adds a new IPostSystemMessageSent event, that is triggered whenever a new System Message is sent
- ([#35013](https://github.com/RocketChat/Rocket.Chat/pull/35013)) Adds a filter option to include or exclude threads in the Apps Engine room read/unread messages bridge, enhancing flexibility in message retrieval.
- ([#35199](https://github.com/RocketChat/Rocket.Chat/pull/35199)) Enables specifying hidden settings that are enabled to be accessed through the apps-engine in the permission list.
### Patch Changes
- ([#35120](https://github.com/RocketChat/Rocket.Chat/pull/35120)) Fixes behavior of app updates that would save undesired field changes to documents
- ([#35170](https://github.com/RocketChat/Rocket.Chat/pull/35170)) Fixes an issue that would cause marketplace apps to become invalid installations after an update
## 1.49.0-rc.0
### Minor Changes
- ([#35177](https://github.com/RocketChat/Rocket.Chat/pull/35177)) Adds a new IPostSystemMessageSent event, that is triggered whenever a new System Message is sent
- ([#35013](https://github.com/RocketChat/Rocket.Chat/pull/35013)) Adds a filter option to include or exclude threads in the Apps Engine room read/unread messages bridge, enhancing flexibility in message retrieval.
- ([#35199](https://github.com/RocketChat/Rocket.Chat/pull/35199)) Enables specifying hidden settings that are enabled to be accessed through the apps-engine in the permission list.
### Patch Changes
- ([#35120](https://github.com/RocketChat/Rocket.Chat/pull/35120)) Fixes behavior of app updates that would save undesired field changes to documents
- ([#35170](https://github.com/RocketChat/Rocket.Chat/pull/35170)) Fixes an issue that would cause marketplace apps to become invalid installations after an update
## 1.48.2
### Patch Changes
- ([#34858](https://github.com/RocketChat/Rocket.Chat/pull/34858)) Fixes an issue that prevented the apps-engine from reestablishing communications with subprocesses in some cases
- ([#35009](https://github.com/RocketChat/Rocket.Chat/pull/35009)) Fix an issue with apps installations via Marketplace
## 1.48.2-rc.0
### Patch Changes
- ([#34858](https://github.com/RocketChat/Rocket.Chat/pull/34858)) Fixes an issue that prevented the apps-engine from reestablishing communications with subprocesses in some cases
## 1.48.1
### Patch Changes
- ([#34205](https://github.com/RocketChat/Rocket.Chat/pull/34205)) Fixes an error where the engine would not retry a subprocess restart if the last attempt failed
- ([#34172](https://github.com/RocketChat/Rocket.Chat/pull/34172)) Fixes the subprocess restarting routine failing to correctly restart apps in some cases
- ([#34858](https://github.com/RocketChat/Rocket.Chat/pull/34858)) Fixes an issue that prevented the apps-engine from reestablishing communications with subprocesses in some cases
- ([#34106](https://github.com/RocketChat/Rocket.Chat/pull/34106)) Adds simple app subprocess metrics report
- ([#34205](https://github.com/RocketChat/Rocket.Chat/pull/34205)) Fixes error propagation when trying to get the status of apps in some cases
- ([#34106](https://github.com/RocketChat/Rocket.Chat/pull/34106)) Attempts to restart an app subprocess if the spawn command fails
- ([#34205](https://github.com/RocketChat/Rocket.Chat/pull/34205)) Fixes wrong data being reported to total failed apps metrics and statistics
- ([#34106](https://github.com/RocketChat/Rocket.Chat/pull/34106)) Fixes an issue while collecting the error message from a failed restart attempt of an app subprocess
- ([#34106](https://github.com/RocketChat/Rocket.Chat/pull/34106)) Prevents app:getStatus requests from timing out in some cases
## 1.48.1-rc.1
### Patch Changes
- ([#34858](https://github.com/RocketChat/Rocket.Chat/pull/34858)) Fixes an issue that prevented the apps-engine from reestablishing communications with subprocesses in some cases
## 1.48.1-rc.0
### Patch Changes
- ([#34205](https://github.com/RocketChat/Rocket.Chat/pull/34205)) Fixes an error where the engine would not retry a subprocess restart if the last attempt failed
- ([#34172](https://github.com/RocketChat/Rocket.Chat/pull/34172)) Fixes the subprocess restarting routine failing to correctly restart apps in some cases
- ([#34106](https://github.com/RocketChat/Rocket.Chat/pull/34106)) Adds simple app subprocess metrics report
- ([#34205](https://github.com/RocketChat/Rocket.Chat/pull/34205)) Fixes error propagation when trying to get the status of apps in some cases
- ([#34106](https://github.com/RocketChat/Rocket.Chat/pull/34106)) Attempts to restart an app subprocess if the spawn command fails
- ([#34205](https://github.com/RocketChat/Rocket.Chat/pull/34205)) Fixes wrong data being reported to total failed apps metrics and statistics
- ([#34106](https://github.com/RocketChat/Rocket.Chat/pull/34106)) Fixes an issue while collecting the error message from a failed restart attempt of an app subprocess
- ([#34106](https://github.com/RocketChat/Rocket.Chat/pull/34106)) Prevents app:getStatus requests from timing out in some cases
## 1.48.0
### Minor Changes
- ([#32727](https://github.com/RocketChat/Rocket.Chat/pull/32727)) These changes aims to add:
- A brand-new omnichannel contact profile
- The ability to communicate with known contacts only
- Communicate with verified contacts only
- Merge verified contacts across different channels
- Block contact channels
- Resolve conflicting contact information when registered via different channels
- An advanced contact center filters
- ([#33997](https://github.com/RocketChat/Rocket.Chat/pull/33997)) Prevent apps' subprocesses from crashing on unhandled rejections or uncaught exceptions
- ([#33690](https://github.com/RocketChat/Rocket.Chat/pull/33690)) Add support to configure apps runtime timeout via the APPS_ENGINE_RUNTIME_TIMEOUT environment variable
### Patch Changes
- ([#33713](https://github.com/RocketChat/Rocket.Chat/pull/33713)) Deprecated the `from` field in the apps email bridge and made it optional, using the server's settings when the field is omitted
- ([#33786](https://github.com/RocketChat/Rocket.Chat/pull/33786)) Fixed an issue that would grant network permission to app's processes in wrong cases
- ([#33865](https://github.com/RocketChat/Rocket.Chat/pull/33865)) Fixes an issue that would cause apps to appear disabled after a subprocess restart
- ([#33690](https://github.com/RocketChat/Rocket.Chat/pull/33690)) Removed the 1 second timeout of `Pre` app events. Now they will follow the "global" configuration
## 1.48.0-rc.0
### Minor Changes
- ([#32727](https://github.com/RocketChat/Rocket.Chat/pull/32727)) These changes aims to add:
- A brand-new omnichannel contact profile
- The ability to communicate with known contacts only
- Communicate with verified contacts only
- Merge verified contacts across different channels
- Block contact channels
- Resolve conflicting contact information when registered via different channels
- An advanced contact center filters
- ([#33997](https://github.com/RocketChat/Rocket.Chat/pull/33997)) Prevent apps' subprocesses from crashing on unhandled rejections or uncaught exceptions
- ([#33690](https://github.com/RocketChat/Rocket.Chat/pull/33690)) Add support to configure apps runtime timeout via the APPS_ENGINE_RUNTIME_TIMEOUT environment variable
### Patch Changes
- ([#33713](https://github.com/RocketChat/Rocket.Chat/pull/33713)) Deprecated the `from` field in the apps email bridge and made it optional, using the server's settings when the field is omitted
- ([#33786](https://github.com/RocketChat/Rocket.Chat/pull/33786)) Fixed an issue that would grant network permission to app's processes in wrong cases
- ([#33865](https://github.com/RocketChat/Rocket.Chat/pull/33865)) Fixes an issue that would cause apps to appear disabled after a subprocess restart
- ([#33690](https://github.com/RocketChat/Rocket.Chat/pull/33690)) Removed the 1 second timeout of `Pre` app events. Now they will follow the "global" configuration
## 1.47.0
### Minor Changes
- ([#33433](https://github.com/RocketChat/Rocket.Chat/pull/33433)) Added support for interacting with add-ons issued in the license
### Patch Changes
- ([#33494](https://github.com/RocketChat/Rocket.Chat/pull/33494)) Fixed a problem in the deno runtime controller where it would not handle undefined child process references correctly
- ([#33417](https://github.com/RocketChat/Rocket.Chat/pull/33417)) Fixes issue with previously disabled private apps being auto enabled on update
## 1.47.0-rc.0
### Minor Changes
- ([#33433](https://github.com/RocketChat/Rocket.Chat/pull/33433)) Added support for interacting with add-ons issued in the license
### Patch Changes
- ([#33494](https://github.com/RocketChat/Rocket.Chat/pull/33494)) Fixed a problem in the deno runtime controller where it would not handle undefined child process references correctly
- ([#33417](https://github.com/RocketChat/Rocket.Chat/pull/33417)) Fixes issue with previously disabled private apps being auto enabled on update

View File

@@ -0,0 +1,125 @@
## Thoughts While Working (for docs)
- Apps which don't provide a valid uuid4 id will be assigned one, but this is not recommended and your App should provide an id
- The language strings are only done on the clients (`TAPi18next.addResourceBundle(lang, projectName, translations);`)
- The implementer of this should restrict the server setting access and environmental variables. Idea is to allow the implementer to have a default set of restricted ones while letting the admin/owner of the server to restrict it even further or lift the restriction on some more. Simple interface with settings and checkbox to allow/disallow them. :thinking:
## What does the Apps-Engine enable you to do?
The Apps-Engine is Rocket.Chat's _plugin framework_ - it provides the APIs for Rocket.Chat Apps to interact with the host system.
Currently, a Rocket.Chat App can:
- Listen to message events
- before/after sent
- before/after updated
- before/after deleted
- Listen to room events
- before/after created
- before/after deleted
- Send messages to users and livechat visitors
- Register new slash commands
- Register new HTTP endpoints
Some features the Engine allows Apps to use:
- Key-Value Storage system
- App specific settings
## Development environment with Rocket.Chat
When developing new functionalities, you need to integrate the local version of the Apps-Engine with your local version of Rocket.Chat.
First of all, make sure you've installed all required packages and compiled the changes you've made to the Apps-Engine, since that is what Rocket.Chat will execute:
```sh
npm install
npm run compile
```
Now, you need to setup a local Rocket.Chat server, [so head to the project's README for instructions on getting started](https://github.com/RocketChat/Rocket.Chat#development) (if you haven't already). Make sure to actually clone the repo, since you will probably need to add some code to it in order to make your new functionality work.
After that, `cd` into Rocket.Chat folder and run:
```sh
meteor npm install PATH_TO_APPS_ENGINE
```
Where `PATH_TO_APPS_ENGINE` is the path to the Apps-Engine repo you've cloned.
That's it! Now when you start Rocket.Chat with the `meteor` command, it will use your local Apps-Engine instead of the one on NPM :)
Whenever you make changes to the engine, run `npm run compile` again - meteor will take care of restarting the server due to the changes.
## Troubleshooting
1. Sometimes, when you update the Apps-Engine code and compile it while Rocket.Chat is running, you might run on errors similar to these:
```
Unable to resolve some modules:
"@rocket.chat/apps-engine/definition/AppStatus" in
/Users/dev/rocket.chat/Rocket.Chat/app/apps/client/admin/helpers.js (web.browser)
If you notice problems related to these missing modules, consider running:
meteor npm install --save @rocket.chat/apps-engine
```
Simply restart the meteor process and it should be fixed.
2. Sometimes when using `meteor npm install PATH_TO_APPS_ENGINE` will cause the following error :-
```
npm ERR! code ENOENT
npm ERR! syscall rename
npm ERR! path PATH_TO_ROCKETCHAT/node_modules/.staging/@rocket.chat/apps-engine-c7135600/node_modules/@babel/code-frame
npm ERR! dest PATH_TO_ROCKETCHAT/node_modules/.staging/@babel/code-frame-f3697825
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, rename 'PATH_TO_ROCKETCHAT/node_modules/.staging/@rocket.chat/apps-engine-c7135600/node_modules/@babel/code-frame' -> 'PATH_TO_ROCKETCHAT/node_modules/.staging/@babel/code-frame-f3697825'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent
```
Here `PATH_TO_ROCKETCHAT` is the path to the main rocketchat server repo in your system
To correct this we reinstall the package once again deleting the previous package
```
~/Rocket.Chat$ rm -rf node_modules/@rocket.chat/apps-engine
~/Rocket.Chat$ cd PATH_TO_APP_ENGINE
~/Rocket.Chat.Apps-engine$ npm install
~/Rocket.Chat.Apps-engine$ cd PATH_TO_ROCKETCHAT
~/Rocket.Chat$ meteor npm install ../Rocket.Chat.Apps-engine
```
## Implementer Needs to Implement:
- `src/server/storage/AppStorage`
- `src/server/storage/AppLogStorage`
- `src/server/bridges/*`
## Testing Framework:
Makes great usage of TypeScript and decorators: https://github.com/alsatian-test/alsatian/wiki
* To run the tests do: `npm run unit-tests`
* To generate the coverage information: `npm run check-coverage`
* To view the coverage: `npm run view-coverage`
# Rocket.Chat Apps TypeScript Definitions
## Handlers
Handlers are essentially "listeners" for different events, except there are various ways to handle an event.
When something happens there is `pre` and `post` handlers.
The set of `pre` handlers happens before the event is finalized.
The set of `post` handlers happens after the event is finalized.
With that said, the rule of thumb is that if you are going to modify, extend, or change the data backing the event then that should be done in the `pre` handlers. If you are simply wanting to listen for when something happens and not modify anything, then the `post` is the way to go.
The order in which they happen is:
* Pre**Event**Prevent
* Pre**Event**Extend
* Pre**Event**Modify
* Post**Event**
Here is an explanation of what each of them means:
* **Prevent**: This is ran to determine whether the event should be prevented or not.
* **Extend**: This is ran to allow extending the data without being destructive of the data (adding an attachment to a message for example).
* **Modify**: This is ran and allows for destructive changes to the data (change any and everything).
* Post**Event**: Is mostly for simple listening and no changes can be made to the data.
## Generating/Updating Documentation
To update or generate the documentation, please commit your changes first and then in a second commit provide the updated documentation.
# Engage with us
## Share your story
We’d love to hear about [your experience](https://survey.zohopublic.com/zs/e4BUFG) and potentially feature it on our [Blog](https://rocket.chat/case-studies/?utm_source=github&utm_medium=readme&utm_campaign=community).
## Subscribe for Updates
Once a month our marketing team releases an email update with news about product releases, company related topics, events and use cases. [Sign Up!](https://rocket.chat/newsletter/?utm_source=github&utm_medium=readme&utm_campaign=community)

View File

@@ -0,0 +1,83 @@
{
"name": "@rocket.chat/apps-engine",
"version": "1.66.0",
"description": "The public API and type definitions for Rocket.Chat App development.",
"keywords": [
"rocket.chat",
"team chat",
"apps engine"
],
"homepage": "https://github.com/RocketChat/Rocket.Chat.Apps-engine#readme",
"bugs": {
"url": "https://github.com/RocketChat/Rocket.Chat.Apps-engine/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/RocketChat/Rocket.Chat.git",
"directory": "packages/apps-engine"
},
"license": "MIT",
"author": {
"name": "Rocket.Chat",
"url": "https://rocket.chat/"
},
"contributors": [
{
"name": "Bradley Hilton",
"email": "bradley.hilton@rocket.chat"
},
{
"name": "Rodrigo Nascimento",
"email": "rodrigo.nascimento@rocket.chat"
},
{
"name": "Douglas Gubert",
"email": "douglas.gubert@rocket.chat"
}
],
"files": [
"definition/**"
],
"scripts": {
"build": "run-s build:clean build:default",
"build:clean": "rimraf definition",
"build:default": "tsc -p tsconfig.json",
"dev": "yarn build:default --watch",
"gen-doc": "typedoc",
"lint": "yarn eslint .",
"typecheck": "tsc -p tsconfig.json --noEmit"
},
"nyc": {
"all": true,
"extension": [
".ts"
],
"include": [
"src/*.ts",
"src/server/**/*.ts"
],
"reporter": [
"lcov",
"json",
"html"
]
},
"dependencies": {
"uuid": "~11.1.1"
},
"devDependencies": {
"@rocket.chat/ui-kit": "workspace:~",
"@types/node": "~24.13.2",
"eslint": "~9.39.5",
"npm-run-all": "^4.1.5",
"rimraf": "^6.0.1",
"typedoc": "~0.28.20",
"typescript": "~5.9.3"
},
"volta": {
"extends": "../../package.json"
},
"installConfig": {
"hoistingLimits": "workspaces"
}
}

View File

@@ -0,0 +1,261 @@
import { AppStatus } from './AppStatus';
import type { IApp } from './IApp';
import type {
IAppAccessors,
IAppInstallationContext,
IAppUninstallationContext,
IConfigurationExtend,
IConfigurationModify,
IEnvironmentRead,
IHttp,
ILogger,
IModify,
IPersistence,
IRead,
IAppUpdateContext,
} from './accessors';
import type { IAppAuthorInfo } from './metadata/IAppAuthorInfo';
import type { IAppInfo } from './metadata/IAppInfo';
import type { ISetting } from './settings';
import type { ISettingUpdateContext } from './settings/ISettingUpdateContext';
export abstract class App implements IApp {
private status: AppStatus = AppStatus.UNKNOWN;
/**
* Create a new App, this is called whenever the server starts up and initiates the Apps.
* Note, your implementation of this class should call `super(name, id, version)` so we have it.
* Also, please use the `initialize()` method to do items instead of the constructor as the constructor
* *might* be called more than once but the `initialize()` will only be called once.
*/
public constructor(
private readonly info: IAppInfo,
private readonly logger: ILogger,
private readonly accessors?: IAppAccessors,
) {
this.logger.debug(
`Constructed the App ${this.info.name} (${this.info.id})`,
`v${this.info.version} which depends on the API v${this.info.requiredApiVersion}!`,
`Created by ${this.info.author.name}`,
);
void this.setStatus(AppStatus.CONSTRUCTED);
}
public async getStatus(): Promise<AppStatus> {
return this.status;
}
/**
* Get the name of this App.
*
* @return {string} the name
*/
public getName(): string {
return this.info.name;
}
/**
* Gets the sluggified name of this App.
*
* @return {string} the name slugged
*/
public getNameSlug(): string {
return this.info.nameSlug;
}
/**
* Gets the username of this App's app user.
*
* @return {string} the username of the app user
*
* @deprecated This method will be removed in the next major version.
* Please use read.getUserReader().getAppUser() instead.
*/
public getAppUserUsername(): string {
return `${this.info.nameSlug}.bot`;
}
/**
* Get the ID of this App, please see <link> for how to obtain an ID for your App.
*
* @return {number} the ID
*/
public getID(): string {
return this.info.id;
}
/**
* Get the version of this App, using http://semver.org/.
*
* @return {string} the version
*/
public getVersion(): string {
return this.info.version;
}
/**
* Get the description of this App, mostly used to show to the clients/administrators.
*
* @return {string} the description
*/
public getDescription(): string {
return this.info.description;
}
/**
* Gets the API Version which this App depends on (http://semver.org/).
* This property is used for the dependency injections.
*
* @return {string} the required api version
*/
public getRequiredApiVersion(): string {
return this.info.requiredApiVersion;
}
/**
* Gets the information regarding the author/maintainer of this App.
*
* @return author information
*/
public getAuthorInfo(): IAppAuthorInfo {
return this.info.author;
}
/**
* Gets the entirity of the App's information.
*
* @return App information
*/
public getInfo(): IAppInfo {
return this.info;
}
/**
* Gets the ILogger instance for this App.
*
* @return the logger instance
*/
public getLogger(): ILogger {
return this.logger;
}
public getAccessors(): IAppAccessors {
if (!this.accessors) {
throw new Error('Accessors not initialized');
}
return this.accessors;
}
/**
* Method which will be called when the App is initialized. This is the recommended place
* to add settings and slash commands. If an error is thrown, all commands will be unregistered.
*/
public async initialize(configurationExtend: IConfigurationExtend, environmentRead: IEnvironmentRead): Promise<void> {
await this.extendConfiguration(configurationExtend, environmentRead);
}
/**
* Method which is called when this App is enabled and can be called several
* times during this instance's life time. Once after the `initialize()` is called,
* pending it doesn't throw an error, and then anytime the App is enabled by the user.
* If this method, `onEnable()`, returns false, then this App will not
* actually be enabled (ex: a setting isn't configured).
*
* @return whether the App should be enabled or not
*/
public async onEnable(environment: IEnvironmentRead, configurationModify: IConfigurationModify): Promise<boolean> {
return true;
}
/**
* Method which is called when this App is disabled and it can be called several times.
* If this App was enabled and then the user disabled it, this method will be called.
*/
public async onDisable(configurationModify: IConfigurationModify): Promise<void> {}
/**
* Method which is called when the App is uninstalled and it is called one single time.
*
* This method will NOT be called when an App is getting disabled manually, ONLY when
* it's being uninstalled from Rocket.Chat.
*/
public async onUninstall(
context: IAppUninstallationContext,
read: IRead,
http: IHttp,
persistence: IPersistence,
modify: IModify,
): Promise<void> {}
/**
* Method which is called when the App is installed and it is called one single time.
*
* This method is NOT called when the App is updated.
*/
public async onInstall(
context: IAppInstallationContext,
read: IRead,
http: IHttp,
persistence: IPersistence,
modify: IModify,
): Promise<void> {}
/**
* Method which is called when the App is updated and it is called one single time.
*
* This method is NOT called when the App is installed.
*/
public async onUpdate(context: IAppUpdateContext, read: IRead, http: IHttp, persistence: IPersistence, modify: IModify): Promise<void> {}
/**
* Method which is called whenever a setting which belongs to this App has been updated
* by an external system and not this App itself. The setting passed is the newly updated one.
*
* @param setting the setting which was updated
* @param configurationModify the accessor to modifiy the system
* @param reader the reader accessor
* @param http an accessor to the outside world
*/
public async onSettingUpdated(setting: ISetting, configurationModify: IConfigurationModify, read: IRead, http: IHttp): Promise<void> {}
/**
* Method which is called before a setting which belongs to this App is going to be updated
* by an external system and not this App itself. The setting passed is the newly updated one.
*
* @param setting the setting which is going to be updated
* @param configurationModify the accessor to modifiy the system
* @param reader the reader accessor
* @param http an accessor to the outside world
*/
public async onPreSettingUpdate(
context: ISettingUpdateContext,
configurationModify: IConfigurationModify,
read: IRead,
http: IHttp,
): Promise<ISetting> {
return context.newSetting;
}
/**
* Method will be called during initialization. It allows for adding custom configuration options and defaults
* @param configuration
*/
protected async extendConfiguration(configuration: IConfigurationExtend, environmentRead: IEnvironmentRead): Promise<void> {}
/**
* Sets the status this App is now at, use only when 100% true (it's protected for a reason).
*
* @param status the new status of this App
*/
protected async setStatus(status: AppStatus): Promise<void> {
this.logger.debug({ msg: 'The status is now', status });
this.status = status;
}
// Avoid leaking references if object is serialized (e.g. to be sent over IPC)
public toJSON(): Record<string, any> {
return this.info;
}
}

View File

@@ -0,0 +1,65 @@
export enum AppStatus {
/** The status is known, aka not been constructed the proper way. */
UNKNOWN = 'unknown',
/** The App has been constructed but that's it. */
CONSTRUCTED = 'constructed',
/** The App's `initialize()` was called and returned true. */
INITIALIZED = 'initialized',
/** The App's `onEnable()` was called, returned true, and this was done automatically (system start up). */
AUTO_ENABLED = 'auto_enabled',
/** The App's `onEnable()` was called, returned true, and this was done by the user such as installing a new one. */
MANUALLY_ENABLED = 'manually_enabled',
/**
* The App was disabled due to an error while attempting to compile it.
* An attempt to enable it again will fail, as it needs to be updated.
*/
COMPILER_ERROR_DISABLED = 'compiler_error_disabled',
/**
* The App was disable due to its license being invalid
*/
INVALID_LICENSE_DISABLED = 'invalid_license_disabled',
/**
* The app was disabled due to an invalid installation or validation in its signature.
*/
INVALID_INSTALLATION_DISABLED = 'invalid_installation_disabled',
/** The App was disabled due to an unrecoverable error being thrown. */
ERROR_DISABLED = 'error_disabled',
/** The App was manually disabled by a user. */
MANUALLY_DISABLED = 'manually_disabled',
INVALID_SETTINGS_DISABLED = 'invalid_settings_disabled',
/** The App was disabled due to other circumstances. */
DISABLED = 'disabled',
}
export class AppStatusUtilsDef {
public isEnabled(status: AppStatus): boolean {
switch (status) {
case AppStatus.AUTO_ENABLED:
case AppStatus.MANUALLY_ENABLED:
return true;
default:
return false;
}
}
public isDisabled(status: AppStatus): boolean {
switch (status) {
case AppStatus.COMPILER_ERROR_DISABLED:
case AppStatus.ERROR_DISABLED:
case AppStatus.MANUALLY_DISABLED:
case AppStatus.INVALID_SETTINGS_DISABLED:
case AppStatus.INVALID_LICENSE_DISABLED:
case AppStatus.INVALID_INSTALLATION_DISABLED:
case AppStatus.DISABLED:
return true;
default:
return false;
}
}
public isError(status: AppStatus): boolean {
return [AppStatus.ERROR_DISABLED, AppStatus.COMPILER_ERROR_DISABLED].includes(status);
}
}
export const AppStatusUtils = new AppStatusUtilsDef();

View File

@@ -0,0 +1,90 @@
import type { AppStatus } from './AppStatus';
import type { IAppAccessors } from './accessors';
import type { ILogger } from './accessors/ILogger';
import type { IAppAuthorInfo } from './metadata/IAppAuthorInfo';
import type { IAppInfo } from './metadata/IAppInfo';
export interface IApp {
/**
* Gets the status of this App.
*
* @return {AppStatus} the status/state of the App
*/
getStatus(): Promise<AppStatus>;
/**
* Get the name of this App.
*
* @return {string} the name
*/
getName(): string;
/**
* Gets the sluggified name of this App.
*
* @return {string} the name slugged
*/
getNameSlug(): string;
/**
* Gets the username of this App's app user.
*
* @return {string} the username of the app user
*
* @deprecated This method will be removed in the next major version.
* Please use read.getAppUser instead.
*/
getAppUserUsername(): string;
/**
* Get the ID of this App, please see <link> for how to obtain an ID for your App.
*
* @return {number} the ID
*/
getID(): string;
/**
* Get the version of this App, using http://semver.org/.
*
* @return {string} the version
*/
getVersion(): string;
/**
* Get the description of this App, mostly used to show to the clients/administrators.
*
* @return {string} the description
*/
getDescription(): string;
/**
* Gets the API Version which this App depends on (http://semver.org/).
* This property is used for the dependency injections.
*
* @return {string} the required api version
*/
getRequiredApiVersion(): string;
/**
* Gets the information regarding the author/maintainer of this App.
*
* @return author information
*/
getAuthorInfo(): IAppAuthorInfo;
/**
* Gets the entirity of the App's information.
*
* @return App information
*/
getInfo(): IAppInfo;
/**
* Gets the ILogger instance for this App.
*
* @return the logger instance
*/
getLogger(): ILogger;
getAccessors(): IAppAccessors;
}

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2015-2023 Rocket.Chat Technologies Corp.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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.

View File

@@ -0,0 +1,12 @@
export interface IAbacAttributeDefinition {
/**
* Validation expectation (NOT enforced here, must be enforced by caller):
* /^[A-Za-z0-9_-]+$/
*/
key: string;
/**
* List of string values for this attribute key.
*/
values: string[];
}

View File

@@ -0,0 +1,16 @@
import type { IApi } from '../api';
/**
* This accessor provides methods for adding a custom api.
* It is provided during the initialization of your App
*/
export interface IApiExtend {
/**
* Adds an api which can be called by external services lateron.
* Should an api already exists an error will be thrown.
*
* @param api the command information
*/
provideApi(api: IApi): Promise<void>;
}

View File

@@ -0,0 +1,11 @@
import type { IEnvironmentRead, IHttp, IRead } from '.';
import type { IApiEndpointMetadata } from '../api';
import type { IEnvironmentWrite } from './IEnvironmentWrite';
export interface IAppAccessors {
readonly environmentReader: IEnvironmentRead;
readonly environmentWriter: IEnvironmentWrite;
readonly reader: IRead;
readonly http: IHttp;
readonly providedApiEndpoints: Array<IApiEndpointMetadata>;
}

View File

@@ -0,0 +1,5 @@
import type { IUser } from '../users';
export interface IAppInstallationContext {
user: IUser;
}

View File

@@ -0,0 +1,5 @@
import type { IUser } from '../users';
export interface IAppUninstallationContext {
user: IUser;
}

View File

@@ -0,0 +1,6 @@
import type { IUser } from '../users';
export interface IAppUpdateContext {
user?: IUser;
oldAppVersion: string;
}

View File

@@ -0,0 +1,24 @@
import type { IWorkspaceToken } from '../cloud/IWorkspaceToken';
/**
* Accessor that enables apps to read information
* related to the Cloud connectivity of the workspace.
*
* Methods in this accessor will usually connect to the
* Rocket.Chat Cloud, which means they won't work properly
* in air-gapped environment.
*
* This accessor available via `IRead` object, which is
* usually received as a parameter wherever it's available.
*/
export interface ICloudWorkspaceRead {
/**
* Returns an access token that can be used to access
* Cloud Services on the workspace's behalf.
*
* @param scope The scope that the token should be authorized with
*
* @RequiresPermission cloud.workspace-token; scopes: Array<string>
*/
getWorkspaceToken(scope: string): Promise<IWorkspaceToken>;
}

View File

@@ -0,0 +1,40 @@
import type { IApiExtend } from './IApiExtend';
import type { IExternalComponentsExtend } from './IExternalComponentsExtend';
import type { IHttpExtend } from './IHttp';
import type { IOutboundCommunicationProviderExtend } from './IOutboundCommunicationProviderExtend';
import type { ISchedulerExtend } from './ISchedulerExtend';
import type { ISettingsExtend } from './ISettingsExtend';
import type { ISlashCommandsExtend } from './ISlashCommandsExtend';
import type { IUIExtend } from './IUIExtend';
import type { IVideoConfProvidersExtend } from './IVideoConfProvidersExtend';
/**
* This accessor provides methods for declaring the configuration
* of your App. It is provided during initialization of your App.
*/
export interface IConfigurationExtend {
/** Accessor for customing the handling of IHttp requests and responses your App causes. */
readonly http: IHttpExtend;
/** Accessor for declaring the settings your App provides. */
readonly settings: ISettingsExtend;
/** Accessor for declaring the commands which your App provides. */
readonly slashCommands: ISlashCommandsExtend;
/** Accessor for declaring api endpoints. */
readonly api: IApiExtend;
readonly externalComponents: IExternalComponentsExtend;
/** Accessor for declaring tasks that can be scheduled (like cron) */
readonly scheduler: ISchedulerExtend;
/** Accessor for registering different elements in the host UI */
readonly ui: IUIExtend;
/** Accessor for declaring the videoconf providers which your App provides. */
readonly videoConfProviders: IVideoConfProvidersExtend;
/** Accessor for declaring outbound communication providers */
readonly outboundCommunication: IOutboundCommunicationProviderExtend;
}

View File

@@ -0,0 +1,18 @@
import type { ISchedulerModify } from './ISchedulerModify';
import type { IServerSettingsModify } from './IServerSettingsModify';
import type { ISlashCommandsModify } from './ISlashCommandsModify';
/**
* This accessor provides methods for modifying the configuration
* of Rocket.Chat. It is provided during "onEnable" of your App.
*/
export interface IConfigurationModify {
/** Accessor for modifying the settings inside of Rocket.Chat. */
readonly serverSettings: IServerSettingsModify;
/** Accessor for modifying the slash commands inside of Rocket.Chat. */
readonly slashCommands: ISlashCommandsModify;
/** Accessor for modifying schedulers */
readonly scheduler: ISchedulerModify;
}

View File

@@ -0,0 +1,13 @@
import type { ILivechatContact } from '../livechat';
export interface IContactCreator {
verifyContact(verifyContactChannelParams: {
contactId: string;
field: string;
value: string;
visitorId: string;
roomId: string;
}): Promise<void>;
addContactEmail(contactId: ILivechatContact['_id'], email: string): Promise<ILivechatContact>;
}

View File

@@ -0,0 +1,5 @@
import type { ILivechatContact } from '../livechat';
export interface IContactRead {
getById(contactId: ILivechatContact['_id']): Promise<ILivechatContact | null>;
}

View File

@@ -0,0 +1,25 @@
import type { IRoomBuilder } from '.';
import type { IMessage } from '../messages';
import type { RocketChatAssociationModel } from '../metadata';
import type { IRoom } from '../rooms';
/**
* Interface for building out a room.
* Please note, a room creator, name, and type must be set otherwise you will NOT
* be able to successfully save the room object.
*/
export interface IDiscussionBuilder extends IRoomBuilder {
kind: RocketChatAssociationModel.DISCUSSION;
setParentRoom(parentRoom: IRoom): IDiscussionBuilder;
getParentRoom(): IRoom;
setParentMessage(parentMessage: IMessage): IDiscussionBuilder;
getParentMessage(): IMessage;
setReply(reply: string): IDiscussionBuilder;
getReply(): string;
}

View File

@@ -0,0 +1,10 @@
import type { IEmail } from '../email';
export interface IEmailCreator {
/**
* Sends an email through Rocket.Chat
*
* @param email the email data
*/
send(email: IEmail): Promise<void>;
}

View File

@@ -0,0 +1,27 @@
import type { IEnvironmentalVariableRead } from './IEnvironmentalVariableRead';
import type { IServerSettingRead } from './IServerSettingRead';
import type { ISettingRead } from './ISettingRead';
/**
* Allows read-access to the App's settings,
* the certain server's settings along with environmental
* variables all of which are not user created.
*/
export interface IEnvironmentRead {
/** Gets an instance of the App's settings reader. */
getSettings(): ISettingRead;
/**
* Gets an instance of the Server's Settings reader.
* Please note: Due to security concerns, only a subset of settings
* are accessible.
*/
getServerSettings(): IServerSettingRead;
/**
* Gets an instance of the Environmental Variables reader.
* Please note: Due to security concerns, only a subset of
* them are readable.
*/
getEnvironmentVariables(): IEnvironmentalVariableRead;
}

View File

@@ -0,0 +1,10 @@
import type { IServerSettingUpdater } from './IServerSettingUpdater';
import type { ISettingUpdater } from './ISettingUpdater';
/**
* Allows write-access to the App's settings,
*/
export interface IEnvironmentWrite {
getSettings(): ISettingUpdater;
getServerSettings(): IServerSettingUpdater;
}

View File

@@ -0,0 +1,11 @@
/** A reader for reading the Environmental Variables. */
export interface IEnvironmentalVariableRead {
/** Gets the value for a variable. */
getValueByName(envVarName: string): Promise<string>;
/** Checks to see if Apps can access the given variable name. */
isReadable(envVarName: string): Promise<boolean>;
/** Checks to see if any value is set for the given variable name. */
isSet(envVarName: string): Promise<boolean>;
}

View File

@@ -0,0 +1,9 @@
/**
* @description
* Experimental bridge for experimental features.
* Methods in this class are not guaranteed to be stable between updates as the
* team evaluates the proper signature, underlying implementation and performance
* impact of candidates for future APIs
*/
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IExperimentalRead {}

View File

@@ -0,0 +1,17 @@
import type { IExternalComponent } from '../externalComponent';
/**
* This accessor provides a method for registering external
* components. This is provided during the initialization of your App.
*/
export interface IExternalComponentsExtend {
/**
* Register an external component to the system.
* If you call this method twice and the component
* has the same name as before, the first one will be
* overwritten as the names provided **must** be unique.
*
* @param externalComponent the external component to be registered
*/
register(externalComponent: IExternalComponent): Promise<void>;
}

View File

@@ -0,0 +1,211 @@
import type { IPersistence } from './IPersistence';
import type { IRead } from './IRead';
/**
* The Http package allows users to call out to an external web service.
* Based off of: https://github.com/meteor-typings/meteor/blob/master/1.4/main.d.ts#L869
*/
export interface IHttp {
get(url: string, options?: IHttpRequest): Promise<IHttpResponse>;
post(url: string, options?: IHttpRequest): Promise<IHttpResponse>;
put(url: string, options?: IHttpRequest): Promise<IHttpResponse>;
del(url: string, options?: IHttpRequest): Promise<IHttpResponse>;
patch(url: string, options?: IHttpRequest): Promise<IHttpResponse>;
}
export enum RequestMethod {
GET = 'get',
POST = 'post',
PUT = 'put',
DELETE = 'delete',
HEAD = 'head',
OPTIONS = 'options',
PATCH = 'patch',
}
export interface IHttpRequest {
content?: string;
data?: any;
query?: string;
params?: {
[key: string]: string;
};
auth?: string;
headers?: {
[key: string]: string;
};
timeout?: number;
/**
* The encoding to be used on response data.
*
* If null, the body is returned as a Buffer. Anything else (including the default value of undefined)
* will be passed as the encoding parameter to toString() (meaning this is effectively 'utf8' by default).
* (Note: if you expect binary data, you should set encoding: null.)
*/
encoding?: string | null;
/**
* if `true`, requires SSL certificates be valid.
*
* Defaul: `true`;
*/
strictSSL?: boolean;
/**
* If `true`, the server certificate is verified against the list of supplied CAs.
*
* Default: `true`.
*
* https://nodejs.org/api/tls.html#tls_tls_connect_options_callback
*/
rejectUnauthorized?: boolean;
/**
* If `true`, enables SSRF (Server-Side Request Forgery) validation for the HTTP request.
* The request URL will be checked against internal IP addresses and private networks.
*
* Default: `false`
*
* As SSRF validation can potentially break legitimate requests to internal resources, it is not enabled by default.
*/
ssrfValidation?: boolean;
}
export interface IHttpResponse {
url: string;
method: RequestMethod;
statusCode: number;
headers?: {
[key: string]: string;
};
content?: string;
data?: any;
}
export interface IHttpExtend {
/**
* A method for providing a single header which is added to every request.
*
* @param key the name of the header
* @param value the header's content
*/
provideDefaultHeader(key: string, value: string): void;
/**
* A method for providing more than one header which are added to every request.
*
* @param headers an object with strings as the keys (header name) and strings as values (header content)
*/
provideDefaultHeaders(headers: { [key: string]: string }): void;
/**
* A method for providing a single query parameter which is added to every request.
*
* @param key the name of the query parameter
* @param value the query parameter's content
*/
provideDefaultParam(key: string, value: string): void;
/**
* A method for providing more than one query parameters which are added to every request.
*
* @param headers an object with strings as the keys (parameter name) and strings as values (parameter content)
*/
provideDefaultParams(params: { [key: string]: string }): void;
/**
* Method for providing a function which is called before every request is called out to the final destination.
* This can be called more than once which means there can be more than one handler. The order provided is the order called.
* Note: if this handler throws an error when it is executed then the request will be aborted.
*
* @param handler the instance of the IHttpPreRequestHandler
*/
providePreRequestHandler(handler: IHttpPreRequestHandler): void;
/**
* Method for providing a function which is called after every response is got from the url and before the result is returned.
* This can be called more than once which means there can be more than one handler. The order provided is the order called.
* Note: if this handler throws an error when it is executed then the respone will not be returned
*
* @param handler the instance of the IHttpPreResponseHandler
*/
providePreResponseHandler(handler: IHttpPreResponseHandler): void;
/**
* A method for getting all of the default headers provided, the value is a readonly and any modifications done will be ignored.
* Please use the provider methods for adding them.
*/
getDefaultHeaders(): Map<string, string>;
/**
* A method for getting all of the default parameters provided, the value is a readonly and any modifications done will be ignored.
* Please use the provider methods for adding them.
*/
getDefaultParams(): Map<string, string>;
/**
* A method for getting all of the pre-request handlers provided, the value is a readonly and any modifications done will be ignored.
* Please use the provider methods for adding them.
*/
getPreRequestHandlers(): Array<IHttpPreRequestHandler>;
/**
* A method for getting all of the pre-response handlers provided, the value is a readonly and any modifications done will be ignored.
* Please use the provider methods for adding them.
*/
getPreResponseHandlers(): Array<IHttpPreResponseHandler>;
}
export interface IHttpPreRequestHandler {
executePreHttpRequest(url: string, request: IHttpRequest, read: IRead, persistence: IPersistence): Promise<IHttpRequest>;
}
export interface IHttpPreResponseHandler {
executePreHttpResponse(response: IHttpResponse, read: IRead, persistence: IPersistence): Promise<IHttpResponse>;
}
export enum HttpStatusCode {
CONTINUE = 100,
SWITCHING_PROTOCOLS = 101,
OK = 200,
CREATED = 201,
ACCEPTED = 202,
NON_AUTHORITATIVE_INFORMATION = 203,
NO_CONTENT = 204,
RESET_CONTENT = 205,
PARTIAL_CONTENT = 206,
MULTIPLE_CHOICES = 300,
MOVED_PERMANENTLY = 301,
FOUND = 302,
SEE_OTHER = 303,
NOT_MODIFIED = 304,
USE_PROXY = 305,
TEMPORARY_REDIRECT = 307,
BAD_REQUEST = 400,
UNAUTHORIZED = 401,
PAYMENT_REQUIRED = 402,
FORBIDDEN = 403,
NOT_FOUND = 404,
METHOD_NOT_ALLOWED = 405,
NOT_ACCEPTABLE = 406,
PROXY_AUTHENTICATION_REQUIRED = 407,
REQUEST_TIMEOUT = 408,
CONFLICT = 409,
GONE = 410,
LENGTH_REQUIRED = 411,
PRECONDITION_FAILED = 412,
REQUEST_ENTITY_TOO_LARGE = 413,
REQUEST_URI_TOO_LONG = 414,
UNSUPPORTED_MEDIA_TYPE = 415,
REQUESTED_RANGE_NOT_SATISFIABLE = 416,
EXPECTATION_FAILED = 417,
UNPROCESSABLE_ENTITY = 422,
TOO_MANY_REQUESTS = 429,
INTERNAL_SERVER_ERROR = 500,
NOT_IMPLEMENTED = 501,
BAD_GATEWAY = 502,
SERVICE_UNAVAILABLE = 503,
GATEWAY_TIMEOUT = 504,
HTTP_VERSION_NOT_SUPPORTED = 505,
}

View File

@@ -0,0 +1,54 @@
import type { ILivechatRoom, IVisitor, IVisitorExternalIdentifier, ResolveVisitorContactData } from '../livechat';
import type { IUser } from '../users';
export interface IExtraRoomParams {
source?: ILivechatRoom['source'];
customFields?: {
[key: string]: unknown;
};
}
export interface ILivechatCreator {
/**
* Resolves a visitor by external identifier (e.g., WhatsApp BSUID) with contact data fallback.
* If found by contact data (phone or email) but not by externalId, enriches the visitor record with the externalId.
* @param externalId The external identifier containing entityId and optional metadata (e.g., `{ entityId: 'bsuid-123', metadata: { username: '@user' } }`)
* @param contactData Optional contact data for fallback lookup. Use `{ phone: '+1234567890' }` or `{ email: 'user@example.com' }`
* @returns The visitor if found, undefined otherwise
*/
resolveVisitor(
externalId: Omit<IVisitorExternalIdentifier, 'appId'>,
contactData?: ResolveVisitorContactData,
): Promise<IVisitor | undefined>;
/**
* Creates a room to connect the `visitor` to an `agent`.
*
* This method uses the Livechat routing method configured
* in the server
*
* @param visitor The Livechat Visitor that started the conversation
* @param agent The agent responsible for the room
*/
createRoom(visitor: IVisitor, agent: IUser, extraParams?: IExtraRoomParams): Promise<ILivechatRoom>;
/**
* @deprecated Use `createAndReturnVisitor` instead.
* Creates a Livechat visitor
*
* @param visitor Data of the visitor to be created
*/
createVisitor(visitor: IVisitor): Promise<string>;
/**
* Creates a Livechat visitor
*
* @param visitor Data of the visitor to be created
*/
createAndReturnVisitor(visitor: IVisitor): Promise<IVisitor | undefined>;
/**
* Creates a token to be used when
* creating a new livechat visitor
*/
createToken(): string;
}

View File

@@ -0,0 +1,219 @@
import type { ILivechatMessage, IVisitor } from '../livechat';
import type { IMessageAttachment } from '../messages';
import type { RocketChatAssociationModel } from '../metadata';
import type { IRoom } from '../rooms';
import type { IUser } from '../users';
import type { IMessageBuilder } from './IMessageBuilder';
/**
* Interface for building out a livechat message.
* Please note, that a room and sender must be associated otherwise you will NOT
* be able to successfully save the message object.
*/
export interface ILivechatMessageBuilder {
kind: RocketChatAssociationModel.LIVECHAT_MESSAGE;
/**
* Provides a convient way to set the data for the message.
* Note: Providing an "id" field here will be ignored.
*
* @param message the message data to set
*/
setData(message: ILivechatMessage): ILivechatMessageBuilder;
/**
* Sets the room where this message should be sent to.
*
* @param room the room where to send
*/
setRoom(room: IRoom): ILivechatMessageBuilder;
/**
* Gets the room where this message was sent to.
*/
getRoom(): IRoom;
/**
* Sets the sender of this message.
*
* @param sender the user sending the message
*/
setSender(sender: IUser): ILivechatMessageBuilder;
/**
* Gets the User which sent the message.
*/
getSender(): IUser;
/**
* Sets the text of the message.
*
* @param text the actual text
*/
setText(text: string): ILivechatMessageBuilder;
/**
* Gets the message text.
*/
getText(): string;
/**
* Sets the emoji to use for the avatar, this overwrites the current avatar
* whether it be the user's or the avatar url provided.
*
* @param emoji the emoji code
*/
setEmojiAvatar(emoji: string): ILivechatMessageBuilder;
/**
* Gets the emoji used for the avatar.
*/
getEmojiAvatar(): string;
/**
* Sets the url which to display for the avatar, this overwrites the current
* avatar whether it be the user's or an emoji one.
*
* @param avatarUrl image url to use as the avatar
*/
setAvatarUrl(avatarUrl: string): ILivechatMessageBuilder;
/**
* Gets the url used for the avatar.
*/
getAvatarUrl(): string;
/**
* Sets the display text of the sender's username that is visible.
*
* @param alias the username alias to display
*/
setUsernameAlias(alias: string): ILivechatMessageBuilder;
/**
* Gets the display text of the sender's username that is visible.
*/
getUsernameAlias(): string;
/**
* Adds one attachment to the message's list of attachments, this will not
* overwrite any existing ones but just adds.
*
* @param attachment the attachment to add
*/
addAttachment(attachment: IMessageAttachment): ILivechatMessageBuilder;
/**
* Sets the attachments for the message, replacing and destroying all of the current attachments.
*
* @param attachments array of the attachments
*/
setAttachments(attachments: Array<IMessageAttachment>): ILivechatMessageBuilder;
/**
* Gets the attachments array for the message
*/
getAttachments(): Array<IMessageAttachment>;
/**
* Replaces an attachment at the given position (index).
* If there is no attachment at that position, there will be an error thrown.
*
* @param position the index of the attachment to replace
* @param attachment the attachment to replace with
*/
replaceAttachment(position: number, attachment: IMessageAttachment): ILivechatMessageBuilder;
/**
* Removes an attachment at the given position (index).
* If there is no attachment at that position, there will be an error thrown.
*
* @param position the index of the attachment to remove
*/
removeAttachment(position: number): ILivechatMessageBuilder;
/**
* Sets the user who is editing this message.
* This is required if you are modifying an existing message.
*
* @param user the editor
*/
setEditor(user: IUser): ILivechatMessageBuilder;
/**
* Gets the user who edited the message
*/
getEditor(): IUser;
/**
* Sets whether this message can group with others.
* This is desirable if you want to avoid confusion with other integrations.
*
* @param groupable whether this message can group with others
*/
setGroupable(groupable: boolean): ILivechatMessageBuilder;
/**
* Gets whether this message can group with others.
*/
getGroupable(): boolean;
/**
* Sets whether this message should have any URLs in the text
* parsed by Rocket.Chat and get the details added to the message's
* attachments.
*
* @param parseUrls whether URLs should be parsed in this message
*/
setParseUrls(parseUrls: boolean): ILivechatMessageBuilder;
/**
* Gets whether this message should have its URLs parsed
*/
getParseUrls(): boolean;
/**
* Set the token of the livechat visitor that
* sent the message
*
* @param token The Livechat visitor's token
*/
setToken(token: string): ILivechatMessageBuilder;
/**
* Gets the token of the livechat visitor that
* sent the message
*/
getToken(): string;
/**
* If the sender of the message is a Livechat Visitor,
* set the visitor who sent the message.
*
* If you set the visitor property of a message, the
* sender will be emptied
*
* @param visitor The visitor who sent the message
*/
setVisitor(visitor: IVisitor): ILivechatMessageBuilder;
/**
* Get the visitor who sent the message,
* if any
*/
getVisitor(): IVisitor;
/**
* Gets the resulting message that has been built up to the point of calling it.
*
* *Note:* This will error out if the Room has not been defined OR if the room
* is not of type RoomType.LIVE_CHAT.
*/
getMessage(): ILivechatMessage;
/**
* Returns a message builder based on the
* livechat message of this builder
*/
getMessageBuilder(): IMessageBuilder;
}

View File

@@ -0,0 +1,38 @@
import type { IDepartment } from '../livechat';
import type { ILivechatRoom } from '../livechat/ILivechatRoom';
import type { IVisitor } from '../livechat/IVisitor';
import type { IMessage } from '../messages';
export interface ILivechatRead {
/**
* Gets online status of the livechat.
* @param departmentId (optional) the id of the livechat department
* @deprecated use `isOnlineAsync` instead
*/
isOnline(departmentId?: string): boolean;
/**
* Gets online status of the livechat.
* @param departmentId (optional) the id of the livechat department
*/
isOnlineAsync(departmentId?: string): Promise<boolean>;
getDepartmentsEnabledWithAgents(): Promise<Array<IDepartment>>;
getLivechatRooms(visitor: IVisitor, departmentId?: string): Promise<Array<ILivechatRoom>>;
getLivechatOpenRoomsByAgentId(agentId: string): Promise<Array<ILivechatRoom>>;
getLivechatTotalOpenRoomsByAgentId(agentId: string): Promise<number>;
/**
* @deprecated This method does not adhere to the conversion practices applied
* elsewhere in the Apps-Engine and will be removed in the next major version.
* Prefer the alternative methods to fetch visitors.
*/
getLivechatVisitors(query: object): Promise<Array<IVisitor>>;
getLivechatVisitorById(id: string): Promise<IVisitor | undefined>;
getLivechatVisitorByEmail(email: string): Promise<IVisitor | undefined>;
getLivechatVisitorByToken(token: string): Promise<IVisitor | undefined>;
getLivechatVisitorByPhoneNumber(phoneNumber: string): Promise<IVisitor | undefined>;
getLivechatDepartmentByIdOrName(value: string): Promise<IDepartment | undefined>;
/**
* @experimental we do not encourage the wider usage of this method,
* as we're evaluating its performance and fit for the API.
*/
_fetchLivechatRoomMessages(roomId: string): Promise<Array<IMessage>>;
}

View File

@@ -0,0 +1,45 @@
import type { ILivechatTransferData, IVisitor, IVisitorExternalIdentifier } from '../livechat';
import type { IRoom } from '../rooms';
import type { IUser } from '../users';
export interface ILivechatUpdater {
/**
* Transfer a Livechat visitor to another room
*
* @param visitor Visitor to be transferred
* @param transferData The data to execute the transferring
*/
transferVisitor(visitor: IVisitor, transferData: ILivechatTransferData): Promise<boolean>;
/**
* Closes a Livechat room
*
* @param room The room to be closed
* @param comment The comment explaining the reason for closing the room
* @param closer The user that closes the room
*/
closeRoom(room: IRoom, comment: string, closer?: IUser): Promise<boolean>;
/**
* Set a livechat visitor's custom fields by its token
* @param token The visitor's token
* @param key The key in the custom fields
* @param value The value to be set
* @param overwrite Whether overwrite or not
*
* @returns Promise to whether success or not
*/
setCustomFields(token: IVisitor['token'], key: string, value: string, overwrite: boolean): Promise<boolean>;
/**
* Updates or adds an external identifier for a visitor.
* The appId is automatically set to the calling app's ID.
* If an externalId with the same appId already exists, it will be replaced.
*
* @param visitorId The visitor's ID
* @param externalId The external identifier containing entityId and optional metadata
*
* @returns Promise resolving to the updated visitor, or undefined if not found
*/
updateVisitorExternalId(visitorId: string, externalId: Omit<IVisitorExternalIdentifier, 'appId'>): Promise<IVisitor | undefined>;
}

View File

@@ -0,0 +1,24 @@
export enum LogMessageSeverity {
DEBUG = 'debug',
INFORMATION = 'info',
LOG = 'log',
WARNING = 'warning',
ERROR = 'error',
SUCCESS = 'success',
}
/**
* Message which will be passed to a UI (either in a log or in the application's UI)
*/
export interface ILogEntry {
/** The function name who did this logging, this is automatically added (can be null). */
caller?: string;
/** The severity rate, this is automatically added. */
severity: LogMessageSeverity;
/** When this entry was made. */
timestamp: Date;
/** The items which were logged. */
args: Array<any>;
/** The method which was logged. */
method?: string;
}

View File

@@ -0,0 +1,29 @@
import type { ILogEntry } from './ILogEntry';
import type { AppMethod } from '../metadata/AppMethod';
/**
* This logger provides a way to log various levels to the entire system.
* When used, the items passed in will be logged to the database. This will
* allow people to easily see what happened (users) or debug what went wrong.
*/
export interface ILogger {
method: `${AppMethod}`;
debug(...items: Array<any>): void;
info(...items: Array<any>): void;
log(...items: Array<any>): void;
warn(...items: Array<any>): void;
error(...items: Array<any>): void;
success(...items: Array<any>): void;
/** Gets the entries logged. */
getEntries(): Array<ILogEntry>;
/** Gets the method which this logger is for. */
getMethod(): `${AppMethod}`;
/** Gets when this logger was constructed. */
getStartTime(): Date;
/** Gets the end time, usually Date.now(). */
getEndTime(): Date;
/** Gets the amount of time this was a logger, start - Date.now(). */
getTotalTime(): number;
}

View File

@@ -0,0 +1,236 @@
import type { LayoutBlock } from '@rocket.chat/ui-kit';
import type { IMessage, IMessageAttachment } from '../messages';
import type { RocketChatAssociationModel } from '../metadata';
import type { IRoom } from '../rooms';
import type { BlockBuilder, IBlock } from '../uikit';
import type { IUser } from '../users';
/**
* Interface for building out a message.
* Please note, that a room and sender must be associated otherwise you will NOT
* be able to successfully save the message object.
*/
export interface IMessageBuilder {
kind: RocketChatAssociationModel.MESSAGE;
/**
* Provides a convenient way to set the data for the message.
* Note: Providing an "id" field here will be ignored.
*
* @param message the message data to set
*/
setData(message: IMessage): IMessageBuilder;
/**
* Provides a convenient way to set the data for the message
* keeping the "id" field so as to update the message later.
*
* @param message the message data to set
* @param editor the user who edited the updated message
*/
setUpdateData(message: IMessage, editor: IUser): IMessageBuilder;
/**
* Sets the thread to which this message belongs, if any.
*
* @param threadId The id of the thread
*/
setThreadId(threadId: string): IMessageBuilder;
/**
* Retrieves the threadId to which this message belongs,
* if any.
*
* If you would like to retrieve the actual message that
* the thread originated from, you can use the
* `IMessageRead.getById()` method
*/
getThreadId(): string;
/**
* Sets the room where this message should be sent to.
*
* @param room the room where to send
*/
setRoom(room: IRoom): IMessageBuilder;
/**
* Gets the room where this message was sent to.
*/
getRoom(): IRoom;
/**
* Sets the sender of this message.
*
* @param sender the user sending the message
*/
setSender(sender: IUser): IMessageBuilder;
/**
* Gets the User which sent the message.
*/
getSender(): IUser;
/**
* Sets the text of the message.
*
* @param text the actual text
*/
setText(text: string): IMessageBuilder;
/**
* Gets the message text.
*/
getText(): string;
/**
* Sets the emoji to use for the avatar, this overwrites the current avatar
* whether it be the user's or the avatar url provided.
*
* @param emoji the emoji code
*/
setEmojiAvatar(emoji: string): IMessageBuilder;
/**
* Gets the emoji used for the avatar.
*/
getEmojiAvatar(): string;
/**
* Sets the url which to display for the avatar, this overwrites the current
* avatar whether it be the user's or an emoji one.
*
* @param avatarUrl image url to use as the avatar
*/
setAvatarUrl(avatarUrl: string): IMessageBuilder;
/**
* Gets the url used for the avatar.
*/
getAvatarUrl(): string;
/**
* Sets the display text of the sender's username that is visible.
*
* @param alias the username alias to display
*/
setUsernameAlias(alias: string): IMessageBuilder;
/**
* Gets the display text of the sender's username that is visible.
*/
getUsernameAlias(): string;
/**
* Adds one attachment to the message's list of attachments, this will not
* overwrite any existing ones but just adds.
*
* @param attachment the attachment to add
*/
addAttachment(attachment: IMessageAttachment): IMessageBuilder;
/**
* Sets the attachments for the message, replacing and destroying all of the current attachments.
*
* @param attachments array of the attachments
*/
setAttachments(attachments: Array<IMessageAttachment>): IMessageBuilder;
/**
* Gets the attachments array for the message
*/
getAttachments(): Array<IMessageAttachment>;
/**
* Replaces an attachment at the given position (index).
* If there is no attachment at that position, there will be an error thrown.
*
* @param position the index of the attachment to replace
* @param attachment the attachment to replace with
*/
replaceAttachment(position: number, attachment: IMessageAttachment): IMessageBuilder;
/**
* Removes an attachment at the given position (index).
* If there is no attachment at that position, there will be an error thrown.
*
* @param position the index of the attachment to remove
*/
removeAttachment(position: number): IMessageBuilder;
/**
* Sets the user who is editing this message.
* This is required if you are modifying an existing message.
*
* @param user the editor
*/
setEditor(user: IUser): IMessageBuilder;
/**
* Gets the user who edited the message
*/
getEditor(): IUser;
/**
* Sets whether this message can group with others.
* This is desirable if you want to avoid confusion with other integrations.
*
* @param groupable whether this message can group with others
*/
setGroupable(groupable: boolean): IMessageBuilder;
/**
* Gets whether this message can group with others.
*/
getGroupable(): boolean;
/**
* Sets whether this message should have any URLs in the text
* parsed by Rocket.Chat and get the details added to the message's
* attachments.
*
* @param parseUrls whether URLs should be parsed in this message
*/
setParseUrls(parseUrls: boolean): IMessageBuilder;
/**
* Gets whether this message should have its URLs parsed
*/
getParseUrls(): boolean;
/**
* Gets the resulting message that has been built up to the point of calling it.
*
* *Note:* This will error out if the Room has not been defined.
*/
getMessage(): IMessage;
/**
* Adds a block collection to the message's
* own collection
*/
addBlocks(blocks: BlockBuilder | Array<IBlock | LayoutBlock>): IMessageBuilder;
/**
* Sets the block collection of the message
*
* @param blocks
*/
setBlocks(blocks: BlockBuilder | Array<IBlock | LayoutBlock>): IMessageBuilder;
/**
* Gets the block collection of the message
*/
getBlocks(): Array<IBlock | LayoutBlock>;
/**
* Adds a custom field to the message.
* Note: This key can not already exist or it will throw an error.
* Note: The key must not contain a period in it, an error will be thrown.
*
* @param key the name of the custom field
* @param value the value of this custom field
*/
addCustomField(key: string, value: any): IMessageBuilder;
}

View File

@@ -0,0 +1,36 @@
import type { IMessage, IMessageAttachment } from '../messages';
import type { RocketChatAssociationModel } from '../metadata';
export interface IMessageExtender {
kind: RocketChatAssociationModel.MESSAGE;
/**
* Adds a custom field to the message.
* Note: This key can not already exist or it will throw an error.
* Note: The key must not contain a period in it, an error will be thrown.
*
* @param key the name of the custom field
* @param value the value of this custom field
*/
addCustomField(key: string, value: any): IMessageExtender;
/**
* Adds a single attachment to the message.
*
* @param attachment the item to add
*/
addAttachment(attachment: IMessageAttachment): IMessageExtender;
/**
* Adds all of the provided attachments to the message.
*
* @param attachments an array of attachments
*/
addAttachments(attachments: Array<IMessageAttachment>): IMessageExtender;
/**
* Gets the resulting message that has been extended at the point of calling it.
* Note: modifying the returned value will have no effect.
*/
getMessage(): IMessage;
}

View File

@@ -0,0 +1,15 @@
import type { IMessage } from '../messages/index';
import type { IRoom } from '../rooms/IRoom';
import type { IUser } from '../users/IUser';
/**
* This accessor provides methods for accessing
* messages in a read-only-fashion.
*/
export interface IMessageRead {
getById(id: string): Promise<IMessage | undefined>;
getSenderUser(messageId: string): Promise<IUser | undefined>;
getRoom(messageId: string): Promise<IRoom | undefined>;
}

View File

@@ -0,0 +1,21 @@
import type { Reaction } from '../messages';
export interface IMessageUpdater {
/**
* Add a reaction to a message
*
* @param messageId the id of the message
* @param userId the id of the user
* @param reaction the reaction
*/
addReaction(messageId: string, userId: string, reaction: Reaction): Promise<void>;
/**
* Remove a reaction from a message
*
* @param messageId the id of the message
* @param userId the id of the user
* @param reaction the reaction
*/
removeReaction(messageId: string, userId: string, reaction: Reaction): Promise<void>;
}

View File

@@ -0,0 +1,27 @@
import type { IMessage } from '../messages';
import type { IUser } from '../users';
export interface IModerationModify {
/**
* Provides a way for Apps to report a message.
* @param messageId the messageId to report
* @param description the description of the report
* @param userId the userId to be reported
* @param appId the app id
*/
report(messageId: string, description: string, userId: string, appId: string): Promise<void>;
/**
* Provides a way for Apps to dismiss reports by message id.
* @param messageId the messageId to dismiss reports
* @param appId the app id
*/
dismissReportsByMessageId(messageId: IMessage['id'], reason: string, action: string, appId: string): Promise<void>;
/**
* Provides a way for Apps to dismiss reports by user id.
* @param userId the userId to dismiss reports
* @param appId the app id
*/
dismissReportsByUserId(userId: IUser['id'], reason: string, action: string, appId: string): Promise<void>;
}

View File

@@ -0,0 +1,45 @@
import type { IModerationModify } from './IModerationModify';
import type { IModifyCreator } from './IModifyCreator';
import type { IModifyDeleter } from './IModifyDeleter';
import type { IModifyExtender } from './IModifyExtender';
import type { IModifyUpdater } from './IModifyUpdater';
import type { INotifier } from './INotifier';
import type { IOAuthAppsModify } from './IOAuthAppsModify';
import type { ISchedulerModify } from './ISchedulerModify';
import type { IUIController } from './IUIController';
export interface IModify {
getCreator(): IModifyCreator;
getDeleter(): IModifyDeleter;
getExtender(): IModifyExtender;
getUpdater(): IModifyUpdater;
/**
* Gets the accessor for sending notifications to a user or users in a room.
*
* @returns the notifier accessor
*/
getNotifier(): INotifier;
/**
* Gets the accessor for interacting with the UI
*/
getUiController(): IUIController;
/**
* Gets the accessor for creating scheduled jobs
*/
getScheduler(): ISchedulerModify;
/**
* Gets the accessor for creating OAuth apps
*/
getOAuthAppsModifier(): IOAuthAppsModify;
/**
* Gets the accessor for modifying moderation
* @returns the moderation accessor
*/
getModerationModifier(): IModerationModify;
}

View File

@@ -0,0 +1,108 @@
import type { ILivechatMessage } from '../livechat';
import type { IMessage } from '../messages';
import type { IRoom } from '../rooms';
import type { BlockBuilder } from '../uikit';
import type { IBotUser } from '../users/IBotUser';
import type { AppVideoConference } from '../videoConferences';
import type { IContactCreator } from './IContactCreator';
import type { IDiscussionBuilder } from './IDiscussionBuilder';
import type { IEmailCreator } from './IEmailCreator';
import type { ILivechatCreator } from './ILivechatCreator';
import type { ILivechatMessageBuilder } from './ILivechatMessageBuilder';
import type { IMessageBuilder } from './IMessageBuilder';
import type { IRoomBuilder } from './IRoomBuilder';
import type { IUploadCreator } from './IUploadCreator';
import type { IUserBuilder } from './IUserBuilder';
import type { IVideoConferenceBuilder } from './IVideoConferenceBuilder';
export interface IModifyCreator {
/**
* Get the creator object responsible for the
* Livechat integrations
*/
getLivechatCreator(): ILivechatCreator;
/**
* Get the creator object responsible for the upload.
*/
getUploadCreator(): IUploadCreator;
/**
* Gets the creator object responsible for email sending
*/
getEmailCreator(): IEmailCreator;
/**
* Gets the creator object responsible for contact related operations.
*/
getContactCreator(): IContactCreator;
/**
* @deprecated please prefer the rocket.chat/ui-kit components
*
* Gets a new instance of a BlockBuilder
*/
getBlockBuilder(): BlockBuilder;
/**
* Starts the process for building a new message object.
*
* @param data (optional) the initial data to pass into the builder,
* the `id` property will be ignored
* @return an IMessageBuilder instance
*/
startMessage(data?: IMessage): IMessageBuilder;
/**
* Starts the process for building a new livechat message object.
*
* @param data (optional) the initial data to pass into the builder,
* the `id` property will be ignored
* @return an IMessageBuilder instance
*/
startLivechatMessage(data?: ILivechatMessage): ILivechatMessageBuilder;
/**
* Starts the process for building a new room.
*
* @param data (optional) the initial data to pass into the builder,
* the `id` property will be ignored
* @return an IRoomBuilder instance
*/
startRoom(data?: IRoom): IRoomBuilder;
/**
* Starts the process for building a new discussion.
*
* @param data (optional) the initial data to pass into the builder,
* the `id` property will be ignored
* @return an IDiscussionBuilder instance
*/
startDiscussion(data?: Partial<IRoom>): IDiscussionBuilder;
/**
* Starts the process for building a new video conference.
*
* @param data (optional) the initial data to pass into the builder,
* @return an IVideoConferenceBuilder instance
*/
startVideoConference(data?: Partial<AppVideoConference>): IVideoConferenceBuilder;
/**
* Starts the process for building a new bot user.
*
* @param data (optional) the initial data to pass into the builder,
* the `id` property will be ignored
* @return an IUserBuilder instance
*/
startBotUser(data?: Partial<IBotUser>): IUserBuilder;
/**
* Finishes the creating process, saving the object to the database.
*
* @param builder the builder instance
* @return the resulting `id` of the resulting object
*/
finish(
builder: IMessageBuilder | ILivechatMessageBuilder | IRoomBuilder | IDiscussionBuilder | IVideoConferenceBuilder | IUserBuilder,
): Promise<string>;
}

View File

@@ -0,0 +1,12 @@
import type { IMessage } from '../messages';
import type { IUser, UserType } from '../users';
export interface IModifyDeleter {
deleteRoom(roomId: string): Promise<void>;
deleteUsers(appId: Exclude<IUser['appId'], undefined>, userType: UserType.APP | UserType.BOT): Promise<boolean>;
deleteMessage(message: IMessage, user: IUser): Promise<void>;
removeUsersFromRoom(roomId: string, usernames: Array<string>): Promise<void>;
}

View File

@@ -0,0 +1,40 @@
import type { IUser } from '../users';
import type { IMessageExtender } from './IMessageExtender';
import type { IRoomExtender } from './IRoomExtender';
import type { IVideoConferenceExtender } from './IVideoConferenceExtend';
export interface IModifyExtender {
/**
* Modifies a message in a non-destructive way: Properties can be added to it,
* but existing properties cannot be changed.
*
* @param messageId the id of the message to be extended
* @param updater the user who is updating/extending the message
* @return the extender instance for the message
*/
extendMessage(messageId: string, updater: IUser): Promise<IMessageExtender>;
/**
* Modifies a room in a non-destructive way: Properties can be added to it,
* but existing properties cannot be changed.
*
* @param roomId the id of the room to be extended
* @param updater the user who is updating/extending the room
* @return the extender instance for the room
*/
extendRoom(roomId: string, updater: IUser): Promise<IRoomExtender>;
/**
* Modifies a video conference in a non-destructive way: Properties can be added to it,
* but existing properties cannot be changed.
*/
extendVideoConference(id: string): Promise<IVideoConferenceExtender>;
/**
* Finishes the extending process, saving the object to the database.
* Note: If there is an issue or error while updating, this will throw an error.
*
* @param extender the extender instance
*/
finish(extender: IRoomExtender | IMessageExtender | IVideoConferenceExtender): Promise<void>;
}

View File

@@ -0,0 +1,52 @@
import type { IUser } from '../users';
import type { ILivechatUpdater } from './ILivechatUpdater';
import type { IMessageBuilder } from './IMessageBuilder';
import type { IMessageUpdater } from './IMessageUpdater';
import type { IRoomBuilder } from './IRoomBuilder';
import type { IUserUpdater } from './IUserUpdater';
export interface IModifyUpdater {
/**
* Get the updater object responsible for the
* Livechat integrations
*/
getLivechatUpdater(): ILivechatUpdater;
/**
* Gets the update object responsible for
* methods that update users
*/
getUserUpdater(): IUserUpdater;
/**
* Get the updater object responsible for
* methods that update messages
*/
getMessageUpdater(): IMessageUpdater;
/**
* Modifies an existing message.
* Raises an exception if a non-existent messageId is supplied
*
* @param messageId the id of the existing message to modfiy and build
* @param updater the user who is updating the message
*/
message(messageId: string, updater: IUser): Promise<IMessageBuilder>;
/**
* Modifies an existing room.
* Raises an exception if a non-existent roomId is supplied
*
* @param roomId the id of the existing room to modify and build
* @param updater the user who is updating the room
*/
room(roomId: string, updater: IUser): Promise<IRoomBuilder>;
/**
* Finishes the updating process, saving the object to the database.
* Note: If there is an issue or error while updating, this will throw an error.
*
* @param builder the builder instance
*/
finish(builder: IMessageBuilder | IRoomBuilder): Promise<void>;
}

View File

@@ -0,0 +1,63 @@
import type { IMessage } from '../messages';
import type { IRoom } from '../rooms';
import type { IUser } from '../users';
import type { IMessageBuilder } from './IMessageBuilder';
export enum TypingScope {
Room = 'room',
}
export interface ITypingOptions {
/**
* The typing scope where the typing message should be presented,
* TypingScope.Room by default.
*/
scope?: TypingScope;
/**
* The id of the typing scope
*
* TypingScope.Room <-> room.id
*/
id: string;
/**
* The name of the user who is typing the message
*
* **Note**: If not provided, it will use app assigned
* user's name by default.
*/
username?: string;
}
export interface INotifier {
/**
* Notifies the provided user of the provided message.
*
* **Note**: Notifications only are shown to the user if they are
* online and it only stays around for the duration of their session.
*
* @param user The user who should be notified
* @param message The message with the content to notify the user about
*/
notifyUser(user: IUser, message: IMessage): Promise<void>;
/**
* Notifies all of the users in the provided room.
*
* **Note**: Notifications only are shown to those online
* and it only stays around for the duration of their session.
*
* @param room The room which to notify the users in
* @param message The message content to notify users about
*/
notifyRoom(room: IRoom, message: IMessage): Promise<void>;
/**
* Notifies all of the users a typing indicator in the provided scope.
*
* @returns a cancellation function to stop typing
*/
typing(options: ITypingOptions): Promise<() => Promise<void>>;
/** Gets a new message builder for building a notification message. */
getMessageBuilder(): IMessageBuilder;
}

View File

@@ -0,0 +1,13 @@
export interface IOAuthApp {
id: string;
name: string;
active: boolean;
clientId?: string;
clientSecret?: string;
redirectUri: string;
createdAt?: string;
updatedAt?: string;
createdBy: { username: string; id: string };
}
export type IOAuthAppParams = Omit<IOAuthApp, 'id' | 'createdAt' | 'updatedAt' | 'createdBy' | 'appId'>;

View File

@@ -0,0 +1,23 @@
import type { IOAuthAppParams } from './IOAuthApp';
export interface IOAuthAppsModify {
/**
* Create an OAuthApp
* @param OAuthApp - the OAuth app to create, in case the clientId and the clientSecret is not sent it will generate automatically
* @param appId - the app id
*/
createOAuthApp(OAuthApp: IOAuthAppParams, appId: string): Promise<string>;
/**
* Update the OAuth app info
* @param OAuthApp - OAuth data that will be updated
* @param id - OAuth app id
* @param appId - the app id
*/
updateOAuthApp(OAuthApp: IOAuthAppParams, id: string, appId: string): Promise<void>;
/**
* Deletes the OAuth app
* @param id - OAuth app id
* @param appId - the app id
*/
deleteOAuthApp(id: string, appId: string): Promise<void>;
}

View File

@@ -0,0 +1,16 @@
import type { IOAuthApp } from './IOAuthApp';
export interface IOAuthAppsReader {
/**
* Returns the OAuth app info by its id
* @param id - OAuth app id
* @param appId - the app id
*/
getOAuthAppById(id: string, appId: string): Promise<IOAuthApp>;
/**
* Returns the OAuth app info by its name
* @param name - OAuth app name
* @param appId - the app id
*/
getOAuthAppByName(name: string, appId: string): Promise<Array<IOAuthApp>>;
}

View File

@@ -0,0 +1,6 @@
import type { IOutboundEmailMessageProvider, IOutboundPhoneMessageProvider } from '../outboundCommunication';
export interface IOutboundCommunicationProviderExtend {
registerPhoneProvider(provider: IOutboundPhoneMessageProvider): Promise<void>;
registerEmailProvider(provider: IOutboundEmailMessageProvider): Promise<void>;
}

View File

@@ -0,0 +1,97 @@
import type { RocketChatAssociationRecord } from '../metadata';
/**
* Provides an accessor write data to the App's persistent storage.
* A App only has access to its own persistent storage and does not
* have access to any other App's.
*/
export interface IPersistence {
/**
* Creates a new record in the App's persistent storage, returning the resulting "id".
*
* @param data the actual data to store, must be an object otherwise it will error out.
* @return the resulting record's id
*/
create(data: object): Promise<string>;
/**
* Creates a new record in the App's persistent storage with the associated information
* being provided.
*
* @param data the actual data to store, must be an object otherwise it will error out
* @param association the association data which includes the model and record id
* @return the resulting record's id
*/
createWithAssociation(data: object, association: RocketChatAssociationRecord): Promise<string>;
/**
* Creates a new record in the App's persistent storage with the data being
* associated with more than one Rocket.Chat record.
*
* @param data the actual data to store, must be an object otherwise it will error out
* @param associations an array of association data which includes the model and record id
* @return the resulting record's id
*/
createWithAssociations(data: object, associations: Array<RocketChatAssociationRecord>): Promise<string>;
/**
* Updates an existing record with the data provided in the App's persistent storage.
* This will throw an error if the record doesn't currently exist or if the data is not an object.
*
* @param id the data record's id
* @param data the actual data to store, must be an object otherwise it will error out
* @param upsert whether a record should be created if the id to be updated does not exist
* @return the id of the updated/upserted record
*/
update(id: string, data: object, upsert?: boolean): Promise<string>;
/**
* Updates an existing record with the data provided in the App's persistent storage which are
* associated with provided information.
* This will throw an error if the record doesn't currently exist or if the data is not an object.
*
* @param association the association record
* @param data the actual data to store, must be an object otherwise it will error out
* @param upsert whether a record should be created if the id to be updated does not exist
* @return the id of the updated/upserted record
*/
updateByAssociation(association: RocketChatAssociationRecord, data: object, upsert?: boolean): Promise<string>;
/**
* Updates an existing record with the data provided in the App's persistent storage which are
* associated with more than one Rocket.Chat record.
* This will throw an error if the record doesn't currently exist or if the data is not an object.
*
* @param associations an array of association data which includes the model and record id
* @param data the actual data to store, must be an object otherwise it will error out
* @param upsert whether a record should be created if the id to be updated does not exist
* @return the id of the updated/upserted record
*/
updateByAssociations(associations: Array<RocketChatAssociationRecord>, data: object, upsert?: boolean): Promise<string>;
/**
* Removes a record by the provided id and returns the removed record.
*
* @param id of the record to remove
* @return the data record which was removed
*/
remove(id: string): Promise<object>;
/**
* Removes all of the records in persistent storage which are associated with the provided information.
*
* @param association the information about the association for the records to be removed
* @return the data of the removed records
*/
removeByAssociation(association: RocketChatAssociationRecord): Promise<Array<object>>;
/**
* Removes all of the records in persistent storage which are associated with the provided information.
* More than one association acts like an AND which means a record in persistent storage must have all
* of the associations to be considered a match.
*
* @param associations the information about the associations for the records to be removed
* @return the data of the removed records
*/
removeByAssociations(associations: Array<RocketChatAssociationRecord>): Promise<Array<object>>;
}

View File

@@ -0,0 +1,40 @@
import type { RocketChatAssociationRecord } from '../metadata';
/**
* Provides a read-only accessor for the App's persistent storage.
* A App only has access to its own persistent storage and does not
* have access to any other App's.
*/
export interface IPersistenceRead {
/**
* Retrieves a record from the App's persistent storage by the provided id.
* A "falsey" value (undefined or null or false) is returned should nothing exist
* in the storage by the provided id.
*
* @param id the record to get's id
* @return the record if it exists, falsey if not
*/
read(id: string): Promise<object>;
/**
* Retrieves a record from the App's persistent storage by the provided id.
* An empty array is returned should there be no records associated with the
* data provided.
*
* @param association the association record to query the persistent storage for
* @return array of the records if any exists, empty array if none exist
*/
readByAssociation(association: RocketChatAssociationRecord): Promise<Array<object>>;
/**
* Retrieves a record from the App's persistent storage by the provided id.
* Providing more than one association record acts like an AND which means a record
* in persistent storage must have all of the associations to be considered a match.
* An empty array is returned should there be no records associated with the
* data provided.
*
* @param associations the association records to query the persistent storage for
* @return array of the records if any exists, empty array if none exist
*/
readByAssociations(associations: Array<RocketChatAssociationRecord>): Promise<Array<object>>;
}

View File

@@ -0,0 +1,57 @@
import type { ICloudWorkspaceRead } from './ICloudWorkspaceRead';
import type { IContactRead } from './IContactRead';
import type { IEnvironmentRead } from './IEnvironmentRead';
import type { IExperimentalRead } from './IExperimentalRead';
import type { ILivechatRead } from './ILivechatRead';
import type { IMessageRead } from './IMessageRead';
import type { INotifier } from './INotifier';
import type { IOAuthAppsReader } from './IOAuthAppsReader';
import type { IPersistenceRead } from './IPersistenceRead';
import type { IRoleRead } from './IRoleRead';
import type { IRoomRead } from './IRoomRead';
import type { IThreadRead } from './IThreadRead';
import type { IUploadRead } from './IUploadRead';
import type { IUserRead } from './IUserRead';
import type { IVideoConferenceRead } from './IVideoConferenceRead';
/**
* The IRead accessor provides methods for accessing the
* Rocket.Chat's environment in a read-only-fashion.
* It is safe to be injected in multiple places, idempotent and extensible
*/
export interface IRead {
/** Gets the IEnvironmentRead instance, contains settings and environmental variables. */
getEnvironmentReader(): IEnvironmentRead;
/** Gets the IThreadRead instance */
getThreadReader(): IThreadRead;
/** Gets the IMessageRead instance. */
getMessageReader(): IMessageRead;
/** Gets the IPersistenceRead instance. */
getPersistenceReader(): IPersistenceRead;
/** Gets the IRoomRead instance. */
getRoomReader(): IRoomRead;
/** Gets the IUserRead instance. */
getUserReader(): IUserRead;
/** Gets the INotifier for notifying users/rooms. */
getNotifier(): INotifier;
getLivechatReader(): ILivechatRead;
getUploadReader(): IUploadRead;
getCloudWorkspaceReader(): ICloudWorkspaceRead;
getVideoConferenceReader(): IVideoConferenceRead;
getOAuthAppsReader(): IOAuthAppsReader;
getRoleReader(): IRoleRead;
getContactReader(): IContactRead;
getExperimentalReader(): IExperimentalRead;
}

View File

@@ -0,0 +1,27 @@
import type { IRole } from '../roles';
/**
* Interface for reading roles.
*/
export interface IRoleRead {
/**
* Retrieves a role by its id or name.
* @param idOrName The id or name of the role to retrieve.
* @param appId The id of the app.
* @returns The role, if found.
* @returns null if no role is found.
* @throws If there is an error while retrieving the role.
*/
getOneByIdOrName(idOrName: string, appId: string): Promise<IRole | null>;
/**
* Retrieves all custom roles.
* @param appId The id of the app.
* @returns All custom roles.
* @throws If there is an error while retrieving the roles.
* @throws If the app does not have the necessary permissions.
* @see IRole.protected
* @see AppPermissions.role.read
*/
getCustomRoles(appId: string): Promise<Array<IRole>>;
}

View File

@@ -0,0 +1,186 @@
import type { RocketChatAssociationModel } from '../metadata';
import type { IRoom, RoomType } from '../rooms';
import type { IUser } from '../users';
/**
* Interface for building out a room.
* Please note, a room creator, name, and type must be set otherwise you will NOT
* be able to successfully save the room object.
*/
export interface IRoomBuilder {
kind: RocketChatAssociationModel.ROOM | RocketChatAssociationModel.DISCUSSION;
/**
* Provides a convient way to set the data for the room.
* Note: Providing an "id" field here will be ignored.
*
* @param room the room data to set
*/
setData(room: Partial<IRoom>): IRoomBuilder;
/**
* Sets the display name of this room.
*
* @param name the display name of the room
*/
setDisplayName(name: string): IRoomBuilder;
/**
* Gets the display name of this room.
*/
getDisplayName(): string;
/**
* Sets the slugified name of this room, it must align to the rules of Rocket.Chat room
* names otherwise there will be an error thrown (no spaces, special characters, etc).
*
* @param name the slugified name
*/
setSlugifiedName(name: string): IRoomBuilder;
/**
* Gets the slugified name of this room.
*/
getSlugifiedName(): string;
/**
* Sets the room's type.
*
* @param type the room type
*/
setType(type: RoomType): IRoomBuilder;
/**
* Gets the room's type.
*/
getType(): RoomType;
/**
* Sets the creator of the room.
*
* @param creator the user who created the room
*/
setCreator(creator: IUser): IRoomBuilder;
/**
* Gets the room's creator.
*/
getCreator(): IUser;
/**
* Adds a user to the room, these are by username until further notice.
*
* @param username the user's username to add to the room
* @deprecated in favor of `addMemberToBeAddedByUsername`. This method will be removed on version 2.0.0
*/
addUsername(username: string): IRoomBuilder;
/**
* Sets the usernames of who are joined to the room.
*
* @param usernames the list of usernames
* @deprecated in favor of `setMembersByUsernames`. This method will be removed on version 2.0.0
*/
setUsernames(usernames: Array<string>): IRoomBuilder;
/**
* Gets the usernames of users in the room.
* @deprecated in favor of `getMembersUsernames`. This method will be removed on version 2.0.0
*/
getUsernames(): Array<string>;
/**
* Adds a member to the room by username
*
* @param username the user's username to add to the room
*/
addMemberToBeAddedByUsername(username: string): IRoomBuilder;
/**
* Sets a list of members to the room by usernames
*
* @param usernames the list of usernames
*/
setMembersToBeAddedByUsernames(usernames: Array<string>): IRoomBuilder;
/**
* Gets the list of usernames of the members who are been added to the room
*/
getMembersToBeAddedUsernames(): Array<string>;
/**
* Sets whether this room should be a default room or not.
* This means that new users will automatically join this room
* when they join the server.
*
* @param isDefault room should be default or not
*/
setDefault(isDefault: boolean): IRoomBuilder;
/**
* Gets whether this room is a default room or not.
*/
getIsDefault(): boolean;
/**
* Sets whether this room should be in read only state or not.
* This means that users without the required permission to talk when
* a room is muted will not be able to talk but instead will only be
* able to read the contents of the room.
*
* @param isReadOnly whether it should be read only or not
*/
setReadOnly(isReadOnly: boolean): IRoomBuilder;
/**
* Gets whether this room is on read only state or not.
*/
getIsReadOnly(): boolean;
/**
* Sets whether this room should display the system messages (like user join, etc)
* or not. This means that whenever a system event, such as joining or leaving, happens
* then Rocket.Chat won't send the message to the channel.
*
* @param displaySystemMessages whether the messages should display or not
*/
setDisplayingOfSystemMessages(displaySystemMessages: boolean): IRoomBuilder;
/**
* Gets whether this room should display the system messages or not.
*/
getDisplayingOfSystemMessages(): boolean;
/**
* Adds a custom field to the room.
* Note: This will replace an existing field with the same key should it exist already.
*
* @param key the name of the key
* @param value the value of the custom field
*/
addCustomField(key: string, value: object): IRoomBuilder;
/**
* Sets the entire custom field property to an object provided. This will overwrite
* every existing key/values which are unrecoverable.
*
* @param fields the data to set
*/
setCustomFields(fields: { [key: string]: object }): IRoomBuilder;
/**
* Gets the custom field property of the room.
*/
getCustomFields(): { [key: string]: object };
/**
* Gets user ids of members from a direct message
*/
getUserIds(): Array<string>;
/**
* Gets the resulting room that has been built up to the point of calling this method.
* Note: modifying the returned value will have no effect.
*/
getRoom(): IRoom;
}

View File

@@ -0,0 +1,40 @@
import type { RocketChatAssociationModel } from '../metadata';
import type { IRoom } from '../rooms';
import type { IUser } from '../users';
export interface IRoomExtender {
kind: RocketChatAssociationModel.ROOM;
/**
* Adds a custom field to the room.
* Note: This key can not already exist or it will throw an error.
* Note: The key must not contain a period in it, an error will be thrown.
*
* @param key the name of the custom field
* @param value the value of this custom field
*/
addCustomField(key: string, value: any): IRoomExtender;
/**
* Adds a user to the room.
*
* @param user the user which is to be added to the room
*/
addMember(user: IUser): IRoomExtender;
/**
* Get a list of users being added to the room.
*/
getMembersBeingAdded(): Array<IUser>;
/**
* Get a list of usernames of users being added to the room.
*/
getUsernamesOfMembersBeingAdded(): Array<string>;
/**
* Gets the resulting room that has been extended at the point of calling this.
* Note: modifying the returned value will have no effect.
*/
getRoom(): IRoom;
}

View File

@@ -0,0 +1,122 @@
import type { IMessageRaw } from '../messages/index';
import type { GetMessagesOptions, GetRoomsFilters, GetRoomsOptions } from '../rooms/IGetMessagesOptions';
import type { IRoom, IRoomRaw } from '../rooms/index';
import type { IUser } from '../users/index';
/**
* This accessor provides methods for accessing
* rooms in a read-only-fashion.
*/
export interface IRoomRead {
/**
* Gets a room by an id.
*
* @param id the id of the room
* @returns the room
*/
getById(id: string): Promise<IRoom | undefined>;
/**
* Gets just the creator of the room by the room's id.
*
* @param id the id of the room
* @returns the creator of the room
*/
getCreatorUserById(id: string): Promise<IUser | undefined>;
/**
* Gets a room by its name.
*
* @param name the name of the room
* @returns the room
*/
getByName(name: string): Promise<IRoom | undefined>;
/**
* Gets just the creator of the room by the room's name.
*
* @param name the name of the room
* @returns the creator of the room
*/
getCreatorUserByName(name: string): Promise<IUser | undefined>;
/**
* Retrieves an array of messages from the specified room.
*
* @param roomId The unique identifier of the room from which to retrieve messages.
* @param options Optional parameters for retrieving messages:
* - limit: The maximum number of messages to retrieve. Maximum 100
* - skip: The number of messages to skip (for pagination).
* - sort: An object defining the sorting order of the messages. Each key is a field to sort by, and the value is either "asc" for ascending order or "desc" for descending order.
* - showThreadMessages: Whether to include thread messages in the results. Defaults to true.
* @returns A Promise that resolves to an array of IMessage objects representing the messages in the room.
*/
getMessages(roomId: string, options?: Partial<GetMessagesOptions>): Promise<Array<IMessageRaw>>;
/**
* Gets an iterator for all of the users in the provided room.
*
* @param roomId the room's id
* @returns an iterator for the users in the room
*/
getMembers(roomId: string): Promise<Array<IUser>>;
/**
* Retrieves rooms in the workspace, optionally filtered by type and whether they are discussions or part of teams.
*
* @returns a list of raw rooms, or undefined if the app does not have the permission to view all rooms
*/
getAllRooms(filters?: GetRoomsFilters, options?: GetRoomsOptions): Promise<Array<IRoomRaw> | undefined>;
/**
* Gets a direct room with all usernames
* @param usernames all usernames belonging to the direct room
* @returns the room
*/
getDirectByUsernames(usernames: Array<string>): Promise<IRoom>;
/**
* Get a list of the moderators of a given room
*
* @param roomId the room's id
* @returns a list of the users with the moderator role in the room
*/
getModerators(roomId: string): Promise<Array<IUser>>;
/**
* Get a list of the owners of a given room
*
* @param roomId the room's id
* @returns a list of the users with the owner role in the room
*/
getOwners(roomId: string): Promise<Array<IUser>>;
/**
* Get a list of the leaders of a given room
*
* @param roomId the room's id
* @returns a list of the users with the leader role in the room
*/
getLeaders(roomId: string): Promise<Array<IUser>>;
/**
* Retrieves an array of unread messages for a specific user in a specific room.
*
* @param roomId The unique identifier of the room from which to retrieve unread messages.
* @param uid The unique identifier of the user for whom to retrieve unread messages.
* @param options Optional parameters for retrieving messages:
* - limit: The maximum number of messages to retrieve. If more than 100 is passed, it defaults to 100.
* - skip: The number of messages to skip (for pagination).
* - sort: An object defining the sorting order of the messages. Each key is a field to sort by, and the value is either 'asc' for ascending order or 'desc' for descending order.
* - showThreadMessages: Whether to include thread messages in the results. Defaults to true.
* @returns A Promise that resolves to an array of IMessage objects representing the unread messages for the specified user in the specified room.
*/
getUnreadByUser(roomId: string, uid: string, options?: Partial<GetMessagesOptions>): Promise<IMessageRaw[]>;
/**
* Gets the user's unread messages count in a room.
* @param roomId room's id
* @param uid user's id
*/
getUserUnreadMessageCount(roomId: string, uid: string): Promise<number>;
}

View File

@@ -0,0 +1,11 @@
import type { IProcessor } from '../scheduler';
export interface ISchedulerExtend {
/**
* Register processors that can be scheduled to run
*
* @param {Array<IProcessor>} processors An array of processors
* @returns List of task ids run at startup, or void no startup run is set
*/
registerProcessors(processors: Array<IProcessor>): Promise<void | Array<string>>;
}

View File

@@ -0,0 +1,31 @@
import type { IOnetimeSchedule, IRecurringSchedule } from '../scheduler';
/**
* This accessor provides methods to work with the Job Scheduler
*/
export interface ISchedulerModify {
/**
* Schedules a registered processor to run _once_.
*
* @param {IOnetimeSchedule} job
* @returns jobid as string
*/
scheduleOnce(job: IOnetimeSchedule): Promise<void | string>;
/**
* Schedules a registered processor to run in recurrencly according to a given interval
*
* @param {IRecurringSchedule} job
* @returns jobid as string
*/
scheduleRecurring(job: IRecurringSchedule): Promise<void | string>;
/**
* Cancels a running job given its jobId
*
* @param {string} jobId
*/
cancelJob(jobId: string): Promise<void>;
/**
* Cancels all the running jobs from the app
*/
cancelAllJobs(): Promise<void>;
}

View File

@@ -0,0 +1,43 @@
import type { ISetting } from '../settings/ISetting';
/**
* Reader for the settings inside of the server (Rocket.Chat).
* Only a subset of them are exposed to Apps.
*/
export interface IServerSettingRead {
/**
* Gets a server setting by id.
* Please note: a error will be thrown if not found
* or trying to access one that isn't exposed.
*
* @param id the id of the setting to get
* @return the setting
*/
getOneById(id: string): Promise<ISetting>;
/**
* Gets a server setting's value by id.
* Please note: a error will be thrown if not found
* or trying to access one that isn't exposed.
*
* @param id the id of the setting to get
* @return the setting's value
*/
getValueById(id: string): Promise<any>;
/**
* Gets all of the server settings which are exposed
* to the Apps.
*
* @return an iterator of the exposed settings
*/
getAll(): Promise<IterableIterator<ISetting>>;
/**
* Checks if the server setting for the id provided is readable,
* will return true or false and won't throw an error.
*
* @param id the server setting id
*/
isReadableById(id: string): Promise<boolean>;
}

View File

@@ -0,0 +1,6 @@
import type { ISetting } from '../settings/ISetting';
export interface IServerSettingUpdater {
updateOne(setting: ISetting): Promise<void>;
incrementValue(id: ISetting['id'], value?: number): Promise<void>;
}

View File

@@ -0,0 +1,40 @@
import type { ISetting } from '../settings';
/**
* This accessor provides methods to change default setting options
* of Rocket.Chat in a compatible way. It is provided during
* your App's "onEnable".
*/
export interface IServerSettingsModify {
/**
* Hides an existing settings group.
*
* @param name The technical name of the group
*/
hideGroup(name: string): Promise<void>;
/**
* Hides a setting. This does not influence the actual functionality (the setting will still
* have its value and can be programatically read), but the administrator will not be able to see it anymore
*
* @param id the id of the setting to hide
*/
hideSetting(id: string): Promise<void>;
/**
* Modifies the configured value of another setting, please use it with caution as an invalid
* setting configuration could cause a Rocket.Chat instance to become unstable.
*
* @param setting the modified setting (id must be provided)
*/
modifySetting(setting: ISetting): Promise<void>;
/**
* Increases the setting value by the specified amount.
* To be used only with statistic settings that track the amount of times an action has been performed
*
* @param id the id of the existing Rocket.Chat setting
* @param value how much should the count be increased by. Defaults to 1.
*/
incrementValue(id: ISetting['id'], value?: number): Promise<void>;
}

View File

@@ -0,0 +1,23 @@
import type { ISetting } from '../settings/index';
/**
* This accessor provides methods for accessing
* App settings in a read-only-fashion.
*/
export interface ISettingRead {
/**
* Gets the App's setting by the provided id.
* Does not throw an error but instead will return undefined it doesn't exist.
*
* @param id the id of the setting
*/
getById(id: string): Promise<ISetting>;
/**
* Gets the App's setting value by the provided id.
* Note: this will throw an error if the setting doesn't exist
*
* @param id the id of the setting value to get
*/
getValueById(id: string): Promise<any>;
}

View File

@@ -0,0 +1,6 @@
import type { ISetting } from '../settings/ISetting';
export interface ISettingUpdater {
updateValue(id: ISetting['id'], value: ISetting['value']): Promise<void>;
updateSelectOptions(id: ISetting['id'], values: ISetting['values']): Promise<void>;
}

View File

@@ -0,0 +1,17 @@
import type { ISetting } from '../settings/index';
/**
* This accessor provides methods for adding custom settings,
* which are displayed on your App's page.
* This is provided on initialization of your App.
*/
export interface ISettingsExtend {
/**
* Adds a setting which can be configured by an administrator.
* Settings can only be added to groups which have been provided by this App earlier
* and if a group is not provided, the setting will appear outside of a group.
*
* @param setting the setting
*/
provideSetting(setting: ISetting): Promise<void>;
}

View File

@@ -0,0 +1,16 @@
import type { ISlashCommand } from '../slashcommands';
/**
* This accessor provides methods for adding custom slash commands.
* It is provided during the initialization of your App
*/
export interface ISlashCommandsExtend {
/**
* Adds a slash command which can be used during conversations lateron.
* Should a command already exists an error will be thrown.
*
* @param slashCommand the command information
*/
provideSlashCommand(slashCommand: ISlashCommand): Promise<void>;
}

View File

@@ -0,0 +1,30 @@
import type { ISlashCommand } from '../slashcommands';
/**
* This accessor provides methods for modifying existing Rocket.Chat slash commands.
* It is provided during "onEnable" of your App.
*/
export interface ISlashCommandsModify {
/**
* Modifies an existing command. The command must either be your App's
* own command or a system command. One App can not modify another
* App's command.
*
* @param slashCommand the modified slash command
*/
modifySlashCommand(slashCommand: ISlashCommand): Promise<void>;
/**
* Renders an existing slash command un-usable.
*
* @param command the command's usage without the slash
*/
disableSlashCommand(command: string): Promise<void>;
/**
* Enables an existing slash command to be usable again.
*
* @param command the command's usage without the slash
*/
enableSlashCommand(command: string): Promise<void>;
}

View File

@@ -0,0 +1,9 @@
import type { IMessage } from '../messages/index';
/**
* This accessor provides methods for accessing
* Thread messages in a read-only-fashion.
*/
export interface IThreadRead {
getThreadById(id: string): Promise<Array<IMessage> | undefined>;
}

View File

@@ -0,0 +1,30 @@
import type { IUIKitErrorInteraction, IUIKitInteraction, IUIKitSurface } from '../uikit';
import type { IUIKitContextualBarViewParam, IUIKitModalViewParam } from '../uikit/UIKitInteractionResponder';
import type { IUser } from '../users';
export type IUIKitInteractionParam = Omit<IUIKitInteraction, 'appId' | 'type'>;
export type IUIKitErrorInteractionParam = Omit<IUIKitErrorInteraction, 'type' | 'appId' | 'triggerId'>;
export type IUIKitSurfaceViewParam = Omit<IUIKitSurface, 'appId' | 'id'> & Partial<Pick<IUIKitSurface, 'id'>>;
export interface IUIController {
/**
* @deprecated please prefer the `openSurfaceView` method
*/
openModalView(view: IUIKitModalViewParam, context: IUIKitInteractionParam, user: IUser): Promise<void>;
/**
* @deprecated please prefer the `updateSurfaceView` method
*/
updateModalView(view: IUIKitModalViewParam, context: IUIKitInteractionParam, user: IUser): Promise<void>;
/**
* @deprecated please prefer the `openSurfaceView` method
*/
openContextualBarView(view: IUIKitContextualBarViewParam, context: IUIKitInteractionParam, user: IUser): Promise<void>;
/**
* @deprecated please prefer the `updateSurfaceView` method
*/
updateContextualBarView(view: IUIKitContextualBarViewParam, context: IUIKitInteractionParam, user: IUser): Promise<void>;
setViewError(errorInteraction: IUIKitErrorInteractionParam, context: IUIKitInteractionParam, user: IUser): Promise<void>;
openSurfaceView(view: IUIKitSurfaceViewParam, context: IUIKitInteractionParam, user: IUser): Promise<void>;
updateSurfaceView(view: IUIKitSurfaceViewParam, context: IUIKitInteractionParam, user: IUser): Promise<void>;
}

View File

@@ -0,0 +1,5 @@
import type { IUIActionButtonDescriptor } from '../ui';
export interface IUIExtend {
registerButton(button: IUIActionButtonDescriptor): void;
}

View File

@@ -0,0 +1,12 @@
import type { IUpload } from '../uploads';
import type { IUploadDescriptor } from '../uploads/IUploadDescriptor';
export interface IUploadCreator {
/**
* Create an upload to a room
*
* @param buffer A Buffer with the file's content (See [here](https://nodejs.org/api/buffer.html)
* @param descriptor The metadata about the upload
*/
uploadBuffer(buffer: Buffer, descriptor: IUploadDescriptor): Promise<IUpload>;
}

View File

@@ -0,0 +1,7 @@
import type { IUpload } from '../uploads';
export interface IUploadRead {
getById(id: string): Promise<IUpload>;
getBufferById(id: string): Promise<Buffer>;
getBuffer(upload: IUpload): Promise<Buffer>;
}

View File

@@ -0,0 +1,60 @@
import type { RocketChatAssociationModel } from '../metadata';
import type { IUser, IUserEmail } from '../users';
/**
* Interface for creating a user.
* Please note, a username and email provided must be unique else you will NOT
* be able to successfully save the user object.
*/
export interface IUserBuilder {
kind: RocketChatAssociationModel.USER;
/**
* Provides a convient way to set the data for the user.
* Note: Providing an "id" field here will be ignored.
*
* @param user the user data to set
*/
setData(user: Partial<IUser>): IUserBuilder;
/**
* Sets emails of the user
*
* @param emails the array of email addresses of the user
*/
setEmails(emails: Array<IUserEmail>): IUserBuilder;
/**
* Gets emails of the user
*/
getEmails(): Array<IUserEmail>;
/**
* Sets the display name of this user.
*
* @param name the display name of the user
*/
setDisplayName(name: string): IUserBuilder;
/**
* Gets the display name of this user.
*/
getDisplayName(): string;
/**
* Sets the username for the user
*
* @param username username of the user
*/
setUsername(username: string): IUserBuilder;
/**
* Gets the username of this user
*/
getUsername(): string;
/**
* Gets the user
*/
getUser(): Partial<IUser>;
}

View File

@@ -0,0 +1,31 @@
import type { IUser } from '../users/index';
/**
* This accessor provides methods for accessing
* users in a read-only-fashion.
*/
export interface IUserRead {
getById(id: string): Promise<IUser>;
getByUsername(username: string): Promise<IUser>;
getBySipExtension(extension: string): Promise<IUser | undefined>;
/**
* Gets the app user of this app.
*/
getAppUser(appId?: string): Promise<IUser | undefined>;
/**
* Gets the user's badge count (unread messages count).
* @param uid user's id
*/
getUserUnreadMessageCount(uid: string): Promise<number | undefined>;
/**
* Fetches the IDs of the rooms that the user is a member of.
*
* @param userId the user whose memberships should be returned
*/
getUserRoomIds(userId: string): Promise<string[]>;
}

View File

@@ -0,0 +1,23 @@
import type { IUser } from '../users/IUser';
/**
* Updating a user is a more granular approach, since
* it is one of the more sensitive aspects of Rocket.Chat -
* or any other system for that matter.
*
* Allowing apps to modify _all_ the aspects of a user
* would open a critical surface for them to abuse such
* power and "take hold" of a server, for instance.
*/
export interface IUserUpdater {
updateStatusText(user: IUser, statusText: IUser['statusText']): Promise<boolean>;
updateStatus(user: IUser, statusText: IUser['statusText'], status: IUser['status']): Promise<boolean>;
updateBio(user: IUser, bio: IUser['bio']): Promise<boolean>;
updateCustomFields(user: IUser, customFields: IUser['customFields']): Promise<boolean>;
deactivate(userId: IUser['id'], confirmRelinquish: boolean): Promise<boolean>;
setActiveState(
userId: IUser['id'],
state: Pick<IUser, 'statusDefault' | 'statusSource' | 'statusText' | 'statusExpiresAt' | 'statusId'>,
): Promise<void>;
endActiveState(userId: IUser['id'], statusId?: string): Promise<void>;
}

View File

@@ -0,0 +1,15 @@
import type { IVideoConfProvider } from '../videoConfProviders';
/**
* This accessor provides methods for adding videoconf providers.
* It is provided during the initialization of your App
*/
export interface IVideoConfProvidersExtend {
/**
* Adds a videoconf provider
*
* @param provider the provider information
*/
provideVideoConfProvider(provider: IVideoConfProvider): Promise<void>;
}

View File

@@ -0,0 +1,34 @@
import type { RocketChatAssociationModel } from '../metadata';
import type { AppVideoConference } from '../videoConferences';
export interface IVideoConferenceBuilder {
kind: RocketChatAssociationModel.VIDEO_CONFERENCE;
setData(call: Partial<AppVideoConference>): IVideoConferenceBuilder;
setRoomId(rid: string): IVideoConferenceBuilder;
getRoomId(): string;
setCreatedBy(userId: string): IVideoConferenceBuilder;
getCreatedBy(): string;
setProviderName(name: string): IVideoConferenceBuilder;
getProviderName(): string;
setProviderData(data: Record<string, any>): IVideoConferenceBuilder;
getProviderData(): Record<string, any>;
setTitle(name: string): IVideoConferenceBuilder;
getTitle(): string;
setDiscussionRid(rid: string | undefined): IVideoConferenceBuilder;
getDiscussionRid(): string | undefined;
getVideoConference(): AppVideoConference;
}

View File

@@ -0,0 +1,21 @@
import type { RocketChatAssociationModel } from '../metadata';
import type { IVideoConferenceUser, VideoConference } from '../videoConferences';
import type { VideoConferenceMember } from '../videoConferences/IVideoConference';
export interface IVideoConferenceExtender {
kind: RocketChatAssociationModel.VIDEO_CONFERENCE;
setProviderData(value: Record<string, any>): IVideoConferenceExtender;
setStatus(value: VideoConference['status']): IVideoConferenceExtender;
setEndedBy(value: IVideoConferenceUser['_id']): IVideoConferenceExtender;
setEndedAt(value: VideoConference['endedAt']): IVideoConferenceExtender;
addUser(userId: VideoConferenceMember['_id'], ts?: VideoConferenceMember['ts']): IVideoConferenceExtender;
setDiscussionRid(rid: VideoConference['discussionRid']): IVideoConferenceExtender;
getVideoConference(): VideoConference;
}

View File

@@ -0,0 +1,15 @@
import type { VideoConference } from '../videoConferences/IVideoConference';
/**
* This accessor provides methods for accessing
* video conferences in a read-only-fashion.
*/
export interface IVideoConferenceRead {
/**
* Gets a video conference by an id.
*
* @param id the id of the video conference
* @returns the video conference
*/
getById(id: string): Promise<VideoConference | undefined>;
}

View File

@@ -0,0 +1,60 @@
export type * from './IApiExtend';
export type * from './IAppAccessors';
export type * from './IAppInstallationContext';
export type * from './IAppUpdateContext';
export type * from './IAppUninstallationContext';
export type * from './ICloudWorkspaceRead';
export type * from './IConfigurationExtend';
export type * from './IConfigurationModify';
export type * from './IDiscussionBuilder';
export type * from './IEnvironmentalVariableRead';
export type * from './IEnvironmentRead';
export type * from './IEnvironmentWrite';
export type * from './IExternalComponentsExtend';
export type * from './IExperimentalRead';
export * from './IHttp';
export type * from './ILivechatCreator';
export type * from './ILivechatMessageBuilder';
export type * from './ILivechatRead';
export type * from './ILivechatUpdater';
export * from './ILogEntry';
export type * from './ILogger';
export type * from './IMessageBuilder';
export type * from './IMessageExtender';
export type * from './IMessageRead';
export type * from './IMessageUpdater';
export type * from './IModify';
export type * from './IModifyCreator';
export type * from './IModifyDeleter';
export type * from './IModifyExtender';
export type * from './IModifyUpdater';
export * from './INotifier';
export type * from './IPersistence';
export type * from './IPersistenceRead';
export type * from './IRead';
export type * from './IRoleRead';
export type * from './IRoomBuilder';
export type * from './IRoomExtender';
export type * from './IRoomRead';
export type * from './ISchedulerExtend';
export type * from './ISchedulerModify';
export type * from './IServerSettingRead';
export type * from './IServerSettingsModify';
export type * from './IServerSettingUpdater';
export type * from './ISettingRead';
export type * from './ISettingsExtend';
export type * from './ISettingUpdater';
export type * from './ISlashCommandsExtend';
export type * from './ISlashCommandsModify';
export type * from './IUIController';
export type * from './IUIExtend';
export type * from './IUploadCreator';
export type * from './IUploadRead';
export type * from './IUserBuilder';
export type * from './IUserRead';
export type * from './IVideoConferenceBuilder';
export type * from './IVideoConferenceExtend';
export type * from './IVideoConferenceRead';
export type * from './IVideoConfProvidersExtend';
export type * from './IModerationModify';
export type * from './IOutboundCommunicationProviderExtend';

View File

@@ -0,0 +1,40 @@
import type { IApp } from '../IApp';
import { HttpStatusCode } from '../accessors';
import type { IApiEndpoint } from './IApiEndpoint';
import type { IApiResponse, IApiResponseJSON } from './IResponse';
/** Represents an api endpoint that is being provided. */
export abstract class ApiEndpoint implements IApiEndpoint {
/**
* The last part of the api URL. Example: https://{your-server-address}/api/apps/public/{your-app-id}/{path}
* or https://{your-server-address}/api/apps/private/{your-app-id}/{private-hash}/{path}
*/
public path!: string;
constructor(public app: IApp) {}
/**
* Return response with status 200 (OK) and a optional content
* @param content
*/
protected success(content?: any): IApiResponse {
return {
status: HttpStatusCode.OK,
content,
};
}
/**
* Return a json response adding Content Type header as
* application/json if not already provided
* @param reponse
*/
protected json(response: IApiResponseJSON): IApiResponse {
if (!response?.headers?.['content-type']) {
response.headers = response.headers || {};
response.headers['content-type'] = 'application/json';
}
return response;
}
}

View File

@@ -0,0 +1,58 @@
import type { IApiEndpoint } from './IApiEndpoint';
/**
* Represents an api that is being provided.
*/
export interface IApi {
/**
* Provides the visibility method of the URL, see the ApiVisibility descriptions for more information
*/
visibility: ApiVisibility;
/**
* Provides the visibility method of the URL, see the ApiSecurity descriptions for more information
*/
security: ApiSecurity;
/**
* Provide enpoints for this api registry
*/
endpoints: Array<IApiEndpoint>;
}
export enum ApiVisibility {
/**
* A public Api has a fixed format for a url. Using it enables an
* easy to remember structure, however, it also means the url is
* intelligently guessed. As a result, we recommend having some
* sort of security setup if you must have a public api.Whether
* you use the provided security, ApiSecurity, or implement your own.
* Url format:
* `https://{your-server-address}/api/apps/public/{your-app-id}/{path}`
*/
PUBLIC,
/**
* Private Api's contain a random value in the url format,
* making them harder go guess by default. The random value
* will be generated whenever the App is installed on a server.
* This means that the URL will not be the same on any server,
* but will remain the same throughout the lifecycle of an App
* including updates. As a result, if a user uninstalls the App
* and reinstalls the App, then the random value will change.
* Url format:
* `https://{your-server-address}/api/apps/private/{your-app-id}/{random-hash}/{path}`
*/
PRIVATE,
}
export enum ApiSecurity {
/**
* No security check will be executed agains the calls made to this URL
*/
UNSECURE,
/**
* Only calls containing a valid token will be able to execute the api
* Mutiple tokens can be generated to access the api, by default one
* will be generated automatically.
* @param `X-Auth-Token`
*/
// CHECKSUM_SECRET,
}

View File

@@ -0,0 +1,96 @@
import type { IHttp, IModify, IPersistence, IRead } from '../accessors';
import type { IApiEndpointInfo } from './IApiEndpointInfo';
import type { IApiExample } from './IApiExample';
import type { IApiRequest } from './IRequest';
import type { IApiResponse } from './IResponse';
/**
* Represents an api endpoint that is being provided.
*/
export interface IApiEndpoint {
/**
* The last part of the api URL. Example: https://{your-server-address}/api/apps/public/{your-app-id}/{path}
* or https://{your-server-address}/api/apps/private/{your-app-id}/{private-hash}/{path}
*/
path: string;
examples?: { [key: string]: IApiExample };
/**
* Whether this endpoint requires an authenticated user to access it.
*
* The authentication will be done by the host server using its own
* authentication system.
*
* If no authentication is provided, the request will be automatically
* rejected with a 401 status code.
*/
authRequired?: boolean;
/**
* The methods that are available for this endpoint.
* This property is provided by the Runtime and should not be set manually.
*
* Its values are used on the Apps-Engine to validate the request method.
*/
_availableMethods?: string[];
/**
* Called whenever the publically accessible url for this App is called,
* if you handle the methods differently then split it out so your code doesn't get too big.
*/
get?(
request: IApiRequest,
endpoint: IApiEndpointInfo,
read: IRead,
modify: IModify,
http: IHttp,
persis: IPersistence,
): Promise<IApiResponse>;
post?(
request: IApiRequest,
endpoint: IApiEndpointInfo,
read: IRead,
modify: IModify,
http: IHttp,
persis: IPersistence,
): Promise<IApiResponse>;
put?(
request: IApiRequest,
endpoint: IApiEndpointInfo,
read: IRead,
modify: IModify,
http: IHttp,
persis: IPersistence,
): Promise<IApiResponse>;
delete?(
request: IApiRequest,
endpoint: IApiEndpointInfo,
read: IRead,
modify: IModify,
http: IHttp,
persis: IPersistence,
): Promise<IApiResponse>;
head?(
request: IApiRequest,
endpoint: IApiEndpointInfo,
read: IRead,
modify: IModify,
http: IHttp,
persis: IPersistence,
): Promise<IApiResponse>;
options?(
request: IApiRequest,
endpoint: IApiEndpointInfo,
read: IRead,
modify: IModify,
http: IHttp,
persis: IPersistence,
): Promise<IApiResponse>;
patch?(
request: IApiRequest,
endpoint: IApiEndpointInfo,
read: IRead,
modify: IModify,
http: IHttp,
persis: IPersistence,
): Promise<IApiResponse>;
}

View File

@@ -0,0 +1,6 @@
export interface IApiEndpointInfo {
basePath: string;
fullPath: string;
appId: string;
hash?: string;
}

View File

@@ -0,0 +1,10 @@
import type { IApiExample } from './IApiExample';
export interface IApiEndpointMetadata {
path: string;
computedPath: string;
methods: Array<string>;
examples?: {
[key: string]: IApiExample;
};
}

View File

@@ -0,0 +1,19 @@
/**
* Represents the parameters of an api example.
*/
export interface IApiExample {
params?: { [key: string]: string };
query?: { [key: string]: string };
headers?: { [key: string]: string };
content?: any;
}
/**
* Decorator to describe api examples
*/
export function example(options: IApiExample) {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
target.examples = target.examples || {};
target.examples[propertyKey] = options;
};
}

View File

@@ -0,0 +1,16 @@
import type { RequestMethod } from '../accessors';
import type { IUser } from '../users';
export interface IApiRequest {
method: RequestMethod;
headers: { [key: string]: string };
query: { [key: string]: string };
params: { [key: string]: string };
content: any;
privateHash?: string;
/**
* The user that is making the request, as
* authenticated by Rocket.Chat's strategy.
*/
user?: IUser;
}

View File

@@ -0,0 +1,13 @@
import type { HttpStatusCode } from '../accessors';
export interface IApiResponse {
status: HttpStatusCode;
headers?: { [key: string]: string };
content?: any;
}
export interface IApiResponseJSON {
status: HttpStatusCode;
headers?: { [key: string]: string };
content?: { [key: string]: any };
}

View File

@@ -0,0 +1,10 @@
export { ApiEndpoint } from './ApiEndpoint';
export type { IApi } from './IApi';
export { ApiVisibility, ApiSecurity } from './IApi';
export type { IApiEndpoint } from './IApiEndpoint';
export type { IApiEndpointInfo } from './IApiEndpointInfo';
export type { IApiExample } from './IApiExample';
export { example } from './IApiExample';
export type { IApiRequest } from './IRequest';
export type { IApiResponse } from './IResponse';
export type { IApiEndpointMetadata } from './IApiEndpointMetadata';

View File

@@ -0,0 +1,75 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Rocket.Chat App",
"description": "A Rocket.Chat App declaration for usage inside of Rocket.Chat.",
"type": "object",
"properties": {
"id": {
"description": "The App's unique identifier in uuid v4 format. This is optional, although recommended, however if you are going to publish on the App store, you will be assigned one.",
"type": "string",
"pattern": "^[0-9a-fA-f]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
"minLength": 36,
"maxLength": 36
},
"name": {
"description": "The public visible name of this App.",
"type": "string"
},
"nameSlug": {
"description": "A url friendly slugged version of your App's name.",
"type": "string",
"pattern": "^([a-z]|\\-)+$",
"minLength": 3
},
"version": {
"description": "The version of this App which will be used for display publicly and letting users know there is an update. This uses the semver format.",
"type": "string",
"pattern": "^(?:\\d*)\\.(?:\\d*)\\.(?:\\d*)$",
"minLength": 5
},
"description": {
"description": "A description of this App, used to explain what this App does and provides for the user.",
"type": "string"
},
"requiredApiVersion": {
"description": "The required version of the App's API which this App depends on. This uses the semver format.",
"type": "string",
"pattern": "^(?:\\^|~)?(?:\\d*)\\.(?:\\d*)\\.(?:\\d*)$",
"minLength": 5
},
"author": {
"type": "object",
"properties": {
"name": {
"description": "The author's name who created this App.",
"type": "string"
},
"support": {
"description": "The place where people can get support for this App, whether email or website.",
"type": "string"
},
"homepage": {
"description": "The homepage for this App, it can be a Github or the author's website.",
"type": "string",
"format": "uri"
}
},
"required": ["name", "support"]
},
"classFile": {
"type": "string",
"description": "The name of the file which contains your App TypeScript source code.",
"pattern": "^.*\\.(ts)$"
},
"iconFile": {
"type": "string",
"description": "The name of the file to use as the icon.",
"pattern": "^.*\\.(png|jpg|jpeg|gif)$"
},
"assetsFolder": {
"type": "string",
"description": "The name of the folder which contains all of your resources, it should not start with a period."
}
},
"required": ["id", "name", "nameSlug", "version", "description", "requiredApiVersion", "author", "classFile", "iconFile"]
}

View File

@@ -0,0 +1,6 @@
export interface IAsset {
name: string;
path: string;
type: string;
public: boolean;
}

View File

@@ -0,0 +1,5 @@
import type { IAsset } from './IAsset';
export interface IAssetProvider {
getAssets(): Array<IAsset>;
}

View File

@@ -0,0 +1,4 @@
import type { IAsset } from './IAsset';
import type { IAssetProvider } from './IAssetProvider';
export type { IAsset, IAssetProvider };

View File

@@ -0,0 +1,4 @@
export interface IWorkspaceToken {
token: string;
expiresAt: Date;
}

View File

@@ -0,0 +1,12 @@
export interface IEmail {
to: string | string[];
/**
* @deprecated this will be inferred from the settings
*/
from?: string;
replyTo?: string;
subject: string;
html?: string;
text?: string;
headers?: string;
}

View File

@@ -0,0 +1,11 @@
export interface IEmailDescriptor {
from?: string | undefined;
to?: string | Array<string> | undefined;
cc?: string | Array<string> | undefined;
bcc?: string | Array<string> | undefined;
replyTo?: string | Array<string> | undefined;
subject?: string | undefined;
text?: string | undefined;
html?: string | undefined;
headers?: Record<string, string> | undefined;
}

View File

@@ -0,0 +1,25 @@
import type { IEmailDescriptor, IPreEmailSentContext } from '.';
import type { IHttp, IModify, IPersistence, IRead } from '../accessors';
import { AppMethod } from '../metadata';
/**
* Event interface that allows apps to
* register as a handler of of the `IPreEmailSent`
* event.
*
* This event is trigger before the mailer sends
* an email.
*
* To prevent the email from being sent, you can
* throw an error with a message specifying the
* reason for rejection.
*/
export interface IPreEmailSent {
[AppMethod.EXECUTE_PRE_EMAIL_SENT](
context: IPreEmailSentContext,
read: IRead,
http: IHttp,
persis: IPersistence,
modify: IModify,
): Promise<IEmailDescriptor>;
}

View File

@@ -0,0 +1,6 @@
import type { IEmailDescriptor } from './IEmailDescriptor';
export interface IPreEmailSentContext {
context: unknown;
email: IEmailDescriptor;
}

View File

@@ -0,0 +1,4 @@
export type * from './IEmailDescriptor';
export type * from './IPreEmailSent';
export type * from './IPreEmailSentContext';
export type * from './IEmail';

View File

@@ -0,0 +1,13 @@
{
//This is an example of how a app.json file will look like
"name": "Testing",
"nameSlug": "testing",
"description": "Testing description",
"version": "1.0.0",
"requiredApiVersion": "0.0.1",
"author": {
"name": "Bradley Hilton",
"support": "https://github.com/RocketChat/Rocket.Chat.Apps-engine"
},
"classFile": "ExampleApp.ts"
}

View File

@@ -0,0 +1,29 @@
/**
* The internal exception from the framework
*
* It's used to signal to the outside world that
* a _known_ exception has happened during the execution
* of the apps.
*
* It's the base exception for other known classes
* such as UserNotAllowedException, which is used
* to inform the host that an app identified
* that a user cannot perform some action, e.g.
* join a room
*/
export class AppsEngineException extends Error {
public name = 'AppsEngineException';
public static JSONRPC_ERROR_CODE = -32070;
constructor(message?: string) {
super(message);
}
public getErrorInfo() {
return {
name: this.name,
message: this.message,
};
}
}

View File

@@ -0,0 +1,16 @@
import { AppsEngineException } from '.';
/**
* This exception informs the host system that an
* app essential to the execution of a system action
* is disabled, so the action should be halted.
*
* Apps can register to be considered essential to
* the execution of internal events of the framework
* such as `IPreMessageSentPrevent`, `IPreRoomUserJoined`,
* etc.
*
* This is used interally by the framework and is not
* intended to be thrown manually by apps.
*/
export class EssentialAppDisabledException extends AppsEngineException {}

Some files were not shown because too many files have changed in this diff Show More