From 71c0f43d961fadad1d726bda3de78fce17fe884d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Dec 2025 16:35:59 +0100 Subject: [PATCH 1/4] build(deps): bump nodemailer from 7.0.7 to 7.0.11 in /backend (#7176) Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 7.0.7 to 7.0.11.
Release notes

Sourced from nodemailer's releases.

v7.0.11

7.0.11 (2025-11-26)

Bug Fixes

v7.0.10

7.0.10 (2025-10-23)

Bug Fixes

v7.0.9

7.0.9 (2025-10-07)

Bug Fixes

v7.0.8

7.0.8 (2025-10-07)

Bug Fixes

Changelog

Sourced from nodemailer's changelog.

7.0.11 (2025-11-26)

Bug Fixes

7.0.10 (2025-10-23)

Bug Fixes

7.0.9 (2025-10-07)

Bug Fixes

7.0.8 (2025-10-07)

Bug Fixes

Commits
Maintainer changes

This version was pushed to npm by [GitHub Actions](https://www.npmjs.com/~GitHub Actions), a new releaser for nodemailer since your current version.


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=nodemailer&package-manager=npm_and_yarn&previous-version=7.0.7&new-version=7.0.11)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/monkeytypegame/monkeytype/network/alerts).
--------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Miodec --- backend/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/package.json b/backend/package.json index e240efe17dca..563b5741e76b 100644 --- a/backend/package.json +++ b/backend/package.json @@ -49,7 +49,7 @@ "mjml": "4.15.0", "mongodb": "6.3.0", "mustache": "4.2.0", - "nodemailer": "7.0.7", + "nodemailer": "7.0.11", "object-hash": "3.0.0", "prom-client": "15.1.3", "rate-limiter-flexible": "5.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 31219991556c..c74ab323e20c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -129,8 +129,8 @@ importers: specifier: 4.2.0 version: 4.2.0 nodemailer: - specifier: 7.0.7 - version: 7.0.7 + specifier: 7.0.11 + version: 7.0.11 object-hash: specifier: 3.0.0 version: 3.0.0 @@ -7293,8 +7293,8 @@ packages: resolution: {integrity: sha512-1uiY543L+N7Og4yswvlm5NCKgPKDEXd9AUR9Jh3gen6oOeBsesr6LqhXom1er3eRzSUcVRWXzhv8tSNrIfGHKw==} engines: {node: '>=18'} - nodemailer@7.0.7: - resolution: {integrity: sha512-jGOaRznodf62TVzdyhKt/f1Q/c3kYynk8629sgJHpRzGZj01ezbgMMWJSAjHADcwTKxco3B68/R+KHJY2T5BaA==} + nodemailer@7.0.11: + resolution: {integrity: sha512-gnXhNRE0FNhD7wPSCGhdNh46Hs6nm+uTyg+Kq0cZukNQiYdnCsoQjodNP9BQVG9XrcK/v6/MgpAPBUFyzh9pvw==} engines: {node: '>=6.0.0'} nodemon@3.1.4: @@ -17710,7 +17710,7 @@ snapshots: dependencies: '@babel/parser': 7.28.5 - nodemailer@7.0.7: {} + nodemailer@7.0.11: {} nodemon@3.1.4: dependencies: From 54e660da6b22103399e31665074795ca231cee87 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Wed, 3 Dec 2025 17:42:18 +0200 Subject: [PATCH 2/4] impr(quote search modal): add custom length filter (@Leonabcd123) (#7109) ### Description Added a new filter option in the quotes search page that allows the user to search for quotes by a minimum and a maximum length. Implementing #1323 --------- Co-authored-by: Jack --- frontend/src/ts/modals/quote-filter.ts | 51 +++++++++++++++++++ frontend/src/ts/modals/quote-search.ts | 68 ++++++++++++++++++++++++-- frontend/src/ts/utils/simple-modal.ts | 4 ++ 3 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 frontend/src/ts/modals/quote-filter.ts diff --git a/frontend/src/ts/modals/quote-filter.ts b/frontend/src/ts/modals/quote-filter.ts new file mode 100644 index 000000000000..d83fccce564f --- /dev/null +++ b/frontend/src/ts/modals/quote-filter.ts @@ -0,0 +1,51 @@ +import { SimpleModal } from "../utils/simple-modal"; + +export let minFilterLength: number = 0; +export let maxFilterLength: number = 0; +export let removeCustom: boolean = false; + +export function setRemoveCustom(value: boolean): void { + removeCustom = value; +} + +function refresh(): void { + const refreshEvent = new CustomEvent("refresh"); + document.dispatchEvent(refreshEvent); +} + +export const quoteFilterModal = new SimpleModal({ + id: "quoteFilter", + title: "Enter minimum and maximum values", + inputs: [ + { + placeholder: "1", + type: "number", + }, + { + placeholder: "100", + type: "number", + }, + ], + buttonText: "save", + execFn: async (_thisPopup, min, max) => { + const minNum = parseInt(min, 10); + const maxNum = parseInt(max, 10); + if (isNaN(minNum) || isNaN(maxNum)) { + return { + status: 0, + message: "Invalid min/max values", + }; + } + + minFilterLength = minNum; + maxFilterLength = maxNum; + refresh(); + + let message: string = "saved custom filter"; + return { status: 1, message }; + }, + afterClickAway: () => { + setRemoveCustom(true); + refresh(); + }, +}); diff --git a/frontend/src/ts/modals/quote-search.ts b/frontend/src/ts/modals/quote-search.ts index 12d02d3ee16a..33f371384681 100644 --- a/frontend/src/ts/modals/quote-search.ts +++ b/frontend/src/ts/modals/quote-search.ts @@ -4,6 +4,7 @@ import * as ManualRestart from "../test/manual-restart-tracker"; import * as Notifications from "../elements/notifications"; import * as QuoteSubmitPopup from "./quote-submit"; import * as QuoteApprovePopup from "./quote-approve"; +import * as QuoteFilterPopup from "./quote-filter"; import * as QuoteReportModal from "./quote-report"; import { buildSearchService, @@ -26,6 +27,7 @@ const searchServiceCache: Record> = {}; const pageSize = 100; let currentPageNumber = 1; +let usingCustomLength = true; function getSearchService( language: string, @@ -45,16 +47,65 @@ function getSearchService( function applyQuoteLengthFilter(quotes: Quote[]): Quote[] { if (!modal.isOpen()) return []; - const quoteLengthFilterValue = $( - "#quoteSearchModal .quoteLengthFilter", - ).val() as string[]; + const quoteLengthDropdown = $("#quoteSearchModal .quoteLengthFilter"); + const quoteLengthFilterValue = quoteLengthDropdown.val() as string[]; + if (quoteLengthFilterValue.length === 0) { + usingCustomLength = true; return quotes; } const quoteLengthFilter = new Set( quoteLengthFilterValue.map((filterValue) => parseInt(filterValue, 10)), ); + + const customFilterIndex = quoteLengthFilterValue.indexOf("4"); + + if (customFilterIndex !== -1) { + if (QuoteFilterPopup.removeCustom) { + QuoteFilterPopup.setRemoveCustom(false); + const selectElement = quoteLengthDropdown.get(0) as + | HTMLSelectElement + | null + | undefined; + + if (!selectElement) { + return quotes; + } + + //@ts-expect-error SlimSelect adds slim to the element + const ss = selectElement.slim as SlimSelect | undefined; + + if (ss !== undefined) { + const currentSelected = ss.getSelected(); + + // remove custom selection + const customIndex = currentSelected.indexOf("4"); + if (customIndex > -1) { + currentSelected.splice(customIndex, 1); + } + + ss.setSelected(currentSelected); + } + } else { + if (usingCustomLength) { + QuoteFilterPopup.quoteFilterModal.show(undefined, {}); + usingCustomLength = false; + } else { + const filteredQuotes = quotes.filter( + (quote) => + (quote.length >= QuoteFilterPopup.minFilterLength && + quote.length <= QuoteFilterPopup.maxFilterLength) || + quoteLengthFilter.has(quote.group), + ); + + return filteredQuotes; + } + } + } else { + usingCustomLength = true; + } + const filteredQuotes = quotes.filter((quote) => quoteLengthFilter.has(quote.group), ); @@ -281,6 +332,10 @@ export async function show(showOptions?: ShowOptions): Promise { text: "thicc", value: "3", }, + { + text: "custom", + value: "4", + }, ], }); }, @@ -437,6 +492,13 @@ async function setup(modalEl: HTMLElement): Promise { currentPageNumber--; void updateResults(searchText); }); + + document?.addEventListener("refresh", () => { + const searchText = ( + document.getElementById("searchBox") as HTMLInputElement + ).value; + void updateResults(searchText); + }); } async function cleanup(): Promise { diff --git a/frontend/src/ts/utils/simple-modal.ts b/frontend/src/ts/utils/simple-modal.ts index b1452dadf3e2..63364467637a 100644 --- a/frontend/src/ts/utils/simple-modal.ts +++ b/frontend/src/ts/utils/simple-modal.ts @@ -111,6 +111,7 @@ type SimpleModalOptions = { onlineOnly?: boolean; hideCallsExec?: boolean; showLabels?: boolean; + afterClickAway?: () => void; }; export class SimpleModal { @@ -131,6 +132,7 @@ export class SimpleModal { onlineOnly: boolean; hideCallsExec: boolean; showLabels: boolean; + afterClickAway: (() => void) | undefined; constructor(options: SimpleModalOptions) { this.parameters = []; this.id = options.id; @@ -149,6 +151,7 @@ export class SimpleModal { this.onlineOnly = options.onlineOnly ?? false; this.hideCallsExec = options.hideCallsExec ?? false; this.showLabels = options.showLabels ?? false; + this.afterClickAway = options.afterClickAway; } reset(): void { this.element.innerHTML = ` @@ -480,6 +483,7 @@ const modal = new AnimatedModal({ hide(); }, customWrapperClickHandler: (e): void => { + activePopup?.afterClickAway?.(); hide(); }, }); From 6cfb8809085901978227fe87f99cf808c8752cab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Dec 2025 16:47:36 +0100 Subject: [PATCH 3/4] build(deps): bump express from 5.1.0 to 5.2.0 in /backend (#7175) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [express](https://github.com/expressjs/express) from 5.1.0 to 5.2.0.
Release notes

Sourced from express's releases.

v5.2.0

Important: Security

What's Changed

... (truncated)

Changelog

Sourced from express's changelog.

5.2.0 / 2025-12-01

  • Security fix for CVE-2024-51999 (GHSA-pj86-cfqh-vqx6)
  • deps: body-parser@^2.2.1
  • A deprecation warning was added when using res.redirect with undefined arguments, Express now emits a warning to help detect calls that pass undefined as the status or URL and make them easier to fix.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=express&package-manager=npm_and_yarn&previous-version=5.1.0&new-version=5.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/monkeytypegame/monkeytype/network/alerts).
--------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Miodec --- backend/package.json | 2 +- pnpm-lock.yaml | 44 ++++++++++++++++++++------------------------ 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/backend/package.json b/backend/package.json index 563b5741e76b..60996ca52dbb 100644 --- a/backend/package.json +++ b/backend/package.json @@ -40,7 +40,7 @@ "date-fns": "3.6.0", "dotenv": "16.4.5", "etag": "1.8.1", - "express": "5.1.0", + "express": "5.2.0", "express-rate-limit": "7.5.1", "firebase-admin": "12.0.0", "helmet": "4.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c74ab323e20c..e895a63bf7cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -73,7 +73,7 @@ importers: version: 3.52.1(@types/node@24.9.1)(zod@3.23.8) '@ts-rest/express': specifier: 3.52.1 - version: 3.52.1(@ts-rest/core@3.52.1(@types/node@24.9.1)(zod@3.23.8))(express@5.1.0)(zod@3.23.8) + version: 3.52.1(@ts-rest/core@3.52.1(@types/node@24.9.1)(zod@3.23.8))(express@5.2.0)(zod@3.23.8) '@ts-rest/open-api': specifier: 3.52.1 version: 3.52.1(@ts-rest/core@3.52.1(@types/node@24.9.1)(zod@3.23.8))(zod@3.23.8) @@ -102,11 +102,11 @@ importers: specifier: 1.8.1 version: 1.8.1 express: - specifier: 5.1.0 - version: 5.1.0 + specifier: 5.2.0 + version: 5.2.0 express-rate-limit: specifier: 7.5.1 - version: 7.5.1(express@5.1.0) + version: 7.5.1(express@5.2.0) firebase-admin: specifier: 12.0.0 version: 12.0.0(encoding@0.1.13) @@ -3883,8 +3883,8 @@ packages: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - body-parser@2.2.0: - resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} + body-parser@2.2.1: + resolution: {integrity: sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==} engines: {node: '>=18'} boolbase@1.0.0: @@ -5187,8 +5187,8 @@ packages: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} - express@5.1.0: - resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} + express@5.2.0: + resolution: {integrity: sha512-XdpJDLxfztVY59X0zPI6sibRiGcxhTPXRD3IhJmjKf2jwMvkRGV1j7loB8U+heeamoU3XvihAaGRTR4aXXUN3A==} engines: {node: '>= 18'} extend@3.0.2: @@ -6837,10 +6837,6 @@ packages: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - mime-db@1.53.0: - resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==} - engines: {node: '>= 0.6'} - mime-db@1.54.0: resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} engines: {node: '>= 0.6'} @@ -11672,7 +11668,7 @@ snapshots: '@hapi/mimos@7.0.1': dependencies: '@hapi/hoek': 11.0.4 - mime-db: 1.53.0 + mime-db: 1.54.0 '@hapi/nigel@5.0.1': dependencies: @@ -11835,7 +11831,7 @@ snapshots: '@kwsites/file-exists@1.1.1': dependencies: - debug: 4.3.6(supports-color@5.5.0) + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -12548,10 +12544,10 @@ snapshots: '@types/node': 24.9.1 zod: 3.23.8 - '@ts-rest/express@3.52.1(@ts-rest/core@3.52.1(@types/node@24.9.1)(zod@3.23.8))(express@5.1.0)(zod@3.23.8)': + '@ts-rest/express@3.52.1(@ts-rest/core@3.52.1(@types/node@24.9.1)(zod@3.23.8))(express@5.2.0)(zod@3.23.8)': dependencies: '@ts-rest/core': 3.52.1(@types/node@24.9.1)(zod@3.23.8) - express: 5.1.0 + express: 5.2.0 optionalDependencies: zod: 3.23.8 @@ -13508,13 +13504,13 @@ snapshots: transitivePeerDependencies: - supports-color - body-parser@2.2.0: + body-parser@2.2.1: dependencies: bytes: 3.1.2 content-type: 1.0.5 debug: 4.4.3 http-errors: 2.0.0 - iconv-lite: 0.6.3 + iconv-lite: 0.7.0 on-finished: 2.4.1 qs: 6.14.0 raw-body: 3.0.1 @@ -15099,9 +15095,9 @@ snapshots: exponential-backoff@3.1.1: optional: true - express-rate-limit@7.5.1(express@5.1.0): + express-rate-limit@7.5.1(express@5.2.0): dependencies: - express: 5.1.0 + express: 5.2.0 express@4.21.2: dependencies: @@ -15139,15 +15135,16 @@ snapshots: transitivePeerDependencies: - supports-color - express@5.1.0: + express@5.2.0: dependencies: accepts: 2.0.0 - body-parser: 2.2.0 + body-parser: 2.2.1 content-disposition: 1.0.0 content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.2.2 debug: 4.4.3 + depd: 2.0.0 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -16096,6 +16093,7 @@ snapshots: iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 + optional: true iconv-lite@0.7.0: dependencies: @@ -17104,8 +17102,6 @@ snapshots: mime-db@1.52.0: {} - mime-db@1.53.0: {} - mime-db@1.54.0: {} mime-types@2.1.35: From 445be887547d012cdfd370c4b3f2241ec4a87d2f Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Wed, 3 Dec 2025 16:52:38 +0100 Subject: [PATCH 4/4] ci: allow dependabot node version (@fehmer) (#7184) --- backend/package.json | 2 +- frontend/package.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/package.json b/backend/package.json index 60996ca52dbb..662e0d95ca04 100644 --- a/backend/package.json +++ b/backend/package.json @@ -21,7 +21,7 @@ "gen-docs": "tsx scripts/openapi.ts dist/static/api/openapi.json && redocly build-docs -o dist/static/api/internal.html internal@v2 && redocly bundle -o dist/static/api/public.json public-filter && redocly build-docs -o dist/static/api/public.html public@v2" }, "engines": { - "node": "24.11.0" + "node": "24.11.0 || 22.21.0" }, "dependencies": { "@date-fns/utc": "1.2.0", diff --git a/frontend/package.json b/frontend/package.json index f1ab6e2691b8..aed5df9013bd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -24,7 +24,7 @@ "docker": "docker compose -f docker/compose.dev.yml up" }, "engines": { - "node": "24.11.0" + "node": "24.11.0 || 22.21.0" }, "browserslist": [ "defaults", diff --git a/package.json b/package.json index e074584a310a..b96f7771b8f5 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "knip": "knip" }, "engines": { - "node": "24.11.0" + "node": "24.11.0 || 22.21.0" }, "devDependencies": { "@commitlint/cli": "17.7.1",