diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index a323f1f1..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,20 +0,0 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file - -version: 2 -updates: - # Enable version updates for npm - - package-ecosystem: "npm" - # Look for `package.json` and `lock` files in the `root` directory - directory: "/" - # Check the npm registry for updates every day (weekdays) - schedule: - interval: "daily" - - package-ecosystem: "github-actions" - # Workflow files stored in the default location of `.github/workflows` - # You don't need to specify `/.github/workflows` for `directory`. You can use `directory: "/"`. - directory: "/" - schedule: - interval: "weekly" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d311ac02..1aca6866 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v6 with: - node-version: "20" + node-version: "24" - name: Install dependencies run: npm ci diff --git a/apps/juxtaposition-ui/package.json b/apps/juxtaposition-ui/package.json index 620fea18..6df13b89 100644 --- a/apps/juxtaposition-ui/package.json +++ b/apps/juxtaposition-ui/package.json @@ -25,12 +25,10 @@ "connect-redis": "^9.0.0", "cookie-parser": "^1.4.7", "crc": "^4.3.2", - "express": "^4.22.1", - "express-async-errors": "^3.1.1", + "express": "^5.2.1", "express-prom-bundle": "^7.0.2", "express-rate-limit": "^8.2.1", "express-session": "^1.19.0", - "express-subdomain": "^1.0.6", "hashmap": "^2.4.0", "i18next": "^25.8.13", "luxon": "^3.7.2", @@ -67,7 +65,7 @@ "@types/hashmap": "^2.3.4", "@types/luxon": "^3.7.1", "@types/method-override": "^3.0.0", - "@types/node": "^22.19.15", + "@types/node": "^24.12.0", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "browserslist": "^4.28.1", @@ -82,4 +80,4 @@ "tsup": "^8.5.1", "typescript": "^5.9.3" } -} +} \ No newline at end of file diff --git a/apps/juxtaposition-ui/src/config.ts b/apps/juxtaposition-ui/src/config.ts index bdfbaedf..2125a45a 100644 --- a/apps/juxtaposition-ui/src/config.ts +++ b/apps/juxtaposition-ui/src/config.ts @@ -69,6 +69,11 @@ const schema = z.object({ host: z.string(), port: z.coerce.number().default(6379) }), + domains: z.object({ + web: z.hostname().default('juxt.pretendo.network'), + ctr: z.hostname().default('ctr.olv.pretendo.cc'), + portal: z.hostname().default('portal.olv.pretendo.cc') + }).prefault({}), dmBanner: z.object({ text: z.string().optional(), // Add `content` to insert the url url: z.url().optional(), diff --git a/apps/juxtaposition-ui/src/middleware/hostLimit.ts b/apps/juxtaposition-ui/src/middleware/hostLimit.ts new file mode 100644 index 00000000..604f0be6 --- /dev/null +++ b/apps/juxtaposition-ui/src/middleware/hostLimit.ts @@ -0,0 +1,14 @@ +import type express from 'express'; + +export function restrictHostnames( + allowedHostnames: string[], + fn: TFn +): (request: express.Request, response: express.Response, next: () => void) => void | TFn { + return (request: express.Request, response: express.Response, next: () => void) => { + if (allowedHostnames.includes(request.hostname)) { + return fn(request, response, next); + } + + return next(); + }; +} diff --git a/apps/juxtaposition-ui/src/server.ts b/apps/juxtaposition-ui/src/server.ts index 921f5d40..f47029fe 100644 --- a/apps/juxtaposition-ui/src/server.ts +++ b/apps/juxtaposition-ui/src/server.ts @@ -2,7 +2,6 @@ import express from 'express'; import cookieParser from 'cookie-parser'; import session from 'express-session'; import { RedisStore } from 'connect-redis'; -import 'express-async-errors'; // See package docs import methodOverride from 'method-override'; import { database } from '@/database'; import { logger } from '@/logger'; diff --git a/apps/juxtaposition-ui/src/services/juxt-web/index.ts b/apps/juxtaposition-ui/src/services/juxt-web/index.ts index 634da1f0..236e8aeb 100644 --- a/apps/juxtaposition-ui/src/services/juxt-web/index.ts +++ b/apps/juxtaposition-ui/src/services/juxt-web/index.ts @@ -1,12 +1,12 @@ import express from 'express'; -import subdomain from 'express-subdomain'; import { webAuth } from '@/middleware/webAuth'; import { consoleAuth } from '@/middleware/consoleAuth'; import { checkBan } from '@/middleware/checkBan'; import { detectVersion } from '@/middleware/detectVersion'; import { checkDiscovery } from '@/middleware/discovery'; -import { logger } from '@/logger'; import { routes } from '@/services/juxt-web/routes'; +import { restrictHostnames } from '@/middleware/hostLimit'; +import { config } from '@/config'; export const router = express.Router(); const consoleRouter = express.Router(); @@ -20,20 +20,8 @@ router.use(routes.ENTRYPOINT); router.use(checkDiscovery); // Create subdomains -logger.info('[JUXT-WEB] Creating \'Web\' subdomain'); -router.use(subdomain('juxt', webRouter)); -router.use(subdomain('juxt-beta', webRouter)); -router.use(subdomain('juxt-dev', webRouter)); - -logger.info('[JUXT-WEB] Creating \'Wii U\' subdomain'); -router.use(subdomain('portal.olv', consoleRouter)); -router.use(subdomain('portal-beta.olv', consoleRouter)); -router.use(subdomain('portal-dev.olv', consoleRouter)); - -logger.info('[JUXT-WEB] Creating \'3DS\' subdomain'); -router.use(subdomain('ctr.olv', consoleRouter)); -router.use(subdomain('ctr-beta.olv', consoleRouter)); -router.use(subdomain('ctr-dev.olv', consoleRouter)); +router.use(restrictHostnames([config.domains.web], webRouter)); +router.use(restrictHostnames([config.domains.portal, config.domains.ctr], consoleRouter)); // Setup routes for console consoleRouter.use(consoleAuth); diff --git a/apps/miiverse-api/package.json b/apps/miiverse-api/package.json index 4f4b9b52..fc68d644 100644 --- a/apps/miiverse-api/package.json +++ b/apps/miiverse-api/package.json @@ -21,11 +21,9 @@ "@repo/grpc-client": "^0.0.0", "colors": "^1.4.0", "crc": "^4.3.2", - "express": "^4.22.1", - "express-async-errors": "^3.1.1", + "express": "^5.2.1", "express-prom-bundle": "^7.0.2", "express-rate-limit": "^8.2.1", - "express-subdomain": "^1.0.6", "moment": "^2.24.0", "mongoose": "^8.23.0", "multer": "^2.1.1", diff --git a/apps/miiverse-api/src/config.ts b/apps/miiverse-api/src/config.ts index 4984df73..fd7a3aa2 100644 --- a/apps/miiverse-api/src/config.ts +++ b/apps/miiverse-api/src/config.ts @@ -52,7 +52,11 @@ const schema = z.object({ port: z.coerce.number().default(8125), apiKey: z.string() }) - }) + }), + domains: z.object({ + api: z.hostname().default('api.olv.pretendo.cc'), + discovery: z.hostname().default('discovery.olv.pretendo.cc') + }).prefault({}) }); export const presets: Record = { diff --git a/apps/miiverse-api/src/middleware/hostLimit.ts b/apps/miiverse-api/src/middleware/hostLimit.ts new file mode 100644 index 00000000..604f0be6 --- /dev/null +++ b/apps/miiverse-api/src/middleware/hostLimit.ts @@ -0,0 +1,14 @@ +import type express from 'express'; + +export function restrictHostnames( + allowedHostnames: string[], + fn: TFn +): (request: express.Request, response: express.Response, next: () => void) => void | TFn { + return (request: express.Request, response: express.Response, next: () => void) => { + if (allowedHostnames.includes(request.hostname)) { + return fn(request, response, next); + } + + return next(); + }; +} diff --git a/apps/miiverse-api/src/server.ts b/apps/miiverse-api/src/server.ts index f9c64e20..e7783a7c 100644 --- a/apps/miiverse-api/src/server.ts +++ b/apps/miiverse-api/src/server.ts @@ -1,5 +1,4 @@ import express from 'express'; -import 'express-async-errors'; // See package docs import expressMetrics from 'express-prom-bundle'; import { connect as connectDatabase } from '@/database'; import { logger } from '@/logger'; diff --git a/apps/miiverse-api/src/services/api/index.ts b/apps/miiverse-api/src/services/api/index.ts index da0ada28..3905bf4a 100644 --- a/apps/miiverse-api/src/services/api/index.ts +++ b/apps/miiverse-api/src/services/api/index.ts @@ -1,7 +1,5 @@ import express from 'express'; -import subdomain from 'express-subdomain'; import { rateLimit } from 'express-rate-limit'; -import { LOG_INFO } from '@/logger'; import postsHandlers from '@/services/api/routes/posts'; import friendMessagesHandlers from '@/services/api/routes/friend_messages'; import communitiesHandlers from '@/services/api/routes/communities'; @@ -9,6 +7,8 @@ import peopleHandlers from '@/services/api/routes/people'; import topicsHandlers from '@/services/api/routes/topics'; import usersHandlers from '@/services/api/routes/users'; import statusHandlers from '@/services/api/routes/status'; +import { restrictHostnames } from '@/middleware/hostLimit'; +import { config } from '@/config'; // Main router for endpointsindex.js const router = express.Router(); @@ -25,11 +25,7 @@ const limiter = rateLimit({ }); router.use(limiter); -// Create subdomains -LOG_INFO('[MIIVERSE] Creating \'api\' subdomain'); -router.use(subdomain('api.olv', api)); -router.use(subdomain('api-test.olv', api)); -router.use(subdomain('api-dev.olv', api)); +router.use(restrictHostnames([config.domains.api], api)); // Setup routes api.use('/v1/posts', postsHandlers); diff --git a/apps/miiverse-api/src/services/discovery/index.ts b/apps/miiverse-api/src/services/discovery/index.ts index c9af7471..f5db02d9 100644 --- a/apps/miiverse-api/src/services/discovery/index.ts +++ b/apps/miiverse-api/src/services/discovery/index.ts @@ -1,7 +1,7 @@ import express from 'express'; -import subdomain from 'express-subdomain'; -import { LOG_INFO } from '@/logger'; import discoveryHandlers from '@/services/discovery/routes/discovery'; +import { restrictHostnames } from '@/middleware/hostLimit'; +import { config } from '@/config'; // Main router for endpointsindex.js const router = express.Router(); @@ -10,10 +10,7 @@ const router = express.Router(); const discovery = express.Router(); // Create subdomains -LOG_INFO('[MIIVERSE] Creating \'discovery\' subdomain'); -router.use(subdomain('discovery.olv', discovery)); -router.use(subdomain('discovery-test.olv', discovery)); -router.use(subdomain('discovery-dev.olv', discovery)); +router.use(restrictHostnames([config.domains.discovery], discovery)); // Setup routes discovery.use('/v1/endpoint', discoveryHandlers); diff --git a/apps/miiverse-api/src/types/express-subdomain.d.ts b/apps/miiverse-api/src/types/express-subdomain.d.ts deleted file mode 100644 index 3604bfca..00000000 --- a/apps/miiverse-api/src/types/express-subdomain.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -// * Credit to https://github.com/bmullan91/express-subdomain/pull/61 for the types! - -declare module 'express-subdomain' { - import type { Request, Response, Router } from 'express'; - - /** - * @description The subdomain function. - * @param subdomain The subdomain to listen on. - * @param fn The listener function, takes a response and request. - * @returns A function call to the value passed as FN, or void (the next function). - */ - export default function subdomain( - subdomain: string, - fn: Router - ): (req: Request, res: Response, next: () => void) => void | typeof fn; -} diff --git a/juxtaposition-ui.Dockerfile b/juxtaposition-ui.Dockerfile index 7a9eebb9..763b64d7 100644 --- a/juxtaposition-ui.Dockerfile +++ b/juxtaposition-ui.Dockerfile @@ -2,7 +2,7 @@ ARG app_dir="/home/node/app" -FROM node:22-alpine +FROM node:24-alpine ARG app_dir WORKDIR ${app_dir} diff --git a/miiverse-api.Dockerfile b/miiverse-api.Dockerfile index b119a0d5..3574bc17 100644 --- a/miiverse-api.Dockerfile +++ b/miiverse-api.Dockerfile @@ -2,7 +2,7 @@ ARG app_dir="/home/node/app" -FROM node:22-alpine +FROM node:24-alpine ARG app_dir WORKDIR ${app_dir} diff --git a/package-lock.json b/package-lock.json index c7020171..e0daec83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,12 +25,10 @@ "connect-redis": "^9.0.0", "cookie-parser": "^1.4.7", "crc": "^4.3.2", - "express": "^4.22.1", - "express-async-errors": "^3.1.1", + "express": "^5.2.1", "express-prom-bundle": "^7.0.2", "express-rate-limit": "^8.2.1", "express-session": "^1.19.0", - "express-subdomain": "^1.0.6", "hashmap": "^2.4.0", "i18next": "^25.8.13", "luxon": "^3.7.2", @@ -67,7 +65,7 @@ "@types/hashmap": "^2.3.4", "@types/luxon": "^3.7.1", "@types/method-override": "^3.0.0", - "@types/node": "^22.19.15", + "@types/node": "^24.12.0", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "browserslist": "^4.28.1", @@ -83,6 +81,309 @@ "typescript": "^5.9.3" } }, + "apps/juxtaposition-ui/node_modules/@types/node": { + "version": "24.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz", + "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "apps/juxtaposition-ui/node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "apps/juxtaposition-ui/node_modules/body-parser": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "apps/juxtaposition-ui/node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "apps/juxtaposition-ui/node_modules/cookie-signature": { + "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" + } + }, + "apps/juxtaposition-ui/node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "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": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "apps/juxtaposition-ui/node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "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": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "apps/juxtaposition-ui/node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "apps/juxtaposition-ui/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "apps/juxtaposition-ui/node_modules/media-typer": { + "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.8" + } + }, + "apps/juxtaposition-ui/node_modules/merge-descriptors": { + "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" + } + }, + "apps/juxtaposition-ui/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" + } + }, + "apps/juxtaposition-ui/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" + } + }, + "apps/juxtaposition-ui/node_modules/negotiator": { + "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" + } + }, + "apps/juxtaposition-ui/node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "apps/juxtaposition-ui/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" + } + }, + "apps/juxtaposition-ui/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" + } + }, + "apps/juxtaposition-ui/node_modules/statuses": { + "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" + } + }, + "apps/juxtaposition-ui/node_modules/type-is": { + "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": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "apps/juxtaposition-ui/node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, "apps/miiverse-api": { "version": "3.0.0", "license": "AGPL-3.0-only", @@ -94,11 +395,9 @@ "@repo/grpc-client": "^0.0.0", "colors": "^1.4.0", "crc": "^4.3.2", - "express": "^4.22.1", - "express-async-errors": "^3.1.1", + "express": "^5.2.1", "express-prom-bundle": "^7.0.2", "express-rate-limit": "^8.2.1", - "express-subdomain": "^1.0.6", "moment": "^2.24.0", "mongoose": "^8.23.0", "multer": "^2.1.1", @@ -133,6 +432,292 @@ "xmlbuilder2": "^4.0.3" } }, + "apps/miiverse-api/node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "apps/miiverse-api/node_modules/body-parser": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "apps/miiverse-api/node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "apps/miiverse-api/node_modules/cookie-signature": { + "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" + } + }, + "apps/miiverse-api/node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "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": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "apps/miiverse-api/node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "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": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "apps/miiverse-api/node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "apps/miiverse-api/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "apps/miiverse-api/node_modules/media-typer": { + "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.8" + } + }, + "apps/miiverse-api/node_modules/merge-descriptors": { + "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" + } + }, + "apps/miiverse-api/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" + } + }, + "apps/miiverse-api/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" + } + }, + "apps/miiverse-api/node_modules/negotiator": { + "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" + } + }, + "apps/miiverse-api/node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "apps/miiverse-api/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" + } + }, + "apps/miiverse-api/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" + } + }, + "apps/miiverse-api/node_modules/statuses": { + "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" + } + }, + "apps/miiverse-api/node_modules/type-is": { + "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": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/@aws-crypto/crc32": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", @@ -2357,6 +2942,7 @@ "resolved": "https://registry.npmjs.org/@redis/client/-/client-5.11.0.tgz", "integrity": "sha512-GHoprlNQD51Xq2Ztd94HHV94MdFZQ3CVrpA04Fz8MVoHM0B7SlbmPEVIjwTbcv58z8QyjnrOuikS0rWF03k5dQ==", "license": "MIT", + "peer": true, "dependencies": { "cluster-key-slot": "1.1.2" }, @@ -3533,6 +4119,7 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "peer": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -3693,6 +4280,7 @@ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -3836,6 +4424,7 @@ "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", @@ -4326,6 +4915,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4883,6 +5473,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -5971,6 +6562,7 @@ "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -6090,6 +6682,7 @@ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -6258,6 +6851,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -6588,15 +7182,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/express-async-errors": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz", - "integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==", - "license": "ISC", - "peerDependencies": { - "express": "^4.16.2" - } - }, "node_modules/express-prom-bundle": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/express-prom-bundle/-/express-prom-bundle-7.0.2.tgz", @@ -6637,6 +7222,7 @@ "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.19.0.tgz", "integrity": "sha512-0csaMkGq+vaiZTmSMMGkfdCOabYv192VbytFypcvI0MANrp+4i/7yEkJ0sbAEhycQjntaKGzYfjfXQyVb7BHMA==", "license": "MIT", + "peer": true, "dependencies": { "cookie": "~0.7.2", "cookie-signature": "~1.0.7", @@ -6673,11 +7259,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/express-subdomain": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/express-subdomain/-/express-subdomain-1.0.6.tgz", - "integrity": "sha512-A51MvQhk5L3aDV4s5XcKrn5I0bCFOk95xikJjlDWNUrtiAaCjy44RjvBz4uLRH0nCvt8Y3SKt1EvxUUmGJ5QRQ==" - }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -7562,6 +8143,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.4" }, @@ -7950,6 +8532,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -10695,6 +11283,7 @@ "version": "15.1.3", "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-15.1.3.tgz", "integrity": "sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g==", + "peer": true, "dependencies": { "@opentelemetry/api": "^1.4.0", "tdigest": "^0.1.1" @@ -10874,6 +11463,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -11003,6 +11593,7 @@ "resolved": "https://registry.npmjs.org/redis/-/redis-5.11.0.tgz", "integrity": "sha512-YwXjATVDT+AuxcyfOwZn046aml9jMlQPvU1VXIlLDVAExe0u93aTfPYSeRgG4p9Q/Jlkj+LXJ1XEoFV+j2JKcQ==", "license": "MIT", + "peer": true, "dependencies": { "@redis/bloom": "5.11.0", "@redis/client": "5.11.0", @@ -11191,6 +11782,32 @@ "fsevents": "~2.3.2" } }, + "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/router/node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -11660,6 +12277,7 @@ "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" @@ -12756,6 +13374,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -12884,6 +13503,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" },