From 1ad204ac7bda0fd6dc2561861745247a1c458a19 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 12:16:27 -0800 Subject: [PATCH 01/20] Remove contributors with deleted accounts (#74053) Co-authored-by: TypeScript Bot --- types/path-complete-extname/package.json | 7 +------ types/react-geocode/package.json | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/types/path-complete-extname/package.json b/types/path-complete-extname/package.json index 1aa97b38ae93b8..ea127b92869614 100644 --- a/types/path-complete-extname/package.json +++ b/types/path-complete-extname/package.json @@ -8,10 +8,5 @@ "devDependencies": { "@types/path-complete-extname": "workspace:." }, - "owners": [ - { - "name": "Marcin C", - "githubUsername": "melangue" - } - ] + "owners": [] } diff --git a/types/react-geocode/package.json b/types/react-geocode/package.json index 838cc28e7d9f7d..2e58be58fb15a5 100644 --- a/types/react-geocode/package.json +++ b/types/react-geocode/package.json @@ -8,10 +8,5 @@ "devDependencies": { "@types/react-geocode": "workspace:." }, - "owners": [ - { - "name": "Steve Mu", - "githubUsername": "stevemu" - } - ] + "owners": [] } From e3aecc5531e007d3ad830eb143d56af879aa3c79 Mon Sep 17 00:00:00 2001 From: Isaiah W Date: Tue, 11 Nov 2025 14:30:25 -0600 Subject: [PATCH 02/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74043=20add?= =?UTF-8?q?=20hints=20to=20`discord-rpc`'s=20`Presence`=20interface=20by?= =?UTF-8?q?=20@RuralAnemone?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/discord-rpc/index.d.ts | 48 ++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/types/discord-rpc/index.d.ts b/types/discord-rpc/index.d.ts index 90e0de2197a48a..04480d88d0cd2e 100644 --- a/types/discord-rpc/index.d.ts +++ b/types/discord-rpc/index.d.ts @@ -449,20 +449,68 @@ export interface VoiceSettings { } export interface Presence { + /** + * The user's current party status + */ state?: string | undefined; + /** + * What the user is currently doing + */ details?: string | undefined; + /** + * Epoch seconds for game start — including will show time as "elapsed" + */ startTimestamp?: number | Date | undefined; + /** + * Epoch seconds for game end — including will show time as "remaining" + */ endTimestamp?: number | Date | undefined; + /** + * Key of the uploaded image for the large profile artwork + */ largeImageKey?: string | undefined; + /** + * Tooltip for the largeImageKey + */ largeImageText?: string | undefined; + /** + * Key of the uploaded image for the small profile artwork + */ smallImageKey?: string | undefined; + /** + * Tooltip for the smallImageKey + */ smallImageText?: string | undefined; + /** + * Whether or not the activity is an instanced game session + */ instance?: boolean | undefined; + /** + * ID of the player's party, lobby, or group + */ partyId?: string | undefined; + /** + * Current size of the player's party, lobby, or group + */ partySize?: number | undefined; + /** + * Maximum size of the player's party, lobby, or group + */ partyMax?: number | undefined; + /** + * Secret for a specified instanced match + */ matchSecret?: string | undefined; + /** + * Secret for spectating a game + */ spectateSecret?: string | undefined; + /** + * Unique hashed string for chat invitations and Ask to Join + */ joinSecret?: string | undefined; + /** + * Custom buttons shown in the Rich Presence (max 2) + */ buttons?: Array<{ label: string; url: string }> | undefined; } From a3d61f9a6353369133c44cbba299e1aeaa29e901 Mon Sep 17 00:00:00 2001 From: Maximilian Hofmann Date: Tue, 11 Nov 2025 21:44:50 +0100 Subject: [PATCH 03/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73901=20Upda?= =?UTF-8?q?te=20exaroton=20types=20to=202.0.0=20by=20@maxiicodes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/exaroton/exaroton-tests.ts | 31 +++++++- types/exaroton/index.d.ts | 126 ++++++++++++++++++++++--------- types/exaroton/package.json | 5 +- types/exaroton/tsconfig.json | 5 +- 4 files changed, 123 insertions(+), 44 deletions(-) diff --git a/types/exaroton/exaroton-tests.ts b/types/exaroton/exaroton-tests.ts index b861a066102f01..a40ece28b43520 100644 --- a/types/exaroton/exaroton-tests.ts +++ b/types/exaroton/exaroton-tests.ts @@ -1,8 +1,18 @@ -import { Client, ServerStatus } from "exaroton"; +import { Client, RequestError, ServerStatus } from "exaroton"; +import { MinecraftServer, Notifications } from "mc-server-management"; const client = new Client("my token"); const startServer = async (name: string) => { + try { + const { name, email } = await client.getAccount(); + console.log(`Using Account ${name} (${email})`); + } catch (err: unknown) { + if (err instanceof RequestError) { + console.error(`${err.statusCode}: ${err.message}`); + } + } + const servers = await client.getServers(); const myServer = servers.find(s => s.name === name); if (!myServer) throw Error("Server not found"); @@ -10,7 +20,7 @@ const startServer = async (name: string) => { console.log(myServer.status); if (myServer.hasStatus([myServer.STATUS.ONLINE, ServerStatus.STARTING])) return; await myServer.start(); - console.log(`${myServer.name} has benn started. Running on: ${myServer.address}`); + console.log(`${myServer.name} has been started. Running on: ${myServer.address}`); console.log(myServer.status); console.log(myServer.players.max); @@ -53,6 +63,21 @@ const startServer = async (name: string) => { myServer.on("stats:stats", data => console.log(data.memory.usage)); myServer.on("heap:heap", data => console.log(data.usage)); myServer.unsubscribe(); + + // management protocol + myServer.subscribe("management"); + const stream = myServer.getWebsocketClient().getStream("management"); + if (typeof stream === "boolean") return; + + const connection = stream.getProxyConnection(); + + const mcServer = new MinecraftServer(connection); + const status = await mcServer.getStatus(); + console.log(status); + + mcServer.on(Notifications.ALLOWLIST_ADDED, data => { + console.log("Allowlist added", data); + }); }; -startServer("my server"); +startServer("my server").then(() => console.log("Server started")); diff --git a/types/exaroton/index.d.ts b/types/exaroton/index.d.ts index 81a986839c5c00..b5394f75deb879 100644 --- a/types/exaroton/index.d.ts +++ b/types/exaroton/index.d.ts @@ -1,9 +1,9 @@ -import { Method, Options as GotOptions, ResponseType } from "got"; +import { Connection } from "mc-server-management"; import { EventEmitter } from "node:events"; -import { ReadStream, WriteStream } from "node:fs"; +import { Readable, Writable } from "node:stream"; import { WebSocket } from "ws"; -export { Client, ConfigOptionType, Pool, PoolMember, Request, Response, Server, ServerStatus, Software }; +export { Client, ConfigOptionType, Pool, PoolMember, Request, RequestError, Response, Server, ServerStatus, Software }; declare enum ServerStatus { OFFLINE = 0, @@ -83,22 +83,7 @@ declare class Client { * @param {Request} request * @throws {RequestError} if the request was unsuccessful */ - request(request: T): Promise; - - /** - * @param {string} url - * @param {GotOptions & { - isStream?: true | boolean; - }} gotOptions - * @param {stream.Writable} outputStream - */ - streamResponse( - url: string, - gotOptions: GotOptions & { - isStream?: true | boolean; - }, - outputStream: T, - ): Promise; + request(request: T): Promise; /** * Get a list of all servers @@ -145,7 +130,7 @@ declare class Request { /** * Request method, e.g. "GET" or "POST" */ - method: Method; + method: HttpMethod; /** * Endpoint URL, without base, version or starting / @@ -189,7 +174,7 @@ declare class Request { /** * Optional stream to stream the response body to */ - outputStream?: WriteStream | null; + outputStream?: Writable | null; /** * Optional path to read the request body from @@ -199,7 +184,7 @@ declare class Request { /** * Optional stream to read the request body from */ - inputStream?: ReadStream | null; + inputStream?: Readable | null; /** * Client that has executed this request @@ -237,7 +222,7 @@ declare class Request { /** * Get body for request */ - getBody(): string | ReadStream; + getBody(): BodyInit; /** * Create a response object for this request @@ -255,7 +240,7 @@ declare class Request { /** * @return {null|WriteStream} */ - getOutputStream(): WriteStream | null; + getOutputStream(): Writable | null; /** * @return {boolean} @@ -265,7 +250,7 @@ declare class Request { /** * @return {null|ReadStream} */ - getInputStream(): ReadStream | null; + getInputStream(): Readable | null; /** * @return {boolean} @@ -302,7 +287,7 @@ declare class Request { * @param {ReadStream} inputStream * @return {this} */ - setInputStream(inputStream: ReadStream): this; + setInputStream(inputStream: Readable): this; /** * Set a stream as output stream for the response body @@ -310,7 +295,7 @@ declare class Request { * @param {WriteStream} outputStream * @return {this} */ - setOutputStream(outputStream: WriteStream): this; + setOutputStream(outputStream: Writable): this; } declare class Response { @@ -434,7 +419,7 @@ declare class File { * @param {WriteStream} outputStream * @return {Promise} */ - downloadToStream(outputStream: WriteStream): Promise; + downloadToStream(outputStream: Writable): Promise; /** * Put the content of a file @@ -462,7 +447,7 @@ declare class File { * @param {ReadStream} inputStream * @return {Promise} */ - uploadFromStream(inputStream: ReadStream): Promise; + uploadFromStream(inputStream: Readable): Promise; /** * Delete the file @@ -683,7 +668,14 @@ interface HeapData { usage: number; } -export interface StreamTypes { +interface ServerManagementData { + id: string; + method: string; + params: Record; +} + +export interface StreamTypesData { + management: [data: ServerManagementData]; status: [server: Server]; "console:line": [data: string]; "tick:tick": [data: TickData]; @@ -691,6 +683,14 @@ export interface StreamTypes { "heap:heap": [data: HeapData]; } +export interface StreamTypes { + console: ConsoleStream; + tick: TickStream; + stats: StatsStream; + heap: HeapStream; + management: ServerManagementStream; +} + declare class Server extends EventEmitter { /** * Shorthand to get server status constants @@ -960,9 +960,9 @@ declare class Server extends EventEmitter { */ toJSON(): Record; - on( + on( stream: StreamType, - listener: (...args: StreamTypes[StreamType]) => void, + listener: (...args: StreamTypesData[StreamType]) => void, ): this; } @@ -978,6 +978,35 @@ declare class Software { // Internal types +declare class RequestError extends Error { + statusCode: number; + + /** + * Response object that caused the error (if any) + */ + response: Response | null; + + /** + * @param {Error|null} error + */ + constructor(error: Error | null); + + /** + * Set error and status code from response object + * + * Returns if an error message was found + * + * @param {Response} response fetch response object + * @param {any} data response data + */ + setErrorFromResponseBody(response: globalThis.Response, data: any): void; +} + +// all types used by the API, see: https://developers.exaroton.com +type HttpMethod = "GET" | "POST" | "PUT" | "DELETE"; + +type ResponseType = "text" | "json" | "buffer"; + declare class Account { #client: Client; @@ -1059,6 +1088,7 @@ declare class WebsocketClient extends EventEmitter { heap: HeapStream; stats: StatsStream; tick: TickStream; + management: ServerManagementStream; }; constructor(server: Server); @@ -1083,15 +1113,15 @@ declare class WebsocketClient extends EventEmitter { getServerStatus(): Promise; - getStreams(stream: string): boolean | Stream; + getStream(stream: StreamType): boolean | StreamTypes[StreamType]; - hasStream(stream: string): boolean; + hasStream(stream: SubscriptionType): boolean; tryToStartStreams(): void; - removeStreams(stream: string): void; + removeStreams(stream: SubscriptionType): void; - send(stream: string, type: string, data: string): boolean; + send(stream: SubscriptionType, type: string, data: string): boolean; } declare class Stream extends EventEmitter { @@ -1129,7 +1159,7 @@ declare class Stream extends EventEmitter { isStarted(): boolean; } -type SubscriptionType = "tick" | "heap" | "stats" | "console"; +type SubscriptionType = "tick" | "heap" | "stats" | "console" | "management"; type TickDataType = "start" | "stop" | "started" | "tick"; @@ -1169,3 +1199,25 @@ declare class ConsoleStream extends Stream { sendCommand(command: string): void; } + +declare class ManagementProxyConnection extends Connection { + stream: ServerManagementStream; + + protected callRaw( + method: string, + parameters: object | Array, + ): Promise<{ success: true; data: unknown } | { success: false; error: unknown }>; + + close(): void; +} + +declare class ServerManagementStream extends Stream { + readonly name: string; + readonly startStatuses: StreamStatus[]; + + onDataMessage(type: string, message: Record): void; + + request(method: HttpMethod, params: any): Promise; + + getProxyConnection(): ManagementProxyConnection; +} diff --git a/types/exaroton/package.json b/types/exaroton/package.json index faaacd29810b88..ad3b948f10724f 100644 --- a/types/exaroton/package.json +++ b/types/exaroton/package.json @@ -1,14 +1,15 @@ { "private": true, "name": "@types/exaroton", - "version": "1.12.9999", + "type": "module", + "version": "2.0.9999", "projects": [ "https://github.com/exaroton/node-exaroton-api" ], "dependencies": { "@types/node": "*", "@types/ws": "*", - "got": "^11.8.2" + "mc-server-management": "^3.1.0" }, "devDependencies": { "@types/exaroton": "workspace:." diff --git a/types/exaroton/tsconfig.json b/types/exaroton/tsconfig.json index 590a1433c4d02d..1f4435340ccf8c 100644 --- a/types/exaroton/tsconfig.json +++ b/types/exaroton/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { - "module": "node16", + "module": "Node16", "lib": [ - "es6" + "es6", + "dom" ], "target": "ES6", "noImplicitAny": true, From c4a35359f051703ba572c110e659c64dd24652d9 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Wed, 12 Nov 2025 04:45:46 +0800 Subject: [PATCH 04/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74045=20feat?= =?UTF-8?q?(validator):=20update=20isStrongPassword()=20with=20fallback=20?= =?UTF-8?q?overload=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/validator/es/lib/isStrongPassword.d.ts | 1 + types/validator/index.d.ts | 39 +++++++++++++++++++- types/validator/lib/isStrongPassword.d.ts | 1 + types/validator/validator-tests.ts | 23 ++++++++---- 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/types/validator/es/lib/isStrongPassword.d.ts b/types/validator/es/lib/isStrongPassword.d.ts index 509dfb2c14239e..9319e04dc187c0 100644 --- a/types/validator/es/lib/isStrongPassword.d.ts +++ b/types/validator/es/lib/isStrongPassword.d.ts @@ -1,2 +1,3 @@ import validator from "../../"; +export type StrongPasswordOptions = validator.StrongPasswordOptions; export default validator.isStrongPassword; diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index 5988c9e3b7b331..e7b485c5eb0084 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -1193,17 +1193,53 @@ declare namespace validator { */ export interface StrongPasswordOptions { + /** + * @default 8 + */ minLength?: number | undefined; + /** + * @default 1 + */ minLowercase?: number | undefined; + /** + * @default 1 + */ minUppercase?: number | undefined; + /** + * @default 1 + */ minNumbers?: number | undefined; + /** + * @default 1 + */ minSymbols?: number | undefined; + /** + * @default false + */ returnScore?: boolean | undefined; + /** + * @default 1 + */ pointsPerUnique?: number | undefined; + /** + * @default 0.5 + */ pointsPerRepeat?: number | undefined; + /** + * @default 10 + */ pointsForContainingLower?: number | undefined; + /** + * @default 10 + */ pointsForContainingUpper?: number | undefined; + /** + * @default 10 + */ pointsForContainingNumber?: number | undefined; + /** + * @default 10 + */ pointsForContainingSymbol?: number | undefined; } @@ -1211,7 +1247,8 @@ declare namespace validator { str: string, options?: StrongPasswordOptions & { returnScore?: false | undefined }, ): boolean; - export function isStrongPassword(str: string, options: StrongPasswordOptions & { returnScore: true }): number; + export function isStrongPassword(str: string, options?: StrongPasswordOptions & { returnScore: true }): number; + export function isStrongPassword(str: string, options?: StrongPasswordOptions): boolean | number; /** * Check if the string contains any surrogate pairs chars. diff --git a/types/validator/lib/isStrongPassword.d.ts b/types/validator/lib/isStrongPassword.d.ts index 63e5e19057662a..ebdfe0405aea79 100644 --- a/types/validator/lib/isStrongPassword.d.ts +++ b/types/validator/lib/isStrongPassword.d.ts @@ -1,2 +1,3 @@ import validator from "../"; +export type StrongPasswordOptions = validator.StrongPasswordOptions; export default validator.isStrongPassword; diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index d245601b00ce2e..4363ee9e68e2f5 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -1113,20 +1113,27 @@ const any: any = null; // $ExpectType boolean validator.isStrongPassword("sample23#@test"); // $ExpectType boolean + validator.isStrongPassword("sample23#@test", {}); + // $ExpectType boolean validator.isStrongPassword("sample23#@test", { - minLength: 10, + minLength: -1, + minLowercase: -1, + minUppercase: -1, + minNumbers: -1, + minSymbols: -1, + pointsPerUnique: -1, + pointsPerRepeat: -1, + pointsForContainingLower: -1, + pointsForContainingUpper: -1, + pointsForContainingNumber: -1, + pointsForContainingSymbol: -1, }); // $ExpectType boolean validator.isStrongPassword("sample23#@test", { returnScore: false }); - // $ExpectType boolean - validator.isStrongPassword("abc", { - minLength: 10, - returnScore: false, - }); // $ExpectType number validator.isStrongPassword("sample23#@test", { returnScore: true }); - // $ExpectType number - validator.isStrongPassword("sample23#@test", { minLength: 10, returnScore: true }); + // $ExpectType boolean | number + validator.isStrongPassword("sample23#@test", { returnScore: Math.random() > 0.5 }); } { From 5691e7acc6ea6f83503a604a5e8f792fe4b360e8 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Wed, 12 Nov 2025 04:45:50 +0800 Subject: [PATCH 05/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74050=20feat?= =?UTF-8?q?(validator):=20add=20`options.allow=5Fprimitives`=20to=20isJSON?= =?UTF-8?q?()=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/validator/es/lib/isJSON.d.ts | 1 + types/validator/index.d.ts | 9 ++++++++- types/validator/lib/isJSON.d.ts | 1 + types/validator/validator-tests.ts | 6 ++++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/types/validator/es/lib/isJSON.d.ts b/types/validator/es/lib/isJSON.d.ts index 576ce6fbc6fbe3..129db9d4ddc9b4 100644 --- a/types/validator/es/lib/isJSON.d.ts +++ b/types/validator/es/lib/isJSON.d.ts @@ -1,2 +1,3 @@ import validator from "../../"; +export type IsJSONOptions = validator.IsJSONOptions; export default validator.isJSON; diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index e7b485c5eb0084..7db4b3a7df9897 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -803,10 +803,17 @@ declare namespace validator { */ export function isRFC3339(str: string): boolean; + export interface IsJSONOptions { + /** + * If true, the primitives 'true', 'false' and 'null' are accepted as valid JSON values. + * @default false + */ + allow_primitives?: boolean | undefined; + } /** * Check if the string is valid JSON (note: uses `JSON.parse`). */ - export function isJSON(str: string): boolean; + export function isJSON(str: string, options?: IsJSONOptions): boolean; /** * Check if the string is valid JWT token. diff --git a/types/validator/lib/isJSON.d.ts b/types/validator/lib/isJSON.d.ts index 6248c48bf7ac20..ae14571fe55476 100644 --- a/types/validator/lib/isJSON.d.ts +++ b/types/validator/lib/isJSON.d.ts @@ -1,2 +1,3 @@ import validator from "../"; +export type IsJSONOptions = validator.IsJSONOptions; export default validator.isJSON; diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index 4363ee9e68e2f5..50300cfe0c3725 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -57,7 +57,7 @@ import isISO6391Func from "validator/lib/isISO6391"; import isISO8601Func from "validator/lib/isISO8601"; import isISRCFunc from "validator/lib/isISRC"; import isISSNFunc from "validator/lib/isISSN"; -import isJSONFunc from "validator/lib/isJSON"; +import isJSONFunc, { IsJSONOptions } from "validator/lib/isJSON"; import isJWTFunc from "validator/lib/isJWT"; import isLatLongFunc from "validator/lib/isLatLong"; import isLengthFunc from "validator/lib/isLength"; @@ -459,7 +459,7 @@ import isISO6391FuncEs from "validator/es/lib/isISO6391"; import isISO8601FuncEs from "validator/es/lib/isISO8601"; import isISRCFuncEs from "validator/es/lib/isISRC"; import isISSNFuncEs from "validator/es/lib/isISSN"; -import isJSONFuncEs from "validator/es/lib/isJSON"; +import isJSONFuncEs, { IsJSONOptions as IsJSONOptionsEs } from "validator/es/lib/isJSON"; import isJWTFuncEs from "validator/es/lib/isJWT"; import isLatLongFuncEs from "validator/es/lib/isLatLong"; import isLengthFuncEs from "validator/es/lib/isLength"; @@ -857,6 +857,8 @@ const any: any = null; result = validator.isInt("sample", isIntOptions); result = validator.isJSON("sample"); + result = validator.isJSON("sample", {}); + result = validator.isJSON("sample", { allow_primitives: true }); result = validator.isLatLong("sample"); From af4bdb13b79a3dfe6fdd560139a89d293a6a4819 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Wed, 12 Nov 2025 04:46:03 +0800 Subject: [PATCH 06/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74035=20feat?= =?UTF-8?q?(validator):=20narrow=20isVAT()'s=20`countryCode`=20to=20a=20fi?= =?UTF-8?q?xed=20locale=20list=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/validator/es/lib/isVAT.d.ts | 1 + types/validator/index.d.ts | 75 +++++++++++++++++++++++++++++- types/validator/lib/isVAT.d.ts | 1 + types/validator/validator-tests.ts | 75 ++++++++++++++++++++++++++++-- 4 files changed, 146 insertions(+), 6 deletions(-) diff --git a/types/validator/es/lib/isVAT.d.ts b/types/validator/es/lib/isVAT.d.ts index af5121e95f81fe..c2b299f138157b 100644 --- a/types/validator/es/lib/isVAT.d.ts +++ b/types/validator/es/lib/isVAT.d.ts @@ -1,2 +1,3 @@ import validator from "../../"; +export type VATCountryCode = validator.VATCountryCode; export default validator.isVAT; diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index 7db4b3a7df9897..c6b6bdb6e6ea4e 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -1329,10 +1329,81 @@ declare namespace validator { */ export function isVariableWidth(str: string): boolean; + export type VATCountryCode = + | "AT" + | "BE" + | "BG" + | "HR" + | "CY" + | "CZ" + | "DK" + | "EE" + | "FI" + | "FR" + | "DE" + | "EL" + | "HU" + | "IE" + | "IT" + | "LV" + | "LT" + | "LU" + | "MT" + | "NL" + | "PL" + | "PT" + | "RO" + | "SK" + | "SI" + | "ES" + | "SE" + | "AL" + | "MK" + | "AU" + | "BY" + | "CA" + | "IS" + | "IN" + | "ID" + | "IL" + | "KZ" + | "NZ" + | "NG" + | "NO" + | "PH" + | "RU" + | "SM" + | "SA" + | "RS" + | "CH" + | "TR" + | "UA" + | "GB" + | "UZ" + | "AR" + | "BO" + | "BR" + | "CL" + | "CO" + | "CR" + | "EC" + | "SV" + | "GT" + | "HN" + | "MX" + | "NI" + | "PA" + | "PY" + | "PE" + | "DO" + | "UY" + | "VE"; + /** - * Checks that the string is a [valid VAT number + * check if the string is a [valid VAT number](https://en.wikipedia.org/wiki/VAT_identification_number) + * if validation is available for the given country code */ - export function isVAT(str: string, countryCode: string): boolean; + export function isVAT(str: string, countryCode: VATCountryCode): boolean; /** * Checks characters if they appear in the whitelist. diff --git a/types/validator/lib/isVAT.d.ts b/types/validator/lib/isVAT.d.ts index f0b0a94cd60d99..5bfcdba5274873 100644 --- a/types/validator/lib/isVAT.d.ts +++ b/types/validator/lib/isVAT.d.ts @@ -1,2 +1,3 @@ import validator from "../"; +export type VATCountryCode = validator.VATCountryCode; export default validator.isVAT; diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index 50300cfe0c3725..fa347f375ae19b 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -89,7 +89,7 @@ import isUppercaseFunc from "validator/lib/isUppercase"; import isURLFunc from "validator/lib/isURL"; import isUUIDFunc from "validator/lib/isUUID"; import isVariableWidthFunc from "validator/lib/isVariableWidth"; -import isVatFunc from "validator/lib/isVAT"; +import isVatFunc, { VATCountryCode } from "validator/lib/isVAT"; import isWhitelistedFunc from "validator/lib/isWhitelisted"; import ltrimFunc from "validator/lib/ltrim"; import matchesFunc from "validator/lib/matches"; @@ -491,7 +491,7 @@ import isUppercaseFuncEs from "validator/es/lib/isUppercase"; import isURLFuncEs from "validator/es/lib/isURL"; import isUUIDFuncEs from "validator/es/lib/isUUID"; import isVariableWidthFuncEs from "validator/es/lib/isVariableWidth"; -import isVATFuncEs from "validator/es/lib/isVAT"; +import isVATFuncEs, { VATCountryCode as VATCountryCodeEs } from "validator/es/lib/isVAT"; import isWhitelistedFuncEs from "validator/es/lib/isWhitelisted"; import ltrimFuncEs from "validator/es/lib/ltrim"; import matchesFuncEs from "validator/es/lib/matches"; @@ -1049,8 +1049,75 @@ const any: any = null; result = validator.isUppercase("sample"); result = validator.isVariableWidth("sample"); - validator.isVAT("GB999 9999 00", "GB"); // $ExpectType boolean - isVatFunc("foo", "GB"); // $ExpectType boolean + + result = validator.isVAT("AT999 9999 00", "AT"); + result = validator.isVAT("BE999 9999 00", "BE"); + result = validator.isVAT("BG999 9999 00", "BG"); + result = validator.isVAT("HR999 9999 00", "HR"); + result = validator.isVAT("CY999 9999 00", "CY"); + result = validator.isVAT("CZ999 9999 00", "CZ"); + result = validator.isVAT("DK999 9999 00", "DK"); + result = validator.isVAT("EE999 9999 00", "EE"); + result = validator.isVAT("FI999 9999 00", "FI"); + result = validator.isVAT("FR999 9999 00", "FR"); + result = validator.isVAT("DE999 9999 00", "DE"); + result = validator.isVAT("EL999 9999 00", "EL"); + result = validator.isVAT("HU999 9999 00", "HU"); + result = validator.isVAT("IE999 9999 00", "IE"); + result = validator.isVAT("IT999 9999 00", "IT"); + result = validator.isVAT("LV999 9999 00", "LV"); + result = validator.isVAT("LT999 9999 00", "LT"); + result = validator.isVAT("LU999 9999 00", "LU"); + result = validator.isVAT("MT999 9999 00", "MT"); + result = validator.isVAT("NL999 9999 00", "NL"); + result = validator.isVAT("PL999 9999 00", "PL"); + result = validator.isVAT("PT999 9999 00", "PT"); + result = validator.isVAT("RO999 9999 00", "RO"); + result = validator.isVAT("SK999 9999 00", "SK"); + result = validator.isVAT("SI999 9999 00", "SI"); + result = validator.isVAT("ES999 9999 00", "ES"); + result = validator.isVAT("SE999 9999 00", "SE"); + result = validator.isVAT("AL999 9999 00", "AL"); + result = validator.isVAT("MK999 9999 00", "MK"); + result = validator.isVAT("AU999 9999 00", "AU"); + result = validator.isVAT("BY999 9999 00", "BY"); + result = validator.isVAT("CA999 9999 00", "CA"); + result = validator.isVAT("IS999 9999 00", "IS"); + result = validator.isVAT("IN999 9999 00", "IN"); + result = validator.isVAT("ID999 9999 00", "ID"); + result = validator.isVAT("IL999 9999 00", "IL"); + result = validator.isVAT("KZ999 9999 00", "KZ"); + result = validator.isVAT("NZ999 9999 00", "NZ"); + result = validator.isVAT("NG999 9999 00", "NG"); + result = validator.isVAT("NO999 9999 00", "NO"); + result = validator.isVAT("PH999 9999 00", "PH"); + result = validator.isVAT("RU999 9999 00", "RU"); + result = validator.isVAT("SM999 9999 00", "SM"); + result = validator.isVAT("SA999 9999 00", "SA"); + result = validator.isVAT("RS999 9999 00", "RS"); + result = validator.isVAT("CH999 9999 00", "CH"); + result = validator.isVAT("TR999 9999 00", "TR"); + result = validator.isVAT("UA999 9999 00", "UA"); + result = validator.isVAT("GB999 9999 00", "GB"); + result = validator.isVAT("UZ999 9999 00", "UZ"); + result = validator.isVAT("AR999 9999 00", "AR"); + result = validator.isVAT("BO999 9999 00", "BO"); + result = validator.isVAT("BR999 9999 00", "BR"); + result = validator.isVAT("CL999 9999 00", "CL"); + result = validator.isVAT("CO999 9999 00", "CO"); + result = validator.isVAT("CR999 9999 00", "CR"); + result = validator.isVAT("EC999 9999 00", "EC"); + result = validator.isVAT("SV999 9999 00", "SV"); + result = validator.isVAT("GT999 9999 00", "GT"); + result = validator.isVAT("HN999 9999 00", "HN"); + result = validator.isVAT("MX999 9999 00", "MX"); + result = validator.isVAT("NI999 9999 00", "NI"); + result = validator.isVAT("PA999 9999 00", "PA"); + result = validator.isVAT("PY999 9999 00", "PY"); + result = validator.isVAT("PE999 9999 00", "PE"); + result = validator.isVAT("DO999 9999 00", "DO"); + result = validator.isVAT("UY999 9999 00", "UY"); + result = validator.isVAT("VE999 9999 00", "VE"); result = validator.isWhitelisted("sample", "abc"); result = validator.isWhitelisted("sample", ["a", "b", "c"]); From 7a50d38e3a360e5f4d5d853f06d54ca68b0a9cbf Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Wed, 12 Nov 2025 04:46:12 +0800 Subject: [PATCH 07/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74020=20feat?= =?UTF-8?q?(validator):=20add=20options=20for=20isBase32(),=20update=20tes?= =?UTF-8?q?t=20for=20isBase58()=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/validator/es/lib/isBase32.d.ts | 1 + types/validator/index.d.ts | 11 ++++++++++- types/validator/lib/isBase32.d.ts | 1 + types/validator/validator-tests.ts | 14 +++++++++++++- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/types/validator/es/lib/isBase32.d.ts b/types/validator/es/lib/isBase32.d.ts index a1729f073abc52..f391af0c9a4b1e 100644 --- a/types/validator/es/lib/isBase32.d.ts +++ b/types/validator/es/lib/isBase32.d.ts @@ -1,2 +1,3 @@ import validator from "../../"; +export type IsBase32Options = validator.IsBase32Options; export default validator.isBase32; diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index c6b6bdb6e6ea4e..3ef3b6949570d9 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -203,10 +203,19 @@ declare namespace validator { */ export function isAscii(str: string): boolean; + export interface IsBase32Options { + /** + * If true, it tests the given base32 encoded string using [Crockford's base32 alternative](http://www.crockford.com/base32.html). + * @default false + */ + crockford?: boolean | undefined; + } + /** * Check if a string is base32 encoded. */ - export function isBase32(str: string): boolean; + export function isBase32(str: string, options?: IsBase32Options): boolean; + /** * check if a string is base58 encoded */ diff --git a/types/validator/lib/isBase32.d.ts b/types/validator/lib/isBase32.d.ts index f33608d4e519d2..852d7286280dc0 100644 --- a/types/validator/lib/isBase32.d.ts +++ b/types/validator/lib/isBase32.d.ts @@ -1,2 +1,3 @@ import validator from "../"; +export type IsBase32Options = validator.IsBase32Options; export default validator.isBase32; diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index fa347f375ae19b..0681fa9f92d526 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -14,6 +14,7 @@ import isAfterFunc from "validator/lib/isAfter"; import isAlphaFunc from "validator/lib/isAlpha"; import isAlphanumericFunc from "validator/lib/isAlphanumeric"; import isAsciiFunc from "validator/lib/isAscii"; +import isBase32Func from "validator/lib/isBase32"; import isBase58Func from "validator/lib/isBase58"; import isBase64Func from "validator/lib/isBase64"; import isBeforeFunc from "validator/lib/isBefore"; @@ -133,6 +134,12 @@ import whitelistFunc from "validator/lib/whitelist"; let _isAscii = validator.isAscii; _isAscii = isAsciiFunc; + let _isBase32 = validator.isBase32; + _isBase32 = isBase32Func; + + let _isBase58 = validator.isBase58; + _isBase58 = isBase58Func; + let _isBase64 = validator.isBase64; _isBase64 = isBase64Func; @@ -417,6 +424,7 @@ import isAfterFuncEs from "validator/es/lib/isAfter"; import isAlphaFuncEs from "validator/es/lib/isAlpha"; import isAlphanumericFuncEs from "validator/es/lib/isAlphanumeric"; import isAsciiFuncEs from "validator/es/lib/isAscii"; +import isBase32FuncEs from "validator/es/lib/isBase32"; import isBase58FuncEs from "validator/es/lib/isBase58"; import isBase64FuncEs from "validator/es/lib/isBase64"; import isBeforeFuncEs from "validator/es/lib/isBefore"; @@ -640,7 +648,11 @@ const any: any = null; result = validator.isAscii("sample"); - isBase58Func("sample"); // $ExpectType boolean + result = validator.isBase32("sample"); + result = validator.isBase32("sample", {}); + result = validator.isBase32("sample", { crockford: true }); + + result = validator.isBase58("sample"); result = validator.isBase64("sample"); result = validator.isBase64("sample", {}); From 533c36eb1bdaa94662d7db8c581fb437e0e111f9 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Wed, 12 Nov 2025 04:46:16 +0800 Subject: [PATCH 08/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74016=20feat?= =?UTF-8?q?(validator):=20update=20isBefore()=20&=20isAfter()=20to=20accep?= =?UTF-8?q?t=20options=20object=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/validator/es/lib/isAfter.d.ts | 1 + types/validator/es/lib/isBefore.d.ts | 1 + types/validator/index.d.ts | 20 ++++++++++++++++++-- types/validator/lib/isAfter.d.ts | 1 + types/validator/lib/isBefore.d.ts | 1 + types/validator/validator-tests.ts | 14 ++++++++++---- 6 files changed, 32 insertions(+), 6 deletions(-) diff --git a/types/validator/es/lib/isAfter.d.ts b/types/validator/es/lib/isAfter.d.ts index e58562fb346589..3a3ccc0ce3d93b 100644 --- a/types/validator/es/lib/isAfter.d.ts +++ b/types/validator/es/lib/isAfter.d.ts @@ -1,2 +1,3 @@ import validator from "../../"; +export type IsAfterOptions = validator.IsAfterOptions; export default validator.isAfter; diff --git a/types/validator/es/lib/isBefore.d.ts b/types/validator/es/lib/isBefore.d.ts index 2a86d9b028a073..0564b1915e786e 100644 --- a/types/validator/es/lib/isBefore.d.ts +++ b/types/validator/es/lib/isBefore.d.ts @@ -1,2 +1,3 @@ import validator from "../../"; +export type IsBeforeOptions = validator.IsBeforeOptions; export default validator.isBefore; diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index 3ef3b6949570d9..95fde59b2187c7 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -45,12 +45,20 @@ declare namespace validator { */ export function isAbaRouting(str: string): boolean; + export interface IsAfterOptions { + /** + * Date to compare to. + * @default Date().toString() + */ + comparisonDate?: string | undefined; + } + /** * Check if the string is a date that's after the specified date. * * @param [date] - Date string (defaults to now) */ - export function isAfter(str: string, date?: string): boolean; + export function isAfter(str: string, dateStringOrOptions?: string | IsAfterOptions): boolean; export type AlphaLocale = | "en-US" @@ -240,12 +248,20 @@ declare namespace validator { */ export function isBase64(str: string, options?: IsBase64Options): boolean; + export interface IsBeforeOptions { + /** + * Date to compare to. + * @default Date().toString() + */ + comparisonDate?: string | undefined; + } + /** * Check if the string is a date that's before the specified date. * * @param [date] - Date string (defaults to now) */ - export function isBefore(str: string, date?: string): boolean; + export function isBefore(str: string, dateStringOrOptions?: string | IsBeforeOptions): boolean; export const isIBAN: typeof _isIBAN.default; export const ibanLocales: typeof _isIBAN.locales; diff --git a/types/validator/lib/isAfter.d.ts b/types/validator/lib/isAfter.d.ts index 3388725729d48a..a39ac018cb77dc 100644 --- a/types/validator/lib/isAfter.d.ts +++ b/types/validator/lib/isAfter.d.ts @@ -1,2 +1,3 @@ import validator from "../"; +export type IsAfterOptions = validator.IsAfterOptions; export default validator.isAfter; diff --git a/types/validator/lib/isBefore.d.ts b/types/validator/lib/isBefore.d.ts index 9c32aacd956721..bec2e922089f65 100644 --- a/types/validator/lib/isBefore.d.ts +++ b/types/validator/lib/isBefore.d.ts @@ -1,2 +1,3 @@ import validator from "../"; +export type IsBeforeOptions = validator.IsBeforeOptions; export default validator.isBefore; diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index 0681fa9f92d526..b9f57f2673cc0f 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -10,14 +10,14 @@ import containsFunc from "validator/lib/contains"; import equalsFunc from "validator/lib/equals"; import escapeFunc from "validator/lib/escape"; import isAbaRoutingFunc from "validator/lib/isAbaRouting"; -import isAfterFunc from "validator/lib/isAfter"; +import isAfterFunc, { IsAfterOptions } from "validator/lib/isAfter"; import isAlphaFunc from "validator/lib/isAlpha"; import isAlphanumericFunc from "validator/lib/isAlphanumeric"; import isAsciiFunc from "validator/lib/isAscii"; import isBase32Func from "validator/lib/isBase32"; import isBase58Func from "validator/lib/isBase58"; import isBase64Func from "validator/lib/isBase64"; -import isBeforeFunc from "validator/lib/isBefore"; +import isBeforeFunc, { IsBeforeOptions } from "validator/lib/isBefore"; import isBICFunc from "validator/lib/isBIC"; import isBooleanFunc from "validator/lib/isBoolean"; import isBtcAddressFunc from "validator/lib/isBtcAddress"; @@ -420,14 +420,14 @@ import containsFuncEs from "validator/es/lib/contains"; import equalsFuncEs from "validator/es/lib/equals"; import escapeFuncEs from "validator/es/lib/escape"; import isAbaRoutingFuncEs from "validator/es/lib/isAbaRouting"; -import isAfterFuncEs from "validator/es/lib/isAfter"; +import isAfterFuncEs, { IsAfterOptions as IsAfterOptionsEs } from "validator/es/lib/isAfter"; import isAlphaFuncEs from "validator/es/lib/isAlpha"; import isAlphanumericFuncEs from "validator/es/lib/isAlphanumeric"; import isAsciiFuncEs from "validator/es/lib/isAscii"; import isBase32FuncEs from "validator/es/lib/isBase32"; import isBase58FuncEs from "validator/es/lib/isBase58"; import isBase64FuncEs from "validator/es/lib/isBase64"; -import isBeforeFuncEs from "validator/es/lib/isBefore"; +import isBeforeFuncEs, { IsBeforeOptions as IsBeforeOptionsEs } from "validator/es/lib/isBefore"; import isBICFuncEs from "validator/es/lib/isBIC"; import isBooleanFuncEs from "validator/es/lib/isBoolean"; import isBtcAddressFuncEs from "validator/es/lib/isBtcAddress"; @@ -539,6 +539,9 @@ const any: any = null; result = validator.isAfter("sample"); result = validator.isAfter("sample", new Date().toString()); + result = validator.isAfter("sample", {} satisfies IsAfterOptions); + result = validator.isAfter("sample", { comparisonDate: undefined }); + result = validator.isAfter("sample", { comparisonDate: new Date().toString() }); result = validator.isAlpha("sample"); result = validator.isAlpha("sample", "ar"); @@ -667,6 +670,9 @@ const any: any = null; result = validator.isBefore("sample"); result = validator.isBefore("sample", new Date().toString()); + result = validator.isBefore("sample", {} satisfies IsBeforeOptions); + result = validator.isBefore("sample", { comparisonDate: undefined }); + result = validator.isBefore("sample", { comparisonDate: new Date().toString() }); result = validator.isIBAN("sample"); result = validator.isIBAN("sample", { whitelist: ["GB", "BR"] }); From 77c0a6a9d6cceff75916d5cfd3f09488b75d4b49 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Wed, 12 Nov 2025 04:46:26 +0800 Subject: [PATCH 09/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74010=20feat?= =?UTF-8?q?(validator):=20update=20&=20export=20isPostalCode's=20locale=20?= =?UTF-8?q?list=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/validator/es/lib/isPostalCode.d.ts | 1 + types/validator/index.d.ts | 13 ++++++++ types/validator/lib/isPostalCode.d.ts | 1 + types/validator/validator-tests.ts | 38 ++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/types/validator/es/lib/isPostalCode.d.ts b/types/validator/es/lib/isPostalCode.d.ts index 470c3895f9b0a9..5f8e778519c4a9 100644 --- a/types/validator/es/lib/isPostalCode.d.ts +++ b/types/validator/es/lib/isPostalCode.d.ts @@ -1,3 +1,4 @@ import validator from "../../"; export type PostalCodeLocale = validator.PostalCodeLocale; +export const locales: PostalCodeLocale[]; export default validator.isPostalCode; diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index 95fde59b2187c7..82050ce23c8c23 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -1152,9 +1152,13 @@ declare namespace validator { | "AD" | "AT" | "AU" + | "AZ" + | "BA" + | "BD" | "BE" | "BG" | "BR" + | "BY" | "CA" | "CH" | "CN" @@ -1162,6 +1166,7 @@ declare namespace validator { | "CZ" | "DE" | "DK" + | "DO" | "DZ" | "EE" | "ES" @@ -1170,6 +1175,7 @@ declare namespace validator { | "GB" | "GR" | "HR" + | "HT" | "HU" | "ID" | "IE" @@ -1185,11 +1191,16 @@ declare namespace validator { | "LT" | "LU" | "LV" + | "LK" + | "MG" | "MX" | "MT" + | "MY" | "NL" | "NO" + | "NP" | "NZ" + | "PK" | "PL" | "PR" | "PT" @@ -1197,8 +1208,10 @@ declare namespace validator { | "RU" | "SA" | "SE" + | "SG" | "SI" | "SK" + | "TH" | "TN" | "TW" | "UA" diff --git a/types/validator/lib/isPostalCode.d.ts b/types/validator/lib/isPostalCode.d.ts index 3b126cd7b8a3ad..67d1f85e8e3490 100644 --- a/types/validator/lib/isPostalCode.d.ts +++ b/types/validator/lib/isPostalCode.d.ts @@ -1,3 +1,4 @@ import validator from "../"; export type PostalCodeLocale = validator.PostalCodeLocale; +export const locales: PostalCodeLocale[]; export default validator.isPostalCode; diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index b9f57f2673cc0f..234430015ab347 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -77,7 +77,7 @@ import isNumericFunc from "validator/lib/isNumeric"; import isOctalFunc from "validator/lib/isOctal"; import isPassportNumberFunc from "validator/lib/isPassportNumber"; import isPortFunc from "validator/lib/isPort"; -import isPostalCodeFunc from "validator/lib/isPostalCode"; +import isPostalCodeFunc, { locales as isPostalCodeLocales } from "validator/lib/isPostalCode"; import isRgbColorFunc from "validator/lib/isRgbColor"; import isSemVerFunc from "validator/lib/isSemVer"; import isSlugFunc from "validator/lib/isSlug"; @@ -486,7 +486,7 @@ import isNumericFuncEs from "validator/es/lib/isNumeric"; import isOctalFuncEs from "validator/es/lib/isOctal"; import isPassportNumberFuncEs from "validator/es/lib/isPassportNumber"; import isPortFuncEs from "validator/es/lib/isPort"; -import isPostalCodeFuncEs from "validator/es/lib/isPostalCode"; +import isPostalCodeFuncEs, { locales as isPostalCodeLocalesEs } from "validator/es/lib/isPostalCode"; import isRgbColorFuncEs from "validator/es/lib/isRgbColor"; import isSemVerFuncEs from "validator/es/lib/isSemVer"; import isSlugFuncEs from "validator/es/lib/isSlug"; @@ -988,40 +988,72 @@ const any: any = null; result = validator.isPort("sample"); + result = validator.isPostalCode("sample", "AD"); result = validator.isPostalCode("sample", "AT"); result = validator.isPostalCode("sample", "AU"); + result = validator.isPostalCode("sample", "AZ"); + result = validator.isPostalCode("sample", "BA"); + result = validator.isPostalCode("sample", "BD"); result = validator.isPostalCode("sample", "BE"); result = validator.isPostalCode("sample", "BG"); + result = validator.isPostalCode("sample", "BR"); + result = validator.isPostalCode("sample", "BY"); result = validator.isPostalCode("sample", "CA"); result = validator.isPostalCode("sample", "CH"); + result = validator.isPostalCode("sample", "CN"); result = validator.isPostalCode("sample", "CO"); result = validator.isPostalCode("sample", "CZ"); result = validator.isPostalCode("sample", "DE"); result = validator.isPostalCode("sample", "DK"); + result = validator.isPostalCode("sample", "DO"); result = validator.isPostalCode("sample", "DZ"); + result = validator.isPostalCode("sample", "EE"); result = validator.isPostalCode("sample", "ES"); result = validator.isPostalCode("sample", "FI"); result = validator.isPostalCode("sample", "FR"); result = validator.isPostalCode("sample", "GB"); result = validator.isPostalCode("sample", "GR"); + result = validator.isPostalCode("sample", "HR"); + result = validator.isPostalCode("sample", "HT"); + result = validator.isPostalCode("sample", "HU"); + result = validator.isPostalCode("sample", "ID"); + result = validator.isPostalCode("sample", "IE"); result = validator.isPostalCode("sample", "IL"); result = validator.isPostalCode("sample", "IN"); + result = validator.isPostalCode("sample", "IR"); result = validator.isPostalCode("sample", "IS"); result = validator.isPostalCode("sample", "IT"); result = validator.isPostalCode("sample", "JP"); - result = validator.isPostalCode("sample", "KR"); result = validator.isPostalCode("sample", "KE"); + result = validator.isPostalCode("sample", "KR"); result = validator.isPostalCode("sample", "LI"); + result = validator.isPostalCode("sample", "LT"); + result = validator.isPostalCode("sample", "LU"); + result = validator.isPostalCode("sample", "LV"); + result = validator.isPostalCode("sample", "LK"); + result = validator.isPostalCode("sample", "MG"); result = validator.isPostalCode("sample", "MX"); + result = validator.isPostalCode("sample", "MT"); + result = validator.isPostalCode("sample", "MY"); result = validator.isPostalCode("sample", "NL"); result = validator.isPostalCode("sample", "NO"); + result = validator.isPostalCode("sample", "NP"); + result = validator.isPostalCode("sample", "NZ"); + result = validator.isPostalCode("sample", "PK"); result = validator.isPostalCode("sample", "PL"); + result = validator.isPostalCode("sample", "PR"); result = validator.isPostalCode("sample", "PT"); result = validator.isPostalCode("sample", "RO"); result = validator.isPostalCode("sample", "RU"); result = validator.isPostalCode("sample", "SA"); result = validator.isPostalCode("sample", "SE"); + result = validator.isPostalCode("sample", "SG"); + result = validator.isPostalCode("sample", "SI"); + result = validator.isPostalCode("sample", "SK"); + result = validator.isPostalCode("sample", "TH"); + result = validator.isPostalCode("sample", "TN"); result = validator.isPostalCode("sample", "TW"); + result = validator.isPostalCode("sample", "UA"); result = validator.isPostalCode("sample", "US"); result = validator.isPostalCode("sample", "ZA"); result = validator.isPostalCode("sample", "ZM"); From 5598a1e8b3423b6047776b6397db867041298186 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Wed, 12 Nov 2025 04:50:42 +0800 Subject: [PATCH 10/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74004=20feat?= =?UTF-8?q?(validator):=20update=20&=20export=20isMobilePhone's=20locale?= =?UTF-8?q?=20list=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/validator/es/lib/isMobilePhone.d.ts | 1 + types/validator/index.d.ts | 47 +++++++- types/validator/lib/isMobilePhone.d.ts | 1 + types/validator/validator-tests.ts | 126 ++++++++++++++++++++-- 4 files changed, 164 insertions(+), 11 deletions(-) diff --git a/types/validator/es/lib/isMobilePhone.d.ts b/types/validator/es/lib/isMobilePhone.d.ts index 3a3ce0b71a57d2..69df8464f34546 100644 --- a/types/validator/es/lib/isMobilePhone.d.ts +++ b/types/validator/es/lib/isMobilePhone.d.ts @@ -1,4 +1,5 @@ import validator from "../../"; export type MobilePhoneLocale = validator.MobilePhoneLocale; export type IsMobilePhoneOptions = validator.IsMobilePhoneOptions; +export const locales: MobilePhoneLocale[]; export default validator.isMobilePhone; diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index 82050ce23c8c23..f962e75b1c2f69 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -974,10 +974,13 @@ declare namespace validator { | "ar-LY" | "ar-MA" | "ar-OM" + | "ar-PS" | "ar-SA" + | "ar-SD" | "ar-SY" | "ar-TN" | "az-AZ" + | "ar-QA" | "bs-BA" | "be-BY" | "bg-BG" @@ -989,20 +992,36 @@ declare namespace validator { | "de-AT" | "de-CH" | "de-LU" + | "dv-MV" | "el-GR" + | "el-CY" + | "en-AI" | "en-AU" + | "en-AG" + | "en-BM" + | "en-BS" | "en-GB" | "en-GG" | "en-GH" + | "en-GY" | "en-HK" | "en-MO" | "en-IE" | "en-IN" + | "en-JM" | "en-KE" + | "fr-CF" + | "en-SS" + | "en-KI" + | "en-KN" + | "en-LS" | "en-MT" | "en-MU" + | "en-MW" + | "en-NA" | "en-NG" | "en-NZ" + | "en-PG" | "en-PK" | "en-PH" | "en-RW" @@ -1014,11 +1033,13 @@ declare namespace validator { | "en-ZA" | "en-ZM" | "en-ZW" + | "en-BW" | "es-AR" | "es-BO" | "es-CO" | "es-CL" | "es-CR" + | "es-CU" | "es-DO" | "es-HN" | "es-EC" @@ -1026,8 +1047,10 @@ declare namespace validator { | "es-GT" | "es-PE" | "es-MX" + | "es-NI" | "es-PA" | "es-PY" + | "es-SV" | "es-UY" | "es-VE" | "et-EE" @@ -1035,14 +1058,21 @@ declare namespace validator { | "fi-FI" | "fj-FJ" | "fo-FO" + | "fr-BF" + | "fr-BJ" + | "fr-CD" + | "fr-CM" | "fr-FR" | "fr-GF" | "fr-GP" | "fr-MQ" + | "fr-PF" | "fr-RE" + | "fr-WF" | "he-IL" | "hu-HU" | "id-ID" + | "ir-IR" | "it-IT" | "it-SM" | "ja-JP" @@ -1050,35 +1080,48 @@ declare namespace validator { | "kk-KZ" | "kl-GL" | "ko-KR" + | "ky-KG" | "lt-LT" | "lv-LV" - | "mk-MK" + | "mg-MG" + | "mn-MN" + | "my-MM" | "ms-MY" | "mz-MZ" | "nb-NO" | "ne-NP" | "nl-BE" | "nl-NL" + | "nl-AW" | "nn-NO" | "pl-PL" | "pt-BR" | "pt-PT" | "pt-AO" + | "ro-MD" | "ro-RO" | "ru-RU" | "si-LK" | "sl-SI" | "sk-SK" + | "so-SO" | "sq-AL" | "sr-RS" | "sv-SE" + | "tg-TJ" | "th-TH" | "tr-TR" + | "tk-TM" | "uk-UA" | "uz-UZ" | "vi-VN" | "zh-CN" - | "zh-TW"; + | "zh-TW" + | "dz-BT" + | "ar-YE" + | "ar-EH" + | "fa-AF" + | "mk-MK"; export type PhoneLocaleAlias = "en-CA" | "fr-CA" | "fr-BE" | "zh-HK" | "zh-MO" | "ga-IE" | "fr-CH" | "it-CH"; export const isMobilePhoneLocales: MobilePhoneLocale[]; diff --git a/types/validator/lib/isMobilePhone.d.ts b/types/validator/lib/isMobilePhone.d.ts index cdce9ec0678869..a7663c348717fa 100644 --- a/types/validator/lib/isMobilePhone.d.ts +++ b/types/validator/lib/isMobilePhone.d.ts @@ -1,4 +1,5 @@ import validator from "../"; export type MobilePhoneLocale = validator.MobilePhoneLocale; export type IsMobilePhoneOptions = validator.IsMobilePhoneOptions; +export const locales: MobilePhoneLocale[]; export default validator.isMobilePhone; diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index 234430015ab347..ef16af60dfdbbb 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -70,7 +70,7 @@ import isMACAddressFunc from "validator/lib/isMACAddress"; import isMailtoURIFunc from "validator/lib/isMailtoURI"; import isMD5Func from "validator/lib/isMD5"; import isMimeTypeFunc from "validator/lib/isMimeType"; -import isMobilePhoneFunc from "validator/lib/isMobilePhone"; +import isMobilePhoneFunc, { locales as isMobilePhoneLocales } from "validator/lib/isMobilePhone"; import isMongoIdFunc from "validator/lib/isMongoId"; import isMultibyteFunc from "validator/lib/isMultibyte"; import isNumericFunc from "validator/lib/isNumeric"; @@ -479,7 +479,7 @@ import isMACAddressFuncEs from "validator/es/lib/isMACAddress"; import isMailtoURIFuncEs from "validator/es/lib/isMailtoURI"; import isMD5FuncEs from "validator/es/lib/isMD5"; import isMimeTypeFuncEs from "validator/es/lib/isMimeType"; -import isMobilePhoneFuncEs from "validator/es/lib/isMobilePhone"; +import isMobilePhoneFuncEs, { locales as isMobilePhoneLocalesEs } from "validator/es/lib/isMobilePhone"; import isMongoIdFuncEs from "validator/es/lib/isMongoId"; import isMultibyteFuncEs from "validator/es/lib/isMultibyte"; import isNumericFuncEs from "validator/es/lib/isNumeric"; @@ -909,66 +909,174 @@ const any: any = null; strictMode: true, }; result = validator.isMobilePhone("sample", "any", isMobilePhoneOptions); + result = validator.isMobilePhone("sample", "am-AM"); result = validator.isMobilePhone("sample", "ar-AE"); + result = validator.isMobilePhone("sample", "ar-BH"); result = validator.isMobilePhone("sample", "ar-DZ"); + result = validator.isMobilePhone("sample", "ar-LB"); result = validator.isMobilePhone("sample", "ar-EG"); + result = validator.isMobilePhone("sample", "ar-IQ"); result = validator.isMobilePhone("sample", "ar-JO"); + result = validator.isMobilePhone("sample", "ar-KW"); + result = validator.isMobilePhone("sample", "ar-LY"); + result = validator.isMobilePhone("sample", "ar-MA"); + result = validator.isMobilePhone("sample", "ar-OM"); + result = validator.isMobilePhone("sample", "ar-PS"); result = validator.isMobilePhone("sample", "ar-SA"); + result = validator.isMobilePhone("sample", "ar-SD"); result = validator.isMobilePhone("sample", "ar-SY"); + result = validator.isMobilePhone("sample", "ar-TN"); + result = validator.isMobilePhone("sample", "az-AZ"); + result = validator.isMobilePhone("sample", "ar-QA"); + result = validator.isMobilePhone("sample", "bs-BA"); result = validator.isMobilePhone("sample", "be-BY"); result = validator.isMobilePhone("sample", "bg-BG"); + result = validator.isMobilePhone("sample", "bn-BD"); + result = validator.isMobilePhone("sample", "ca-AD"); result = validator.isMobilePhone("sample", "cs-CZ"); - result = validator.isMobilePhone("sample", "de-DE"); result = validator.isMobilePhone("sample", "da-DK"); + result = validator.isMobilePhone("sample", "de-DE"); + result = validator.isMobilePhone("sample", "de-AT"); + result = validator.isMobilePhone("sample", "de-CH"); + result = validator.isMobilePhone("sample", "de-LU"); + result = validator.isMobilePhone("sample", "dv-MV"); result = validator.isMobilePhone("sample", "el-GR"); + result = validator.isMobilePhone("sample", "el-CY"); + result = validator.isMobilePhone("sample", "en-AI"); result = validator.isMobilePhone("sample", "en-AU"); + result = validator.isMobilePhone("sample", "en-AG"); + result = validator.isMobilePhone("sample", "en-BM"); + result = validator.isMobilePhone("sample", "en-BS"); result = validator.isMobilePhone("sample", "en-GB"); + result = validator.isMobilePhone("sample", "en-GG"); + result = validator.isMobilePhone("sample", "en-GH"); + result = validator.isMobilePhone("sample", "en-GY"); result = validator.isMobilePhone("sample", "en-HK"); + result = validator.isMobilePhone("sample", "en-MO"); + result = validator.isMobilePhone("sample", "en-IE"); result = validator.isMobilePhone("sample", "en-IN"); + result = validator.isMobilePhone("sample", "en-JM"); result = validator.isMobilePhone("sample", "en-KE"); + result = validator.isMobilePhone("sample", "fr-CF"); + result = validator.isMobilePhone("sample", "en-SS"); + result = validator.isMobilePhone("sample", "en-KI"); + result = validator.isMobilePhone("sample", "en-KN"); + result = validator.isMobilePhone("sample", "en-LS"); + result = validator.isMobilePhone("sample", "en-MT"); + result = validator.isMobilePhone("sample", "en-MU"); + result = validator.isMobilePhone("sample", "en-MW"); + result = validator.isMobilePhone("sample", "en-NA"); result = validator.isMobilePhone("sample", "en-NG"); result = validator.isMobilePhone("sample", "en-NZ"); - result = validator.isMobilePhone("sample", "en-UG"); + result = validator.isMobilePhone("sample", "en-PG"); + result = validator.isMobilePhone("sample", "en-PK"); + result = validator.isMobilePhone("sample", "en-PH"); result = validator.isMobilePhone("sample", "en-RW"); result = validator.isMobilePhone("sample", "en-SG"); + result = validator.isMobilePhone("sample", "en-SL"); result = validator.isMobilePhone("sample", "en-TZ"); - result = validator.isMobilePhone("sample", "en-PK"); + result = validator.isMobilePhone("sample", "en-UG"); result = validator.isMobilePhone("sample", "en-US"); - result = validator.isMobilePhone("sample", "en-CA"); result = validator.isMobilePhone("sample", "en-ZA"); result = validator.isMobilePhone("sample", "en-ZM"); + result = validator.isMobilePhone("sample", "en-ZW"); + result = validator.isMobilePhone("sample", "en-BW"); + result = validator.isMobilePhone("sample", "es-AR"); + result = validator.isMobilePhone("sample", "es-BO"); + result = validator.isMobilePhone("sample", "es-CO"); + result = validator.isMobilePhone("sample", "es-CL"); + result = validator.isMobilePhone("sample", "es-CR"); + result = validator.isMobilePhone("sample", "es-CU"); + result = validator.isMobilePhone("sample", "es-DO"); + result = validator.isMobilePhone("sample", "es-HN"); + result = validator.isMobilePhone("sample", "es-EC"); result = validator.isMobilePhone("sample", "es-ES"); result = validator.isMobilePhone("sample", "es-GT"); + result = validator.isMobilePhone("sample", "es-PE"); + result = validator.isMobilePhone("sample", "es-MX"); + result = validator.isMobilePhone("sample", "es-NI"); + result = validator.isMobilePhone("sample", "es-PA"); + result = validator.isMobilePhone("sample", "es-PY"); + result = validator.isMobilePhone("sample", "es-SV"); + result = validator.isMobilePhone("sample", "es-UY"); + result = validator.isMobilePhone("sample", "es-VE"); + result = validator.isMobilePhone("sample", "et-EE"); result = validator.isMobilePhone("sample", "fa-IR"); result = validator.isMobilePhone("sample", "fi-FI"); + result = validator.isMobilePhone("sample", "fj-FJ"); result = validator.isMobilePhone("sample", "fo-FO"); + result = validator.isMobilePhone("sample", "fr-BF"); + result = validator.isMobilePhone("sample", "fr-BJ"); + result = validator.isMobilePhone("sample", "fr-CD"); + result = validator.isMobilePhone("sample", "fr-CM"); result = validator.isMobilePhone("sample", "fr-FR"); + result = validator.isMobilePhone("sample", "fr-GF"); + result = validator.isMobilePhone("sample", "fr-GP"); + result = validator.isMobilePhone("sample", "fr-MQ"); + result = validator.isMobilePhone("sample", "fr-PF"); + result = validator.isMobilePhone("sample", "fr-RE"); + result = validator.isMobilePhone("sample", "fr-WF"); result = validator.isMobilePhone("sample", "he-IL"); result = validator.isMobilePhone("sample", "hu-HU"); result = validator.isMobilePhone("sample", "id-ID"); + result = validator.isMobilePhone("sample", "ir-IR"); result = validator.isMobilePhone("sample", "it-IT"); + result = validator.isMobilePhone("sample", "it-SM"); result = validator.isMobilePhone("sample", "ja-JP"); + result = validator.isMobilePhone("sample", "ka-GE"); result = validator.isMobilePhone("sample", "kk-KZ"); result = validator.isMobilePhone("sample", "kl-GL"); result = validator.isMobilePhone("sample", "ko-KR"); + result = validator.isMobilePhone("sample", "ky-KG"); result = validator.isMobilePhone("sample", "lt-LT"); - result = validator.isMobilePhone("sample", "mk-MK"); + result = validator.isMobilePhone("sample", "lv-LV"); + result = validator.isMobilePhone("sample", "mg-MG"); + result = validator.isMobilePhone("sample", "mn-MN"); + result = validator.isMobilePhone("sample", "my-MM"); result = validator.isMobilePhone("sample", "ms-MY"); + result = validator.isMobilePhone("sample", "mz-MZ"); result = validator.isMobilePhone("sample", "nb-NO"); + result = validator.isMobilePhone("sample", "ne-NP"); + result = validator.isMobilePhone("sample", "nl-BE"); + result = validator.isMobilePhone("sample", "nl-NL"); + result = validator.isMobilePhone("sample", "nl-AW"); result = validator.isMobilePhone("sample", "nn-NO"); result = validator.isMobilePhone("sample", "pl-PL"); + result = validator.isMobilePhone("sample", "pt-BR"); result = validator.isMobilePhone("sample", "pt-PT"); + result = validator.isMobilePhone("sample", "pt-AO"); + result = validator.isMobilePhone("sample", "ro-MD"); result = validator.isMobilePhone("sample", "ro-RO"); result = validator.isMobilePhone("sample", "ru-RU"); - result = validator.isMobilePhone("sample", "sr-RS"); + result = validator.isMobilePhone("sample", "si-LK"); + result = validator.isMobilePhone("sample", "sl-SI"); result = validator.isMobilePhone("sample", "sk-SK"); + result = validator.isMobilePhone("sample", "so-SO"); + result = validator.isMobilePhone("sample", "sq-AL"); + result = validator.isMobilePhone("sample", "sr-RS"); + result = validator.isMobilePhone("sample", "sv-SE"); + result = validator.isMobilePhone("sample", "tg-TJ"); result = validator.isMobilePhone("sample", "th-TH"); result = validator.isMobilePhone("sample", "tr-TR"); + result = validator.isMobilePhone("sample", "tk-TM"); result = validator.isMobilePhone("sample", "uk-UA"); + result = validator.isMobilePhone("sample", "uz-UZ"); result = validator.isMobilePhone("sample", "vi-VN"); result = validator.isMobilePhone("sample", "zh-CN"); - result = validator.isMobilePhone("sample", "zh-HK"); result = validator.isMobilePhone("sample", "zh-TW"); + result = validator.isMobilePhone("sample", "dz-BT"); + result = validator.isMobilePhone("sample", "ar-YE"); + result = validator.isMobilePhone("sample", "ar-EH"); + result = validator.isMobilePhone("sample", "fa-AF"); + result = validator.isMobilePhone("sample", "mk-MK"); + result = validator.isMobilePhone("sample", "en-CA"); + result = validator.isMobilePhone("sample", "fr-CA"); + result = validator.isMobilePhone("sample", "fr-BE"); + result = validator.isMobilePhone("sample", "zh-HK"); + result = validator.isMobilePhone("sample", "zh-MO"); + result = validator.isMobilePhone("sample", "ga-IE"); + result = validator.isMobilePhone("sample", "fr-CH"); + result = validator.isMobilePhone("sample", "it-CH"); result = validator.isMobilePhone("sample", "any"); result = validator.isMobilePhone("sample"); result = validator.isMobilePhone("sample", ["pl-PL", "pt-PT"]); From 10a6e6322f992d932382aa73f4441b489e4d1af2 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Wed, 12 Nov 2025 05:16:17 +0800 Subject: [PATCH 11/20] feat(validator): update isLicensePlate's locale list (#74008) --- types/validator/index.d.ts | 6 +++--- types/validator/validator-tests.ts | 18 +++++++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index f962e75b1c2f69..fa97c3586eb0b7 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -883,18 +883,18 @@ declare namespace validator { | "en-IN" | "en-SG" | "es-AR" + | "fi-FI" | "hu-HU" | "pt-BR" | "pt-PT" | "sq-AL" | "sv-SE" - | "en-PK" - | "any"; + | "en-PK"; /** * Check if the string matches the format of a country's license plate. */ - export function isLicensePlate(str: string, locale: LicensePlateLocale): boolean; + export function isLicensePlate(str: string, locale: LicensePlateLocale | "any"): boolean; export function isLicensePlate(str: string, locale: string): unknown; /** diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index ef16af60dfdbbb..75cc8f3e4e522c 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -287,7 +287,7 @@ import whitelistFunc from "validator/lib/whitelist"; let _isLength = validator.isLength; _isLength = isLengthFunc; - // $ExpectType { (str: string, locale: LicensePlateLocale): boolean; (str: string, locale: string): unknown; } + // $ExpectType { (str: string, locale: "any" | LicensePlateLocale): boolean; (str: string, locale: string): unknown; } let _isLicensePlate = validator.isLicensePlate; _isLicensePlate = isLicensePlateFunc; @@ -884,8 +884,20 @@ const any: any = null; result = validator.isLength("sample", isLengthOptions); result = validator.isLength("sample"); - const licensePlateLocale: validator.LicensePlateLocale = "any"; - result = validator.isLicensePlate("sample", licensePlateLocale); + result = validator.isLicensePlate("sample", "cs-CZ" satisfies validator.LicensePlateLocale); + result = validator.isLicensePlate("sample", "de-DE"); + result = validator.isLicensePlate("sample", "de-LI"); + result = validator.isLicensePlate("sample", "en-IN"); + result = validator.isLicensePlate("sample", "en-SG"); + result = validator.isLicensePlate("sample", "es-AR"); + result = validator.isLicensePlate("sample", "fi-FI"); + result = validator.isLicensePlate("sample", "hu-HU"); + result = validator.isLicensePlate("sample", "pt-BR"); + result = validator.isLicensePlate("sample", "pt-PT"); + result = validator.isLicensePlate("sample", "sq-AL"); + result = validator.isLicensePlate("sample", "sv-SE"); + result = validator.isLicensePlate("sample", "en-PK"); + result = validator.isLicensePlate("sample", "any"); // $ExpectType unknown validator.isLicensePlate("sample", ""); From 9871bf306fe0e03b7f4f29b19437e2ccf57eb8f8 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Wed, 12 Nov 2025 05:16:37 +0800 Subject: [PATCH 12/20] feat(validator): add options.ignore_max_length to isFQDN() (#74024) --- types/validator/lib/isFQDN.d.ts | 9 +++++++++ types/validator/validator-tests.ts | 25 +++++++++++++++---------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/types/validator/lib/isFQDN.d.ts b/types/validator/lib/isFQDN.d.ts index 131dac01bb2db3..38898f5cf7148a 100644 --- a/types/validator/lib/isFQDN.d.ts +++ b/types/validator/lib/isFQDN.d.ts @@ -1,17 +1,21 @@ export interface IsFQDNOptions { /** + * If `require_tld` is set to false, the validator will not check if the domain includes a TLD. * @default true */ require_tld?: boolean | undefined; /** + * If `allow_underscores` is set to true, the validator will allow underscores in the domain. * @default false */ allow_underscores?: boolean | undefined; /** + * If `allow_trailing_dot` is set to true, the validator will allow the domain to end with a `.` character. * @default false */ allow_trailing_dot?: boolean | undefined; /** + * If `allow_numeric_tld` is set to true, the validator will allow the TLD of the domain to be made up solely of numbers. * @default false */ allow_numeric_tld?: boolean | undefined; @@ -20,6 +24,11 @@ export interface IsFQDNOptions { * @default false */ allow_wildcard?: boolean | undefined; + /** + * If `ignore_max_length` is set to true, the validator will not check for the standard max length of a domain. + * @default false + */ + ignore_max_length?: boolean | undefined; } /** diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index 75cc8f3e4e522c..e7e27845541d0c 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -189,11 +189,8 @@ import whitelistFunc from "validator/lib/whitelist"; let _isEmpty = validator.isEmpty; _isEmpty = isEmptyFunc; - validator.isFQDN; // $ExpectType (str: string, options?: IsFQDNOptions | undefined) => boolean - isFQDNFunc; // $ExpectType (str: string, options?: IsFQDNOptions | undefined) => boolean - const isFQDNOptions: IsFQDNOptions = { - allow_numeric_tld: true, - }; + let _isFQDN = validator.isFQDN; + _isFQDN = isFQDNFunc; let _isFloat = validator.isFloat; _isFloat = isFloatFunc; @@ -443,7 +440,7 @@ import isEmailFuncEs from "validator/es/lib/isEmail"; import isEmptyFuncEs from "validator/es/lib/isEmpty"; import isEthereumAddressFuncEs from "validator/es/lib/isEthereumAddress"; import isFloatFuncEs from "validator/es/lib/isFloat"; -import isFQDNFuncEs from "validator/es/lib/isFQDN"; +import isFQDNFuncEs, { IsFQDNOptions as IsFQDNOptionsEs } from "validator/es/lib/isFQDN"; import isFullWidthFuncEs from "validator/es/lib/isFullWidth"; import isHalfWidthFuncEs from "validator/es/lib/isHalfWidth"; import isHashFuncEs from "validator/es/lib/isHash"; @@ -771,11 +768,19 @@ const any: any = null; result = validator.isEmpty("sample"); result = validator.isEmpty("sample", isEmptyOptions); - const isFQDNOptions: validator.IsFQDNOptions = { - allow_wildcard: true, - }; result = validator.isFQDN("sample"); - result = validator.isFQDN("sample", isFQDNOptions); + result = validator.isFQDN("sample", {}); + result = validator.isFQDN( + "sample", + { + require_tld: true, + allow_underscores: true, + allow_trailing_dot: true, + allow_numeric_tld: true, + allow_wildcard: true, + ignore_max_length: true, + } satisfies IsFQDNOptions, + ); const isFloatOptions: validator.IsFloatOptions = {}; result = validator.isFloat("sample"); From e1dd81c9f496acd5fa88c5f1277c384fdd3d3cd0 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Wed, 12 Nov 2025 05:16:54 +0800 Subject: [PATCH 13/20] feat(validator): update isIBAN's locale list & factor out locale type (#74026) --- types/validator/es/lib/isIBAN.d.ts | 5 +- types/validator/index.d.ts | 2 + types/validator/lib/isIBAN.d.ts | 13 +++-- types/validator/validator-tests.ts | 92 ++++++++++++++++++++++++++++-- 4 files changed, 99 insertions(+), 13 deletions(-) diff --git a/types/validator/es/lib/isIBAN.d.ts b/types/validator/es/lib/isIBAN.d.ts index 8c1c77fcecf22e..9f7e6416bb053b 100644 --- a/types/validator/es/lib/isIBAN.d.ts +++ b/types/validator/es/lib/isIBAN.d.ts @@ -1,4 +1,3 @@ -import isIBAN, { IsIBANOptions as IsIBANValidationOptions, locales } from "../../lib/isIBAN"; +import isIBAN, { IBANLocale, IsIBANOptions, locales } from "../../lib/isIBAN"; export default isIBAN; -export { locales }; -export type IsIBANOptions = IsIBANValidationOptions; +export { IBANLocale, IsIBANOptions, locales }; diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index fa97c3586eb0b7..4c532deec9c903 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -265,6 +265,8 @@ declare namespace validator { export const isIBAN: typeof _isIBAN.default; export const ibanLocales: typeof _isIBAN.locales; + export type IBANLocale = _isIBAN.IBANLocale; + export type IsIBANOptions = _isIBAN.IsIBANOptions; /** * Check if a string is a BIC (Bank Identification Code) or SWIFT code. diff --git a/types/validator/lib/isIBAN.d.ts b/types/validator/lib/isIBAN.d.ts index 716f5a6d0d5f7a..fc4c1623722c17 100644 --- a/types/validator/lib/isIBAN.d.ts +++ b/types/validator/lib/isIBAN.d.ts @@ -1,4 +1,4 @@ -export const locales: Array< +export type IBANLocale = | "AD" | "AE" | "AL" @@ -17,6 +17,7 @@ export const locales: Array< | "DE" | "DK" | "DO" + | "DZ" | "EE" | "EG" | "ES" @@ -46,6 +47,7 @@ export const locales: Array< | "LT" | "LU" | "LV" + | "MA" | "MC" | "MD" | "ME" @@ -76,18 +78,19 @@ export const locales: Array< | "UA" | "VA" | "VG" - | "XK" ->; + | "XK"; + +export const locales: IBANLocale[]; export interface IsIBANOptions { /** * @default undefined */ - whitelist?: typeof locales | undefined; + whitelist?: IBANLocale[] | undefined; /** * @default undefined */ - blacklist?: typeof locales | undefined; + blacklist?: IBANLocale[] | undefined; } /** diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index e7e27845541d0c..41ea599c7d1298 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -40,7 +40,7 @@ import isHashFunc from "validator/lib/isHash"; import isHexadecimalFunc from "validator/lib/isHexadecimal"; import isHexColorFunc from "validator/lib/isHexColor"; import isHSLFunc from "validator/lib/isHSL"; -import isIBANFunc, { locales } from "validator/lib/isIBAN"; +import isIBANFunc, { IBANLocale, IsIBANOptions, locales as isIBANLocales } from "validator/lib/isIBAN"; import isIMEIFunc from "validator/lib/isIMEI"; import isInFunc from "validator/lib/isIn"; import isIntFunc from "validator/lib/isInt"; @@ -447,7 +447,11 @@ import isHashFuncEs from "validator/es/lib/isHash"; import isHexadecimalFuncEs from "validator/es/lib/isHexadecimal"; import isHexColorFuncEs from "validator/es/lib/isHexColor"; import isHSLFuncEs from "validator/es/lib/isHSL"; -import isIBANFuncEs from "validator/es/lib/isIBAN"; +import isIBANFuncEs, { + IBANLocale as IBANLocaleEs, + IsIBANOptions as IsIBANOptionsEs, + locales as isIBANLocalesEs, +} from "validator/es/lib/isIBAN"; import isInFuncEs from "validator/es/lib/isIn"; import isIntFuncEs from "validator/es/lib/isInt"; import isIPFuncEs from "validator/es/lib/isIP"; @@ -672,9 +676,87 @@ const any: any = null; result = validator.isBefore("sample", { comparisonDate: new Date().toString() }); result = validator.isIBAN("sample"); - result = validator.isIBAN("sample", { whitelist: ["GB", "BR"] }); - result = validator.isIBAN("sample", { blacklist: ["LT", "GL"] }); - result = validator.isIBAN("sample", { whitelist: ["GB", "BR"], blacklist: ["DK"] }); + result = validator.isIBAN("sample", {}); + result = validator.isIBAN("sample", { whitelist: ["AD"], blacklist: ["AD"] }); + result = validator.isIBAN("sample", { whitelist: ["AE"], blacklist: ["AE"] }); + result = validator.isIBAN("sample", { whitelist: ["AL"], blacklist: ["AL"] }); + result = validator.isIBAN("sample", { whitelist: ["AT"], blacklist: ["AT"] }); + result = validator.isIBAN("sample", { whitelist: ["AZ"], blacklist: ["AZ"] }); + result = validator.isIBAN("sample", { whitelist: ["BA"], blacklist: ["BA"] }); + result = validator.isIBAN("sample", { whitelist: ["BE"], blacklist: ["BE"] }); + result = validator.isIBAN("sample", { whitelist: ["BG"], blacklist: ["BG"] }); + result = validator.isIBAN("sample", { whitelist: ["BH"], blacklist: ["BH"] }); + result = validator.isIBAN("sample", { whitelist: ["BR"], blacklist: ["BR"] }); + result = validator.isIBAN("sample", { whitelist: ["BY"], blacklist: ["BY"] }); + result = validator.isIBAN("sample", { whitelist: ["CH"], blacklist: ["CH"] }); + result = validator.isIBAN("sample", { whitelist: ["CR"], blacklist: ["CR"] }); + result = validator.isIBAN("sample", { whitelist: ["CY"], blacklist: ["CY"] }); + result = validator.isIBAN("sample", { whitelist: ["CZ"], blacklist: ["CZ"] }); + result = validator.isIBAN("sample", { whitelist: ["DE"], blacklist: ["DE"] }); + result = validator.isIBAN("sample", { whitelist: ["DK"], blacklist: ["DK"] }); + result = validator.isIBAN("sample", { whitelist: ["DO"], blacklist: ["DO"] }); + result = validator.isIBAN("sample", { whitelist: ["DZ"], blacklist: ["DZ"] }); + result = validator.isIBAN("sample", { whitelist: ["EE"], blacklist: ["EE"] }); + result = validator.isIBAN("sample", { whitelist: ["EG"], blacklist: ["EG"] }); + result = validator.isIBAN("sample", { whitelist: ["ES"], blacklist: ["ES"] }); + result = validator.isIBAN("sample", { whitelist: ["FI"], blacklist: ["FI"] }); + result = validator.isIBAN("sample", { whitelist: ["FO"], blacklist: ["FO"] }); + result = validator.isIBAN("sample", { whitelist: ["FR"], blacklist: ["FR"] }); + result = validator.isIBAN("sample", { whitelist: ["GB"], blacklist: ["GB"] }); + result = validator.isIBAN("sample", { whitelist: ["GE"], blacklist: ["GE"] }); + result = validator.isIBAN("sample", { whitelist: ["GI"], blacklist: ["GI"] }); + result = validator.isIBAN("sample", { whitelist: ["GL"], blacklist: ["GL"] }); + result = validator.isIBAN("sample", { whitelist: ["GR"], blacklist: ["GR"] }); + result = validator.isIBAN("sample", { whitelist: ["GT"], blacklist: ["GT"] }); + result = validator.isIBAN("sample", { whitelist: ["HR"], blacklist: ["HR"] }); + result = validator.isIBAN("sample", { whitelist: ["HU"], blacklist: ["HU"] }); + result = validator.isIBAN("sample", { whitelist: ["IE"], blacklist: ["IE"] }); + result = validator.isIBAN("sample", { whitelist: ["IL"], blacklist: ["IL"] }); + result = validator.isIBAN("sample", { whitelist: ["IQ"], blacklist: ["IQ"] }); + result = validator.isIBAN("sample", { whitelist: ["IR"], blacklist: ["IR"] }); + result = validator.isIBAN("sample", { whitelist: ["IS"], blacklist: ["IS"] }); + result = validator.isIBAN("sample", { whitelist: ["IT"], blacklist: ["IT"] }); + result = validator.isIBAN("sample", { whitelist: ["JO"], blacklist: ["JO"] }); + result = validator.isIBAN("sample", { whitelist: ["KW"], blacklist: ["KW"] }); + result = validator.isIBAN("sample", { whitelist: ["KZ"], blacklist: ["KZ"] }); + result = validator.isIBAN("sample", { whitelist: ["LB"], blacklist: ["LB"] }); + result = validator.isIBAN("sample", { whitelist: ["LC"], blacklist: ["LC"] }); + result = validator.isIBAN("sample", { whitelist: ["LI"], blacklist: ["LI"] }); + result = validator.isIBAN("sample", { whitelist: ["LT"], blacklist: ["LT"] }); + result = validator.isIBAN("sample", { whitelist: ["LU"], blacklist: ["LU"] }); + result = validator.isIBAN("sample", { whitelist: ["LV"], blacklist: ["LV"] }); + result = validator.isIBAN("sample", { whitelist: ["MA"], blacklist: ["MA"] }); + result = validator.isIBAN("sample", { whitelist: ["MC"], blacklist: ["MC"] }); + result = validator.isIBAN("sample", { whitelist: ["MD"], blacklist: ["MD"] }); + result = validator.isIBAN("sample", { whitelist: ["ME"], blacklist: ["ME"] }); + result = validator.isIBAN("sample", { whitelist: ["MK"], blacklist: ["MK"] }); + result = validator.isIBAN("sample", { whitelist: ["MR"], blacklist: ["MR"] }); + result = validator.isIBAN("sample", { whitelist: ["MT"], blacklist: ["MT"] }); + result = validator.isIBAN("sample", { whitelist: ["MU"], blacklist: ["MU"] }); + result = validator.isIBAN("sample", { whitelist: ["MZ"], blacklist: ["MZ"] }); + result = validator.isIBAN("sample", { whitelist: ["NL"], blacklist: ["NL"] }); + result = validator.isIBAN("sample", { whitelist: ["NO"], blacklist: ["NO"] }); + result = validator.isIBAN("sample", { whitelist: ["PK"], blacklist: ["PK"] }); + result = validator.isIBAN("sample", { whitelist: ["PL"], blacklist: ["PL"] }); + result = validator.isIBAN("sample", { whitelist: ["PS"], blacklist: ["PS"] }); + result = validator.isIBAN("sample", { whitelist: ["PT"], blacklist: ["PT"] }); + result = validator.isIBAN("sample", { whitelist: ["QA"], blacklist: ["QA"] }); + result = validator.isIBAN("sample", { whitelist: ["RO"], blacklist: ["RO"] }); + result = validator.isIBAN("sample", { whitelist: ["RS"], blacklist: ["RS"] }); + result = validator.isIBAN("sample", { whitelist: ["SA"], blacklist: ["SA"] }); + result = validator.isIBAN("sample", { whitelist: ["SC"], blacklist: ["SC"] }); + result = validator.isIBAN("sample", { whitelist: ["SE"], blacklist: ["SE"] }); + result = validator.isIBAN("sample", { whitelist: ["SI"], blacklist: ["SI"] }); + result = validator.isIBAN("sample", { whitelist: ["SK"], blacklist: ["SK"] }); + result = validator.isIBAN("sample", { whitelist: ["SM"], blacklist: ["SM"] }); + result = validator.isIBAN("sample", { whitelist: ["SV"], blacklist: ["SV"] }); + result = validator.isIBAN("sample", { whitelist: ["TL"], blacklist: ["TL"] }); + result = validator.isIBAN("sample", { whitelist: ["TN"], blacklist: ["TN"] }); + result = validator.isIBAN("sample", { whitelist: ["TR"], blacklist: ["TR"] }); + result = validator.isIBAN("sample", { whitelist: ["UA"], blacklist: ["UA"] }); + result = validator.isIBAN("sample", { whitelist: ["VA"], blacklist: ["VA"] }); + result = validator.isIBAN("sample", { whitelist: ["VG"], blacklist: ["VG"] }); + result = validator.isIBAN("sample", { whitelist: ["XK"], blacklist: ["XK"] }); result = validator.isBIC("SBICKEN1345"); From 74209b3be06e0fc54f6ebc212b3474da7fc96ece Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Wed, 12 Nov 2025 05:17:13 +0800 Subject: [PATCH 14/20] feat(validator): add `options.withOptionalSeconds` to isTime() (#74044) --- types/validator/es/lib/isTime.d.ts | 1 + types/validator/index.d.ts | 11 +++++++---- types/validator/lib/isTime.d.ts | 1 + types/validator/validator-tests.ts | 12 ++++++++---- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/types/validator/es/lib/isTime.d.ts b/types/validator/es/lib/isTime.d.ts index 406d9d6c7a39e9..913a8524ae8ae6 100644 --- a/types/validator/es/lib/isTime.d.ts +++ b/types/validator/es/lib/isTime.d.ts @@ -1,2 +1,3 @@ import validator from "../../"; +export type IsTimeOptions = validator.IsTimeOptions; export default validator.isTime; diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index 4c532deec9c903..22ece45cd6adfb 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -1347,16 +1347,19 @@ declare namespace validator { export interface IsTimeOptions { /** - * 'hour24' will validate hours in 24 format and 'hour12' will validate hours in 12 format. + * `'hour24'` will validate hours in 24 format, + * `'hour12'` will validate hours in 12 format. * @default 'hour24' */ - hourFormat?: "hour12" | "hour24"; + hourFormat?: "hour12" | "hour24" | undefined; /** - * 'default' will validate HH:MM format, 'withSeconds' will validate the HH:MM:SS format + * `'default'` will validate `HH:MM` format, + * `'withSeconds'` will validate the `HH:MM:SS` format, + * `'withOptionalSeconds'` will validate `'HH:MM'` and `'HH:MM:SS'` formats. * * @default 'default' */ - mode?: "default" | "withSeconds"; + mode?: "default" | "withSeconds" | "withOptionalSeconds" | undefined; } /** diff --git a/types/validator/lib/isTime.d.ts b/types/validator/lib/isTime.d.ts index ff0753b8c888ef..54cac9eb093bff 100644 --- a/types/validator/lib/isTime.d.ts +++ b/types/validator/lib/isTime.d.ts @@ -1,2 +1,3 @@ import validator from "../"; +export type IsTimeOptions = validator.IsTimeOptions; export default validator.isTime; diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index 41ea599c7d1298..3788f6da21a8e6 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -84,7 +84,7 @@ import isSlugFunc from "validator/lib/isSlug"; import isStrongPasswordFunc from "validator/lib/isStrongPassword"; import isSurrogatePairFunc from "validator/lib/isSurrogatePair"; import isTaxIDFunc from "validator/lib/isTaxID"; -import isTimeFunc from "validator/lib/isTime"; +import isTimeFunc, { IsTimeOptions } from "validator/lib/isTime"; import isULIDFunc from "validator/lib/isULID"; import isUppercaseFunc from "validator/lib/isUppercase"; import isURLFunc from "validator/lib/isURL"; @@ -494,7 +494,7 @@ import isSlugFuncEs from "validator/es/lib/isSlug"; import isStrongPasswordFuncEs from "validator/es/lib/isStrongPassword"; import isSurrogatePairFuncEs from "validator/es/lib/isSurrogatePair"; import isTaxIDFuncEs from "validator/es/lib/isTaxID"; -import isTimeFuncEs from "validator/es/lib/isTime"; +import isTimeFuncEs, { IsTimeOptions as IsTimeOptionsEs } from "validator/es/lib/isTime"; import isULIDFuncEs from "validator/es/lib/isULID"; import isUppercaseFuncEs from "validator/es/lib/isUppercase"; import isURLFuncEs from "validator/es/lib/isURL"; @@ -1270,9 +1270,13 @@ const any: any = null; result = validator.isSurrogatePair("sample"); - const isTimeOptions: validator.IsTimeOptions = {}; result = validator.isTime("sample"); - result = validator.isTime("sample", isTimeOptions); + result = validator.isTime("sample", {} satisfies IsTimeOptions); + result = validator.isTime("sample", { hourFormat: "hour12" }); + result = validator.isTime("sample", { hourFormat: "hour24" }); + result = validator.isTime("sample", { mode: "default" }); + result = validator.isTime("sample", { mode: "withSeconds" }); + result = validator.isTime("sample", { mode: "withOptionalSeconds" }); result = validator.isULID("sample"); From 80a919b05f9c44f234e12fd71ba6e9ad72cc278b Mon Sep 17 00:00:00 2001 From: Erwan Jugand <47392755+erwanjugand@users.noreply.github.com> Date: Tue, 11 Nov 2025 22:35:03 +0100 Subject: [PATCH 15/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73998=20[chr?= =?UTF-8?q?ome]=20update=20browserAction=20namespace=20(MV2=20only)=20by?= =?UTF-8?q?=20@erwanjugand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 180 +++++++++-------------- types/chrome/test/index.ts | 282 ++++++++++--------------------------- 2 files changed, 140 insertions(+), 322 deletions(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index 4582035757825e..eddc80acf3486a 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -867,174 +867,120 @@ declare namespace chrome { */ export namespace browserAction { export interface BadgeBackgroundColorDetails { - /** An array of four integers in the range [0,255] that make up the RGBA color of the badge. For example, opaque red is [255, 0, 0, 255]. Can also be a string with a CSS value, with opaque red being #FF0000 or #F00. */ + /** An array of four integers in the range 0-255 that make up the RGBA color of the badge. Can also be a string with a CSS hex color value; for example, `#FF0000` or `#F00` (red). Renders colors at full opacity. */ color: string | extensionTypes.ColorArray; - /** Optional. Limits the change to when a particular tab is selected. Automatically resets when the tab is closed. */ - tabId?: number | undefined; + /** Limits the change to when a particular tab is selected. Automatically resets when the tab is closed. */ + tabId?: number | null | undefined; } export interface BadgeTextDetails { - /** Any number of characters can be passed, but only about four can fit in the space. */ + /** Any number of characters can be passed, but only about four can fit into the space. If an empty string (`''`) is passed, the badge text is cleared. If `tabId` is specified and `text` is null, the text for the specified tab is cleared and defaults to the global badge text. */ text?: string | null | undefined; - /** Optional. Limits the change to when a particular tab is selected. Automatically resets when the tab is closed. */ - tabId?: number | undefined; + /** Limits the change to when a particular tab is selected. Automatically resets when the tab is closed. */ + tabId?: number | null | undefined; } export interface TitleDetails { /** The string the browser action should display when moused over. */ title: string; /** Optional. Limits the change to when a particular tab is selected. Automatically resets when the tab is closed. */ - tabId?: number | null; + tabId?: number | null | undefined; } export interface TabDetails { - /** Optional. Specify the tab to get the information. If no tab is specified, the non-tab-specific information is returned. */ - tabId?: number | null; + /** The ID of the tab to query state for. If no tab is specified, the non-tab-specific state is returned. */ + tabId?: number | null | undefined; } - export interface TabIconDetails { - /** Optional. Either a relative image path or a dictionary {size -> relative image path} pointing to icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals scale, then image with size scale * 19 will be selected. Initially only scales 1 and 2 will be supported. At least one image must be specified. Note that 'details.path = foo' is equivalent to 'details.imageData = {'19': foo}' */ - path?: string | { [index: string]: string } | undefined; - /** Optional. Limits the change to when a particular tab is selected. Automatically resets when the tab is closed. */ - tabId?: number | undefined; - /** Optional. Either an ImageData object or a dictionary {size -> ImageData} representing icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals scale, then image with size scale * 19 will be selected. Initially only scales 1 and 2 will be supported. At least one image must be specified. Note that 'details.imageData = foo' is equivalent to 'details.imageData = {'19': foo}' */ - imageData?: ImageData | { [index: number]: ImageData } | undefined; - } + export type TabIconDetails = + & { + /** Limits the change to when a particular tab is selected. Automatically resets when the tab is closed. */ + tabId?: number | null | undefined; + } + & ( + | { + /** Either an ImageData object or a dictionary {size -> ImageData} representing an icon to be set. If the icon is specified as a dictionary, the image used is chosen depending on the screen's pixel density. If the number of image pixels that fit into one screen space unit equals `scale`, then an image with size `scale` \* n is selected, where _n_ is the size of the icon in the UI. At least one image must be specified. Note that 'details.imageData = foo' is equivalent to 'details.imageData = {'16': foo}' */ + imageData: ImageData | { [index: number]: ImageData }; + /** Either a relative image path or a dictionary {size -> relative image path} pointing to an icon to be set. If the icon is specified as a dictionary, the image used is chosen depending on the screen's pixel density. If the number of image pixels that fit into one screen space unit equals `scale`, then an image with size `scale` \* n is selected, where _n_ is the size of the icon in the UI. At least one image must be specified. Note that 'details.path = foo' is equivalent to 'details.path = {'16': foo}' */ + path?: string | { [index: string]: string } | undefined; + } + | { + /** Either an ImageData object or a dictionary {size -> ImageData} representing an icon to be set. If the icon is specified as a dictionary, the image used is chosen depending on the screen's pixel density. If the number of image pixels that fit into one screen space unit equals `scale`, then an image with size `scale` \* n is selected, where _n_ is the size of the icon in the UI. At least one image must be specified. Note that 'details.imageData = foo' is equivalent to 'details.imageData = {'16': foo}' */ + imageData?: ImageData | { [index: number]: ImageData } | undefined; + /** Either a relative image path or a dictionary {size -> relative image path} pointing to an icon to be set. If the icon is specified as a dictionary, the image used is chosen depending on the screen's pixel density. If the number of image pixels that fit into one screen space unit equals `scale`, then an image with size `scale` \* n is selected, where _n_ is the size of the icon in the UI. At least one image must be specified. Note that 'details.path = foo' is equivalent to 'details.path = {'16': foo}' */ + path: string | { [index: string]: string }; + } + ); export interface PopupDetails { - /** Optional. Limits the change to when a particular tab is selected. Automatically resets when the tab is closed. */ - tabId?: number | null; - /** The html file to show in a popup. If set to the empty string (''), no popup is shown. */ + /** Limits the change to when a particular tab is selected. Automatically resets when the tab is closed. */ + tabId?: number | null | undefined; + /** The relative path to the HTML file to show in a popup. If set to the empty string (`''`), no popup is shown.*/ popup: string; } - export interface BrowserClickedEvent extends chrome.events.Event<(tab: chrome.tabs.Tab) => void> {} - - /** - * @since Chrome 22 - * Enables the browser action for a tab. By default, browser actions are enabled. - * @param tabId The id of the tab for which you want to modify the browser action. - * @return The `enable` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. - */ - export function enable(tabId?: number | null): Promise; /** - * @since Chrome 22 - * Enables the browser action for a tab. By default, browser actions are enabled. - * @param tabId The id of the tab for which you want to modify the browser action. - * @param callback Supported since Chrome 67 + * Enables the browser action for a tab. Defaults to enabled. + * @param tabId The ID of the tab for which to modify the browser action. + * @param callback Since Chrome 67 */ export function enable(callback?: () => void): void; export function enable(tabId: number | null | undefined, callback?: () => void): void; + /** * Sets the background color for the badge. - * @return The `setBadgeBackgroundColor` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. - */ - export function setBadgeBackgroundColor(details: BadgeBackgroundColorDetails): Promise; - /** - * Sets the background color for the badge. - * @param callback Supported since Chrome 67 + * @param callback Since Chrome 67 */ export function setBadgeBackgroundColor(details: BadgeBackgroundColorDetails, callback?: () => void): void; + /** * Sets the badge text for the browser action. The badge is displayed on top of the icon. - * @return The `setBadgeText` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. - */ - export function setBadgeText(details: BadgeTextDetails): Promise; - /** - * Sets the badge text for the browser action. The badge is displayed on top of the icon. - * @param callback Supported since Chrome 67 - */ - export function setBadgeText(details: BadgeTextDetails, callback: () => void): void; - /** - * Sets the title of the browser action. This shows up in the tooltip. - * @return The `setTitle` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. + * @param callback Since Chrome 67 */ - export function setTitle(details: TitleDetails): Promise; - /** - * Sets the title of the browser action. This shows up in the tooltip. - * @param callback Supported since Chrome 67 - */ - export function setTitle(details: TitleDetails, callback: () => void): void; + export function setBadgeText(details: BadgeTextDetails, callback?: () => void): void; + /** - * @since Chrome 19 - * Gets the badge text of the browser action. If no tab is specified, the non-tab-specific badge text is returned. - * @param callback Supported since Chrome 67 + * Sets the title of the browser action. This title appears in the tooltip. + * @param callback Since Chrome 67 */ + export function setTitle(details: TitleDetails, callback?: () => void): void; + + /** Gets the badge text of the browser action. If no tab is specified, the non-tab-specific badge text is returned. */ export function getBadgeText(details: TabDetails, callback: (result: string) => void): void; + /** - * @since Chrome 19 - * Gets the badge text of the browser action. If no tab is specified, the non-tab-specific badge text is returned. - * @return The `getBadgeText` method provides its result via callback or returned as a `Promise` (MV3 only). - */ - export function getBadgeText(details: TabDetails): Promise; - /** - * Sets the html document to be opened as a popup when the user clicks on the browser action's icon. - * @return The `setPopup` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. - */ - export function setPopup(details: PopupDetails): Promise; - /** - * Sets the html document to be opened as a popup when the user clicks on the browser action's icon. - * @param callback Supported since Chrome 67 + * Sets the HTML document to be opened as a popup when the user clicks the browser action icon. + * @param callback Since Chrome 67 */ export function setPopup(details: PopupDetails, callback?: () => void): void; + /** - * @since Chrome 22 - * Disables the browser action for a tab. - * @param tabId The id of the tab for which you want to modify the browser action. - * @return The `disable` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. - */ - export function disable(tabId?: number | null): Promise; - /** - * @since Chrome 22 * Disables the browser action for a tab. - * @param tabId The id of the tab for which you want to modify the browser action. - * @param callback Supported since Chrome 67 - */ - export function disable(callback: () => void): void; - export function disable(tabId?: number | null, callback?: () => void): void; - /** - * @since Chrome 19 - * Gets the title of the browser action. + * @param tabId The ID of the tab for which to modify the browser action. + * @param callback since Chrome 67 */ + export function disable(callback?: () => void): void; + export function disable(tabId: number | null | undefined, callback?: () => void): void; + + /** Gets the title of the browser action. */ export function getTitle(details: TabDetails, callback: (result: string) => void): void; - /** - * @since Chrome 19 - * Gets the title of the browser action. - * @return The `getTitle` method provides its result via callback or returned as a `Promise` (MV3 only). - */ - export function getTitle(details: TabDetails): Promise; - /** - * @since Chrome 19 - * Gets the background color of the browser action. - */ + + /** Gets the background color of the browser action. */ export function getBadgeBackgroundColor( details: TabDetails, callback: (result: extensionTypes.ColorArray) => void, ): void; - /** - * @since Chrome 19 - * Gets the background color of the browser action. - * @return The `getBadgeBackgroundColor` method provides its result via callback or returned as a `Promise` (MV3 only). - */ - export function getBadgeBackgroundColor(details: TabDetails): Promise; - /** - * @since Chrome 19 - * Gets the html document set as the popup for this browser action. - */ + + /** Gets the HTML document that is set as the popup for this browser action. */ export function getPopup(details: TabDetails, callback: (result: string) => void): void; + /** - * @since Chrome 19 - * Gets the html document set as the popup for this browser action. - * @return The `getPopup` method provides its result via callback or returned as a `Promise` (MV3 only). - */ - export function getPopup(details: TabDetails): Promise; - /** - * Sets the icon for the browser action. The icon can be specified either as the path to an image file or as the pixel data from a canvas element, or as dictionary of either one of those. Either the path or the imageData property must be specified. + * Sets the icon for the browser action. The icon can be specified as the path to an image file, as the pixel data from a canvas element, or as a dictionary of one of those. Either the `path` or the `imageData` property must be specified. */ export function setIcon(details: TabIconDetails, callback?: () => void): void; - /** Fired when a browser action icon is clicked. This event will not fire if the browser action has a popup. */ - export var onClicked: BrowserClickedEvent; + /** Fired when a browser action icon is clicked. Does not fire if the browser action has a popup. */ + export const onClicked: events.Event<(tab: chrome.tabs.Tab) => void>; } //////////////////// diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index 0e211acb8ebf62..b3982232c5cfb3 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -153,25 +153,6 @@ function testBookmarks() { }); } -// https://developer.chrome.com/extensions/examples/api/browserAction/make_page_red/background.js -function pageRedder() { - chrome.browserAction.onClicked.addListener(function(tab) { - // No tabs or host permissions needed! - console.log("Turning " + tab.url + " red!"); - chrome.tabs.executeScript({ - code: "document.body.style.backgroundColor=\"red\"", - }); - }); -} - -// https://developer.chrome.com/extensions/examples/api/browserAction/print/background.js -function printPage() { - chrome.browserAction.onClicked.addListener(function(tab) { - var action_url = "javascript:window.print();"; - chrome.tabs.update(tab.id!, { url: action_url }); - }); -} - // https://developer.chrome.com/docs/extensions/reference/api/webNavigation function testWebNavigation() { /** @@ -2202,196 +2183,101 @@ function testSearch() { chrome.search.query(queryInfo1, () => {}).then(() => {}); } -// https://developer.chrome.com/docs/extensions/reference/browserAction/#method-enable -function testBrowserAcionEnable() { - chrome.browserAction.enable(); - chrome.browserAction.enable(console.log); - chrome.browserAction.enable(0); - chrome.browserAction.enable(0, console.log); - chrome.browserAction.enable(null); - chrome.browserAction.enable(null, console.log); - chrome.browserAction.enable(undefined); - chrome.browserAction.enable(undefined, console.log); -} +// https://developer.chrome.com/docs/extensions/mv2/reference/browserAction +function testBrowserAction() { + const tabId = 0; + chrome.browserAction.disable(); // $ExpectType void + chrome.browserAction.disable(() => void 0); // $ExpectType void + chrome.browserAction.disable(tabId); // $ExpectType void + chrome.browserAction.disable(tabId, () => void 0); // $ExpectType void + chrome.browserAction.disable(null); // $ExpectType void + chrome.browserAction.disable(null, () => void 0); // $ExpectType void -// https://developer.chrome.com/docs/extensions/reference/browserAction/#method-disable -function testBrowserAcionDisable() { - chrome.browserAction.disable(); - chrome.browserAction.disable(console.log); - chrome.browserAction.disable(0); - chrome.browserAction.disable(0, console.log); - chrome.browserAction.disable(null); - chrome.browserAction.disable(null, console.log); - chrome.browserAction.disable(undefined); - chrome.browserAction.disable(undefined, console.log); -} + chrome.browserAction.enable(); // $ExpectType void + chrome.browserAction.enable(() => void 0); // $ExpectType void + chrome.browserAction.enable(tabId); // $ExpectType void + chrome.browserAction.enable(tabId, () => void 0); // $ExpectType void + chrome.browserAction.enable(null); // $ExpectType void + chrome.browserAction.enable(null, () => void 0); // $ExpectType void -// https://developer.chrome.com/docs/extensions/reference/browserAction/#method-getBadgeBackgroundColor -function testBrowserAcionGetBadgeBackgroundColor() { - chrome.browserAction.getBadgeBackgroundColor({}, console.log); - chrome.browserAction.getBadgeBackgroundColor({ tabId: 0 }, console.log); - chrome.browserAction.getBadgeBackgroundColor({ tabId: null }, console.log); - chrome.browserAction.getBadgeBackgroundColor({ tabId: undefined }, console.log); + const getDetails: chrome.browserAction.TabDetails = { tabId }; - // @ts-expect-error - chrome.browserAction.getBadgeBackgroundColor(); - // @ts-expect-error - chrome.browserAction.getBadgeBackgroundColor(null); - // @ts-expect-error - chrome.browserAction.getBadgeBackgroundColor(undefined); -} + chrome.browserAction.getBadgeBackgroundColor(getDetails, (result) => { // $ExpectType void + result; // $ExpectType ColorArray + }); + // @ts-expect-error No matching signature + chrome.browserAction.getBadgeBackgroundColor(getDetails); -// https://developer.chrome.com/docs/extensions/reference/browserAction/#method-getBadgeText -function testBrowserAcionGetBadgeText() { - chrome.browserAction.getBadgeText({}, console.log); - chrome.browserAction.getBadgeText({ tabId: 0 }, console.log); - chrome.browserAction.getBadgeText({ tabId: null }, console.log); - chrome.browserAction.getBadgeText({ tabId: undefined }, console.log); + chrome.browserAction.getBadgeText(getDetails, (result) => { // $ExpectType void + result; // $ExpectType string + }); + // @ts-expect-error No matching signature + chrome.browserAction.getBadgeText(getDetails); - // @ts-expect-error - chrome.browserAction.getBadgeText(); - // @ts-expect-error - chrome.browserAction.getBadgeText(null); - // @ts-expect-error - chrome.browserAction.getBadgeText(undefined); - // @ts-expect-error - chrome.browserAction.getBadgeText(console.log); -} + chrome.browserAction.getPopup(getDetails, (result) => { // $ExpectType void + result; // $ExpectType string + }); + // @ts-expect-error No matching signature + chrome.browserAction.getPopup(getDetails); -// https://developer.chrome.com/docs/extensions/reference/browserAction/#method-getPopup -function testBrowserAcionGetPopup() { - chrome.browserAction.getPopup({}); - chrome.browserAction.getPopup({}, console.log); - chrome.browserAction.getPopup({ tabId: 0 }); - chrome.browserAction.getPopup({ tabId: 0 }, console.log); - chrome.browserAction.getPopup({ tabId: null }); - chrome.browserAction.getPopup({ tabId: null }, console.log); - chrome.browserAction.getPopup({ tabId: undefined }); - chrome.browserAction.getPopup({ tabId: undefined }, console.log); + chrome.browserAction.getTitle(getDetails, (result) => { // $ExpectType void + result; // $ExpectType string + }); + // @ts-expect-error No matching signature + chrome.browserAction.getTitle(getDetails); - // @ts-expect-error - chrome.browserAction.getPopup(); - // @ts-expect-error - chrome.browserAction.getPopup(null); - // @ts-expect-error - chrome.browserAction.getPopup(undefined); - // @ts-expect-error - chrome.browserAction.getPopup(console.log); -} + const badgeBackgroundColorDetails: chrome.browserAction.BadgeBackgroundColorDetails = { + color: [255, 0, 0, 255], + tabId, + }; -// https://developer.chrome.com/docs/extensions/reference/browserAction/#method-getPopup -function testBrowserAcionGetTitle() { - chrome.browserAction.getTitle({}); - chrome.browserAction.getTitle({}, console.log); - chrome.browserAction.getTitle({ tabId: 0 }); - chrome.browserAction.getTitle({ tabId: 0 }, console.log); - chrome.browserAction.getTitle({ tabId: null }); - chrome.browserAction.getTitle({ tabId: null }, console.log); - chrome.browserAction.getTitle({ tabId: undefined }); - chrome.browserAction.getTitle({ tabId: undefined }, console.log); + chrome.browserAction.setBadgeBackgroundColor(badgeBackgroundColorDetails); // $ExpectType void + chrome.browserAction.setBadgeBackgroundColor(badgeBackgroundColorDetails, () => void 0); // $ExpectType void - // @ts-expect-error - chrome.browserAction.getTitle(); - // @ts-expect-error - chrome.browserAction.getTitle(null); - // @ts-expect-error - chrome.browserAction.getTitle(undefined); - // @ts-expect-error - chrome.browserAction.getTitle(console.log); -} + const badgeTextDetails: chrome.browserAction.BadgeTextDetails = { + text: "text", + tabId, + }; -// https://developer.chrome.com/docs/extensions/reference/browserAction/#method-setBadgeBackgroundColor -function testBrowserAcionSetBadgeBackgroundColor() { - chrome.browserAction.setBadgeBackgroundColor({ color: "red" }); - chrome.browserAction.setBadgeBackgroundColor({ color: "red" }, console.log); - chrome.browserAction.setBadgeBackgroundColor({ color: "red", tabId: 0 }); - chrome.browserAction.setBadgeBackgroundColor({ color: "red", tabId: 0 }, console.log); - chrome.browserAction.setBadgeBackgroundColor({ color: [1, 2, 3, 4], tabId: 0 }); - chrome.browserAction.setBadgeBackgroundColor({ color: [1, 2, 3, 4], tabId: 0 }, console.log); + chrome.browserAction.setBadgeText(badgeTextDetails); // $ExpectType void + chrome.browserAction.setBadgeText(badgeTextDetails, () => void 0); // $ExpectType void - // @ts-expect-error - chrome.browserAction.setBadgeBackgroundColor(); - // @ts-expect-error - chrome.browserAction.setBadgeBackgroundColor({}); - // @ts-expect-error - chrome.browserAction.setBadgeBackgroundColor({ tabId: 0 }); - // @ts-expect-error - chrome.browserAction.setBadgeBackgroundColor({ color: [1, 2, 3] }, console.log); - // @ts-expect-error - chrome.browserAction.setBadgeBackgroundColor(null); - // @ts-expect-error - chrome.browserAction.setBadgeBackgroundColor(undefined); -} - -// https://developer.chrome.com/docs/extensions/reference/browserAction/#method-setBadgeText -function testBrowserActionSetBrowserBadgeText() { - chrome.browserAction.setBadgeText({}); - chrome.browserAction.setBadgeText({ text: "test" }); - chrome.browserAction.setBadgeText({ text: null }); - chrome.browserAction.setBadgeText({ text: undefined }); - chrome.browserAction.setBadgeText({ tabId: 123 }); - chrome.browserAction.setBadgeText({ text: "test", tabId: 123 }); - chrome.browserAction.setBadgeText({}, () => {}); + const iconDetails: chrome.browserAction.TabIconDetails = { + imageData: { 16: new ImageData(16, 16) }, + tabId, + }; - // @ts-expect-error - chrome.browserAction.setBadgeText(); - // @ts-expect-error - chrome.browserAction.setBadgeText(undefined); -} + const iconDetails2: chrome.browserAction.TabIconDetails = { + path: "path/to/icon.png", + tabId, + }; -// https://developer.chrome.com/docs/extensions/reference/browserAction/#method-setIcon -function testBrowserAcionSetIcon() { - chrome.browserAction.setIcon({ path: "/icon.png" }); - chrome.browserAction.setIcon({ path: "/icon.png" }, console.log); - chrome.browserAction.setIcon({ path: { 16: "/icon.png" } }); - chrome.browserAction.setIcon({ path: { 16: "/icon.png" } }, console.log); - chrome.browserAction.setIcon({ path: { 16: "/icon.png" }, tabId: 0 }); - chrome.browserAction.setIcon({ path: { 16: "/icon.png" }, tabId: 0 }, console.log); + chrome.browserAction.setIcon(iconDetails); // $ExpectType void + chrome.browserAction.setIcon(iconDetails2); // $ExpectType void + chrome.browserAction.setIcon(iconDetails, () => void 0); // $ExpectType void + chrome.browserAction.setIcon(iconDetails2, () => void 0); // $ExpectType void + // @ts-expect-error Either the path or imageData property must be specified. + chrome.browserAction.setIcon({}); - // @ts-expect-error - chrome.browserAction.setIcon(); - // @ts-expect-error - chrome.browserAction.setIcon(null); - // @ts-expect-error - chrome.browserAction.setIcon(undefined); -} + const popupDetails: chrome.browserAction.PopupDetails = { + popup: "popup.html", + tabId, + }; -// https://developer.chrome.com/docs/extensions/reference/browserAction/#method-setPopup -function testBrowserAcionSetPopup() { - chrome.browserAction.setPopup({ popup: "index.html" }); - chrome.browserAction.setPopup({ popup: "index.html" }, console.log); - chrome.browserAction.setPopup({ popup: "index.html", tabId: 0 }); - chrome.browserAction.setPopup({ popup: "index.html", tabId: 0 }, console.log); - chrome.browserAction.setPopup({ popup: "index.html", tabId: null }); - chrome.browserAction.setPopup({ popup: "index.html", tabId: null }, console.log); - chrome.browserAction.setPopup({ popup: "index.html", tabId: undefined }); - chrome.browserAction.setPopup({ popup: "index.html", tabId: undefined }, console.log); + chrome.browserAction.setPopup(popupDetails); // $ExpectType void + chrome.browserAction.setPopup(popupDetails, () => void 0); // $ExpectType void - // @ts-expect-error - chrome.browserAction.setPopup(); - // @ts-expect-error - chrome.browserAction.setPopup(null); - // @ts-expect-error - chrome.browserAction.setPopup(undefined); -} + const titleDetails: chrome.browserAction.TitleDetails = { + title: "title", + tabId, + }; -// https://developer.chrome.com/docs/extensions/reference/browserAction/#method-setTitle -function testBrowserAcionSetTitle() { - chrome.browserAction.setTitle({ title: "Title" }); - chrome.browserAction.setTitle({ title: "Title" }, console.log); - chrome.browserAction.setTitle({ title: "Title", tabId: 0 }); - chrome.browserAction.setTitle({ title: "Title", tabId: 0 }, console.log); - chrome.browserAction.setTitle({ title: "Title", tabId: null }); - chrome.browserAction.setTitle({ title: "Title", tabId: null }, console.log); - chrome.browserAction.setTitle({ title: "Title", tabId: undefined }); - chrome.browserAction.setTitle({ title: "Title", tabId: undefined }, console.log); + chrome.browserAction.setTitle(titleDetails); // $ExpectType void + chrome.browserAction.setTitle(titleDetails, () => void 0); // $ExpectType void - // @ts-expect-error - chrome.browserAction.setTitle(); - // @ts-expect-error - chrome.browserAction.setTitle(null); - // @ts-expect-error - chrome.browserAction.setTitle(undefined); + checkChromeEvent(chrome.browserAction.onClicked, (tab) => { + tab; // $ExpectType Tab + }); } // https://developer.chrome.com/docs/extensions/reference/api/action @@ -2682,20 +2568,6 @@ async function testBookmarksForPromise() { await chrome.bookmarks.removeTree("id1"); } -// https://developer.chrome.com/docs/extensions/reference/browserAction -async function testBrowserActionForPromise() { - await chrome.browserAction.enable(0); - await chrome.browserAction.setBadgeBackgroundColor({ color: "color1" }); - await chrome.browserAction.setBadgeText({}); - await chrome.browserAction.setTitle({ title: "title1" }); - await chrome.browserAction.getBadgeText({}); - await chrome.browserAction.setPopup({ popup: "popup1" }); - await chrome.browserAction.disable(0); - await chrome.browserAction.getTitle({}); - await chrome.browserAction.getBadgeBackgroundColor({}); - await chrome.browserAction.getPopup({}); -} - // https://developer.chrome.com/docs/extensions/reference/api/cookies async function testCookie() { chrome.cookies.OnChangedCause.EVICTED === "evicted"; From d3264da0a191420fbaca0473e1bd0782847ca015 Mon Sep 17 00:00:00 2001 From: Erwan Jugand <47392755+erwanjugand@users.noreply.github.com> Date: Tue, 11 Nov 2025 22:35:45 +0100 Subject: [PATCH 16/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73999=20[chr?= =?UTF-8?q?ome]=20update=20pageAction=20namespace=20(MV2=20only)=20by=20@e?= =?UTF-8?q?rwanjugand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 86 +++++++++++++++++++------------------- types/chrome/test/index.ts | 61 +++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 44 deletions(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index eddc80acf3486a..4c7b625c6d0c96 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -7497,8 +7497,6 @@ declare namespace chrome { * MV2 only */ export namespace pageAction { - export interface PageActionClickedEvent extends chrome.events.Event<(tab: chrome.tabs.Tab) => void> {} - export interface TitleDetails { /** The id of the tab for which you want to modify the page action. */ tabId: number; @@ -7506,77 +7504,77 @@ declare namespace chrome { title: string; } - export interface GetDetails { - /** Specify the tab to get the title from. */ + export interface TabDetails { + /** The ID of the tab to query state for. */ tabId: number; } export interface PopupDetails { /** The id of the tab for which you want to modify the page action. */ tabId: number; - /** The html file to show in a popup. If set to the empty string (''), no popup is shown. */ + /** The relative path to the HTML file to show in a popup. If set to the empty string (`''`), no popup is shown. */ popup: string; } - export interface IconDetails { - /** The id of the tab for which you want to modify the page action. */ - tabId: number; - /** - * Optional. - * @deprecated This argument is ignored. - */ - iconIndex?: number | undefined; - /** - * Optional. - * Either an ImageData object or a dictionary {size -> ImageData} representing icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals scale, then image with size scale * 19 will be selected. Initially only scales 1 and 2 will be supported. At least one image must be specified. Note that 'details.imageData = foo' is equivalent to 'details.imageData = {'19': foo}' - */ - imageData?: ImageData | { [index: number]: ImageData } | undefined; - /** - * Optional. - * Either a relative image path or a dictionary {size -> relative image path} pointing to icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals scale, then image with size scale * 19 will be selected. Initially only scales 1 and 2 will be supported. At least one image must be specified. Note that 'details.path = foo' is equivalent to 'details.imageData = {'19': foo}' - */ - path?: string | { [index: string]: string } | undefined; - } + export type IconDetails = + & { + /** @deprecated This argument is ignored. */ + iconIndex?: number | undefined; + /** The id of the tab for which you want to modify the page action. */ + tabId: number; + } + & ( + | { + /** Either an ImageData object or a dictionary {size -> ImageData} representing icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals `scale`, then image with size `scale` \* n will be selected, where n is the size of the icon in the UI. At least one image must be specified. Note that 'details.imageData = foo' is equivalent to 'details.imageData = {'16': foo}' */ + imageData: ImageData | { [index: number]: ImageData }; + /** Either a relative image path or a dictionary {size -> relative image path} pointing to icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals `scale`, then image with size `scale` \* n will be selected, where n is the size of the icon in the UI. At least one image must be specified. Note that 'details.path = foo' is equivalent to 'details.path = {'16': foo}' */ + path?: string | { [index: string]: string } | undefined; + } + | { + /** Either an ImageData object or a dictionary {size -> ImageData} representing icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals `scale`, then image with size `scale` \* n will be selected, where n is the size of the icon in the UI. At least one image must be specified. Note that 'details.imageData = foo' is equivalent to 'details.imageData = {'16': foo}' */ + imageData?: ImageData | { [index: number]: ImageData } | undefined; + /** Either a relative image path or a dictionary {size -> relative image path} pointing to icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals `scale`, then image with size `scale` \* n will be selected, where n is the size of the icon in the UI. At least one image must be specified. Note that 'details.path = foo' is equivalent to 'details.path = {'16': foo}' */ + path: string | { [index: string]: string }; + } + ); /** - * Shows the page action. The page action is shown whenever the tab is selected. + * Hides the page action. Hidden page actions still appear in the Chrome toolbar, but are grayed out. * @param tabId The id of the tab for which you want to modify the page action. - * @param callback Supported since Chrome 67 + * @param callback Since Chrome 67 */ export function hide(tabId: number, callback?: () => void): void; + /** * Shows the page action. The page action is shown whenever the tab is selected. * @param tabId The id of the tab for which you want to modify the page action. - * @param callback Supported since Chrome 67 + * @param callback Since Chrome 67 */ export function show(tabId: number, callback?: () => void): void; + /** * Sets the title of the page action. This is displayed in a tooltip over the page action. - * @param callback Supported since Chrome 67 + * @param callback Since Chrome 67 */ export function setTitle(details: TitleDetails, callback?: () => void): void; + /** - * Sets the html document to be opened as a popup when the user clicks on the page action's icon. - * @param callback Supported since Chrome 67 + * Sets the HTML document to be opened as a popup when the user clicks on the page action's icon. + * @param callback Since Chrome 67 */ export function setPopup(details: PopupDetails, callback?: () => void): void; - /** - * Gets the title of the page action. - * @since Chrome 19 - */ - export function getTitle(details: GetDetails, callback: (result: string) => void): void; - /** - * Gets the html document set as the popup for this page action. - * @since Chrome 19 - */ - export function getPopup(details: GetDetails, callback: (result: string) => void): void; - /** - * Sets the icon for the page action. The icon can be specified either as the path to an image file or as the pixel data from a canvas element, or as dictionary of either one of those. Either the path or the imageData property must be specified. - */ + + /** Gets the title of the page action. */ + export function getTitle(details: TabDetails, callback: (result: string) => void): void; + + /** Gets the html document set as the popup for this page action. */ + export function getPopup(details: TabDetails, callback: (result: string) => void): void; + + /** Sets the icon for the page action. The icon can be specified either as the path to an image file or as the pixel data from a canvas element, or as dictionary of either one of those. Either the path or the imageData property must be specified. */ export function setIcon(details: IconDetails, callback?: () => void): void; /** Fired when a page action icon is clicked. This event will not fire if the page action has a popup. */ - export var onClicked: PageActionClickedEvent; + export const onClicked: events.Event<(tab: chrome.tabs.Tab) => void>; } //////////////////// diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index b3982232c5cfb3..05f3b71a5caaec 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -4784,6 +4784,67 @@ function testI18n() { chrome.i18n.getUILanguage(); // $ExpectType string } +// https://developer.chrome.com/docs/extensions/mv2/reference/pageAction +function testPageAction() { + const tabId = 1; + const getDetails: chrome.pageAction.TabDetails = { tabId }; + + chrome.pageAction.getPopup(getDetails, (result) => { // $ExpectType void + result; // $ExpectType string + }); + // @ts-expect-error No matching signature + chrome.pageAction.getPopup(getDetails); + + chrome.pageAction.getTitle(getDetails, (result) => { // $ExpectType void + result; // $ExpectType string + }); + // @ts-expect-error No matching signature + chrome.pageAction.getTitle(getDetails); + + chrome.pageAction.hide(tabId); // $ExpectType void + chrome.pageAction.hide(tabId, () => void 0); // $ExpectType void + + const iconDetails: chrome.pageAction.IconDetails = { + tabId, + path: "path/to/icon.png", + }; + + const iconDetails2: chrome.pageAction.IconDetails = { + tabId, + imageData: new ImageData(16, 16), + }; + + chrome.pageAction.setIcon(iconDetails); // $ExpectType void + chrome.pageAction.setIcon(iconDetails2); // $ExpectType void + chrome.pageAction.setIcon(iconDetails, () => void 0); // $ExpectType void + chrome.pageAction.setIcon(iconDetails2, () => void 0); // $ExpectType void + // @ts-expect-error Either the path or imageData property must be specified. + chrome.pageAction.setIcon({}); + + const popupDetails: chrome.pageAction.PopupDetails = { + popup: "popup.html", + tabId, + }; + + chrome.pageAction.setPopup(popupDetails); // $ExpectType void + chrome.pageAction.setPopup(popupDetails, () => void 0); // $ExpectType void + + const titleDetails: chrome.pageAction.TitleDetails = { + title: "My Page Action", + tabId, + }; + + chrome.pageAction.setTitle(titleDetails); // $ExpectType void + chrome.pageAction.setTitle(titleDetails, () => void 0); // $ExpectType void + + chrome.pageAction.show(tabId); // $ExpectType void + chrome.pageAction.show(tabId, () => void 0); // $ExpectType void + + checkChromeEvent(chrome.pageAction.onClicked, (tab) => { + tab; // $ExpectType Tab + }); +} + // https://developer.chrome.com/docs/extensions/reference/api/pageCapture function testPageCapture() { const details = { tabId: 0 }; From 69142f72d19996eb56e375f762638a064a7dc348 Mon Sep 17 00:00:00 2001 From: Erwan Jugand <47392755+erwanjugand@users.noreply.github.com> Date: Tue, 11 Nov 2025 22:36:47 +0100 Subject: [PATCH 17/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74000=20[chr?= =?UTF-8?q?ome]=20update=20declarativeWebRequest=20namespace=20(MV2=20only?= =?UTF-8?q?)=20by=20@erwanjugand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 161 +++++++++++++++++++++++++++++++++++-- types/chrome/test/index.ts | 26 ++++++ 2 files changed, 181 insertions(+), 6 deletions(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index 4c7b625c6d0c96..765553826cd06f 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -2435,109 +2435,258 @@ declare namespace chrome { * @deprecated Check out the {@link declarativeNetRequest} API instead */ export namespace declarativeWebRequest { + /** Filters request headers for various criteria. Multiple criteria are evaluated as a conjunction. */ export interface HeaderFilter { + /** Matches if the header name is equal to the specified string. */ nameEquals?: string | undefined; + /** Matches if the header value contains all of the specified strings. */ valueContains?: string | string[] | undefined; + /** Matches if the header name ends with the specified string. */ nameSuffix?: string | undefined; + /** Matches if the header value ends with the specified string. */ valueSuffix?: string | undefined; + /** Matches if the header value starts with the specified string. */ valuePrefix?: string | undefined; + /** Matches if the header name contains all of the specified strings. */ nameContains?: string | string[] | undefined; + /** Matches if the header value is equal to the specified string. */ valueEquals?: string | undefined; + /** Matches if the header name starts with the specified string. */ namePrefix?: string | undefined; } + /** Adds the response header to the response of this web request. As multiple response headers may share the same name, you need to first remove and then add a new response header in order to replace one. */ export interface AddResponseHeader { + /** HTTP response header name. */ name: string; + /** HTTP response header value. */ value: string; } + /** Removes one or more cookies of response. Note that it is preferred to use the Cookies API because this is computationally less expensive. */ export interface RemoveResponseCookie { - filter: ResponseCookie; + /** Filter for cookies that will be removed. All empty entries are ignored. */ + filter: FilterResponseCookie; } + /** Removes all response headers of the specified names and values. */ export interface RemoveResponseHeader { + /** HTTP request header name (case-insensitive). */ name: string; + /** HTTP request header value (case-insensitive). */ value?: string | undefined; } + /** Matches network events by various criteria. */ export interface RequestMatcher { + /** Matches if the MIME media type of a response (from the HTTP Content-Type header) is contained in the list. */ contentType?: string[] | undefined; - url?: chrome.events.UrlFilter | undefined; + /** Matches if the conditions of the UrlFilter are fulfilled for the URL of the request. */ + url?: events.UrlFilter | undefined; + /** Matches if the MIME media type of a response (from the HTTP Content-Type header) is not contained in the list. */ excludeContentType?: string[] | undefined; + /** Matches if none of the request headers is matched by any of the HeaderFilters. */ + excludeResponseHeaders?: HeaderFilter[] | undefined; + /** Matches if none of the response headers is matched by any of the HeaderFilters. */ excludeResponseHeader?: HeaderFilter[] | undefined; - resourceType?: string | undefined; + /** + * Matches if the conditions of the UrlFilter are fulfilled for the 'first party' URL of the request. The 'first party' URL of a request, when present, can be different from the request's target URL, and describes what is considered 'first party' for the sake of third-party checks for cookies. + * @deprecated since Chrome 82 + */ + firstPartyForCookiesUrl?: events.UrlFilter | undefined; + /** Matches if some of the request headers is matched by one of the HeaderFilters. */ + requestHeaders?: HeaderFilter[] | undefined; + /** Matches if the request type of a request is contained in the list. Requests that cannot match any of the types will be filtered out. */ + resourceType?: `${webRequest.ResourceType}`[] | undefined; + /** Matches if some of the response headers is matched by one of the HeaderFilters. */ responseHeaders?: HeaderFilter[] | undefined; + /** Contains a list of strings describing stages. Allowed values are 'onBeforeRequest', 'onBeforeSendHeaders', 'onHeadersReceived', 'onAuthRequired'. If this attribute is present, then it limits the applicable stages to those listed. Note that the whole condition is only applicable in stages compatible with all attributes. */ + stages?: `${Stage}`[] | undefined; + /** + * If set to true, matches requests that are subject to third-party cookie policies. If set to false, matches all other requests. + * @deprecated since Chrome 87 + */ + thirdPartyForCookies?: boolean | undefined; } + /** Masks all rules that match the specified criteria. */ export interface IgnoreRules { - lowerPriorityThan: number; + /** If set, rules with the specified tag are ignored. This ignoring is not persisted, it affects only rules and their actions of the same network request stage. Note that rules are executed in descending order of their priorities. This action affects rules of lower priority than the current rule. Rules with the same priority may or may not be ignored. */ + hasTag?: string | undefined; + /** If set, rules with a lower priority than the specified value are ignored. This boundary is not persisted, it affects only rules and their actions of the same network request stage. */ + lowerPriorityThan?: number | undefined; } + /** Declarative event action that redirects a network request to an empty document. */ export interface RedirectToEmptyDocument {} + /** Declarative event action that redirects a network request. */ export interface RedirectRequest { + /** Destination to where the request is redirected. */ redirectUrl: string; } + /** A specification of a cookie in HTTP Responses. */ export interface ResponseCookie { + /** Value of the Domain cookie attribute. */ domain?: string | undefined; + /** Name of a cookie. */ name?: string | undefined; + /** Value of the Expires cookie attribute. */ expires?: string | undefined; + /** Value of the Max-Age cookie attribute */ maxAge?: number | undefined; + /** Value of a cookie, may be padded in double-quotes. */ value?: string | undefined; + /** Value of the Path cookie attribute. */ path?: string | undefined; + /** Existence of the HttpOnly cookie attribute. */ httpOnly?: string | undefined; + /** Existence of the Secure cookie attribute. */ secure?: string | undefined; } + /** Adds a cookie to the response or overrides a cookie, in case another cookie of the same name exists already. Note that it is preferred to use the Cookies API because this is computationally less expensive. */ export interface AddResponseCookie { cookie: ResponseCookie; } + /** Edits one or more cookies of response. Note that it is preferred to use the Cookies API because this is computationally less expensive. */ export interface EditResponseCookie { + /** Filter for cookies that will be modified. All empty entries are ignored. */ filter: ResponseCookie; + /** Attributes that shall be overridden in cookies that machted the filter. Attributes that are set to an empty string are removed. */ modification: ResponseCookie; } + /** Declarative event action that cancels a network request. */ export interface CancelRequest {} + /** Removes the request header of the specified name. Do not use SetRequestHeader and RemoveRequestHeader with the same header name on the same request. Each request header name occurs only once in each request. */ export interface RemoveRequestHeader { + /** HTTP request header name (case-insensitive). */ name: string; } + /** Edits one or more cookies of request. Note that it is preferred to use the Cookies API because this is computationally less expensive. */ export interface EditRequestCookie { + /** Filter for cookies that will be modified. All empty entries are ignored. */ filter: RequestCookie; + /** Attributes that shall be overridden in cookies that machted the filter. Attributes that are set to an empty string are removed. */ modification: RequestCookie; } + /** A filter of a cookie in HTTP Responses. */ + export interface FilterResponseCookie { + /** Inclusive lower bound on the cookie lifetime (specified in seconds after current time). Only cookies whose expiration date-time is set to 'now + ageLowerBound' or later fulfill this criterion. Session cookies do not meet the criterion of this filter. The cookie lifetime is calculated from either 'max-age' or 'expires' cookie attributes. If both are specified, 'max-age' is used to calculate the cookie lifetime. */ + ageLowerBound?: number | undefined; + /** Inclusive upper bound on the cookie lifetime (specified in seconds after current time). Only cookies whose expiration date-time is in the interval [now, now + ageUpperBound] fulfill this criterion. Session cookies and cookies whose expiration date-time is in the past do not meet the criterion of this filter. The cookie lifetime is calculated from either 'max-age' or 'expires' cookie attributes. If both are specified, 'max-age' is used to calculate the cookie lifetime. */ + ageUpperBound?: number | undefined; + /** Value of the Domain cookie attribute. */ + domain?: string | undefined; + /** Value of the Expires cookie attribute. */ + expires?: string | undefined; + /** Existence of the HttpOnly cookie attribute. */ + httpOnly?: string | undefined; + /** Value of the Max-Age cookie attribute */ + maxAge?: number | undefined; + /** Name of a cookie. */ + name?: string | undefined; + /** Value of the Path cookie attribute. */ + path?: string | undefined; + /** Existence of the Secure cookie attribute. */ + secure?: string | undefined; + /** Filters session cookies. Session cookies have no lifetime specified in any of 'max-age' or 'expires' attributes. */ + session?: boolean | undefined; + /** Value of a cookie, may be padded in double-quotes. */ + value?: string | undefined; + } + + /** Sets the request header of the specified name to the specified value. If a header with the specified name did not exist before, a new one is created. Header name comparison is always case-insensitive. Each request header name occurs only once in each request. */ export interface SetRequestHeader { + /** HTTP request header name. */ name: string; + /** HTTP request header value. */ value: string; } + /** A filter or specification of a cookie in HTTP Requests. */ export interface RequestCookie { + /** Name of a cookie. */ name?: string | undefined; + /** Value of a cookie, may be padded in double-quotes. */ value?: string | undefined; } + /** Redirects a request by applying a regular expression on the URL. The regular expressions use the RE2 syntax. */ export interface RedirectByRegEx { + /** Destination pattern. */ to: string; + /** A match pattern that may contain capture groups. Capture groups are referenced in the Perl syntax ($1, $2, ...) instead of the RE2 syntax (\1, \2, ...) in order to be closer to JavaScript Regular Expressions. */ from: string; } + /** Declarative event action that redirects a network request to a transparent image. */ export interface RedirectToTransparentImage {} + /** Adds a cookie to the request or overrides a cookie, in case another cookie of the same name exists already. Note that it is preferred to use the Cookies API because this is computationally less expensive. */ export interface AddRequestCookie { cookie: RequestCookie; } + /** Removes one or more cookies of request. Note that it is preferred to use the Cookies API because this is computationally less expensive. */ export interface RemoveRequestCookie { + /** Filter for cookies that will be removed. All empty entries are ignored. */ filter: RequestCookie; } - export interface RequestedEvent extends chrome.events.Event<() => void> {} + export enum Stage { + ON_AUTH_REQUIRED = "onAuthRequired", + ON_BEFORE_REQUEST = "onBeforeRequest", + ON_BEFORE_SEND_HEADERS = "onBeforeSendHeaders", + ON_HEADERS_RECEIVED = "onHeadersReceived", + } + + export interface MessageDetails { + /** A UUID of the document that made the request. */ + documentId?: string; + /** The lifecycle the document is in. */ + documentLifecycle: extensionTypes.DocumentLifecycle; + /** The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (`type` is `main_frame` or `sub_frame`), `frameId` indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab. */ + frameId: number; + /** The type of frame the navigation occurred in. */ + frameType: extensionTypes.FrameType; + /** The message sent by the calling script. */ + message: string; + /** Standard HTTP method. */ + method: string; + /** A UUID of the parent document owning this frame. This is not set if there is no parent. */ + parentDocumentId?: string; + /** ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. */ + parentFrameId: number; + /** The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request. */ + requestId: string; + /** The stage of the network request during which the event was triggered. */ + stage: `${Stage}`; + /** The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. */ + tabId: number; + /** The time when this signal is triggered, in milliseconds since the epoch. */ + timeStamp: number; + /** How the requested resource will be used. */ + type: `${webRequest.ResourceType}`; + url: string; + } + + export interface SendMessageToExtension { + /** The value that will be passed in the message attribute of the dictionary that is passed to the event handler. */ + message: string; + } + + /** Fired when a message is sent via {@link declarativeWebRequest.SendMessageToExtension} from an action of the declarative web request API. */ + export const onMessage: events.Event<(details: MessageDetails) => void>; - export var onRequest: RequestedEvent; + /** Provides the Declarative Event API consisting of `addRules`, `removeRules`, and `getRules`. */ + export const onRequest: events.Event<() => void>; } //////////////////// diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index 05f3b71a5caaec..c219c3225a1c37 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -4149,6 +4149,32 @@ async function testDeclarativeNetRequest() { }); } +// https://developer.chrome.com/docs/extensions/mv2/reference/declarativeWebRequest +function testDeclarativeWebRequest() { + chrome.declarativeWebRequest.onRequest.addRules([]); // $ExpectType void + chrome.declarativeWebRequest.onRequest.removeRules([]); // $ExpectType void + chrome.declarativeWebRequest.onRequest.getRules((rules) => { // $ExpectType void + rules; // $ExpectType Rule[] + }); + + checkChromeEvent(chrome.declarativeWebRequest.onMessage, (details) => { + details.documentId; // $ExpectType string | undefined + details.documentLifecycle; // $ExpectType DocumentLifecycle + details.frameId; // $ExpectType number + details.frameType; // $ExpectType FrameType + details.message; // $ExpectType string + details.method; // $ExpectType string + details.parentDocumentId; // $ExpectType string | undefined + details.parentFrameId; // $ExpectType number + details.requestId; // $ExpectType string + details.stage; // $ExpectType "onBeforeRequest" | "onBeforeSendHeaders" | "onHeadersReceived" | "onAuthRequired" + details.tabId; // $ExpectType number + details.timeStamp; // $ExpectType number + details.type; // $ExpectType "object" | "other" | "main_frame" | "sub_frame" | "stylesheet" | "script" | "image" | "font" | "xmlhttprequest" | "ping" | "csp_report" | "media" | "websocket" | "webbundle" + details.url; // $ExpectType string + }); +} + // https://developer.chrome.com/docs/extensions/reference/storage function testStorageForPromise() { chrome.storage.sync.getBytesInUse().then(() => {}); From 9054266e764f51260a6904d41df46d2925fc3900 Mon Sep 17 00:00:00 2001 From: Erwan Jugand <47392755+erwanjugand@users.noreply.github.com> Date: Tue, 11 Nov 2025 22:37:27 +0100 Subject: [PATCH 18/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73965=20[chr?= =?UTF-8?q?ome]=20update=20since=20Chrome=20141-142=20by=20@erwanjugand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 59 +++++++++++++++++++++++++++++++++++++- types/chrome/test/index.ts | 14 +++++++-- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index 765553826cd06f..692bb5fd07c3a1 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -1656,6 +1656,12 @@ declare namespace chrome { INCOGNITO_SESSION_ONLY = "incognito_session_only", } + /** @since Chrome 141 */ + export enum SoundContentSetting { + ALLOW = "allow", + BLOCK = "block", + } + /** * Whether to allow sites to download multiple files automatically. One of * @@ -6996,16 +7002,26 @@ declare namespace chrome { */ export namespace loginState { export enum ProfileType { + /** Specifies that the extension is in the signin profile. */ SIGNIN_PROFILE = "SIGNIN_PROFILE", + /** Specifies that the extension is in the user profile. */ USER_PROFILE = "USER_PROFILE", + /** Specifies that the extension is in the lock screen profile. */ + LOCK_PROFILE = "LOCK_PROFILE", } export enum SessionState { + /** Specifies that the session state is unknown. */ UNKNOWN = "UNKNOWN", + /** Specifies that the user is in the out-of-box-experience screen. */ IN_OOBE_SCREEN = "IN_OOBE_SCREEN", + /** Specifies that the user is in the login screen. */ IN_LOGIN_SCREEN = "IN_LOGIN_SCREEN", + /** Specifies that the user is in the session. */ IN_SESSION = "IN_SESSION", + /** Specifies that the user is in the lock screen. */ IN_LOCK_SCREEN = "IN_LOCK_SCREEN", + /** Specifies that the device is in RMA mode, finalizing repairs. */ IN_RMA_SCREEN = "IN_RMA_SCREEN", } @@ -13780,7 +13796,7 @@ declare namespace chrome { * @since Chrome 86 */ export enum HeaderOperation { - /** Adds a new entry for the specified header. This operation is not supported for request headers. */ + /** Adds a new entry for the specified header. When modifying the headers of a request, this operation is only supported for specific headers. */ APPEND = "append", /** Sets a new value for the specified header, removing any existing headers with the same name. */ SET = "set", @@ -14410,6 +14426,21 @@ declare namespace chrome { * @since Chrome 114, MV3 */ export namespace sidePanel { + /** @since Chrome 141 */ + export type CloseOptions = + | { + /** The tab in which to close the side panel. If a tab-specific side panel is open in the specified tab, it will be closed for that tab. At least one of this or `windowId` must be provided. */ + tabId: number; + /** The window in which to close the side panel. If a global side panel is open in the specified window, it will be closed for all tabs in that window where no tab-specific panel is active. At least one of this or `tabId` must be provided. */ + windowId?: number | undefined; + } + | { + /** The tab in which to close the side panel. If a tab-specific side panel is open in the specified tab, it will be closed for that tab. At least one of this or `windowId` must be provided. */ + tabId?: number | undefined; + /** The window in which to close the side panel. If a global side panel is open in the specified window, it will be closed for all tabs in that window where no tab-specific panel is active. At least one of this or `tabId` must be provided. */ + windowId: number; + }; + export interface GetPanelOptions { /** * If specified, the side panel options for the given tab will be returned. @@ -14447,11 +14478,31 @@ declare namespace chrome { openPanelOnActionClick?: boolean | undefined; } + /** @since Chrome 142 */ + export interface PanelClosedInfo { + /** The path of the local resource within the extension package whose content is displayed in the panel. */ + path: string; + /** The optional ID of the tab where the side panel was closed. This is provided only when the panel is tab-specific. */ + tabId?: number; + /** The ID of the window where the side panel was closed. This is available for both global and tab-specific panels. */ + windowId: number; + } + /** @since Chrome 140 */ export interface PanelLayout { side: `${Side}`; } + /** @since Chrome 141 */ + export interface PanelOpenedInfo { + /** The path of the local resource within the extension package whose content is displayed in the panel. */ + path: string; + /** The optional ID of the tab where the side panel is opened. This is provided only when the panel is tab-specific. */ + tabId?: number; + /** The ID of the window where the side panel is opened. This is available for both global and tab-specific panels. */ + windowId: number; + } + export interface PanelOptions { /** Whether the side panel should be enabled. This is optional. The default value is true. */ enabled?: boolean | undefined; @@ -14530,6 +14581,12 @@ declare namespace chrome { */ export function setPanelBehavior(behavior: PanelBehavior): Promise; export function setPanelBehavior(behavior: PanelBehavior, callback: () => void): void; + + /** + * Fired when the extension's side panel is opened. + * @since Chrome 141 + */ + const onOpened: events.Event<(info: PanelOpenedInfo) => void>; } //////////////////// diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index c219c3225a1c37..6ae1d5c789342c 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -527,6 +527,9 @@ function testContentSettings() { chrome.contentSettings.Scope.INCOGNITO_SESSION_ONLY === "incognito_session_only"; chrome.contentSettings.Scope.REGULAR === "regular"; + chrome.contentSettings.SoundContentSetting.ALLOW === "allow"; + chrome.contentSettings.SoundContentSetting.BLOCK === "block"; + const contentSettingsGetParams: chrome.contentSettings.ContentSettingGetParams = { primaryUrl: "https://example.com", secondaryUrl: "https://example2.com", @@ -6256,6 +6259,12 @@ function testSidePanel() { chrome.sidePanel.setPanelBehavior(setPanelBehavior, () => void 0); // $ExpectType void // @ts-expect-error chrome.sidePanel.setPanelBehavior(setPanelBehavior, () => {}).then(() => {}); + + checkChromeEvent(chrome.sidePanel.onOpened, (info) => { + info.path; // $ExpectType string + info.tabId; // $ExpectType number | undefined + info.windowId; // $ExpectType number + }); } // https://developer.chrome.com/docs/extensions/reference/api/instanceID @@ -6308,6 +6317,7 @@ function testInstanceID() { function testLoginState() { chrome.loginState.ProfileType.SIGNIN_PROFILE === "SIGNIN_PROFILE"; chrome.loginState.ProfileType.USER_PROFILE === "USER_PROFILE"; + chrome.loginState.ProfileType.LOCK_PROFILE === "LOCK_PROFILE"; chrome.loginState.SessionState.IN_LOCK_SCREEN === "IN_LOCK_SCREEN"; chrome.loginState.SessionState.IN_LOGIN_SCREEN === "IN_LOGIN_SCREEN"; @@ -6316,9 +6326,9 @@ function testLoginState() { chrome.loginState.SessionState.IN_SESSION === "IN_SESSION"; chrome.loginState.SessionState.UNKNOWN === "UNKNOWN"; - chrome.loginState.getProfileType(); // $ExpectType Promise<"SIGNIN_PROFILE" | "USER_PROFILE"> + chrome.loginState.getProfileType(); // $ExpectType Promise<"SIGNIN_PROFILE" | "USER_PROFILE" | "LOCK_PROFILE"> chrome.loginState.getProfileType((result) => { // $ExpectType void - result; // $ExpectType "SIGNIN_PROFILE" | "USER_PROFILE" + result; // $ExpectType "SIGNIN_PROFILE" | "USER_PROFILE" | "LOCK_PROFILE" }); // @ts-expect-error chrome.loginState.getProfileType(() => {}).then(() => {}); From 51b82cb4c032dbb6a54e56affe3394a686507665 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Wed, 12 Nov 2025 06:38:34 +0900 Subject: [PATCH 19/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73949=20fix(?= =?UTF-8?q?chrome):=20corrected=20typo=20for=20`chrome.declarativeNetReque?= =?UTF-8?q?st.RuleCondition.tabIds`=20by=20@cyfung1031?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index 692bb5fd07c3a1..37884a17505a8d 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -13989,7 +13989,7 @@ declare namespace chrome { requestMethods?: `${RequestMethod}`[] | undefined; /** - * List of {@link tabs.Tab.id} which the rule should not match. + * List of {@link tabs.Tab.id} which the rule should match. * An ID of {@link tabs.TAB_ID_NONE} matches requests which don't originate from a tab. * An empty list is not allowed. Only supported for session-scoped rules. * @since Chrome 92 From 2df641b876ec8e1a0c6ff60eb0a58a988a6d01c5 Mon Sep 17 00:00:00 2001 From: "R. N. West (Nat)" <98110034+rnwst@users.noreply.github.com> Date: Tue, 11 Nov 2025 21:39:16 +0000 Subject: [PATCH 20/20] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73979=20fix(?= =?UTF-8?q?chrome):=20Fix=20definitions=20of=20MV2=20permissions=20by=20@r?= =?UTF-8?q?nwst?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 28 +++++++++++++++++++--------- types/chrome/test/index.ts | 13 +++++++++---- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index 37884a17505a8d..e25f56db496a1f 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -246,7 +246,7 @@ declare namespace chrome { ): void; /** - * Gets the badge text of the action. If no tab is specified, the non-tab-specific badge text is returned. If {@link declarativeNetRequest.ExtensionActionOptions.displayActionCountAsBadgeText displayActionCountAsBadgeText} is enabled, a placeholder text will be returned unless the {@link runtime.ManifestPermissions declarativeNetRequestFeedback} permission is present or tab-specific badge text was provided. + * Gets the badge text of the action. If no tab is specified, the non-tab-specific badge text is returned. If {@link declarativeNetRequest.ExtensionActionOptions.displayActionCountAsBadgeText displayActionCountAsBadgeText} is enabled, a placeholder text will be returned unless the {@link runtime.ManifestPermission declarativeNetRequestFeedback} permission is present or tab-specific badge text was provided. * * Can return its result via Promise. */ @@ -7776,7 +7776,7 @@ declare namespace chrome { /** The list of host permissions, including those specified in the `optional_permissions` or `permissions` keys in the manifest, and those associated with [Content Scripts](https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts). */ origins?: string[]; /** List of named permissions (does not include hosts or origins). */ - permissions?: chrome.runtime.ManifestPermissions[]; + permissions?: chrome.runtime.ManifestPermission[]; } export interface AddHostAccessRequest { @@ -9082,7 +9082,7 @@ declare namespace chrome { } /** Source: https://developer.chrome.com/docs/extensions/reference/permissions-list */ - export type ManifestPermissions = + export type ManifestPermission = | "accessibilityFeatures.modify" | "accessibilityFeatures.read" | "activeTab" @@ -9166,9 +9166,14 @@ declare namespace chrome { | "webRequestBlocking" | "webRequestAuthProvider"; + /** + * @deprecated Use `ManifestPermission` instead. + */ + export type ManifestPermissions = ManifestPermission; + /** Source : https://developer.chrome.com/docs/extensions/reference/api/permissions */ - export type ManifestOptionalPermissions = Exclude< - ManifestPermissions, + export type ManifestOptionalPermission = Exclude< + ManifestPermission, | "debugger" | "declarativeNetRequest" | "devtools" @@ -9183,6 +9188,11 @@ declare namespace chrome { | "webAuthenticationProxy" >; + /** + * @deprecated Use `ManifestOptionalPermission` instead. + */ + export type ManifestOptionalPermissions = ManifestOptionalPermission; + export interface SearchProvider { name?: string | undefined; keyword?: string | undefined; @@ -9402,8 +9412,8 @@ declare namespace chrome { } | undefined; content_security_policy?: string | undefined; - optional_permissions?: ManifestOptionalPermissions[] | string[] | undefined; - permissions?: ManifestPermissions[] | string[] | undefined; + optional_permissions?: (ManifestOptionalPermission | string)[] | undefined; + permissions?: (ManifestPermission | string)[] | undefined; web_accessible_resources?: string[] | undefined; } @@ -9438,9 +9448,9 @@ declare namespace chrome { sandbox?: string; }; host_permissions?: string[] | undefined; - optional_permissions?: ManifestOptionalPermissions[] | undefined; + optional_permissions?: ManifestOptionalPermission[] | undefined; optional_host_permissions?: string[] | undefined; - permissions?: ManifestPermissions[] | undefined; + permissions?: ManifestPermission[] | undefined; web_accessible_resources?: | Array< & { diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index 6ae1d5c789342c..02a77db8fa2cb3 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -1036,8 +1036,13 @@ function testGetManifest() { manifest.content_security_policy; // $ExpectType string | undefined manifest.host_permissions; // $ExpectType any - manifest.optional_permissions; // $ExpectType ManifestOptionalPermissions[] | string[] | undefined - manifest.permissions; // $ExpectType ManifestPermissions[] |string[] | undefined + manifest.optional_permissions; // $ExpectType string[] | undefined + manifest.permissions; // $ExpectType string[] | undefined + // Verify that string permissions can be added. + if (manifest.optional_permissions && manifest.permissions) { + manifest.optional_permissions.push("*://developer.mozilla.org/*"); + manifest.permissions.push("*://developer.mozilla.org/*"); + } manifest.web_accessible_resources; // $ExpectType string[] | undefined } else if (manifest.manifest_version === 3) { @@ -1051,9 +1056,9 @@ function testGetManifest() { }; manifest.host_permissions; // $ExpectType string[] | undefined - manifest.optional_permissions; // $ExpectType ManifestOptionalPermissions[] | undefined + manifest.optional_permissions; // $ExpectType ManifestOptionalPermission[] | undefined manifest.optional_host_permissions; // $ExpectType string[] | undefined - manifest.permissions; // $ExpectType ManifestPermissions[] | undefined + manifest.permissions; // $ExpectType ManifestPermission[] | undefined manifest.web_accessible_resources = [{ resources: ["resource.js"],