From 772eb2f1d4db852ffada4ced71b5871d959bfe11 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 13 Jul 2025 09:33:16 -0400 Subject: [PATCH] fix: `randomstring` dep does not work in browser with rolldown-vite (#9624) * fix: randomstring dep does not work in browser with rolldown-vite * fix: Last usage of randomstring, docs * feedback --- package.json | 2 - plugins/slack/server/api/hooks.test.ts | 12 +- .../components/WebhookSubscriptionForm.tsx | 5 +- server/emails/templates/BaseEmail.tsx | 5 +- server/middlewares/authentication.test.ts | 4 +- server/models/ApiKey.test.ts | 4 +- server/models/ApiKey.ts | 4 +- server/models/Collection.test.ts | 4 +- server/models/oauth/OAuthClient.ts | 6 +- server/routes/api/developer/developer.ts | 4 +- server/test/factories.ts | 14 +- server/utils/url.ts | 4 +- shared/random.test.ts | 186 ++++++++++++++++++ shared/random.ts | 66 ++++++- yarn.lock | 89 +-------- 15 files changed, 290 insertions(+), 119 deletions(-) create mode 100644 shared/random.test.ts diff --git a/package.json b/package.json index 08004ad42c..9ebf5161a8 100644 --- a/package.json +++ b/package.json @@ -203,7 +203,6 @@ "prosemirror-transform": "1.10.0", "prosemirror-view": "^1.39.1", "query-string": "^7.1.3", - "randomstring": "1.3.1", "rate-limiter-flexible": "^2.4.2", "react": "^17.0.2", "react-avatar-editor": "^13.0.2", @@ -314,7 +313,6 @@ "@types/pluralize": "^0.0.33", "@types/png-chunks-extract": "^1.0.2", "@types/quoted-printable": "^1.0.2", - "@types/randomstring": "^1.3.0", "@types/react": "^17.0.34", "@types/react-avatar-editor": "^13.0.4", "@types/react-color": "^3.0.13", diff --git a/plugins/slack/server/api/hooks.test.ts b/plugins/slack/server/api/hooks.test.ts index 84770a3f98..3d91363aef 100644 --- a/plugins/slack/server/api/hooks.test.ts +++ b/plugins/slack/server/api/hooks.test.ts @@ -1,4 +1,4 @@ -import randomstring from "randomstring"; +import { randomString } from "@shared/random"; import { IntegrationService } from "@shared/types"; import { IntegrationAuthentication, SearchQuery } from "@server/models"; import { buildDocument, buildTeam, buildUser } from "@server/test/factories"; @@ -24,19 +24,19 @@ describe("#hooks.unfurl", () => { service: IntegrationService.Slack, userId: user.id, teamId: user.teamId, - token: randomstring.generate(32), + token: randomString(32), }); const res = await server.post("/api/hooks.unfurl", { body: { token: env.SLACK_VERIFICATION_TOKEN, - team_id: `T${randomstring.generate(8)}`, - api_app_id: `A${randomstring.generate(8)}`, + team_id: `T${randomString(8)}`, + api_app_id: `A${randomString(8)}`, event: { type: "link_shared", - channel: `C${randomstring.generate(8)}`, + channel: `C${randomString(8)}`, user: user.authentications[0].providerId, - message_ts: randomstring.generate(12), + message_ts: randomString(12), links: [ { domain: "getoutline.com", diff --git a/plugins/webhooks/client/components/WebhookSubscriptionForm.tsx b/plugins/webhooks/client/components/WebhookSubscriptionForm.tsx index 36ef84ed5f..6ca20b043b 100644 --- a/plugins/webhooks/client/components/WebhookSubscriptionForm.tsx +++ b/plugins/webhooks/client/components/WebhookSubscriptionForm.tsx @@ -1,12 +1,11 @@ import filter from "lodash/filter"; import includes from "lodash/includes"; import isEqual from "lodash/isEqual"; -import randomstring from "randomstring"; -import * as React from "react"; import { useEffect } from "react"; import { useForm } from "react-hook-form"; import { useTranslation, Trans } from "react-i18next"; import styled from "styled-components"; +import { randomString } from "@shared/random"; import { TeamPreference } from "@shared/types"; import WebhookSubscription from "~/models/WebhookSubscription"; import Button from "~/components/Button"; @@ -159,7 +158,7 @@ interface FormData { } function generateSigningSecret() { - return `ol_whs_${randomstring.generate(32)}`; + return `ol_whs_${randomString(32)}`; } function WebhookSubscriptionForm({ handleSubmit, webhookSubscription }: Props) { diff --git a/server/emails/templates/BaseEmail.tsx b/server/emails/templates/BaseEmail.tsx index 583259bdb6..fafa5d5305 100644 --- a/server/emails/templates/BaseEmail.tsx +++ b/server/emails/templates/BaseEmail.tsx @@ -2,8 +2,7 @@ import addressparser, { EmailAddress } from "addressparser"; import Bull from "bull"; import invariant from "invariant"; import { Node } from "prosemirror-model"; -import randomstring from "randomstring"; -import * as React from "react"; +import { randomString } from "@shared/random"; import { TeamPreference } from "@shared/types"; import { Day } from "@shared/utils/time"; import mailer from "@server/emails/mailer"; @@ -200,7 +199,7 @@ export default abstract class BaseEmail< address: env.isCloudHosted && this.category === EmailMessageCategory.Authentication - ? `noreply-${randomstring.generate(24)}@${domain}` + ? `noreply-${randomString(24)}@${domain}` : parsedFrom.address, }; } diff --git a/server/middlewares/authentication.test.ts b/server/middlewares/authentication.test.ts index e5cd020c33..c3ad8559eb 100644 --- a/server/middlewares/authentication.test.ts +++ b/server/middlewares/authentication.test.ts @@ -1,5 +1,5 @@ import { DefaultState } from "koa"; -import randomstring from "randomstring"; +import { randomString } from "@shared/random"; import { Scope } from "@shared/types"; import { buildUser, @@ -106,7 +106,7 @@ describe("Authentication middleware", () => { { // @ts-expect-error mock request request: { - get: jest.fn(() => `Bearer ${randomstring.generate(38)}`), + get: jest.fn(() => `Bearer ${randomString(38)}`), }, state, cache: {}, diff --git a/server/models/ApiKey.test.ts b/server/models/ApiKey.test.ts index ea2b4de895..8b62cf6545 100644 --- a/server/models/ApiKey.test.ts +++ b/server/models/ApiKey.test.ts @@ -1,4 +1,4 @@ -import randomstring from "randomstring"; +import { randomString } from "@shared/random"; import { buildApiKey } from "@server/test/factories"; import ApiKey from "./ApiKey"; @@ -7,7 +7,7 @@ describe("#ApiKey", () => { it("should match an API secret", async () => { const apiKey = await buildApiKey(); expect(ApiKey.match(apiKey.value!)).toBe(true); - expect(ApiKey.match(`${randomstring.generate(38)}`)).toBe(true); + expect(ApiKey.match(`${randomString(38)}`)).toBe(true); }); it("should not match non secrets", async () => { diff --git a/server/models/ApiKey.ts b/server/models/ApiKey.ts index 2f0980a708..7cfef82a5a 100644 --- a/server/models/ApiKey.ts +++ b/server/models/ApiKey.ts @@ -1,6 +1,5 @@ import { Matches } from "class-validator"; import { subMinutes } from "date-fns"; -import randomstring from "randomstring"; import { InferAttributes, InferCreationAttributes, Op } from "sequelize"; import { Column, @@ -14,6 +13,7 @@ import { AfterFind, BeforeSave, } from "sequelize-typescript"; +import { randomString } from "@shared/random"; import { ApiKeyValidation } from "@shared/validations"; import { hash } from "@server/utils/crypto"; import User from "./User"; @@ -95,7 +95,7 @@ class ApiKey extends ParanoidModel< @BeforeValidate public static async generateSecret(model: ApiKey) { if (!model.hash) { - const secret = `${ApiKey.prefix}${randomstring.generate(38)}`; + const secret = `${ApiKey.prefix}${randomString(38)}`; model.value = model.secret || secret; model.hash = hash(model.value); } diff --git a/server/models/Collection.test.ts b/server/models/Collection.test.ts index 9c85f344b7..70f0d5a253 100644 --- a/server/models/Collection.test.ts +++ b/server/models/Collection.test.ts @@ -1,5 +1,5 @@ -import randomstring from "randomstring"; import { v4 as uuidv4 } from "uuid"; +import { randomString } from "@shared/random"; import slugify from "@shared/utils/slugify"; import { buildUser, @@ -511,7 +511,7 @@ describe("#findByPk", () => { }); it("should return null when no collection is found with urlId", async () => { - const id = `${slugify("test collection")}-${randomstring.generate(15)}`; + const id = `${slugify("test collection")}-${randomString(15)}`; const response = await Collection.findByPk(id); expect(response).toBe(null); }); diff --git a/server/models/oauth/OAuthClient.ts b/server/models/oauth/OAuthClient.ts index 533ce75470..673f33cf31 100644 --- a/server/models/oauth/OAuthClient.ts +++ b/server/models/oauth/OAuthClient.ts @@ -5,7 +5,6 @@ import { ArrayUnique, IsUrl, } from "class-validator"; -import rs from "randomstring"; import { InferAttributes, InferCreationAttributes } from "sequelize"; import { Column, @@ -17,6 +16,7 @@ import { BeforeCreate, AllowNull, } from "sequelize-typescript"; +import { randomString } from "@shared/random"; import { OAuthClientValidation } from "@shared/validations"; import Team from "@server/models/Team"; import User from "@server/models/User"; @@ -144,7 +144,7 @@ class OAuthClient extends ParanoidModel< } private static generateNewClientId(): string { - return rs.generate({ + return randomString({ length: 20, charset: "alphanumeric", capitalization: "lowercase", @@ -152,7 +152,7 @@ class OAuthClient extends ParanoidModel< } private static generateNewClientSecret(): string { - return `${OAuthClient.clientSecretPrefix}${rs.generate(32)}`; + return `${OAuthClient.clientSecretPrefix}${randomString(32)}`; } } diff --git a/server/routes/api/developer/developer.ts b/server/routes/api/developer/developer.ts index 2de25ea5ad..fc6ef249e7 100644 --- a/server/routes/api/developer/developer.ts +++ b/server/routes/api/developer/developer.ts @@ -1,6 +1,6 @@ import { Context, Next } from "koa"; import Router from "koa-router"; -import randomstring from "randomstring"; +import { randomString } from "@shared/random"; import userInviter, { Invite } from "@server/commands/userInviter"; import env from "@server/env"; import Logger from "@server/logging/Logger"; @@ -33,7 +33,7 @@ router.post( const invites = Array(Math.min(count, 100)) .fill(0) .map(() => { - const rando = randomstring.generate(10); + const rando = randomString(10); return { email: `${rando}@example.com`, diff --git a/server/test/factories.ts b/server/test/factories.ts index 05378dd6b8..155bc0d872 100644 --- a/server/test/factories.ts +++ b/server/test/factories.ts @@ -2,10 +2,10 @@ import { faker } from "@faker-js/faker"; import isNil from "lodash/isNil"; import isNull from "lodash/isNull"; import { Node } from "prosemirror-model"; -import randomstring from "randomstring"; import { InferCreationAttributes } from "sequelize"; import { DeepPartial } from "utility-types"; import { v4 as uuidv4 } from "uuid"; +import { randomString } from "@shared/random"; import { CollectionPermission, FileOperationState, @@ -154,7 +154,7 @@ export function buildTeam( authenticationProviders: [ { name: "slack", - providerId: randomstring.generate(32), + providerId: randomString(32), }, ], ...overrides, @@ -215,7 +215,7 @@ export async function buildUser(overrides: Partial = {}) { ? [ { authenticationProviderId: authenticationProvider.id, - providerId: randomstring.generate(32), + providerId: randomString(32), }, ] : [], @@ -272,7 +272,7 @@ export async function buildIntegration(overrides: Partial = {}) { service: IntegrationService.Slack, userId: user.id, teamId: user.teamId, - token: randomstring.generate(32), + token: randomString(32), scopes: ["example", "scopes", "here"], }); return Integration.create({ @@ -737,7 +737,7 @@ export async function buildOAuthAuthorizationCode( overrides.expiresAt = new Date(); } - const code = randomstring.generate(32); + const code = randomString(32); let client; if (overrides.oauthClientId) { @@ -817,11 +817,11 @@ export function buildCommentMark(overrides: { resolved?: boolean; }) { if (!overrides.id) { - overrides.id = randomstring.generate(10); + overrides.id = randomString(10); } if (!overrides.userId) { - overrides.userId = randomstring.generate(10); + overrides.userId = randomString(10); } return { diff --git a/server/utils/url.ts b/server/utils/url.ts index 2b400c23d0..405e8bced0 100644 --- a/server/utils/url.ts +++ b/server/utils/url.ts @@ -1,5 +1,5 @@ -import randomstring from "randomstring"; +import { randomString } from "@shared/random"; const UrlIdLength = 10; -export const generateUrlId = () => randomstring.generate(UrlIdLength); +export const generateUrlId = () => randomString(UrlIdLength); diff --git a/shared/random.test.ts b/shared/random.test.ts new file mode 100644 index 0000000000..17f78e2dbf --- /dev/null +++ b/shared/random.test.ts @@ -0,0 +1,186 @@ +import { randomString } from "./random"; + +describe("randomString", () => { + describe("with number parameter", () => { + it("should generate string of correct length", () => { + const result = randomString(10); + expect(result).toHaveLength(10); + }); + + it("should generate alphanumeric mixed case by default", () => { + const result = randomString(100); + expect(result).toMatch(/^[a-zA-Z0-9]+$/); + // Check that it contains both cases and numbers (with high probability) + expect(result).toMatch(/[a-z]/); + expect(result).toMatch(/[A-Z]/); + expect(result).toMatch(/[0-9]/); + }); + + it("should generate different strings on multiple calls", () => { + const result1 = randomString(20); + const result2 = randomString(20); + expect(result1).not.toEqual(result2); + }); + }); + + describe("with object parameter", () => { + describe("charset: numeric", () => { + it("should generate only numbers", () => { + const result = randomString({ length: 50, charset: "numeric" }); + expect(result).toMatch(/^[0-9]+$/); + expect(result).toHaveLength(50); + }); + + it("should ignore capitalization for numeric charset", () => { + const lowercase = randomString({ + length: 50, + charset: "numeric", + capitalization: "lowercase", + }); + const uppercase = randomString({ + length: 50, + charset: "numeric", + capitalization: "uppercase", + }); + const mixed = randomString({ + length: 50, + charset: "numeric", + capitalization: "mixed", + }); + + expect(lowercase).toMatch(/^[0-9]+$/); + expect(uppercase).toMatch(/^[0-9]+$/); + expect(mixed).toMatch(/^[0-9]+$/); + }); + }); + + describe("charset: alphabetic", () => { + it("should generate only letters with mixed capitalization by default", () => { + const result = randomString({ length: 100, charset: "alphabetic" }); + expect(result).toMatch(/^[a-zA-Z]+$/); + expect(result).toMatch(/[a-z]/); + expect(result).toMatch(/[A-Z]/); + }); + + it("should generate only lowercase letters", () => { + const result = randomString({ + length: 50, + charset: "alphabetic", + capitalization: "lowercase", + }); + expect(result).toMatch(/^[a-z]+$/); + expect(result).toHaveLength(50); + }); + + it("should generate only uppercase letters", () => { + const result = randomString({ + length: 50, + charset: "alphabetic", + capitalization: "uppercase", + }); + expect(result).toMatch(/^[A-Z]+$/); + expect(result).toHaveLength(50); + }); + + it("should generate mixed case letters", () => { + const result = randomString({ + length: 100, + charset: "alphabetic", + capitalization: "mixed", + }); + expect(result).toMatch(/^[a-zA-Z]+$/); + expect(result).toMatch(/[a-z]/); + expect(result).toMatch(/[A-Z]/); + }); + }); + + describe("charset: alphanumeric", () => { + it("should generate letters and numbers with mixed capitalization by default", () => { + const result = randomString({ length: 100, charset: "alphanumeric" }); + expect(result).toMatch(/^[a-zA-Z0-9]+$/); + expect(result).toMatch(/[a-z]/); + expect(result).toMatch(/[A-Z]/); + expect(result).toMatch(/[0-9]/); + }); + + it("should generate lowercase letters and numbers", () => { + const result = randomString({ + length: 100, + charset: "alphanumeric", + capitalization: "lowercase", + }); + expect(result).toMatch(/^[a-z0-9]+$/); + expect(result).toMatch(/[a-z]/); + expect(result).toMatch(/[0-9]/); + }); + + it("should generate uppercase letters and numbers", () => { + const result = randomString({ + length: 100, + charset: "alphanumeric", + capitalization: "uppercase", + }); + expect(result).toMatch(/^[A-Z0-9]+$/); + expect(result).toMatch(/[A-Z]/); + expect(result).toMatch(/[0-9]/); + }); + + it("should generate mixed case letters and numbers", () => { + const result = randomString({ + length: 100, + charset: "alphanumeric", + capitalization: "mixed", + }); + expect(result).toMatch(/^[a-zA-Z0-9]+$/); + expect(result).toMatch(/[a-z]/); + expect(result).toMatch(/[A-Z]/); + expect(result).toMatch(/[0-9]/); + }); + }); + + describe("default values", () => { + it("should default to alphanumeric charset", () => { + const result = randomString({ length: 100 }); + expect(result).toMatch(/^[a-zA-Z0-9]+$/); + expect(result).toMatch(/[a-z]/); + expect(result).toMatch(/[A-Z]/); + expect(result).toMatch(/[0-9]/); + }); + + it("should default to mixed capitalization", () => { + const result = randomString({ length: 100, charset: "alphabetic" }); + expect(result).toMatch(/^[a-zA-Z]+$/); + expect(result).toMatch(/[a-z]/); + expect(result).toMatch(/[A-Z]/); + }); + }); + + describe("edge cases", () => { + it("should handle length of 1", () => { + const result = randomString({ length: 1, charset: "alphabetic" }); + expect(result).toHaveLength(1); + expect(result).toMatch(/^[a-zA-Z]$/); + }); + + it("should handle length of 0", () => { + const result = randomString({ length: 0 }); + expect(result).toHaveLength(0); + expect(result).toBe(""); + }); + + it("should generate different strings on multiple calls", () => { + const result1 = randomString({ + length: 20, + charset: "alphanumeric", + capitalization: "lowercase", + }); + const result2 = randomString({ + length: 20, + charset: "alphanumeric", + capitalization: "lowercase", + }); + expect(result1).not.toEqual(result2); + }); + }); + }); +}); diff --git a/shared/random.ts b/shared/random.ts index 4f18a6aac2..8ec12406ea 100644 --- a/shared/random.ts +++ b/shared/random.ts @@ -1,6 +1,66 @@ -const randomInteger = (min: number, max: number) => +/** + * Generate a random integer within a given range. + * + * @param min - The minimum value of the range. + * @param max - The maximum value of the range. + * @returns A random integer within the range. + */ +export const randomInteger = (min: number, max: number) => Math.floor(Math.random() * (max - min + 1) + min); -const randomElement = (arr: T[]): T => arr[randomInteger(0, arr.length - 1)]; +/** + * Choose a random element from an array. + * + * @param arr - The array to choose from. + * @returns A random element from the array. + */ +export const randomElement = (arr: T[]): T => + arr[randomInteger(0, arr.length - 1)]; -export { randomInteger, randomElement }; +type RandomStringOptions = { + /** The length of the output string. */ + length: number; + /** The character set to use. */ + charset?: "alphabetic" | "numeric" | "alphanumeric"; + /** The capitalization of the string. */ + capitalization?: "lowercase" | "uppercase" | "mixed"; +}; + +/** + * Generate a random string of a given length and charset. + * + * @param options - The length of the string or an object with options. + * @returns A random string. + */ +export const randomString = (options: number | RandomStringOptions) => { + const lowercase = "abcdefghijklmnopqrstuvwxyz"; + const uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const numeric = "0123456789"; + + const length = typeof options === "number" ? options : options.length; + const charset = + typeof options === "number" + ? "alphanumeric" + : options.charset || "alphanumeric"; + const capitalization = + typeof options === "number" ? "mixed" : options.capitalization || "mixed"; + + const chars = + charset === "numeric" + ? numeric + : charset === "alphabetic" + ? capitalization === "lowercase" + ? lowercase + : capitalization === "uppercase" + ? uppercase + : lowercase + uppercase + : capitalization === "lowercase" + ? lowercase + numeric + : capitalization === "uppercase" + ? uppercase + numeric + : lowercase + uppercase + numeric; + + const array = new Uint8Array(length); + crypto.getRandomValues(array); + return Array.from(array, (x) => chars[x % chars.length]).join(""); +}; diff --git a/yarn.lock b/yarn.lock index 945b2f59c0..223af8ce6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -744,14 +744,7 @@ "@jridgewell/trace-mapping" "^0.3.28" jsesc "^3.0.2" -"@babel/helper-annotate-as-pure@^7.22.5", "@babel/helper-annotate-as-pure@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz#4345d81a9a46a6486e24d069469f13e60445c05d" - integrity sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow== - dependencies: - "@babel/types" "^7.27.1" - -"@babel/helper-annotate-as-pure@^7.27.3": +"@babel/helper-annotate-as-pure@^7.22.5", "@babel/helper-annotate-as-pure@^7.27.1", "@babel/helper-annotate-as-pure@^7.27.3": version "7.27.3" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz#f31fd86b915fc4daf1f3ac6976c59be7084ed9c5" integrity sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg== @@ -1693,15 +1686,7 @@ "@babel/types" "^7.28.0" debug "^4.3.1" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.27.6", "@babel/types@^7.28.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": - version "7.28.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.0.tgz#2fd0159a6dc7353933920c43136335a9b264d950" - integrity sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg== - dependencies: - "@babel/helper-string-parser" "^7.27.1" - "@babel/helper-validator-identifier" "^7.27.1" - -"@babel/types@^7.27.3": +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.27.6", "@babel/types@^7.28.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": version "7.28.1" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.1.tgz#2aaf3c10b31ba03a77ac84f52b3912a0edef4cf9" integrity sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ== @@ -5151,11 +5136,6 @@ resolved "https://registry.yarnpkg.com/@types/quoted-printable/-/quoted-printable-1.0.2.tgz#1d89663da9ded3df30d162558c5d18759831f659" integrity "sha1-HYlmPane098w0WJVjF0YdZgx9lk= sha512-3B28oB1rRaZNb3N5dlxysm8lH1ujzvReDuYBiIO4jvpTIg9ksrILCNgPxSGVyTWE/qwuxzgHaVehwMK3CVqAtA==" -"@types/randomstring@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@types/randomstring/-/randomstring-1.3.0.tgz#2953e8de350c27c10eb1aa011fbca8d88c327d79" - integrity sha512-kCP61wludjY7oNUeFiMxfswHB3Wn/aC03Cu82oQsNTO6OCuhVN/rCbBs68Cq6Nkgjmp2Sh3Js6HearJPkk7KQA== - "@types/range-parser@*": version "1.2.4" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" @@ -6432,17 +6412,7 @@ browserslist-to-esbuild@^1.2.0: dependencies: browserslist "^4.17.3" -browserslist@^4.17.3, browserslist@^4.24.0: - version "4.24.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" - integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== - dependencies: - caniuse-lite "^1.0.30001688" - electron-to-chromium "^1.5.73" - node-releases "^2.0.19" - update-browserslist-db "^1.1.1" - -browserslist@^4.25.1: +browserslist@^4.17.3, browserslist@^4.24.0, browserslist@^4.25.1: version "4.25.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.25.1.tgz#ba9e8e6f298a1d86f829c9b975e07948967bb111" integrity sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw== @@ -6585,12 +6555,7 @@ camelize@^1.0.0: resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" integrity "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs= sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg==" -caniuse-lite@^1.0.30001688: - version "1.0.30001699" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz#a102cf330d153bf8c92bfb5be3cd44c0a89c8c12" - integrity sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w== - -caniuse-lite@^1.0.30001726: +caniuse-lite@^1.0.30001688, caniuse-lite@^1.0.30001726: version "1.0.30001727" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz#22e9706422ad37aa50556af8c10e40e2d93a8b85" integrity sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q== @@ -8007,16 +7972,11 @@ ejs@^3.1.10, ejs@^3.1.6: dependencies: jake "^10.8.5" -electron-to-chromium@^1.5.173: +electron-to-chromium@^1.5.173, electron-to-chromium@^1.5.73: version "1.5.182" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.182.tgz#4ab73104f893938acb3ab9c28d7bec170c116b3e" integrity sha512-Lv65Btwv9W4J9pyODI6EWpdnhfvrve/us5h1WspW8B2Fb0366REPtY3hX7ounk1CkV/TBjWCEvCBBbYbmV0qCA== -electron-to-chromium@^1.5.73: - version "1.5.99" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.99.tgz#4817c7526d71b66e6c56c3e5231fe1113653a85d" - integrity sha512-77c/+fCyL2U+aOyqfIFi89wYLBeSTCs55xCZL0oFH0KjqsvSvyh6AdQ+UIl1vgpnQQE6g+/KK8hOIupH6VwPtg== - email-providers@^1.14.0: version "1.14.0" resolved "https://registry.yarnpkg.com/email-providers/-/email-providers-1.14.0.tgz#a353f56390f9a8b42ba1843a1701c1f5fcd332ee" @@ -9860,14 +9820,7 @@ is-callable@^1.1.3, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity "sha1-O8KoXqdC2eNiBdys3XLKH9xRsFU= sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" -is-core-module@^2.13.0, is-core-module@^2.15.1: - version "2.16.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.0.tgz#6c01ffdd5e33c49c1d2abfa93334a85cb56bd81c" - integrity sha512-urTSINYfAYgcbLb0yDQ6egFm6h3Mo1DcF9EkyXSRjjzdHbsulg01qhwWuXdOoUBuTkbQ80KDboXa0vFJ+BDH+g== - dependencies: - hasown "^2.0.2" - -is-core-module@^2.16.0: +is-core-module@^2.13.0, is-core-module@^2.15.1, is-core-module@^2.16.0: version "2.16.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== @@ -13144,20 +13097,13 @@ quick-temp@^0.1.8: rimraf "^2.5.4" underscore.string "~3.3.4" -randombytes@2.1.0, randombytes@^2.1.0: +randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo= sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==" dependencies: safe-buffer "^5.1.0" -randomstring@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/randomstring/-/randomstring-1.3.1.tgz#11a494a9d51b320dd8694a3e0ee7d77b0f8e477c" - integrity sha512-lgXZa80MUkjWdE7g2+PZ1xDLzc7/RokXVEQOv5NN2UOTChW1I8A9gha5a9xYBOqgaSoI6uJikDmCU8PyRdArRQ== - dependencies: - randombytes "2.1.0" - rate-limiter-flexible@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/rate-limiter-flexible/-/rate-limiter-flexible-2.4.2.tgz#2a219cc473f015142fd8fb599371223d730decbd" @@ -13690,16 +13636,7 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.0.tgz#c1a0028c2d166ec2fbf7d0644584927e76e7400e" integrity "sha1-waACjC0WbsL799BkRYSSfnbnQA4= sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg==" -resolve@^1.1.6, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.4: - version "1.22.4" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" - integrity "sha1-HcQN9GVUza+JSKSGoQ9roeICbDQ= sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==" - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^1.22.10: +resolve@^1.1.6, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.10, resolve@^1.22.4: version "1.22.10" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== @@ -15330,15 +15267,7 @@ upath@^1.2.0: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity "sha1-j2bbzVWog6za5ECK+LA1pQRMGJQ= sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" -update-browserslist-db@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz#97e9c96ab0ae7bcac08e9ae5151d26e6bc6b5580" - integrity sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg== - dependencies: - escalade "^3.2.0" - picocolors "^1.1.1" - -update-browserslist-db@^1.1.3: +update-browserslist-db@^1.1.1, update-browserslist-db@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==