From 8cc57546d22a7329d0341dfdef269db28424e3e6 Mon Sep 17 00:00:00 2001 From: Mateusz Russak Date: Wed, 29 Jul 2026 21:47:39 +0200 Subject: [PATCH] chore(deno): upgrade runtime to 2.9.4 (+ non-mutating serializer fix) (#316) --- .github/workflows/apps.yml | 2 +- .github/workflows/dev.yml | 2 +- .github/workflows/docker.yml | 2 +- .github/workflows/tests.yml | 2 +- Dockerfile | 2 +- deno.lock | 169 +++++++++++++++++++++++++- deno/server/core/app.ts | 2 +- deno/server/core/serializer.ts | 15 ++- deno/server/infra/repo/serializer.ts | 39 +++--- deno/server/inter/cli/mod.ts | 2 +- deno/storage/src/core/resizePool.ts | 2 +- deno/storage/tests/resizePool.test.ts | 2 +- 12 files changed, 211 insertions(+), 30 deletions(-) diff --git a/.github/workflows/apps.yml b/.github/workflows/apps.yml index 9d9ccceb..cc5f4302 100644 --- a/.github/workflows/apps.yml +++ b/.github/workflows/apps.yml @@ -18,7 +18,7 @@ jobs: - uses: denoland/setup-deno@v2 with: - deno-version: '2.6.8' + deno-version: '2.9.4' - run: deno install --allow-scripts diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 34de0403..571c9097 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -35,7 +35,7 @@ jobs: - uses: actions/checkout@v3 - uses: denoland/setup-deno@v2 with: - deno-version: '2.6.8' + deno-version: '2.9.4' - run: deno install --allow-scripts - name: Install Socket Firewall uses: socketdev/action@ba6de6cc0565af1f42295590380973573297e31f diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 97dddde9..1d373f9e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -47,7 +47,7 @@ jobs: - uses: actions/checkout@v3 - uses: denoland/setup-deno@v2 with: - deno-version: '2.6.8' + deno-version: '2.9.4' - run: deno install --allow-scripts - run: deno task migrate:tests - run: deno task check diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ca0a2540..e7e9e717 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,7 +29,7 @@ jobs: - uses: actions/checkout@v3 - uses: denoland/setup-deno@v2 with: - deno-version: '2.6.8' + deno-version: '2.9.4' - run: deno install --allow-scripts - name: Install Socket Firewall uses: socketdev/action@ba6de6cc0565af1f42295590380973573297e31f diff --git a/Dockerfile b/Dockerfile index 689c11c0..c8727819 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ ARG APP_VERSION=3.x.x ENV APP_VERSION=$APP_VERSION RUN APP_NAME=quack APP_VERSION=$APP_VERSION pnpm build -FROM denoland/deno:alpine-2.6.8 +FROM denoland/deno:alpine-2.9.4 # WORKAROUND: Deno alpine image ships glibc-linked libs in /usr/local/lib/ that break # apk and post-install triggers (libz, libcrypto, libzstd, libgcc_s shadow Alpine's musl libs). # Move them aside during apk install, then restore for Deno compatibility. diff --git a/deno.lock b/deno.lock index ca41e706..953fb498 100644 --- a/deno.lock +++ b/deno.lock @@ -1,44 +1,75 @@ { "version": "5", "specifiers": { + "jsr:@cliffy/command@1.0.0-rc.5": "1.0.0-rc.5", + "jsr:@cliffy/flags@1.0.0-rc.5": "1.0.0-rc.5", + "jsr:@cliffy/internal@1.0.0-rc.5": "1.0.0-rc.5", + "jsr:@cliffy/table@1.0.0-rc.5": "1.0.0-rc.5", "jsr:@jd1378/another-cookiejar@^5.0.7": "5.0.7", + "jsr:@oak/commons@0.11": "0.11.0", + "jsr:@oak/oak@16.1.0": "16.1.0", "jsr:@planigale/body-parser@*": "0.2.1", + "jsr:@planigale/body-parser@0.2.1": "0.2.1", "jsr:@planigale/planigale@*": "0.6.10", + "jsr:@planigale/planigale@0.6.10": "0.6.10", "jsr:@planigale/planigale@~0.6.10": "0.6.10", "jsr:@planigale/planigale@~0.6.4": "0.6.10", "jsr:@planigale/planigale@~0.6.8": "0.6.10", "jsr:@planigale/querystring@0.1": "0.1.0", "jsr:@planigale/schema@*": "0.1.4", + "jsr:@planigale/schema@0.1.4": "0.1.4", "jsr:@planigale/sse@0.2.8": "0.2.8", "jsr:@planigale/sse@~0.2.5": "0.2.8", "jsr:@planigale/testing@*": "0.3.6", + "jsr:@planigale/testing@0.3.6": "0.3.6", "jsr:@std/assert@0.221": "0.221.0", + "jsr:@std/assert@0.223": "0.223.0", + "jsr:@std/assert@0.224": "0.224.0", + "jsr:@std/assert@0.226": "0.226.0", "jsr:@std/assert@1": "1.0.18", "jsr:@std/assert@1.0.0": "1.0.0", "jsr:@std/assert@1.0.14": "1.0.14", "jsr:@std/async@^1.0.0-rc.1": "1.1.0", + "jsr:@std/bytes@0.223": "0.223.0", + "jsr:@std/bytes@0.224": "0.224.0", "jsr:@std/bytes@^1.0.0-rc.3": "1.0.6", "jsr:@std/bytes@^1.0.2": "1.0.6", + "jsr:@std/bytes@^1.0.6": "1.0.6", + "jsr:@std/cli@1.0.0-rc.2": "1.0.0-rc.2", "jsr:@std/cli@~0.224.7": "0.224.7", + "jsr:@std/crypto@0.223": "0.223.0", + "jsr:@std/crypto@0.224": "0.224.0", + "jsr:@std/crypto@^1.0.5": "1.0.5", + "jsr:@std/encoding@0.223": "0.223.0", "jsr:@std/encoding@1.0.0-rc.2": "1.0.0-rc.2", "jsr:@std/encoding@1.0.10": "1.0.10", "jsr:@std/fmt@~0.225.4": "0.225.6", "jsr:@std/fs@0.221.0": "0.221.0", + "jsr:@std/fs@1.0.17": "1.0.17", + "jsr:@std/http@0.223": "0.223.0", + "jsr:@std/http@0.224": "0.224.5", "jsr:@std/http@~0.224.5": "0.224.5", "jsr:@std/internal@^1.0.1": "1.0.12", "jsr:@std/internal@^1.0.10": "1.0.12", "jsr:@std/internal@^1.0.12": "1.0.12", + "jsr:@std/io@0.223": "0.223.0", "jsr:@std/io@~0.224.1": "0.224.9", + "jsr:@std/media-types@0.223": "0.223.0", + "jsr:@std/media-types@0.224": "0.224.1", "jsr:@std/media-types@1.0.2": "1.0.2", "jsr:@std/media-types@^1.0.0-rc.1": "1.0.2", "jsr:@std/net@~0.224.3": "0.224.5", "jsr:@std/path@0.221": "0.221.0", + "jsr:@std/path@0.223": "0.223.0", "jsr:@std/path@1.0.0": "1.0.0", "jsr:@std/path@1.0.0-rc.2": "1.0.0-rc.2", "jsr:@std/path@1.0.1": "1.0.1", "jsr:@std/path@1.0.2": "1.0.2", "jsr:@std/path@1.1.2": "1.1.2", + "jsr:@std/path@^1.0.9": "1.1.2", "jsr:@std/streams@~0.224.5": "0.224.5", + "jsr:@std/text@1.0.0-rc.1": "1.0.0-rc.1", + "jsr:@std/uuid@1.0.9": "1.0.9", "jsr:@ts-rex/bcrypt@1.0.3": "1.0.3", "npm:@cf-wasm/photon@0.3.6": "0.3.6", "npm:@faker-js/faker@9.3.0": "9.3.0", @@ -56,15 +87,66 @@ "npm:mongodb@6.12.0": "6.12.0", "npm:mongodb@6.19.0": "6.19.0", "npm:nodemon@3.1.10": "3.1.10", + "npm:path-to-regexp@6.2.1": "6.2.1", "npm:valibot@0.31.1": "0.31.1", "npm:valibot@0.36.0": "0.36.0", "npm:valibot@1.1.0": "1.1.0", "npm:web-push@3.6.7": "3.6.7" }, "jsr": { + "@cliffy/command@1.0.0-rc.5": { + "integrity": "55e00a1d0ae38152fb275a89494a81ffb9b144eb9060107c0be5af46e1ba736c", + "dependencies": [ + "jsr:@cliffy/flags", + "jsr:@cliffy/internal", + "jsr:@cliffy/table", + "jsr:@std/fmt", + "jsr:@std/text" + ] + }, + "@cliffy/flags@1.0.0-rc.5": { + "integrity": "bd33b7b399e0af353f5516d87a2d552d46ee7e7f4a6f0c0bc65fcce750710217", + "dependencies": [ + "jsr:@std/text" + ] + }, + "@cliffy/internal@1.0.0-rc.5": { + "integrity": "1e8dca4fcfba1815bf1a899bb880e09f8b45284c352465ef8fb015887c1fc126" + }, + "@cliffy/table@1.0.0-rc.5": { + "integrity": "2b3e1b4764bbb56b0c39aeba95bc0bb551d9bd4475fbb6d1ce368c08b7ef9eb3", + "dependencies": [ + "jsr:@std/cli@1.0.0-rc.2", + "jsr:@std/fmt" + ] + }, "@jd1378/another-cookiejar@5.0.7": { "integrity": "788e22828dd428aaebaedc9acbed6ae7033cc240982a10fcfc34aa72dcf01088" }, + "@oak/commons@0.11.0": { + "integrity": "07702bfe5c07cd8144c422022994da1f9fea466b185824f4be63a2b1b1a65125", + "dependencies": [ + "jsr:@std/assert@0.226", + "jsr:@std/bytes@0.224", + "jsr:@std/crypto@0.224", + "jsr:@std/http@0.224", + "jsr:@std/media-types@0.224" + ] + }, + "@oak/oak@16.1.0": { + "integrity": "ab21506555fffeb08dc8f45ff5d28607e8087949ff58bd2964b27df65994480b", + "dependencies": [ + "jsr:@oak/commons", + "jsr:@std/assert@0.223", + "jsr:@std/bytes@0.223", + "jsr:@std/crypto@0.223", + "jsr:@std/http@0.223", + "jsr:@std/io@0.223", + "jsr:@std/media-types@0.223", + "jsr:@std/path@0.223", + "npm:path-to-regexp" + ] + }, "@planigale/body-parser@0.2.1": { "integrity": "005c9d126aea22d32a3e45d5790d2eff5398a9ff5f3c827f7380a78042bbe673", "dependencies": [ @@ -77,7 +159,7 @@ "dependencies": [ "jsr:@planigale/querystring", "jsr:@planigale/sse@~0.2.5", - "jsr:@std/http", + "jsr:@std/http@~0.224.5", "jsr:@std/media-types@1.0.2", "jsr:@std/path@1.0.1" ] @@ -112,6 +194,15 @@ "@std/assert@0.221.0": { "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a" }, + "@std/assert@0.223.0": { + "integrity": "eb8d6d879d76e1cc431205bd346ed4d88dc051c6366365b1af47034b0670be24" + }, + "@std/assert@0.224.0": { + "integrity": "8643233ec7aec38a940a8264a6e3eed9bfa44e7a71cc6b3c8874213ff401967f" + }, + "@std/assert@0.226.0": { + "integrity": "0dfb5f7c7723c18cec118e080fec76ce15b4c31154b15ad2bd74822603ef75b3" + }, "@std/assert@1.0.0": { "integrity": "0e4f6d873f7f35e2a1e6194ceee39686c996b9e5d134948e644d35d4c4df2008", "dependencies": [ @@ -133,12 +224,40 @@ "@std/async@1.1.0": { "integrity": "72418df08d1be84668a53e48aab3520d68ae6882182f8a5ca75c6d1f087220d1" }, + "@std/bytes@0.223.0": { + "integrity": "84b75052cd8680942c397c2631318772b295019098f40aac5c36cead4cba51a8" + }, + "@std/bytes@0.224.0": { + "integrity": "a2250e1d0eb7d1c5a426f21267ab9bdeac2447fa87a3d0d1a467d3f7a6058e49" + }, "@std/bytes@1.0.6": { "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a" }, "@std/cli@0.224.7": { "integrity": "654ca6477518e5e3a0d3fabafb2789e92b8c0febf1a1d24ba4b567aba94b5977" }, + "@std/cli@1.0.0-rc.2": { + "integrity": "97dfae82b9f0e189768ebfa7a5da53375955b94bad0a1804f8e3b73563b03787" + }, + "@std/crypto@0.223.0": { + "integrity": "1aa9555ff56b09e197ad988ea200f84bc6781fd4fd83f3a156ee44449af93000", + "dependencies": [ + "jsr:@std/assert@0.223", + "jsr:@std/encoding@0.223" + ] + }, + "@std/crypto@0.224.0": { + "integrity": "154ef3ff08ef535562ef1a718718c5b2c5fc3808f0f9100daad69e829bfcdf2d", + "dependencies": [ + "jsr:@std/assert@0.224" + ] + }, + "@std/crypto@1.0.5": { + "integrity": "0dcfbb319fe0bba1bd3af904ceb4f948cde1b92979ec1614528380ed308a3b40" + }, + "@std/encoding@0.223.0": { + "integrity": "2b5615a75e00337ce113f34cf2f9b8c18182c751a8dcc8b1a2c2fc0e117bef00" + }, "@std/encoding@1.0.0-rc.2": { "integrity": "160d7674a20ebfbccdf610b3801fee91cf6e42d1c106dd46bbaf46e395cd35ef" }, @@ -155,11 +274,24 @@ "jsr:@std/path@0.221" ] }, + "@std/fs@1.0.17": { + "integrity": "1c00c632677c1158988ef7a004cb16137f870aafdb8163b9dce86ec652f3952b", + "dependencies": [ + "jsr:@std/path@^1.0.9" + ] + }, + "@std/http@0.223.0": { + "integrity": "15ab8a0c5a7e9d5be017a15b01600f20f66602ceec48b378939fa24fcec522aa", + "dependencies": [ + "jsr:@std/assert@0.223", + "jsr:@std/encoding@0.223" + ] + }, "@std/http@0.224.5": { "integrity": "b03b5d1529f6c423badfb82f6640f9f2557b4034cd7c30655ba5bb447ff750a4", "dependencies": [ "jsr:@std/async", - "jsr:@std/cli", + "jsr:@std/cli@~0.224.7", "jsr:@std/encoding@1.0.0-rc.2", "jsr:@std/fmt", "jsr:@std/media-types@^1.0.0-rc.1", @@ -171,12 +303,24 @@ "@std/internal@1.0.12": { "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" }, + "@std/io@0.223.0": { + "integrity": "2d8c3c2ab3a515619b90da2c6ff5ea7b75a94383259ef4d02116b228393f84f1", + "dependencies": [ + "jsr:@std/bytes@0.223" + ] + }, "@std/io@0.224.9": { "integrity": "4414664b6926f665102e73c969cfda06d2c4c59bd5d0c603fd4f1b1c840d6ee3", "dependencies": [ "jsr:@std/bytes@^1.0.2" ] }, + "@std/media-types@0.223.0": { + "integrity": "84684680c2eb6bc6d9369c6d6f26a49decaf2c7603ff531862dda575d9d6776e" + }, + "@std/media-types@0.224.1": { + "integrity": "9e69a5daed37c5b5c6d3ce4731dc191f80e67f79bed392b0957d1d03b87f11e1" + }, "@std/media-types@1.0.2": { "integrity": "abb78dc8f7d88141cba8c4d60fc1e8b421e5c7b0d7c84f2f708bc666cad46784" }, @@ -189,6 +333,12 @@ "jsr:@std/assert@0.221" ] }, + "@std/path@0.223.0": { + "integrity": "593963402d7e6597f5a6e620931661053572c982fc014000459edc1f93cc3989", + "dependencies": [ + "jsr:@std/assert@0.223" + ] + }, "@std/path@1.0.0-rc.2": { "integrity": "39f20d37a44d1867abac8d91c169359ea6e942237a45a99ee1e091b32b921c7d" }, @@ -211,7 +361,17 @@ "integrity": "bcde7818dd5460d474cdbd674b15f6638b9cd73cd64e52bd852fba2bd4d8ec91", "dependencies": [ "jsr:@std/bytes@^1.0.0-rc.3", - "jsr:@std/io" + "jsr:@std/io@~0.224.1" + ] + }, + "@std/text@1.0.0-rc.1": { + "integrity": "34c722203e87ee12792c8d4a0cd2ee0e001341cbce75b860fc21be19d62232b0" + }, + "@std/uuid@1.0.9": { + "integrity": "44b627bf2d372fe1bd099e2ad41b2be41a777fc94e62a3151006895a037f1642", + "dependencies": [ + "jsr:@std/bytes@^1.0.6", + "jsr:@std/crypto@^1.0.5" ] }, "@ts-rex/bcrypt@1.0.3": { @@ -1062,6 +1222,9 @@ "entities@6.0.1" ] }, + "path-to-regexp@6.2.1": { + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + }, "picomatch@2.3.1": { "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, diff --git a/deno/server/core/app.ts b/deno/server/core/app.ts index 279af0bb..6d124de0 100644 --- a/deno/server/core/app.ts +++ b/deno/server/core/app.ts @@ -26,7 +26,7 @@ class App { this.core.bus.direct(userId, { type: "message", id: `ephemeral:${Math.random().toString(10)}`, - appId, + appId: this.appId, ephemeral: true, channelId: message.channelId, parentId: message.parentId, diff --git a/deno/server/core/serializer.ts b/deno/server/core/serializer.ts index 3e86d4d4..17bfbabc 100644 --- a/deno/server/core/serializer.ts +++ b/deno/server/core/serializer.ts @@ -1,5 +1,11 @@ import { EntityId } from "../types.ts"; +function isPlainObject(obj: unknown): obj is Record { + if (typeof obj !== "object" || obj === null) return false; + const proto = Object.getPrototypeOf(obj); + return proto === Object.prototype || proto === null; +} + function recursiveSerialize(obj: unknown): unknown { if (obj instanceof EntityId) { return obj.toString(); @@ -7,11 +13,12 @@ function recursiveSerialize(obj: unknown): unknown { if (Array.isArray(obj)) { return obj.map(recursiveSerialize); } - if (typeof obj === "object" && obj !== null) { - const record = obj as Record; - for (const key in record) { - record[key] = recursiveSerialize(record[key]); + if (isPlainObject(obj)) { + const result: Record = {}; + for (const key in obj) { + result[key] = recursiveSerialize(obj[key]); } + return result; } return obj; } diff --git a/deno/server/infra/repo/serializer.ts b/deno/server/infra/repo/serializer.ts index 6de128c5..f87791af 100644 --- a/deno/server/infra/repo/serializer.ts +++ b/deno/server/infra/repo/serializer.ts @@ -1,6 +1,12 @@ import { EntityId } from "../../types.ts"; import { ObjectId } from "./db.ts"; +function isPlainObject(obj: unknown): obj is Record { + if (typeof obj !== "object" || obj === null) return false; + const proto = Object.getPrototypeOf(obj); + return proto === Object.prototype || proto === null; +} + // deno-lint-ignore no-explicit-any function recursiveDeserialize(obj: unknown): any { if (obj instanceof EntityId) { @@ -12,15 +18,16 @@ function recursiveDeserialize(obj: unknown): any { if (Array.isArray(obj)) { return obj.map(recursiveDeserialize); } - if (typeof obj === "object" && obj !== null) { - const record = obj as Record; - for (const key in record) { - record[key] = recursiveDeserialize(record[key]); + if (isPlainObject(obj)) { + const result: Record = {}; + for (const key in obj) { + result[key] = recursiveDeserialize(obj[key]); } - if (record._id) { - record.id = record._id; - delete record._id; + if (result._id) { + result.id = result._id; + delete result._id; } + return result; } return obj; } @@ -35,18 +42,22 @@ function recursiveSerialize(obj: unknown): any { if (obj instanceof EntityId) { return new ObjectId(obj.value); } + if (obj instanceof ObjectId) { + return obj; + } if (Array.isArray(obj)) { return obj.map(recursiveSerialize); } - if (typeof obj === "object" && obj !== null) { - const record = obj as Record; - for (const key in record) { - record[key] = recursiveSerialize(record[key]); + if (isPlainObject(obj)) { + const result: Record = {}; + for (const key in obj) { + result[key] = recursiveSerialize(obj[key]); } - if (record.id) { - record._id = record.id; - delete record.id; + if (result.id) { + result._id = result.id; + delete result.id; } + return result; } return obj; } diff --git a/deno/server/inter/cli/mod.ts b/deno/server/inter/cli/mod.ts index ab3634bc..198f83a0 100644 --- a/deno/server/inter/cli/mod.ts +++ b/deno/server/inter/cli/mod.ts @@ -5,7 +5,7 @@ const run = new Command() .description("Runs the chat server.") .action( ( - _options: Record, + _options: void, source: string, _destination?: string, ) => { diff --git a/deno/storage/src/core/resizePool.ts b/deno/storage/src/core/resizePool.ts index 7b0b7f01..88ee9cbe 100644 --- a/deno/storage/src/core/resizePool.ts +++ b/deno/storage/src/core/resizePool.ts @@ -10,7 +10,7 @@ type Task = { type Active = { resolve: Pending; - timer: number; + timer: ReturnType; }; const DEFAULT_WORKERS = 2; diff --git a/deno/storage/tests/resizePool.test.ts b/deno/storage/tests/resizePool.test.ts index bc514383..5e211660 100644 --- a/deno/storage/tests/resizePool.test.ts +++ b/deno/storage/tests/resizePool.test.ts @@ -134,7 +134,7 @@ Deno.test("ResizePool - times out a stuck job and stays usable", async () => { const first = await pool.resize(new Uint8Array(source), 100, 0, true); assertEquals(first, null, "the job should time out to null"); - let guard: number | undefined; + let guard: ReturnType | undefined; const stuck = new Promise<"stuck">((resolve) => { guard = setTimeout(() => resolve("stuck"), 3000); });