Merge pull request #548 from FoxxMD/express5

chore: Update to expressjs 5
This commit is contained in:
Matt Foxx 2026-04-09 09:34:29 -04:00 committed by GitHub
commit 2f53a60da1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 314 additions and 280 deletions

489
package-lock.json generated
View file

@ -14,7 +14,6 @@
"@atcute/identity-resolver-node": "^1.0.3",
"@atproto/api": "^0.18.0",
"@atproto/oauth-client-node": "^0.3.10",
"@awaitjs/express": "^0.6.3",
"@donedeal0/superdiff": "^1.1.1",
"@ewanc26/tid": "^1.0.2",
"@foxxmd/chromecast-client": "^1.0.4",
@ -29,7 +28,6 @@
"@lukehagar/plexjs": "^0.39.0",
"@supercharge/promise-pool": "^3.0.0",
"@svrooij/sonos": "^2.5.0",
"@types/express-serve-static-core": "^4.19.6",
"@xhayper/discord-rpc": "^1.3.0",
"abort-controller-x": "^0.5.0",
"address": "^1.2.2",
@ -49,7 +47,7 @@
"dbus-ts": "^0.0.7",
"discord.js": "^14.26.0",
"dotenv": "^10.0.0",
"express": "^4.22.1",
"express": "^5.2.1",
"express-session": "^1.19.0",
"fast-deep-equal": "^3.1.3",
"fixed-size-list": "^0.3.0",
@ -124,7 +122,8 @@
"@types/common-tags": "^1.8.1",
"@types/concat-stream": "^2.0.0",
"@types/cors": "^2.8.17",
"@types/express": "^4.17.13",
"@types/express": "^5.0.6",
"@types/express-serve-static-core": "^5.1.1",
"@types/express-session": "^1.18.2",
"@types/formidable": "^3.4.5",
"@types/jest": "^27.5.2",
@ -535,16 +534,6 @@
"zod": "^3.23.8"
}
},
"node_modules/@awaitjs/express": {
"version": "0.6.3",
"license": "Apache 2.0",
"engines": {
"node": ">=7.6.0"
},
"peerDependencies": {
"express": "4.x"
}
},
"node_modules/@babel/code-frame": {
"version": "7.29.0",
"dev": true,
@ -4305,18 +4294,22 @@
"license": "MIT"
},
"node_modules/@types/express": {
"version": "4.17.21",
"version": "5.0.6",
"resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz",
"integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.33",
"@types/qs": "*",
"@types/serve-static": "*"
"@types/express-serve-static-core": "^5.0.0",
"@types/serve-static": "^2"
}
},
"node_modules/@types/express-serve-static-core": {
"version": "4.19.6",
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz",
"integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*",
@ -4374,7 +4367,9 @@
"license": "MIT"
},
"node_modules/@types/http-errors": {
"version": "2.0.4",
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
"integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
"dev": true,
"license": "MIT"
},
@ -4439,6 +4434,7 @@
},
"node_modules/@types/mime": {
"version": "1.3.5",
"dev": true,
"license": "MIT"
},
"node_modules/@types/mocha": {
@ -4482,10 +4478,12 @@
},
"node_modules/@types/qs": {
"version": "6.9.16",
"dev": true,
"license": "MIT"
},
"node_modules/@types/range-parser": {
"version": "1.2.7",
"dev": true,
"license": "MIT"
},
"node_modules/@types/react": {
@ -4532,6 +4530,7 @@
},
"node_modules/@types/send": {
"version": "0.17.4",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/mime": "^1",
@ -4539,13 +4538,14 @@
}
},
"node_modules/@types/serve-static": {
"version": "1.15.7",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz",
"integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/http-errors": "*",
"@types/node": "*",
"@types/send": "*"
"@types/node": "*"
}
},
"node_modules/@types/sinon": {
@ -5939,16 +5939,43 @@
"license": "MIT"
},
"node_modules/accepts": {
"version": "1.3.8",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
"integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
"license": "MIT",
"dependencies": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
"mime-types": "^3.0.0",
"negotiator": "^1.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/accepts/node_modules/mime-db": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/accepts/node_modules/mime-types": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
"integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
"license": "MIT",
"dependencies": {
"mime-db": "^1.54.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/acorn": {
"version": "8.16.0",
"license": "MIT",
@ -6093,10 +6120,6 @@
"dequal": "^2.0.3"
}
},
"node_modules/array-flatten": {
"version": "1.1.1",
"license": "MIT"
},
"node_modules/array-union": {
"version": "2.1.0",
"dev": true,
@ -6343,46 +6366,6 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/body-parser/node_modules/media-typer": {
"version": "1.1.0",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/body-parser/node_modules/mime-db": {
"version": "1.54.0",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/body-parser/node_modules/mime-types": {
"version": "3.0.2",
"license": "MIT",
"dependencies": {
"mime-db": "^1.54.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/body-parser/node_modules/type-is": {
"version": "2.0.1",
"license": "MIT",
"dependencies": {
"content-type": "^1.0.5",
"media-typer": "^1.1.0",
"mime-types": "^3.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/brace-expansion": {
"version": "1.1.13",
"dev": true,
@ -6973,13 +6956,16 @@
}
},
"node_modules/content-disposition": {
"version": "0.5.4",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
"integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==",
"license": "MIT",
"dependencies": {
"safe-buffer": "5.2.1"
},
"engines": {
"node": ">= 0.6"
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/content-type": {
@ -7002,8 +6988,13 @@
}
},
"node_modules/cookie-signature": {
"version": "1.0.6",
"license": "MIT"
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
"license": "MIT",
"engines": {
"node": ">=6.6.0"
}
},
"node_modules/cookiejar": {
"version": "2.1.4",
@ -8077,43 +8068,42 @@
}
},
"node_modules/express": {
"version": "4.22.1",
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "~1.20.3",
"content-disposition": "~0.5.4",
"content-type": "~1.0.4",
"cookie": "~0.7.1",
"cookie-signature": "~1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "~1.3.1",
"fresh": "~0.5.2",
"http-errors": "~2.0.0",
"merge-descriptors": "1.0.3",
"methods": "~1.1.2",
"on-finished": "~2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "~0.1.12",
"proxy-addr": "~2.0.7",
"qs": "~6.14.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "~0.19.0",
"serve-static": "~1.16.2",
"setprototypeof": "1.2.0",
"statuses": "~2.0.1",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
"accepts": "^2.0.0",
"body-parser": "^2.2.1",
"content-disposition": "^1.0.0",
"content-type": "^1.0.5",
"cookie": "^0.7.1",
"cookie-signature": "^1.2.1",
"debug": "^4.4.0",
"depd": "^2.0.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"finalhandler": "^2.1.0",
"fresh": "^2.0.0",
"http-errors": "^2.0.0",
"merge-descriptors": "^2.0.0",
"mime-types": "^3.0.0",
"on-finished": "^2.4.1",
"once": "^1.4.0",
"parseurl": "^1.3.3",
"proxy-addr": "^2.0.7",
"qs": "^6.14.0",
"range-parser": "^1.2.1",
"router": "^2.2.0",
"send": "^1.1.0",
"serve-static": "^2.2.0",
"statuses": "^2.0.1",
"type-is": "^2.0.1",
"vary": "^1.1.2"
},
"engines": {
"node": ">= 0.10.0"
"node": ">= 18"
},
"funding": {
"type": "opencollective",
@ -8166,75 +8156,85 @@
"serve-static": "^1.16.2"
}
},
"node_modules/express/node_modules/body-parser": {
"version": "1.20.4",
"license": "MIT",
"dependencies": {
"bytes": "~3.1.2",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "~1.2.0",
"http-errors": "~2.0.1",
"iconv-lite": "~0.4.24",
"on-finished": "~2.4.1",
"qs": "~6.14.0",
"raw-body": "~2.5.3",
"type-is": "~1.6.18",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/express/node_modules/debug": {
"version": "2.6.9",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/express/node_modules/iconv-lite": {
"version": "0.4.24",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/express/node_modules/ms": {
"node_modules/express/node_modules/fresh": {
"version": "2.0.0",
"license": "MIT"
},
"node_modules/express/node_modules/qs": {
"version": "6.14.2",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/express/node_modules/raw-body": {
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
"license": "MIT",
"dependencies": {
"bytes": "~3.1.2",
"http-errors": "~2.0.1",
"iconv-lite": "~0.4.24",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/express/node_modules/mime-db": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express/node_modules/mime-types": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
"integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
"license": "MIT",
"dependencies": {
"mime-db": "^1.54.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/express/node_modules/send": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
"integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
"license": "MIT",
"dependencies": {
"debug": "^4.4.3",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"fresh": "^2.0.0",
"http-errors": "^2.0.1",
"mime-types": "^3.0.2",
"ms": "^2.1.3",
"on-finished": "^2.4.1",
"range-parser": "^1.2.1",
"statuses": "^2.0.2"
},
"engines": {
"node": ">= 18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/express/node_modules/serve-static": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
"integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
"license": "MIT",
"dependencies": {
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"parseurl": "^1.3.3",
"send": "^1.2.0"
},
"engines": {
"node": ">= 18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/extend": {
"version": "3.0.2",
"license": "MIT"
@ -8414,32 +8414,26 @@
}
},
"node_modules/finalhandler": {
"version": "1.3.1",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
"integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"statuses": "2.0.1",
"unpipe": "~1.0.0"
"debug": "^4.4.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"on-finished": "^2.4.1",
"parseurl": "^1.3.3",
"statuses": "^2.0.1"
},
"engines": {
"node": ">= 0.8"
"node": ">= 18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/finalhandler/node_modules/debug": {
"version": "2.6.9",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/finalhandler/node_modules/ms": {
"version": "2.0.0",
"license": "MIT"
},
"node_modules/find-root": {
"version": "1.1.0",
"dev": true,
@ -9210,13 +9204,6 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/http-errors/node_modules/statuses": {
"version": "2.0.2",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/http-status-codes": {
"version": "2.3.0",
"license": "MIT"
@ -9538,6 +9525,12 @@
"node": ">=8"
}
},
"node_modules/is-promise": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
"license": "MIT"
},
"node_modules/is-stream": {
"version": "2.0.1",
"license": "MIT",
@ -10482,15 +10475,22 @@
}
},
"node_modules/media-typer": {
"version": "0.3.0",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
"integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
"node": ">= 0.8"
}
},
"node_modules/merge-descriptors": {
"version": "1.0.3",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
"integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
@ -10913,14 +10913,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/msw/node_modules/statuses": {
"version": "2.0.2",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/msw/node_modules/string-width": {
"version": "4.2.3",
"dev": true,
@ -11086,7 +11078,9 @@
"license": "MIT"
},
"node_modules/negotiator": {
"version": "0.6.3",
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
@ -11669,8 +11663,14 @@
}
},
"node_modules/path-to-regexp": {
"version": "0.1.13",
"license": "MIT"
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
"integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/path-type": {
"version": "4.0.0",
@ -12665,6 +12665,22 @@
"@datastructures-js/priority-queue": "^6.1.0"
}
},
"node_modules/router": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
"integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
"license": "MIT",
"dependencies": {
"debug": "^4.4.0",
"depd": "^2.0.0",
"is-promise": "^4.0.0",
"parseurl": "^1.3.3",
"path-to-regexp": "^8.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/rpc-websocket-client": {
"version": "1.1.4",
"license": "MIT",
@ -12869,13 +12885,6 @@
"version": "2.0.0",
"license": "MIT"
},
"node_modules/send/node_modules/statuses": {
"version": "2.0.2",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/serialize-error": {
"version": "13.0.1",
"license": "MIT",
@ -13204,7 +13213,9 @@
"license": "MIT"
},
"node_modules/statuses": {
"version": "2.0.1",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
@ -13989,16 +14000,44 @@
}
},
"node_modules/type-is": {
"version": "1.6.18",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
"license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
"content-type": "^1.0.5",
"media-typer": "^1.1.0",
"mime-types": "^3.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/type-is/node_modules/mime-db": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/type-is/node_modules/mime-types": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
"integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
"license": "MIT",
"dependencies": {
"mime-db": "^1.54.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/typed-emitter": {
"version": "1.4.0",
"license": "MIT"

View file

@ -52,7 +52,6 @@
"@atcute/identity-resolver-node": "^1.0.3",
"@atproto/api": "^0.18.0",
"@atproto/oauth-client-node": "^0.3.10",
"@awaitjs/express": "^0.6.3",
"@donedeal0/superdiff": "^1.1.1",
"@ewanc26/tid": "^1.0.2",
"@foxxmd/chromecast-client": "^1.0.4",
@ -67,7 +66,6 @@
"@lukehagar/plexjs": "^0.39.0",
"@supercharge/promise-pool": "^3.0.0",
"@svrooij/sonos": "^2.5.0",
"@types/express-serve-static-core": "^4.19.6",
"@xhayper/discord-rpc": "^1.3.0",
"abort-controller-x": "^0.5.0",
"address": "^1.2.2",
@ -87,7 +85,7 @@
"dbus-ts": "^0.0.7",
"discord.js": "^14.26.0",
"dotenv": "^10.0.0",
"express": "^4.22.1",
"express": "^5.2.1",
"express-session": "^1.19.0",
"fast-deep-equal": "^3.1.3",
"fixed-size-list": "^0.3.0",
@ -162,7 +160,8 @@
"@types/common-tags": "^1.8.1",
"@types/concat-stream": "^2.0.0",
"@types/cors": "^2.8.17",
"@types/express": "^4.17.13",
"@types/express": "^5.0.6",
"@types/express-serve-static-core": "^5.1.1",
"@types/express-session": "^1.18.2",
"@types/formidable": "^3.4.5",
"@types/jest": "^27.5.2",
@ -228,9 +227,6 @@
"overrides": {
"spotify-web-api-node": {
"superagent": "$superagent"
},
"@awaitjs/express": {
"@types/express": "*"
}
}
}

View file

@ -1,7 +1,7 @@
import { Logger } from '@foxxmd/logging';
import { Dayjs, ManipulateType } from "dayjs";
import { Request, Response } from "express";
import { NextFunction, ParamsDictionary, Query } from "express-serve-static-core";
import { type NextFunction, type ParamsDictionary, type Query } from "express-serve-static-core";
import { FixedSizeList } from 'fixed-size-list';
import { isPlayObject, PlayMetaLifecycleless, PlayObject, PlayObjectLifecycleless, UnixTimestamp } from "../../../core/Atomic.js";
import TupleMap from "../TupleMap.js";

View file

@ -229,7 +229,7 @@ export default abstract class AbstractScrobbleClient extends AbstractComponent i
if(preCompare.length > 0) {
let pcInits: number[] = [0],
pcMaxStagger: number[] = [];
for(const hook of this.transformRules.preCompare) {
for(const hook of preCompare) {
const t = this.transformManager.getTransformerByStage({type: hook.type, name: hook.name});
pcInits.push(t.staggerOpts?.initialInterval ?? 0);
pcMaxStagger.push(t.staggerOpts?.maxRandomStagger ?? 0)
@ -240,7 +240,7 @@ export default abstract class AbstractScrobbleClient extends AbstractComponent i
if(existing.length > 0) {
let eInits: number[] = [0],
eMaxStagger: number[] = [];
for(const hook of this.transformRules.postCompare) {
for(const hook of existing) {
const t = this.transformManager.getTransformerByStage({type: hook.type, name: hook.name});
eInits.push(t.staggerOpts?.initialInterval ?? 0);
eMaxStagger.push(t.staggerOpts?.maxRandomStagger ?? 0)

View file

@ -1,5 +1,5 @@
import { ExpressWithAsync } from "@awaitjs/express";
import { LogDataPretty, Logger, LogLevel } from "@foxxmd/logging";
import { Express } from 'express';
import bsseDef from 'better-sse';
import bodyParser from "body-parser";
import { FixedSizeList } from 'fixed-size-list';
@ -55,7 +55,7 @@ const getLogs = (minLevel: number, limit: number = maxBufferSize, sort: 'asc' |
return allLogs.flat(1).sort((a, b) => a.time - b.time).slice(0, limit);
}
export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream: PassThrough, initialLogOutput: LogDataPretty[] = [], scrobbleSources: ScrobbleSources, scrobbleClients: ScrobbleClients) => {
export const setupApi = (app: Express, logger: Logger, appLoggerStream: PassThrough, initialLogOutput: LogDataPretty[] = [], scrobbleSources: ScrobbleSources, scrobbleClients: ScrobbleClients) => {
for(const level of Object.keys(logger.levels.labels)) {
output[level] = new FixedSizeList<LeveledLogData>(maxBufferSize);
}
@ -155,17 +155,17 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
setupLastfmEndpointRoutes(app, logger, scrobbleSources);
setupAuthRoutes(app, logger, sourceRequiredMiddle, clientRequiredMiddle, scrobbleSources, scrobbleClients);
app.putAsync('/api/webscrobbler', bodyParser.json({type: ['text/*', 'application/json']}), async (req, res) => {
app.put('/api/webscrobbler', bodyParser.json({type: ['text/*', 'application/json']}), async (req, res) => {
logger.info(req.body);
res.sendStatus(200);
});
app.getAsync('/api/webscrobbler', bodyParser.json({type: ['text/*', 'application/json']}), async (req, res) => {
app.get('/api/webscrobbler', bodyParser.json({type: ['text/*', 'application/json']}), async (req, res) => {
logger.info(req.body);
res.sendStatus(200);
});
app.getAsync('/api/status', async (req, res, next) => {
app.get('/api/status', async (req, res, next) => {
const sourceData = scrobbleSources.sources.map((x) => {
const {
@ -257,7 +257,7 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
return res.json({sources: sourceData, clients: clientData});
});
app.getAsync('/api/recent', sourceMiddleFunc(false), async (req, res, next) => {
app.get('/api/recent', sourceMiddleFunc(false), async (req, res, next) => {
const {
// @ts-expect-error TS(2339): Property 'scrobbleSource' does not exist on type '... Remove this comment to see the full error message
scrobbleSource: source,
@ -285,7 +285,7 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
return res.json(result);
});
app.getAsync('/api/source/art', sourceMiddleFunc(false), async (req, res, next) => {
app.get('/api/source/art', sourceMiddleFunc(false), async (req, res, next) => {
const {
// @ts-expect-error TS(2339): Property 'scrobbleSource' does not exist on type '... Remove this comment to see the full error message
scrobbleSource,
@ -313,7 +313,7 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
}
});
app.getAsync('/api/dead', clientMiddleFunc(true), async (req, res, next) => {
app.get('/api/dead', clientMiddleFunc(true), async (req, res, next) => {
const {
// @ts-expect-error TS(2339): Property 'scrobbleSource' does not exist on type '... Remove this comment to see the full error message
scrobbleClient: client,
@ -324,7 +324,7 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
return res.json(result);
});
app.putAsync('/api/dead', clientMiddleFunc(true), async (req, res, next) => {
app.put('/api/dead', clientMiddleFunc(true), async (req, res, next) => {
const {
// @ts-expect-error TS(2339): Property 'scrobbleSource' does not exist on type '... Remove this comment to see the full error message
scrobbleClient: client,
@ -337,7 +337,7 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
await ((client as AbstractScrobbleClient).processDeadLetterQueue(1000));
});
app.putAsync('/api/dead/:id', clientMiddleFunc(true), async (req, res, next) => {
app.put('/api/dead/:id', clientMiddleFunc(true), async (req, res, next) => {
const {
// @ts-expect-error TS(2339): Property 'scrobbleSource' does not exist on type '... Remove this comment to see the full error message
scrobbleClient: client,
@ -366,7 +366,7 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
return res.json(dead);
});
app.deleteAsync('/api/dead', clientMiddleFunc(true), async (req, res, next) => {
app.delete('/api/dead', clientMiddleFunc(true), async (req, res, next) => {
const {
// @ts-expect-error TS(2339): Property 'scrobbleSource' does not exist on type '... Remove this comment to see the full error message
scrobbleClient: client,
@ -379,7 +379,7 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
return res.json([]);
});
app.deleteAsync('/api/dead/:id', clientMiddleFunc(true), async (req, res, next) => {
app.delete('/api/dead/:id', clientMiddleFunc(true), async (req, res, next) => {
const {
// @ts-expect-error TS(2339): Property 'scrobbleSource' does not exist on type '... Remove this comment to see the full error message
scrobbleClient: client,
@ -403,7 +403,7 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
return res.status(200).send();
});
app.getAsync('/api/scrobbled', clientMiddleFunc(false), async (req, res, next) => {
app.get('/api/scrobbled', clientMiddleFunc(false), async (req, res, next) => {
const {
// @ts-expect-error scrobbleClient not part of req
scrobbleClient: client,
@ -418,7 +418,7 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
});
app.use('/api/source/init', sourceRequiredMiddle);
app.postAsync('/api/source/init', async (req, res) => {
app.post('/api/source/init', async (req, res) => {
// @ts-expect-error TS(2339): Property 'scrobbleSource' does not exist on type '... Remove this comment to see the full error message
const source = req.scrobbleSource as AbstractSource;
@ -446,7 +446,7 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
});
app.use('/api/source/listen', sourceRequiredMiddle);
app.postAsync('/api/source/listen', async (req, res) => {
app.post('/api/source/listen', async (req, res) => {
// @ts-expect-error TS(2339): Property 'scrobbleSource' does not exist on type '... Remove this comment to see the full error message
const source = req.scrobbleSource as AbstractSource;
@ -474,7 +474,7 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
});
app.use('/api/client/init', clientRequiredMiddle);
app.postAsync('/api/client/init', async (req, res) => {
app.post('/api/client/init', async (req, res) => {
// @ts-expect-error TS(2339): Property 'scrobbleSource' does not exist on type '... Remove this comment to see the full error message
const client = req.scrobbleClient as AbstractScrobbleClient;
@ -498,8 +498,8 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
res.status(200).send('OK');
});
app.getAsync('/health', async (req, res) => res.redirect(307, `/api/${req.url.slice(1)}`));
app.getAsync('/api/health', async (req, res) => {
app.get('/health', async (req, res) => res.redirect(307, `/api/${req.url.slice(1)}`));
app.get('/api/health', async (req, res) => {
const {
type,
name
@ -549,7 +549,7 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
prom.collectDefaultMetrics();
}
app.getAsync('/api/metrics', async (req, res) => {
app.get('/api/metrics', async (req, res) => {
const metricsString = await prom.register.metrics();
return res
@ -559,11 +559,11 @@ export const setupApi = (app: ExpressWithAsync, logger: Logger, appLoggerStream:
});
app.getAsync('/api/version', async (req, res) => {
app.get('/api/version', async (req, res) => {
return res.json({version: root.get('version')});
});
app.useAsync('/api/*', async (req, res) => {
app.use('/api/*path', async (req, res) => {
const remote = req.connection.remoteAddress;
const proxyRemote = req.headers["x-forwarded-for"];
const ua = req.headers["user-agent"];

View file

@ -1,4 +1,4 @@
import { ExpressWithAsync } from "@awaitjs/express";
import { Express } from 'express';
import { Logger } from "@foxxmd/logging";
import passport from "passport";
import { ExpressHandler } from "../common/infrastructure/Atomic.js";
@ -18,9 +18,9 @@ import LibrefmSource from "../sources/LibrefmSource.js";
import e from "express";
import AbstractSource from "../sources/AbstractSource.js";
export const setupAuthRoutes = (app: ExpressWithAsync, logger: Logger, sourceMiddle: ExpressHandler, clientMiddle: ExpressHandler, scrobbleSources: ScrobbleSources, scrobbleClients: ScrobbleClients) => {
export const setupAuthRoutes = (app: Express, logger: Logger, sourceMiddle: ExpressHandler, clientMiddle: ExpressHandler, scrobbleSources: ScrobbleSources, scrobbleClients: ScrobbleClients) => {
app.use('/api/client/auth', clientMiddle);
app.getAsync('/api/client/auth', async (req, res) => {
app.get('/api/client/auth', async (req, res) => {
const {
scrobbleClient,
} = req as any;
@ -40,7 +40,7 @@ export const setupAuthRoutes = (app: ExpressWithAsync, logger: Logger, sourceMid
});
app.use('/api/source/auth', sourceMiddle);
app.getAsync('/api/source/auth', async (req, res, next) => {
app.get('/api/source/auth', async (req, res, next) => {
const {
// @ts-expect-error TS(2339): Property 'scrobbleSource' does not exist on type '... Remove this comment to see the full error message
scrobbleSource: source,
@ -74,7 +74,7 @@ export const setupAuthRoutes = (app: ExpressWithAsync, logger: Logger, sourceMid
}
});
app.getAsync(/.*callback$/, async (req, res, next) => {
app.get(/.*callback$/, async (req, res, next) => {
if(req.url.indexOf('/api') !== 0) {
return res.redirect(307, `/api${req.url}`);
}
@ -155,7 +155,7 @@ export const setupAuthRoutes = (app: ExpressWithAsync, logger: Logger, sourceMid
}
});
app.getAsync(/(\/api\/tealfm\/.*)/, async function (req, res) {
app.get(/(\/api\/tealfm\/.*)/, async function (req, res) {
const clients = scrobbleClients.getByType('tealfm') as TealScrobbler[];
if (clients.length === 0) {

View file

@ -1,11 +1,11 @@
import { ExpressWithAsync } from "@awaitjs/express";
import { Express } from 'express';
import { Logger } from "@foxxmd/logging";
import passport from "passport";
import DeezerSource from "../sources/DeezerSource.js";
import ScrobbleSources from "../sources/ScrobbleSources.js";
import { sleep } from "../utils.js";
export const setupDeezerRoutes = (app: ExpressWithAsync, logger: Logger, scrobbleSources: ScrobbleSources) => {
export const setupDeezerRoutes = (app: Express, logger: Logger, scrobbleSources: ScrobbleSources) => {
// initialize deezer strategies
// const deezerSources = scrobbleSources.getByType('deezer') as DeezerSource[];
@ -15,7 +15,7 @@ export const setupDeezerRoutes = (app: ExpressWithAsync, logger: Logger, scrobbl
// something about the deezer passport strategy makes express continue with the response even though it should wait for accesstoken callback and userprofile fetching
// so to get around this add an additional middleware that loops/sleeps until we should have fetched everything ¯\_(ツ)_/¯
app.getAsync(/.*deezer\/callback*$/, (req, res, next) => {
app.get(/.*deezer\/callback*$/, (req, res, next) => {
if(req.url.indexOf('/api') !== 0) {
return res.redirect(307, `/api${req.url}`);
}

View file

@ -1,5 +1,5 @@
/* eslint-disable prefer-arrow-functions/prefer-arrow-functions */
import { ExpressWithAsync } from "@awaitjs/express";
import { Express } from 'express';
import { childLogger, Logger } from "@foxxmd/logging";
import bodyParser from "body-parser";
import ScrobbleSources from "../sources/ScrobbleSources.js";
@ -8,14 +8,14 @@ import { LFMEndpointNotifier } from "../sources/ingressNotifiers/LFMEndpointNoti
import { EndpointLastfmSource, playStateFromRequest, parseDisplayIdentifiersFromRequest } from "../sources/EndpointLastfmSource.js";
import { LastFMScrobbleRequestPayload } from "../common/vendor/LastfmApiClient.js";
export const setupLastfmEndpointRoutes = (app: ExpressWithAsync, parentLogger: Logger, scrobbleSources: ScrobbleSources) => {
export const setupLastfmEndpointRoutes = (app: Express, parentLogger: Logger, scrobbleSources: ScrobbleSources) => {
const logger = childLogger(parentLogger, ['Ingress', 'LFM']);
const nonEmptyCheck = nonEmptyBody(logger, 'LFM Endpoint');
const webhookIngress = new LFMEndpointNotifier(logger);
app.useAsync(/(\/api\/lastfm(?!\/callback))|(\/2.0\/?)$/,
app.use(/(\/api\/lastfm(?!\/callback))|(\/2.0\/?)$/,
async function (req, res, next) {
// track request before parsing body to ensure we at least log that something is happening
// (in the event body parsing does not work or request is not POST/PATCH)

View file

@ -1,5 +1,5 @@
/* eslint-disable prefer-arrow-functions/prefer-arrow-functions */
import { ExpressWithAsync } from "@awaitjs/express";
import { Express } from 'express';
import { childLogger, Logger } from "@foxxmd/logging";
import bodyParser from "body-parser";
import { EndpointListenbrainzSource, playStateFromRequest, parseDisplayIdentifiersFromRequest } from "../sources/EndpointListenbrainzSource.js";
@ -10,7 +10,7 @@ import { isDebugMode } from "../utils.js";
const TEXT_WILDCARD_REGEX = new RegExp(/text\/.+/);
export const setupLZEndpointRoutes = (app: ExpressWithAsync, parentLogger: Logger, scrobbleSources: ScrobbleSources) => {
export const setupLZEndpointRoutes = (app: Express, parentLogger: Logger, scrobbleSources: ScrobbleSources) => {
const logger = childLogger(parentLogger, ['Ingress', 'Listenbrainz']);
@ -30,7 +30,7 @@ export const setupLZEndpointRoutes = (app: ExpressWithAsync, parentLogger: Logge
const nonEmptyCheck = nonEmptyBody(logger, 'LZ Endpoint');
const webhookIngress = new LZEndpointNotifier(logger);
app.useAsync(/(\/api\/listenbrainz.*)|(\/1\/submit-listens\/?$)/,
app.use(/(\/api\/listenbrainz.*)|(\/1\/submit-listens\/?$)/,
async function (req, res, next) {
// track request before parsing body to ensure we at least log that something is happening
// (in the event body parsing does not work or request is not POST/PATCH)
@ -67,7 +67,7 @@ export const setupLZEndpointRoutes = (app: ExpressWithAsync, parentLogger: Logge
await source.handle(playerState);
}
});
app.getAsync('/1/validate-token', async function (req, res) {
app.get('/1/validate-token', async function (req, res) {
//https://listenbrainz.readthedocs.io/en/latest/users/api/core.html#get--1-validate-token
logger.info('Validated token');
return res.status(200).json({
@ -77,7 +77,7 @@ export const setupLZEndpointRoutes = (app: ExpressWithAsync, parentLogger: Logge
user_name: "Multi-Scrobbler"
})
});
app.useAsync(/\/1\/.*/, async function (req, res) {
app.use(/\/1\/.*/, async function (req, res) {
logger.warn(`Received what looks like a Listenbrainz Endpoint request but it was to an invalid URL route: ${req.originalUrl}\nMake sure base URL path to MS endpoint is correct.`);
res.status(404);
});

View file

@ -1,8 +1,7 @@
import { addAsync, Router } from '@awaitjs/express';
import express, { Router } from 'express';
import { childLogger, LogDataPretty, Logger } from "@foxxmd/logging";
import bodyParser from 'body-parser';
import { stripIndents } from "common-tags";
import express from 'express';
import session from 'express-session';
import { PassThrough } from "node:stream";
import passport from 'passport';
@ -16,7 +15,7 @@ import { setupApi } from "./api.js";
import ScrobbleSources from '../sources/ScrobbleSources.js';
import ScrobbleClients from '../scrobblers/ScrobbleClients.js';
const app = addAsync(express());
const app = express();
const router = Router();
export const initServer = async (parentLogger: Logger, appLoggerStream: PassThrough, initialOutput: LogDataPretty[] = [], sources: ScrobbleSources, clients: ScrobbleClients) => {

View file

@ -1,4 +1,4 @@
import { ExpressWithAsync } from "@awaitjs/express";
import { Express } from 'express';
import { childLogger, Logger } from "@foxxmd/logging";
import bodyParser from "body-parser";
import cors from 'cors';
@ -12,7 +12,7 @@ const corsOpts: cors.CorsOptions = {
methods: ['POST']
}
export const setupWebscrobblerRoutes = (app: ExpressWithAsync, parentLogger: Logger, scrobbleSources: ScrobbleSources) => {
export const setupWebscrobblerRoutes = (app: Express, parentLogger: Logger, scrobbleSources: ScrobbleSources) => {
const logger = childLogger(parentLogger, ['Ingress', 'WebScrobbler']);
@ -25,13 +25,13 @@ export const setupWebscrobblerRoutes = (app: ExpressWithAsync, parentLogger: Log
// }
});
const webhookIngress = new WebhookNotifier(logger);
app.options('/api/webscrobbler*', async (req, res, next) => {
app.options('/api/webscrobbler*path', async (req, res, next) => {
webhookIngress.trackIngress(req, true);
next();
},
cors(corsOpts));
app.postAsync('/api/webscrobbler*',
app.post('/api/webscrobbler*path',
async (req, res, next) => {
webhookIngress.trackIngress(req, true);
next();