From 9d6f03b076321f8f04fb19d44981af7d90ff1b3e Mon Sep 17 00:00:00 2001 From: zhongliang02 Date: Wed, 15 Jan 2025 07:12:01 +0800 Subject: [PATCH 1/8] feat: add allowedCharactersInPath whitelist --- packages/validators/package.json | 2 +- packages/validators/src/__tests__/url.test.ts | 131 +++++++++++++++++- packages/validators/src/url/index.ts | 3 +- packages/validators/src/url/options.ts | 17 ++- packages/validators/src/url/schema.ts | 56 +++++++- packages/validators/src/url/utils.ts | 72 +++++++--- 6 files changed, 245 insertions(+), 36 deletions(-) diff --git a/packages/validators/package.json b/packages/validators/package.json index e0a40d5..a595aef 100644 --- a/packages/validators/package.json +++ b/packages/validators/package.json @@ -1,6 +1,6 @@ { "name": "@opengovsg/starter-kitty-validators", - "version": "1.2.11", + "version": "1.2.12", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { diff --git a/packages/validators/src/__tests__/url.test.ts b/packages/validators/src/__tests__/url.test.ts index fb855fe..18cd89d 100644 --- a/packages/validators/src/__tests__/url.test.ts +++ b/packages/validators/src/__tests__/url.test.ts @@ -1,8 +1,10 @@ import { describe, expect, it } from 'vitest' +import { ZodError } from 'zod' import { OptionsError } from '@/common/errors' import { createUrlSchema, RelUrlValidator, UrlValidator } from '@/index' import { UrlValidationError } from '@/url/errors' +import { defaultAllowedChars } from '@/url/options' describe('UrlValidator with default options', () => { const validator = new UrlValidator() @@ -12,6 +14,11 @@ describe('UrlValidator with default options', () => { expect(url).toBeInstanceOf(URL) }) + it('should parse a valid URL', () => { + const url = validator.parse('https://example.com/path?query=1#hash') + expect(url).toBeInstanceOf(URL) + }) + it('should throw an error when the protocol is not http or https', () => { expect(() => validator.parse('ftp://example.com')).toThrow(UrlValidationError) }) @@ -30,10 +37,11 @@ describe('UrlValidator with default options', () => { expect(() => validator.parse('https://example.com/[[...slug]]')).toThrow(UrlValidationError) expect(() => validator.parse('https://example.com/[[slug]]')).toThrow(UrlValidationError) expect(() => validator.parse('https://example.com/[x]?x=1')).toThrow(UrlValidationError) + expect(() => validator.parse('https://example.com/path/(.)part')).toThrow(UrlValidationError) }) it('should prevent XSS attacks', () => { - expect(() => validator.parse('javascript&colonalert(/xss/)').protocol).toThrow(UrlValidationError) + expect(() => validator.parse('javascript&colonalert(/xss/)')).toThrow(UrlValidationError) expect(() => validator.parse('javascript:alert(/xss/)')).toThrow(UrlValidationError) }) @@ -47,19 +55,20 @@ describe('UrlValidator with default options', () => { describe('UrlValidator with custom protocol whitelist', () => { const validator = new UrlValidator({ whitelist: { - protocols: ['http', 'https', 'mailto'], + protocols: ['http', 'https'], + allowedCharactersInPath: '', // blank to allow all characters for tests }, }) it('should not throw an error when the protocol on the whitelist', () => { expect(() => validator.parse('https://example.com')).not.toThrow() expect(() => validator.parse('http://example.com')).not.toThrow() - expect(() => validator.parse('mailto:contact@example.com')).not.toThrow() }) it('should throw an error when the protocol is not on the whitelist', () => { expect(() => validator.parse('ftp://example.com')).toThrow(UrlValidationError) expect(() => validator.parse('javascript:alert()')).toThrow(UrlValidationError) + expect(() => validator.parse('mailto:contact@example.com')).toThrow(UrlValidationError) }) }) @@ -68,6 +77,7 @@ describe('UrlValidator with custom host whitelist', () => { whitelist: { protocols: ['http', 'https'], hosts: ['example.com'], + allowedCharactersInPath: '', // blank to allow all characters }, }) @@ -85,6 +95,7 @@ describe('UrlValidator with disallowHostnames', () => { whitelist: { protocols: ['http', 'https'], disallowHostnames: true, + allowedCharactersInPath: '', // blank to allow all characters for tests }, }) @@ -92,6 +103,11 @@ describe('UrlValidator with disallowHostnames', () => { expect(() => validator.parse('https://example.com')).not.toThrow() }) + it('should not throw an error with a proper domain', () => { + const url = validator.parse('https://example.com/path?query=1#hash') + expect(url).toBeInstanceOf(URL) + }) + it('should throw an error with a hostname', () => { expect(() => validator.parse('https://tld')).toThrow(UrlValidationError) expect(() => validator.parse('https://.tld')).toThrow(UrlValidationError) @@ -110,6 +126,7 @@ describe('UrlValidator with both hosts and disallowHostnames', () => { protocols: ['http', 'https'], hosts: ['example.com', 'localhost'], disallowHostnames: true, + allowedCharactersInPath: '', // blank to allow all characters for tests }, }) @@ -117,6 +134,11 @@ describe('UrlValidator with both hosts and disallowHostnames', () => { expect(() => validator.parse('https://example.com')).not.toThrow() }) + it('should not throw an error when the host is on the whitelist', () => { + const url = validator.parse('https://example.com/path?query=1#hash') + expect(url).toBeInstanceOf(URL) + }) + it('should ignore the disallowHostnames option', () => { expect(() => validator.parse('https://localhost')).not.toThrow() }) @@ -125,6 +147,10 @@ describe('UrlValidator with both hosts and disallowHostnames', () => { describe('UrlValidator with base URL', () => { const validator = new UrlValidator({ baseOrigin: 'https://example.com', + whitelist: { + protocols: ['http', 'https'], // default + allowedCharactersInPath: '', // blank to allow all characters for tests + }, }) it('should parse a valid relative URL', () => { @@ -161,6 +187,82 @@ describe('UrlValidator with base URL', () => { UrlValidationError, ) }) + + it('should not allow Next.js dynamic routes', () => { + expect(() => validator.parse('/[[x]]http:example.com/(.)[y]/?x&y')).toThrow(UrlValidationError) + }) +}) + +describe('UrlValidator with a whitelist of allowed characters in the path', () => { + const validator = new UrlValidator({ + whitelist: { + protocols: ['http', 'https'], + allowedCharactersInPath: 'abc123/', + }, + }) + it('should parse a valid URL', () => { + const url = validator.parse('https://example.com/abc123') + expect(url).toBeInstanceOf(URL) + }) + + it('should parse a valid URL with query string and hash', () => { + const url = validator.parse('https://example.com/abc123?q=1#hash') + expect(url).toBeInstanceOf(URL) + }) + + it('should throw an error when the path contains disallowed characters', () => { + expect(() => validator.parse('https://example.com/abc1234')).toThrow(UrlValidationError) + }) +}) + +describe('UrlValidator with the default whitelist', () => { + const validator = new UrlValidator({}) + + it('should parse a valid URL', () => { + const url = validator.parse('https://example.com') + expect(url).toBeInstanceOf(URL) + }) + + it('should parse a valid URL', () => { + const url = validator.parse('https://example.com/path?query=1#hash') + expect(url).toBeInstanceOf(URL) + }) + + it('should throw an error when the path contains disallowed characters', () => { + expect(() => validator.parse('https://example.com/1@23')).toThrow(UrlValidationError) + }) + + it('should throw an error when the protocol is not http or https', () => { + expect(() => validator.parse('ftp://example.com')).toThrow(UrlValidationError) + }) + + it('should allow any host when no host whitelist is provided', () => { + expect(() => validator.parse('https://open.gov.sg')).not.toThrow() + }) + + // https://url.spec.whatwg.org/#missing-scheme-non-relative-url + it('should throw an error when missing a scheme and no base URL or base URL', () => { + expect(() => validator.parse('example.com')).toThrow(UrlValidationError) + expect(() => validator.parse('/path')).toThrow(UrlValidationError) + }) + + it('should not allow Next.js dynamic routes', () => { + expect(() => validator.parse('https://example.com/[[...slug]]')).toThrow(UrlValidationError) + expect(() => validator.parse('https://example.com/[[slug]]')).toThrow(UrlValidationError) + expect(() => validator.parse('https://example.com/[x]?x=1')).toThrow(UrlValidationError) + expect(() => validator.parse('https://example.com/path/(.)part')).toThrow(UrlValidationError) + }) + + it('should prevent XSS attacks', () => { + expect(() => validator.parse('javascript&colonalert(/xss/)')).toThrow(UrlValidationError) + expect(() => validator.parse('javascript:alert(/xss/)')).toThrow(UrlValidationError) + }) + + it('should throw an error when given an invalid type', () => { + expect(() => validator.parse(123)).toThrow(UrlValidationError) + expect(() => validator.parse(undefined)).toThrow(UrlValidationError) + expect(() => validator.parse(['1', '2'])).toThrow(UrlValidationError) + }) }) describe('UrlValidator with invalid options', () => { @@ -185,6 +287,11 @@ describe('RelUrlValidator with string origin', () => { expect(url).toBeInstanceOf(URL) }) + it('should parse a valid absolute URL', () => { + const url = validator.parse('https://a.com/path?query=1#hash') + expect(url).toBeInstanceOf(URL) + }) + it('should throw an error on invalid URL', () => { expect(() => validator.parse('https://b.com/hello')).toThrow(UrlValidationError) }) @@ -251,6 +358,7 @@ describe('UrlValidatorOptions.parsePathname', () => { it('should throw an error when the path is a NextJS dynamic path', () => { expect(() => validator.parsePathname('https://a.com/hello/[id]?id=3')).toThrow(UrlValidationError) + expect(() => validator.parsePathname('https://a.com/hello/(.)bye')).toThrow(UrlValidationError) }) it('should fallback to fallbackUrl if it is provided', () => { @@ -271,7 +379,17 @@ describe('createUrlSchema', () => { protocols: ['http', 'https', 'mailto'], }, }) - expect(() => schema.parse('mailto:test@test.test')).not.toThrow() + expect(() => schema.parse('https://example.com')).not.toThrow() + }) + + it('should create a schema with custom options', () => { + const schema = createUrlSchema({ + whitelist: { + protocols: ['http', 'https', 'mailto'], + allowedCharactersInPath: defaultAllowedChars + '@', + }, + }) + expect(() => schema.parse('mailto:contact@example.com')).not.toThrow() }) it('should throw an error when the options are invalid', () => { @@ -287,13 +405,14 @@ describe('createUrlSchema', () => { protocols: ['http', 'https'], hosts: ['example.com'], disallowHostnames: true, + allowedCharactersInPath: defaultAllowedChars, }, }), ).not.toThrow() }) - it('should reject relaative URLs when the base URL is not provided', () => { + it('should reject relative URLs when the base URL is not provided', () => { const schema = createUrlSchema() - expect(() => schema.parse('/path')).toThrow(UrlValidationError) + expect(() => schema.parse('/path')).toThrow(ZodError) }) }) diff --git a/packages/validators/src/url/index.ts b/packages/validators/src/url/index.ts index f219d09..088b1ce 100644 --- a/packages/validators/src/url/index.ts +++ b/packages/validators/src/url/index.ts @@ -3,7 +3,7 @@ import { fromError } from 'zod-validation-error' import { OptionsError } from '@/common/errors' import { UrlValidationError } from '@/url/errors' -import { defaultOptions, optionsSchema, UrlValidatorOptions } from '@/url/options' +import { defaultAllowedChars, defaultOptions, optionsSchema, UrlValidatorOptions } from '@/url/options' import { toSchema } from '@/url/schema' /** @@ -128,6 +128,7 @@ export class RelUrlValidator extends UrlValidator { whitelist: { protocols: ['http', 'https'], hosts: [urlObject.host], + allowedCharactersInPath: defaultAllowedChars, }, }) } diff --git a/packages/validators/src/url/options.ts b/packages/validators/src/url/options.ts index e44961d..f863f5a 100644 --- a/packages/validators/src/url/options.ts +++ b/packages/validators/src/url/options.ts @@ -1,9 +1,16 @@ import { z } from 'zod' +export const lowercase = 'abcdefghijklmnopqrstuvwxyz' +export const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +export const digits = '0123456789' +export const alnum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' +export const defaultAllowedChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/' + export const defaultOptions = { whitelist: { protocols: ['http', 'https'], disallowHostnames: false, + allowedCharactersInPath: defaultAllowedChars, }, } @@ -28,6 +35,14 @@ export const whitelistSchema = z.object({ * @defaultValue false */ disallowHostnames: z.boolean().optional(), + /** + * Which characters are allowed in the URL path. + * Use empty string to allow all characters. + * If your protocol is mailto, you will need to include "\@" here. + * + * @defaultValue 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/' + */ + allowedCharactersInPath: z.string().optional().default(defaultAllowedChars), }) /** @@ -61,7 +76,7 @@ export interface UrlValidatorOptions { * * @public */ -export type UrlValidatorWhitelist = z.infer +export type UrlValidatorWhitelist = z.input export const optionsSchema = z.object({ baseOrigin: z diff --git a/packages/validators/src/url/schema.ts b/packages/validators/src/url/schema.ts index 5804d18..0aadaf2 100644 --- a/packages/validators/src/url/schema.ts +++ b/packages/validators/src/url/schema.ts @@ -1,13 +1,61 @@ import { z } from 'zod' import { ParsedUrlValidatorOptions } from '@/url/options' -import { isSafeUrl, resolveRelativeUrl } from '@/url/utils' +import { createAllowedCharsSchema, getErrorMessage, IS_NOT_HOSTNAME_REGEX, resolveRelativeUrl } from '@/url/utils' + +import { isDynamicRoute } from './nextjs-dynamic-route' export const toSchema = (options: ParsedUrlValidatorOptions) => { + const { whitelist } = options + + // create and cache this zod schema beforehand + const zAllowedCharsString = createAllowedCharsSchema(whitelist.allowedCharactersInPath) + return z .string() - .transform(url => resolveRelativeUrl(url, options.baseOrigin)) - .refine(url => isSafeUrl(url, options.whitelist), { - message: 'Unsafe URL', + .transform((url, ctx) => { + try { + return resolveRelativeUrl(url, options.baseOrigin) + } catch (error) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: getErrorMessage(error), + }) + return z.NEVER + } }) + .refine( + url => { + // only allow whitelisted protocols + if (!whitelist.protocols.some(protocol => url.protocol === `${protocol}:`)) { + return false + } + // only allow whitelisted characters in the path + const onlyHasAllowedChars = zAllowedCharsString.safeParse(url.pathname).success + if (!onlyHasAllowedChars) { + return false + } + + if (whitelist.hosts) { + // only allow whitelisted hosts + if (!whitelist.hosts.some(host => url.host === host)) { + return false + } + } else { + // no hosts provided + if (whitelist.disallowHostnames && !url.host.match(IS_NOT_HOSTNAME_REGEX)) { + return false + } + } + + // don't allow dynamic routes + if (isDynamicRoute(url)) { + return false + } + return true + }, + { + message: 'Unsafe URL', + }, + ) } diff --git a/packages/validators/src/url/utils.ts b/packages/validators/src/url/utils.ts index 1b85a29..aab6c7d 100644 --- a/packages/validators/src/url/utils.ts +++ b/packages/validators/src/url/utils.ts @@ -1,8 +1,45 @@ +import { z } from 'zod' + import { UrlValidationError } from '@/url/errors' -import { isDynamicRoute } from '@/url/nextjs-dynamic-route' -import { UrlValidatorWhitelist } from '@/url/options' -const IS_NOT_HOSTNAME_REGEX = /[^.]+\.[^.]+/g +/** + * Creates a Zod schema that validates a string to ensure all characters are within the allowed characters set. + * + * @param allowedChars - A string containing all allowed characters. If this is blank, the schema will always pass. + * @returns A Zod schema that validates a string to ensure all characters are within the allowed characters set. + * + * @example + * ```typescript + * const schema = createAllowedCharsSchema('abc123'); + * schema.parse('abc'); // Valid + * schema.parse('a1b2c3'); // Valid + * schema.parse('abcd'); // Throws an error + * ``` + */ +export const createAllowedCharsSchema = (allowedChars: string): z.ZodType => { + if (!allowedChars) { + return z.string() + } + const allowed = new Set(Array.from(allowedChars)) + + const schema = z.string().refine( + (str: string) => { + for (const char of str) { + if (!allowed.has(char)) { + return false + } + } + return true + }, + { + message: `Every character must be in ${allowedChars}`, + }, + ) + + return schema +} + +export const IS_NOT_HOSTNAME_REGEX = /[^.]+\.[^.]+/g export const resolveRelativeUrl = (url: string, baseOrigin?: URL): URL => { if (!baseOrigin) { @@ -26,26 +63,15 @@ export const resolveRelativeUrl = (url: string, baseOrigin?: URL): URL => { return normalizedUrl } -export const isSafeUrl = (url: URL, whitelist: UrlValidatorWhitelist) => { - // only allow whitelisted protocols - if (!whitelist.protocols.some(protocol => url.protocol === `${protocol}:`)) { - return false - } - if (whitelist.hosts) { - // only allow whitelisted hosts - if (!whitelist.hosts.some(host => url.host === host)) { - return false - } - } else { - // no hosts provided - if (whitelist.disallowHostnames && !url.host.match(IS_NOT_HOSTNAME_REGEX)) { - return false +export const getErrorMessage = (err: unknown): string => { + if (err instanceof Error) return err.message + if (typeof err === 'string') return err + if (err) { + try { + return JSON.stringify(err) + } catch { + return String(err) } } - - // don't allow dynamic routes - if (isDynamicRoute(url)) { - return false - } - return true + return 'Unknown error' } From 2251a6a77f8c07df38d69bedb03a55fb682c9c84 Mon Sep 17 00:00:00 2001 From: zhongliang02 Date: Wed, 15 Jan 2025 07:20:50 +0800 Subject: [PATCH 2/8] fix: dont allow urls with double slashes in pathname --- packages/validators/src/url/schema.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/validators/src/url/schema.ts b/packages/validators/src/url/schema.ts index 0aadaf2..8050591 100644 --- a/packages/validators/src/url/schema.ts +++ b/packages/validators/src/url/schema.ts @@ -48,6 +48,11 @@ export const toSchema = (options: ParsedUrlValidatorOptions) => { } } + // don't allow pathname with double slashes + if (url.pathname.replace(/\\/g, '/').startsWith('//')) { + return false + } + // don't allow dynamic routes if (isDynamicRoute(url)) { return false From b0e401f08a5cb85a74839ba882dd3c2e5376d468 Mon Sep 17 00:00:00 2001 From: zhongliang02 Date: Wed, 15 Jan 2025 07:25:50 +0800 Subject: [PATCH 3/8] fix: add tests for double slashes in pathname --- packages/validators/src/__tests__/url.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/validators/src/__tests__/url.test.ts b/packages/validators/src/__tests__/url.test.ts index 18cd89d..3317620 100644 --- a/packages/validators/src/__tests__/url.test.ts +++ b/packages/validators/src/__tests__/url.test.ts @@ -33,6 +33,13 @@ describe('UrlValidator with default options', () => { expect(() => validator.parse('/path')).toThrow(UrlValidationError) }) + it('should not allow double slashes in pathnames', () => { + expect(() => validator.parse('https://example.com//test')).toThrow(UrlValidationError) + expect(() => validator.parse('https://example.com\\\\test')).toThrow(UrlValidationError) + expect(() => validator.parse('https://example.com/\\test')).toThrow(UrlValidationError) + expect(() => validator.parse('https://example.com\\/test')).toThrow(UrlValidationError) + }) + it('should not allow Next.js dynamic routes', () => { expect(() => validator.parse('https://example.com/[[...slug]]')).toThrow(UrlValidationError) expect(() => validator.parse('https://example.com/[[slug]]')).toThrow(UrlValidationError) From b9a38e8394f9c4951f659800ba5a3afd4deb555b Mon Sep 17 00:00:00 2001 From: zhongliang02 Date: Wed, 15 Jan 2025 13:59:20 +0800 Subject: [PATCH 4/8] chore: pnpm audit --fix --- package.json | 11 + pnpm-lock.yaml | 651 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 517 insertions(+), 145 deletions(-) diff --git a/package.json b/package.json index a4607fa..f3cdbad 100644 --- a/package.json +++ b/package.json @@ -22,5 +22,16 @@ "packageManager": "pnpm@9.4.0", "engines": { "node": ">=18" + }, + "pnpm": { + "overrides": { + "braces@<3.0.3": ">=3.0.3", + "micromatch@<4.0.8": ">=4.0.8", + "vite@>=5.3.0 <5.3.6": ">=5.3.6", + "vite@>=5.3.0 <=5.3.5": ">=5.3.6", + "rollup@>=4.0.0 <4.22.4": ">=4.22.4", + "cross-spawn@>=7.0.0 <7.0.5": ">=7.0.5", + "nanoid@<3.3.8": ">=3.3.8" + } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 41c9c1e..62cf95e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,15 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + braces@<3.0.3: '>=3.0.3' + micromatch@<4.0.8: '>=4.0.8' + vite@>=5.3.0 <5.3.6: '>=5.3.6' + vite@>=5.3.0 <=5.3.5: '>=5.3.6' + rollup@>=4.0.0 <4.22.4: '>=4.22.4' + cross-spawn@>=7.0.0 <7.0.5: '>=7.0.5' + nanoid@<3.3.8: '>=3.3.8' + importers: .: @@ -28,7 +37,7 @@ importers: version: link:../../packages/validators vitepress: specifier: ^1.3.1 - version: 1.3.1(@algolia/client-search@4.24.0)(@types/node@18.19.47)(postcss@8.4.39)(search-insights@2.15.0)(typescript@5.4.5) + version: 1.3.1(@algolia/client-search@4.24.0)(@types/node@18.19.47)(postcss@8.5.1)(search-insights@2.15.0)(typescript@5.4.5)(yaml@2.4.5) vue: specifier: ~3.4.31 version: 3.4.33(typescript@5.4.5) @@ -46,7 +55,7 @@ importers: version: 8.57.0 eslint-config-opengovsg: specifier: ^3.0.0 - version: 3.0.0(@pulumi/eslint-plugin@0.2.0(eslint@8.57.0))(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint-plugin-import@2.30.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0))(eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.36.1(eslint@8.57.0))(eslint-plugin-simple-import-sort@10.0.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8) + version: 3.0.0(@pulumi/eslint-plugin@0.2.0(eslint@8.57.0))(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint-import-resolver-typescript@3.6.3)(eslint-plugin-import@2.30.0)(eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.36.1(eslint@8.57.0))(eslint-plugin-simple-import-sort@10.0.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8) eslint-config-prettier: specifier: ^8.6.0 version: 8.10.0(eslint@8.57.0) @@ -103,13 +112,13 @@ importers: version: 1.8.10 tsup: specifier: ^8.1.0 - version: 8.1.0(@swc/core@1.6.13)(postcss@8.4.39)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.47)(typescript@5.4.5))(typescript@5.4.5) + version: 8.1.0(@swc/core@1.6.13)(postcss@8.5.1)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.47)(typescript@5.4.5))(typescript@5.4.5) typescript: specifier: ^5.4.5 version: 5.4.5 vitest: specifier: ^2.0.2 - version: 2.0.2(@types/node@18.19.47) + version: 2.0.2(@types/node@18.19.47)(yaml@2.4.5) packages/validators: dependencies: @@ -140,13 +149,13 @@ importers: version: 1.8.10 tsup: specifier: ^8.1.0 - version: 8.1.0(@swc/core@1.6.13)(postcss@8.4.39)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.39)(typescript@5.4.5))(typescript@5.4.5) + version: 8.1.0(@swc/core@1.6.13)(postcss@8.5.1)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.39)(typescript@5.4.5))(typescript@5.4.5) typescript: specifier: ^5.4.5 version: 5.4.5 vitest: specifier: ^2.0.2 - version: 2.0.2(@types/node@18.19.39) + version: 2.0.2(@types/node@18.19.39)(yaml@2.4.5) packages: @@ -273,138 +282,288 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.24.2': + resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.21.5': resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.24.2': + resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.21.5': resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] + '@esbuild/android-arm@0.24.2': + resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.21.5': resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] + '@esbuild/android-x64@0.24.2': + resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.21.5': resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.24.2': + resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.21.5': resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.24.2': + resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.21.5': resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.24.2': + resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.21.5': resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.24.2': + resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.21.5': resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.24.2': + resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.21.5': resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.24.2': + resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.21.5': resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.24.2': + resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.21.5': resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.24.2': + resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.21.5': resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.24.2': + resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.21.5': resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.24.2': + resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.21.5': resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.24.2': + resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.21.5': resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.24.2': + resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.21.5': resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.24.2': + resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.24.2': + resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.21.5': resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.24.2': + resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.24.2': + resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.21.5': resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.24.2': + resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/sunos-x64@0.21.5': resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.24.2': + resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.21.5': resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.24.2': + resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.21.5': resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.24.2': + resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.21.5': resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.24.2': + resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -519,83 +678,98 @@ packages: '@pulumi/eslint-plugin@0.2.0': resolution: {integrity: sha512-tb2Wo1pO8kmNIt+ECkVd7ykRHgadFJfddjLG8Of002X+qbRkNZNttdt55o7EdCDHGB6Dn1RFo/MJYNuHjYn/Dg==} - '@rollup/rollup-android-arm-eabi@4.18.1': - resolution: {integrity: sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==} + '@rollup/rollup-android-arm-eabi@4.30.1': + resolution: {integrity: sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.18.1': - resolution: {integrity: sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==} + '@rollup/rollup-android-arm64@4.30.1': + resolution: {integrity: sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.18.1': - resolution: {integrity: sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==} + '@rollup/rollup-darwin-arm64@4.30.1': + resolution: {integrity: sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.18.1': - resolution: {integrity: sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==} + '@rollup/rollup-darwin-x64@4.30.1': + resolution: {integrity: sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.18.1': - resolution: {integrity: sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==} + '@rollup/rollup-freebsd-arm64@4.30.1': + resolution: {integrity: sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.30.1': + resolution: {integrity: sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.30.1': + resolution: {integrity: sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.18.1': - resolution: {integrity: sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==} + '@rollup/rollup-linux-arm-musleabihf@4.30.1': + resolution: {integrity: sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.18.1': - resolution: {integrity: sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==} + '@rollup/rollup-linux-arm64-gnu@4.30.1': + resolution: {integrity: sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.18.1': - resolution: {integrity: sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==} + '@rollup/rollup-linux-arm64-musl@4.30.1': + resolution: {integrity: sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.18.1': - resolution: {integrity: sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==} + '@rollup/rollup-linux-loongarch64-gnu@4.30.1': + resolution: {integrity: sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.30.1': + resolution: {integrity: sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.18.1': - resolution: {integrity: sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==} + '@rollup/rollup-linux-riscv64-gnu@4.30.1': + resolution: {integrity: sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.18.1': - resolution: {integrity: sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==} + '@rollup/rollup-linux-s390x-gnu@4.30.1': + resolution: {integrity: sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.18.1': - resolution: {integrity: sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==} + '@rollup/rollup-linux-x64-gnu@4.30.1': + resolution: {integrity: sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.18.1': - resolution: {integrity: sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==} + '@rollup/rollup-linux-x64-musl@4.30.1': + resolution: {integrity: sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.18.1': - resolution: {integrity: sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==} + '@rollup/rollup-win32-arm64-msvc@4.30.1': + resolution: {integrity: sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.18.1': - resolution: {integrity: sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==} + '@rollup/rollup-win32-ia32-msvc@4.30.1': + resolution: {integrity: sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.18.1': - resolution: {integrity: sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==} + '@rollup/rollup-win32-x64-msvc@4.30.1': + resolution: {integrity: sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==} cpu: [x64] os: [win32] @@ -698,6 +872,9 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} @@ -833,7 +1010,7 @@ packages: resolution: {integrity: sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: - vite: ^5.0.0 + vite: '>=5.3.6' vue: ^3.2.25 '@vitest/expect@2.0.2': @@ -1054,8 +1231,8 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} bundle-require@4.2.1: @@ -1117,8 +1294,8 @@ packages: create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} csstype@3.1.3: @@ -1249,6 +1426,11 @@ packages: engines: {node: '>=12'} hasBin: true + esbuild@0.24.2: + resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} + engines: {node: '>=18'} + hasBin: true + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -1435,8 +1617,8 @@ packages: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} find-up@5.0.0: @@ -1832,8 +2014,8 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} mimic-fn@2.1.0: @@ -1874,11 +2056,16 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@5.0.9: + resolution: {integrity: sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==} + engines: {node: ^18 || >=20} + hasBin: true + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -1993,6 +2180,9 @@ packages: picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -2025,6 +2215,10 @@ packages: resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.1: + resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==} + engines: {node: ^10 || ^12 || >=14} + preact@10.22.1: resolution: {integrity: sha512-jRYbDDgMpIb5LHq3hkI0bbl+l/TQ9UnkdQ0ww+lp+4MMOdqaUYdFc5qeyP+IV8FAd/2Em7drVPeKdQxsiWCf/A==} @@ -2110,8 +2304,8 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rollup@4.18.1: - resolution: {integrity: sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==} + rollup@4.30.1: + resolution: {integrity: sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2179,6 +2373,10 @@ packages: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} @@ -2465,33 +2663,45 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite@5.3.3: - resolution: {integrity: sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==} - engines: {node: ^18.0.0 || >=20.0.0} + vite@6.0.7: + resolution: {integrity: sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' less: '*' lightningcss: ^1.21.0 sass: '*' + sass-embedded: '*' stylus: '*' sugarss: '*' - terser: ^5.4.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 peerDependenciesMeta: '@types/node': optional: true + jiti: + optional: true less: optional: true lightningcss: optional: true sass: optional: true + sass-embedded: + optional: true stylus: optional: true sugarss: optional: true terser: optional: true + tsx: + optional: true + yaml: + optional: true vitepress@1.3.1: resolution: {integrity: sha512-soZDpg2rRVJNIM/IYMNDPPr+zTHDA5RbLDHAxacRu+Q9iZ2GwSR0QSUlLs+aEZTkG0SOX1dc8RmUYwyuxK8dfQ==} @@ -2772,72 +2982,147 @@ snapshots: '@esbuild/aix-ppc64@0.21.5': optional: true + '@esbuild/aix-ppc64@0.24.2': + optional: true + '@esbuild/android-arm64@0.21.5': optional: true + '@esbuild/android-arm64@0.24.2': + optional: true + '@esbuild/android-arm@0.21.5': optional: true + '@esbuild/android-arm@0.24.2': + optional: true + '@esbuild/android-x64@0.21.5': optional: true + '@esbuild/android-x64@0.24.2': + optional: true + '@esbuild/darwin-arm64@0.21.5': optional: true + '@esbuild/darwin-arm64@0.24.2': + optional: true + '@esbuild/darwin-x64@0.21.5': optional: true + '@esbuild/darwin-x64@0.24.2': + optional: true + '@esbuild/freebsd-arm64@0.21.5': optional: true + '@esbuild/freebsd-arm64@0.24.2': + optional: true + '@esbuild/freebsd-x64@0.21.5': optional: true + '@esbuild/freebsd-x64@0.24.2': + optional: true + '@esbuild/linux-arm64@0.21.5': optional: true + '@esbuild/linux-arm64@0.24.2': + optional: true + '@esbuild/linux-arm@0.21.5': optional: true + '@esbuild/linux-arm@0.24.2': + optional: true + '@esbuild/linux-ia32@0.21.5': optional: true + '@esbuild/linux-ia32@0.24.2': + optional: true + '@esbuild/linux-loong64@0.21.5': optional: true + '@esbuild/linux-loong64@0.24.2': + optional: true + '@esbuild/linux-mips64el@0.21.5': optional: true + '@esbuild/linux-mips64el@0.24.2': + optional: true + '@esbuild/linux-ppc64@0.21.5': optional: true + '@esbuild/linux-ppc64@0.24.2': + optional: true + '@esbuild/linux-riscv64@0.21.5': optional: true + '@esbuild/linux-riscv64@0.24.2': + optional: true + '@esbuild/linux-s390x@0.21.5': optional: true + '@esbuild/linux-s390x@0.24.2': + optional: true + '@esbuild/linux-x64@0.21.5': optional: true + '@esbuild/linux-x64@0.24.2': + optional: true + + '@esbuild/netbsd-arm64@0.24.2': + optional: true + '@esbuild/netbsd-x64@0.21.5': optional: true + '@esbuild/netbsd-x64@0.24.2': + optional: true + + '@esbuild/openbsd-arm64@0.24.2': + optional: true + '@esbuild/openbsd-x64@0.21.5': optional: true + '@esbuild/openbsd-x64@0.24.2': + optional: true + '@esbuild/sunos-x64@0.21.5': optional: true + '@esbuild/sunos-x64@0.24.2': + optional: true + '@esbuild/win32-arm64@0.21.5': optional: true + '@esbuild/win32-arm64@0.24.2': + optional: true + '@esbuild/win32-ia32@0.21.5': optional: true + '@esbuild/win32-ia32@0.24.2': + optional: true + '@esbuild/win32-x64@0.21.5': optional: true + '@esbuild/win32-x64@0.24.2': + optional: true + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': dependencies: eslint: 8.57.0 @@ -2971,52 +3256,61 @@ snapshots: - eslint - supports-color - '@rollup/rollup-android-arm-eabi@4.18.1': + '@rollup/rollup-android-arm-eabi@4.30.1': + optional: true + + '@rollup/rollup-android-arm64@4.30.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.30.1': optional: true - '@rollup/rollup-android-arm64@4.18.1': + '@rollup/rollup-darwin-x64@4.30.1': optional: true - '@rollup/rollup-darwin-arm64@4.18.1': + '@rollup/rollup-freebsd-arm64@4.30.1': optional: true - '@rollup/rollup-darwin-x64@4.18.1': + '@rollup/rollup-freebsd-x64@4.30.1': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.18.1': + '@rollup/rollup-linux-arm-gnueabihf@4.30.1': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.18.1': + '@rollup/rollup-linux-arm-musleabihf@4.30.1': optional: true - '@rollup/rollup-linux-arm64-gnu@4.18.1': + '@rollup/rollup-linux-arm64-gnu@4.30.1': optional: true - '@rollup/rollup-linux-arm64-musl@4.18.1': + '@rollup/rollup-linux-arm64-musl@4.30.1': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.18.1': + '@rollup/rollup-linux-loongarch64-gnu@4.30.1': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.18.1': + '@rollup/rollup-linux-powerpc64le-gnu@4.30.1': optional: true - '@rollup/rollup-linux-s390x-gnu@4.18.1': + '@rollup/rollup-linux-riscv64-gnu@4.30.1': optional: true - '@rollup/rollup-linux-x64-gnu@4.18.1': + '@rollup/rollup-linux-s390x-gnu@4.30.1': optional: true - '@rollup/rollup-linux-x64-musl@4.18.1': + '@rollup/rollup-linux-x64-gnu@4.30.1': optional: true - '@rollup/rollup-win32-arm64-msvc@4.18.1': + '@rollup/rollup-linux-x64-musl@4.30.1': optional: true - '@rollup/rollup-win32-ia32-msvc@4.18.1': + '@rollup/rollup-win32-arm64-msvc@4.30.1': optional: true - '@rollup/rollup-win32-x64-msvc@4.18.1': + '@rollup/rollup-win32-ia32-msvc@4.30.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.30.1': optional: true '@rtsao/scc@1.1.0': {} @@ -3095,6 +3389,8 @@ snapshots: '@types/estree@1.0.5': {} + '@types/estree@1.0.6': {} + '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.2 @@ -3267,9 +3563,9 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-vue@5.0.5(vite@5.3.3(@types/node@18.19.47))(vue@3.4.33(typescript@5.4.5))': + '@vitejs/plugin-vue@5.0.5(vite@6.0.7(@types/node@18.19.47)(yaml@2.4.5))(vue@3.4.33(typescript@5.4.5))': dependencies: - vite: 5.3.3(@types/node@18.19.47) + vite: 6.0.7(@types/node@18.19.47)(yaml@2.4.5) vue: 3.4.33(typescript@5.4.5) '@vitest/expect@2.0.2': @@ -3558,9 +3854,9 @@ snapshots: dependencies: balanced-match: 1.0.2 - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 bundle-require@4.2.1(esbuild@0.21.5): dependencies: @@ -3597,7 +3893,7 @@ snapshots: chokidar@3.6.0: dependencies: anymatch: 3.1.3 - braces: 3.0.2 + braces: 3.0.3 glob-parent: 5.1.2 is-binary-path: 2.1.0 is-glob: 4.0.3 @@ -3625,7 +3921,7 @@ snapshots: create-require@1.1.1: optional: true - cross-spawn@7.0.3: + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 @@ -3827,9 +4123,37 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 + esbuild@0.24.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.2 + '@esbuild/android-arm': 0.24.2 + '@esbuild/android-arm64': 0.24.2 + '@esbuild/android-x64': 0.24.2 + '@esbuild/darwin-arm64': 0.24.2 + '@esbuild/darwin-x64': 0.24.2 + '@esbuild/freebsd-arm64': 0.24.2 + '@esbuild/freebsd-x64': 0.24.2 + '@esbuild/linux-arm': 0.24.2 + '@esbuild/linux-arm64': 0.24.2 + '@esbuild/linux-ia32': 0.24.2 + '@esbuild/linux-loong64': 0.24.2 + '@esbuild/linux-mips64el': 0.24.2 + '@esbuild/linux-ppc64': 0.24.2 + '@esbuild/linux-riscv64': 0.24.2 + '@esbuild/linux-s390x': 0.24.2 + '@esbuild/linux-x64': 0.24.2 + '@esbuild/netbsd-arm64': 0.24.2 + '@esbuild/netbsd-x64': 0.24.2 + '@esbuild/openbsd-arm64': 0.24.2 + '@esbuild/openbsd-x64': 0.24.2 + '@esbuild/sunos-x64': 0.24.2 + '@esbuild/win32-arm64': 0.24.2 + '@esbuild/win32-ia32': 0.24.2 + '@esbuild/win32-x64': 0.24.2 + escape-string-regexp@4.0.0: {} - eslint-config-opengovsg@3.0.0(@pulumi/eslint-plugin@0.2.0(eslint@8.57.0))(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint-plugin-import@2.30.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0))(eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.36.1(eslint@8.57.0))(eslint-plugin-simple-import-sort@10.0.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8): + eslint-config-opengovsg@3.0.0(@pulumi/eslint-plugin@0.2.0(eslint@8.57.0))(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint-import-resolver-typescript@3.6.3)(eslint-plugin-import@2.30.0)(eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.36.1(eslint@8.57.0))(eslint-plugin-simple-import-sort@10.0.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8): dependencies: '@pulumi/eslint-plugin': 0.2.0(eslint@8.57.0) '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) @@ -3861,7 +4185,7 @@ snapshots: debug: 4.3.5 enhanced-resolve: 5.17.1 eslint: 8.57.0 - eslint-module-utils: 2.11.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.11.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 @@ -3874,7 +4198,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.11.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.11.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: @@ -3896,7 +4220,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.11.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.11.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -3980,7 +4304,7 @@ snapshots: '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 debug: 4.3.5 doctrine: 3.0.0 escape-string-regexp: 4.0.0 @@ -4039,7 +4363,7 @@ snapshots: execa@5.1.1: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 get-stream: 6.0.1 human-signals: 2.1.0 is-stream: 2.0.1 @@ -4051,7 +4375,7 @@ snapshots: execa@8.0.1: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 get-stream: 8.0.1 human-signals: 5.0.0 is-stream: 3.0.0 @@ -4071,7 +4395,7 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.8 fast-glob@3.3.2: dependencies: @@ -4079,7 +4403,7 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.8 fast-json-stable-stringify@2.1.0: {} @@ -4093,7 +4417,7 @@ snapshots: dependencies: flat-cache: 3.2.0 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -4120,7 +4444,7 @@ snapshots: foreground-child@3.1.1: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 signal-exit: 4.1.0 fs.realpath@1.0.0: {} @@ -4472,9 +4796,9 @@ snapshots: merge2@1.4.1: {} - micromatch@4.0.5: + micromatch@4.0.8: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 mimic-fn@2.1.0: {} @@ -4507,7 +4831,9 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nanoid@3.3.7: {} + nanoid@3.3.8: {} + + nanoid@5.0.9: {} natural-compare@1.4.0: {} @@ -4617,6 +4943,8 @@ snapshots: picocolors@1.0.1: {} + picocolors@1.1.1: {} + picomatch@2.3.1: {} pirates@4.0.6: {} @@ -4627,28 +4955,34 @@ snapshots: possible-typed-array-names@1.0.0: {} - postcss-load-config@4.0.2(postcss@8.4.39)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.39)(typescript@5.4.5)): + postcss-load-config@4.0.2(postcss@8.5.1)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.39)(typescript@5.4.5)): dependencies: lilconfig: 3.1.2 yaml: 2.4.5 optionalDependencies: - postcss: 8.4.39 + postcss: 8.5.1 ts-node: 10.9.1(@swc/core@1.6.13)(@types/node@18.19.39)(typescript@5.4.5) - postcss-load-config@4.0.2(postcss@8.4.39)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.47)(typescript@5.4.5)): + postcss-load-config@4.0.2(postcss@8.5.1)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.47)(typescript@5.4.5)): dependencies: lilconfig: 3.1.2 yaml: 2.4.5 optionalDependencies: - postcss: 8.4.39 + postcss: 8.5.1 ts-node: 10.9.1(@swc/core@1.6.13)(@types/node@18.19.47)(typescript@5.4.5) postcss@8.4.39: dependencies: - nanoid: 3.3.7 + nanoid: 5.0.9 picocolors: 1.0.1 source-map-js: 1.2.0 + postcss@8.5.1: + dependencies: + nanoid: 3.3.8 + picocolors: 1.1.1 + source-map-js: 1.2.1 + preact@10.22.1: {} prelude-ls@1.2.1: {} @@ -4724,26 +5058,29 @@ snapshots: dependencies: glob: 7.2.3 - rollup@4.18.1: + rollup@4.30.1: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.18.1 - '@rollup/rollup-android-arm64': 4.18.1 - '@rollup/rollup-darwin-arm64': 4.18.1 - '@rollup/rollup-darwin-x64': 4.18.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.18.1 - '@rollup/rollup-linux-arm-musleabihf': 4.18.1 - '@rollup/rollup-linux-arm64-gnu': 4.18.1 - '@rollup/rollup-linux-arm64-musl': 4.18.1 - '@rollup/rollup-linux-powerpc64le-gnu': 4.18.1 - '@rollup/rollup-linux-riscv64-gnu': 4.18.1 - '@rollup/rollup-linux-s390x-gnu': 4.18.1 - '@rollup/rollup-linux-x64-gnu': 4.18.1 - '@rollup/rollup-linux-x64-musl': 4.18.1 - '@rollup/rollup-win32-arm64-msvc': 4.18.1 - '@rollup/rollup-win32-ia32-msvc': 4.18.1 - '@rollup/rollup-win32-x64-msvc': 4.18.1 + '@rollup/rollup-android-arm-eabi': 4.30.1 + '@rollup/rollup-android-arm64': 4.30.1 + '@rollup/rollup-darwin-arm64': 4.30.1 + '@rollup/rollup-darwin-x64': 4.30.1 + '@rollup/rollup-freebsd-arm64': 4.30.1 + '@rollup/rollup-freebsd-x64': 4.30.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.30.1 + '@rollup/rollup-linux-arm-musleabihf': 4.30.1 + '@rollup/rollup-linux-arm64-gnu': 4.30.1 + '@rollup/rollup-linux-arm64-musl': 4.30.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.30.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.30.1 + '@rollup/rollup-linux-riscv64-gnu': 4.30.1 + '@rollup/rollup-linux-s390x-gnu': 4.30.1 + '@rollup/rollup-linux-x64-gnu': 4.30.1 + '@rollup/rollup-linux-x64-musl': 4.30.1 + '@rollup/rollup-win32-arm64-msvc': 4.30.1 + '@rollup/rollup-win32-ia32-msvc': 4.30.1 + '@rollup/rollup-win32-x64-msvc': 4.30.1 fsevents: 2.3.3 run-parallel@1.2.0: @@ -4813,6 +5150,8 @@ snapshots: source-map-js@1.2.0: {} + source-map-js@1.2.1: {} + source-map@0.8.0-beta.0: dependencies: whatwg-url: 7.1.0 @@ -5020,7 +5359,7 @@ snapshots: tslib@2.7.0: {} - tsup@8.1.0(@swc/core@1.6.13)(postcss@8.4.39)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.39)(typescript@5.4.5))(typescript@5.4.5): + tsup@8.1.0(@swc/core@1.6.13)(postcss@8.5.1)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.39)(typescript@5.4.5))(typescript@5.4.5): dependencies: bundle-require: 4.2.1(esbuild@0.21.5) cac: 6.7.14 @@ -5030,21 +5369,21 @@ snapshots: execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.2(postcss@8.4.39)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.39)(typescript@5.4.5)) + postcss-load-config: 4.0.2(postcss@8.5.1)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.39)(typescript@5.4.5)) resolve-from: 5.0.0 - rollup: 4.18.1 + rollup: 4.30.1 source-map: 0.8.0-beta.0 sucrase: 3.35.0 tree-kill: 1.2.2 optionalDependencies: '@swc/core': 1.6.13 - postcss: 8.4.39 + postcss: 8.5.1 typescript: 5.4.5 transitivePeerDependencies: - supports-color - ts-node - tsup@8.1.0(@swc/core@1.6.13)(postcss@8.4.39)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.47)(typescript@5.4.5))(typescript@5.4.5): + tsup@8.1.0(@swc/core@1.6.13)(postcss@8.5.1)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.47)(typescript@5.4.5))(typescript@5.4.5): dependencies: bundle-require: 4.2.1(esbuild@0.21.5) cac: 6.7.14 @@ -5054,15 +5393,15 @@ snapshots: execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.2(postcss@8.4.39)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.47)(typescript@5.4.5)) + postcss-load-config: 4.0.2(postcss@8.5.1)(ts-node@10.9.1(@swc/core@1.6.13)(@types/node@18.19.47)(typescript@5.4.5)) resolve-from: 5.0.0 - rollup: 4.18.1 + rollup: 4.30.1 source-map: 0.8.0-beta.0 sucrase: 3.35.0 tree-kill: 1.2.2 optionalDependencies: '@swc/core': 1.6.13 - postcss: 8.4.39 + postcss: 8.5.1 typescript: 5.4.5 transitivePeerDependencies: - supports-color @@ -5158,66 +5497,76 @@ snapshots: v8-compile-cache-lib@3.0.1: optional: true - vite-node@2.0.2(@types/node@18.19.39): + vite-node@2.0.2(@types/node@18.19.39)(yaml@2.4.5): dependencies: cac: 6.7.14 debug: 4.3.5 pathe: 1.1.2 tinyrainbow: 1.2.0 - vite: 5.3.3(@types/node@18.19.39) + vite: 6.0.7(@types/node@18.19.39)(yaml@2.4.5) transitivePeerDependencies: - '@types/node' + - jiti - less - lightningcss - sass + - sass-embedded - stylus - sugarss - supports-color - terser + - tsx + - yaml - vite-node@2.0.2(@types/node@18.19.47): + vite-node@2.0.2(@types/node@18.19.47)(yaml@2.4.5): dependencies: cac: 6.7.14 debug: 4.3.5 pathe: 1.1.2 tinyrainbow: 1.2.0 - vite: 5.3.3(@types/node@18.19.47) + vite: 6.0.7(@types/node@18.19.47)(yaml@2.4.5) transitivePeerDependencies: - '@types/node' + - jiti - less - lightningcss - sass + - sass-embedded - stylus - sugarss - supports-color - terser + - tsx + - yaml - vite@5.3.3(@types/node@18.19.39): + vite@6.0.7(@types/node@18.19.39)(yaml@2.4.5): dependencies: - esbuild: 0.21.5 - postcss: 8.4.39 - rollup: 4.18.1 + esbuild: 0.24.2 + postcss: 8.5.1 + rollup: 4.30.1 optionalDependencies: '@types/node': 18.19.39 fsevents: 2.3.3 + yaml: 2.4.5 - vite@5.3.3(@types/node@18.19.47): + vite@6.0.7(@types/node@18.19.47)(yaml@2.4.5): dependencies: - esbuild: 0.21.5 - postcss: 8.4.39 - rollup: 4.18.1 + esbuild: 0.24.2 + postcss: 8.5.1 + rollup: 4.30.1 optionalDependencies: '@types/node': 18.19.47 fsevents: 2.3.3 + yaml: 2.4.5 - vitepress@1.3.1(@algolia/client-search@4.24.0)(@types/node@18.19.47)(postcss@8.4.39)(search-insights@2.15.0)(typescript@5.4.5): + vitepress@1.3.1(@algolia/client-search@4.24.0)(@types/node@18.19.47)(postcss@8.5.1)(search-insights@2.15.0)(typescript@5.4.5)(yaml@2.4.5): dependencies: '@docsearch/css': 3.6.1 '@docsearch/js': 3.6.1(@algolia/client-search@4.24.0)(search-insights@2.15.0) '@shikijs/core': 1.11.0 '@shikijs/transformers': 1.11.0 '@types/markdown-it': 14.1.1 - '@vitejs/plugin-vue': 5.0.5(vite@5.3.3(@types/node@18.19.47))(vue@3.4.33(typescript@5.4.5)) + '@vitejs/plugin-vue': 5.0.5(vite@6.0.7(@types/node@18.19.47)(yaml@2.4.5))(vue@3.4.33(typescript@5.4.5)) '@vue/devtools-api': 7.3.6 '@vue/shared': 3.4.33 '@vueuse/core': 10.11.0(vue@3.4.33(typescript@5.4.5)) @@ -5226,10 +5575,10 @@ snapshots: mark.js: 8.11.1 minisearch: 7.0.2 shiki: 1.11.0 - vite: 5.3.3(@types/node@18.19.47) + vite: 6.0.7(@types/node@18.19.47)(yaml@2.4.5) vue: 3.4.33(typescript@5.4.5) optionalDependencies: - postcss: 8.4.39 + postcss: 8.5.1 transitivePeerDependencies: - '@algolia/client-search' - '@types/node' @@ -5241,6 +5590,7 @@ snapshots: - drauu - fuse.js - idb-keyval + - jiti - jwt-decode - less - lightningcss @@ -5249,15 +5599,18 @@ snapshots: - react - react-dom - sass + - sass-embedded - search-insights - sortablejs - stylus - sugarss - terser + - tsx - typescript - universal-cookie + - yaml - vitest@2.0.2(@types/node@18.19.39): + vitest@2.0.2(@types/node@18.19.39)(yaml@2.4.5): dependencies: '@ampproject/remapping': 2.3.0 '@vitest/expect': 2.0.2 @@ -5275,21 +5628,25 @@ snapshots: tinybench: 2.8.0 tinypool: 1.0.0 tinyrainbow: 1.2.0 - vite: 5.3.3(@types/node@18.19.39) - vite-node: 2.0.2(@types/node@18.19.39) + vite: 6.0.7(@types/node@18.19.39)(yaml@2.4.5) + vite-node: 2.0.2(@types/node@18.19.39)(yaml@2.4.5) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 18.19.39 transitivePeerDependencies: + - jiti - less - lightningcss - sass + - sass-embedded - stylus - sugarss - supports-color - terser + - tsx + - yaml - vitest@2.0.2(@types/node@18.19.47): + vitest@2.0.2(@types/node@18.19.47)(yaml@2.4.5): dependencies: '@ampproject/remapping': 2.3.0 '@vitest/expect': 2.0.2 @@ -5307,19 +5664,23 @@ snapshots: tinybench: 2.8.0 tinypool: 1.0.0 tinyrainbow: 1.2.0 - vite: 5.3.3(@types/node@18.19.47) - vite-node: 2.0.2(@types/node@18.19.47) + vite: 6.0.7(@types/node@18.19.47)(yaml@2.4.5) + vite-node: 2.0.2(@types/node@18.19.47)(yaml@2.4.5) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 18.19.47 transitivePeerDependencies: + - jiti - less - lightningcss - sass + - sass-embedded - stylus - sugarss - supports-color - terser + - tsx + - yaml vue-demi@0.14.8(vue@3.4.33(typescript@5.4.5)): dependencies: From 6624d79a8ea0ee6999e445980bd8e95352a28b61 Mon Sep 17 00:00:00 2001 From: zhongliang02 Date: Wed, 15 Jan 2025 16:42:13 +0800 Subject: [PATCH 5/8] chore: add default(false) for disallowHostnames Co-authored-by: Eugene Lim --- packages/validators/src/url/options.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/validators/src/url/options.ts b/packages/validators/src/url/options.ts index f863f5a..0f99668 100644 --- a/packages/validators/src/url/options.ts +++ b/packages/validators/src/url/options.ts @@ -34,7 +34,7 @@ export const whitelistSchema = z.object({ * * @defaultValue false */ - disallowHostnames: z.boolean().optional(), + disallowHostnames: z.boolean().optional().default(false), /** * Which characters are allowed in the URL path. * Use empty string to allow all characters. From 4c2014b60edf1c24322b08135dd09e4d96609aab Mon Sep 17 00:00:00 2001 From: zhongliang02 Date: Wed, 15 Jan 2025 16:54:31 +0800 Subject: [PATCH 6/8] chore: removed .optional() from whitelistSchema members --- packages/validators/src/url/options.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/validators/src/url/options.ts b/packages/validators/src/url/options.ts index 0f99668..10dffcb 100644 --- a/packages/validators/src/url/options.ts +++ b/packages/validators/src/url/options.ts @@ -34,7 +34,7 @@ export const whitelistSchema = z.object({ * * @defaultValue false */ - disallowHostnames: z.boolean().optional().default(false), + disallowHostnames: z.boolean().default(false), /** * Which characters are allowed in the URL path. * Use empty string to allow all characters. @@ -42,7 +42,7 @@ export const whitelistSchema = z.object({ * * @defaultValue 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/' */ - allowedCharactersInPath: z.string().optional().default(defaultAllowedChars), + allowedCharactersInPath: z.string().default(defaultAllowedChars), }) /** From 40e7672e6e2db17fa663db384264f7f60a65b549 Mon Sep 17 00:00:00 2001 From: zhongliang02 Date: Wed, 15 Jan 2025 17:12:48 +0800 Subject: [PATCH 7/8] feat: move to regex validation of path instead of by characters --- packages/validators/src/__tests__/url.test.ts | 26 ++++++------- packages/validators/src/url/index.ts | 4 +- packages/validators/src/url/options.ts | 16 +++----- packages/validators/src/url/schema.ts | 10 ++--- packages/validators/src/url/utils.ts | 39 ------------------- 5 files changed, 24 insertions(+), 71 deletions(-) diff --git a/packages/validators/src/__tests__/url.test.ts b/packages/validators/src/__tests__/url.test.ts index 3317620..04b2e99 100644 --- a/packages/validators/src/__tests__/url.test.ts +++ b/packages/validators/src/__tests__/url.test.ts @@ -4,7 +4,7 @@ import { ZodError } from 'zod' import { OptionsError } from '@/common/errors' import { createUrlSchema, RelUrlValidator, UrlValidator } from '@/index' import { UrlValidationError } from '@/url/errors' -import { defaultAllowedChars } from '@/url/options' +import { defaultValidPathRegex } from '@/url/options' describe('UrlValidator with default options', () => { const validator = new UrlValidator() @@ -63,7 +63,7 @@ describe('UrlValidator with custom protocol whitelist', () => { const validator = new UrlValidator({ whitelist: { protocols: ['http', 'https'], - allowedCharactersInPath: '', // blank to allow all characters for tests + validPathRegex: /.*/, // allow all characters for tests }, }) @@ -84,7 +84,7 @@ describe('UrlValidator with custom host whitelist', () => { whitelist: { protocols: ['http', 'https'], hosts: ['example.com'], - allowedCharactersInPath: '', // blank to allow all characters + validPathRegex: /.*/, // allow all characters for tests }, }) @@ -102,7 +102,7 @@ describe('UrlValidator with disallowHostnames', () => { whitelist: { protocols: ['http', 'https'], disallowHostnames: true, - allowedCharactersInPath: '', // blank to allow all characters for tests + validPathRegex: /.*/, // allow all characters for tests }, }) @@ -133,7 +133,7 @@ describe('UrlValidator with both hosts and disallowHostnames', () => { protocols: ['http', 'https'], hosts: ['example.com', 'localhost'], disallowHostnames: true, - allowedCharactersInPath: '', // blank to allow all characters for tests + validPathRegex: /.*/, // allow all characters for tests }, }) @@ -156,7 +156,7 @@ describe('UrlValidator with base URL', () => { baseOrigin: 'https://example.com', whitelist: { protocols: ['http', 'https'], // default - allowedCharactersInPath: '', // blank to allow all characters for tests + validPathRegex: /.*/, // allow all characters for tests }, }) @@ -200,11 +200,11 @@ describe('UrlValidator with base URL', () => { }) }) -describe('UrlValidator with a whitelist of allowed characters in the path', () => { +describe('UrlValidator with valid path regex', () => { const validator = new UrlValidator({ whitelist: { protocols: ['http', 'https'], - allowedCharactersInPath: 'abc123/', + validPathRegex: /^[abc123/]*$/, }, }) it('should parse a valid URL', () => { @@ -217,12 +217,12 @@ describe('UrlValidator with a whitelist of allowed characters in the path', () = expect(url).toBeInstanceOf(URL) }) - it('should throw an error when the path contains disallowed characters', () => { + it('should throw an error when the path does not conform to path regex', () => { expect(() => validator.parse('https://example.com/abc1234')).toThrow(UrlValidationError) }) }) -describe('UrlValidator with the default whitelist', () => { +describe('UrlValidator with the default valid path regex', () => { const validator = new UrlValidator({}) it('should parse a valid URL', () => { @@ -235,7 +235,7 @@ describe('UrlValidator with the default whitelist', () => { expect(url).toBeInstanceOf(URL) }) - it('should throw an error when the path contains disallowed characters', () => { + it('should throw an error when the path does not conform to path regex', () => { expect(() => validator.parse('https://example.com/1@23')).toThrow(UrlValidationError) }) @@ -393,7 +393,7 @@ describe('createUrlSchema', () => { const schema = createUrlSchema({ whitelist: { protocols: ['http', 'https', 'mailto'], - allowedCharactersInPath: defaultAllowedChars + '@', + validPathRegex: /^[a-zA-Z0-9.-_/@]*$/, }, }) expect(() => schema.parse('mailto:contact@example.com')).not.toThrow() @@ -412,7 +412,7 @@ describe('createUrlSchema', () => { protocols: ['http', 'https'], hosts: ['example.com'], disallowHostnames: true, - allowedCharactersInPath: defaultAllowedChars, + validPathRegex: defaultValidPathRegex, }, }), ).not.toThrow() diff --git a/packages/validators/src/url/index.ts b/packages/validators/src/url/index.ts index 088b1ce..fab7353 100644 --- a/packages/validators/src/url/index.ts +++ b/packages/validators/src/url/index.ts @@ -3,7 +3,7 @@ import { fromError } from 'zod-validation-error' import { OptionsError } from '@/common/errors' import { UrlValidationError } from '@/url/errors' -import { defaultAllowedChars, defaultOptions, optionsSchema, UrlValidatorOptions } from '@/url/options' +import { defaultOptions, defaultValidPathRegex, optionsSchema, UrlValidatorOptions } from '@/url/options' import { toSchema } from '@/url/schema' /** @@ -128,7 +128,7 @@ export class RelUrlValidator extends UrlValidator { whitelist: { protocols: ['http', 'https'], hosts: [urlObject.host], - allowedCharactersInPath: defaultAllowedChars, + validPathRegex: defaultValidPathRegex, }, }) } diff --git a/packages/validators/src/url/options.ts b/packages/validators/src/url/options.ts index 10dffcb..9a00dba 100644 --- a/packages/validators/src/url/options.ts +++ b/packages/validators/src/url/options.ts @@ -1,16 +1,12 @@ import { z } from 'zod' -export const lowercase = 'abcdefghijklmnopqrstuvwxyz' -export const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' -export const digits = '0123456789' -export const alnum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' -export const defaultAllowedChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/' +export const defaultValidPathRegex = /^[a-zA-Z0-9._\-/]*$/ export const defaultOptions = { whitelist: { protocols: ['http', 'https'], disallowHostnames: false, - allowedCharactersInPath: defaultAllowedChars, + validPathRegex: defaultValidPathRegex, }, } @@ -36,13 +32,13 @@ export const whitelistSchema = z.object({ */ disallowHostnames: z.boolean().default(false), /** - * Which characters are allowed in the URL path. - * Use empty string to allow all characters. + * Regex to match against the URL path. + * Use / .* / to allow all characters * If your protocol is mailto, you will need to include "\@" here. * - * @defaultValue 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/' + * @defaultValue defaultValidPathRgex */ - allowedCharactersInPath: z.string().default(defaultAllowedChars), + validPathRegex: z.instanceof(RegExp).default(defaultValidPathRegex), }) /** diff --git a/packages/validators/src/url/schema.ts b/packages/validators/src/url/schema.ts index 8050591..13a5d80 100644 --- a/packages/validators/src/url/schema.ts +++ b/packages/validators/src/url/schema.ts @@ -1,16 +1,12 @@ import { z } from 'zod' import { ParsedUrlValidatorOptions } from '@/url/options' -import { createAllowedCharsSchema, getErrorMessage, IS_NOT_HOSTNAME_REGEX, resolveRelativeUrl } from '@/url/utils' +import { getErrorMessage, IS_NOT_HOSTNAME_REGEX, resolveRelativeUrl } from '@/url/utils' import { isDynamicRoute } from './nextjs-dynamic-route' export const toSchema = (options: ParsedUrlValidatorOptions) => { const { whitelist } = options - - // create and cache this zod schema beforehand - const zAllowedCharsString = createAllowedCharsSchema(whitelist.allowedCharactersInPath) - return z .string() .transform((url, ctx) => { @@ -31,8 +27,8 @@ export const toSchema = (options: ParsedUrlValidatorOptions) => { return false } // only allow whitelisted characters in the path - const onlyHasAllowedChars = zAllowedCharsString.safeParse(url.pathname).success - if (!onlyHasAllowedChars) { + const conformsToPathRegex = z.string().regex(options.whitelist.validPathRegex).safeParse(url.pathname).success + if (!conformsToPathRegex) { return false } diff --git a/packages/validators/src/url/utils.ts b/packages/validators/src/url/utils.ts index aab6c7d..5f01150 100644 --- a/packages/validators/src/url/utils.ts +++ b/packages/validators/src/url/utils.ts @@ -1,44 +1,5 @@ -import { z } from 'zod' - import { UrlValidationError } from '@/url/errors' -/** - * Creates a Zod schema that validates a string to ensure all characters are within the allowed characters set. - * - * @param allowedChars - A string containing all allowed characters. If this is blank, the schema will always pass. - * @returns A Zod schema that validates a string to ensure all characters are within the allowed characters set. - * - * @example - * ```typescript - * const schema = createAllowedCharsSchema('abc123'); - * schema.parse('abc'); // Valid - * schema.parse('a1b2c3'); // Valid - * schema.parse('abcd'); // Throws an error - * ``` - */ -export const createAllowedCharsSchema = (allowedChars: string): z.ZodType => { - if (!allowedChars) { - return z.string() - } - const allowed = new Set(Array.from(allowedChars)) - - const schema = z.string().refine( - (str: string) => { - for (const char of str) { - if (!allowed.has(char)) { - return false - } - } - return true - }, - { - message: `Every character must be in ${allowedChars}`, - }, - ) - - return schema -} - export const IS_NOT_HOSTNAME_REGEX = /[^.]+\.[^.]+/g export const resolveRelativeUrl = (url: string, baseOrigin?: URL): URL => { From d4c2703aa432b955fc6e5ad96a34adb741f4715c Mon Sep 17 00:00:00 2001 From: zhongliang02 Date: Wed, 15 Jan 2025 18:37:51 +0800 Subject: [PATCH 8/8] chore: update validPathRegex in test --- packages/validators/src/__tests__/url.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/validators/src/__tests__/url.test.ts b/packages/validators/src/__tests__/url.test.ts index 04b2e99..61ea110 100644 --- a/packages/validators/src/__tests__/url.test.ts +++ b/packages/validators/src/__tests__/url.test.ts @@ -393,7 +393,7 @@ describe('createUrlSchema', () => { const schema = createUrlSchema({ whitelist: { protocols: ['http', 'https', 'mailto'], - validPathRegex: /^[a-zA-Z0-9.-_/@]*$/, + validPathRegex: /^[a-zA-Z0-9._\-/@]*$/, }, }) expect(() => schema.parse('mailto:contact@example.com')).not.toThrow()