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
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
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
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
This commit is contained in:
1
packages/apps/deno-runtime/.gitignore
vendored
Normal file
1
packages/apps/deno-runtime/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.deno/
|
||||
34
packages/apps/deno-runtime/deno.jsonc
Normal file
34
packages/apps/deno-runtime/deno.jsonc
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"imports": {
|
||||
"@msgpack/msgpack": "npm:@msgpack/msgpack@3.0.0-beta2",
|
||||
"@rocket.chat/ui-kit": "npm:@rocket.chat/ui-kit@^0.31.22",
|
||||
"@rocket.chat/apps-engine/": "../../../packages/apps-engine/",
|
||||
"@rocket.chat/apps/base-runtime/": "../base-runtime/src/",
|
||||
"@rocket.chat/apps/": "../",
|
||||
"@std/io": "jsr:@std/io@^0.225.3",
|
||||
"acorn": "npm:acorn@8.17.0",
|
||||
"acorn-walk": "npm:acorn-walk@8.3.5",
|
||||
"astring": "npm:astring@1.8.6",
|
||||
"jsonrpc-lite": "npm:jsonrpc-lite@2.2.0",
|
||||
"stack-trace": "npm:stack-trace@0.0.10",
|
||||
"uuid": "npm:uuid@8.3.2"
|
||||
},
|
||||
"unstable": ["detect-cjs", "sloppy-imports"],
|
||||
"compilerOptions": {
|
||||
"strict": false
|
||||
},
|
||||
"tasks": {
|
||||
"test": "deno test --no-check --allow-read --allow-write --allow-env"
|
||||
},
|
||||
"fmt": {
|
||||
"lineWidth": 160,
|
||||
"useTabs": true,
|
||||
"indentWidth": 4,
|
||||
"singleQuote": true
|
||||
},
|
||||
"lint": {
|
||||
"rules": {
|
||||
"exclude": ["no-sloppy-imports"]
|
||||
}
|
||||
}
|
||||
}
|
||||
129
packages/apps/deno-runtime/deno.lock
generated
Normal file
129
packages/apps/deno-runtime/deno.lock
generated
Normal file
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"version": "5",
|
||||
"specifiers": {
|
||||
"jsr:@std/bytes@^1.0.6": "1.0.6",
|
||||
"jsr:@std/io@~0.225.3": "0.225.3",
|
||||
"npm:@msgpack/msgpack@3.0.0-beta2": "3.0.0-beta2",
|
||||
"npm:@rocket.chat/ui-kit@~0.31.22": "0.31.25_@rocket.chat+icons@0.32.0",
|
||||
"npm:@types/node@*": "22.12.0",
|
||||
"npm:acorn-walk@8.3.5": "8.3.5",
|
||||
"npm:acorn@8.17.0": "8.17.0",
|
||||
"npm:astring@1.8.6": "1.8.6",
|
||||
"npm:jsonrpc-lite@2.2.0": "2.2.0",
|
||||
"npm:stack-trace@*": "0.0.10",
|
||||
"npm:stack-trace@0.0.10": "0.0.10",
|
||||
"npm:uuid@8.3.2": "8.3.2"
|
||||
},
|
||||
"jsr": {
|
||||
"@std/bytes@1.0.6": {
|
||||
"integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a"
|
||||
},
|
||||
"@std/io@0.225.3": {
|
||||
"integrity": "27b07b591384d12d7b568f39e61dff966b8230559122df1e9fd11cc068f7ddd1",
|
||||
"dependencies": [
|
||||
"jsr:@std/bytes"
|
||||
]
|
||||
}
|
||||
},
|
||||
"npm": {
|
||||
"@msgpack/msgpack@3.0.0-beta2": {
|
||||
"integrity": "sha512-y+l1PNV0XDyY8sM3YtuMLK5vE3/hkfId+Do8pLo/OPxfxuFAUwcGz3oiiUuV46/aBpwTzZ+mRWVMtlSKbradhw==",
|
||||
"deprecated": true
|
||||
},
|
||||
"@rocket.chat/icons@0.32.0": {
|
||||
"integrity": "sha512-7yhhELKNLb9kUtXCvau0V+iMXraV2bOsxcPjc/ZtLR5VeeIDTeaflqRWGtLroX6f3bE+J1n5qB5zi8A4YXuH2g=="
|
||||
},
|
||||
"@rocket.chat/ui-kit@0.31.25_@rocket.chat+icons@0.32.0": {
|
||||
"integrity": "sha512-yTgTKDw9SMlJ6p8n0PDO6zSvox/nHYUrwCIvILQeAK6PvTrgSe/u9CvU7ATTYjnQiQ603yEGR6dxjF4euCGdNA==",
|
||||
"dependencies": [
|
||||
"@rocket.chat/icons"
|
||||
]
|
||||
},
|
||||
"@types/node@22.12.0": {
|
||||
"integrity": "sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==",
|
||||
"dependencies": [
|
||||
"undici-types"
|
||||
]
|
||||
},
|
||||
"acorn-walk@8.3.5": {
|
||||
"integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==",
|
||||
"dependencies": [
|
||||
"acorn"
|
||||
]
|
||||
},
|
||||
"acorn@8.17.0": {
|
||||
"integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==",
|
||||
"bin": true
|
||||
},
|
||||
"astring@1.8.6": {
|
||||
"integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==",
|
||||
"bin": true
|
||||
},
|
||||
"jsonrpc-lite@2.2.0": {
|
||||
"integrity": "sha512-/cbbSxtZWs1O7R4tWqabrCM/t3N8qKUZMAg9IUqpPvUs6UyRvm6pCNYkskyKN/XU0UgffW+NY2ZRr8t0AknX7g=="
|
||||
},
|
||||
"stack-trace@0.0.10": {
|
||||
"integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="
|
||||
},
|
||||
"undici-types@6.20.0": {
|
||||
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="
|
||||
},
|
||||
"uuid@8.3.2": {
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"bin": true
|
||||
}
|
||||
},
|
||||
"remote": {
|
||||
"https://deno.land/std@0.203.0/assert/_constants.ts": "8a9da298c26750b28b326b297316cdde860bc237533b07e1337c021379e6b2a9",
|
||||
"https://deno.land/std@0.203.0/assert/_diff.ts": "1a3c044aedf77647d6cac86b798c6417603361b66b54c53331b312caeb447aea",
|
||||
"https://deno.land/std@0.203.0/assert/_format.ts": "a69126e8a469009adf4cf2a50af889aca364c349797e63174884a52ff75cf4c7",
|
||||
"https://deno.land/std@0.203.0/assert/assert.ts": "9a97dad6d98c238938e7540736b826440ad8c1c1e54430ca4c4e623e585607ee",
|
||||
"https://deno.land/std@0.203.0/assert/assert_almost_equals.ts": "e15ca1f34d0d5e0afae63b3f5d975cbd18335a132e42b0c747d282f62ad2cd6c",
|
||||
"https://deno.land/std@0.203.0/assert/assert_array_includes.ts": "6856d7f2c3544bc6e62fb4646dfefa3d1df5ff14744d1bca19f0cbaf3b0d66c9",
|
||||
"https://deno.land/std@0.203.0/assert/assert_equals.ts": "d8ec8a22447fbaf2fc9d7c3ed2e66790fdb74beae3e482855d75782218d68227",
|
||||
"https://deno.land/std@0.203.0/assert/assert_exists.ts": "407cb6b9fb23a835cd8d5ad804e2e2edbbbf3870e322d53f79e1c7a512e2efd7",
|
||||
"https://deno.land/std@0.203.0/assert/assert_false.ts": "0ccbcaae910f52c857192ff16ea08bda40fdc79de80846c206bfc061e8c851c6",
|
||||
"https://deno.land/std@0.203.0/assert/assert_greater.ts": "ae2158a2d19313bf675bf7251d31c6dc52973edb12ac64ac8fc7064152af3e63",
|
||||
"https://deno.land/std@0.203.0/assert/assert_greater_or_equal.ts": "1439da5ebbe20855446cac50097ac78b9742abe8e9a43e7de1ce1426d556e89c",
|
||||
"https://deno.land/std@0.203.0/assert/assert_instance_of.ts": "3aedb3d8186e120812d2b3a5dea66a6e42bf8c57a8bd927645770bd21eea554c",
|
||||
"https://deno.land/std@0.203.0/assert/assert_is_error.ts": "c21113094a51a296ffaf036767d616a78a2ae5f9f7bbd464cd0197476498b94b",
|
||||
"https://deno.land/std@0.203.0/assert/assert_less.ts": "aec695db57db42ec3e2b62e97e1e93db0063f5a6ec133326cc290ff4b71b47e4",
|
||||
"https://deno.land/std@0.203.0/assert/assert_less_or_equal.ts": "5fa8b6a3ffa20fd0a05032fe7257bf985d207b85685fdbcd23651b70f928c848",
|
||||
"https://deno.land/std@0.203.0/assert/assert_match.ts": "c4083f80600bc190309903c95e397a7c9257ff8b5ae5c7ef91e834704e672e9b",
|
||||
"https://deno.land/std@0.203.0/assert/assert_not_equals.ts": "9f1acab95bd1f5fc9a1b17b8027d894509a745d91bac1718fdab51dc76831754",
|
||||
"https://deno.land/std@0.203.0/assert/assert_not_instance_of.ts": "0c14d3dfd9ab7a5276ed8ed0b18c703d79a3d106102077ec437bfe7ed912bd22",
|
||||
"https://deno.land/std@0.203.0/assert/assert_not_match.ts": "3796a5b0c57a1ce6c1c57883dd4286be13a26f715ea662318ab43a8491a13ab0",
|
||||
"https://deno.land/std@0.203.0/assert/assert_not_strict_equals.ts": "ca6c6d645e95fbc873d25320efeb8c4c6089a9a5e09f92d7c1c4b6e935c2a6ad",
|
||||
"https://deno.land/std@0.203.0/assert/assert_object_match.ts": "d8fc2867cfd92eeacf9cea621e10336b666de1874a6767b5ec48988838370b54",
|
||||
"https://deno.land/std@0.203.0/assert/assert_rejects.ts": "45c59724de2701e3b1f67c391d6c71c392363635aad3f68a1b3408f9efca0057",
|
||||
"https://deno.land/std@0.203.0/assert/assert_strict_equals.ts": "b1f538a7ea5f8348aeca261d4f9ca603127c665e0f2bbfeb91fa272787c87265",
|
||||
"https://deno.land/std@0.203.0/assert/assert_string_includes.ts": "b821d39ebf5cb0200a348863c86d8c4c4b398e02012ce74ad15666fc4b631b0c",
|
||||
"https://deno.land/std@0.203.0/assert/assert_throws.ts": "63784e951475cb7bdfd59878cd25a0931e18f6dc32a6077c454b2cd94f4f4bcd",
|
||||
"https://deno.land/std@0.203.0/assert/assertion_error.ts": "4d0bde9b374dfbcbe8ac23f54f567b77024fb67dbb1906a852d67fe050d42f56",
|
||||
"https://deno.land/std@0.203.0/assert/equal.ts": "9f1a46d5993966d2596c44e5858eec821859b45f783a5ee2f7a695dfc12d8ece",
|
||||
"https://deno.land/std@0.203.0/assert/fail.ts": "c36353d7ae6e1f7933d45f8ea51e358c8c4b67d7e7502028598fe1fea062e278",
|
||||
"https://deno.land/std@0.203.0/assert/mod.ts": "37c49a26aae2b254bbe25723434dc28cd7532e444cf0b481a97c045d110ec085",
|
||||
"https://deno.land/std@0.203.0/assert/unimplemented.ts": "d56fbeecb1f108331a380f72e3e010a1f161baa6956fd0f7cf3e095ae1a4c75a",
|
||||
"https://deno.land/std@0.203.0/assert/unreachable.ts": "4600dc0baf7d9c15a7f7d234f00c23bca8f3eba8b140286aaca7aa998cf9a536",
|
||||
"https://deno.land/std@0.203.0/fmt/colors.ts": "c51c4642678eb690dcf5ffee5918b675bf01a33fba82acf303701ae1a4f8c8d9",
|
||||
"https://deno.land/std@0.203.0/testing/_test_suite.ts": "30f018feeb3835f12ab198d8a518f9089b1bcb2e8c838a8b615ab10d5005465c",
|
||||
"https://deno.land/std@0.203.0/testing/bdd.ts": "3f446df5ef8e856a869e8eec54c8482590415741ff0b6358a00c43486cc15769",
|
||||
"https://deno.land/std@0.203.0/testing/mock.ts": "6576b4aa55ee20b1990d656a78fff83599e190948c00e9f25a7f3ac5e9d6492d",
|
||||
"https://deno.land/std@0.216.0/io/types.ts": "748bbb3ac96abda03594ef5a0db15ce5450dcc6c0d841c8906f8b10ac8d32c96",
|
||||
"https://deno.land/std@0.216.0/io/write_all.ts": "24aac2312bb21096ae3ae0b102b22c26164d3249dff96dbac130958aa736f038",
|
||||
"https://jsr.io/@std/cli/1.0.9/parse_args.ts": "29ac18602d8836d2723cab1d90111ff954acc369f184626a3f9f677e3185caef"
|
||||
},
|
||||
"workspace": {
|
||||
"dependencies": [
|
||||
"jsr:@std/io@~0.225.3",
|
||||
"npm:@msgpack/msgpack@3.0.0-beta2",
|
||||
"npm:@rocket.chat/ui-kit@~0.31.22",
|
||||
"npm:acorn-walk@8.3.5",
|
||||
"npm:acorn@8.17.0",
|
||||
"npm:astring@1.8.6",
|
||||
"npm:jsonrpc-lite@2.2.0",
|
||||
"npm:stack-trace@0.0.10",
|
||||
"npm:uuid@8.3.2"
|
||||
]
|
||||
}
|
||||
}
|
||||
28
packages/apps/deno-runtime/error-handlers.ts
Normal file
28
packages/apps/deno-runtime/error-handlers.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import * as Messenger from '@rocket.chat/apps/base-runtime/lib/messenger';
|
||||
|
||||
export function unhandledRejectionListener(event: PromiseRejectionEvent) {
|
||||
event.preventDefault();
|
||||
|
||||
const error = event.reason;
|
||||
|
||||
Messenger.sendNotification({
|
||||
method: 'unhandledRejection',
|
||||
params: [error?.stack || error],
|
||||
});
|
||||
}
|
||||
|
||||
export function unhandledExceptionListener(event: ErrorEvent) {
|
||||
event.preventDefault();
|
||||
|
||||
const error = event.error;
|
||||
|
||||
Messenger.sendNotification({
|
||||
method: 'uncaughtException',
|
||||
params: [error?.stack || error],
|
||||
});
|
||||
}
|
||||
|
||||
export default function registerErrorListeners() {
|
||||
addEventListener('unhandledrejection', unhandledRejectionListener);
|
||||
addEventListener('error', unhandledExceptionListener);
|
||||
}
|
||||
44
packages/apps/deno-runtime/lib/require.ts
Normal file
44
packages/apps/deno-runtime/lib/require.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { createRequire } from 'node:module';
|
||||
|
||||
const _require = createRequire(import.meta.url);
|
||||
|
||||
const ALLOWED_NATIVE_MODULES = [
|
||||
'path',
|
||||
'url',
|
||||
'crypto',
|
||||
'buffer',
|
||||
'stream',
|
||||
'net',
|
||||
'http',
|
||||
'https',
|
||||
'zlib',
|
||||
'util',
|
||||
'punycode',
|
||||
'os',
|
||||
'querystring',
|
||||
'fs',
|
||||
];
|
||||
|
||||
const ALLOWED_EXTERNAL_MODULES = ['uuid', '@rocket.chat/apps-engine'];
|
||||
|
||||
// As the apps are bundled, the only times they will call require are
|
||||
// 1. To require native modules
|
||||
// 2. To require external npm packages we may provide
|
||||
// 3. To require apps-engine files
|
||||
export const require = (module: string) => {
|
||||
// Normalize Node built-in specifiers: accept both 'crypto' and 'node:crypto'
|
||||
const normalized = module.replace('node:', '');
|
||||
|
||||
|
||||
// We allow variants like 'fs', 'node:fs' or 'node:fs/promises'
|
||||
if (ALLOWED_NATIVE_MODULES.some((mod) => normalized.startsWith(mod))) {
|
||||
return _require(`node:${normalized}`);
|
||||
}
|
||||
|
||||
if (ALLOWED_EXTERNAL_MODULES.some((mod) => module.startsWith(mod))) {
|
||||
// External modules cannot be resolved by the require algorithm, we need to pass the full path already resolved by Deno's import map
|
||||
return _require(import.meta.resolve(module).replace('file://', ''));
|
||||
}
|
||||
|
||||
throw new Error(`Module ${module} is not allowed`);
|
||||
};
|
||||
16
packages/apps/deno-runtime/lib/transports/stdoutTransport.ts
Normal file
16
packages/apps/deno-runtime/lib/transports/stdoutTransport.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { writeAll } from '@std/io';
|
||||
|
||||
import type { Transport } from '@rocket.chat/apps/base-runtime/lib/messenger';
|
||||
|
||||
/**
|
||||
* Transport that writes messages to the process' standard output.
|
||||
*
|
||||
* This is the transport used when the runtime is executed as a subprocess by
|
||||
* the Apps-Engine framework, and it is specific to platforms that expose a
|
||||
* Node-compatible `process.stdout`.
|
||||
*/
|
||||
export const stdoutTransport: Transport = {
|
||||
send(message: Uint8Array): Promise<void> {
|
||||
return writeAll(Deno.stdout, message);
|
||||
},
|
||||
};
|
||||
54
packages/apps/deno-runtime/main.ts
Normal file
54
packages/apps/deno-runtime/main.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { Buffer } from 'node:buffer';
|
||||
import { Socket } from 'node:net';
|
||||
import process from 'node:process';
|
||||
|
||||
// Deno consumes the base as TypeScript source through the import map: ESM
|
||||
// imports honor the map (`@rocket.chat/apps/` → `../`), so bare specifiers and
|
||||
// `@rocket.chat/apps/*` resolve to allowed paths. Importing the compiled `dist`
|
||||
// instead would run the base as CommonJS, whose `require()` bypasses the import
|
||||
// map and falls back to node_modules — outside the subprocess read allowlist.
|
||||
import { setSandboxGlobals, setSandboxRequire } from '@rocket.chat/apps/base-runtime/handlers/app/construct';
|
||||
import { setTransport } from '@rocket.chat/apps/base-runtime/lib/messenger';
|
||||
import { startMainLoop } from '@rocket.chat/apps/base-runtime/mainLoop';
|
||||
|
||||
import registerErrorListeners from './error-handlers';
|
||||
import { require } from './lib/require';
|
||||
import { stdoutTransport } from './lib/transports/stdoutTransport';
|
||||
|
||||
if (!process.argv.includes('--subprocess')) {
|
||||
console.error(`
|
||||
This is the Deno wrapper for the Rocket.Chat Apps runtime. It is not meant to be executed stand-alone;
|
||||
It is instead meant to be executed as a subprocess by the Apps-Engine framework.
|
||||
`);
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function prepareEnvironment() {
|
||||
// Deno does not behave equally to Node when it comes to piping content to a socket
|
||||
// So we intervene here
|
||||
const originalFinal = Socket.prototype._final;
|
||||
// deno-lint-ignore no-explicit-any
|
||||
Socket.prototype._final = function _final(cb: any) {
|
||||
// Deno closes the readable stream in the Socket earlier than Node
|
||||
// The exact reason for that is yet unknown, so we'll need to simply delay the execution
|
||||
// which allows data to be read in a response
|
||||
setTimeout(() => originalFinal.call(this, cb), 1);
|
||||
};
|
||||
}
|
||||
|
||||
// This runtime communicates with the Apps-Engine host through stdout
|
||||
setTransport(stdoutTransport);
|
||||
|
||||
// Deno's sandbox `require` is a createRequire shim that resolves compiled
|
||||
// apps-engine paths; the eval shell additionally needs a `Buffer` and a
|
||||
// shadowed `Deno` (→ undefined) bound by name.
|
||||
setSandboxRequire(require);
|
||||
setSandboxGlobals({ Buffer, Deno: undefined });
|
||||
|
||||
// Process-global side effect; doing it once at startup is cleaner than inside construct
|
||||
prepareEnvironment();
|
||||
|
||||
registerErrorListeners();
|
||||
|
||||
startMainLoop();
|
||||
44
packages/apps/deno-runtime/tests/error-handlers.test.ts
Normal file
44
packages/apps/deno-runtime/tests/error-handlers.test.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { assertEquals } from 'https://deno.land/std@0.203.0/assert/mod.ts';
|
||||
import { describe, it } from 'https://deno.land/std@0.203.0/testing/bdd.ts';
|
||||
import { spy } from 'https://deno.land/std@0.203.0/testing/mock.ts';
|
||||
|
||||
import * as Messenger from '@rocket.chat/apps/base-runtime/lib/messenger';
|
||||
|
||||
import { unhandledExceptionListener, unhandledRejectionListener } from '../error-handlers';
|
||||
|
||||
// the Deno seam suite: exercises the platform-specific error-handler
|
||||
// registration and, in doing so, confirms the Deno adapter resolves the base
|
||||
// source through the import map.
|
||||
describe('error-handlers (Deno seam)', () => {
|
||||
it('forwards unhandled rejections to the base Messenger as a notification', () => {
|
||||
const enqueue = spy(Messenger.Queue, 'enqueue');
|
||||
|
||||
try {
|
||||
const error = new Error('rejected');
|
||||
unhandledRejectionListener({ preventDefault() {}, reason: error } as unknown as PromiseRejectionEvent);
|
||||
|
||||
assertEquals(enqueue.calls.length, 1);
|
||||
const notification = enqueue.calls[0].args[0] as { method: string; params: unknown[] };
|
||||
assertEquals(notification.method, 'unhandledRejection');
|
||||
assertEquals(notification.params, [error.stack]);
|
||||
} finally {
|
||||
enqueue.restore();
|
||||
}
|
||||
});
|
||||
|
||||
it('forwards uncaught exceptions to the base Messenger as a notification', () => {
|
||||
const enqueue = spy(Messenger.Queue, 'enqueue');
|
||||
|
||||
try {
|
||||
const error = new Error('thrown');
|
||||
unhandledExceptionListener({ preventDefault() {}, error } as unknown as ErrorEvent);
|
||||
|
||||
assertEquals(enqueue.calls.length, 1);
|
||||
const notification = enqueue.calls[0].args[0] as { method: string; params: unknown[] };
|
||||
assertEquals(notification.method, 'uncaughtException');
|
||||
assertEquals(notification.params, [error.stack]);
|
||||
} finally {
|
||||
enqueue.restore();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user